diff --git a/.claude/worktrees/agent-a6b77bdf3dc410c7c b/.claude/worktrees/agent-a6b77bdf3dc410c7c
new file mode 160000
index 0000000..23d5a75
--- /dev/null
+++ b/.claude/worktrees/agent-a6b77bdf3dc410c7c
@@ -0,0 +1 @@
+Subproject commit 23d5a758910bbb9bc3201a0ba366c0bdfc4b3bce
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..f818879
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,2 @@
+TMDB_API_TOKEN=yourapitoken
+TMDB_API_KEY=yourapikey
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..22a4e4e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+import/img/* filter=lfs diff=lfs merge=lfs -text
diff --git a/astro.config.mjs b/astro.config.mjs
index e762ba5..7c0d18f 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,5 +1,22 @@
// @ts-check
-import { defineConfig } from 'astro/config';
+import { defineConfig, envField } from 'astro/config';
+
+import react from '@astrojs/react';
+import tailwindcss from '@tailwindcss/vite';
+
// https://astro.build/config
-export default defineConfig({});
+export default defineConfig({
+ integrations: [react({
+ include: ['**/react/*']
+ })],
+ vite: {
+ plugins: [tailwindcss()],
+ },
+ env: {
+ schema: {
+ TMDB_API_TOKEN: envField.string({ context: 'client', access: 'public', default: 'https://api.example.com' }),
+ SETTINGS_TOKEN: envField.string({ context: 'server', access: 'secret' }),
+ }
+ }
+});
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 8449054..fd1e285 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,7 +8,18 @@
"name": "kino-astro",
"version": "0.0.1",
"dependencies": {
- "astro": "^6.1.10"
+ "@astrojs/react": "^5.0.4",
+ "@tailwindcss/vite": "^4.2.4",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
+ "astro": "^6.1.10",
+ "dotenv": "^17.4.2",
+ "react": "^19.2.5",
+ "react-dom": "^19.2.5",
+ "tailwindcss": "^4.2.4"
+ },
+ "devDependencies": {
+ "@types/node": "^25.6.0"
},
"engines": {
"node": ">=22.12.0"
@@ -70,6 +81,102 @@
"node": ">=22.12.0"
}
},
+ "node_modules/@astrojs/react": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-5.0.4.tgz",
+ "integrity": "sha512-yDNE4VnKOzCjH9dCBi7pT4F6kpI3M9TkS+uxnCB0sGIS6t5vKonOY+Hs/UUnSajJGT5jeBRfpI9IQp+r/n1fBA==",
+ "license": "MIT",
+ "dependencies": {
+ "@astrojs/internal-helpers": "0.9.0",
+ "@vitejs/plugin-react": "^5.2.0",
+ "devalue": "^5.6.4",
+ "ultrahtml": "^1.6.0",
+ "vite": "^7.3.2"
+ },
+ "engines": {
+ "node": ">=22.12.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0",
+ "@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0",
+ "react": "^17.0.2 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@astrojs/react/node_modules/vite": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
+ "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@astrojs/telemetry": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.1.tgz",
@@ -87,6 +194,166 @@
"node": "18.20.8 || ^20.3.0 || >=22.0.0"
}
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
@@ -105,6 +372,28 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/parser": {
"version": "7.29.2",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
@@ -120,6 +409,68 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+ "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+ "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/types": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
@@ -173,6 +524,17 @@
"node": ">= 20.12.0"
}
},
+ "node_modules/@emnapi/core": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.1",
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@emnapi/runtime": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
@@ -183,6 +545,16 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
"node_modules/@esbuild/aix-ppc64": {
"version": "0.27.7",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
@@ -1065,18 +1437,348 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"license": "MIT"
},
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
+ "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1"
+ }
+ },
"node_modules/@oslojs/encoding": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz",
"integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==",
"license": "MIT"
},
+ "node_modules/@oxc-project/types": {
+ "version": "0.127.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz",
+ "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==",
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz",
+ "integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz",
+ "integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz",
+ "integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz",
+ "integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz",
+ "integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz",
+ "integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.3",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz",
+ "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==",
+ "license": "MIT"
+ },
"node_modules/@rollup/pluginutils": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
@@ -1524,6 +2226,314 @@
"integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
"license": "MIT"
},
+ "node_modules/@tailwindcss/node": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.4.tgz",
+ "integrity": "sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "enhanced-resolve": "^5.19.0",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.32.0",
+ "magic-string": "^0.30.21",
+ "source-map-js": "^1.2.1",
+ "tailwindcss": "4.2.4"
+ }
+ },
+ "node_modules/@tailwindcss/oxide": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.4.tgz",
+ "integrity": "sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 20"
+ },
+ "optionalDependencies": {
+ "@tailwindcss/oxide-android-arm64": "4.2.4",
+ "@tailwindcss/oxide-darwin-arm64": "4.2.4",
+ "@tailwindcss/oxide-darwin-x64": "4.2.4",
+ "@tailwindcss/oxide-freebsd-x64": "4.2.4",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.4",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.2.4",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.2.4",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.2.4",
+ "@tailwindcss/oxide-linux-x64-musl": "4.2.4",
+ "@tailwindcss/oxide-wasm32-wasi": "4.2.4",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.2.4",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.2.4"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-android-arm64": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.4.tgz",
+ "integrity": "sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-arm64": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.4.tgz",
+ "integrity": "sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-darwin-x64": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.4.tgz",
+ "integrity": "sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-freebsd-x64": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.4.tgz",
+ "integrity": "sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.4.tgz",
+ "integrity": "sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.4.tgz",
+ "integrity": "sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.4.tgz",
+ "integrity": "sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.4.tgz",
+ "integrity": "sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.4.tgz",
+ "integrity": "sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.4.tgz",
+ "integrity": "sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==",
+ "bundleDependencies": [
+ "@napi-rs/wasm-runtime",
+ "@emnapi/core",
+ "@emnapi/runtime",
+ "@tybys/wasm-util",
+ "@emnapi/wasi-threads",
+ "tslib"
+ ],
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.8.1",
+ "@emnapi/runtime": "^1.8.1",
+ "@emnapi/wasi-threads": "^1.1.0",
+ "@napi-rs/wasm-runtime": "^1.1.1",
+ "@tybys/wasm-util": "^0.10.1",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.4.tgz",
+ "integrity": "sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.4.tgz",
+ "integrity": "sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 20"
+ }
+ },
+ "node_modules/@tailwindcss/vite": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.4.tgz",
+ "integrity": "sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw==",
+ "license": "MIT",
+ "dependencies": {
+ "@tailwindcss/node": "4.2.4",
+ "@tailwindcss/oxide": "4.2.4",
+ "tailwindcss": "4.2.4"
+ },
+ "peerDependencies": {
+ "vite": "^5.2.0 || ^6 || ^7 || ^8"
+ }
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
"node_modules/@types/debug": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
@@ -1572,6 +2582,34 @@
"@types/unist": "*"
}
},
+ "node_modules/@types/node": {
+ "version": "25.6.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz",
+ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.19.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
"node_modules/@types/unist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
@@ -1584,6 +2622,26 @@
"integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
"license": "ISC"
},
+ "node_modules/@vitejs/plugin-react": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz",
+ "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.29.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+ "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+ "@rolldown/pluginutils": "1.0.0-rc.3",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.18.0"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
@@ -1711,6 +2769,80 @@
"sharp": "^0.34.0"
}
},
+ "node_modules/astro/node_modules/vite": {
+ "version": "7.3.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
+ "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.27.0",
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.43.0",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
"node_modules/axobject-query": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
@@ -1730,12 +2862,77 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.24",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.24.tgz",
+ "integrity": "sha512-I2NkZOOrj2XuguvWCK6OVh9GavsNjZjK908Rq3mIBK25+GD8vPX5w2WdxVqnQ7xx3SrZJiCiZFu+/Oz50oSYSA==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"license": "ISC"
},
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001791",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001791.tgz",
+ "integrity": "sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
"node_modules/ccount": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
@@ -1843,6 +3040,12 @@
"node": ">= 18"
}
},
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "license": "MIT"
+ },
"node_modules/cookie": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
@@ -1945,6 +3148,12 @@
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
"license": "CC0-1.0"
},
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@@ -2001,7 +3210,6 @@
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
"license": "Apache-2.0",
- "optional": true,
"engines": {
"node": ">=8"
}
@@ -2107,6 +3315,18 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
+ "node_modules/dotenv": {
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz",
+ "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
"node_modules/dset": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
@@ -2116,6 +3336,25 @@
"node": ">=4"
}
},
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.345",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.345.tgz",
+ "integrity": "sha512-F9JXQGiMrz6yVNPI2qOVPvB9HzjH5cGzhs8oJ6A28V5L/YnzN/0KsuiibqF+F1Fd9qxFzD1BUnYSd8JfULxTwg==",
+ "license": "ISC"
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.21.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+ "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
@@ -2175,6 +3414,15 @@
"@esbuild/win32-x64": "0.27.7"
}
},
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
@@ -2290,12 +3538,27 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/github-slugger": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
"integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==",
"license": "ISC"
},
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "license": "ISC"
+ },
"node_modules/h3": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz",
@@ -2596,6 +3859,21 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/jiti": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+ "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "lib/jiti-cli.mjs"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
+ },
"node_modules/js-yaml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
@@ -2608,6 +3886,279 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.32.0",
+ "lightningcss-darwin-arm64": "1.32.0",
+ "lightningcss-darwin-x64": "1.32.0",
+ "lightningcss-freebsd-x64": "1.32.0",
+ "lightningcss-linux-arm-gnueabihf": "1.32.0",
+ "lightningcss-linux-arm64-gnu": "1.32.0",
+ "lightningcss-linux-arm64-musl": "1.32.0",
+ "lightningcss-linux-x64-gnu": "1.32.0",
+ "lightningcss-linux-x64-musl": "1.32.0",
+ "lightningcss-win32-arm64-msvc": "1.32.0",
+ "lightningcss-win32-x64-msvc": "1.32.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
+ "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
+ "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
+ "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
+ "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
+ "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
+ "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
+ "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
+ "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
+ "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
+ "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
+ "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
"node_modules/longest-streak": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
@@ -3518,6 +5069,12 @@
"integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==",
"license": "MIT"
},
+ "node_modules/node-releases": {
+ "version": "2.0.38",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz",
+ "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==",
+ "license": "MIT"
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -3739,6 +5296,36 @@
"integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==",
"license": "MIT"
},
+ "node_modules/react": {
+ "version": "19.2.5",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz",
+ "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.5",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz",
+ "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.5"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz",
+ "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/readdirp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
@@ -3979,6 +5566,47 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/rolldown": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.17.tgz",
+ "integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@oxc-project/types": "=0.127.0",
+ "@rolldown/pluginutils": "1.0.0-rc.17"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.0.0-rc.17",
+ "@rolldown/binding-darwin-arm64": "1.0.0-rc.17",
+ "@rolldown/binding-darwin-x64": "1.0.0-rc.17",
+ "@rolldown/binding-freebsd-x64": "1.0.0-rc.17",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17",
+ "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17",
+ "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17",
+ "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17",
+ "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17"
+ }
+ },
+ "node_modules/rolldown/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz",
+ "integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==",
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/rollup": {
"version": "4.60.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz",
@@ -4032,6 +5660,12 @@
"node": ">=11.0.0"
}
},
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
"node_modules/semver": {
"version": "7.7.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
@@ -4184,6 +5818,25 @@
"url": "https://opencollective.com/svgo"
}
},
+ "node_modules/tailwindcss": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.4.tgz",
+ "integrity": "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==",
+ "license": "MIT"
+ },
+ "node_modules/tapable": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+ "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
"node_modules/tiny-inflate": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
@@ -4289,6 +5942,13 @@
"integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==",
"license": "MIT"
},
+ "node_modules/undici-types": {
+ "version": "7.19.2",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz",
+ "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
+ "devOptional": true,
+ "license": "MIT"
+ },
"node_modules/unified": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
@@ -4538,6 +6198,36 @@
}
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/vfile": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
@@ -4581,17 +6271,17 @@
}
},
"node_modules/vite": {
- "version": "7.3.2",
- "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz",
- "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",
+ "version": "8.0.10",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz",
+ "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==",
"license": "MIT",
+ "peer": true,
"dependencies": {
- "esbuild": "^0.27.0",
- "fdir": "^6.5.0",
- "picomatch": "^4.0.3",
- "postcss": "^8.5.6",
- "rollup": "^4.43.0",
- "tinyglobby": "^0.2.15"
+ "lightningcss": "^1.32.0",
+ "picomatch": "^4.0.4",
+ "postcss": "^8.5.10",
+ "rolldown": "1.0.0-rc.17",
+ "tinyglobby": "^0.2.16"
},
"bin": {
"vite": "bin/vite.js"
@@ -4607,9 +6297,10 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.1.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
- "lightningcss": "^1.21.0",
"sass": "^1.70.0",
"sass-embedded": "^1.70.0",
"stylus": ">=0.54.8",
@@ -4622,15 +6313,18 @@
"@types/node": {
"optional": true
},
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
"jiti": {
"optional": true
},
"less": {
"optional": true
},
- "lightningcss": {
- "optional": true
- },
"sass": {
"optional": true
},
@@ -4698,6 +6392,12 @@
"integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==",
"license": "MIT"
},
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "license": "ISC"
+ },
"node_modules/yargs-parser": {
"version": "22.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz",
diff --git a/package.json b/package.json
index 63a8008..d166a11 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,17 @@
"astro": "astro"
},
"dependencies": {
- "astro": "^6.1.10"
+ "@astrojs/react": "^5.0.4",
+ "@tailwindcss/vite": "^4.2.4",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
+ "astro": "^6.1.10",
+ "dotenv": "^17.4.2",
+ "react": "^19.2.5",
+ "react-dom": "^19.2.5",
+ "tailwindcss": "^4.2.4"
+ },
+ "devDependencies": {
+ "@types/node": "^25.6.0"
}
-}
\ No newline at end of file
+}
diff --git a/public/img/Apfelschorle.png b/public/img/Apfelschorle.png
new file mode 100644
index 0000000..9bdd93a
Binary files /dev/null and b/public/img/Apfelschorle.png differ
diff --git a/public/img/Dolby.png b/public/img/Dolby.png
new file mode 100644
index 0000000..12d6424
Binary files /dev/null and b/public/img/Dolby.png differ
diff --git a/public/img/Schorle.png b/public/img/Schorle.png
new file mode 100644
index 0000000..d75beea
Binary files /dev/null and b/public/img/Schorle.png differ
diff --git a/public/img/Zoomania-2.jpg b/public/img/Zoomania-2.jpg
new file mode 100644
index 0000000..11c4d48
Binary files /dev/null and b/public/img/Zoomania-2.jpg differ
diff --git a/public/img/applepay.png b/public/img/applepay.png
new file mode 100644
index 0000000..3040f0d
Binary files /dev/null and b/public/img/applepay.png differ
diff --git a/public/img/astronautpopcorn.jpg b/public/img/astronautpopcorn.jpg
new file mode 100644
index 0000000..84eadc0
Binary files /dev/null and b/public/img/astronautpopcorn.jpg differ
diff --git a/public/img/bladerunner2049.jpg b/public/img/bladerunner2049.jpg
new file mode 100644
index 0000000..04a44ad
Binary files /dev/null and b/public/img/bladerunner2049.jpg differ
diff --git a/public/img/cola-light.png b/public/img/cola-light.png
new file mode 100644
index 0000000..75902ec
Binary files /dev/null and b/public/img/cola-light.png differ
diff --git a/public/img/cola-zero.png b/public/img/cola-zero.png
new file mode 100644
index 0000000..f5eb3d2
Binary files /dev/null and b/public/img/cola-zero.png differ
diff --git a/public/img/cola.png b/public/img/cola.png
new file mode 100644
index 0000000..014156c
Binary files /dev/null and b/public/img/cola.png differ
diff --git a/public/img/dbox.jpg b/public/img/dbox.jpg
new file mode 100644
index 0000000..ff19d1f
Binary files /dev/null and b/public/img/dbox.jpg differ
diff --git a/public/img/derAustronaut.jpg b/public/img/derAustronaut.jpg
new file mode 100644
index 0000000..67078d4
Binary files /dev/null and b/public/img/derAustronaut.jpg differ
diff --git a/public/img/fallguy.jpg b/public/img/fallguy.jpg
new file mode 100644
index 0000000..aff1689
Binary files /dev/null and b/public/img/fallguy.jpg differ
diff --git a/public/img/fanta.png b/public/img/fanta.png
new file mode 100644
index 0000000..4fa589f
Binary files /dev/null and b/public/img/fanta.png differ
diff --git a/public/img/fuze-tea.png b/public/img/fuze-tea.png
new file mode 100644
index 0000000..5d60a8e
Binary files /dev/null and b/public/img/fuze-tea.png differ
diff --git a/public/img/gangstergang.jpg b/public/img/gangstergang.jpg
new file mode 100644
index 0000000..0f76a04
Binary files /dev/null and b/public/img/gangstergang.jpg differ
diff --git a/public/img/gangstergang2.png b/public/img/gangstergang2.png
new file mode 100644
index 0000000..c291aae
Binary files /dev/null and b/public/img/gangstergang2.png differ
diff --git a/public/img/glennkill.jpg b/public/img/glennkill.jpg
new file mode 100644
index 0000000..bbeb570
Binary files /dev/null and b/public/img/glennkill.jpg differ
diff --git a/public/img/goat.jpg b/public/img/goat.jpg
new file mode 100644
index 0000000..6221db1
Binary files /dev/null and b/public/img/goat.jpg differ
diff --git a/public/img/googlepay.png b/public/img/googlepay.png
new file mode 100644
index 0000000..8ef3b93
Binary files /dev/null and b/public/img/googlepay.png differ
diff --git a/public/img/haribo.png b/public/img/haribo.png
new file mode 100644
index 0000000..937cfac
Binary files /dev/null and b/public/img/haribo.png differ
diff --git a/public/img/homefront.jpg b/public/img/homefront.jpg
new file mode 100644
index 0000000..386876a
Binary files /dev/null and b/public/img/homefront.jpg differ
diff --git a/public/img/hoppers.jpg b/public/img/hoppers.jpg
new file mode 100644
index 0000000..918158b
Binary files /dev/null and b/public/img/hoppers.jpg differ
diff --git a/public/img/hopperskidsmenu.jpg b/public/img/hopperskidsmenu.jpg
new file mode 100644
index 0000000..2ed0b17
Binary files /dev/null and b/public/img/hopperskidsmenu.jpg differ
diff --git a/public/img/hopperspopcornmetall.jpg b/public/img/hopperspopcornmetall.jpg
new file mode 100644
index 0000000..a30856e
Binary files /dev/null and b/public/img/hopperspopcornmetall.jpg differ
diff --git a/public/img/hopperspopcornwood.png b/public/img/hopperspopcornwood.png
new file mode 100644
index 0000000..431b5ff
Binary files /dev/null and b/public/img/hopperspopcornwood.png differ
diff --git a/public/img/klarna.png b/public/img/klarna.png
new file mode 100644
index 0000000..35c0467
Binary files /dev/null and b/public/img/klarna.png differ
diff --git a/public/img/käsedip.png b/public/img/käsedip.png
new file mode 100644
index 0000000..304ef78
Binary files /dev/null and b/public/img/käsedip.png differ
diff --git a/public/img/mandalorian.jpeg b/public/img/mandalorian.jpeg
new file mode 100644
index 0000000..a28305c
Binary files /dev/null and b/public/img/mandalorian.jpeg differ
diff --git a/public/img/mariogalaxy.jpg b/public/img/mariogalaxy.jpg
new file mode 100644
index 0000000..35939cc
Binary files /dev/null and b/public/img/mariogalaxy.jpg differ
diff --git a/public/img/mariokidsmenu.png b/public/img/mariokidsmenu.png
new file mode 100644
index 0000000..003a8bd
Binary files /dev/null and b/public/img/mariokidsmenu.png differ
diff --git a/public/img/marioyoshipopcorn.png b/public/img/marioyoshipopcorn.png
new file mode 100644
index 0000000..513a5ec
Binary files /dev/null and b/public/img/marioyoshipopcorn.png differ
diff --git a/public/img/mastercard.png b/public/img/mastercard.png
new file mode 100644
index 0000000..4cdb1a1
Binary files /dev/null and b/public/img/mastercard.png differ
diff --git a/public/img/masteruniverse.jpg b/public/img/masteruniverse.jpg
new file mode 100644
index 0000000..691476f
Binary files /dev/null and b/public/img/masteruniverse.jpg differ
diff --git a/public/img/meg.JPG b/public/img/meg.JPG
new file mode 100644
index 0000000..2557016
Binary files /dev/null and b/public/img/meg.JPG differ
diff --git a/public/img/meg2.jpg b/public/img/meg2.jpg
new file mode 100644
index 0000000..607e29a
Binary files /dev/null and b/public/img/meg2.jpg differ
diff --git a/public/img/menu-big.png b/public/img/menu-big.png
new file mode 100644
index 0000000..c303863
Binary files /dev/null and b/public/img/menu-big.png differ
diff --git a/public/img/minionsmonsters.jpg b/public/img/minionsmonsters.jpg
new file mode 100644
index 0000000..95375f5
Binary files /dev/null and b/public/img/minionsmonsters.jpg differ
diff --git a/public/img/mms.png b/public/img/mms.png
new file mode 100644
index 0000000..c993ae6
Binary files /dev/null and b/public/img/mms.png differ
diff --git a/public/img/monsterag.png b/public/img/monsterag.png
new file mode 100644
index 0000000..02967bb
Binary files /dev/null and b/public/img/monsterag.png differ
diff --git a/public/img/monsteruni.jpg b/public/img/monsteruni.jpg
new file mode 100644
index 0000000..6dab4b7
Binary files /dev/null and b/public/img/monsteruni.jpg differ
diff --git a/public/img/mutiny.jpg b/public/img/mutiny.jpg
new file mode 100644
index 0000000..6913501
Binary files /dev/null and b/public/img/mutiny.jpg differ
diff --git a/public/img/nachokombiklein.png b/public/img/nachokombiklein.png
new file mode 100644
index 0000000..12f8f6f
Binary files /dev/null and b/public/img/nachokombiklein.png differ
diff --git a/public/img/nachos.jpg b/public/img/nachos.jpg
new file mode 100644
index 0000000..c18edff
Binary files /dev/null and b/public/img/nachos.jpg differ
diff --git a/public/img/nachosnormal.png b/public/img/nachosnormal.png
new file mode 100644
index 0000000..f5d268c
Binary files /dev/null and b/public/img/nachosnormal.png differ
diff --git a/public/img/paypal.png b/public/img/paypal.png
new file mode 100644
index 0000000..0ffc583
Binary files /dev/null and b/public/img/paypal.png differ
diff --git a/public/img/popcorn-big.png b/public/img/popcorn-big.png
new file mode 100644
index 0000000..974bf1f
Binary files /dev/null and b/public/img/popcorn-big.png differ
diff --git a/public/img/popcorn-klein.png b/public/img/popcorn-klein.png
new file mode 100644
index 0000000..94a0a6e
Binary files /dev/null and b/public/img/popcorn-klein.png differ
diff --git a/public/img/popcorn-mittel.png b/public/img/popcorn-mittel.png
new file mode 100644
index 0000000..134cd5f
Binary files /dev/null and b/public/img/popcorn-mittel.png differ
diff --git a/public/img/popcorn.jpg b/public/img/popcorn.jpg
new file mode 100644
index 0000000..8a0fd9b
Binary files /dev/null and b/public/img/popcorn.jpg differ
diff --git a/public/img/riegel.png b/public/img/riegel.png
new file mode 100644
index 0000000..7726f5c
Binary files /dev/null and b/public/img/riegel.png differ
diff --git a/public/img/salsadip.png b/public/img/salsadip.png
new file mode 100644
index 0000000..538556c
Binary files /dev/null and b/public/img/salsadip.png differ
diff --git a/public/img/screamdoorpopcorn.jpg b/public/img/screamdoorpopcorn.jpg
new file mode 100644
index 0000000..69d55e5
Binary files /dev/null and b/public/img/screamdoorpopcorn.jpg differ
diff --git a/public/img/screamvii.jpg b/public/img/screamvii.jpg
new file mode 100644
index 0000000..9d7b14b
Binary files /dev/null and b/public/img/screamvii.jpg differ
diff --git a/public/img/shelter.jpg b/public/img/shelter.jpg
new file mode 100644
index 0000000..f7c9077
Binary files /dev/null and b/public/img/shelter.jpg differ
diff --git a/public/img/solomio.png b/public/img/solomio.png
new file mode 100644
index 0000000..8b99bd1
Binary files /dev/null and b/public/img/solomio.png differ
diff --git a/public/img/sourdip.png b/public/img/sourdip.png
new file mode 100644
index 0000000..552e76b
Binary files /dev/null and b/public/img/sourdip.png differ
diff --git a/public/img/spezi.png b/public/img/spezi.png
new file mode 100644
index 0000000..bb18479
Binary files /dev/null and b/public/img/spezi.png differ
diff --git a/public/img/spidermannewday.jpg b/public/img/spidermannewday.jpg
new file mode 100644
index 0000000..0f092ba
Binary files /dev/null and b/public/img/spidermannewday.jpg differ
diff --git a/public/img/sprite.png b/public/img/sprite.png
new file mode 100644
index 0000000..af59ed7
Binary files /dev/null and b/public/img/sprite.png differ
diff --git a/public/img/super-mario-galaxy-banner.jpg b/public/img/super-mario-galaxy-banner.jpg
new file mode 100644
index 0000000..532f1b9
Binary files /dev/null and b/public/img/super-mario-galaxy-banner.jpg differ
diff --git a/public/img/toystory1.jpg b/public/img/toystory1.jpg
new file mode 100644
index 0000000..6095273
Binary files /dev/null and b/public/img/toystory1.jpg differ
diff --git a/public/img/toystory2.jpg b/public/img/toystory2.jpg
new file mode 100644
index 0000000..2aa78aa
Binary files /dev/null and b/public/img/toystory2.jpg differ
diff --git a/public/img/toystory3.jpg b/public/img/toystory3.jpg
new file mode 100644
index 0000000..6d9e334
Binary files /dev/null and b/public/img/toystory3.jpg differ
diff --git a/public/img/toystory4.jpg b/public/img/toystory4.jpg
new file mode 100644
index 0000000..3f14c76
Binary files /dev/null and b/public/img/toystory4.jpg differ
diff --git a/public/img/toystory5.png b/public/img/toystory5.png
new file mode 100644
index 0000000..da0add6
Binary files /dev/null and b/public/img/toystory5.png differ
diff --git a/public/img/visa.png b/public/img/visa.png
new file mode 100644
index 0000000..ffeaef0
Binary files /dev/null and b/public/img/visa.png differ
diff --git a/public/img/wasser.png b/public/img/wasser.png
new file mode 100644
index 0000000..d7afb8e
Binary files /dev/null and b/public/img/wasser.png differ
diff --git a/public/img/zoomania-popcorn.jpg b/public/img/zoomania-popcorn.jpg
new file mode 100644
index 0000000..48b42f9
Binary files /dev/null and b/public/img/zoomania-popcorn.jpg differ
diff --git a/public/img/zoomaniakidsmenu.jpg b/public/img/zoomaniakidsmenu.jpg
new file mode 100644
index 0000000..023e54c
Binary files /dev/null and b/public/img/zoomaniakidsmenu.jpg differ
diff --git a/src/components/AboutView.astro b/src/components/AboutView.astro
new file mode 100644
index 0000000..ecd2cec
--- /dev/null
+++ b/src/components/AboutView.astro
@@ -0,0 +1,58 @@
+
+
+
+
+
Über uns
+
+ EAGLE's IMAX vereint modernes Design, starke Technik und echtes Kinofeeling.
+ Unser Anspruch: Jeder Besuch soll wie ein kleines Event wirken. Von entspannten Abenden
+ bis zu großen Blockbuster-Premieren liefern wir Bild, Sound und Atmosphäre auf Top-Niveau.
+
+
+ 4 Säle
+ IMAX Experience
+ D-BOX Motion Seats
+ Premium Snacks
+
+
+
+
+
+
+
+ 600+
+ Sitzplätze insgesamt
+
+
+ 4K / Laser
+ Hochauflösende Projektion
+
+
+ Dolby Atmos
+ Raumklang in ausgewählten Sälen
+
+
+ D-BOX
+ Bewegung synchron zum Film
+
+
+
+
+
+ Säle
+ Vom klassischen Kinoraum bis zum IMAX-Erlebnis: Jeder Saal ist individuell abgestimmt auf Genre, Publikum und Stimmung.
+ Mehr erfahren
+
+
+ D-BOX Plätze
+ Synchronisierte Sitzbewegungen machen Action und Effekte physisch spürbar und verstärken die Immersion im Film.
+ Mehr erfahren
+
+
+ Technik
+ Leinwandgrößen, Projektoren, Soundsysteme und Kapazitäten in einem separaten Technikfenster zusammengefasst.
+ Mehr erfahren
+
+
+
+
diff --git a/src/components/AccountView.astro b/src/components/AccountView.astro
new file mode 100644
index 0000000..94603a9
--- /dev/null
+++ b/src/components/AccountView.astro
@@ -0,0 +1,45 @@
+
+
+
Mein Konto
+
+
+
+
Passwort vergessen?
+
+
+ Falsche E-Mail oder Passwort
+
+
+
Anmelden
+
Noch kein Konto?
+
Registrieren
+
+
+
+
+
+
+
+
×
+
Passwort vergessen
+
Gib deine E-Mail ein und wir senden dir einen Reset-Code.
+
+
+
Code senden
+
+
+ Ein Code wurde simuliert versendet.
+
+
+
diff --git a/src/components/BookingModal.astro b/src/components/BookingModal.astro
new file mode 100644
index 0000000..de24660
--- /dev/null
+++ b/src/components/BookingModal.astro
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
Deine Auswahl
+
+
+
+
+ Gesamtbetrag:
+ 0,00€
+
+
+
+
+
+
+
+
Plätze bestätigen
+
+
diff --git a/src/components/CartView.astro b/src/components/CartView.astro
new file mode 100644
index 0000000..eda767c
--- /dev/null
+++ b/src/components/CartView.astro
@@ -0,0 +1,37 @@
+
+
+
Dein Warenkorb
+
+
+
+
+
+
+
Zusammenfassung
+
+ Gesamtsumme:
+ 0,00€
+
+
+ inkl. 19% MwSt: 0,00€
+
+
+
Jetzt kostenpflichtig bestellen
+
+
+
Sicher bezahlen mit
+
+
+
+
+
+
+
diff --git a/src/components/CheckoutView.astro b/src/components/CheckoutView.astro
new file mode 100644
index 0000000..f0e49b1
--- /dev/null
+++ b/src/components/CheckoutView.astro
@@ -0,0 +1,52 @@
+
+
+
+
+
+
Zahlungsmethode wählen
+
+
+
+
Apple Pay
+
+
+
+
PayPal
+
+
+
+
Google Pay
+
+
+
+
Visa
+
+
+
Weiter zur Übersicht
+
+
+
+
+ ←
+
Persönliche Daten
+
+
Bestellübersicht
+
+
+
+
Jetzt Bezahlen
+
+
+
+
Kauf erfolgreich!
+
+
Zurück zur Startseite
+
+
+
diff --git a/src/components/CollectorsView.astro b/src/components/CollectorsView.astro
new file mode 100644
index 0000000..73d068b
--- /dev/null
+++ b/src/components/CollectorsView.astro
@@ -0,0 +1,33 @@
+
+
+
← Zur Startseite
+
Collectors Popcorn Specials
+
Filmbezogene Specials in einer links/rechts versetzten Darstellung.
+
+
+ Filmlogo
+
+
Special Becher 01
+
Kurzbeschreibung des Artikels und Bezug zum Film.
+
+
+
+
+ Filmlogo
+
+
Special Eimer 02
+
Weitere Edition mit eigenem Motiv und Text.
+
+
+
+
+ Filmlogo
+
+
Special Box 03
+
Noch ein Eintrag fuer limitierte Collectors.
+
+
+
+
+
+
diff --git a/src/components/DboxView.astro b/src/components/DboxView.astro
new file mode 100644
index 0000000..e6ed7bf
--- /dev/null
+++ b/src/components/DboxView.astro
@@ -0,0 +1,31 @@
+
+
+
← Zur Startseite
+
D-BOX & Technik
+
Inspiriert von Technikseiten moderner Kinos, aber in deinem Design.
+
+ Wie D-BOX funktioniert
+ D-BOX Sitze reagieren synchron zum Film. Die Bewegungsintensität ist individuell steuerbar und kann bei Bedarf reduziert oder deaktiviert werden.
+
+
+ Technik im Saal
+ Ergänze hier deine Informationen zu Projektion, Soundsystem, Sitzkomfort und den Sälen mit D-BOX-Unterstützung.
+
+
Bildplatz Technik 1
+
Bildplatz Technik 2
+
Bildplatz Technik 3
+
Bildplatz Technik 4
+
+
+
+ Filme in D-BOX
+
+
Zoomania 2
+
Der Austronaut
+
Spider Man
+
Scream VII
+
Gangster Gang 2
+
+
+
+
diff --git a/src/components/HallsView.astro b/src/components/HallsView.astro
new file mode 100644
index 0000000..1ba9f09
--- /dev/null
+++ b/src/components/HallsView.astro
@@ -0,0 +1,29 @@
+
+
+
← Zur Startseite
+
Unsere Säle
+
Pflegbare Infoseite zu allen Sälen inkl. Bild- und Textbereichen.
+
+
+
diff --git a/src/components/Hero.astro b/src/components/Hero.astro
new file mode 100644
index 0000000..084558a
--- /dev/null
+++ b/src/components/Hero.astro
@@ -0,0 +1,10 @@
+
diff --git a/src/components/HomeSection.astro b/src/components/HomeSection.astro
new file mode 100644
index 0000000..6fa03a6
--- /dev/null
+++ b/src/components/HomeSection.astro
@@ -0,0 +1,58 @@
+
+
+
+
+
+
Jetzt läuft
+ Heute im Fokus
+
+
+
+
+
+
diff --git a/src/components/MovieListView.astro b/src/components/MovieListView.astro
new file mode 100644
index 0000000..be9e8f1
--- /dev/null
+++ b/src/components/MovieListView.astro
@@ -0,0 +1,19 @@
+---
+
+const api_token = import.meta.env.TMDB_API_TOKEN;
+
+var api = await fetch("https://api.themoviedb.org/3/movie/11")
+var request = await api.json
+
+---
+
+
+
+
Aktuelle Filme & Spielzeiten
+
Alle Filme mit 7 Tagen Spielplan. Erste Vorstellung täglich ab 13:00 Uhr.
+
{ api_token }
+
+
+
+
+
diff --git a/src/components/Navbar.astro b/src/components/Navbar.astro
new file mode 100644
index 0000000..86cd442
--- /dev/null
+++ b/src/components/Navbar.astro
@@ -0,0 +1,22 @@
+
+ EAGLE's IMAX
+
+
diff --git a/src/components/SnackPrompt.astro b/src/components/SnackPrompt.astro
new file mode 100644
index 0000000..e9ffe10
--- /dev/null
+++ b/src/components/SnackPrompt.astro
@@ -0,0 +1,10 @@
+
+
+
Popcorn gefällig? 🍿
+
Möchtest du noch Snacks oder Getränke hinzufügen?
+
+ Ja, Snacks wählen
+ Weiter zum Warenkorb
+
+
+
diff --git a/src/components/SnacksView.astro b/src/components/SnacksView.astro
new file mode 100644
index 0000000..683e6e8
--- /dev/null
+++ b/src/components/SnacksView.astro
@@ -0,0 +1,449 @@
+
+
+
Snacks & Getränke
+
+
+ Getränke
+ Popcorn
+ Nachos
+ Snacks
+ Kombi
+ Eis
+
+
+
+
+
+
+
+
Coca Cola
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+ 0,75L 4,50€
+ 1L 5,50€
+
+
+
+
+
+
+
Coca Cola Zero
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+ 0,75L 4,50€
+ 1L 5,50€
+
+
+
+
+
+
+
Coca Cola Light
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+ 0,75L 4,50€
+ 1L 5,50€
+
+
+
+
+
+
+
Sprite
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+ 0,75L 4,50€
+ 1L 5,50€
+
+
+
+
+
+
+
Fanta
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+ 0,75L 4,50€
+ 1L 5,50€
+
+
+
+
+
+
+
Mezzo Mix
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+ 0,75L 4,50€
+ 1L 5,50€
+
+
+
+
+
+
+
Wasser
+
+ 0,33L 2,00€
+ 0,50L 3,00€
+ 0,75L 3,50€
+ 1L 4,00€
+
+
+
+
+
+
+
Apfelschorle
+
+ 0,33L 2,00€
+ 0,50L 3,00€
+ 0,75L 3,50€
+ 1L 4,00€
+
+
+
+
+
+
+
Fuze Tea
+
+ 0,33L 2,50€
+ 0,50L 3,50€
+
+
+
+
+
+
+
+
+
+
+
+
Popcorn klein
+
+ Süß
+ Salzig
+
+
+ 3,50€
+
+
+
+
+
+
+
Popcorn Mittel
+
+ Süß
+ Salzig
+
+
+ 4,50€
+
+
+
+
+
+
+
Popcorn Groß
+
+ Süß
+ Salzig
+
+
+ 6,00€
+
+
+
+
+
+
+
Limitierter Metallbecher - Zoomania 2
+
+ Süß
+ Salzig
+
+
+ 12,00€
+
+
+
+
+
+
+
Limitierter Sammelbecher - Scream VII
+
+ Süß
+ Salzig
+
+
+ 29,00€
+
+
+
+
+
+
+
Limitierter Sammelbecher - Der Austronaut
+
+ Süß
+ Salzig
+
+
+ 34,00€
+
+
+
+
+
+
+
Limitierter Metallbecher - Hoppers
+
+ Süß
+ Salzig
+
+
+ 12,00€
+
+
+
+
+
+
+
Limitierter Sammelbecher - Hoppers
+
+ Süß
+ Salzig
+
+
+ 21,00€
+
+
+
+
+
+
+
Limitierter Sammelbecher - Yoshi Becher
+
+ Süß
+ Salzig
+
+
+ 35,90€
+
+
+
+
+
+
+
+
+
+
+
+
Nachos Klein
+
+ Käse-Dip
+ Salsa-Dip
+
+
+ Klein 5,00€
+
+
+
+
+
+
+
Nachos Normal
+
+ Käse-Dip
+ Salsa-Dip
+
+
+ Mittel 6,50€
+
+
+
+
+
+
+
Nachos Groß
+
+ Käse-Dip
+ Sourcreme-Dip
+ Salsa-Dip
+
+
+ Groß 8,00€
+
+
+
+
Dips
+
+
+
+
Käse-Dip (warm)
+
+ Normal
+ Scharf
+
+
+ Schale 2,00€
+
+
+
+
+
+
+
Sourcreme-Dip
+
+ Normal
+
+
+ Schale 2,00€
+
+
+
+
+
+
+
Salsa-Dip
+
+ Normal
+
+
+ Schale 2,00€
+
+
+
+
Nacho Kombi-Menüs
+
+
+
+
Nacho Menü Klein – Nachos klein + 1 Dip + 1 0,33L Getränk
+
+ Klein
+
+
+ Kombi 6,90€
+
+
+
+
+
+
+
+
+
+
+
+
M&M's (verschiedene Sorten)
+
+ Packung 4,00€
+
+
+
+
+
+
+
Haribo Goldbären (verschiedene Sorten)
+
+ Tüte 3,00€
+
+
+
+
+
+
+
Schokoriegel (verschiedene Sorten)
+
+ Tüte 2,50€
+
+
+
+
+
+
+
+
+
+
+
Kleines Menü
+
0,33L Getränk + Popcorn Klein
+
+ Menü-Preis 5,00€
+
+
+
+
+
+
Mittleres Menü
+
0,5L Getränk + Popcorn Mittel
+
+ Menü-Preis 6,50€
+
+
+
+
+
+
Bestseller
+
Großes Menü
+
1L Getränk + Popcorn Groß
+
+ Menü-Preis 8,00€
+
+
+
+
+
+
+
SPECIAL
+
Limitiertes Menü
+
0,5L Getränk im HOPPERS Becher + HOPPERS Popcorn Schale + HOPPERS Figur
+
+ Menü-Preis 10,00€
+
+
+
+
+
+
+
SPECIAL
+
Limitiertes Menü
+
0,5L Getränk im MARIO GALAXY Becher + MARIO GALAXY Popcorn Schale
+
+ Menü-Preis 10,00€
+
+
+
+
+
+
+
SPECIAL
+
Limitiertes Menü
+
0,5L Getränk im ZOOMANIA Becher + ZOOMANIA Popcorn Schale + Figur zum aussuchen
+
+ Menü-Preis 10,00€
+
+
+
+
+
+
+
+
+
Eiscreme & Shakes
+
Coming Soon...
+
Wir bereiten etwas ganz Besonderes für dich vor! Coming this summer!
+
+
+
+
diff --git a/src/components/TechModal.astro b/src/components/TechModal.astro
new file mode 100644
index 0000000..17199c8
--- /dev/null
+++ b/src/components/TechModal.astro
@@ -0,0 +1,25 @@
+
+
+
×
+
Technik
+
Daten und Eckwerte zu Bild, Projektoren, Leinwandgrößen und Sitzkapazitäten.
+
+
+ Projektoren
+
+
+
+ Leinwandgrößen
+
+
+
+ Sitzplätze pro Saal
+
+
+
+ Bild & Audio
+
+
+
+
+
diff --git a/src/components/react/topbar.tsx b/src/components/react/topbar.tsx
new file mode 100644
index 0000000..438f02e
--- /dev/null
+++ b/src/components/react/topbar.tsx
@@ -0,0 +1,8 @@
+export default function topbar() {
+ return (
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/topbar.astro b/src/components/topbar.astro
new file mode 100644
index 0000000..791dd3d
--- /dev/null
+++ b/src/components/topbar.astro
@@ -0,0 +1,14 @@
+---
+import "../../src/styles/global.css";
+---
+
+
\ No newline at end of file
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 561196b..5a734b8 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,17 +1,48 @@
---
+import Navbar from "../components/Navbar.astro";
+import Hero from "../components/Hero.astro";
+import HomeSection from "../components/HomeSection.astro";
+import MovieListView from "../components/MovieListView.astro";
+import HallsView from "../components/HallsView.astro";
+import DboxView from "../components/DboxView.astro";
+import CollectorsView from "../components/CollectorsView.astro";
+import AboutView from "../components/AboutView.astro";
+import SnacksView from "../components/SnacksView.astro";
+import BookingModal from "../components/BookingModal.astro";
+import CartView from "../components/CartView.astro";
+import AccountView from "../components/AccountView.astro";
+import CheckoutView from "../components/CheckoutView.astro";
+import SnackPrompt from "../components/SnackPrompt.astro";
+import TechModal from "../components/TechModal.astro";
+import "../styles/global.css";
+---
----
+
+
+
+
+
+ EAGLE's IMAX | Deluxe Experience
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- Astro
-
-
- Astro
-
+
+
diff --git a/src/scripts/account.ts b/src/scripts/account.ts
new file mode 100644
index 0000000..4f39041
--- /dev/null
+++ b/src/scripts/account.ts
@@ -0,0 +1,474 @@
+import type { User } from "./interfaces.js";
+
+function readStorageJson(key: string, fallbackValue: any) {
+ const raw = localStorage.getItem(key);
+
+ if (!raw || raw === "undefined" || raw === "null") {
+ return fallbackValue;
+ }
+
+ try {
+ return JSON.parse(raw);
+ } catch (error) {
+ console.warn(`Konnte LocalStorage-Wert fuer ${key} nicht lesen.`, error);
+ return fallbackValue;
+ }
+}
+
+function normalizeUser(user: User): User {
+ return {
+ firstName: user.firstName || "",
+ lastName: user.lastName || "",
+ email: user.email || "",
+ hashedPassword: user.hashedPassword || "",
+ orders: Array.isArray(user.orders) ? user.orders : [],
+ paymentMethods: Array.isArray(user.paymentMethods) ? user.paymentMethods : []
+ };
+}
+
+function escapeHtml(value: string) {
+ return String(value || "")
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'");
+}
+
+function formatEuro(value: string) {
+ return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
+}
+
+function persistUsers() {
+ localStorage.setItem("eagleUsers", JSON.stringify(users));
+}
+
+function persistCurrentUser() {
+ if (currentUser) {
+ localStorage.setItem("currentUser", JSON.stringify(currentUser));
+ } else {
+ localStorage.removeItem("currentUser");
+ }
+}
+
+export let users = readStorageJson("eagleUsers", []);
+if (!Array.isArray(users)) {
+ users = [];
+}
+users = users.map(normalizeUser).filter(Boolean);
+
+const rawCurrentUser = readStorageJson("currentUser", null);
+
+export var currentUser: User | null = rawCurrentUser ? normalizeUser(rawCurrentUser) : null;
+
+if (currentUser && currentUser.email) {
+ const currentEmail = currentUser.email;
+ const storedMatch = users.find((user: { email: string; }) => {
+ return user.email === currentEmail;
+ });
+ if (storedMatch) {
+ currentUser = storedMatch;
+ } else {
+ users.push(currentUser);
+ persistUsers();
+ }
+}
+
+async function hashMessage(message: string) {
+ const msgBuffer = new TextEncoder().encode(message); // Encode as UTF-8
+ const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer); // Hash
+ const hashArray = Array.from(new Uint8Array(hashBuffer)); // Convert to bytes
+ return hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // Hex string
+}
+
+function getInputValue(id: string): string {
+ const el = document.getElementById(id) as HTMLInputElement | null;
+ return el?.value.trim() ?? "";
+}
+
+export async function registerUser() {
+const firstName = getInputValue("reg-firstname");
+const lastName = getInputValue("reg-lastname");
+const email = getInputValue("reg-email").toLowerCase();
+const password = document.querySelector("#reg-password")?.value ?? "";
+
+ if (!firstName || !lastName || !email || !password) {
+ alert("Bitte fuelle alle Felder aus.");
+ return;
+ }
+
+ if (!email.includes("@")) {
+ alert("Bitte gib eine gueltige E-Mail-Adresse ein.");
+ return;
+ }
+
+ const existingUser = users.find((user: User) => user.email.toLowerCase() === email);
+ if (existingUser) {
+ alert("E-Mail bereits registriert");
+ return;
+ }
+
+ const hashedPassword = await hashMessage(password);
+
+ const newUser = {
+ firstName,
+ lastName,
+ email,
+ hashedPassword,
+ orders: [],
+ paymentMethods: []
+ };
+
+ users.push(newUser);
+ currentUser = newUser;
+
+ persistUsers();
+ persistCurrentUser();
+
+ alert("Registrierung erfolgreich");
+ document.getElementById("register-modal")?.classList.add("hidden");
+
+ openAccountDashboard();
+}
+
+export async function loginUser() {
+ const email = (document.querySelector("#login-email")?.value.trim() || "").toLowerCase();
+ const password = document.querySelector("#login-password")?.value || "";
+ const hashedPassword = await hashMessage(password);
+
+ const user = users.find(
+ (entry: User) => entry.email.toLowerCase() === email && entry.hashedPassword === hashedPassword
+ );
+
+ if (!user) {
+ document.getElementById("login-error")?.classList.remove("hidden");
+ return;
+ }
+
+ currentUser = user;
+ persistCurrentUser();
+ openAccountDashboard();
+}
+
+export function openAccountDashboard() {
+ const accountView = document.getElementById("account-view");
+ if (!accountView) {
+ return;
+ }
+
+ if (!currentUser) {
+ accountView.innerHTML = "Mein Konto Bitte melde dich an oder registriere dich.
";
+ return;
+ }
+
+ accountView.innerHTML = /*html*/`
+
+
+
+
+ Persönliche Daten
+ Meine Bestellungen
+ Zahlungsmethoden
+
+
+
+
+ `;
+
+ renderPersonalInfo();
+}
+
+function renderPersonalInfo() {
+ const target = document.getElementById("account-tab-content");
+ if (!target || !currentUser) {
+ return;
+ }
+
+ target.innerHTML = `
+
+
Vorname: ${currentUser.firstName || "-"}
+
Nachname: ${currentUser.lastName || "-"}
+
E-Mail: ${currentUser.email || "-"}
+
+ `;
+}
+
+function renderOrders() {
+ const target = document.getElementById("account-tab-content");
+ if (!target || !currentUser) {
+ return;
+ }
+
+ const orders = Array.isArray(currentUser.orders) ? currentUser.orders : [];
+
+ if (!orders.length) {
+ target.innerHTML = `
+
+
Meine Bestellungen
+
Noch keine Bestellungen vorhanden.
+
+ `;
+ return;
+ }
+
+ const orderHtml = orders
+ .map((order, index) => {
+ const movieItems = Array.isArray(order.items)
+ ? order.items.filter((item: any) => item.category === "movie")
+ : [];
+ const previewItem = movieItems[0] || (Array.isArray(order.items) ? order.items[0] : null);
+ const previewTitle = previewItem?.title || "Bestellung";
+ const ticketsCount = movieItems.length || (Array.isArray(order.items) ? order.items.length : 0);
+
+ return `
+
+
+
${escapeHtml(previewTitle)}
+ ${formatEuro(order.total || 0)}
+
+ Datum: ${escapeHtml(order.date || "-")}
+ Anzahl: ${ticketsCount}x
+
+ `;
+ })
+ .join("");
+
+ target.innerHTML = `
+
+
Meine Bestellungen
+
Klicke auf eine Bestellung, um dein Ticket-Detail zu sehen.
+
${orderHtml}
+
+
+ `;
+
+ const detailTarget = document.getElementById("order-ticket-details");
+ const orderButtons = Array.from(target.querySelectorAll(".order-item-btn"));
+
+ const renderOrderTicket = (orderIndex: number) => {
+ const order = orders[orderIndex];
+ if (!order || !detailTarget) {
+ return;
+ }
+
+ const movieItems = Array.isArray(order.items)
+ ? order.items.filter((item: any) => item.category === "movie")
+ : [];
+ const primaryMovie = movieItems[0] || (Array.isArray(order.items) ? order.items[0] : null);
+ const poster = primaryMovie?.img || "";
+ const seats = movieItems.map((item: any) => item.seatId).filter(Boolean).join(", ") || "-";
+ const ticketCount = movieItems.length || (Array.isArray(order.items) ? order.items.length : 0);
+ const hall = primaryMovie?.hall || "-";
+ const time = primaryMovie?.time ? `${primaryMovie.time} Uhr` : "-";
+
+ detailTarget.innerHTML = `
+
+
+ ${poster
+ ? `
`
+ : `
Kein Poster
`}
+
+
+
EAGLE'S IMAX | Bestell-Details
+
${escapeHtml(primaryMovie?.title || "Bestellung")}
+
+
Datum ${escapeHtml(order.date || "-")}
+
Saal ${escapeHtml(hall)}
+
Uhrzeit ${escapeHtml(time)}
+
Tickets ${ticketCount}x
+
Sitze ${escapeHtml(seats)}
+
Gesamt ${formatEuro(order.total || 0)}
+
+
+
+ `;
+
+ detailTarget.classList.remove("hidden");
+ orderButtons.forEach((button) => {
+ button.classList.toggle("active", Number(button.dataset.orderIndex) === orderIndex);
+ });
+ };
+
+ orderButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ const orderIndex = Number(button.dataset.orderIndex || -1);
+ if (orderIndex >= 0) {
+ renderOrderTicket(orderIndex);
+ }
+ });
+ });
+
+}
+
+function renderPayments() {
+ const target = document.getElementById("account-tab-content");
+ if (!target || !currentUser) {
+ return;
+ }
+
+ target.innerHTML = /*html*/`
+
+
Zahlungsmethoden
+
Platzhalter zum Hinterlegen deiner Logos oder Anbieter-Informationen.
+
+
+
+
+
+ Visa / Mastercard
+ Karteninformationen hinterlegen
+
+
+
+
+
+ PayPal
+ Konto verbinden
+
+
+
+
+
+ Apple Pay
+ Geraet freischalten
+
+
+
+
+
+ Google Pay
+ Wallet verknuepfen
+
+
+
+
+
+
+
×
+
+
+
Kreditkarte hinterlegen
+
+
+
Karte speichern
+
+
+
+
+
+
×
+
+
+
PayPal verbinden
+
+
Einloggen und dein PayPal-Konto mit deinem Kino-Account verbinden.
+
E-Mail
+
+
+
Passwort
+
+
+
Mit PayPal fortfahren
+
+
+
+
+
+
×
+
+
+
Apple Pay einrichten
+
+
Apple Pay wirkt schlicht, klar und fokussiert. Hinterlege hier die bevorzugte Karte für schnelle Zahlungen.
+
Apple-ID E-Mail
+
+
+
Bevorzugte Karte
+
+
+
Zu Wallet hinzufügen
+
+
+
+
+
+
×
+
+
+
Google Pay einrichten
+
+
Verbinde deine Wallet, damit zukünftige Bestellungen in wenigen Klicks abgeschlossen werden.
+
Google-Konto
+
+
+
Standard-Zahlungsquelle
+
+
+
Wallet verbinden
+
+
+ `;
+
+ const modals = Array.from(target.querySelectorAll(".pay-modal-overlay"));
+ const triggers = Array.from(target.querySelectorAll(".account-pay-trigger"));
+ const closeButtons = Array.from(target.querySelectorAll("[data-pay-close]"));
+
+ const closeAllPaymentModals = () => {
+ modals.forEach((modal) => modal.classList.add("hidden"));
+ document.body.style.overflow = "auto";
+ };
+
+ triggers.forEach((trigger) => {
+ trigger.addEventListener("click", () => {
+ closeAllPaymentModals();
+ const targetId = trigger.getAttribute("data-pay-modal");
+ const modal = targetId ? target.querySelector(`#${targetId}`) : null;
+
+ if (modal) {
+ modal.classList.remove("hidden");
+ document.body.style.overflow = "hidden";
+ }
+ });
+ });
+
+ closeButtons.forEach((button) => {
+ button.addEventListener("click", closeAllPaymentModals);
+ });
+
+ modals.forEach((modal) => {
+ modal.addEventListener("click", (event) => {
+ if (event.target === modal) {
+ closeAllPaymentModals();
+ }
+ });
+ });
+}
+
+function logoutUser() {
+ persistCurrentUser();
+ window.location.reload();
+}
+
+(window as any).logoutUser = logoutUser;
+(window as any).renderPersonalInfo = renderPersonalInfo;
+(window as any).renderOrders = renderOrders;
+(window as any).renderPayments = renderPayments;
+
diff --git a/src/scripts/bigConsts.ts b/src/scripts/bigConsts.ts
new file mode 100644
index 0000000..fa8f087
--- /dev/null
+++ b/src/scripts/bigConsts.ts
@@ -0,0 +1,33 @@
+import type { MovieCatalog } from "./interfaces";
+// script will be removed since we switch to apis
+
+
+export const movieCatalog:MovieCatalog[] = [
+ {
+ title: "Zoomania 2",
+ genre: "Animation",
+ duration: 148,
+ fsk: "6",
+ description: "In Walt Disney Animation Studios’ \"Zoomania 2\" geraten die tierischen Detektive Judy Hopps und Nick Wilde auf die rätselhafte Spur eines geheimnisvollen Reptils, das in Zoomania auftaucht und die Metropole völlig auf den Kopf stellt: Gary De’Snake! ",
+ poster: "img/Zoomania-2.jpg",
+ backdrop: "img/Zoomania-2.jpg"
+ },
+ {
+ title: "Shelter",
+ genre: "Action, Abenteuer",
+ duration: 147,
+ fsk: "16",
+ description: "Michael Mason, ein untergetauchter Elite-Agent, lebt auf einer abgelegenen Insel in Schottland. Als er in einem schweren Sturm ein Mädchen vor dem Ertrinken rettet, setzt er damit eine Kette von Ereignissen in Gang, die sein Versteck enttarnen und ihn zurück in die Welt zwingen. Dort muss er nicht nur um das Überleben der Teenagerin kämpfen, sondern sich auch den Dämonen seiner Vergangenheit stellen…",
+ poster: "img/shelter.jpg",
+ backdrop: "img/shelter.jpg"
+ },
+ {
+ title: "Mutiny",
+ genre: "Action, Abenteuer",
+ duration: 0,
+ fsk: "?",
+ description: "Als sein milliardenschwerer Boss vor seinen Augen einem Mordkomplott zum Opfer fällt, wird Cole Reed (Jason Statham) für das Verbrechen verantwortlich gemacht. Im Bestreben dessen Tod zu rächen und die Täter zu überführen, gelangt Reed an Bord eines Frachters und stößt dabei auf eine internationale Verschwörung. Im Alleingang startet Cole eine gnadenlose Racheaktion auf hoher See…",
+ poster: "img/mutiny.jpg",
+ backdrop: "img/mutiny.jpg"
+ }
+ ];
\ No newline at end of file
diff --git a/src/scripts/booking.ts b/src/scripts/booking.ts
new file mode 100644
index 0000000..9c12878
--- /dev/null
+++ b/src/scripts/booking.ts
@@ -0,0 +1,358 @@
+import { seatLayouts, occupiedSeatsData, prices, cart } from "./main.js"
+import { renderCart, saveCart } from "./cart.js";
+import { renderCheckout } from "./checkout.js";
+
+let currentBookingContext: any = null;
+let currentHallLayout: any = null;
+
+export function openBooking(movie: string, hall: string, time: any) {
+ const titleEl = document.getElementById("modal-movie-title");
+ const infoEl = document.getElementById("modal-info-text");
+
+ if (titleEl) {
+ titleEl.innerText = movie;
+ }
+
+ if (infoEl) {
+ infoEl.innerText = `${hall} • ${time} Uhr`;
+ }
+
+ currentBookingContext = { movie, hall, time };
+
+ createSeats(hall, time);
+ renderBookingLegend();
+ updateBookingSummary();
+
+ document.getElementById("booking-modal")?.classList.remove("hidden");
+ }
+
+function getRowLabel(rowIndex: number) {
+ return String(rowIndex + 1);
+}
+
+function buildHallLayout(hallName: string, baseConfig:any) {
+ const rows = Number(baseConfig.rows || 0);
+ const totalCols = Number(baseConfig.left || 0) + Number(baseConfig.right || 0);
+ const isDeluxe = /deluxe/i.test(hallName);
+
+ const left = isDeluxe
+ ? Math.max(3, Number(baseConfig.left || 0) - 1)
+ : Number(baseConfig.left || 0);
+ const right = Math.max(0, totalCols - left);
+
+ const vipRows = rows > 0 ? [rows] : [];
+
+ const dboxMap = new Set();
+ const markDboxRange = (rowNumber: number, startCol: number, width: number) => {
+ if (!rowNumber || width <= 0) {
+ return;
+ }
+
+ const maxCol = Math.min(totalCols, startCol + width - 1);
+ for (let col = startCol; col <= maxCol; col++) {
+ dboxMap.add(`${rowNumber}-${col}`);
+ }
+ };
+
+ if (isDeluxe) {
+ const configuredDboxSeats = Array.isArray(baseConfig.dbox)
+ ? baseConfig.dbox.reduce((sum: number, section: any) => sum + Number(section.w || 0), 0)
+ : 0;
+
+ const totalDboxSeats = Math.max(4, configuredDboxSeats || 0);
+
+ const firstRow = Math.max(1, rows - 2);
+ const secondRow = Math.max(1, rows - 1);
+ const targetRows = [firstRow, secondRow]
+ .filter((rowNumber, index, arr) => arr.indexOf(rowNumber) === index)
+ .filter((rowNumber) => !vipRows.includes(rowNumber));
+
+ const rowCount = Math.max(1, targetRows.length);
+ const seatsPerFirstRows = Math.ceil(totalDboxSeats / rowCount);
+ let remaining = totalDboxSeats;
+
+ targetRows.forEach((rowNumber, index) => {
+ const seatsForRow = index === targetRows.length - 1
+ ? remaining
+ : Math.min(seatsPerFirstRows, remaining);
+ remaining -= seatsForRow;
+
+ const startCol = left + Math.max(1, Math.floor((right - seatsForRow) / 2) + 1);
+ markDboxRange(rowNumber, startCol, seatsForRow);
+ });
+ } else if (Array.isArray(baseConfig.dbox)) {
+ baseConfig.dbox.forEach((section: any) => {
+ const rowNumber = Number(section.r || 0);
+ const width = Number(section.w || 0);
+ const startCol = Number(section.c || 0);
+ markDboxRange(rowNumber, startCol, width);
+ });
+ }
+
+ return {
+ rows,
+ left,
+ right,
+ totalCols,
+ vipRows,
+ dboxMap,
+ isImax: Boolean(baseConfig.isImax)
+ };
+}
+
+function getSeatType(layout: any, rowNumber: number, colNumber: number) {
+ if (layout.dboxMap.has(`${rowNumber}-${colNumber}`)) {
+ return "dbox";
+ }
+
+ if (layout.vipRows.includes(rowNumber)) {
+ return "vip";
+ }
+
+ if (layout.isImax) {
+ return "imax";
+ }
+
+ return "normal";
+}
+
+function createSeatElement({seatId, seatType, occupiedSeats }:any) {
+ const seat = document.createElement("button");
+ seat.type = "button";
+ seat.classList.add("seat", seatType);
+ seat.dataset.seatId = seatId;
+ seat.dataset.type = seatType;
+ seat.title = `${seatId} (${seatType.toUpperCase()})`;
+
+ if (occupiedSeats.has(seatId)) {
+ seat.classList.add("occupied");
+ seat.disabled = true;
+ seat.setAttribute("aria-label", `${seatId} belegt`);
+ return seat;
+ }
+
+ seat.setAttribute("aria-label", `${seatId} frei`);
+ seat.addEventListener("click", () => {
+ seat.classList.toggle("selected");
+ updateBookingSummary();
+ });
+
+ return seat;
+}
+
+function createSeats(hallName: string, time: any) {
+ const seatGrid = document.getElementById("seat-grid");
+ if (!seatGrid) {
+ return;
+ }
+
+ seatGrid.innerHTML = "";
+
+ const arrIndex = hallName as keyof typeof seatLayouts;
+ const baseConfig: any = seatLayouts[arrIndex];
+ if (!baseConfig) {
+ currentHallLayout = null;
+ return;
+ }
+
+ currentHallLayout = buildHallLayout(hallName, baseConfig);
+
+ const occupiedKey = `${hallName}-${time}`;
+ const occupiedSeats = new Set(Array.isArray(occupiedSeatsData?.[occupiedKey]) ? occupiedSeatsData[occupiedKey] : []);
+
+ for (let rowIndex = 0; rowIndex < currentHallLayout.rows; rowIndex++) {
+ const rowNumber = rowIndex + 1;
+ const rowLabel = getRowLabel(rowIndex);
+
+ const perspectiveFactor = (currentHallLayout.rows - rowNumber) / Math.max(currentHallLayout.rows - 1, 1);
+ const rowIndent = Math.round(18 * perspectiveFactor);
+
+ const row = document.createElement("div");
+ row.className = "seat-row cinema-row";
+ row.style.setProperty("--row-indent", `${rowIndent}px`);
+
+ const leftLabel = document.createElement("div");
+ leftLabel.className = "row-label";
+ leftLabel.textContent = rowLabel;
+
+ const rightLabel = document.createElement("div");
+ rightLabel.className = "row-label row-label-right";
+ rightLabel.textContent = rowLabel;
+
+ const leftBlock = document.createElement("div");
+ leftBlock.className = "row-seat-block left-block";
+
+ const rightBlock = document.createElement("div");
+ rightBlock.className = "row-seat-block right-block";
+
+ for (let col = 1; col <= currentHallLayout.totalCols; col++) {
+ const seatId = `R${rowNumber}-P${col}`;
+ const seatType = getSeatType(currentHallLayout, rowNumber, col);
+ const seat = createSeatElement({ seatId, seatType, occupiedSeats });
+
+ if (col <= currentHallLayout.left) {
+ leftBlock.appendChild(seat);
+ } else {
+ rightBlock.appendChild(seat);
+ }
+ }
+
+ const aisle = document.createElement("div");
+ aisle.className = "aisle-gap";
+
+ row.append(leftLabel, leftBlock, aisle, rightBlock, rightLabel);
+ seatGrid.appendChild(row);
+ }
+}
+
+function renderBookingLegend() {
+ const legend = document.getElementById("dynamic-legend");
+ if (!legend || !currentHallLayout) {
+ return;
+ }
+
+ const legendItems = [
+ { type: "normal", label: "Standard" },
+ { type: "selected", label: "Ausgewählt" },
+ { type: "occupied", label: "Belegt" }
+ ];
+
+ if (currentHallLayout.isImax) {
+ legendItems.unshift({ type: "imax", label: "IMAX" });
+ }
+
+ if (currentHallLayout.vipRows.length > 0) {
+ legendItems.unshift({ type: "vip", label: "VIP" });
+ }
+
+ if (currentHallLayout.dboxMap.size > 0) {
+ legendItems.unshift({ type: "dbox", label: "D-BOX" });
+ }
+
+ legend.innerHTML = legendItems
+ .map((item) => `
+
+
+ ${item.label}
+
+ `)
+ .join("");
+}
+
+function updateBookingSummary() {
+ const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected")) as HTMLElement[];;
+ const summaryPanel = document.getElementById("booking-summary");
+ const summaryItems = document.getElementById("summary-items");
+ const totalEl = document.getElementById("total-price");
+
+ let total = 0;
+
+ if (summaryItems) {
+ summaryItems.innerHTML = selectedSeats
+ .map((seat) => {
+ const type = (seat.dataset.type || "normal") as keyof typeof prices;
+ const seatPrice = Number(prices?.[type] ?? prices?.normal ?? 11);
+ total += seatPrice;
+
+ return `
+
+ ${seat.dataset.seatId}
+ ${seatPrice.toFixed(2).replace(".", ",")} EUR
+
+ `;
+ })
+ .join("");
+ } else {
+ selectedSeats.forEach((seat) => {
+ const type = seat.dataset.type || "normal";
+ const seatPrice = Number(prices?.[type] ?? prices?.normal ?? 11);
+ total += seatPrice;
+ });
+ }
+
+ if (totalEl) {
+ totalEl.innerText = `${total.toFixed(2).replace(".", ",")} EUR`;
+ }
+
+ summaryPanel?.classList.toggle("hidden", selectedSeats.length === 0);
+}
+
+function findMoviePoster(movieTitle: string) {
+ const cards = Array.from(document.querySelectorAll(".movie-card, .detailed-card"));
+ const normalizedTarget = String(movieTitle || "").trim().toLowerCase();
+
+ for (const card of cards) {
+ const currentCard = card.querySelector("h2, h3") as HTMLElement;
+ const title = currentCard.innerText?.trim().toLowerCase();
+ if (title === normalizedTarget) {
+ const imageSrc = card.querySelector("img")?.src;
+ if (imageSrc) {
+ return imageSrc;
+ }
+ }
+ }
+
+ return "";
+}
+
+function confirmSelectedSeats() {
+ const selectedSeats = Array.from(document.querySelectorAll("#seat-grid .seat.selected")) as HTMLElement[];
+
+ if (!currentBookingContext || selectedSeats.length === 0) {
+ alert("Bitte waehle mindestens einen Platz aus.");
+ return;
+ }
+
+ const moviePoster = findMoviePoster(currentBookingContext.movie);
+ const addedSeats = [];
+
+ selectedSeats.forEach((seat) => {
+ const seatId = seat.dataset.seatId;
+ const seatType = seat.dataset.type || "normal";
+
+ const alreadyInCart = cart.some((item: any) =>
+ item.category === "movie" &&
+ item.title === currentBookingContext.movie &&
+ item.hall === currentBookingContext.hall &&
+ item.time === currentBookingContext.time &&
+ item.seatId === seatId
+ );
+
+ if (alreadyInCart) {
+ return;
+ }
+
+ cart.push({
+ id: Date.now() + Math.random(),
+ category: "movie",
+ title: currentBookingContext.movie,
+ hall: currentBookingContext.hall,
+ time: currentBookingContext.time,
+ seatId,
+ type: seatType.toUpperCase(),
+ price: Number(prices?.[seatType] ?? prices?.normal ?? 11),
+ img: moviePoster
+ });
+
+ addedSeats.push(seatId);
+ });
+
+ if (!addedSeats.length) {
+ alert("Diese Plaetze sind bereits im Warenkorb.");
+ return;
+ }
+
+ saveCart?.();
+ renderCart?.();
+ renderCheckout?.();
+
+ document.getElementById("booking-modal")?.classList.add("hidden");
+
+ const snackOverlay = document.getElementById("snack-prompt-overlay");
+ snackOverlay?.classList.remove("hidden");
+ document.body.style.overflow = "hidden";
+}
+
+document.addEventListener("DOMContentLoaded", () => {
+ document.getElementById("btn-confirm-seats")?.addEventListener("click", confirmSelectedSeats);
+});
diff --git a/src/scripts/cart.ts b/src/scripts/cart.ts
new file mode 100644
index 0000000..a81c934
--- /dev/null
+++ b/src/scripts/cart.ts
@@ -0,0 +1,203 @@
+import { cart } from "./main.js";
+
+function formatEuro(value: number) {
+ return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
+}
+
+function escapeHtml(value: any) {
+ return String(value || "")
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'");
+}
+
+function buildCartKey(item: { category: string; seatId: any; hall: any; time: any; title: any; }) {
+ const infoText = item.category === "movie"
+ ? `Sitz: ${item.seatId} (${item.hall})`
+ : item.time;
+ return `${item.title}-${item.hall}-${infoText}`;
+}
+
+function isDrinkItem(item: { category: string; title: any; hall: any; }) {
+ if (item.category !== "snack") {
+ return false;
+ }
+
+ const title = String(item.title || "").toLowerCase();
+ const size = String(item.hall || "").toLowerCase();
+ const drinkKeywords = [
+ "cola",
+ "sprite",
+ "fanta",
+ "mezzo",
+ "fuze",
+ "wasser",
+ "getraenk",
+ "drink"
+ ];
+
+ return drinkKeywords.some((word) => title.includes(word)) || size.includes("l");
+}
+
+function buildItemInfo(item: { category: any; seatId?: any; hall: any; time?: any; title: any; }) {
+ if (item.category === "movie") {
+ return `
+ Sitzplatz: ${escapeHtml(item.seatId || "-")}
+ Saal: ${escapeHtml(item.hall || "-")}
+ Uhrzeit: ${escapeHtml(item.time || "-")} Uhr
+ `;
+ }
+
+ if (isDrinkItem(item)) {
+ return `
+ Variante: ${escapeHtml(item.time || "-")}
+ Groesse: ${escapeHtml(item.hall || "-")}
+ `;
+ }
+
+ return `
+ Kategorie: Snack
+ Variante: ${escapeHtml(item.time || "-")}
+ Groesse: ${escapeHtml(item.hall || "-")}
+ `;
+}
+
+function groupCartItems() {
+ const groups = new Map();
+
+ cart.forEach((item: { price?: any; category: string; seatId: any; hall: any; time: any; title: any; }) => {
+ const key = buildCartKey(item);
+
+ if (!groups.has(key)) {
+ groups.set(key, {
+ key,
+ quantity: 0,
+ total: 0,
+ item
+ });
+ }
+
+ const group = groups.get(key);
+ group.quantity += 1;
+ group.total += Number(item.price || 0);
+ });
+
+ return Array.from(groups.values());
+}
+
+export function saveCart() {
+ localStorage.setItem("eagleCart", JSON.stringify(cart));
+ updateCartBadge();
+}
+
+export function updateCartBadge() {
+ const cartBadge = document.getElementById("cart-badge");
+
+ if (!cartBadge) {
+ return;
+ }
+
+ cartBadge.innerText = cart.length;
+ cartBadge.classList.toggle("hidden", cart.length === 0);
+}
+
+export function renderCart() {
+ const cartList = document.getElementById("cart-items-list");
+ const totalEl = document.getElementById("cart-total-right");
+ const vatEl = document.getElementById("cart-vat-right");
+
+ if (!cartList || !totalEl || !vatEl) {
+ return;
+ }
+
+ if (!Array.isArray(cart) || cart.length === 0) {
+ cartList.innerHTML = 'Dein Warenkorb ist leer.
';
+ totalEl.innerText = formatEuro(0);
+ vatEl.innerText = `inkl. 19% MwSt: ${formatEuro(0)}`;
+ return;
+ }
+
+ const groupedItems = groupCartItems();
+
+ const header = /*html*/`
+
+ `;
+
+ const rows = groupedItems
+ .map((group) => {
+ const imageHtml = group.item.img
+ ? /*html*/` `
+ : /*html*/`Kein Bild
`;
+ const quantityHtml = group.item.category === "movie"
+ ? /*html*/`${group.quantity}x
`
+ : /*html*/`
+
+ -
+ ${group.quantity}
+ +
+
+ `;
+
+ return /*html*/`
+
+
+ ${quantityHtml}
+
+
${imageHtml}
+
${escapeHtml(group.item.title)}
+
${buildItemInfo(group.item)}
+
${formatEuro(group.total)}
+
+ 🗑️
+
+
+ `;
+ })
+ .join("");
+
+ cartList.innerHTML = header + rows;
+
+ const total = cart.reduce((sum, item) => sum + Number(item.price || 0), 0);
+ const vat = total - total / 1.19;
+
+ totalEl.innerText = formatEuro(total);
+ vatEl.innerText = `inkl. 19% MwSt: ${formatEuro(vat)}`;
+
+ saveCart();
+}
+//@ts-ignore
+window.removeItem = function removeItem(id: any) {
+ var localCart = cart.filter((item: { id: any; }) => item.id !== id);
+ saveCart();
+ renderCart();
+};
+
+//@ts-ignore
+window.changeQty = function changeQty(title, delta): void {
+ if (delta > 0) {
+ const item = cart.find((entry: { title: any; }) => entry.title === title);
+ if (item) {
+ cart.push({ ...item, id: Date.now() + Math.random() });
+ }
+ } else {
+ const index = cart
+ .map((entry: { title: any; }) => entry.title)
+ .lastIndexOf(title);
+ if (index !== -1) {
+ cart.splice(index, 1);
+ }
+ }
+
+ saveCart();
+ renderCart();
+};
+
diff --git a/src/scripts/checkout.ts b/src/scripts/checkout.ts
new file mode 100644
index 0000000..2c7c58b
--- /dev/null
+++ b/src/scripts/checkout.ts
@@ -0,0 +1,238 @@
+import { currentUser, users } from "./account.js";
+import { renderCart, saveCart } from "./cart.js";
+import { cart, emptyCart, occupiedSeatsData } from "./main.js";
+
+function formatCheckoutEuro(value: number) {
+ return `${Number(value || 0).toFixed(2).replace(".", ",")} EUR`;
+}
+
+let selectedPaymentMethod = "";
+let checkoutEventsBound = false;
+
+function setCheckoutStep(step: number) {
+ const step1 = document.getElementById("checkout-step-1");
+ const step2 = document.getElementById("checkout-step-2");
+ const step3 = document.getElementById("checkout-step-3");
+
+ step1?.classList.toggle("hidden", step !== 1);
+ step2?.classList.toggle("hidden", step !== 2);
+ step3?.classList.toggle("hidden", step !== 3);
+
+ const line1 = document.getElementById("line-1");
+ const line2 = document.getElementById("line-2");
+ const indicator1 = document.getElementById("step-1-indicator");
+ const indicator2 = document.getElementById("step-2-indicator");
+ const indicator3 = document.getElementById("step-3-indicator");
+
+ indicator1?.classList.add("active");
+ indicator2?.classList.toggle("active", step >= 2);
+ indicator3?.classList.toggle("active", step >= 3);
+ line1?.classList.toggle("active", step >= 2);
+ line2?.classList.toggle("active", step >= 3);
+}
+
+export function renderCheckout() {
+ const summaryList = document.getElementById("checkout-summary-list");
+ const totalDisplay = document.getElementById("checkout-total-display");
+ const vatDisplay = document.getElementById("checkout-vat-display");
+ const nextButton = document.getElementById("btn-next-step-2");
+
+ if (!summaryList) {
+ return;
+ }
+
+ summaryList.innerHTML = "";
+
+ const safeCart = Array.isArray(cart) ? cart : [];
+ const total = safeCart.reduce((sum, item) => sum + Number(item.price || 0), 0);
+ const vat = total - total / 1.19;
+
+ safeCart.forEach((item) => {
+ const row = document.createElement("div");
+ row.style.cssText = "display:flex; justify-content:space-between; gap:12px; margin-bottom:10px; font-size:0.95rem;";
+
+ const infoText = item.category === "movie"
+ ? `Sitz ${item.seatId || "-"} | ${item.hall || "-"} | ${item.time || "-"} Uhr`
+ : `${item.time || "Standard"} | ${item.hall || "-"}`;
+
+ row.innerHTML = `${item.title} (${infoText}) ${formatCheckoutEuro(item.price)} `;
+ summaryList.appendChild(row);
+ });
+
+ if (totalDisplay) {
+ totalDisplay.innerText = `Gesamtbetrag: ${formatCheckoutEuro(total)}`;
+ }
+
+ if (vatDisplay) {
+ vatDisplay.innerText = `inkl. 19% MwSt: ${formatCheckoutEuro(vat)}`;
+ }
+
+ selectedPaymentMethod = "";
+ document.querySelectorAll(".payment-method").forEach((method) => {
+ method.classList.remove("selected");
+ });
+
+ nextButton?.classList.add("hidden");
+ setCheckoutStep(1);
+}
+
+function generateTicket() {
+ const ticketContainer = document.getElementById("ticket-container");
+ if (!ticketContainer) {
+ return;
+ }
+
+ const moviesInCart = (Array.isArray(cart) ? cart : []).filter((item) => item.category === "movie");
+ if (!moviesInCart.length) {
+ ticketContainer.innerHTML = "Danke fuer deinen Einkauf!
";
+ return;
+ }
+
+ const mainMovie = moviesInCart[0];
+ const matchingMovieSeats = moviesInCart
+ .filter((item) => item.title === mainMovie.title && item.time === mainMovie.time)
+ .map((item) => item.seatId)
+ .join(", ");
+
+ const qrData = encodeURIComponent(`EAGLE-IMAX|${mainMovie.title}|${mainMovie.hall}|${matchingMovieSeats}`);
+ const qrUrl = `https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=${qrData}&bgcolor=ffffff`;
+
+ ticketContainer.innerHTML = /*html*/`
+
+
+
+
+
+
EAGLE'S IMAX PREMIUM
+
${mainMovie.title}
+
+
SAAL ${mainMovie.hall}
+
ZEIT ${mainMovie.time} Uhr
+
SITZE ${matchingMovieSeats || "-"}
+
+
+
+
+ `;
+}
+
+function saveOrderForCurrentUser(orderItems: any[], orderTotal: any) {
+ if (typeof currentUser === "undefined" || !currentUser) {
+ return;
+ }
+
+ if (typeof users === "undefined" || !Array.isArray(users)) {
+ return;
+ }
+
+ const order = {
+ date: new Date().toLocaleString("de-DE"),
+ items: orderItems,
+ total: orderTotal,
+ paymentMethod: selectedPaymentMethod || "-"
+ };
+
+ //@ts-ignore
+ const userIndex = users.findIndex((entry) => entry.email === currentUser.email);
+ if (userIndex === -1) {
+ return;
+ }
+
+ if (!Array.isArray(users[userIndex].orders)) {
+ users[userIndex].orders = [];
+ }
+
+ users[userIndex].orders.push(order);
+ localStorage.setItem("eagleUsers", JSON.stringify(users));
+}
+
+function reserveSeatsAfterPayment(orderItems: any[]) {
+ const movieItems = orderItems.filter((item) => item.category === "movie");
+
+ movieItems.forEach((item) => {
+ const key = `${item.hall}-${item.time}`;
+ if (!occupiedSeatsData[key]) {
+ occupiedSeatsData[key] = [];
+ }
+
+ occupiedSeatsData[key].push(item.seatId);
+ });
+
+ localStorage.setItem("eagleOccupied", JSON.stringify(occupiedSeatsData));
+}
+
+function completeCheckout() {
+ const orderItems = Array.isArray(cart) ? [...cart] : [];
+ const orderTotal = orderItems.reduce((sum, item) => sum + Number(item.price || 0), 0);
+
+ saveOrderForCurrentUser(orderItems, orderTotal);
+ reserveSeatsAfterPayment(orderItems);
+
+ emptyCart?.()
+ saveCart?.();
+ renderCart?.();
+}
+
+function bindCheckoutEvents() {
+ if (checkoutEventsBound) {
+ return;
+ }
+
+ checkoutEventsBound = true;
+
+ const nextButton = document.getElementById("btn-next-step-2");
+ const backButton = document.getElementById("btn-back-to-step1");
+ const payNowButton = document.getElementById("btn-pay-now") as HTMLButtonElement;
+
+ document.querySelectorAll(".payment-method").forEach((method) => {
+ method.addEventListener("click", () => {
+ document.querySelectorAll(".payment-method").forEach((entry) => {
+ entry.classList.remove("selected");
+ });
+
+ method.classList.add("selected");
+ //@ts-ignore
+ selectedPaymentMethod = method.dataset.method || "";
+ nextButton?.classList.remove("hidden");
+ });
+ });
+
+ nextButton?.addEventListener("click", () => {
+ if (!selectedPaymentMethod) {
+ alert("Bitte waehle zuerst eine Zahlungsmethode aus.");
+ return;
+ }
+
+ setCheckoutStep(2);
+ });
+
+ backButton?.addEventListener("click", () => {
+ setCheckoutStep(1);
+ });
+
+ payNowButton?.addEventListener("click", () => {
+ if (!Array.isArray(cart) || !cart.length) {
+ alert("Dein Warenkorb ist leer.");
+ return;
+ }
+
+ payNowButton.disabled = true;
+ payNowButton.innerText = "Verarbeite...";
+ payNowButton.style.opacity = "0.7";
+
+ setTimeout(() => {
+ setCheckoutStep(3);
+ generateTicket();
+ completeCheckout();
+
+ payNowButton.disabled = false;
+ payNowButton.innerText = "Jetzt Bezahlen";
+ payNowButton.style.opacity = "1";
+ }, 1200);
+ });
+}
+
+document.addEventListener("DOMContentLoaded", bindCheckoutEvents);
diff --git a/src/scripts/interfaces.ts b/src/scripts/interfaces.ts
new file mode 100644
index 0000000..5254fce
--- /dev/null
+++ b/src/scripts/interfaces.ts
@@ -0,0 +1,18 @@
+export interface User {
+ firstName: string;
+ lastName: string;
+ email: string;
+ hashedPassword: string;
+ orders: any[]; // TODO: figure out proper array type of orders. Probably smartest do create an Order interface which this would be an array of
+ paymentMethods: any[]; // TODO: figure out proper array type of paymentMethods. create paymentMethod interface and make this an array of it
+}
+
+export interface MovieCatalog {
+ title: string;
+ genre: string;
+ duration: number;
+ fsk: string;
+ description: string;
+ poster: string;
+ backdrop: string;
+}
diff --git a/src/scripts/main.ts b/src/scripts/main.ts
new file mode 100644
index 0000000..75e7af9
--- /dev/null
+++ b/src/scripts/main.ts
@@ -0,0 +1,851 @@
+import { currentUser, loginUser, openAccountDashboard, registerUser } from "./account.js";
+import { openBooking } from "./booking.js";
+import { renderCart, saveCart, updateCartBadge } from "./cart.js";
+import { renderCheckout } from "./checkout.js";
+import { movieCatalog } from "./bigConsts.js";
+
+// Shared app state for legacy script files (account.js, booking.js, cart.js, checkout.js)
+export const prices: Record = { normal: 11.0, imax: 15.0, vip: 12.0, dbox: 16.0 };
+export var seatLayouts = {
+ "Kino 1": { rows: 6, left: 3, right: 7, vipRows: [5], dbox: [] },
+ "Kino 2": { rows: 7, left: 5, right: 5, vipRows: [6], dbox: [] },
+ "Deluxe 1": { rows: 10, left: 7, right: 8, vipRows: [9], dbox: [{ r: 4, c: 5, w: 4 }] },
+ IMAX: { rows: 15, left: 10, right: 10, vipRows: [], dbox: [], isImax: true }
+};
+export var cart:any[] = JSON.parse(localStorage.getItem("eagleCart") || '[]');
+export var occupiedSeatsData = JSON.parse(localStorage.getItem("eagleOccupied") || '{}');
+
+document.addEventListener("DOMContentLoaded", () => {
+ const views = {
+ hero: document.querySelector(".hero"),
+ moviesGrid: document.getElementById("movies-grid-section"),
+ list: document.getElementById("movie-list-view"),
+ halls: document.getElementById("halls-view"),
+ dbox: document.getElementById("dbox-view"),
+ collectors: document.getElementById("collectors-view"),
+ about: document.getElementById("about-view"),
+ snacks: document.getElementById("snacks-view"),
+ cart: document.getElementById("cart-view"),
+ checkout: document.getElementById("checkout-view"),
+ account: document.getElementById("account-view")
+ };
+
+ const ui = {
+ logo: document.getElementById("logo-home"),
+ linkFilme: document.getElementById("link-filme"),
+ linkSnacks: document.getElementById("link-snacks"),
+ linkAbout: document.getElementById("link-about"),
+ linkCart: document.getElementById("link-cart"),
+ linkAccount: document.getElementById("link-account"),
+ themeToggle: document.getElementById("theme-toggle"),
+ heroBookingBtn: document.getElementById("hero-booking-btn"),
+ heroSlider: document.getElementById("hero-slider"),
+ heroDots: document.getElementById("hero-dots"),
+ heroTitle: document.getElementById("hero-title"),
+ heroText: document.getElementById("hero-text"),
+ nowRunningRow: document.getElementById("now-running-row"),
+ movieProgramList: document.getElementById("movie-program-list"),
+ checkoutBtn: document.getElementById("btn-checkout-final"),
+ backHomeBtn: document.getElementById("btn-back-home"),
+ snacksView: document.getElementById("snacks-view"),
+ snackOverlay: document.getElementById("snack-prompt-overlay"),
+ btnYesSnacks: document.getElementById("btn-yes-snacks"),
+ btnNoCart: document.getElementById("btn-no-cart"),
+ bookingModal: document.getElementById("booking-modal"),
+ closeBookingModalBtn: document.querySelector(".close-btn")
+ };
+
+ const checkoutSteps = {
+ one: document.getElementById("checkout-step-1"),
+ two: document.getElementById("checkout-step-2"),
+ three: document.getElementById("checkout-step-3")
+ };
+
+ const hallRotation = ["IMAX", "Deluxe 1", "Kino 1", "Kino 2"];
+ const timePatterns = [
+ ["13:00", "15:20", "17:40", "20:00", "22:20"],
+ ["13:00", "14:50", "17:10", "19:30", "21:50"],
+ ["13:00", "15:10", "17:30", "19:50", "22:10"],
+ ["13:00", "16:00", "18:20", "20:40"]
+ ];
+
+ let movieProgram: any = []; // TODO: Find type
+ let heroItems: any = []; // TODO: find Type
+ let heroIndex = 0;
+ let heroTimer:any = null; // TODO: find type
+
+ const weekdayShort = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
+
+ const hideAllViews = () => {
+ Object.values(views).forEach((view) => view?.classList.add("hidden"));
+ document.getElementById("about-tech-modal")?.classList.add("hidden");
+ document.body.style.overflow = "auto";
+ };
+
+ const showHome = () => {
+ hideAllViews();
+ views.hero?.classList.remove("hidden");
+ views.moviesGrid?.classList.remove("hidden");
+ document.getElementById("about-tech-modal")?.classList.add("hidden");
+ document.body.style.overflow = "auto";
+ window.scrollTo({ top: 0, behavior: "smooth" });
+ };
+
+ const showMovieList = (programIndexToFocus:number = NaN) => {
+ hideAllViews();
+ views.list?.classList.remove("hidden");
+
+ if (programIndexToFocus === null) {
+ window.scrollTo({ top: 0, behavior: "smooth" });
+ return;
+ }
+
+ const target = views.list?.querySelector(`[data-program-index="${programIndexToFocus}"]`);
+ if (target) {
+ target.scrollIntoView({ behavior: "smooth", block: "start" });
+ target.classList.add("flash-focus");
+ setTimeout(() => target.classList.remove("flash-focus"), 1200);
+ }
+ };
+
+ const showStaticView = (viewElement: HTMLElement) => {
+ if (!viewElement) {
+ return;
+ }
+
+ hideAllViews();
+ viewElement.classList.remove("hidden");
+ window.scrollTo({ top: 0, behavior: "smooth" });
+ };
+
+ const showCheckoutStart = () => {
+ if (!cart.length) {
+ alert("Dein Warenkorb ist leer.");
+ return;
+ }
+
+ hideAllViews();
+ views.checkout?.classList.remove("hidden");
+ checkoutSteps.one?.classList.remove("hidden");
+ checkoutSteps.two?.classList.add("hidden");
+ checkoutSteps.three?.classList.add("hidden");
+ renderCheckout?.();
+ window.scrollTo(0, 0);
+ };
+
+ const closeBookingModal = () => {
+ ui.bookingModal?.classList.add("hidden");
+ };
+
+ const escapeHtml = (value: string) => String(value || "")
+ .replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ .replaceAll('"', """)
+ .replaceAll("'", "'");
+
+ const formatDateShort = (dateObj: any) => {
+ const day = String(dateObj.getDate()).padStart(2, "0");
+ const month = String(dateObj.getMonth() + 1).padStart(2, "0");
+ return `${day}.${month}.`;
+ };
+
+ const buildDayMeta = (offset: number) => {
+ const date = new Date();
+ date.setHours(0, 0, 0, 0);
+ date.setDate(date.getDate() + offset);
+
+ const weekday = weekdayShort[date.getDay()];
+ const formattedDate = formatDateShort(date);
+
+ if (offset === 0) {
+ return {
+ offset,
+ date,
+ short: "Heute",
+ long: `Heute, ${formattedDate}`
+ };
+ }
+
+ if (offset === 1) {
+ return {
+ offset,
+ date,
+ short: "Morgen",
+ long: `Morgen, ${formattedDate}`
+ };
+ }
+
+ return {
+ offset,
+ date,
+ short: weekday,
+ long: `${weekday}, ${formattedDate}`
+ };
+ };
+
+ const buildScheduleForMovie = (movieIndex: number) => {
+ return Array.from({ length: 7 }, (_, dayOffset) => {
+ const dayMeta = buildDayMeta(dayOffset);
+ const pattern = timePatterns[(movieIndex + dayOffset) % timePatterns.length] || "Error reading";
+ const desiredCount = 4 + ((movieIndex + dayOffset) % 2);
+ const showCount = Math.min(pattern.length, desiredCount);
+
+ //@ts-ignore
+ const showings = pattern.slice(0, showCount).map((time: any, slotIndex: number) => { // TODO: fix map issue
+ const hall = hallRotation[(movieIndex + dayOffset + slotIndex) % hallRotation.length];
+ return { time, hall };
+ });
+
+ return {
+ ...dayMeta,
+ showings
+ };
+ });
+ };
+
+ const buildMovieProgram = () => {
+ //@ts-ignore
+ movieProgram = movieCatalog.map((movie: any, movieIndex: number) => ({
+ ...movie,
+ schedule: buildScheduleForMovie(movieIndex)
+ }));
+ heroItems = movieProgram.slice(0, 5);
+ };
+
+ const setHeroSlide = (index: number) => {
+ if (!heroItems.length || !ui.heroSlider) {
+ return;
+ }
+
+ heroIndex = (index + heroItems.length) % heroItems.length;
+
+ ui.heroSlider.querySelectorAll(".hero-slide").forEach((slide, slideIndex) => {
+ slide.classList.toggle("active", slideIndex === heroIndex);
+ });
+
+ ui.heroDots?.querySelectorAll(".hero-dot").forEach((dot, dotIndex) => {
+ dot.classList.toggle("active", dotIndex === heroIndex);
+ });
+
+ const activeMovie = heroItems[heroIndex];
+ if (ui.heroTitle) {
+ ui.heroTitle.textContent = activeMovie.title;
+ }
+ if (ui.heroText) {
+ ui.heroText.textContent = `${activeMovie.genre} • ${activeMovie.duration} Min. • Heute erste Vorstellung um 13:00 Uhr.`;
+ }
+ };
+
+ const renderHero = () => {
+ if (!ui.heroSlider || !heroItems.length) {
+ return;
+ }
+
+ ui.heroSlider.innerHTML = heroItems.map((movie: any, index: number) => `
+
+ `).join("");
+
+ if (ui.heroDots) {
+ ui.heroDots.innerHTML = heroItems.map((_:any, index: number) => `
+
+ `).join("");
+
+ ui.heroDots.addEventListener("click", (event: any) => {
+ const dotTarget = event.target || 0;
+ const dot = dotTarget.closest(".hero-dot");
+ if (!dot) {
+ return;
+ }
+
+ const nextIndex = Number(dot.dataset.heroIndex || 0);
+ setHeroSlide(nextIndex);
+
+ if (heroTimer) {
+ clearInterval(heroTimer);
+ heroTimer = setInterval(() => setHeroSlide(heroIndex + 1), 6500);
+ }
+ });
+ }
+
+ setHeroSlide(0);
+
+ if (heroTimer) {
+ clearInterval(heroTimer);
+ }
+
+ heroTimer = setInterval(() => {
+ setHeroSlide(heroIndex + 1);
+ }, 6500);
+ };
+
+ const renderNowRunningRow = () => {
+ if (!ui.nowRunningRow) {
+ return;
+ }
+
+ // TODO: implement movie interface
+ ui.nowRunningRow.innerHTML = movieProgram.map((movie: any, index: number) => /*html*/`
+
+
+
+
+ `).join("");
+ };
+
+ const renderScheduleRows = (programIndex: number, dayIndex: number) => {
+ const movie = movieProgram[programIndex];
+ if (!movie) {
+ return;
+ }
+
+ const day = movie.schedule[dayIndex];
+ const body = document.getElementById(`schedule-body-${programIndex}`);
+ if (!body || !day) {
+ return;
+ }
+
+ body.innerHTML = day.showings.map((showing: { hall: string; time: string; }) => /*html*/`
+
+ ${escapeHtml(day.long)}
+ ${escapeHtml(showing.hall)}
+ ${escapeHtml(showing.time)}
+
+ `).join("");
+ };
+
+ const renderMovieProgramList = () => {
+ if (!ui.movieProgramList) {
+ return;
+ }
+
+ ui.movieProgramList.innerHTML = movieProgram.map((movie: { schedule: any[]; poster: string; title: string; fsk: string; duration: any; genre: string; description: string; }, programIndex: any) => {
+ const dayTabs = movie.schedule.map((day, dayIndex) => /*html*/`
+
+ ${escapeHtml(day.short)}
+ ${escapeHtml(formatDateShort(day.date))}
+
+ `).join("");
+
+ return /*html*/`
+
+
+
+
${escapeHtml(movie.fsk)}
+
+
+
+
${escapeHtml(movie.description)}
+
+
${dayTabs}
+
+
+
+
+ `;
+ }).join("");
+
+ movieProgram.forEach((_: any, programIndex: number) => {
+ renderScheduleRows(programIndex, 0);
+ });
+ };
+
+ const initRevealAnimations = () => {
+ const revealElements = Array.from(document.querySelectorAll(".reveal-on-scroll"));
+ if (!revealElements.length) {
+ return;
+ }
+
+ if (!("IntersectionObserver" in window)) {
+ revealElements.forEach((element) => element.classList.add("is-visible"));
+ return;
+ }
+
+ const observer = new IntersectionObserver((entries, obs) => {
+ entries.forEach((entry) => {
+ if (!entry.isIntersecting) {
+ return;
+ }
+
+ entry.target.classList.add("is-visible");
+ obs.unobserve(entry.target);
+ });
+ }, { threshold: 0.2 });
+
+ revealElements.forEach((element) => observer.observe(element));
+ };
+
+ const renderMovieExperience = () => {
+ buildMovieProgram();
+ renderHero();
+ renderNowRunningRow();
+ renderMovieProgramList();
+ initRevealAnimations();
+ };
+
+ const bindNavigation = () => {
+ ui.logo?.addEventListener("click", showHome);
+
+ ui.linkFilme?.addEventListener("click", (event) => {
+ event.preventDefault();
+ showMovieList();
+ });
+
+ ui.linkSnacks?.addEventListener("click", (event) => {
+ event.preventDefault();
+ if (views.snacks) {
+ showStaticView(views.snacks);
+ }
+ });
+
+ ui.linkAbout?.addEventListener("click", (event) => {
+ event.preventDefault();
+ if (views.about) {
+ showStaticView(views.about);
+ }
+ });
+
+ ui.linkCart?.addEventListener("click", (event) => {
+ event.preventDefault();
+ hideAllViews();
+ views.cart?.classList.remove("hidden");
+ renderCart?.();
+ });
+
+ ui.linkAccount?.addEventListener("click", (event) => {
+ event.preventDefault();
+ hideAllViews();
+ views.account?.classList.remove("hidden");
+
+ const isUserLoggedIn = typeof currentUser !== "undefined" && currentUser;
+ if (isUserLoggedIn && typeof openAccountDashboard === "function") {
+ openAccountDashboard();
+ }
+ });
+
+ ui.heroBookingBtn?.addEventListener("click", () => {
+ showMovieList();
+ });
+
+ ui.checkoutBtn?.addEventListener("click", showCheckoutStart);
+ ui.backHomeBtn?.addEventListener("click", showHome);
+ };
+
+ const bindProgramActions = () => {
+ views.moviesGrid?.addEventListener("click", (event:any) => {
+ const trigger = event.target.closest(".open-program-btn");
+ if (!trigger) {
+ return;
+ }
+
+ const programIndex = Number(trigger.dataset.programIndex) || 0;
+ showMovieList(programIndex);
+ });
+
+ ui.movieProgramList?.addEventListener("click", (event:any) => {
+ const dayButton = event.target.closest(".program-day-tab");
+ if (!dayButton) {
+ return;
+ }
+
+ const programIndex = Number(dayButton.dataset.programIndex || 0);
+ const dayIndex = Number(dayButton.dataset.dayIndex || 0);
+
+ const tabRow = dayButton.closest(".program-day-tabs");
+ tabRow?.querySelectorAll(".program-day-tab").forEach((tab: { classList: { remove: (arg0: string) => any; }; }) => tab.classList.remove("active"));
+ dayButton.classList.add("active");
+
+ renderScheduleRows(programIndex, dayIndex);
+ });
+ };
+
+ const bindHomeInfoNavigation = () => {
+ const openButtons = Array.from(document.querySelectorAll("[data-home-view-open]"));
+ const backButtons = Array.from(document.querySelectorAll("[data-go-home]"));
+ const aboutOpenButtons = Array.from(document.querySelectorAll("[data-about-modal-open]"));
+ const aboutCloseButtons = Array.from(document.querySelectorAll("[data-about-modal-close]"));
+ const aboutModal = document.getElementById("about-tech-modal");
+
+ if (!openButtons.length) {
+ return;
+ }
+
+ const targetMap = {
+ "halls-view": views.halls,
+ "dbox-view": views.dbox,
+ "collectors-view": views.collectors
+ };
+
+ openButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ const targetId = button.getAttribute("data-home-view-open") as keyof typeof targetMap;
+ const target = targetId ? targetMap[targetId] : null;
+ if (target) {
+ showStaticView(target);
+ }
+ });
+ });
+
+ backButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ showHome();
+ });
+ });
+
+ aboutOpenButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ const targetId = button.getAttribute("data-about-modal-open");
+ if (targetId === "about-tech-modal" && aboutModal) {
+ aboutModal.classList.remove("hidden");
+ document.body.style.overflow = "hidden";
+ }
+ });
+ });
+
+ aboutCloseButtons.forEach((button) => {
+ button.addEventListener("click", () => {
+ aboutModal?.classList.add("hidden");
+ document.body.style.overflow = "auto";
+ });
+ });
+
+ aboutModal?.addEventListener("click", (event) => {
+ if (event.target === aboutModal) {
+ aboutModal.classList.add("hidden");
+ document.body.style.overflow = "auto";
+ }
+ });
+
+ document.addEventListener("keydown", (event) => {
+ if (event.key === "Escape" && aboutModal && !aboutModal.classList.contains("hidden")) {
+ aboutModal.classList.add("hidden");
+ document.body.style.overflow = "auto";
+ }
+ });
+ };
+
+ const initThemeToggle = () => {
+ if (!ui.themeToggle) {
+ return;
+ }
+
+ const THEME_KEY = "eagleTheme";
+
+ const applyTheme = (theme: any) => {
+ const isLight = theme === "light";
+ document.body.classList.toggle("theme-light", isLight);
+ document.body.classList.toggle("theme-dark", !isLight);
+ //@ts-ignore
+ ui.themeToggle.classList.toggle("is-light", isLight);
+ localStorage.setItem(THEME_KEY, isLight ? "light" : "dark");
+ };
+
+ const storedTheme = localStorage.getItem(THEME_KEY);
+ applyTheme(storedTheme === "light" ? "light" : "dark");
+
+ ui.themeToggle.addEventListener("click", () => {
+ const nextTheme = document.body.classList.contains("theme-light") ? "dark" : "light";
+ applyTheme(nextTheme);
+ });
+ };
+
+ const bindAccountActions = () => {
+ const registerModal = document.getElementById("register-modal");
+ const forgotModal = document.getElementById("forgot-modal");
+ const forgotEmailInput = document.getElementById("forgot-email") as HTMLInputElement;
+ const resetMessage = document.getElementById("reset-message");
+ const loginError = document.getElementById("login-error");
+ const loginEmailInput = document.getElementById("login-email");
+ const loginPasswordInput = document.getElementById("login-password");
+
+ const openModal = (modal: HTMLElement | null) => modal?.classList.remove("hidden");
+ const closeModal = (modal: HTMLElement | null) => modal?.classList.add("hidden");
+ const triggerLogin = () => {
+ loginError?.classList.add("hidden");
+ if (typeof loginUser === "function") {
+ loginUser();
+ }
+ };
+
+ document.getElementById("btn-open-register")?.addEventListener("click", () => {
+ openModal(registerModal);
+ });
+
+ document.getElementById("btn-close-register")?.addEventListener("click", () => {
+ closeModal(registerModal);
+ });
+
+ document.getElementById("btn-register-save")?.addEventListener("click", () => {
+ if (typeof registerUser === "function") {
+ registerUser();
+ }
+ });
+
+ document.getElementById("btn-login-account")?.addEventListener("click", triggerLogin);
+
+ [loginEmailInput, loginPasswordInput].forEach((input) => {
+ input?.addEventListener("keydown", (event) => {
+ if (event.key !== "Enter") {
+ return;
+ }
+
+ event.preventDefault();
+ triggerLogin();
+ });
+ });
+
+ document.getElementById("btn-forgot-password")?.addEventListener("click", () => {
+ if (forgotEmailInput != null) {
+ forgotEmailInput.value = "";
+ }
+ resetMessage?.classList.add("hidden");
+ openModal(forgotModal);
+ });
+
+ document.getElementById("btn-close-forgot")?.addEventListener("click", () => {
+ closeModal(forgotModal);
+ });
+
+ document.getElementById("btn-send-reset")?.addEventListener("click", () => {
+ const email = forgotEmailInput?.value.trim() || "";
+ if (!email || !email.includes("@")) {
+ alert("Bitte gib eine gueltige E-Mail-Adresse ein.");
+ return;
+ }
+
+ if (resetMessage) {
+ resetMessage.textContent = "Wenn ein Konto existiert, wurde ein Reset-Code simuliert versendet.";
+ resetMessage.classList.remove("hidden");
+ }
+ });
+
+ registerModal?.addEventListener("click", (event) => {
+ if (event.target === registerModal) {
+ closeModal(registerModal);
+ }
+ });
+
+ forgotModal?.addEventListener("click", (event) => {
+ if (event.target === forgotModal) {
+ closeModal(forgotModal);
+ }
+ });
+
+ document.addEventListener("keydown", (event) => {
+ if (event.key === "Escape") {
+ closeModal(registerModal);
+ closeModal(forgotModal);
+ }
+ });
+ };
+
+ const bindGlobalDocumentClicks = () => {
+ document.addEventListener("click", (event: any) => {
+ if (event.target.classList.contains("opt-btn")) {
+ const optionGroup = event.target.parentElement;
+ optionGroup?.querySelectorAll(".opt-btn").forEach((button: { classList: { remove: (arg0: string) => any; }; }) => button.classList.remove("active"));
+ event.target.classList.add("active");
+ }
+
+ const deleteBtn = event.target.closest(".btn-delete-item");
+ if (deleteBtn?.dataset.key) {
+ const row = deleteBtn.closest(".cart-item-row");
+ if (row) {
+ row.classList.add("slide-out-left");
+ row.querySelectorAll("button").forEach((button: { disabled: boolean; }) => {
+ button.disabled = true;
+ });
+
+ setTimeout(() => {
+ //@ts-ignore
+ removeFromCartByKey(deleteBtn.dataset.key); //TODO: removeFromCartByKey doesnt exist
+ }, 380);
+ } else {
+ //@ts-ignore
+ removeFromCartByKey(deleteBtn.dataset.key); //TODO: removeFromCartByKey doesnt exist
+ }
+ return;
+ }
+
+ const chip = event.target.closest(".time-chip");
+ if (chip) {
+ const movieFromData = chip.getAttribute("data-movie");
+ const movieCard = chip.closest(".movie-card, .detailed-card, .program-card");
+ const movie = movieFromData || movieCard?.querySelector("h2, h3")?.innerText || "Film";
+ const hall = chip.getAttribute("data-hall");
+ const time = chip.getAttribute("data-time");
+
+ if (hall && time && typeof openBooking === "function") {
+ openBooking(movie, hall, time);
+ }
+ }
+
+ const qtyBtn = event.target.closest(".btn-qty");
+ if (!qtyBtn) {
+ return;
+ }
+
+ const action = qtyBtn.dataset.action;
+ const key = qtyBtn.dataset.key;
+ if (!action || !key) {
+ return;
+ }
+
+ const relatedItem = cart.find((item: { category: string; seatId: any; hall: any; time: any; title: any; }) => {
+ const infoText = item.category === "movie"
+ ? `Sitz: ${item.seatId} (${item.hall})`
+ : item.time;
+ return `${item.title}-${item.hall}-${infoText}` === key;
+ });
+
+ if (!relatedItem || relatedItem.category === "movie") {
+ return;
+ }
+
+ if (action === "plus") {
+ cart.push({ ...relatedItem, id: Date.now() + Math.random() });
+ } else {
+ const keyList = cart.map((item: { category: string; seatId: any; hall: any; time: any; title: any; }) => {
+ const infoText = item.category === "movie"
+ ? `Sitz: ${item.seatId} (${item.hall})`
+ : item.time;
+ return `${item.title}-${item.hall}-${infoText}`;
+ });
+ const lastMatch = keyList.lastIndexOf(key);
+
+ if (lastMatch !== -1) {
+ cart.splice(lastMatch, 1);
+ }
+ }
+
+ saveCart?.();
+ renderCart?.();
+ });
+ };
+
+ const bindSnacksActions = () => {
+ ui.snacksView?.addEventListener("click", (event:any) => {
+ const sizeChip = event.target.closest(".size-chip");
+ if (!sizeChip) {
+ return;
+ }
+
+ const snackCard = sizeChip.closest(".snack-card");
+ if (!snackCard) {
+ return;
+ }
+
+ const snackTitle = snackCard.querySelector("h3, h2")?.innerText || "Snack";
+ const snackImg = snackCard.querySelector("img")?.src || "";
+ const priceSpan = sizeChip.querySelector("span");
+ const rawPriceText = (priceSpan ? priceSpan.innerText : sizeChip.innerText)
+ .replace("EUR", "")
+ .replace("€", "")
+ .replace(",", ".")
+ .trim();
+ const priceVal = parseFloat(rawPriceText) || 0;
+ const sizeVal = sizeChip.innerText.replace(priceSpan?.innerText || "", "").trim() || "Standard";
+ const activeOption = snackCard.querySelector(".opt-btn.active");
+ const variantVal = activeOption ? activeOption.innerText : "Normal";
+
+ cart.push({
+ id: Date.now() + Math.random(),
+ category: "snack",
+ title: snackTitle,
+ hall: sizeVal,
+ time: variantVal,
+ type: "SNACK",
+ price: priceVal,
+ img: snackImg
+ });
+
+ saveCart?.();
+
+ const originalHtml = sizeChip.innerHTML;
+ sizeChip.innerHTML = "Hinzugefügt!";
+ setTimeout(() => {
+ sizeChip.innerHTML = originalHtml;
+ }, 800);
+ });
+
+ document.querySelectorAll(".tab-btn").forEach((button: any) => {
+ button.addEventListener("click", () => {
+ document.querySelectorAll(".tab-btn").forEach((tab) => tab.classList.remove("active"));
+ button.classList.add("active");
+
+ document.querySelectorAll(".snack-category").forEach((category) => category.classList.add("hidden"));
+ document.getElementById(button.dataset.target)?.classList.remove("hidden");
+ });
+ });
+ };
+
+ const bindOverlayActions = () => {
+ ui.btnYesSnacks?.addEventListener("click", () => {
+ ui.snackOverlay?.classList.add("hidden");
+ hideAllViews();
+ views.snacks?.classList.remove("hidden");
+ document.body.style.overflow = "auto";
+ });
+
+ ui.btnNoCart?.addEventListener("click", () => {
+ ui.snackOverlay?.classList.add("hidden");
+ hideAllViews();
+ views.cart?.classList.remove("hidden");
+ renderCart?.();
+ document.body.style.overflow = "auto";
+ });
+ };
+
+ const bindBookingModalClose = () => {
+ ui.closeBookingModalBtn?.addEventListener("click", closeBookingModal);
+
+ ui.bookingModal?.addEventListener("click", (event) => {
+ if (event.target === ui.bookingModal) {
+ closeBookingModal();
+ }
+ });
+ };
+ // @ts-ignore
+ window.removeFromCartByKey = function removeFromCartByKey(key: string) {
+ cart = cart.filter((item: { category: string; seatId: any; hall: any; time: any; title: any; }) => {
+ const infoText = item.category === "movie"
+ ? `Sitz: ${item.seatId} (${item.hall})`
+ : item.time;
+ return `${item.title}-${item.hall}-${infoText}` !== key;
+ });
+
+ saveCart?.();
+ renderCart?.();
+ };
+
+ renderMovieExperience();
+ initThemeToggle();
+ bindNavigation();
+ bindProgramActions();
+ bindHomeInfoNavigation();
+ bindAccountActions();
+ bindGlobalDocumentClicks();
+ bindSnacksActions();
+ bindOverlayActions();
+ bindBookingModalClose();
+
+ updateCartBadge?.();
+ renderCheckout?.();
+});
+
+export function emptyCart() {
+ cart = []
+ return
+}
\ No newline at end of file
diff --git a/src/styles/global.css b/src/styles/global.css
new file mode 100644
index 0000000..296146d
--- /dev/null
+++ b/src/styles/global.css
@@ -0,0 +1,3867 @@
+:root {
+ --bg-black: #000000;
+ --card-bg: #1c1c1e;
+ --text-white: #f5f5f7;
+ --accent-blue: #0071e3;
+ --glass: rgba(29, 29, 31, 0.75);
+}
+
+/* Global Reset */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ font-family: 'Segoe UI', sans-serif;
+}
+
+body {
+ background: var(--bg-black);
+ color: var(--text-white);
+ overflow-x: hidden;
+}
+
+.hidden { display: none !important; }
+
+/* --- Navigation --- */
+.navbar {
+ position: fixed;
+ top: 0;
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1.2rem 10%;
+ background: var(--glass);
+ backdrop-filter: blur(20px);
+ z-index: 1000;
+}
+
+.nav-links {
+ display: flex;
+ list-style: none;
+ gap: 2rem;
+}
+
+.nav-links a {
+ color: white;
+ text-decoration: none;
+ opacity: 0.8;
+ font-size: 0.9rem;
+}
+
+/* --- Hero Section --- */
+.hero {
+ height: 100vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ background: linear-gradient(rgba(0,0,0,0.4), #000), url('https://images.unsplash.com/photo-1485846234645-a62644f84728?q=80&w=2000') center/cover;
+}
+
+.badge {
+ background: var(--accent-blue);
+ padding: 4px 12px;
+ border-radius: 20px;
+ font-size: 0.7rem;
+ font-weight: bold;
+}
+
+.hero h1 {
+ font-size: 4.5rem;
+ margin: 10px 0;
+}
+
+/* --- Movie Grid & Sections --- */
+.movie-section { padding: 80px 10%; }
+
+.movie-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
+ gap: 30px;
+}
+
+.movie-card {
+ background: var(--card-bg);
+ border-radius: 20px;
+ overflow: hidden;
+}
+
+.movie-poster img {
+ width: 100%;
+ aspect-ratio: 2/3;
+ object-fit: cover;
+}
+
+.movie-info { padding: 20px; }
+
+.showtimes {
+ display: flex;
+ gap: 10px;
+ margin-top: 15px;
+}
+
+/* --- UI Elements (Chips & Buttons) --- */
+.time-chip {
+ background: rgba(255,255,255,0.1);
+ border: none;
+ color: white;
+ padding: 8px 15px;
+ border-radius: 10px;
+ cursor: pointer;
+ transition: 0.3s;
+}
+
+.time-chip:hover { background: var(--accent-blue); }
+
+.btn-primary {
+ background: var(--accent-blue);
+ color: white;
+ border: none;
+ padding: 12px 25px;
+ border-radius: 20px;
+ cursor: pointer;
+}
+
+/* --- Detailed List View --- */
+.detailed-card {
+ display: flex;
+ background: var(--card-bg);
+ border-radius: 24px;
+ margin-bottom: 30px;
+ overflow: hidden;
+}
+
+.card-left {
+ width: 250px;
+ position: relative;
+}
+
+.card-left img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.card-right {
+ flex: 1;
+ padding: 30px;
+}
+
+.fsk {
+ position: absolute;
+ bottom: 10px;
+ left: 10px;
+ width: 35px;
+ height: 35px;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: bold;
+}
+
+.fsk-0 { background: #d6d6d6; }
+.fsk-6 { background: #e3c500; }
+.fsk-12 { background: #008d39; }
+.fsk-16 { background: #0095ff; }
+.fsk-18 { background: #ff3730; }
+
+.schedule-container {
+ background: rgba(0,0,0,0.2);
+ padding: 15px;
+ border-radius: 15px;
+ margin-top: 20px;
+}
+
+.schedule-header {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ color: #86868b;
+ font-size: 0.7rem;
+ margin-bottom: 10px;
+}
+
+.schedule-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ align-items: center;
+ padding: 10px;
+ border-radius: 10px;
+}
+
+.time-btn {
+ background: var(--accent-blue);
+ padding: 5px 10px;
+ border-radius: 5px;
+ width: fit-content;
+}
+
+/* --- Booking Modal --- */
+.modal {
+ position: fixed;
+ top: 0; left: 0; width: 100%; height: 100%;
+ background: rgba(0,0,0,0.85);
+ backdrop-filter: blur(20px);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 2000;
+}
+
+.modal-content {
+ background: #1c1c1e;
+ padding: 40px;
+ border-radius: 32px;
+ width: 90%;
+ max-width: 1000px;
+ border: 1px solid rgba(255,255,255,0.1);
+ position: relative;
+}
+
+.close-btn {
+ position: absolute;
+ top: 20px;
+ right: 25px;
+ font-size: 2rem;
+ cursor: pointer;
+ color: #86868b;
+}
+
+.modal-close-btn {
+ position: absolute;
+ top: 16px;
+ right: 16px;
+ width: 36px;
+ height: 36px;
+ border: 0;
+ border-radius: 50%;
+ background: #2b2b2d;
+ color: #fff;
+ font-size: 1.4rem;
+ line-height: 1;
+ cursor: pointer;
+ transition: background 0.2s ease;
+}
+
+.modal-close-btn:hover {
+ background: #3a3a3d;
+}
+
+.screen {
+ height: 5px;
+ background: white;
+ width: 80%;
+ margin: 20px auto;
+ box-shadow: 0 0 15px white;
+}
+
+.screen-text {
+ text-align: center;
+ font-size: 0.7rem;
+ color: #86868b;
+ letter-spacing: 5px;
+}
+
+/* --- MODAL & SITZPLAN UPDATE --- */
+.modal-large {
+ max-width: 95vw !important; /* Fast die ganze Breite nutzen */
+ max-height: 90vh;
+ overflow-y: auto; /* Vertikales Scrollen erlauben */
+ width: 1000px !important;
+}
+
+#deluxe-logos {
+ display: flex;
+ gap: 10px;
+ justify-content: center;
+ margin-top: 15px;
+}
+
+.logo-placeholder {
+ background: rgba(255,255,255,0.1);
+ padding: 6px 12px;
+ border-radius: 8px;
+ font-size: 0.75rem;
+ color: #86868b;
+ border: 1px dashed rgba(255,255,255,0.3);
+}
+
+.seat-map-container {
+ width: 100%;
+ overflow-x: auto; /* Horizontales Scrollen für IMAX */
+ padding: 10px 0 20px 0;
+}
+
+.seat-grid-custom {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ align-items: center;
+ margin: 20px auto;
+ width: fit-content;
+}
+
+.seat-row {
+ display: flex;
+ gap: 8px;
+ justify-content: center;
+}
+
+.aisle {
+ width: 25px; /* Breite des Durchgangs */
+}
+
+/* Sitzplatz Design */
+/* --- SITZPLATZ DESIGN UPDATE --- */
+.seat {
+ width: 26px;
+ height: 26px;
+ background: #3a3a3c; /* Standard Grau */
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.2s ease-in-out;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ border: 1px solid rgba(255,255,255,0.1);
+}
+
+/* Hover-Effekt (Hervorhebung) */
+.seat:hover:not(.occupied) {
+ transform: scale(1.25);
+ z-index: 10;
+ border-color: rgba(255,255,255,0.5);
+}
+
+/* Farben der Typen */
+.seat.normal, .seat.imax { background: #3a3a3c; }
+.seat.vip { background: #ff9500; } /* Orange */
+.seat.dbox {
+ background: #ffca28; /* Gold */
+ box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
+}
+
+/* Ausgewählter Zustand (Grün + Glow) */
+.seat.selected {
+ background: #34c759 !important; /* iOS Grün */
+ box-shadow: 0 0 15px #34c759;
+ transform: scale(1.1);
+ border-color: white;
+}
+
+/* Belegter Zustand (Rot mit X) */
+.seat.occupied {
+ background: #ff3b30 !important; /* Rot */
+ cursor: not-allowed;
+ opacity: 1;
+ transform: none;
+}
+
+.seat.occupied::after {
+ content: '×';
+ color: white;
+ font-size: 18px;
+ font-weight: bold;
+ line-height: 1;
+}
+
+/* Legende Styling */
+.legend .seat { cursor: default; pointer-events: none; width: 20px; height: 20px; }
+.legend .item { display: flex; align-items: center; gap: 8px; font-size: 0.8rem; color: #86868b; }
+
+#dynamic-legend {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 15px;
+ margin-top: 20px;
+ padding: 15px;
+ background: rgba(255,255,255,0.05);
+ border-radius: 12px;
+}
+
+/* --- Snack Tabs Navigation --- */
+.category-tabs {
+ display: flex;
+ justify-content: center;
+ gap: 15px;
+ margin-bottom: 50px;
+}
+
+.tab-btn {
+ background: #1c1c1e;
+ border: 1px solid rgba(255,255,255,0.1);
+ color: white;
+ padding: 12px 25px;
+ border-radius: 30px;
+ cursor: pointer;
+ transition: 0.3s;
+}
+.tab-btn:hover { background: rgba(255,255,255,0.1); }
+.tab-btn.active { background: var(--accent-blue); border-color: var(--accent-blue); }
+
+.snack-category {
+ animation: fadeIn 0.4s ease-in-out;
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(10px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+/* --- Snack Grid & Cards --- */
+.snack-section { padding: 100px 10%; }
+.snack-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
+ gap: 25px;
+}
+
+.snack-card {
+ background: var(--card-bg);
+ border-radius: 20px;
+ overflow: hidden;
+ transition: 0.3s;
+ border: 1px solid rgba(255,255,255,0.05);
+}
+
+.snack-card:hover {
+ transform: translateY(-8px); border-color: var(--accent-blue);
+}
+
+.snack-card.highlight {
+ border: 1px solid var(--accent-blue);
+ background: linear-gradient(145deg, #1c1c1e, #0a2540);
+}
+
+.snack-img {
+ width: 100%;
+ height: 150px;
+ background: #111;
+}
+
+.snack-img img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain; /* Ideal für Produktfotos auf dunklem Grund */
+ padding: 10px;
+}
+
+/* --- SNACK INFO ZENTRIERUNG --- */
+
+.snack-info {
+ padding: 20px;
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.snack-info h3 {
+ font-size: 1rem;
+ margin-bottom: 15px;
+ width: 100%;
+}
+
+.size-selector {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: center;
+}
+
+.size-chip {
+ background: rgba(255,255,255,0.05);
+ border: 1px solid rgba(255,255,255,0.1);
+ color: white;
+ padding: 6px 12px;
+ border-radius: 8px;
+ font-size: 0.75rem;
+ cursor: pointer;
+ transition: 0.2s;
+}
+
+.size-chip span {
+ display: block;
+ color: var(--accent-blue);
+ font-weight: bold;
+}
+
+.size-chip:hover {
+ background: var(--accent-blue);
+ border-color: var(--accent-blue);
+}
+
+.size-chip:hover span {
+ color: white;
+}
+
+.size-chip.special {
+ background: rgba(229, 160, 13, 0.1);
+ border: 1px solid #e5a00d;
+}
+
+.size-chip.special span {
+ color: #e5a00d;
+}
+
+/* Snack Options (Sweet/Salty & Dips) */
+.option-group {
+ display: flex;
+ gap: 5px;
+ margin-bottom: 15px;
+ background: rgba(0, 0, 0, 0.3);
+ padding: 4px;
+ border-radius: 10px;
+}
+
+.opt-btn {
+ flex: 1;
+ background: transparent;
+ border: none;
+ color: #86868b;
+ padding: 6px;
+ font-size: 0.75rem;
+ font-weight: bold;
+ cursor: pointer;
+ border-radius: 7px;
+ transition: 0.2s;
+}
+
+.opt-btn.active {
+ background: #3a3a3c;
+ color: white;
+}
+
+/* --- Coming Soon Banner --- */
+.coming-soon-banner {
+ background: linear-gradient(45deg, #1c1c1e, #2a2a2d);
+ border: 2px dashed rgba(255,255,255,0.2);
+ border-radius: 20px;
+ padding: 80px 20px;
+ text-align: center;
+ color: var(--text-white);
+}
+
+.coming-soon-banner h2 {
+ font-size: 2.5rem;
+ margin-bottom: 10px;
+ color: var(--accent-blue);
+}
+
+.coming-soon-banner p {
+ font-size: 1.5rem;
+ font-weight: bold;
+ margin-bottom: 10px;
+}
+
+.coming-soon-banner span { color: #86868b; }
+
+/* Layout breiter machen */
+.booking-layout {
+ display: flex;
+ gap: 40px; /* Mehr Abstand zwischen Plan und Preis */
+ align-items: flex-start;
+ justify-content: center;
+ max-width: 1200px; /* Erlaubt dem Fenster mehr Platz */
+ margin: 0 auto;
+ transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1);
+}
+
+/* Das rechte Panel optimiert */
+.summary-panel {
+ width: 300px; /* Etwas breiter für bessere Lesbarkeit */
+ background: rgba(255, 255, 255, 0.03);
+ backdrop-filter: blur(10px);
+ border-radius: 24px;
+ padding: 25px;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+
+ /* Langsamere, sanftere Animation */
+ animation: slideInSoft 0.8s cubic-bezier(0.25, 1, 0.5, 1) forwards;
+}
+
+@keyframes slideInSoft {
+ from {
+ opacity: 0;
+ transform: translateX(40px) scale(0.98);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0) scale(1);
+ }
+}
+
+.summary-row {
+ display: flex;
+ justify-content: space-between;
+ font-size: 0.95rem;
+ margin-bottom: 12px;
+ color: #a1a1a6;
+ /* Die einzelnen Zeilen faden auch sanft ein */
+ animation: fadeInRow 0.5s ease forwards;
+}
+
+@keyframes fadeInRow {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+.summary-row .type { color: #f5f5f7; }
+.summary-row .price { font-weight: bold; color: var(--accent-blue); }
+
+.divider {
+ height: 1px;
+ background: rgba(255, 255, 255, 0.1);
+ margin: 15px 0;
+}
+
+.total-row {
+ display: flex;
+ justify-content: space-between;
+ font-weight: 600;
+ font-size: 1.2rem;
+ color: #ffffff;
+ letter-spacing: -0.02em;
+}
+
+/* Verstecken mit sanftem Übergang */
+.hidden { display: none !important; }
+
+.header-sub-info {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+ margin-top: 5px;
+}
+
+.tech-badges-container {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ /* Sanfter Übergang beim Einblenden */
+ animation: fadeIn 0.5s ease;
+}
+
+.tech-badge {
+ height: 14px; /* Schön klein und dezent */
+ width: auto;
+ opacity: 0.7; /* Leicht transparent für den edlen Look */
+ filter: brightness(0) invert(1); /* Macht schwarze Logos weiß, passend zum Dark Mode */
+}
+
+.tech-badges-container.hidden {
+ display: none;
+}
+
+.tech-badges-container {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ margin-left: 10px;
+}
+
+.tech-badge {
+ height: 18px; /* Oder die gewünschte Höhe */
+ width: auto;
+ opacity: 0.8;
+}
+
+/* --- Warenkorb Badge --- */
+.cart-badge {
+ background-color: #e50914; /* Kino-Rot */
+ color: white;
+ font-size: 0.75rem;
+ font-weight: bold;
+ border-radius: 50%;
+ padding: 2px 6px;
+ position: absolute;
+ top: -8px;
+ right: -15px;
+ transition: transform 0.3s ease;
+}
+.cart-badge.hidden { display: none; }
+.cart-badge.pop { transform: scale(1.3); } /* Für eine kleine Animation beim Hinzufügen */
+
+/* --- WARENKORB SPALTEN-LAYOUT & HINTERGRÜNDE --- */
+/* --- WARENKORB DESIGN (SPALTEN-LAYOUT) --- */
+.cart-container {
+ display: flex;
+ gap: 50px;
+ align-items: flex-start;
+ margin-top: 40px;
+}
+
+/* Linke Seite (Artikelliste) mit Panel-Hintergrund */
+.cart-left {
+ flex: 2;
+ background-color: #1c1c1e !important; /* !important stellt sicher, dass es grau bleibt */
+ padding: 35px;
+ border-radius: 28px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+/* Rechte Seite (Zusammenfassung) */
+.cart-right {
+ flex: 1;
+ min-width: 380px;
+}
+
+.cart-items {
+ flex: 2;
+ background: #1c1c1e;
+ border-radius: 12px;
+ padding: 20px;
+}
+.cart-summary-box {
+ flex: 1;
+ background: #1c1c1e;
+ border-radius: 12px;
+ padding: 25px;
+ position: sticky;
+ top: 100px;
+}
+.cart-total-row {
+ display: flex;
+ justify-content: space-between;
+ font-size: 1.3rem;
+ font-weight: bold;
+ margin-top: 15px;
+ padding-top: 15px;
+ border-top: 1px solid #333;
+}
+.payment-methods-panel {
+ background: #2c2c2e !important; /* Ein helleres Grau als die Boxen oben */
+ padding: 20px;
+ border-radius: 18px;
+ margin-top: 30px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+/* Die Logos selbst */
+.payment-methods-panel div {
+ display: flex;
+ justify-content: center;
+ gap: 15px;
+ opacity: 0.95; /* Fast volle Sichtbarkeit (vorher 0.6) */
+}
+
+.payment-methods-panel img {
+ height: 22px; /* Etwas größer für bessere Sichtbarkeit */
+ filter: drop-shadow(0 2px 4px rgba(0,0,0,0.5)); /* Kleiner Schatten für Tiefe */
+ transition: transform 0.2s;
+}
+
+.payment-methods-panel img:hover {
+ transform: scale(1.1); /* Kleiner Effekt beim Drüberfahren */
+}
+
+/* --- Snack Prompt Overlay --- */
+.snack-overlay {
+ position: fixed;
+ top: 0; left: 0; width: 100%; height: 100%;
+ background: rgba(0,0,0,0.8);
+ backdrop-filter: blur(5px);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 2000;
+ opacity: 1;
+ transition: opacity 0.4s ease;
+}
+.snack-overlay.hidden {
+ opacity: 0;
+ pointer-events: none;
+}
+.snack-prompt-box {
+ background: #1c1c1e;
+ padding: 40px;
+ border-radius: 16px;
+ text-align: center;
+ max-width: 500px;
+ transform: translateY(0);
+ transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+}
+.snack-overlay.hidden .snack-prompt-box {
+ transform: translateY(50px);
+}
+.snack-prompt-box h2 { margin-bottom: 15px; color: #fff; }
+.snack-prompt-box p { color: #aaa; margin-bottom: 25px; }
+.prompt-buttons { display: flex; gap: 15px; justify-content: center; }
+.btn-secondary {
+ background: transparent;
+ border: 1px solid #fff;
+ color: #fff;
+ padding: 12px 24px;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: 0.3s;
+}
+.btn-secondary:hover { background: rgba(255,255,255,0.1); }
+
+/* --- WARENKORB TABELLEN-LAYOUT --- */
+.cart-item-row,
+.cart-header {
+ display: grid;
+ grid-template-columns: 100px 80px 1.5fr 1fr 100px 50px;
+ align-items: center;
+ gap: 0; /* Wir nutzen kein gap, um volle Kontrolle über die Spalten zu haben */
+}
+
+.cart-header {
+ font-size: 0.75rem;
+ color: #86868b;
+ font-weight: bold;
+ letter-spacing: 1.2px;
+ border-bottom: 1px solid #333;
+ padding: 15px 0;
+ margin-bottom: 10px;
+}
+
+.cart-item-row {
+ padding: 20px 0;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+}
+
+/* 1. Spalte: Menge (Zentriert den Stepper/Text etwas) */
+.cart-item-row > div:nth-child(1),
+.cart-header > div:nth-child(1) {
+ padding-left: 5px;
+}
+
+/* 2. Spalte: Das Bild (Bekommt links Platz zum Stepper) */
+.cart-item-row > div:nth-child(2) {
+ padding-left: 15px; /* Abstand zwischen +/- Button und Bild */
+}
+
+/* 3. Spalte: ARTIKEL (Titel) - Hier schieben wir die Schrift nach rechts */
+.cart-header > div:nth-child(3),
+.cart-item-row > div:nth-child(3) {
+ padding-left: 30px; /* Dieser Wert sorgt für die Ordnung */
+}
+
+/* 4. Spalte: INFO - Auch hier schieben wir für die vertikale Linie nach rechts */
+.cart-header > div:nth-child(4),
+.cart-item-row > div:nth-child(4) {
+ padding-left: 30px;
+}
+
+/* 5. Spalte: PREIS (Rechtsbündig für Tabellen-Look) */
+.cart-header > div:nth-child(5),
+.cart-item-row > div:nth-child(5) {
+ text-align: right;
+ padding-right: 15px;
+}
+
+/* 6. Spalte: LÖSCHEN (Zentriert am Ende) */
+.cart-header > div:nth-child(6),
+.cart-item-row > div:nth-child(6) {
+ text-align: right;
+}
+
+/* Bild-Styling innerhalb der Spalte */
+.cart-item-row img {
+ width: 45px;
+ height: 60px;
+ object-fit: cover;
+ border-radius: 8px;
+ display: block;
+}
+/* Plus-Minus Buttons */
+.qty-stepper {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ background: rgba(0,0,0,0.3);
+ padding: 5px 10px;
+ border-radius: 20px;
+ width: fit-content;
+}
+
+.btn-qty {
+ background: none;
+ border: 1px solid var(--accent-blue);
+ color: var(--accent-blue);
+ width: 22px;
+ height: 22px;
+ border-radius: 50%;
+ cursor: pointer;
+ font-weight: bold;
+}
+.btn-delete-item {
+ transition: background 0.2s ease, transform 0.1s ease, opacity 0.2s ease;
+ cursor: pointer;
+}
+
+.btn-qty:hover,
+.btn-delete-item:hover {
+ background: #0071e3 !important; /* Das Apple-Blau */
+ border-radius: 6px; /* Schön abgerundet */
+ transform: scale(1.1); /* Minimal vergrößern */
+}
+/* Animationen */
+@keyframes popIn {
+ 0% { transform: scale(0.9); opacity: 0; }
+ 100% { transform: scale(1); opacity: 1; }
+}
+
+.animate-pop-in {
+ animation: popIn 0.4s cubic-bezier(0.17, 0.67, 0.83, 0.67);
+}
+
+.btn-delete-item {
+ background: none;
+ border: none;
+ font-size: 1.2rem;
+ cursor: pointer;
+ opacity: 0.5;
+ transition: 0.3s;
+}
+
+.btn-delete-item:hover {
+ opacity: 1; transform: scale(1.2);
+}
+
+/* Checkout Container */
+.checkout-container {
+ max-width: 600px;
+ margin: 0 auto;
+ padding: 30px;
+ background: #1a1a1a;
+ border-radius: 12px;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
+}
+
+/* Fortschrittsleiste */
+.progress-bar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 40px;
+}
+
+.progress-bar .step {
+ width: 35px;
+ height: 35px;
+ border-radius: 50%;
+ background: #333;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: bold;
+ color: #e5e5e7; /* Zahlen deutlich heller gemacht */
+ transition: 0.3s;
+}
+
+.progress-bar .step.active {
+ background: #4caf50 !important; /* Grün statt Rot/Blau */
+ color: white;
+ border-color: #4caf50 !important;
+}
+
+.progress-bar .line {
+ height: 4px;
+ width: 80px;
+ background: #333;
+ margin: 0 15px;
+ transition: all 0.5s ease;
+}
+
+.progress-bar .line.active {
+ background: #4caf50 !important;
+}
+/* Zahlungsarten */
+.payment-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 15px;
+}
+
+.payment-method {
+ background: #1c1c1e;
+ padding: 20px;
+ border-radius: 12px;
+ cursor: pointer;
+ border: 2px solid transparent;
+ display: flex;
+ flex-direction: row; /* Nebeneinander statt untereinander */
+ align-items: center; /* Vertikal zentriert */
+ justify-content: center;
+ gap: 15px;
+ transition: 0.3s;
+}
+
+.payment-method img {
+ height: 22px; /* Einheitliche Größe */
+ width: auto;
+ margin-top: 2px; /* Schiebt das Bild dezent nach unten für optische Symmetrie zum Text */
+}
+
+.payment-method:hover {
+ border-color: #888;
+}
+
+.payment-method.selected {
+ border-color: #e50914;
+ background: rgba(229, 9, 20, 0.1);
+ transform: scale(1.02);
+}
+
+/* Hover-Effekt für den Zurück-Pfeil */
+#btn-back-to-step1:hover {
+ opacity: 1;
+ transform: translateX(-3px);
+}
+
+.cart-header-row,
+.cart-item-row {
+ display: grid;
+ /* Spalten: Menge(100px) | Bild(100px) | Produkt(1.5fr) | Details(2fr) | Preis(100px) | Aktion(80px) */
+ grid-template-columns: 100px 100px 1.5fr 2fr 100px 80px;
+ gap: 15px;
+ align-items: center;
+ padding: 15px 20px;
+}
+
+.cart-header-row,
+.cart-item-row {
+ display: grid;
+ /* Menge | Bild | Produkt | Details | Preis | Aktion */
+ grid-template-columns: 110px 100px 1.3fr 1.7fr 100px 60px;
+ gap: 10px;
+ align-items: center;
+ padding: 15px 20px;
+}
+
+.col-amount { text-align: center; }
+.col-img { text-align: center; }
+
+/* Produkt & Details nach rechts schieben */
+.col-product {
+ text-align: left;
+ padding-left: 25px; /* Minimal mehr nach rechts */
+}
+
+.col-details {
+ text-align: left;
+ padding-left: 35px; /* Minimal mehr nach rechts */
+}
+
+/* Preis weiter links ausrichten */
+.col-price {
+ text-align: left;
+ padding-left: 10px;
+}
+
+.col-action { text-align: right; }
+
+/* Menge-Stepper im Warenkorb */
+.qty-stepper {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ background: #2c2c2e;
+ padding: 5px 10px;
+ border-radius: 8px;
+ width: fit-content;
+}
+
+.btn-qty {
+ cursor: pointer;
+ width: 28px;
+ height: 28px;
+ border: none;
+ background: #3a3a3c;
+ color: white;
+ border-radius: 6px;
+ font-weight: bold;
+ transition: 0.2s;
+}
+/* Klick-Zustand: Leicht eindrücken */
+.btn-qty:active,
+.btn-delete-item:active {
+ transform: scale(0.95);
+}
+
+/* Spezifisches Styling für den Mülleimer (damit der Hover-Hintergrund passt) */
+.btn-delete-item {
+ background: none;
+ border: none;
+ font-size: 1.2rem;
+ padding: 5px 8px; /* Etwas Platz für den blauen Hintergrund */
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.cart-img-small {
+ width: 60px;
+ height: 85px;
+ object-fit: cover;
+ border-radius: 6px;
+ box-shadow: 0 4px 10px rgba(0,0,0,0.3);
+}
+
+.cart-item-info {
+ color: #0071e3;
+ font-size: 0.9rem;
+ line-height: 1.4;
+}
+
+/* --- Luxury Dark Ticket --- */
+.luxury-ticket {
+ background: #111; /* Dunkel statt Weiß */
+ color: #f5f5f7;
+ display: flex;
+ max-width: 600px;
+ margin: 20px auto;
+ border-radius: 15px;
+ overflow: hidden;
+ border: 1px solid #333;
+ box-shadow: 0 20px 40px rgba(0,0,0,0.8);
+}
+
+.ticket-left {
+ width: 35%;
+}
+
+.ticket-poster {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.ticket-right {
+ width: 65%;
+ padding: 25px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.ticket-brand {
+ font-size: 0.7rem;
+ letter-spacing: 3px;
+ color: #0071e3;
+ margin-bottom: 10px;
+}
+
+.ticket-title {
+ font-size: 1.8rem;
+ margin-bottom: 20px;
+ border-bottom: 1px solid #333;
+ padding-bottom: 10px;
+}
+
+.ticket-details p {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 8px;
+ font-size: 0.9rem;
+}
+
+.ticket-details span {
+ color: #86868b;
+}
+
+.ticket-footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-end;
+ margin-top: 20px;
+}
+
+.ticket-qr {
+ width: 100px;
+ height: 100px;
+ border: 5px solid white; /* Weißer Rand für Scanbarkeit auf dunklem Grund */
+ border-radius: 5px;
+}
+
+.ticket-code {
+ font-family: 'Courier New', Courier, monospace;
+ color: #444;
+ font-size: 1.2rem;
+}
+
+/* Kinoticket */
+.kinoticket {
+ background: #fff;
+ color: #000;
+ padding: 20px;
+ border-radius: 15px;
+ max-width: 300px; /* Begrenzt die Breite des Tickets */
+ margin: 20px auto;
+ text-align: center;
+ box-shadow: 0 10px 30px rgba(0,0,0,0.5);
+}
+
+.kinoticket .poster {
+ width: 100%;
+ max-height: 180px; /* Macht das Bild deutlich kleiner */
+ object-fit: cover; /* Verhindert Verzerrung */
+ border-radius: 10px;
+ margin-bottom: 15px;
+}
+
+.kinoticket h3 {
+ margin: 10px 0 5px;
+ font-size: 1.2rem;
+}
+.kinoticket p { color: #ccc; margin-bottom: 5px; font-size: 0.9rem; }
+.kinoticket .seats { font-weight: bold; color: #e50914; margin-top: 10px; font-size: 1.1rem; }
+
+.kinoticket .qr-code {
+ background: white;
+ padding: 10px;
+ display: inline-block;
+ margin-top: 15px;
+ border: 1px solid #ddd;
+}
+
+.kinoticket .qr-code img {
+ width: 130px; /* Feste Größe für den QR-Code */
+ height: 130px;
+ display: block;
+}
+
+/* Fix für Screenshot 1: Modal-Info Zeile */
+#modal-info-text {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 15px;
+}
+
+/* --- Lösch-Animation nach Links --- */
+.cart-item-row.slide-out-left {
+ animation: slideOutLeft 0.4s ease forwards;
+ pointer-events: none; /* Verhindert Klicks während der Animation */
+}
+
+@keyframes slideOutLeft {
+ 0% {
+ transform: translateX(0);
+ opacity: 1;
+ }
+ 100% {
+ transform: translateX(-100%); /* Vollständig nach links raus */
+ opacity: 0;
+ /* Verhindert, dass die Lücke abrupt kollabiert */
+ height: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ border: none;
+ }
+}
+.summary-box-black {
+ background-color: #1c1c1e !important;
+ padding: 35px;
+ border-radius: 28px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ position: sticky;
+ top: 120px;
+}
+
+.summary-row-large {
+ display: flex;
+ justify-content: space-between;
+ font-size: 1.6rem;
+ font-weight: 600;
+ margin-top: 25px;
+}
+
+.blue-button {
+ width: 100%;
+ background: var(--accent-blue);
+ color: white;
+ border: none;
+ padding: 18px;
+ border-radius: 14px;
+ font-weight: bold;
+ font-size: 1.1rem;
+ margin-top: 30px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.blue-button:hover {
+ background: #0077ed;
+ transform: scale(1.02);
+}
+
+.summary-content {
+ width: 100%;
+ max-width: 350px;
+ text-align: right;
+}
+
+.total-row {
+ font-size: 1.5rem;
+ font-weight: bold;
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 5px;
+}
+
+.vat-row {
+ color: #86868b;
+ font-size: 0.9rem;
+ margin-bottom: 20px;
+}
+
+.checkout-main-btn {
+ width: 100%;
+ padding: 16px;
+ background: #e50914;
+ color: white;
+ border: none;
+ border-radius: 8px;
+ font-weight: bold;
+ font-size: 1.1rem;
+ cursor: pointer;
+ transition: transform 0.2s, background 0.2s;
+}
+
+.checkout-main-btn:hover {
+ background: #f40a16;
+ transform: translateY(-2px);
+}
+
+#modal-info-text {
+ display: block; /* Verhindert das Nebeneinanderquetschen */
+ margin-top: 5px;
+ color: #ccc;
+}
+
+.modal-header-container {
+ padding-bottom: 15px;
+ border-bottom: 1px solid #333;
+ margin-bottom: 20px;
+}
+
+#snacks-view, #movie-list-view, #cart-view {
+ padding-bottom: 100px; /* Platz unten lassen */
+ min-height: 100vh;
+ overflow-y: auto; /* Sicherstellen, dass gescrollt werden kann */
+}
+
+/* --- Account View (stabil & sichtbar) --- */
+#account-view {
+ padding: 130px 8% 60px;
+ min-height: 100vh;
+}
+
+.account-login-box,
+.account-panel {
+ width: min(820px, 100%);
+ margin: 0 auto;
+ background: #1c1c1e;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 24px;
+ padding: 28px;
+}
+
+.account-login-box {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+}
+
+.account-login-box h2,
+.account-panel h2 {
+ margin-bottom: 16px;
+}
+
+.account-login-box input {
+ width: 100%;
+ margin-bottom: 12px;
+ padding: 12px 14px;
+ background: #111214;
+ border: 1px solid #3a3a3a;
+ border-radius: 10px;
+ color: #fff;
+}
+
+.account-login-box button {
+ width: 100%;
+ margin-top: 10px;
+ padding: 12px 14px;
+ border: 0;
+ border-radius: 10px;
+ background: #0071e3;
+ color: #fff;
+ cursor: pointer;
+}
+
+#btn-forgot-password {
+ width: auto !important;
+ align-self: flex-start;
+ margin-top: 2px;
+ margin-bottom: 12px;
+ padding: 0;
+ background: transparent !important;
+ border: none !important;
+ color: #95bce9;
+ font-size: 0.82rem;
+ text-decoration: underline;
+}
+
+#btn-open-register {
+ width: auto !important;
+ align-self: flex-start;
+ margin-top: 6px;
+ padding: 8px 14px !important;
+ font-size: 0.82rem;
+ background: #2a2d31 !important;
+ border: 1px solid #4d4f54 !important;
+}
+
+#account-register-hint {
+ margin-top: 18px;
+ margin-bottom: 2px;
+ font-size: 0.82rem;
+ color: #9ca0a8;
+ align-self: flex-start;
+}
+
+/* --- Auth Modals (Register + Forgot) --- */
+.account-auth-modal {
+ width: min(460px, 92vw);
+ max-width: 460px;
+ padding: 30px 24px 22px;
+ border-radius: 22px;
+ background: linear-gradient(180deg, #1f2125 0%, #181a1e 100%);
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.45);
+}
+
+.account-auth-modal h2 {
+ font-size: 1.45rem;
+ margin-bottom: 8px;
+}
+
+.auth-modal-subtitle {
+ color: #9da3ad;
+ font-size: 0.9rem;
+ margin-bottom: 16px;
+ line-height: 1.4;
+}
+
+.account-auth-modal input {
+ width: 100%;
+ margin-bottom: 11px;
+ padding: 12px 13px;
+ border-radius: 10px;
+ border: 1px solid #3a3f46;
+ background: #111317;
+ color: #f5f5f7;
+ outline: none;
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
+}
+
+.account-auth-modal input:focus {
+ border-color: #0071e3;
+ box-shadow: 0 0 0 3px rgba(0, 113, 227, 0.18);
+}
+
+.auth-submit-btn {
+ width: 100%;
+ margin-top: 6px;
+ padding: 12px 14px;
+ border: 0;
+ border-radius: 11px;
+ background: #0071e3;
+ color: #fff;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background 0.2s ease, transform 0.15s ease;
+}
+
+.auth-submit-btn:hover {
+ background: #0a7cf0;
+ transform: translateY(-1px);
+}
+
+#reset-message {
+ margin-top: 12px;
+ padding: 10px 12px;
+ border-radius: 10px;
+ background: rgba(17, 101, 42, 0.22);
+ border: 1px solid rgba(74, 199, 123, 0.32);
+ color: #84e5aa;
+ font-size: 0.88rem;
+}
+
+.account-panel-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 16px;
+}
+
+.account-logout-btn {
+ border: 1px solid #4a4a4a;
+ background: transparent;
+ color: #fff;
+ border-radius: 10px;
+ padding: 8px 12px;
+ cursor: pointer;
+}
+
+.account-tabs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin: 20px 0 16px;
+}
+
+.account-tab-btn {
+ border: 1px solid #3f3f3f;
+ background: #151618;
+ color: #fff;
+ border-radius: 999px;
+ padding: 8px 14px;
+ cursor: pointer;
+}
+
+#account-tab-content {
+ margin-top: 8px;
+}
+
+.account-card,
+.order-box {
+ background: #111214;
+ border: 1px solid #2f2f2f;
+ border-radius: 12px;
+ padding: 14px 16px;
+ margin-bottom: 10px;
+}
+
+/* --- Cart Columns (final override) --- */
+#cart-items-list .cart-header-row,
+#cart-items-list .cart-item-row {
+ display: grid;
+ grid-template-columns: 120px 90px 1.2fr 1.5fr 130px 70px;
+ gap: 12px;
+ align-items: center;
+}
+
+#cart-items-list .cart-header-row {
+ padding: 12px 8px;
+ margin-bottom: 6px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.15);
+ color: #9ca0a8;
+ font-size: 0.74rem;
+ font-weight: 700;
+ letter-spacing: 1px;
+}
+
+#cart-items-list .cart-item-row {
+ padding: 16px 8px;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+}
+
+#cart-items-list .col-amount {
+ display: flex;
+ justify-content: center;
+}
+
+#cart-items-list .col-img {
+ display: flex;
+ justify-content: center;
+}
+
+#cart-items-list .col-product {
+ font-weight: 600;
+}
+
+#cart-items-list .col-details {
+ color: #8fbef6;
+ font-size: 0.9rem;
+ line-height: 1.35;
+}
+
+#cart-items-list .col-price {
+ font-weight: 700;
+ text-align: right;
+ padding-right: 18px;
+}
+
+#cart-items-list .cart-header-row .col-price {
+ text-align: left;
+ padding-left: 8px;
+ padding-right: 0;
+}
+
+#cart-items-list .col-action {
+ display: flex;
+ justify-content: flex-end;
+ text-align: right;
+ padding-right: 0;
+}
+
+#cart-items-list .btn-delete-item {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 34px;
+ height: 34px;
+ border-radius: 8px;
+ border: 1px solid #7a3a45;
+ background: #2b1116;
+ color: #ff7a90;
+ font-size: 1.05rem;
+ opacity: 1;
+ transform: translateX(6px);
+}
+
+#cart-items-list .btn-delete-item:hover {
+ background: #3a161d;
+ color: #ff95a7;
+ border-color: #97505d;
+ transform: translateX(6px) scale(1.06);
+}
+
+#cart-items-list .btn-delete-item:active {
+ transform: translateX(6px) scale(0.96);
+}
+
+.cart-img-fallback {
+ width: 60px;
+ height: 85px;
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.7rem;
+ text-align: center;
+ background: #2b2d31;
+ color: #aeb3bb;
+ padding: 6px;
+}
+
+@media (max-width: 980px) {
+ .cart-container {
+ flex-direction: column;
+ gap: 24px;
+ }
+
+ .cart-right {
+ width: 100%;
+ min-width: 0;
+ }
+
+ #cart-items-list .cart-header-row {
+ display: none;
+ }
+
+ #cart-items-list .cart-item-row {
+ grid-template-columns: 1fr;
+ gap: 10px;
+ padding: 14px 0;
+ }
+
+ #cart-items-list .col-amount,
+ #cart-items-list .col-img,
+ #cart-items-list .col-action {
+ justify-content: flex-start;
+ text-align: left;
+ }
+
+ #cart-items-list .col-price {
+ text-align: left;
+ }
+}
+
+/* --- Seat Map Refresh (Cinema-Like Layout) --- */
+.seat-map-container {
+ perspective: 900px;
+}
+
+#seat-grid.seat-grid-custom {
+ display: flex;
+ flex-direction: column;
+ gap: 9px;
+ align-items: center;
+ min-width: max-content;
+ padding: 16px 8px 6px;
+ transform: rotateX(4deg);
+ transform-origin: top center;
+}
+
+#seat-grid .seat-row.cinema-row {
+ display: grid;
+ grid-template-columns: 28px auto 40px auto 28px;
+ align-items: center;
+ gap: 9px;
+ width: max-content;
+ margin-left: var(--row-indent, 0);
+ margin-right: var(--row-indent, 0);
+}
+
+#seat-grid .row-seat-block {
+ display: flex;
+ gap: 7px;
+}
+
+#seat-grid .row-label {
+ font-size: 0.72rem;
+ letter-spacing: 1px;
+ color: #8f949c;
+ font-weight: 700;
+ text-align: center;
+}
+
+#seat-grid .row-label-right {
+ opacity: 0.65;
+}
+
+#seat-grid .aisle-gap {
+ width: 40px;
+ height: 1px;
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.25), transparent);
+}
+
+#seat-grid .seat {
+ width: 24px;
+ height: 20px;
+ border-radius: 8px 8px 5px 5px;
+ border: 1px solid rgba(255, 255, 255, 0.18);
+ position: relative;
+ appearance: none;
+ padding: 0;
+ cursor: pointer;
+ transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
+}
+
+#seat-grid .seat::before {
+ content: "";
+ position: absolute;
+ left: 2px;
+ right: 2px;
+ top: -4px;
+ height: 5px;
+ border-radius: 5px 5px 0 0;
+ background: inherit;
+ opacity: 0.92;
+}
+
+#seat-grid .seat:hover:not(.occupied) {
+ transform: translateY(-2px) scale(1.08);
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.45);
+}
+
+#seat-grid .seat.normal,
+#seat-grid .seat.imax {
+ background: linear-gradient(180deg, #45484f 0%, #2f3238 100%);
+}
+
+#seat-grid .seat.vip {
+ background: linear-gradient(180deg, #ffb74d 0%, #ff8f00 100%);
+}
+
+#seat-grid .seat.dbox {
+ background: linear-gradient(180deg, #ffeb3b 0%, #f9a825 100%);
+}
+
+#seat-grid .seat.selected {
+ background: linear-gradient(180deg, #56f189 0%, #28a745 100%) !important;
+ box-shadow: 0 0 14px rgba(69, 233, 120, 0.72);
+ border-color: #d6ffe4;
+}
+
+#seat-grid .seat.occupied {
+ background: linear-gradient(180deg, #ef5350 0%, #c62828 100%) !important;
+ opacity: 1;
+ cursor: not-allowed;
+}
+
+#seat-grid .seat:disabled {
+ opacity: 1;
+}
+
+#seat-grid .seat.occupied::after {
+ content: "×";
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ font-size: 14px;
+ font-weight: 700;
+}
+
+#dynamic-legend {
+ margin-top: 14px;
+}
+
+#summary-items .summary-row {
+ display: flex;
+ justify-content: space-between;
+ gap: 14px;
+ padding: 7px 0;
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
+ font-size: 0.9rem;
+}
+
+/* --- April 2026 Refresh --- */
+.hero-overlay {
+ max-width: 860px;
+ border-radius: 24px;
+ background: linear-gradient(90deg, rgba(6, 9, 14, 0.7), rgba(6, 9, 14, 0.25));
+ backdrop-filter: blur(2px);
+}
+
+.running-poster {
+ display: flex;
+ flex-direction: column;
+}
+
+.running-poster img {
+ height: 240px;
+ object-position: center 18%;
+}
+
+.running-meta {
+ display: flex;
+ flex-direction: column;
+ min-height: 150px;
+}
+
+.running-meta p {
+ margin-bottom: 14px;
+}
+
+.open-program-btn {
+ margin-top: auto;
+}
+
+/* --- Latest home/account refinement --- */
+.hero {
+ min-height: 94vh;
+}
+
+.hero::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(180deg, rgba(3, 5, 8, 0.05) 0%, rgba(3, 5, 8, 0.62) 80%, rgba(3, 5, 8, 0.88) 100%);
+ pointer-events: none;
+ z-index: 1;
+}
+
+.hero-overlay {
+ z-index: 2;
+ max-width: 980px;
+ padding: 180px 8% 118px;
+ background: transparent;
+ backdrop-filter: none;
+ border-radius: 0;
+ text-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
+}
+
+.hero-slide {
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-color: #06080d;
+ transform: none;
+}
+
+.hero-slide.active {
+ transform: none;
+}
+
+.home-experience {
+ margin-top: 34px;
+ display: grid;
+ grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
+ gap: 16px;
+}
+
+.experience-main-card,
+.experience-side-card {
+ background: linear-gradient(158deg, #151820 0%, #0f1219 100%);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 18px;
+ padding: 20px 20px 22px;
+}
+
+.experience-main-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ gap: 12px;
+ margin-bottom: 10px;
+}
+
+.experience-main-head h3 {
+ font-size: 1.25rem;
+}
+
+.experience-main-head span {
+ color: #9aa4b2;
+ font-size: 0.78rem;
+}
+
+.experience-main-card p,
+.experience-side-card p {
+ color: #b4becb;
+ line-height: 1.5;
+ font-size: 0.92rem;
+}
+
+.experience-tags,
+.experience-chip-row {
+ margin-top: 14px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.experience-tags span,
+.experience-chip-row span {
+ border-radius: 999px;
+ border: 1px solid rgba(0, 113, 227, 0.45);
+ background: rgba(0, 113, 227, 0.16);
+ color: #c4dffe;
+ padding: 4px 11px;
+ font-size: 0.76rem;
+}
+
+.experience-side-stack {
+ display: grid;
+ gap: 16px;
+}
+
+.collector-card .collector-placeholder-grid {
+ margin-top: 12px;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.collector-card .collector-slot {
+ min-height: 100px;
+}
+
+.account-orders-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 10px;
+ margin-top: 8px;
+}
+
+.order-item-btn {
+ width: 100%;
+ text-align: left;
+ cursor: pointer;
+ transition: border-color 0.2s ease, transform 0.2s ease, background 0.2s ease;
+}
+
+.order-item-btn:hover {
+ border-color: rgba(0, 113, 227, 0.58);
+ transform: translateY(-2px);
+}
+
+.order-item-btn.active {
+ border-color: #0071e3;
+ background: linear-gradient(150deg, #162334 0%, #111720 100%);
+}
+
+.order-item-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 8px;
+}
+
+.order-item-head h4 {
+ font-size: 0.98rem;
+}
+
+.order-item-head span {
+ color: #9ed0ff;
+ font-weight: 700;
+ font-size: 0.86rem;
+}
+
+.order-ticket-details {
+ margin-top: 14px;
+}
+
+.order-ticket-card {
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ border-radius: 16px;
+ background: linear-gradient(155deg, #12161f 0%, #0c1017 100%);
+ padding: 14px;
+ display: grid;
+ grid-template-columns: 120px minmax(0, 1fr);
+ gap: 14px;
+}
+
+.order-ticket-poster img {
+ width: 100%;
+ height: 100%;
+ max-height: 180px;
+ object-fit: cover;
+ border-radius: 10px;
+}
+
+.order-ticket-poster-fallback {
+ height: 100%;
+ min-height: 150px;
+ border-radius: 10px;
+ background: #202632;
+ color: #9aa4b2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.8rem;
+}
+
+.order-ticket-brand {
+ color: #9ec3ee;
+ font-size: 0.73rem;
+ letter-spacing: 0.8px;
+ margin-bottom: 6px;
+}
+
+.order-ticket-content h4 {
+ margin-bottom: 10px;
+}
+
+.order-ticket-grid {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 8px 14px;
+}
+
+.order-ticket-grid p {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ margin: 0;
+}
+
+.order-ticket-grid span {
+ font-size: 0.74rem;
+ color: #8c98a9;
+}
+
+.order-ticket-grid strong {
+ font-size: 0.9rem;
+}
+
+.payment-logo-slot img {
+ max-width: 72%;
+ max-height: 30px;
+ object-fit: contain;
+ filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.35));
+}
+
+@media (max-width: 1000px) {
+ .home-experience {
+ grid-template-columns: 1fr;
+ }
+}
+
+@media (max-width: 720px) {
+ .hero-overlay {
+ padding: 145px 6% 92px;
+ }
+
+ .order-ticket-card {
+ grid-template-columns: 1fr;
+ }
+
+ .order-ticket-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .collector-card .collector-placeholder-grid {
+ grid-template-columns: 1fr;
+ }
+}
+
+.home-feature-grid {
+ margin-top: 34px;
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 14px;
+}
+
+.feature-card {
+ background: linear-gradient(155deg, #17191f 0%, #101218 100%);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 16px;
+ padding: 16px 16px 18px;
+}
+
+.feature-card h4 {
+ margin-bottom: 8px;
+ font-size: 0.95rem;
+}
+
+.feature-card p {
+ color: #a7afbb;
+ font-size: 0.86rem;
+ line-height: 1.45;
+}
+
+.feature-card-wide {
+ grid-column: span 2;
+}
+
+.hall-tags {
+ margin-top: 12px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.hall-tags span {
+ border: 1px solid rgba(0, 113, 227, 0.5);
+ background: rgba(0, 113, 227, 0.18);
+ color: #c6e1ff;
+ border-radius: 999px;
+ padding: 4px 10px;
+ font-size: 0.75rem;
+}
+
+.feature-highlight {
+ margin-top: 12px;
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ border-radius: 10px;
+ color: #d8dee8;
+ padding: 8px 10px;
+ font-size: 0.8rem;
+}
+
+.feature-card-collector {
+ grid-column: span 2;
+}
+
+.collector-placeholder-grid {
+ margin-top: 12px;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 10px;
+}
+
+.collector-slot {
+ min-height: 90px;
+ border-radius: 12px;
+ border: 1px dashed rgba(255, 255, 255, 0.25);
+ background: linear-gradient(140deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0.02));
+ color: #9ca6b3;
+ font-size: 0.78rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ padding: 6px;
+}
+
+#cart-items-list .qty-static {
+ min-width: 68px;
+ text-align: center;
+ padding: 7px 10px;
+ border-radius: 999px;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background: rgba(255, 255, 255, 0.05);
+ color: #d8dce3;
+ font-weight: 600;
+}
+
+.account-payments-note {
+ color: #9aa1ad;
+ font-size: 0.9rem;
+ margin-bottom: 12px;
+}
+
+.account-payment-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
+ gap: 10px;
+}
+
+.account-payment-card {
+ background: #141518;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 12px;
+ padding: 12px;
+}
+
+.account-payment-card h4 {
+ font-size: 0.9rem;
+ margin-bottom: 4px;
+}
+
+.account-payment-card p {
+ color: #9aa1ad;
+ font-size: 0.8rem;
+}
+
+.payment-logo-slot {
+ height: 52px;
+ border-radius: 10px;
+ border: 1px dashed rgba(255, 255, 255, 0.28);
+ margin-bottom: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #9aa1ad;
+ font-size: 0.8rem;
+}
+
+@media (max-width: 900px) {
+ .feature-card-wide,
+ .feature-card-collector {
+ grid-column: span 1;
+ }
+
+ .collector-placeholder-grid {
+ grid-template-columns: 1fr;
+ }
+}
+/* =========================================================
+ Cinecity-Inspired Home + Program Refresh
+ ========================================================= */
+
+.hero {
+ position: relative;
+ min-height: 92vh;
+ height: auto;
+ display: block;
+ overflow: hidden;
+ isolation: isolate;
+}
+
+.hero-slider {
+ position: absolute;
+ inset: 0;
+}
+
+.hero-slide {
+ position: absolute;
+ inset: 0;
+ background-size: cover;
+ background-position: center;
+ opacity: 0;
+ transform: scale(1.03);
+ transition: opacity 0.8s ease, transform 1.4s ease;
+}
+
+.hero-slide.active {
+ opacity: 1;
+ transform: scale(1);
+}
+
+.hero-overlay {
+ position: relative;
+ z-index: 2;
+ max-width: 760px;
+ margin: 0 auto;
+ padding: 190px 10% 130px;
+ text-align: left;
+}
+
+.hero-overlay h1 {
+ font-size: clamp(2.2rem, 5vw, 4.7rem);
+ letter-spacing: 0.4px;
+ margin: 12px 0;
+}
+
+.hero-overlay p {
+ color: #d1d4da;
+ font-size: 1.05rem;
+ max-width: 620px;
+ margin-bottom: 22px;
+}
+
+.hero-dots {
+ margin-top: 22px;
+ display: flex;
+ gap: 10px;
+ align-items: center;
+}
+
+.hero-dot {
+ width: 30px;
+ height: 6px;
+ border-radius: 99px;
+ border: 0;
+ background: rgba(255, 255, 255, 0.3);
+ cursor: pointer;
+}
+
+.hero-dot.active {
+ background: #0071e3;
+}
+
+.cinema-home {
+ background:
+ radial-gradient(circle at 20% -10%, rgba(0, 113, 227, 0.15), transparent 45%),
+ radial-gradient(circle at 85% 15%, rgba(255, 255, 255, 0.08), transparent 38%),
+ #07080b;
+ border-top: 1px solid rgba(255, 255, 255, 0.08);
+}
+
+.home-poster-band {
+ margin-top: 18px;
+ padding: 18px;
+ background: rgba(255, 255, 255, 0.03);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 18px;
+}
+
+.home-band-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ margin-bottom: 14px;
+}
+
+.home-band-header h3 {
+ font-size: 1.2rem;
+}
+
+.home-band-header span {
+ color: #8f95a0;
+ font-size: 0.85rem;
+}
+
+.now-running-row {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+ gap: 14px;
+}
+
+.running-poster {
+ background: #121317;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 14px;
+ overflow: hidden;
+}
+
+.running-poster img {
+ width: 100%;
+ height: 210px;
+ object-fit: cover;
+ display: block;
+}
+
+.running-meta {
+ padding: 12px;
+}
+
+.running-meta h4 {
+ font-size: 0.95rem;
+ margin-bottom: 4px;
+}
+
+.running-meta p {
+ color: #94a0af;
+ font-size: 0.78rem;
+ margin-bottom: 10px;
+}
+
+.open-program-btn {
+ width: 100%;
+ border: 1px solid rgba(255, 255, 255, 0.25);
+ background: transparent;
+ color: #e7ebf0;
+ border-radius: 8px;
+ font-size: 0.78rem;
+ padding: 7px 10px;
+ cursor: pointer;
+}
+
+.open-program-btn:hover {
+ background: rgba(255, 255, 255, 0.08);
+}
+
+.home-program-head {
+ margin-top: 36px;
+}
+
+.home-program-grid {
+ margin-top: 10px;
+}
+
+.home-movie-card {
+ box-shadow: 0 20px 30px rgba(0, 0, 0, 0.3);
+}
+
+.home-info-grid {
+ margin-top: 34px;
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 14px;
+}
+
+.info-card {
+ background: linear-gradient(155deg, #17191f 0%, #101218 100%);
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ border-radius: 16px;
+ padding: 16px 16px 18px;
+}
+
+.info-card h4 {
+ margin-bottom: 8px;
+ font-size: 0.95rem;
+}
+
+.info-card p {
+ color: #a7afbb;
+ font-size: 0.86rem;
+ line-height: 1.45;
+}
+
+.movie-list-shell {
+ padding: 120px 8% 60px;
+}
+
+.list-subtitle {
+ margin-top: 8px;
+ color: #9aa1ac;
+ margin-bottom: 22px;
+}
+
+.movie-program-list {
+ display: flex;
+ flex-direction: column;
+ gap: 28px;
+}
+
+.program-card {
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ box-shadow: 0 22px 40px rgba(0, 0, 0, 0.33);
+}
+
+.program-card .card-header {
+ margin-bottom: 12px;
+}
+
+.program-card .description {
+ color: #c2c8d1;
+ margin-bottom: 16px;
+ line-height: 1.55;
+}
+
+.program-day-tabs {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ margin-bottom: 14px;
+}
+
+.program-day-tab {
+ min-width: 78px;
+ border: 1px solid rgba(255, 255, 255, 0.16);
+ background: rgba(255, 255, 255, 0.03);
+ color: #f2f5f9;
+ border-radius: 12px;
+ padding: 7px 10px;
+ cursor: pointer;
+ display: inline-flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 3px;
+}
+
+.program-day-tab small {
+ font-size: 0.72rem;
+ color: #94a0ad;
+}
+
+.program-day-tab.active {
+ border-color: #0071e3;
+ background: rgba(0, 113, 227, 0.2);
+}
+
+.program-schedule-shell {
+ margin-top: 0;
+}
+
+.program-schedule-body {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.program-time-row {
+ width: 100%;
+ text-align: left;
+ padding: 12px 14px;
+ display: grid;
+ grid-template-columns: 1fr 130px 90px;
+ align-items: center;
+ gap: 10px;
+ border: 1px solid rgba(255, 255, 255, 0.09);
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.program-time-row:hover {
+ border-color: #0071e3;
+ transform: translateX(3px);
+}
+
+.hall-pill {
+ justify-self: center;
+ font-size: 0.78rem;
+ color: #bcd6f6;
+ border: 1px solid rgba(0, 113, 227, 0.4);
+ background: rgba(0, 113, 227, 0.15);
+ border-radius: 999px;
+ padding: 4px 10px;
+}
+
+.flash-focus {
+ animation: cardFlash 1.1s ease;
+}
+
+@keyframes cardFlash {
+ 0% {
+ box-shadow: 0 0 0 rgba(0, 113, 227, 0);
+ transform: translateY(0);
+ }
+ 40% {
+ box-shadow: 0 0 0 4px rgba(0, 113, 227, 0.35);
+ transform: translateY(-2px);
+ }
+ 100% {
+ box-shadow: 0 0 0 rgba(0, 113, 227, 0);
+ transform: translateY(0);
+ }
+}
+
+.reveal-on-scroll {
+ opacity: 0;
+ transform: translateY(28px);
+ transition: opacity 0.7s ease, transform 0.7s ease;
+}
+
+.reveal-on-scroll.is-visible {
+ opacity: 1;
+ transform: translateY(0);
+}
+
+@media (max-width: 900px) {
+ .hero-overlay {
+ padding: 150px 8% 90px;
+ }
+
+ .program-time-row {
+ grid-template-columns: 1fr;
+ align-items: flex-start;
+ }
+
+ .hall-pill {
+ justify-self: flex-start;
+ }
+
+ .movie-list-shell {
+ padding-left: 5%;
+ padding-right: 5%;
+ }
+}
+
+/* --- Final visual overrides --- */
+.hero-overlay {
+ max-width: 860px;
+ border-radius: 24px;
+ background: linear-gradient(90deg, rgba(6, 9, 14, 0.7), rgba(6, 9, 14, 0.25));
+ backdrop-filter: blur(2px);
+}
+
+.running-poster {
+ display: flex;
+ flex-direction: column;
+}
+
+.running-poster img {
+ height: 240px;
+ object-position: center 18%;
+}
+
+.running-meta {
+ display: flex;
+ flex-direction: column;
+ min-height: 150px;
+}
+
+.running-meta p {
+ margin-bottom: 14px;
+}
+
+.open-program-btn {
+ margin-top: auto;
+}
+
+/* --- 2026-04 final overrides (keep at file end) --- */
+.hero {
+ min-height: 94vh;
+}
+
+.hero::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(180deg, rgba(3, 5, 8, 0.05) 0%, rgba(3, 5, 8, 0.62) 80%, rgba(3, 5, 8, 0.88) 100%);
+ pointer-events: none;
+ z-index: 1;
+}
+
+.hero-overlay {
+ z-index: 2;
+ max-width: 980px;
+ padding: 180px 8% 118px;
+ background: transparent;
+ backdrop-filter: none;
+ border-radius: 0;
+ text-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
+}
+
+.home-experience {
+ margin-top: 34px;
+ display: grid;
+ grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
+ gap: 16px;
+}
+
+.experience-main-card,
+.experience-side-card {
+ background: linear-gradient(158deg, #151820 0%, #0f1219 100%);
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 18px;
+ padding: 20px 20px 22px;
+}
+
+.experience-main-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ gap: 12px;
+ margin-bottom: 10px;
+}
+
+.experience-main-head h3 {
+ font-size: 1.25rem;
+}
+
+.experience-main-head span {
+ color: #9aa4b2;
+ font-size: 0.78rem;
+}
+
+.experience-main-card p,
+.experience-side-card p {
+ color: #b4becb;
+ line-height: 1.5;
+ font-size: 0.92rem;
+}
+
+.experience-tags,
+.experience-chip-row {
+ margin-top: 14px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.experience-tags span,
+.experience-chip-row span {
+ border-radius: 999px;
+ border: 1px solid rgba(0, 113, 227, 0.45);
+ background: rgba(0, 113, 227, 0.16);
+ color: #c4dffe;
+ padding: 4px 11px;
+ font-size: 0.76rem;
+}
+
+.experience-side-stack {
+ display: grid;
+ gap: 16px;
+}
+
+.collector-card .collector-placeholder-grid {
+ margin-top: 12px;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.collector-card .collector-slot {
+ min-height: 100px;
+}
+
+.account-orders-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 10px;
+ margin-top: 8px;
+}
+
+.order-item-btn {
+ width: 100%;
+ text-align: left;
+ cursor: pointer;
+ transition: border-color 0.2s ease, transform 0.2s ease, background 0.2s ease;
+}
+
+.order-item-btn:hover {
+ border-color: rgba(0, 113, 227, 0.58);
+ transform: translateY(-2px);
+}
+
+.order-item-btn.active {
+ border-color: #0071e3;
+ background: linear-gradient(150deg, #162334 0%, #111720 100%);
+}
+
+.order-item-head {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 8px;
+}
+
+.order-item-head h4 {
+ font-size: 0.98rem;
+}
+
+.order-item-head span {
+ color: #9ed0ff;
+ font-weight: 700;
+ font-size: 0.86rem;
+}
+
+.order-ticket-details {
+ margin-top: 14px;
+}
+
+.order-ticket-card {
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ border-radius: 16px;
+ background: linear-gradient(155deg, #12161f 0%, #0c1017 100%);
+ padding: 14px;
+ display: grid;
+ grid-template-columns: 120px minmax(0, 1fr);
+ gap: 14px;
+}
+
+.order-ticket-poster img {
+ width: 100%;
+ height: 100%;
+ max-height: 180px;
+ object-fit: cover;
+ border-radius: 10px;
+}
+
+.order-ticket-poster-fallback {
+ height: 100%;
+ min-height: 150px;
+ border-radius: 10px;
+ background: #202632;
+ color: #9aa4b2;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 0.8rem;
+}
+
+.order-ticket-brand {
+ color: #9ec3ee;
+ font-size: 0.73rem;
+ letter-spacing: 0.8px;
+ margin-bottom: 6px;
+}
+
+.order-ticket-content h4 {
+ margin-bottom: 10px;
+}
+
+.order-ticket-grid {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 8px 14px;
+}
+
+.order-ticket-grid p {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ margin: 0;
+}
+
+.order-ticket-grid span {
+ font-size: 0.74rem;
+ color: #8c98a9;
+}
+
+.order-ticket-grid strong {
+ font-size: 0.9rem;
+}
+
+.payment-logo-slot img {
+ max-width: 72%;
+ max-height: 30px;
+ object-fit: contain;
+ filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.35));
+}
+
+@media (max-width: 1000px) {
+ .home-experience {
+ grid-template-columns: 1fr;
+ }
+}
+
+@media (max-width: 720px) {
+ .hero-overlay {
+ padding: 145px 6% 92px;
+ }
+
+ .order-ticket-card {
+ grid-template-columns: 1fr;
+ }
+
+ .order-ticket-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .collector-card .collector-placeholder-grid {
+ grid-template-columns: 1fr;
+ }
+}
+
+/* hero slide clarity final */
+.hero-slide {
+ background-size: contain;
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-color: #06080d;
+ transform: none;
+}
+
+.hero-slide.active {
+ transform: none;
+}
+
+/* --- 2026-04-21 final UX overrides --- */
+.hero-overlay {
+ padding: 230px 8% 74px;
+}
+
+.hero-slide {
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center 34%;
+ transform: scale(1.09);
+}
+
+.hero-slide.active {
+ transform: scale(1.02);
+}
+
+.home-inline-showcase {
+ margin-top: 36px;
+ display: flex;
+ flex-direction: column;
+ gap: 28px;
+}
+
+.inline-section {
+ display: grid;
+ grid-template-columns: 1.15fr 1fr;
+ border-radius: 26px;
+ overflow: hidden;
+ border: 1px solid rgba(255, 255, 255, 0.11);
+ background: #0d1118;
+ min-height: 290px;
+ box-shadow: 0 26px 50px rgba(0, 0, 0, 0.34);
+}
+
+.inline-media {
+ position: relative;
+ background-size: cover;
+ background-position: center;
+}
+
+.inline-media::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(110deg, rgba(4, 6, 10, 0.08), rgba(4, 6, 10, 0.58));
+}
+
+.inline-halls .inline-media {
+ background-image: linear-gradient(120deg, rgba(0, 113, 227, 0.3), rgba(7, 10, 16, 0.55)), url('/img/shelter.jpg');
+}
+
+.inline-dbox .inline-media {
+ background-image: linear-gradient(120deg, rgba(255, 176, 0, 0.2), rgba(8, 12, 18, 0.62)), url('/img/dbox.jpg');
+}
+
+.inline-collectors .inline-media {
+ background-image: linear-gradient(120deg, rgba(185, 124, 255, 0.15), rgba(8, 12, 18, 0.62)), url('/img/popcorn.jpg');
+}
+
+.inline-content {
+ padding: 28px 26px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.inline-content h3 {
+ font-size: clamp(1.3rem, 2.3vw, 1.9rem);
+ margin-bottom: 12px;
+}
+
+.inline-content p {
+ color: #b4bfcc;
+ line-height: 1.58;
+ margin-bottom: 16px;
+}
+
+.inline-tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ margin-bottom: 16px;
+}
+
+.inline-tags span {
+ border-radius: 999px;
+ border: 1px solid rgba(0, 113, 227, 0.5);
+ background: rgba(0, 113, 227, 0.16);
+ color: #cae3ff;
+ padding: 5px 11px;
+ font-size: 0.76rem;
+}
+
+.story-more-btn {
+ align-self: flex-start;
+ border: 1px solid rgba(255, 255, 255, 0.24);
+ background: rgba(255, 255, 255, 0.04);
+ color: #e8edf3;
+ border-radius: 999px;
+ padding: 10px 16px;
+ font-size: 0.82rem;
+ cursor: pointer;
+ transition: transform 0.25s ease, background 0.25s ease, border-color 0.25s ease, box-shadow 0.25s ease;
+}
+
+.story-more-btn:hover {
+ transform: translateY(-2px) scale(1.03);
+ background: rgba(0, 113, 227, 0.16);
+ border-color: rgba(0, 113, 227, 0.72);
+ box-shadow: 0 10px 24px rgba(0, 113, 227, 0.22);
+}
+
+.dbox-now-highlight {
+ border: 1px solid rgba(255, 181, 59, 0.5);
+ background: linear-gradient(160deg, rgba(255, 164, 27, 0.2), rgba(255, 213, 128, 0.08));
+ border-radius: 14px;
+ padding: 12px;
+ margin-bottom: 16px;
+}
+
+.dbox-now-highlight h4 {
+ font-size: 0.88rem;
+ margin-bottom: 8px;
+ color: #ffe2b5;
+}
+
+.dbox-mini-cards {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 8px;
+}
+
+.dbox-mini-cards div {
+ border-radius: 10px;
+ border: 1px solid rgba(255, 228, 168, 0.35);
+ background: rgba(23, 16, 8, 0.42);
+ padding: 7px 10px;
+ font-size: 0.78rem;
+ color: #f7dfb6;
+ text-align: center;
+}
+
+.home-modal-overlay {
+ position: fixed;
+ inset: 0;
+ background: rgba(2, 5, 10, 0.74);
+ backdrop-filter: blur(8px);
+ z-index: 2500;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 24px;
+}
+
+.home-modal-panel {
+ width: min(980px, 100%);
+ max-height: 90vh;
+ overflow-y: auto;
+ border-radius: 22px;
+ border: 1px solid rgba(255, 255, 255, 0.14);
+ background: linear-gradient(165deg, #171b24 0%, #10141c 100%);
+ padding: 22px;
+ position: relative;
+}
+
+.home-modal-wide {
+ width: min(1120px, 100%);
+}
+
+.home-modal-close {
+ position: absolute;
+ top: 14px;
+ right: 14px;
+ width: 34px;
+ height: 34px;
+ border-radius: 50%;
+ border: 0;
+ background: #2a2f3a;
+ color: #fff;
+ font-size: 1.2rem;
+ cursor: pointer;
+}
+
+.home-modal-sub {
+ color: #96a1b2;
+ margin-top: 4px;
+ margin-bottom: 14px;
+}
+
+.hall-modal-grid {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 12px;
+}
+
+.hall-modal-item {
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 14px;
+ padding: 12px;
+ background: rgba(255, 255, 255, 0.02);
+}
+
+.hall-modal-item h4 {
+ margin-bottom: 10px;
+}
+
+.hall-modal-item textarea,
+.hall-modal-item input,
+.dbox-modal-section input,
+.collector-entry-content input {
+ width: 100%;
+ border-radius: 10px;
+ border: 1px solid #3e4658;
+ background: #111621;
+ color: #f3f6fb;
+ padding: 10px 11px;
+}
+
+.hall-modal-item textarea {
+ min-height: 100px;
+ resize: vertical;
+ margin-bottom: 8px;
+}
+
+.dbox-modal-section {
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ border-radius: 14px;
+ padding: 14px;
+ margin-top: 12px;
+}
+
+.dbox-image-grid {
+ margin-top: 12px;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: 10px;
+}
+
+.dbox-image-slot {
+ min-height: 98px;
+ border: 1px dashed rgba(255, 255, 255, 0.3);
+ border-radius: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ color: #9aa8ba;
+ font-size: 0.78rem;
+}
+
+.modal-highlight {
+ margin-top: 14px;
+}
+
+.collector-zigzag {
+ margin-top: 14px;
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+}
+
+.collector-entry {
+ width: 82%;
+ display: grid;
+ grid-template-columns: 90px 1fr;
+ gap: 10px;
+ border-radius: 14px;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ background: rgba(255, 255, 255, 0.03);
+ padding: 12px;
+}
+
+.collector-entry.left {
+ align-self: flex-start;
+}
+
+.collector-entry.right {
+ align-self: flex-end;
+}
+
+.collector-film-logo {
+ border-radius: 10px;
+ border: 1px dashed rgba(255, 255, 255, 0.35);
+ min-height: 72px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #9ba7b9;
+ font-size: 0.74rem;
+}
+
+.collector-entry-content h4 {
+ margin-bottom: 6px;
+}
+
+.collector-entry-content p {
+ color: #b3becc;
+ margin-bottom: 8px;
+ font-size: 0.9rem;
+}
+
+.account-payment-card {
+ text-align: left;
+ cursor: pointer;
+}
+
+.account-payment-card:hover {
+ border-color: rgba(0, 113, 227, 0.6);
+ transform: translateY(-2px);
+}
+
+.payment-logo-slot {
+ border: 1px solid rgba(255, 255, 255, 0.16);
+ background: rgba(255, 255, 255, 0.04);
+}
+
+.pay-modal-overlay {
+ position: fixed;
+ inset: 0;
+ z-index: 2600;
+ background: rgba(2, 4, 9, 0.72);
+ backdrop-filter: blur(8px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 20px;
+}
+
+.pay-modal-panel {
+ width: min(460px, 100%);
+ border-radius: 18px;
+ border: 1px solid rgba(255, 255, 255, 0.16);
+ background: #12151d;
+ padding: 18px;
+ position: relative;
+}
+
+.pay-modal-head {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 12px;
+}
+
+.pay-modal-head img {
+ height: 26px;
+ width: auto;
+}
+
+.pay-close-btn {
+ position: absolute;
+ top: 11px;
+ right: 11px;
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ border: 0;
+ background: rgba(255, 255, 255, 0.08);
+ color: #fff;
+ cursor: pointer;
+ font-size: 1.1rem;
+}
+
+.pay-form-grid label,
+.pay-modal-panel label {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+ font-size: 0.84rem;
+ color: #b2bece;
+ margin-top: 8px;
+}
+
+.pay-form-grid input,
+.pay-modal-panel input {
+ border-radius: 10px;
+ border: 1px solid #3b4255;
+ background: #10141f;
+ color: #f2f6fd;
+ padding: 10px;
+}
+
+.pay-form-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 10px;
+}
+
+.pay-submit-btn {
+ width: 100%;
+ margin-top: 14px;
+ border: 0;
+ border-radius: 11px;
+ padding: 11px 12px;
+ font-weight: 600;
+ cursor: pointer;
+ background: #0071e3;
+ color: #fff;
+}
+
+.paypal-btn {
+ background: linear-gradient(90deg, #005ea6, #0b84e3);
+}
+
+.apple-btn {
+ background: linear-gradient(90deg, #e9edf5, #cfd7e5);
+ color: #0c1016;
+}
+
+.google-btn {
+ background: linear-gradient(90deg, #1967d2, #34a853);
+}
+
+.pay-modal-paypal-style {
+ background: linear-gradient(160deg, #112544 0%, #0f1e34 100%);
+}
+
+.pay-modal-apple-style {
+ background: linear-gradient(160deg, #1d212b 0%, #131722 100%);
+}
+
+.pay-modal-google-style {
+ background: linear-gradient(160deg, #122033 0%, #141925 100%);
+}
+
+@media (max-width: 980px) {
+ .inline-section {
+ grid-template-columns: 1fr;
+ }
+
+ .inline-media {
+ min-height: 210px;
+ }
+
+ .hall-modal-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .dbox-image-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+
+ .collector-entry {
+ width: 100%;
+ }
+}
+
+/* --- 2026-04-21 nav/theme/info pages --- */
+#link-cart {
+ transform: translateY(2px);
+}
+
+.theme-toggle-item {
+ display: flex;
+ align-items: center;
+}
+
+.theme-toggle-btn {
+ width: 44px;
+ height: 44px;
+ border-radius: 999px;
+ border: 1px solid rgba(255, 255, 255, 0.24);
+ background: linear-gradient(140deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.02));
+ color: #fff;
+ position: relative;
+ cursor: pointer;
+ transition: transform 0.35s ease, box-shadow 0.35s ease, background 0.35s ease;
+}
+
+.theme-toggle-btn:hover {
+ transform: translateY(-1px) scale(1.03);
+ box-shadow: 0 10px 18px rgba(0, 0, 0, 0.28);
+}
+
+.theme-icon {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.05rem;
+ transition: opacity 0.35s ease, transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
+}
+
+.theme-icon-sun {
+ opacity: 0;
+ transform: rotate(-35deg) scale(0.5);
+}
+
+.theme-icon-moon {
+ opacity: 1;
+ transform: rotate(0deg) scale(1);
+}
+
+.theme-toggle-btn.is-light .theme-icon-sun {
+ opacity: 1;
+ transform: rotate(0deg) scale(1);
+}
+
+.theme-toggle-btn.is-light .theme-icon-moon {
+ opacity: 0;
+ transform: rotate(35deg) scale(0.55);
+}
+
+.info-view {
+ min-height: 100vh;
+ padding-top: 120px;
+ padding-bottom: 70px;
+}
+
+.info-view-shell {
+ padding: 0 8%;
+}
+
+.info-view-shell h1 {
+ font-size: clamp(2rem, 4vw, 3rem);
+}
+
+.info-view-subtitle {
+ color: #98a3b3;
+ margin-top: 8px;
+ margin-bottom: 22px;
+}
+
+.full-page-grid {
+ margin-top: 16px;
+}
+
+.subpage-back-btn {
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ background: rgba(255, 255, 255, 0.04);
+ color: #ebf1f9;
+ border-radius: 999px;
+ padding: 10px 14px;
+ margin-bottom: 18px;
+ cursor: pointer;
+ transition: transform 0.2s ease, border-color 0.2s ease;
+}
+
+.subpage-back-btn:hover {
+ transform: translateX(-2px);
+ border-color: rgba(0, 113, 227, 0.65);
+}
+
+.about-intro {
+ margin-top: 12px;
+ color: #b2bcc9;
+ line-height: 1.65;
+ max-width: 900px;
+}
+
+.about-cards {
+ margin-top: 24px;
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: 14px;
+}
+
+.about-card {
+ border: 1px solid rgba(255, 255, 255, 0.11);
+ border-radius: 16px;
+ background: linear-gradient(155deg, #151922 0%, #10141c 100%);
+ padding: 16px;
+}
+
+.about-card h3 {
+ margin-bottom: 8px;
+}
+
+.about-card p {
+ color: #aeb8c6;
+ margin-bottom: 14px;
+ line-height: 1.5;
+}
+
+body.theme-dark .program-card .description,
+body.theme-dark .inline-content p,
+body.theme-dark .about-intro {
+ color: #d1d7e0;
+}
+
+body.theme-dark #checkout-summary-list,
+body.theme-dark .hall-modal-item,
+body.theme-dark .dbox-modal-section {
+ color: #eaf1fc;
+}
+
+body.theme-light {
+ background: #eef2f8;
+ color: #121620;
+}
+
+body.theme-light .navbar {
+ background: rgba(244, 248, 255, 0.85);
+ border-bottom: 1px solid rgba(11, 22, 42, 0.08);
+}
+
+body.theme-light .nav-links a,
+body.theme-light .logo {
+ color: #1a2435;
+ opacity: 0.95;
+}
+
+body.theme-light .hero::after {
+ background: linear-gradient(180deg, rgba(240, 246, 255, 0.04) 0%, rgba(240, 246, 255, 0.26) 100%);
+}
+
+body.theme-light .hero-overlay h1,
+body.theme-light .hero-overlay p {
+ color: #131a26;
+ text-shadow: none;
+}
+
+body.theme-light .home-poster-band,
+body.theme-light .inline-section,
+body.theme-light .detailed-card,
+body.theme-light .program-card,
+body.theme-light .hall-modal-item,
+body.theme-light .dbox-modal-section,
+body.theme-light .about-card,
+body.theme-light .account-panel,
+body.theme-light .account-login-box,
+body.theme-light .account-card,
+body.theme-light .order-box,
+body.theme-light .summary-box-black,
+body.theme-light .cart-left,
+body.theme-light .pay-modal-panel,
+body.theme-light .home-modal-panel,
+body.theme-light .snack-card,
+body.theme-light .snack-card.highlight {
+ background: #ffffff !important;
+ color: #1a2435;
+ border-color: rgba(21, 35, 58, 0.14) !important;
+ box-shadow: 0 10px 30px rgba(21, 35, 58, 0.08);
+}
+
+body.theme-light .inline-content p,
+body.theme-light .program-card .description,
+body.theme-light .list-subtitle,
+body.theme-light .info-view-subtitle,
+body.theme-light .about-intro,
+body.theme-light .about-card p,
+body.theme-light .account-payments-note,
+body.theme-light .running-meta p {
+ color: #45556f !important;
+}
+
+body.theme-light .running-poster,
+body.theme-light .order-ticket-card,
+body.theme-light .order-item-btn.active,
+body.theme-light .dbox-now-highlight,
+body.theme-light .modal-highlight,
+body.theme-light .collector-entry {
+ background: #f7f9fd !important;
+ border-color: rgba(28, 56, 94, 0.16) !important;
+}
+
+body.theme-light .story-more-btn,
+body.theme-light .subpage-back-btn,
+body.theme-light .open-program-btn,
+body.theme-light .account-tab-btn,
+body.theme-light .account-logout-btn,
+body.theme-light .theme-toggle-btn {
+ color: #1c2b44;
+ background: #f3f7ff;
+ border-color: rgba(28, 56, 94, 0.22);
+}
+
+body.theme-light .btn-primary,
+body.theme-light .blue-button,
+body.theme-light .auth-submit-btn,
+body.theme-light .pay-submit-btn {
+ color: #fff;
+}
+
+body.theme-light #checkout-summary-list,
+body.theme-light .hall-modal-item textarea,
+body.theme-light .hall-modal-item input,
+body.theme-light .pay-modal-panel input,
+body.theme-light .collector-entry-content input,
+body.theme-light .account-login-box input,
+body.theme-light .account-auth-modal input {
+ background: #f5f8ff !important;
+ color: #1a2435 !important;
+ border-color: rgba(33, 55, 91, 0.22) !important;
+}
+
+body.theme-light .pay-modal-overlay,
+body.theme-light .home-modal-overlay,
+body.theme-light .modal,
+body.theme-light .snack-overlay {
+ background: rgba(203, 216, 236, 0.7);
+}
+
+body.theme-light .theme-toggle-btn {
+ background: linear-gradient(140deg, #fff9d5, #ffe9b0);
+}
+
+@media (max-width: 1000px) {
+ .about-cards {
+ grid-template-columns: 1fr;
+ }
+}
+
+/* --- 2026-04-28 light-mode polish + new about design --- */
+.about-hero-block {
+ margin-top: 8px;
+ border-radius: 24px;
+ overflow: hidden;
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ display: grid;
+ grid-template-columns: 1.2fr 1fr;
+ background: linear-gradient(130deg, #111722 0%, #0b111a 100%);
+ box-shadow: 0 24px 46px rgba(0, 0, 0, 0.3);
+}
+
+.about-hero-content {
+ padding: 30px 28px;
+}
+
+.about-hero-content h1 {
+ margin-bottom: 10px;
+}
+
+.about-pill-row {
+ margin-top: 18px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.about-pill-row span {
+ border: 1px solid rgba(0, 113, 227, 0.45);
+ background: rgba(0, 113, 227, 0.15);
+ color: #c8e2ff;
+ border-radius: 999px;
+ padding: 6px 12px;
+ font-size: 0.76rem;
+}
+
+.about-hero-media {
+ min-height: 300px;
+ background-image:
+ linear-gradient(150deg, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0.58)),
+ url('/img/derAustronaut.jpg');
+ background-size: cover;
+ background-position: center;
+ position: relative;
+}
+
+.about-hero-media::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background:
+ radial-gradient(circle at 25% 25%, rgba(0, 113, 227, 0.22), transparent 45%),
+ radial-gradient(circle at 70% 70%, rgba(255, 184, 92, 0.18), transparent 42%);
+}
+
+.about-stats-grid {
+ margin-top: 18px;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: 10px;
+}
+
+.about-stats-grid article {
+ border-radius: 14px;
+ border: 1px solid rgba(255, 255, 255, 0.12);
+ background: rgba(255, 255, 255, 0.03);
+ padding: 12px;
+}
+
+.about-stats-grid h3 {
+ color: #8ec8ff;
+ margin-bottom: 4px;
+}
+
+.about-stats-grid p {
+ color: #aab7c8;
+ font-size: 0.84rem;
+}
+
+.about-cards {
+ margin-top: 20px;
+ gap: 16px;
+}
+
+.about-card {
+ position: relative;
+ overflow: hidden;
+ border-radius: 18px;
+ min-height: 230px;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ padding: 18px;
+ background-size: cover;
+ background-position: center;
+}
+
+.about-card::before {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(175deg, rgba(7, 10, 15, 0.2), rgba(7, 10, 15, 0.82));
+ z-index: 0;
+}
+
+.about-card > * {
+ position: relative;
+ z-index: 1;
+}
+
+.about-card-halls {
+ background-image: url('/img/Zoomania-2.jpg');
+}
+
+.about-card-dbox {
+ background-image: url('/img/shelter.jpg');
+}
+
+.about-card-tech {
+ background-image: url('/img/spidermannewday.jpg');
+}
+
+.about-card p {
+ color: #d7dfeb;
+}
+
+/* Light mode readability improvements */
+body.theme-light .cinema-home {
+ background:
+ radial-gradient(circle at 12% -2%, rgba(0, 113, 227, 0.17), transparent 36%),
+ radial-gradient(circle at 88% 18%, rgba(123, 164, 218, 0.22), transparent 34%),
+ #edf2fb;
+}
+
+body.theme-light .home-band-header h3,
+body.theme-light .section-header h2,
+body.theme-light .list-title,
+body.theme-light .movie-info h3,
+body.theme-light .duration,
+body.theme-light .program-card h2,
+body.theme-light .running-meta h4,
+body.theme-light .snack-info h3,
+body.theme-light #account-view h2,
+body.theme-light #account-tab-content h3,
+body.theme-light .order-item-head h4 {
+ color: #13233c !important;
+}
+
+body.theme-light .home-band-header span,
+body.theme-light .movie-info .genre,
+body.theme-light .program-day-tab small,
+body.theme-light .card-right .description,
+body.theme-light .account-card p,
+body.theme-light .order-box p,
+body.theme-light .order-ticket-grid span,
+body.theme-light .order-ticket-brand,
+body.theme-light .summary-row,
+body.theme-light .vat-row,
+body.theme-light .snack-prompt-box p {
+ color: #4a5d79 !important;
+}
+
+body.theme-light .program-day-tab {
+ border-color: rgba(22, 45, 74, 0.24);
+ background: #f4f8ff;
+ color: #13233c;
+}
+
+body.theme-light .program-day-tab.active {
+ border-color: #0071e3;
+ background: rgba(0, 113, 227, 0.14);
+}
+
+body.theme-light .program-time-row {
+ border-color: rgba(24, 52, 87, 0.2);
+ background: #f5f9ff;
+ color: #13233c;
+}
+
+body.theme-light .program-time-row:hover {
+ background: #ebf3ff;
+}
+
+body.theme-light .hall-pill {
+ color: #144274;
+ border-color: rgba(0, 113, 227, 0.32);
+ background: rgba(0, 113, 227, 0.11);
+}
+
+body.theme-light .time-btn {
+ background: #0071e3;
+ color: #fff;
+}
+
+body.theme-light .category-tabs {
+ background: rgba(255, 255, 255, 0.65);
+ border: 1px solid rgba(26, 51, 83, 0.12);
+ border-radius: 18px;
+ padding: 10px;
+}
+
+body.theme-light .tab-btn {
+ background: #eef4ff;
+ color: #1b2f4d;
+ border-color: rgba(20, 45, 78, 0.2);
+}
+
+body.theme-light .tab-btn.active {
+ background: #0071e3;
+ color: #fff;
+}
+
+body.theme-light .option-group {
+ background: #edf3ff;
+}
+
+body.theme-light .opt-btn {
+ color: #445976;
+}
+
+body.theme-light .opt-btn.active {
+ background: #dbe9ff;
+ color: #11325b;
+}
+
+body.theme-light .size-chip {
+ background: #f4f8ff;
+ color: #122741;
+ border-color: rgba(17, 41, 72, 0.2);
+}
+
+body.theme-light .size-chip span {
+ color: #0057ae;
+}
+
+body.theme-light .size-chip:hover {
+ background: #0071e3;
+ color: #fff;
+}
+
+body.theme-light .size-chip:hover span {
+ color: #fff;
+}
+
+body.theme-light .summary-row-large,
+body.theme-light .total-row,
+body.theme-light #cart-total-right,
+body.theme-light #cart-vat-right,
+body.theme-light #checkout-total-display,
+body.theme-light #checkout-vat-display,
+body.theme-light .col-price {
+ color: #10213a !important;
+}
+
+body.theme-light .order-item-btn.active .order-item-head span {
+ color: #0053aa;
+}
+
+body.theme-light .order-ticket-grid strong,
+body.theme-light .order-item-head span,
+body.theme-light .order-ticket-content h4 {
+ color: #112742;
+}
+
+body.theme-light .about-hero-block {
+ background: linear-gradient(130deg, #f7fbff 0%, #ecf3ff 100%);
+ border-color: rgba(24, 48, 80, 0.14);
+}
+
+body.theme-light .about-hero-content h1,
+body.theme-light .about-stats-grid h3,
+body.theme-light .about-card h3 {
+ color: #122440;
+}
+
+body.theme-light .about-hero-content p,
+body.theme-light .about-stats-grid p,
+body.theme-light .about-card p {
+ color: #455a77;
+}
+
+body.theme-light .about-stats-grid article {
+ background: #ffffff;
+ border-color: rgba(24, 49, 82, 0.14);
+}
+
+body.theme-light .about-card::before {
+ background: linear-gradient(175deg, rgba(245, 250, 255, 0.2), rgba(245, 250, 255, 0.78));
+}
+
+body.theme-light .about-card {
+ border-color: rgba(22, 47, 80, 0.18);
+}
+
+@media (max-width: 980px) {
+ .about-hero-block {
+ grid-template-columns: 1fr;
+ }
+
+ .about-hero-media {
+ min-height: 230px;
+ }
+
+ .about-stats-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+}
diff --git a/tsconfig.app.json b/tsconfig.app.json
new file mode 100644
index 0000000..f580bb3
--- /dev/null
+++ b/tsconfig.app.json
@@ -0,0 +1,5 @@
+{
+ "compilerOptions": {
+ "types": ["node"]
+ }
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 8bf91d3..0b51620 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,5 +1,16 @@
{
"extends": "astro/tsconfigs/strict",
- "include": [".astro/types.d.ts", "**/*"],
- "exclude": ["dist"]
-}
+ "include": [
+ ".astro/types.d.ts",
+ "**/*"
+ ],
+ "exclude": [
+ "dist"
+ ],
+
+ "compilerOptions": {
+ "jsx": "react-jsx",
+ "jsxImportSource": "react",
+ "types": ["node"]
+ }
+}
\ No newline at end of file