Index: itignore
===================================================================
--- .gitignore	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,2 +1,0 @@
-.idea/
-**/.env
Index: .idea/vcs.xml
===================================================================
--- .idea/vcs.xml	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ .idea/vcs.xml	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/finkwave" vcs="Git" />
+  </component>
+</project>
Index: .idea/workspace.xml
===================================================================
--- .idea/workspace.xml	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ .idea/workspace.xml	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AutoImportSettings">
+    <option name="autoReloadType" value="SELECTIVE" />
+  </component>
+  <component name="ChangeListManager">
+    <list default="true" id="d0a1424a-dc09-4978-b407-b0082f1335b6" name="Changes" comment="">
+      <change beforePath="$PROJECT_DIR$/finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Admin.java" beforeDir="false" afterPath="$PROJECT_DIR$/finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Admin.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Users.java" beforeDir="false" afterPath="$PROJECT_DIR$/finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Users.java" afterDir="false" />
+    </list>
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="com.intellij.jpb.JpaEntity" />
+        <option value="Class" />
+      </list>
+    </option>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/finkwave" />
+  </component>
+  <component name="JpbToolWindowState">
+    <option name="isToolWindowVisible" value="false" />
+  </component>
+  <component name="KubernetesApiPersistence"><![CDATA[{}]]></component>
+  <component name="KubernetesApiProvider"><![CDATA[{
+  "isMigrated": true
+}]]></component>
+  <component name="MavenImportPreferences">
+    <option name="generalSettings">
+      <MavenGeneralSettings>
+        <option name="mavenHomeTypeForPersistence" value="WRAPPER" />
+      </MavenGeneralSettings>
+    </option>
+  </component>
+  <component name="ProjectColorInfo"><![CDATA[{
+  "associatedIndex": 2
+}]]></component>
+  <component name="ProjectId" id="38Qsdy3npYDvI6LxhE5QtX5gyuA" />
+  <component name="ProjectViewState">
+    <option name="hideEmptyMiddlePackages" value="true" />
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent"><![CDATA[{
+  "keyToString": {
+    "RequestMappingsPanelOrder0": "0",
+    "RequestMappingsPanelOrder1": "1",
+    "RequestMappingsPanelWidth0": "75",
+    "RequestMappingsPanelWidth1": "75",
+    "RunOnceActivity.ShowReadmeOnStart": "true",
+    "Spring Boot.FinkwaveApplication.executor": "Run",
+    "git-widget-placeholder": "main",
+    "kotlin-language-version-configured": "true",
+    "last_opened_file_path": "/Users/Filip/Desktop/dev/proekti-faks/finkwave/finkwave",
+    "node.js.detected.package.eslint": "true",
+    "node.js.detected.package.tslint": "true",
+    "node.js.selected.package.eslint": "(autodetect)",
+    "node.js.selected.package.tslint": "(autodetect)",
+    "nodejs_package_manager_path": "npm",
+    "settings.editor.selected.configurable": "reference.projectsettings.compiler.annotationProcessors",
+    "vue.rearranger.settings.migration": "true"
+  }
+}]]></component>
+  <component name="RunManager">
+    <configuration name="FinkwaveApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" temporary="true" nameIsGenerated="true">
+      <option name="FRAME_DEACTIVATION_UPDATE_POLICY" value="UpdateClassesAndResources" />
+      <module name="finkwave" />
+      <option name="SPRING_BOOT_MAIN_CLASS" value="com.ukim.finki.develop.finkwave.FinkwaveApplication" />
+      <extension name="coverage">
+        <pattern>
+          <option name="PATTERN" value="com.ukim.finki.develop.finkwave.*" />
+          <option name="ENABLED" value="true" />
+        </pattern>
+      </extension>
+      <method v="2">
+        <option name="Make" enabled="true" />
+      </method>
+    </configuration>
+    <recent_temporary>
+      <list>
+        <item itemvalue="Spring Boot.FinkwaveApplication" />
+      </list>
+    </recent_temporary>
+  </component>
+  <component name="SharedIndexes">
+    <attachedChunks>
+      <set>
+        <option value="bundled-jdk-9823dce3aa75-28b599e66164-intellij.indexing.shared.core-IU-242.26775.15" />
+        <option value="bundled-js-predefined-d6986cc7102b-5c90d61e3bab-JavaScript-IU-242.26775.15" />
+      </set>
+    </attachedChunks>
+  </component>
+  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="d0a1424a-dc09-4978-b407-b0082f1335b6" name="Changes" comment="" />
+      <created>1768743219750</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1768743219750</updated>
+      <workItem from="1768743220798" duration="3532000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="3" />
+  </component>
+  <component name="github-copilot-workspace">
+    <instructionFileLocations>
+      <option value=".github/instructions" />
+    </instructionFileLocations>
+    <promptFileLocations>
+      <option value=".github/prompts" />
+    </promptFileLocations>
+  </component>
+</project>
Index: finkwave/.gitignore
===================================================================
--- finkwave/.gitignore	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ finkwave/.gitignore	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -32,5 +32,3 @@
 ### VS Code ###
 .vscode/
-application*.properties
-
-uploads/profile-pictures/*
+application.properties
Index: finkwave/pom.xml
===================================================================
--- finkwave/pom.xml	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ finkwave/pom.xml	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -61,30 +61,4 @@
 			<artifactId>spring-boot-starter-data-jpa</artifactId>
 		</dependency>
-		<dependency>
-			<groupId>io.jsonwebtoken</groupId>
-			<artifactId>jjwt-api</artifactId>
-			<version>0.11.5</version>
-		</dependency>
-		<dependency>
-			<groupId>io.jsonwebtoken</groupId>
-			<artifactId>jjwt-impl</artifactId>
-			<version>0.11.5</version>
-			<scope>runtime</scope>
-		</dependency>
-		<dependency>
-			<groupId>io.jsonwebtoken</groupId>
-			<artifactId>jjwt-jackson</artifactId>
-			<version>0.11.5</version>
-			<scope>runtime</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework.boot</groupId>
-			<artifactId>spring-boot-starter-security</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework.security</groupId>
-			<artifactId>spring-security-test</artifactId>
-			<scope>test</scope>
-		</dependency>
 	</dependencies>
 
@@ -99,5 +73,4 @@
 							<groupId>org.projectlombok</groupId>
 							<artifactId>lombok</artifactId>
-							<version>${lombok.version}</version>
 						</path>
 					</annotationProcessorPaths>
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/config/AuthProperties.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/config/AuthProperties.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package com.ukim.finki.develop.finkwave.config;
-
-import lombok.Getter;
-import lombok.Setter;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-@Getter @Setter
-@ConfigurationProperties(prefix = "auth")
-public class AuthProperties {
-    private String secret;
-    private int accessTokenMaxAge;
-    private int refreshTokenMaxAge;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/config/SecurityBeans.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/config/SecurityBeans.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,14 +1,0 @@
-package com.ukim.finki.develop.finkwave.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-
-@Configuration
-public class SecurityBeans {
-    @Bean
-    public PasswordEncoder passwordEncoder(){
-        return new BCryptPasswordEncoder(10);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/config/SecurityConfig.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/config/SecurityConfig.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,52 +1,0 @@
-package com.ukim.finki.develop.finkwave.config;
-
-import java.util.List;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
-import org.springframework.security.config.http.SessionCreationPolicy;
-import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.CorsConfigurationSource;
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-
-import com.ukim.finki.develop.finkwave.filters.JwtFilter;
-
-import lombok.RequiredArgsConstructor;
-
-@Configuration
-@RequiredArgsConstructor
-public class SecurityConfig {
-    private final JwtFilter jwtFilter;
-
-    @Bean
-    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
-        http
-                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
-                .csrf(AbstractHttpConfigurer::disable)
-                .authorizeHttpRequests(auth -> auth
-                    .requestMatchers("/auth/user").authenticated()
-                    .anyRequest().permitAll())
-                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
-                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
-                .headers((headers) ->
-                        headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin));
-        return http.build();
-    }
-
-    @Bean
-    public CorsConfigurationSource corsConfigurationSource() {
-        CorsConfiguration configuration = new CorsConfiguration();
-        configuration.setAllowedOriginPatterns(List.of("http://localhost:*"));
-        configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
-        configuration.setAllowedHeaders(List.of("*"));
-        configuration.setAllowCredentials(true);
-        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-        source.registerCorsConfiguration("/**", configuration);
-        return source;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AlbumController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AlbumController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,28 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
-import com.ukim.finki.develop.finkwave.service.AlbumService;
-import lombok.AllArgsConstructor;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@AllArgsConstructor
-@RequestMapping("/albums")
-public class AlbumController {
-    private final AlbumService albumService;
-
-    @GetMapping("/{id}")
-    public HttpEntity<MusicalEntityDto> getAlbum(@PathVariable Long id){
-        return ResponseEntity.ok(albumService.getAlbum(id));
-    }
-
-    @GetMapping("/search")
-    public HttpEntity<List<MusicalEntityDto>> searchAlbums(@RequestParam(name = "q") String searchTerm){
-        return ResponseEntity.ok(albumService.searchAlbums(searchTerm));
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/AuthController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,98 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.web.bind.annotation.CookieValue;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import com.ukim.finki.develop.finkwave.exceptions.InvalidTokenException;
-import com.ukim.finki.develop.finkwave.exceptions.UnauthenticatedException;
-import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.UserResponseDto;
-import com.ukim.finki.develop.finkwave.service.AuthService;
-
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
-
-@RestController
-@RequestMapping("/auth")
-@RequiredArgsConstructor
-public class AuthController {
-    private final AuthProperties authProperties;
-    private final AuthService authService;
-
-    @PostMapping(value = "/register", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public ResponseEntity<Map<String, Object>> register(
-            @ModelAttribute AuthRequestDto authRequestDto,
-            HttpServletResponse httpServletResponse) throws IOException {
-        UserResponseDto userResponseDto = authService.registerAndLogIn(httpServletResponse, authRequestDto);
-        return ResponseEntity.ok(Map.of(
-                "user", userResponseDto,
-                "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
-        ));
-    }
-
-    @PostMapping("/login")
-    public ResponseEntity<Map<String, Object>> login(
-            @RequestBody LoginRequestDto loginRequestDto,
-            HttpServletResponse httpServletResponse) {
-        UserResponseDto userResponseDto = authService.login(httpServletResponse, loginRequestDto);
-        return ResponseEntity.ok(Map.of(
-                "user", userResponseDto,
-                "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
-        ));
-    }
-
-    @PostMapping("/refresh")
-    public ResponseEntity<Map<String, Integer>> refresh(
-            HttpServletResponse httpServletResponse,
-            @CookieValue(name = "refreshToken", required = false) String refreshToken) {
-        if (refreshToken == null) {
-            throw new InvalidTokenException("No refresh token provided.");
-        }
-        authService.refreshAccessTokenAndAddCookie(httpServletResponse, refreshToken);
-        return ResponseEntity.ok(Map.of(
-                "tokenExpiresIn", authProperties.getAccessTokenMaxAge()
-        ));
-    }
-
-    @PostMapping("/logout")
-    public ResponseEntity<Map<String, String>> logout(
-            HttpServletResponse httpServletResponse,
-            @CookieValue(name = "refreshToken", required = false) String refreshToken) {
-        authService.clearCookies(httpServletResponse, refreshToken);
-        SecurityContextHolder.clearContext();
-        return ResponseEntity.ok(Map.of("message", "Successful log out"));
-    }
-
-    @GetMapping("/user")
-    public ResponseEntity<Map<String, Object>> getUser() {
-        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        if (authentication == null || !authentication.isAuthenticated()) {
-            throw new UnauthenticatedException();
-        }
-        Object principal = authentication.getPrincipal();
-        String username = principal instanceof UserDetails userDetails
-                ? userDetails.getUsername()
-                : (principal != null ? principal.toString() : "");
-        UserResponseDto userDto = authService.getUserDtoByUsername(username);
-        return ResponseEntity.ok(Map.of(
-                "tokenExpiresIn", authProperties.getAccessTokenMaxAge(),
-                "user", userDto
-        ));
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/GlobalExceptionHandler.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,105 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import java.util.Map;
-
-import com.ukim.finki.develop.finkwave.exceptions.*;
-import com.ukim.finki.develop.finkwave.repository.PlaylistRepository;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
-import org.springframework.web.multipart.MaxUploadSizeExceededException;
-import org.springframework.web.server.ResponseStatusException;
-
-@RestControllerAdvice
-public class GlobalExceptionHandler {
-    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
-
-    @ExceptionHandler(AuthException.class)
-    public ResponseEntity<Map<String, String>> handleAuthException(AuthException ex) {
-        return ResponseEntity
-                .status(ex.getStatus())
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-    @ExceptionHandler(UsernameNotFoundException.class)
-    public ResponseEntity<Map<String, String>> handleUsernameNotFound(UsernameNotFoundException ex) {
-        return ResponseEntity
-                .status(HttpStatus.UNAUTHORIZED)
-                .body(Map.of("error", "Invalid credentials."));
-    }
-
-    @ExceptionHandler(UserNotFoundException.class)
-    public ResponseEntity<Map<String, String>> handleUserNotFound(UserNotFoundException ex) {
-        return ResponseEntity
-                .status(HttpStatus.NOT_FOUND)
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-    @ExceptionHandler(NotAuthorizedException.class)
-    public ResponseEntity<Map<String, String>> handleNotAuthorizedAction(NotAuthorizedException ex) {
-        return ResponseEntity
-                .status(HttpStatus.UNAUTHORIZED)
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-    @ExceptionHandler(FollowException.class)
-    public ResponseEntity<Map<String, String>> handleSelfFollow(FollowException ex) {
-        return ResponseEntity
-                .status(HttpStatus.BAD_REQUEST)
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-    @ExceptionHandler(AlbumNotFoundException.class)
-    public ResponseEntity<Map<String, String>> handleAlbumNotFound(AlbumNotFoundException ex) {
-        return ResponseEntity
-                .status(HttpStatus.NOT_FOUND)
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-    @ExceptionHandler(MusicalEntityNotFoundException.class)
-    public ResponseEntity<Map<String, String>> handleMusicalEntityNotFound(MusicalEntityNotFoundException ex) {
-        return ResponseEntity
-                .status(HttpStatus.NOT_FOUND)
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-    @ExceptionHandler(PlaylistAlreadyExistsException.class)
-    public ResponseEntity<Map<String, String>> handlePlaylistAlreadyExits(PlaylistAlreadyExistsException ex) {
-        return ResponseEntity
-                .status(HttpStatus.BAD_REQUEST)
-                .body(Map.of("error", ex.getMessage()));
-    }
-
-
-
-    @ExceptionHandler(ResponseStatusException.class)
-    public ResponseEntity<Map<String, String>> handleResponseStatusException(ResponseStatusException ex) {
-        logger.error("Response status error: {}", ex.getMessage());
-        return ResponseEntity
-                .status(ex.getStatusCode())
-                .body(Map.of("error", ex.getReason() != null ? ex.getReason() : "An error occurred."));
-    }
-
-    @ExceptionHandler(MaxUploadSizeExceededException.class)
-    public ResponseEntity<Map<String, Object>> handleMaxSize(MaxUploadSizeExceededException ex) {
-        logger.error("Max upload size error: {}", ex.getMessage());
-        return ResponseEntity
-                .status(HttpStatus.PAYLOAD_TOO_LARGE)
-                .body(Map.of(
-                        "error", "File too large.",
-                        "maxSize", "2MB"
-                ));
-    }
-
-    @ExceptionHandler(Exception.class)
-    public ResponseEntity<Map<String, String>> handleGenericException(Exception ex) {
-        logger.error("Unexpected error occurred: {}", ex.getMessage());
-        return ResponseEntity
-                .status(HttpStatus.INTERNAL_SERVER_ERROR)
-                .body(Map.of("error", "An unexpected error occurred."));
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/MusicalEntityController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/MusicalEntityController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,41 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.LikeStatusDto;
-import com.ukim.finki.develop.finkwave.model.dto.PublishAlbumRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.PublishSongRequestDto;
-import com.ukim.finki.develop.finkwave.service.LikeService;
-import com.ukim.finki.develop.finkwave.service.MusicalEntityService;
-import lombok.AllArgsConstructor;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.io.IOException;
-
-@RestController
-@AllArgsConstructor
-@RequestMapping("/musical-entity")
-public class MusicalEntityController {
-
-    private final LikeService likeService;
-    private final MusicalEntityService musicalEntityService;
-
-    @PostMapping("/{id}/like")
-    public HttpEntity<LikeStatusDto>likeMusicalEntity(@PathVariable(name = "id") Long entityId){
-        return ResponseEntity.ok(likeService.toggleLike(entityId));
-    }
-
-    @PostMapping(value = "/publish/song", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public HttpEntity<?> publishSong(@ModelAttribute PublishSongRequestDto publishSongRequestDto) throws IOException {
-        musicalEntityService.handleSongPublish(publishSongRequestDto);
-        return ResponseEntity.status(HttpStatus.CREATED).build();
-    }
-
-    @PostMapping(value = "/publish/album", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public HttpEntity<?> publishAlbum(@ModelAttribute PublishAlbumRequestDto publishAlbumRequestDto) throws IOException {
-        musicalEntityService.handleAlbumPublish(publishAlbumRequestDto);
-        return ResponseEntity.status(HttpStatus.CREATED).build();
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/NonAdminUserController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/NonAdminUserController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,55 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.FollowStatusDto;
-import com.ukim.finki.develop.finkwave.model.dto.NonAdminUserDto;
-import com.ukim.finki.develop.finkwave.service.FollowService;
-import com.ukim.finki.develop.finkwave.service.NonAdminUserService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@CrossOrigin("*")
-@RequiredArgsConstructor
-@RequestMapping("/users/na/")
-public class NonAdminUserController {
-
-    private final NonAdminUserService nonAdminUserService;
-    private final FollowService followService;
-
-    @GetMapping("/all")
-    public HttpEntity<List<NonAdminUserDto>>getAllNonAdminUsers(){
-        return ResponseEntity.ok(nonAdminUserService.getAllUsers());
-    }
-
-    @GetMapping("/{username}")
-    public HttpEntity<NonAdminUserDto>getNonAdminUserById(@PathVariable String username){
-        return ResponseEntity.ok(nonAdminUserService.getNonAdminUserProfile(username));
-    }
-
-    @GetMapping("/search")
-    public HttpEntity<List<NonAdminUserDto>>searchNonAdminUsers(@RequestParam String name){
-        return ResponseEntity.ok(nonAdminUserService.searchUsers(name));
-    }
-
-    @GetMapping("/{username}/followers")
-    public HttpEntity<List<NonAdminUserDto>>getFollowersForUser(@PathVariable String username){
-        return ResponseEntity.ok(followService.getFollowersForUser(username));
-    }
-
-    @GetMapping("/{username}/following")
-    public HttpEntity<List<NonAdminUserDto>>getFollowingForUser(@PathVariable String username){
-        return ResponseEntity.ok(followService.getFollowingForUser(username));
-    }
-
-    @PostMapping("/{username}/follow")
-    public HttpEntity<FollowStatusDto>followUser(@PathVariable String username){
-
-        return ResponseEntity.ok(followService.toggleFollow(username));
-    }
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/PlaylistController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/PlaylistController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,67 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.BasicPlaylistDto;
-import com.ukim.finki.develop.finkwave.model.dto.PlaylistDto;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.AddSongToPlaylistStatusDto;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.SavePlaylistStatusDto;
-import com.ukim.finki.develop.finkwave.service.PlaylistService;
-import lombok.AllArgsConstructor;
-import org.springframework.data.repository.query.Param;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@AllArgsConstructor
-@RequestMapping("/playlists")
-public class PlaylistController {
-    private final PlaylistService playlistService;
-
-    @GetMapping("/{id}")
-    public HttpEntity<PlaylistDto> getPlaylist(@PathVariable Long id){
-        return ResponseEntity.ok(playlistService.getPlaylist(id));
-    }
-
-    @GetMapping("/user")
-    public HttpEntity<List<BasicPlaylistDto>> getUserBasicPlaylists(){
-        return ResponseEntity.ok(playlistService.getBasicPlaylists());
-    }
-
-    @GetMapping("/song/{songId}")
-    public HttpEntity<List<Long>>getPlaylistIdsThatContainSong(@PathVariable Long songId){
-        return ResponseEntity.ok(playlistService.getPlaylistIdsThatContainSong(songId));
-    }
-
-    @PostMapping("/{playlistId}/song/{songId}")
-    public HttpEntity<AddSongToPlaylistStatusDto>addSongToPlaylist(@PathVariable Long playlistId,
-                                                                   @PathVariable Long songId){
-        return ResponseEntity.ok(playlistService.addSongToPlaylist(playlistId,songId));
-    }
-
-    @PostMapping
-    public ResponseEntity<List<BasicPlaylistDto>> createPlaylist(
-            @RequestParam String playlistName,
-            @RequestParam(required = false) Long songId
-    ) {
-        playlistService.createPlaylist(playlistName,songId);
-
-        return ResponseEntity.ok(playlistService.getBasicPlaylists());
-    }
-
-    @PostMapping("/{id}/save")
-    public HttpEntity<SavePlaylistStatusDto>savePlaylist(@PathVariable Long id) throws Exception {
-        return ResponseEntity.ok(playlistService.savePlaylist(id));
-    }
-
-
-
-    @DeleteMapping("/{id}")
-    public HttpEntity<Void>deletePlaylist(@PathVariable Long id){
-        playlistService.deletePlaylist(id);
-        return ResponseEntity.noContent().build();
-    }
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/ReviewController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/ReviewController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,31 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.ReviewPostDto;
-import com.ukim.finki.develop.finkwave.service.ReviewService;
-import lombok.AllArgsConstructor;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Map;
-
-@RestController
-@RequestMapping("/reviews")
-@AllArgsConstructor
-public class ReviewController {
-    private final ReviewService reviewService;
-
-    @PostMapping("/{songId}")
-    public HttpEntity<Map<String, String>> postReview(@PathVariable Long songId,
-                                                      @RequestBody ReviewPostDto reviewPostDto){
-        reviewService.createReview(songId, reviewPostDto);
-        return ResponseEntity.status(HttpStatus.CREATED).build();
-    }
-
-    @DeleteMapping("/{songId}")
-    public HttpEntity<Void> deleteReview(@PathVariable Long songId){
-        reviewService.deleteReview(songId);
-        return ResponseEntity.noContent().build();
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/SongController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/SongController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,47 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.*;
-import com.ukim.finki.develop.finkwave.repository.SongRepository;
-import com.ukim.finki.develop.finkwave.service.AuthService;
-import com.ukim.finki.develop.finkwave.service.SongService;
-import lombok.AllArgsConstructor;
-import org.springframework.data.repository.query.Param;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@RequestMapping("/songs")
-@AllArgsConstructor
-public class SongController {
-    private final SongService songService;
-
-    @GetMapping("/top")
-    public HttpEntity<List<SongDto>> getSongs(){
-        return ResponseEntity.ok(songService.getTopSongs());
-    }
-
-    @GetMapping("/search")
-    public HttpEntity<List<SongDto>> searchSongs(
-            @RequestParam(name = "q") String searchTerm){
-        return ResponseEntity.ok(songService.searchSongs(searchTerm));
-    }
-
-    @GetMapping("/recent")
-    public HttpEntity<List<BasicSongDto>> getRecentlyListenedSongs(){
-        return ResponseEntity.ok(songService.getRecentlyListened());
-    }
-
-    @GetMapping("/{songId}/details")
-    public HttpEntity<SongDetailsDto> getSongById(@PathVariable Long songId){
-        return ResponseEntity.ok(songService.getSongDetails(songId));
-    }
-
-    @GetMapping("/catalog")
-    public HttpEntity<List<MusicalEntitesByArtistDto>> getArtistCatalog(){
-        List<MusicalEntitesByArtistDto> artistCatalog = songService.getArtistCatalog();
-        return ResponseEntity.ok(artistCatalog);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/TestController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/TestController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,34 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.dto.SongDto;
-import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
-import com.ukim.finki.develop.finkwave.repository.SongRepository;
-import com.ukim.finki.develop.finkwave.repository.UserRepository;
-import lombok.AllArgsConstructor;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@AllArgsConstructor
-@RequestMapping("/test")
-public class TestController {
-    private final SongRepository songRepository;
-    private final UserRepository userRepository;
-
-    @GetMapping("/search/{searchTerm}")
-    public HttpEntity<List<SongDto>> searchSongsTest(@PathVariable String searchTerm){
-        return ResponseEntity.ok(songRepository.searchSongs(null, searchTerm));
-    }
-
-    @GetMapping("/search/u/{searchTerm}")
-    public HttpEntity<List<UserSearchResultDto>> searchUsersTest(@PathVariable String searchTerm){
-        return ResponseEntity.ok(userRepository.searchListeners(searchTerm, 10));
-    }
-    @GetMapping("/search/a/{searchTerm}")
-    public HttpEntity<List<UserSearchResultDto>> searchArtistsTest(@PathVariable String searchTerm){
-        return ResponseEntity.ok(userRepository.searchArtists(searchTerm, 10));
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/UserController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/UserController.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,35 +1,0 @@
-package com.ukim.finki.develop.finkwave.controller;
-
-import com.ukim.finki.develop.finkwave.model.User;
-import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
-import com.ukim.finki.develop.finkwave.model.enums.UserType;
-import com.ukim.finki.develop.finkwave.service.UserService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@CrossOrigin("*")
-@RequiredArgsConstructor
-@RequestMapping("/users")
-public class UserController {
-    private final UserService usersService;
-
-    @GetMapping
-    public HttpEntity<List<User>> getAllUsers(){
-        return ResponseEntity.ok(usersService.getAll());
-    }
-
-    @GetMapping("/search")
-    public HttpEntity<List<UserSearchResultDto>> searchArtists(
-            @RequestParam(name = "type") UserType userType,
-            @RequestParam(name = "q") String searchTerm,
-            @RequestParam(name = "limit", defaultValue = "10") Integer limit)
-            {
-        return ResponseEntity.ok(usersService.search(userType, searchTerm, limit));
-    }
-
-}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/UsersController.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/UsersController.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/controller/UsersController.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,26 @@
+package com.ukim.finki.develop.finkwave.controller;
+
+import com.ukim.finki.develop.finkwave.model.Users;
+import com.ukim.finki.develop.finkwave.service.UsersService;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@RestController
+@CrossOrigin("*")
+public class UsersController {
+    private final UsersService usersService;
+
+    public UsersController(UsersService usersService) {
+        this.usersService = usersService;
+    }
+
+    @GetMapping
+    public HttpEntity<List<Users>> getAllUsers(){
+        return ResponseEntity.ok(usersService.getAll());
+    }
+}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AlbumNotFoundException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AlbumNotFoundException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-public class AlbumNotFoundException extends RuntimeException {
-    public AlbumNotFoundException(Long id) {
-        super(String.format("Cannot find album with id: %d", id));
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AuthException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/AuthException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,16 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public abstract class AuthException extends RuntimeException {
-    
-    public AuthException(String message) {
-        super(message);
-    }
-    
-    public AuthException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public abstract HttpStatus getStatus();
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/FollowException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/FollowException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class FollowException extends RuntimeException{
-
-    public FollowException(String message){
-        super(message);
-    }
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidCredentialsException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidCredentialsException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class InvalidCredentialsException extends AuthException {
-    
-    public InvalidCredentialsException() {
-        super("Invalid credentials.");
-    }
-    
-    public InvalidCredentialsException(String message) {
-        super(message);
-    }
-    
-    @Override
-    public HttpStatus getStatus() {
-        return HttpStatus.UNAUTHORIZED;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidFileException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidFileException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,24 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class InvalidFileException extends AuthException {
-    
-    public InvalidFileException(String message) {
-        super(message);
-    }
-    
-    public static InvalidFileException invalidType() {
-        return new InvalidFileException("Invalid file type. Only images are allowed.");
-    }
-    
-    public static InvalidFileException tooLarge(long maxSizeBytes) {
-        long maxSizeMB = maxSizeBytes / 1_000_000;
-        return new InvalidFileException("File too large. Maximum size is " + maxSizeMB + "MB.");
-    }
-    
-    @Override
-    public HttpStatus getStatus() {
-        return HttpStatus.BAD_REQUEST;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidTokenException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/InvalidTokenException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class InvalidTokenException extends AuthException {
-    
-    public InvalidTokenException() {
-        super("Invalid or expired token.");
-    }
-    
-    public InvalidTokenException(String message) {
-        super(message);
-    }
-    
-    @Override
-    public HttpStatus getStatus() {
-        return HttpStatus.UNAUTHORIZED;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/MusicalEntityNotFoundException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/MusicalEntityNotFoundException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-public class MusicalEntityNotFoundException extends RuntimeException{
-    public MusicalEntityNotFoundException(String message) {
-        super(message);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/NotAuthorizedException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/NotAuthorizedException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-public class NotAuthorizedException extends RuntimeException {
-    public NotAuthorizedException(String message) {
-        super(message);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/PlaylistAlreadyExistsException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/PlaylistAlreadyExistsException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-public class PlaylistAlreadyExistsException extends RuntimeException {
-    public PlaylistAlreadyExistsException(String message) {
-        super(message);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/PlaylistNotFoundException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/PlaylistNotFoundException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,7 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-public class PlaylistNotFoundException extends RuntimeException {
-    public PlaylistNotFoundException(Long id) {
-        super(String.format("Cannot find playlist with id: %d",id));
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UnauthenticatedException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UnauthenticatedException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class UnauthenticatedException extends AuthException {
-    
-    public UnauthenticatedException() {
-        super("User not authenticated.");
-    }
-    
-    public UnauthenticatedException(String message) {
-        super(message);
-    }
-    
-    @Override
-    public HttpStatus getStatus() {
-        return HttpStatus.UNAUTHORIZED;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserAlreadyExistsException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserAlreadyExistsException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class UserAlreadyExistsException extends AuthException {
-    
-    public UserAlreadyExistsException(String username) {
-        super("Username '" + username + "' is already taken.");
-    }
-    public UserAlreadyExistsException() {
-        super("Username is already taken.");
-    }
-    
-    @Override
-    public HttpStatus getStatus() {
-        return HttpStatus.CONFLICT;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserNotFoundException.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/exceptions/UserNotFoundException.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.ukim.finki.develop.finkwave.exceptions;
-
-import org.springframework.http.HttpStatus;
-
-public class UserNotFoundException extends AuthException {
-    
-    public UserNotFoundException() {
-        super("User not found.");
-    }
-    
-    public UserNotFoundException(String message) {
-        super(message);
-    }
-    
-    @Override
-    public HttpStatus getStatus() {
-        return HttpStatus.NOT_FOUND;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/filters/JwtFilter.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/filters/JwtFilter.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,71 +1,0 @@
-package com.ukim.finki.develop.finkwave.filters;
-
-import com.ukim.finki.develop.finkwave.service.CustomUserDetailsService;
-import com.ukim.finki.develop.finkwave.service.JwtService;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.ExpiredJwtException;
-import io.jsonwebtoken.JwtException;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-import org.springframework.http.HttpStatus;
-
-import java.io.IOException;
-
-@Component
-@RequiredArgsConstructor
-public class JwtFilter extends OncePerRequestFilter {
-    private final CustomUserDetailsService userDetailsService;
-    private final JwtService jwtService;
-
-    @Override
-    protected void doFilterInternal(
-            @NonNull HttpServletRequest request,
-            @NonNull HttpServletResponse response,
-            @NonNull FilterChain filterChain) throws ServletException, IOException {
-        
-        String token = null;
-        if (request.getCookies() != null){
-            for (Cookie cookie: request.getCookies()){
-                if ("accessToken".equals(cookie.getName())){
-                    token = cookie.getValue();
-                    break;
-                }
-            }
-        }
-        if (token != null && !token.isEmpty()){
-            try {
-                Claims claims = jwtService.extractClaims(token);
-                String username = claims.getSubject();
-                if (username != null && SecurityContextHolder.getContext().getAuthentication() == null){
-                    UserDetails userDetails = userDetailsService.loadUserByUsername(username);
-                    UsernamePasswordAuthenticationToken authToken =
-                            new UsernamePasswordAuthenticationToken(username, null, userDetails.getAuthorities());
-                    SecurityContextHolder.getContext().setAuthentication(authToken);
-                }
-            } catch (ExpiredJwtException e){
-                System.out.println("Expired jwt token.");
-                response.setStatus(HttpStatus.UNAUTHORIZED.value());
-                return;
-            } catch (JwtException e){
-                System.out.println("Invalid jwt token.");
-                response.setStatus(HttpStatus.UNAUTHORIZED.value());
-                return;
-            } catch (Exception e){
-                System.out.println(e.getMessage());
-                response.setStatus(HttpStatus.UNAUTHORIZED.value());
-                return;
-            }
-        }
-        filterChain.doFilter(request, response);
-    }
-}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Admin.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Admin.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Admin.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -1,19 +1,10 @@
 package com.ukim.finki.develop.finkwave.model;
 
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.MapsId;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.Table;
+import jakarta.persistence.*;
 import lombok.Getter;
+import lombok.Setter;
 
 @Entity
 @Table(name = "admins", schema = "project")
-@Getter
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
 public class Admin {
     @Id
@@ -22,7 +13,7 @@
 
     @MapsId
-    @OneToOne
+    @OneToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "user_id")
-    private User user;
+    private Users users;
 
 }
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Album.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Album.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,35 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.MapsId;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.Table;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "albums", schema = "project")
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
-public class Album {
-    @Id
-    @Column(name = "id", nullable = false)
-    private Long id;
-
-    @MapsId
-    @OneToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "id", nullable = false)
-    private MusicalEntity musicalEntities;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Artist.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Artist.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,35 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.MapsId;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.Table;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "artists", schema = "project")
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
-public class Artist {
-    @Id
-    @Column(name = "user_id", nullable = false)
-    private Long id;
-
-    @MapsId
-    @OneToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "user_id", nullable = false)
-    private NonAdminUser nonAdminUser;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ArtistContribution.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ArtistContribution.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,32 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "artist_contributions", schema = "project")
-public class ArtistContribution {
-    @EmbeddedId
-    private ArtistContributionId id;
-
-    @MapsId("artistId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "artist_id", nullable = false)
-    private Artist artist;
-
-    @MapsId("musicalEntityId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "musical_entity_id", nullable = false)
-    private MusicalEntity musicalEntity;
-
-    @Column(name = "role", nullable = false, length = Integer.MAX_VALUE)
-    private String role;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ArtistContributionId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ArtistContributionId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-public class ArtistContributionId implements Serializable {
-    private static final long serialVersionUID = -3193987026608380950L;
-    @Column(name = "artist_id", nullable = false)
-    private Long artistId;
-
-    @Column(name = "musical_entity_id", nullable = false)
-    private Long musicalEntityId;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        ArtistContributionId entity = (ArtistContributionId) o;
-        return Objects.equals(this.artistId, entity.artistId) &&
-                Objects.equals(this.musicalEntityId, entity.musicalEntityId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(artistId, musicalEntityId);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Event.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Event.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,40 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-import java.time.LocalDate;
-import java.time.LocalTime;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "events", schema = "project")
-public class Event {
-    @Id
-    @Column(name = "event_id", nullable = false)
-    private Long id;
-
-    @Column(nullable = false, length = Integer.MAX_VALUE)
-    private String name;
-
-    @Column( nullable = false, length = Integer.MAX_VALUE)
-    private String location;
-
-    @Column(nullable = false, length = Integer.MAX_VALUE)
-    private String venue;
-
-    @Column(nullable = false)
-    private LocalDate date;
-
-    @Column(nullable = false)
-    private LocalTime time;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "creator_id")
-    private User creatorUser;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/EventProjection.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/EventProjection.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-public interface EventProjection {
-    String getLocation();
-    String getVenue();
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Follow.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Follow.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@NoArgsConstructor
-@Table(name = "follows", schema = "project")
-public class Follow {
-    @EmbeddedId
-    private FollowId id;
-
-    @MapsId("follower")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "follower", nullable = false)
-    private NonAdminUser follower;
-
-    @MapsId("followee")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "followee", nullable = false)
-    private NonAdminUser followee;
-
-    public Follow(NonAdminUser follower,NonAdminUser followee){
-        this.follower=follower;
-        this.followee=followee;
-        this.id=new FollowId(follower.getId(),followee.getId());
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/FollowId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/FollowId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,41 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-@NoArgsConstructor
-@AllArgsConstructor
-public class FollowId implements Serializable {
-    private static final long serialVersionUID = -915670330063692538L;
-    @Column(name = "follower", nullable = false)
-    private Long follower;
-
-    @Column(name = "followee", nullable = false)
-    private Long followee;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        FollowId entity = (FollowId) o;
-        return Objects.equals(this.follower, entity.follower) &&
-                Objects.equals(this.followee, entity.followee);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(follower, followee);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Like.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Like.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,36 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@NoArgsConstructor
-@Table(name = "likes", schema = "project")
-public class Like {
-    @EmbeddedId
-    private LikeId id;
-
-    @MapsId("listenerId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "listener_id", nullable = false)
-    private Listener listener;
-
-    @MapsId("musicalEntityId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "musical_entity_id", nullable = false)
-    private MusicalEntity musicalEntity;
-
-    public Like(MusicalEntity musicalEntity, Listener listener) {
-        this.musicalEntity = musicalEntity;
-        this.listener = listener;
-        this.id=new LikeId(listener.getId(),musicalEntity.getId());
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/LikeId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/LikeId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,41 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-@AllArgsConstructor
-@NoArgsConstructor
-public class LikeId implements Serializable {
-    private static final long serialVersionUID = -2521356135522333223L;
-    @Column(name = "listener_id", nullable = false)
-    private Long listenerId;
-
-    @Column(name = "musical_entity_id", nullable = false)
-    private Long musicalEntityId;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        LikeId entity = (LikeId) o;
-        return Objects.equals(this.listenerId, entity.listenerId) &&
-                Objects.equals(this.musicalEntityId, entity.musicalEntityId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(listenerId, musicalEntityId);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Listen.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Listen.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,32 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "listens", schema = "project")
-public class Listen {
-    @EmbeddedId
-    private ListenId id;
-
-    @MapsId("listenerId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @JsonIgnore
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "listener_id", nullable = false)
-    private Listener listener;
-
-    @MapsId("songId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @JsonIgnore
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "song_id", nullable = false)
-    private Song song;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ListenId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ListenId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,44 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.time.LocalDateTime;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-public class ListenId implements Serializable {
-    @Serial
-    private static final long serialVersionUID = 7485589950837124664L;
-    @Column(name = "listener_id", nullable = false)
-    private Long listenerId;
-
-    @Column(name = "song_id", nullable = false)
-    private Long songId;
-
-    @Column(name = "timestamp", nullable = false)
-    private LocalDateTime timestamp;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        ListenId entity = (ListenId) o;
-        return Objects.equals(this.listenerId, entity.listenerId) &&
-                Objects.equals(this.songId, entity.songId) &&
-                Objects.equals(this.timestamp, ((ListenId) o).timestamp);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(listenerId, songId, timestamp);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Listener.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Listener.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,35 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.Id;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.MapsId;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.Table;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "listeners", schema = "project")
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
-public class Listener {
-    @Id
-    @Column(name = "user_id", nullable = false)
-    private Long id;
-
-    @MapsId
-    @OneToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "user_id", nullable = false)
-    private NonAdminUser nonAdminUser;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/MusicalEntity.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/MusicalEntity.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,43 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import java.time.LocalDate;
-
-import jakarta.persistence.*;
-import lombok.*;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "musical_entities", schema = "project")
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class MusicalEntity {
-    @Id
-    @Column(name = "id", nullable = false)
-    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "musical_entity_id_gen")
-    @SequenceGenerator(name = "musical_entity_id_gen", sequenceName = "musical_entities_id_seq", allocationSize = 1)
-    private Long id;
-
-    @Column(name = "title", nullable = false, length = Integer.MAX_VALUE)
-    private String title;
-
-    @Column(name = "genre", nullable = false, length = Integer.MAX_VALUE)
-    private String genre;
-
-    @Column(name = "release_date", nullable = false)
-    private LocalDate releaseDate;
-
-    private String cover;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "released_by")
-    private Artist releasedBy;
-
-}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/NonAdminUser.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/NonAdminUser.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/NonAdminUser.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -4,5 +4,4 @@
 import lombok.Getter;
 import lombok.Setter;
-import org.hibernate.annotations.Cascade;
 
 @Getter
@@ -16,7 +15,7 @@
 
     @MapsId
-    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
+    @OneToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "user_id")
-    private User user;
+    private Users users;
 
 }
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PerformsAt.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PerformsAt.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,29 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "performs_at", schema = "project")
-public class PerformsAt {
-    @EmbeddedId
-    private PerformsAtId id;
-
-    @MapsId("eventId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "event_id", nullable = false)
-    private Event event;
-
-    @MapsId("artistId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "artist_id", nullable = false)
-    private Artist artist;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PerformsAtId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PerformsAtId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-public class PerformsAtId implements Serializable {
-    private static final long serialVersionUID = 1686751772857702507L;
-    @Column(name = "event_id", nullable = false)
-    private Long eventId;
-
-    @Column(name = "artist_id", nullable = false)
-    private Long artistId;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        PerformsAtId entity = (PerformsAtId) o;
-        return Objects.equals(this.eventId, entity.eventId) &&
-                Objects.equals(this.artistId, entity.artistId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(eventId, artistId);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Playlist.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Playlist.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,42 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.NoArgsConstructor;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "playlists", schema = "project")
-@NoArgsConstructor
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
-public class Playlist {
-    @Id
-    @Column(name = "playlist_id", nullable = false)
-    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "playlist_seq_gen")
-    @SequenceGenerator(name = "playlist_seq_gen", sequenceName = "project.playlists_seq", schema = "project", allocationSize = 1)
-    private Long id;
-
-    @Column(name = "cover", length = Integer.MAX_VALUE)
-    private String cover;
-
-    @Column(name = "name", nullable = false, length = Integer.MAX_VALUE)
-    private String name;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "created_by")
-    private Listener createdBy;
-
-    public Playlist(String cover, String name, Listener createdBy) {
-        this.cover = cover;
-        this.name = name;
-        this.createdBy = createdBy;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PlaylistSong.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PlaylistSong.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@NoArgsConstructor
-@Table(name = "playlist_songs", schema = "project")
-public class PlaylistSong {
-    @EmbeddedId
-    private PlaylistSongId id;
-
-    @MapsId("songId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "song_id", nullable = false)
-    private Song song;
-
-    @MapsId("playlistId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "playlist_id", nullable = false)
-    private Playlist playlist;
-
-    public PlaylistSong(PlaylistSongId id, Song song, Playlist playlist) {
-        this.id = id;
-        this.song = song;
-        this.playlist = playlist;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PlaylistSongId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/PlaylistSongId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,45 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-@NoArgsConstructor
-public class PlaylistSongId implements Serializable {
-    private static final long serialVersionUID = -1096457880126729057L;
-    @Column(name = "song_id", nullable = false)
-    private Long songId;
-
-    @Column(name = "playlist_id", nullable = false)
-    private Long playlistId;
-
-    public PlaylistSongId(Long songId, Long playlistId) {
-        this.songId = songId;
-        this.playlistId = playlistId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        PlaylistSongId entity = (PlaylistSongId) o;
-        return Objects.equals(this.playlistId, entity.playlistId) &&
-                Objects.equals(this.songId, entity.songId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(playlistId, songId);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/RefreshToken.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/RefreshToken.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,28 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.time.Instant;
-
-@Entity
-@Getter @Setter
-@Table(name = "refresh_token")
-public class RefreshToken {
-    @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @Column(nullable = false, unique = true)
-    private String token;
-
-    @ManyToOne
-    @JoinColumn(name = "user_id", nullable = false)
-    private User user;
-
-    @Column(name = "expires_at")
-    private Instant expiresAt;
-
-    private boolean revoked = false;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Review.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Review.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,35 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "reviews", schema = "project")
-public class Review {
-    @EmbeddedId
-    private ReviewId id;
-
-    @MapsId("listenerId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "listener_id", nullable = false)
-    private Listener listener;
-
-    @MapsId("musicalEntityId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "musical_entity_id", nullable = false)
-    private MusicalEntity musicalEntity;
-
-    @Column(name = "grade", nullable = false)
-    private Integer grade;
-
-    @Column(name = "comment", length = Integer.MAX_VALUE)
-    private String comment;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ReviewId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/ReviewId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-public class ReviewId implements Serializable {
-    private static final long serialVersionUID = -747031476754115455L;
-    @Column(name = "listener_id", nullable = false)
-    private Long listenerId;
-
-    @Column(name = "musical_entity_id", nullable = false)
-    private Long musicalEntityId;
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        ReviewId entity = (ReviewId) o;
-        return Objects.equals(this.listenerId, entity.listenerId) &&
-                Objects.equals(this.musicalEntityId, entity.musicalEntityId);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(listenerId, musicalEntityId);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Role.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Role.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-public enum Role {
-    ADMIN,
-    NONADMIN
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/SavedPlaylist.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/SavedPlaylist.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,36 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@NoArgsConstructor
-@Table(name = "saved_playlists", schema = "project")
-public class SavedPlaylist {
-    @EmbeddedId
-    private SavedPlaylistId id;
-
-    @MapsId("listenerId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "listener_id", nullable = false)
-    private Listener listener;
-
-    @MapsId("playlistId")
-    @ManyToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "playlist_id", nullable = false)
-    private Playlist playlist;
-
-    public SavedPlaylist( Listener listener, Playlist playlist) {
-        this.id=new SavedPlaylistId(listener.getId(),playlist.getId());
-        this.listener = listener;
-        this.playlist = playlist;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/SavedPlaylistId.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/SavedPlaylistId.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,46 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Embeddable;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.hibernate.Hibernate;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-@Getter
-@Setter
-@Embeddable
-@NoArgsConstructor
-public class SavedPlaylistId implements Serializable {
-    private static final long serialVersionUID = 678748242066896235L;
-    @Column(name = "listener_id", nullable = false)
-    private Long listenerId;
-
-    @Column(name = "playlist_id", nullable = false)
-    private Long playlistId;
-
-    public SavedPlaylistId(Long listenerId, Long playlistId) {
-        this.listenerId = listenerId;
-        this.playlistId = playlistId;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
-        SavedPlaylistId entity = (SavedPlaylistId) o;
-        return Objects.equals(this.playlistId, entity.playlistId) &&
-                Objects.equals(this.listenerId, entity.listenerId);
-    }
-
-
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(playlistId, listenerId);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Song.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Song.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,34 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import jakarta.persistence.*;
-import lombok.Getter;
-import lombok.Setter;
-import org.hibernate.annotations.OnDelete;
-import org.hibernate.annotations.OnDeleteAction;
-
-@Getter
-@Setter
-@Entity
-@Table(name = "songs", schema = "project")
-public class Song {
-    @Id
-    @Column(name = "id", nullable = false)
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
-    private Long id;
-
-    @MapsId
-    @OneToOne(fetch = FetchType.LAZY, optional = false)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "id", nullable = false)
-    private MusicalEntity musicalEntities;
-
-    @ManyToOne(fetch = FetchType.LAZY)
-    @OnDelete(action = OnDeleteAction.CASCADE)
-    @JoinColumn(name = "album_id")
-    private Album album;
-
-    @Column(name = "link", nullable = false, length = Integer.MAX_VALUE)
-    private String link;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/User.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/User.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,60 +1,0 @@
-package com.ukim.finki.develop.finkwave.model;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-import jakarta.persistence.*;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Setter
-@Getter
-@Entity
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@Table(name = "users")
-@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
-public class User {
-    @Id
-    @Column(name = "user_id", nullable = false)
-    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users_id_seq")
-    private Long id;
-
-    @Column(name = "full_name", nullable = false, length = Integer.MAX_VALUE)
-    private String fullName;
-
-    @Column(nullable = false, length = Integer.MAX_VALUE)
-    private String email;
-
-    @Column(nullable = false, length = Integer.MAX_VALUE)
-    @JsonIgnore
-    private String password;
-
-    @Column(nullable = false, length = Integer.MAX_VALUE)
-    private String username;
-
-    @Column(nullable = false)
-    private boolean artist;
-
-    @Column(nullable = false)
-    private boolean listener;
-
-    @Column(name = "profile_photo", length = Integer.MAX_VALUE)
-    private String profilePhoto;
-
-    @OneToOne(mappedBy = "user")
-    @JsonIgnore
-    private Admin admin;
-
-    @Enumerated(EnumType.STRING)
-    private Role role;
-
-    @OneToOne(mappedBy = "user", orphanRemoval = true)
-    @JsonIgnore
-    private NonAdminUser nonAdminUser;
-
-}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Users.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Users.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/Users.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,102 @@
+package com.ukim.finki.develop.finkwave.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Entity
+@NoArgsConstructor
+public class Users {
+    @Id
+    @Column(name = "user_id", nullable = false)
+    private Long id;
+
+    @Column(name = "full_name", nullable = false, length = Integer.MAX_VALUE)
+    private String fullName;
+
+    @Column(name = "email", nullable = false, length = Integer.MAX_VALUE)
+    private String email;
+
+    @Column(name = "password", nullable = false, length = Integer.MAX_VALUE)
+    @JsonIgnore
+    private String password;
+
+    @Column(name = "username", nullable = false, length = Integer.MAX_VALUE)
+    private String username;
+
+    @Column(name = "profile_photo", length = Integer.MAX_VALUE)
+    private String profilePhoto;
+
+    @OneToOne(mappedBy = "users")
+    @JsonIgnore
+    private Admin admin;
+
+    @OneToOne(mappedBy = "users")
+    @JsonIgnore
+    private NonAdminUser nonAdminUser;
+
+    public NonAdminUser getNonAdminUser() {
+        return nonAdminUser;
+    }
+
+    public void setNonAdminUser(NonAdminUser nonAdminUser) {
+        this.nonAdminUser = nonAdminUser;
+    }
+
+    public Admin getAdmin() {
+        return admin;
+    }
+
+    public void setAdmin(Admin admin) {
+        this.admin = admin;
+    }
+
+    public String getProfilePhoto() {
+        return profilePhoto;
+    }
+
+    public void setProfilePhoto(String profilePhoto) {
+        this.profilePhoto = profilePhoto;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public String getFullName() {
+        return fullName;
+    }
+
+    public void setFullName(String fullName) {
+        this.fullName = fullName;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/AlbumDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/AlbumDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.util.List;
-
-@Getter
-@Setter
-@AllArgsConstructor
-public class AlbumDto extends MusicalEntityDto{
-    private List<SongWithLinkDto>songs;
-
-    public AlbumDto(Long id, String title, String genre, String type, String releasedBy, String artistUsername, String cover, Boolean isLikedByCurrentUser) {
-        super(id, title, genre, type, releasedBy, artistUsername, cover, isLikedByCurrentUser);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/AlbumSongsDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/AlbumSongsDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import java.util.List;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class AlbumSongsDto {
-    private String title;
-    private String link;
-    private List<ArtistContributionSummaryDto> contributors;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistContributionDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistContributionDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-@AllArgsConstructor
-public class ArtistContributionDto {
-    private Long id;
-    private String title;
-    private String genre;
-    private String role;
-    private String entityType;
-    private Boolean isLikedByCurrentUser;
-    private String cover;
-    private String link;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistContributionSummaryDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistContributionSummaryDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,22 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-// this dto is useful when we already have all the necessary info for the song and just need the contribution info
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class ArtistContributionSummaryDto {
-    Long id = null;
-    private String artistName;
-    private String role;
-
-    public ArtistContributionSummaryDto(String artistName, String role) {
-        this.artistName = artistName;
-        this.role = role;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import java.util.List;
-
-@Getter
-@Setter
-public class ArtistDto extends NonAdminUserDto {
-    private List<ArtistContributionDto> contributions;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistMusicalEntitiesDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ArtistMusicalEntitiesDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,16 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-import java.util.List;
-
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-public class ArtistMusicalEntitiesDto {
-    private List<ArtistContributionDto> contributions;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/AuthRequestDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/AuthRequestDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,16 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import com.ukim.finki.develop.finkwave.model.enums.UserType;
-import jakarta.annotation.Nullable;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.ArrayList;
-
-public record AuthRequestDto(
-        String username,
-        String fullname,
-        String email,
-        String password,
-        ArrayList<UserType> userType,
-        @Nullable MultipartFile profilePhoto){
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/BasicPlaylistDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/BasicPlaylistDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,8 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-
-public record BasicPlaylistDto(
-    Long id,
-    String name,
-    String cover,
-    Long songCount){}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/BasicSongDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/BasicSongDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import jakarta.annotation.Nullable;
-
-public record BasicSongDto (
-    Long id,
-    String title,
-    String artist,
-    String artistUsername,
-    String link,
-    @Nullable String cover
-){}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ListenerDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ListenerDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,14 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import java.util.List;
-
-@Getter
-@Setter
-public class ListenerDto extends NonAdminUserDto {
-    private List<MusicalEntityDto> likedEntities;
-    private List<PlaylistDto> createdPlaylists;
-    private List<PlaylistDto>savedPlaylists;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ListenerLikesDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ListenerLikesDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,16 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-import java.util.*;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Setter
-@Getter
-@AllArgsConstructor
-@NoArgsConstructor
-public class ListenerLikesDto {
-    private List<MusicalEntityDto> likedEntities;
-    
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/LoginRequestDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/LoginRequestDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-public record LoginRequestDto(
-        String username,
-        String password){
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/MusicalEntitesByArtistDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/MusicalEntitesByArtistDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-import java.time.LocalDate;
-
-@AllArgsConstructor
-@Getter
-@Setter
-@NoArgsConstructor
-public class MusicalEntitesByArtistDto {
-    private Long id;
-    private String title;
-    private String genre;
-    private String type;
-    private String cover;
-    private LocalDate releaseDate;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/MusicalEntityDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/MusicalEntityDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@AllArgsConstructor
-@Getter
-@Setter
-@NoArgsConstructor
-public class MusicalEntityDto {
-    private Long id;
-    private String title;
-    private String genre;
-    private String type;
-    private String releasedBy;
-    private String artistUsername;
-    private String cover;
-    private Boolean isLikedByCurrentUser;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/NonAdminUserDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/NonAdminUserDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,20 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.Getter;
-import lombok.Setter;
-
-
-@Getter
-@Setter
-
-public  class NonAdminUserDto {
-    private String username;
-    private String fullName;
-    private String profilePhoto;
-    private String userType;
-    private Long followers;
-    private Long following;
-    private Boolean isFollowedByCurrentUser;
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/PlaylistDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/PlaylistDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.Setter;
-
-import java.util.List;
-
-@AllArgsConstructor
-@Getter
-@Setter
-public class PlaylistDto {
-    private Long id;
-    private String name;
-    private String cover;
-    private String creatorName;
-    private String creatorUsername;
-    private List<SongWithLinkDto>songsInPlaylist;
-    private Boolean isSavedByCurrentUser;
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/PublishAlbumRequestDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/PublishAlbumRequestDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,24 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import java.util.List;
-
-import org.springframework.web.multipart.MultipartFile;
-
-import jakarta.annotation.Nullable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class PublishAlbumRequestDto {
-    private String title;
-    private String genre;
-    private String link;
-    @Nullable
-    private MultipartFile cover;
-    private List<AlbumSongsDto> albumSongs;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/PublishSongRequestDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/PublishSongRequestDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,23 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import jakarta.annotation.Nullable;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.List;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class PublishSongRequestDto {
-    private String title;
-    private String genre;
-    private String link;
-    @Nullable
-    private MultipartFile cover;
-    private List<ArtistContributionSummaryDto> contributors;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ReviewDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ReviewDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,15 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import com.ukim.finki.develop.finkwave.model.ReviewId;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-@Getter
-@AllArgsConstructor
-public class ReviewDto {
-    private ReviewId id;
-    private String author;
-    private String authorUsername;
-    private Integer grade;
-    private String comment;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ReviewPostDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/ReviewPostDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-@Getter
-@AllArgsConstructor
-public class ReviewPostDto {
-    private int grade;
-    private String comment;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/SongDetailsDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/SongDetailsDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,17 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-import java.util.List;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-public class SongDetailsDto extends SongDto{
-    private List<ArtistContributionSummaryDto> contributions;
-    private List<ReviewDto> reviews;
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/SongDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/SongDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@NoArgsConstructor
-public class SongDto extends MusicalEntityDto{
-    private String link;
-    private String album;
-    private Long albumId;
-
-    public SongDto(Long id, String title, String genre, String type, String releasedBy, String artistUsername, String cover, Boolean isLikedByCurrentUser, String album, Long albumId, String link) {
-        super(id, title, genre, type, releasedBy, artistUsername, cover, isLikedByCurrentUser);
-        this.link = link;
-        this.album = album;
-        this.albumId = albumId;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/SongWithLinkDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/SongWithLinkDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,19 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-@Getter
-@Setter
-@AllArgsConstructor
-@NoArgsConstructor
-public class SongWithLinkDto extends MusicalEntityDto {
-    String link;
-
-    public SongWithLinkDto(Long id, String title, String genre, String type, String releasedBy, String artistUsername, String cover, Boolean isLikedByCurrentUser, String link) {
-        super(id, title, genre, type, releasedBy, artistUsername, cover, isLikedByCurrentUser);
-        this.link = link;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/UserResponseDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/UserResponseDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-import jakarta.annotation.Nullable;
-import lombok.Builder;
-
-@Builder
-public record UserResponseDto(
-        String fullname,
-        String username,
-        @Nullable String profilePhoto,
-        Boolean isAdmin,
-        @Nullable Boolean isArtist
-){}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/UserSearchResultDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/UserSearchResultDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto;
-
-
-public record UserSearchResultDto(
-        Long id,
-        String fullName,
-        String username,
-        String profilePhoto
-){}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/AddSongToPlaylistStatusDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/AddSongToPlaylistStatusDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,4 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto.statusDto;
-
-public record AddSongToPlaylistStatusDto(Long playlistId, Boolean isSongAddedToPlaylist) {
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/FollowStatusDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/FollowStatusDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,4 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto.statusDto;
-
-public record FollowStatusDto(boolean isFollowing, Long followerCount, Long followingCount)
-{ }
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/LikeStatusDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/LikeStatusDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,4 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto.statusDto;
-
-public record LikeStatusDto(Long entityId,Boolean isLiked, String type) {
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/SavePlaylistStatusDto.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/dto/statusDto/SavePlaylistStatusDto.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,4 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.dto.statusDto;
-
-public record SavePlaylistStatusDto(Long id, Boolean isSavedByCurrentUser) {
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/model/enums/UserType.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/model/enums/UserType.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,6 +1,0 @@
-package com.ukim.finki.develop.finkwave.model.enums;
-
-public enum UserType {
-    LISTENER,
-    ARTIST
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/AdminRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/AdminRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,9 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.Admin;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface AdminRepository extends JpaRepository<Admin, Long> {
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/AlbumRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/AlbumRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,30 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Album;
-
-import java.util.List;
-
-@Repository
-public interface AlbumRepository extends JpaRepository<Album, Long> {
-
-    List<Album>findAllByIdIn(List<Long>ids);
-
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto(
-            a.id, me.title, me.genre, 'ALBUM', u.fullName, u.username, me.cover, FALSE )
-        FROM Album a
-        JOIN a.musicalEntities me
-        JOIN me.releasedBy rb
-        JOIN rb.nonAdminUser nau
-        JOIN nau.user u
-        WHERE me.title ILIKE '%' || :searchTerm || '%'
-    """)
-    List<MusicalEntityDto> searchAlbums(@Param("currentUserId")Long currentUserId, @Param("searchTerm") String searchTerm);
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ArtistContributionRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ArtistContributionRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,44 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import java.util.List;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.ArtistContribution;
-import com.ukim.finki.develop.finkwave.model.ArtistContributionId;
-import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionDto;
-import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionSummaryDto;
-
-@Repository
-public interface ArtistContributionRepository extends JpaRepository<ArtistContribution, ArtistContributionId> {
-
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.ArtistContributionDto(
-            ac.musicalEntity.id, ac.musicalEntity.title, ac.musicalEntity.genre, ac.role,
-            (CASE WHEN s.id IS NOT NULL THEN 'SONG'
-                  WHEN a.id IS NOT NULL THEN 'ALBUM'
-                  ELSE 'Unknown' END),
-            (CASE WHEN l.id IS NOT NULL THEN true ELSE false END),
-            ac.musicalEntity.cover,
-            s.link)
-        FROM ArtistContribution ac
-        LEFT JOIN Song s  ON s.musicalEntities.id=ac.musicalEntity.id
-        LEFT JOIN Album a ON a.musicalEntities.id=ac.musicalEntity.id
-        LEFT JOIN Like l ON l.musicalEntity.id=ac.musicalEntity.id AND l.listener.id=:currentUserId
-        WHERE ac.artist.id=:artistId
-        """)
-    List<ArtistContributionDto>findContributionsByArtistId(@Param("currentUserId")Long currentUserId,@Param("artistId")Long artistId);
-
-
-    @Query("""
-    SELECT NEW com.ukim.finki.develop.finkwave.model.dto.ArtistContributionSummaryDto(
-    ac.artist.nonAdminUser.user.fullName, ac.role
-    )
-    FROM ArtistContribution ac
-    WHERE ac.id.musicalEntityId = :songId
-    """)
-    List<ArtistContributionSummaryDto> findContributionsBySongId(@Param("songId")Long songId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ArtistRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ArtistRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,32 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import java.util.Optional;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Artist;
-
-@Repository
-public interface ArtistRepository extends JpaRepository<Artist, Long> {
-
-    @Query("""
-        SELECT DISTINCT a FROM Artist a
-        JOIN FETCH a.nonAdminUser nu
-        JOIN FETCH nu.user
-        WHERE a.id=:artistId
-        """)
-    Optional<Artist>findByIdWithUser(@Param("artistId")Long artistId);
-
-    @Query("""
-            SELECT a FROM Artist a
-            JOIN FETCH a.nonAdminUser nau
-            JOIN FETCH nau.user u
-            WHERE u.username = :username
-            """)
-    Optional<Artist> findByUsername(@Param("username") String username);
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/EventRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/EventRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,13 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.Event;
-import com.ukim.finki.develop.finkwave.model.EventProjection;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-public interface EventRepository extends JpaRepository<Event, Long> {
-    List<EventProjection> findAllByLocation(String location);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/FollowRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/FollowRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,48 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Follow;
-import com.ukim.finki.develop.finkwave.model.FollowId;
-
-import java.util.List;
-
-@Repository
-public interface FollowRepository extends JpaRepository<Follow, FollowId> {
-
-    // count how many followers the user has
-    long countByFolloweeId(Long userId);
-
-    //count how many users does this user follow
-    long countByFollowerId(Long userId);
-
-    @Query("""
-        SELECT CASE WHEN COUNT (f)>0 THEN  true ELSE false END
-        FROM Follow f
-        WHERE f.followee.id=:selectedUserId AND f.follower.id=:currentUserId
-        """)
-    boolean isFollowing(@Param("currentUserId") Long currentUSerId,@Param("selectedUserId")Long selectedUserId);
-
-
-    List<Follow>getFollowsByFollower_Id(Long id);
-
-    @Query("""
-        SELECT f FROM Follow f
-        JOIN FETCH f.follower nu
-        JOIN FETCH nu.user
-        WHERE f.followee.id = :id
-        """)
-    List<Follow> findFollowersWithProfile(@Param("id") Long id);
-
-    @Query("""
-        SELECT f FROM Follow f
-        JOIN FETCH f.followee nu
-        JOIN FETCH nu.user
-        WHERE f.follower.id = :id
-        """)
-    List<Follow> findFollowingWithProfile(@Param("id") Long id);
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/LikeRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/LikeRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,48 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Like;
-import com.ukim.finki.develop.finkwave.model.LikeId;
-
-import java.util.List;
-
-@Repository
-public interface LikeRepository extends JpaRepository<Like, LikeId> {
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto(
-            me.id,
-            me.title,
-            me.genre,
-            (CASE WHEN s.id IS NOT NULL THEN 'SONG'
-                 WHEN a.id IS NOT NULL THEN 'ALBUM'
-                 ELSE 'UNKNOWN' END),
-            u.fullName,
-            u.username,
-            me.cover,
-            (CASE WHEN currentUserLike.id IS NOT NULL THEN true ELSE false END))
-        FROM Like l
-        JOIN l.musicalEntity me
-        JOIN me.releasedBy nu
-        JOIN nu.nonAdminUser.user u
-        LEFT JOIN Song s ON s.musicalEntities.id = me.id
-        LEFT JOIN Album a ON a.musicalEntities.id = me.id
-        LEFT JOIN Like currentUserLike ON currentUserLike.musicalEntity.id = me.id
-        AND currentUserLike.listener.id = :currentUserId
-        WHERE l.listener.id = :listenerId
-        """)
-    List<MusicalEntityDto> findLikedEntitiesWithTypeByListenerId(@Param("currentUserId")Long currentUserId,@Param("listenerId") Long listenerId);
-
-
-    @Query("""
-        SELECT CASE WHEN COUNT (l)>0 THEN true ELSE false END
-        FROM MusicalEntity me
-        JOIN Like l on l.musicalEntity.id=me.id
-        WHERE l.listener.id=:userId
-        """)
-    boolean isLikedByUser(@Param("userId") Long userId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ListenRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ListenRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Listen;
-import com.ukim.finki.develop.finkwave.model.ListenId;
-
-@Repository
-public interface ListenRepository extends JpaRepository<Listen, ListenId> {
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ListenerRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ListenerRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,29 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import java.util.Optional;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Listener;
-
-@Repository
-public interface ListenerRepository extends JpaRepository<Listener, Long> {
-    @Query("""
-        SELECT DISTINCT l FROM Listener l
-       JOIN FETCH l.nonAdminUser nu
-       JOIN FETCH nu.user
-       WHERE l.id = :listenerId
-       """)
-    Optional<Listener> findByIdWithUser(@Param("listenerId") Long listenerId);
-
-    @Query("""
-        SELECT l FROM Listener l
-        JOIN FETCH l.nonAdminUser nu
-        JOIN FETCH nu.user u
-        WHERE u.username=:username
-        """)
-    Optional<Listener>findByUsername(@Param("username")String username);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/MusicalEntityRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/MusicalEntityRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,14 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.MusicalEntity;
-
-import java.util.List;
-
-@Repository
-public interface MusicalEntityRepository extends JpaRepository<MusicalEntity, Long> {
-
-    List<MusicalEntity>findAllByReleasedBy_Id(Long id);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/NonAdminUserRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/NonAdminUserRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.NonAdminUser;
-
-import java.util.List;
-import java.util.Optional;
-
-@Repository
-public interface NonAdminUserRepository extends JpaRepository<NonAdminUser, Long> {
-
-    @Query("""
-        SELECT n FROM NonAdminUser n JOIN FETCH n.user
-    """)
-    List<NonAdminUser> findAllWithUser();
-
-    @Query("""
-        SELECT u FROM NonAdminUser u
-        WHERE u.user.fullName ILIKE '%' || :name || '%'
-        OR  u.user.username ILIKE '%' || :name || '%'
-    """)
-    List<NonAdminUser> searchByName(String name);
-
-    @Query("""
-        SELECT nau FROM NonAdminUser nau
-        JOIN FETCH nau.user u
-        WHERE u.username = :username
-        """)
-    Optional<NonAdminUser> findByUsername(@Param("username") String username);
-
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PerformsAtRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PerformsAtRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,11 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.PerformsAt;
-import com.ukim.finki.develop.finkwave.model.PerformsAtId;
-
-@Repository
-public interface PerformsAtRepository extends JpaRepository<PerformsAt, PerformsAtId> {
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PlaylistRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PlaylistRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,45 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.dto.BasicPlaylistDto;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Playlist;
-
-import java.util.List;
-import java.util.Optional;
-
-@Repository
-public interface PlaylistRepository extends JpaRepository<Playlist, Long> {
-
-
-    @Query("""
-        SELECT DISTINCT p FROM Playlist p
-        JOIN FETCH p.createdBy l
-        JOIN FETCH l.nonAdminUser nu
-        JOIN FETCH nu.user u
-        WHERE l.id = :creatorId
-        """)
-    List<Playlist> findByCreatorId(@Param("creatorId") Long creatorId);
-
-    @SuppressWarnings("JpaQlInspection") // count returns long, intellij expects int
-    @Query("""
-    SELECT NEW com.ukim.finki.develop.finkwave.model.dto.BasicPlaylistDto(
-    p.id, p.name, p.cover, (SELECT COUNT(*) FROM PlaylistSong ps where ps.playlist.id = p.id)
-    )
-    FROM Playlist p
-    WHERE p.createdBy.id = :userId
-    """)
-    List<BasicPlaylistDto> getPlaylistsByIdIs(@Param("userId") Long userId);
-
-    @Query("""
-                SELECT p
-                FROM Playlist p
-                WHERE p.name=:name AND p.createdBy.id=:currentUserId
-            
-            """)
-    Optional<Playlist>getPlaylistByName(@Param("name") String name,
-                                        @Param("currentUserId") Long currentUserId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PlaylistSongRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/PlaylistSongRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,21 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.PlaylistSong;
-import com.ukim.finki.develop.finkwave.model.PlaylistSongId;
-
-import java.util.List;
-
-@Repository
-public interface PlaylistSongRepository extends JpaRepository<PlaylistSong, PlaylistSongId> {
-
-    @Query("""
-                select ps.id.playlistId
-                from PlaylistSong ps
-                where ps.song.id=:songId and ps.playlist.createdBy.id=:userId
-            """)
-    List<Long>getPlaylistsIdsWithSong(Long songId, Long userId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/RefreshTokenRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/RefreshTokenRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,12 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.RefreshToken;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.Optional;
-
-@Repository
-public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
-    Optional<RefreshToken> findByToken(String token);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ReviewRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/ReviewRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,30 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.dto.ReviewDto;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Review;
-import com.ukim.finki.develop.finkwave.model.ReviewId;
-
-import java.util.List;
-
-@Repository
-public interface ReviewRepository extends JpaRepository<Review, ReviewId> {
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.ReviewDto(
-        r.id,
-        r.listener.nonAdminUser.user.fullName,
-        r.listener.nonAdminUser.user.username,
-        r.grade,
-        r.comment
-        )
-        FROM Review r
-        WHERE r.id.musicalEntityId = :songId
-    """)
-    List<ReviewDto> getReviewsForSongId(@Param("songId") Long songId);
-
-    Review getReviewById_ListenerIdAndId_MusicalEntityId(Long listenerId, Long musicalEntityId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/SavedPlaylistRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/SavedPlaylistRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,28 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.Playlist;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.SavedPlaylist;
-import com.ukim.finki.develop.finkwave.model.SavedPlaylistId;
-
-import java.util.List;
-
-@Repository
-public interface SavedPlaylistRepository extends JpaRepository<SavedPlaylist, SavedPlaylistId> {
-
-    List<SavedPlaylist>findAllByListener_Id(Long currentUserId);
-
-    @Query("""
-        SELECT p FROM SavedPlaylist sp
-        JOIN sp.playlist p
-        JOIN FETCH p.createdBy l
-        JOIN FETCH l.nonAdminUser nau
-        JOIN FETCH nau.user u
-        WHERE sp.id.listenerId = :listenerId
-        """)
-    List<Playlist> findSavedPlaylistsMetadata(@Param("listenerId") Long listenerId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/SongRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/SongRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,187 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import java.util.List;
-
-import com.ukim.finki.develop.finkwave.model.dto.*;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import com.ukim.finki.develop.finkwave.model.Song;
-
-@Repository
-public interface SongRepository extends JpaRepository<Song, Long> {
-
-
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongWithLinkDto(
-            s.id, me.title, me.genre, 'SONG', u.fullName, u.username, me.cover,
-            (CASE WHEN :currentUserId IS NOT NULL AND l.id IS NOT NULL THEN true ELSE false END),
-            s.link
-        )
-        FROM Song s
-        JOIN s.musicalEntities me
-        JOIN me.releasedBy a
-        JOIN a.nonAdminUser nau
-        JOIN nau.user u
-        LEFT JOIN Like l ON l.musicalEntity.id = s.id AND l.listener.id = :currentUserId
-        WHERE s.album.id = :albumId
-    """)
-    List<SongWithLinkDto>findSongsByAlbum(@Param("albumId") Long albumId, @Param("currentUserId")Long currentUserId);
-
-
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongWithLinkDto(
-            s.id, me.title, me.genre, 'SONG', u.fullName, u.username, me.cover,
-            (CASE WHEN :currentUserId IS NOT NULL AND l.id IS NOT NULL THEN true ELSE false END),
-            s.link
-            )
-        FROM Song s
-        JOIN s.musicalEntities me
-        JOIN me.releasedBy a
-        JOIN a.nonAdminUser nau
-        JOIN nau.user u
-        JOIN PlaylistSong ps ON ps.song.id=s.id
-        LEFT JOIN Like l ON l.musicalEntity.id=s.id AND l.listener.id=:currentUserId
-        WHERE ps.playlist.id=:playlistId
-    """)
-    List<SongWithLinkDto>findSongsByPlaylistId(@Param("playlistId")Long playlistId, @Param("currentUserId")Long currentUserId);
-
-    @Query("""
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongDto(
-            s.id,
-            s.musicalEntities.title,
-            s.musicalEntities.genre,
-            'SONG',
-            s.musicalEntities.releasedBy.nonAdminUser.user.fullName,
-            s.musicalEntities.releasedBy.nonAdminUser.user.username,
-            s.musicalEntities.cover,
-            (EXISTS (SELECT 1 FROM Like l WHERE l.musicalEntity.id = s.id AND l.listener.id = :currentUserId)),
-            s.album.musicalEntities.title,
-            s.album.musicalEntities.id,
-            s.link
-        )
-        FROM Song s
-        JOIN Listen l on l.id.songId = s.id
-        GROUP BY
-            s.id,
-            s.musicalEntities.title,
-            s.musicalEntities.genre,
-            s.musicalEntities.releasedBy.nonAdminUser.user.fullName,
-            s.musicalEntities.releasedBy.nonAdminUser.user.username,
-            s.musicalEntities.cover,
-            s.album.musicalEntities.title,
-            s.album.musicalEntities.id
-        ORDER BY count(*) desc
-    """)
-    // todo: add paging
-    List<SongDto> findTopByListens(@Param("currentUserId")Long currentUserId);
-
-    @Query("""
-    SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongDto(
-        s.id,
-        me.title,
-        me.genre,
-        'SONG',
-        u.fullName,
-        u.username,
-        me.cover,
-        (EXISTS (
-            SELECT 1 FROM Like l
-            WHERE l.musicalEntity.id = s.id
-              AND l.listener.id = :currentUserId
-        )),
-        albumMe.title,
-        a.id,
-        s.link
-    )
-    FROM Song s
-    JOIN s.musicalEntities me
-    JOIN me.releasedBy rb
-    JOIN rb.nonAdminUser nau
-    JOIN nau.user u
-    LEFT JOIN s.album a
-    LEFT JOIN a.musicalEntities albumMe
-    WHERE me.title ILIKE CONCAT('%', :searchTerm, '%')
-""")
-    List<SongDto> searchSongs(@Param("currentUserId")Long currentUserId, @Param("searchTerm") String searchTerm);
-
-
-    @Query(value = """
-        SELECT
-            t.song_id,
-            t.title,
-            t.full_name,
-            t.username,
-            t.link,
-            t.cover
-        FROM (
-                 SELECT DISTINCT ON (l.song_id)
-                     l.song_id,
-                     me.title,
-                     u.full_name,
-                     u.username,
-                     me.cover,
-                     s.link,
-                     l.timestamp
-                 FROM listens l
-                     JOIN musical_entities me ON me.id = l.song_id
-                     JOIN songs s on s.id = l.song_id
-                     JOIN users u ON u.user_id = me.released_by
-                     WHERE l.listener_id = :userId
-                 ORDER BY l.song_id, l.timestamp DESC
-             ) t
-        ORDER BY t.timestamp DESC
-        LIMIT 5;
-    """, nativeQuery = true)
-    List<BasicSongDto> getRecentlyListened(@Param("userId")Long userId);
-
-    @Query(value = """
-        SELECT NEW com.ukim.finki.develop.finkwave.model.dto.SongDto(
-            s.id,
-            me.title,
-            me.genre,
-            'SONG',
-            u.fullName,
-            u.username,
-            me.cover,
-            (EXISTS (
-                SELECT 1 FROM Like l
-                WHERE l.musicalEntity.id = s.id
-                  AND l.listener.id = :userId
-            )),
-            albumMe.title,
-            albumMe.id,
-            s.link
-        )
-        FROM Song s
-        JOIN s.musicalEntities me
-        JOIN me.releasedBy a
-        JOIN a.nonAdminUser nau
-        JOIN nau.user u
-        LEFT JOIN s.album album
-        LEFT JOIN album.musicalEntities albumMe
-        WHERE s.id = :songId
-    """)
-    SongDto getSongById(@Param("songId") Long songId, @Param("userId") Long userId);
-
-    @Query("""
-        SELECT new com.ukim.finki.develop.finkwave.model.dto.MusicalEntitesByArtistDto(
-          me.id,
-          me.title,
-          me.genre,
-          (CASE
-            WHEN EXISTS (SELECT 1 FROM Song s WHERE me.id = s.id AND s.album IS NULL) THEN 'SONG'
-            WHEN EXISTS (SELECT 1 FROM Album a WHERE a.id = me.id) THEN 'ALBUM'
-            ELSE NULL
-           END),
-          me.cover,
-          me.releaseDate
-        )
-        FROM MusicalEntity me
-        WHERE me.releasedBy.id = :artistId
-        ORDER BY me.releaseDate DESC
-    """)
-    List<MusicalEntitesByArtistDto> getMusicalEntitiesReleasedByArtist(@Param("artistId")Long artistId);
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/UserRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/UserRepository.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,34 +1,0 @@
-package com.ukim.finki.develop.finkwave.repository;
-
-import com.ukim.finki.develop.finkwave.model.User;
-import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.Query;
-import org.springframework.data.repository.query.Param;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-import java.util.Optional;
-
-@Repository
-public interface UserRepository extends JpaRepository<User, Long> {
-    Optional<User> findByUsername(String username);
-
-
-    @Query(value = """
-        SELECT u.user_id, u.full_name, u.username, u.profile_photo from users u
-        WHERE (u.full_name ILIKE '%' || :searchTerm || '%' or u.username ILIKE '%' || :searchTerm || '%')
-            and u.listener = true and u.artist = false
-        LIMIT :limit
-        """, nativeQuery = true)
-    List<UserSearchResultDto> searchListeners(@Param("searchTerm") String searchTerm, @Param("limit") Integer limit);
-
-    @Query(value = """
-        SELECT u.user_id, u.full_name, u.username, u.profile_photo from users u
-        WHERE (u.full_name ILIKE '%' || :searchTerm || '%' or u.username ILIKE '%' || :searchTerm || '%') and u.artist = true
-        LIMIT :limit
-        """, nativeQuery = true)
-    List<UserSearchResultDto> searchArtists(@Param("searchTerm") String searchTerm, @Param("limit") Integer limit);
-
-
-}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/UsersRepository.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/UsersRepository.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/repository/UsersRepository.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,9 @@
+package com.ukim.finki.develop.finkwave.repository;
+
+import com.ukim.finki.develop.finkwave.model.Users;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface UsersRepository extends JpaRepository<Users, Long> {
+}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AlbumService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AlbumService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,50 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.AlbumNotFoundException;
-import com.ukim.finki.develop.finkwave.model.Album;
-import com.ukim.finki.develop.finkwave.model.MusicalEntity;
-import com.ukim.finki.develop.finkwave.model.dto.AlbumDto;
-import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
-import com.ukim.finki.develop.finkwave.model.dto.SongWithLinkDto;
-import com.ukim.finki.develop.finkwave.repository.AlbumRepository;
-import com.ukim.finki.develop.finkwave.repository.LikeRepository;
-import com.ukim.finki.develop.finkwave.repository.SongRepository;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-public class AlbumService {
-    private final AlbumRepository albumRepository;
-    private final SongRepository songRepository;
-    private final AuthService authService;
-    private final LikeRepository likeRepository;
-
-    public MusicalEntityDto getAlbum(Long id){
-        if (!albumRepository.existsById(id)){
-            throw new AlbumNotFoundException(id);
-        }
-        Long currentUserId=authService.getCurrentUserIDOptional().orElse(null);
-
-        Album album=albumRepository.findById(id).orElseThrow(()->new AlbumNotFoundException(id));
-        AlbumDto dto=new AlbumDto(album.getId(),
-                album.getMusicalEntities().getTitle(),
-                album.getMusicalEntities().getGenre(),
-                "ALBUM",
-                album.getMusicalEntities().getReleasedBy().getNonAdminUser().getUser().getFullName(),
-                album.getMusicalEntities().getReleasedBy().getNonAdminUser().getUser().getUsername(),
-                album.getMusicalEntities().getCover(),
-                likeRepository.isLikedByUser(currentUserId));
-        List<SongWithLinkDto>songsFromAlbum=songRepository.findSongsByAlbum(id,currentUserId);
-
-        dto.setSongs(songsFromAlbum);
-        return dto;
-    }
-
-    public List<MusicalEntityDto> searchAlbums(String searchTerm){
-        return albumRepository.searchAlbums(authService.getCurrentUserIDOptional().orElse(null), searchTerm);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ArtistContributionService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ArtistContributionService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,18 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionSummaryDto;
-import com.ukim.finki.develop.finkwave.repository.ArtistContributionRepository;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-public class ArtistContributionService {
-    private final ArtistContributionRepository artistContributionRepository;
-
-    public List<ArtistContributionSummaryDto> getContributionsBySongId(Long songId){
-        return artistContributionRepository.findContributionsBySongId(songId);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ArtistService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ArtistService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,31 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
-import com.ukim.finki.develop.finkwave.model.Artist;
-import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionDto;
-import com.ukim.finki.develop.finkwave.repository.ArtistContributionRepository;
-
-import com.ukim.finki.develop.finkwave.repository.ArtistRepository;
-import org.springframework.transaction.annotation.Transactional;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-public class ArtistService {
-    private final ArtistContributionRepository artistContributionRepository;
-    private final ArtistRepository artistRepository;
-
-
-    @Transactional(readOnly=true)
-    public List<ArtistContributionDto> getArtistContributions(Long artistId, Long currentUserId){
-        return artistContributionRepository.findContributionsByArtistId(currentUserId,artistId);
-    }
-
-    public Artist getArtistById(Long id){
-        return artistRepository.findById(id).orElseThrow(UserNotFoundException::new);
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/AuthService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,226 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
-
-import com.ukim.finki.develop.finkwave.model.*;
-import com.ukim.finki.develop.finkwave.model.enums.UserType;
-import com.ukim.finki.develop.finkwave.repository.ArtistRepository;
-import com.ukim.finki.develop.finkwave.repository.ListenerRepository;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-
-import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import com.ukim.finki.develop.finkwave.exceptions.InvalidCredentialsException;
-import com.ukim.finki.develop.finkwave.exceptions.InvalidFileException;
-import com.ukim.finki.develop.finkwave.exceptions.UnauthenticatedException;
-import com.ukim.finki.develop.finkwave.exceptions.UserAlreadyExistsException;
-import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
-import com.ukim.finki.develop.finkwave.model.dto.AuthRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.LoginRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.UserResponseDto;
-import com.ukim.finki.develop.finkwave.repository.NonAdminUserRepository;
-import com.ukim.finki.develop.finkwave.repository.UserRepository;
-
-import jakarta.servlet.http.Cookie;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.transaction.Transactional;
-import lombok.RequiredArgsConstructor;
-
-@Service
-@RequiredArgsConstructor
-public class AuthService {
-    private final UserRepository userRepository;
-    private final NonAdminUserRepository nonAdminUserRepository;
-    private final ArtistRepository artistRepository;
-    private final ListenerRepository listenerRepository;
-
-    private final JwtService jwtService;
-    private final RefreshTokenService refreshTokenService;
-
-    private final PasswordEncoder passwordEncoder;
-    private final AuthProperties authProperties;
-
-
-    private static final long MAX_FILE_SIZE = 2_000_000;
-
-    @Transactional
-    public UserResponseDto registerAndLogIn(HttpServletResponse response, AuthRequestDto authRequestDto)
-    throws IOException {
-        if (userRepository.findByUsername(authRequestDto.username()).isPresent()){
-            throw new UserAlreadyExistsException();
-        }
-        User user = createNonAdminUser(authRequestDto);
-        return authenticateAndRespond(response, user);
-    }
-
-    public UserResponseDto login(HttpServletResponse response, LoginRequestDto loginRequestDto){
-        User user = userRepository.findByUsername(loginRequestDto.username())
-                .orElseThrow(InvalidCredentialsException::new);
-
-        if (!passwordEncoder.matches(loginRequestDto.password(), user.getPassword())){
-            throw new InvalidCredentialsException();
-        }
-
-        return authenticateAndRespond(response, user);
-    }
-
-    public String refreshAccessToken(String refreshTokenString) {
-        RefreshToken refreshToken = refreshTokenService.validateRefreshToken(refreshTokenString);
-        User user = refreshToken.getUser();
-        return jwtService.generateToken(user.getUsername(), user.getRole().name());
-    }
-
-    public void refreshAccessTokenAndAddCookie(HttpServletResponse response, String refreshToken){
-        String accessToken = refreshAccessToken(refreshToken);
-        addAccessCookieToResponse(response, accessToken);
-    }
-
-    public UserResponseDto getUserDtoByUsername(String username){
-        User user = userRepository.findByUsername(username)
-                .orElseThrow(UserNotFoundException::new);
-
-        return userResponseFromUser(user);
-    }
-
-    public void invalidateRefreshToken(String refreshToken) {
-        refreshTokenService.revokeToken(refreshToken);
-    }
-
-    public void addAccessCookieToResponse(HttpServletResponse response, String accessToken){
-        Cookie accessCookie = new Cookie("accessToken", accessToken);
-        accessCookie.setHttpOnly(true);
-        accessCookie.setSecure(false);
-        accessCookie.setPath("/");
-        accessCookie.setMaxAge(authProperties.getAccessTokenMaxAge());
-        response.addCookie(accessCookie);
-    }
-
-    public void clearCookies(HttpServletResponse httpServletResponse, String refreshToken) {
-        if (refreshToken != null){
-            invalidateRefreshToken(refreshToken);
-            clearCookieByName(httpServletResponse, "refreshToken");
-        }
-        clearCookieByName(httpServletResponse, "accessToken");
-    }
-
-    public Long getCurrentUserID(){
-        Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
-        if (authentication == null || !authentication.isAuthenticated()) {
-            throw new UnauthenticatedException();
-        }
-
-        String username=authentication.getName();
-
-        return userRepository.findByUsername(username).map(User::getId)
-                .orElseThrow(UnauthenticatedException::new);
-    }
-
-    public Optional<Long> getCurrentUserIDOptional(){
-        Authentication authentication= SecurityContextHolder.getContext().getAuthentication();
-        if (authentication == null || !authentication.isAuthenticated()) {
-            return Optional.empty();
-        }
-        String username=authentication.getName();
-        return userRepository.findByUsername(username).map(User::getId);
-    }
-
-    @Transactional
-    public User createNonAdminUser(AuthRequestDto authRequestDto) throws IOException {
-        User.UserBuilder userBuilder = User.builder()
-                .username(authRequestDto.username())
-                .fullName(authRequestDto.fullname())
-                .email(authRequestDto.email())
-                .password(passwordEncoder.encode(authRequestDto.password()))
-                .role(Role.NONADMIN)
-                .artist(authRequestDto.userType().contains(UserType.ARTIST))
-                .listener(authRequestDto.userType().contains(UserType.LISTENER));
-
-
-        MultipartFile profilePhoto = authRequestDto.profilePhoto();
-        if (profilePhoto != null && !profilePhoto.isEmpty()) {
-            String contentType = profilePhoto.getContentType();
-            if (contentType == null || !contentType.startsWith("image/")) {
-                throw InvalidFileException.invalidType();
-            }
-
-            if (profilePhoto.getSize() > MAX_FILE_SIZE) {
-                throw InvalidFileException.tooLarge(MAX_FILE_SIZE);
-            }
-
-            String filename = UUID.randomUUID() + "-" + profilePhoto.getOriginalFilename();
-            Path path = Paths.get("uploads/profile-pictures", filename);
-            Files.copy(profilePhoto.getInputStream(), path);
-            userBuilder.profilePhoto("profile-pictures/" + filename);
-        }
-
-        User user = userBuilder.build();
-
-        NonAdminUser nonAdminUser = new NonAdminUser();
-        nonAdminUser.setUser(user);
-        user.setNonAdminUser(nonAdminUser);
-        nonAdminUserRepository.save(nonAdminUser);
-
-        if (user.isArtist()){
-            Artist artist = new Artist();
-            artist.setNonAdminUser(nonAdminUser);
-            artistRepository.save(artist);
-        }
-        if (user.isListener()){
-            Listener listener = new Listener();
-            listener.setNonAdminUser(nonAdminUser);
-            listenerRepository.save(listener);
-        }
-
-        return user;
-    }
-
-    private UserResponseDto authenticateAndRespond(HttpServletResponse response, User user){
-        String accessToken = jwtService.generateToken(user.getUsername(), user.getRole().name());
-        RefreshToken refreshToken = refreshTokenService.createRefreshToken(user);
-
-        UserResponseDto userResponseDto = userResponseFromUser(user);
-
-        addTokensToResponse(response, refreshToken, accessToken);
-        return userResponseDto;
-    }
-
-    private void clearCookieByName(HttpServletResponse response, String cookieName){
-        Cookie clearAccess = new Cookie(cookieName, null);
-        clearAccess.setHttpOnly(true);
-        clearAccess.setSecure(false);
-        clearAccess.setPath("/");
-        clearAccess.setMaxAge(0);
-        response.addCookie(clearAccess);
-    }
-
-
-    private void addTokensToResponse(HttpServletResponse response, RefreshToken refreshToken, String accessToken){
-        Cookie refreshCookie = new Cookie("refreshToken", refreshToken.getToken());
-        refreshCookie.setHttpOnly(true);
-        refreshCookie.setSecure(false);
-        refreshCookie.setPath("/");
-        refreshCookie.setMaxAge(authProperties.getRefreshTokenMaxAge());
-        response.addCookie(refreshCookie);
-
-        addAccessCookieToResponse(response, accessToken);
-    }
-
-    private UserResponseDto userResponseFromUser(User user){
-        return UserResponseDto.builder()
-                .fullname(user.getFullName())
-                .username(user.getUsername())
-                .profilePhoto(user.getProfilePhoto())
-                .isAdmin(user.getRole().equals(Role.ADMIN))
-                .isArtist(user.isArtist())
-                .build();
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/CustomUserDetailsService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/CustomUserDetailsService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,31 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.model.User;
-import com.ukim.finki.develop.finkwave.repository.UserRepository;
-import lombok.RequiredArgsConstructor;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-public class CustomUserDetailsService implements UserDetailsService {
-    private final UserRepository userRepository;
-
-    @Override
-    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
-        User user = userRepository.findByUsername(username)
-                .orElseThrow(() -> new RuntimeException("user not found"));
-        List<GrantedAuthority> authorities = List.of(new SimpleGrantedAuthority("ROLE_" + user.getRole().name()));
-        return new org.springframework.security.core.userdetails.User(
-                user.getUsername(),
-                user.getPassword(),
-                authorities
-        );
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/FollowService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/FollowService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,119 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.FollowException;
-import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
-import com.ukim.finki.develop.finkwave.model.Artist;
-import com.ukim.finki.develop.finkwave.model.Follow;
-import com.ukim.finki.develop.finkwave.model.FollowId;
-import com.ukim.finki.develop.finkwave.model.NonAdminUser;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.FollowStatusDto;
-import com.ukim.finki.develop.finkwave.model.dto.NonAdminUserDto;
-import com.ukim.finki.develop.finkwave.repository.ArtistRepository;
-import com.ukim.finki.develop.finkwave.repository.FollowRepository;
-import com.ukim.finki.develop.finkwave.repository.NonAdminUserRepository;
-import com.ukim.finki.develop.finkwave.service.mappers.NonAdminUserMapper;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-@Service
-@AllArgsConstructor
-public class FollowService {
-
-    private final FollowRepository followRepository;
-    private final NonAdminUserRepository nonAdminUserRepository;
-    private final AuthService authService;
-    private final ArtistRepository artistRepository;
-    private final NonAdminUserMapper mapper;
-
-
-    private boolean isFollowedByCurrentUser(Long currentUserId,Long otherUserId){
-        Set<Long> currentUserFollows = followRepository.getFollowsByFollower_Id(currentUserId)
-                .stream()
-                .map(f -> f.getFollowee().getId())
-                .collect(Collectors.toSet());
-        return currentUserFollows.contains(otherUserId);
-    }
-
-    private  NonAdminUser getNonAdminUser(String username){
-        Optional<Artist>artistOptional=artistRepository.findByUsername(username);
-        if (artistOptional.isPresent()){
-            throw new FollowException("Cannot view for artist");
-        }
-        return nonAdminUserRepository.findByUsername(username)
-                .orElseThrow(()-> new UserNotFoundException("Cannot find user with username: "+ username));
-    }
-
-    public List<NonAdminUserDto>getFollowersForUser(String username){
-        NonAdminUser nonAdminUser=getNonAdminUser(username);
-
-        Long id=nonAdminUser.getId();
-        List<Follow> followers = followRepository.findFollowersWithProfile(id);
-        Long currentUserId=authService.getCurrentUserIDOptional().orElse(null);
-
-
-        return followers.stream()
-                .map(f -> {
-                    NonAdminUser follower = f.getFollower();
-                    boolean isFollowedByCurrentUser=isFollowedByCurrentUser(currentUserId,follower.getId());
-
-                    return mapper.toDto(follower, null, new FollowStatusDto(isFollowedByCurrentUser,null,null));
-                })
-                .toList();
-    }
-
-    public List<NonAdminUserDto>getFollowingForUser(String username){
-        NonAdminUser nonAdminUser=getNonAdminUser(username);
-        Long id=nonAdminUser.getId();
-        List<Follow>followings=followRepository.getFollowsByFollower_Id(id);
-        Long currentUserId=authService.getCurrentUserID();
-        return followings.stream()
-                .map(f->{
-                    NonAdminUser followee=f.getFollowee();
-                    boolean isFollowedByCurrentUser=isFollowedByCurrentUser(currentUserId,followee.getId());
-                    return mapper.toDto(f.getFollowee(),null,new FollowStatusDto(isFollowedByCurrentUser,null,null));
-                })
-                .toList();
-    }
-
-
-
-    public FollowStatusDto toggleFollow(String username){
-        Long currentUserId=authService.getCurrentUserID();
-        boolean isFollowing;
-        NonAdminUser nonAdminUser=nonAdminUserRepository.findByUsername(username)
-                .orElseThrow(()-> new UserNotFoundException("Cannot find user with username: "+ username));
-        Long id=nonAdminUser.getId();
-
-        if (currentUserId.equals(id)){
-            throw new FollowException("Cannot follow yourself");
-        }
-
-        FollowId followId=new FollowId(currentUserId,id);
-
-
-        if (followRepository.existsById(followId)){
-            followRepository.deleteById(followId);
-            isFollowing=false;
-
-        }else{
-            NonAdminUser follower = nonAdminUserRepository.findById(currentUserId)
-                    .orElseThrow(UserNotFoundException::new);
-            NonAdminUser followee = nonAdminUserRepository.findById(id)
-                    .orElseThrow(UserNotFoundException::new);
-
-            followRepository.save(new Follow(follower, followee));
-            isFollowing=true;
-
-        }
-        return new FollowStatusDto(
-                isFollowing,
-                followRepository.countByFolloweeId(id),
-                followRepository.countByFollowerId(id));
-
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/JwtService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/JwtService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,38 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import io.jsonwebtoken.Claims;
-import io.jsonwebtoken.Jwts;
-import io.jsonwebtoken.security.Keys;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-
-import javax.crypto.SecretKey;
-import java.nio.charset.StandardCharsets;
-import java.util.Date;
-
-@Service
-@RequiredArgsConstructor
-public class JwtService {
-    private final AuthProperties authProperties;
-
-    public String generateToken(String username, String role){
-        SecretKey key = Keys.hmacShaKeyFor(authProperties.getSecret().getBytes(StandardCharsets.UTF_8));
-        return Jwts.builder()
-                .setSubject(username)
-                .claim("role", "ROLE_" + role)
-                .setExpiration(new Date(System.currentTimeMillis() + (long) authProperties.getAccessTokenMaxAge() * 1000))
-                .signWith(key)
-                .compact();
-    }
-
-    public Claims extractClaims(String token){
-        SecretKey key = Keys.hmacShaKeyFor(authProperties.getSecret().getBytes(StandardCharsets.UTF_8));
-        return Jwts.parserBuilder()
-                .setSigningKey(key)
-                .build()
-                .parseClaimsJws(token)
-                .getBody();
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/LikeService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/LikeService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,63 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.MusicalEntityNotFoundException;
-import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
-import com.ukim.finki.develop.finkwave.model.Like;
-import com.ukim.finki.develop.finkwave.model.LikeId;
-import com.ukim.finki.develop.finkwave.model.Listener;
-import com.ukim.finki.develop.finkwave.model.MusicalEntity;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.LikeStatusDto;
-import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
-import com.ukim.finki.develop.finkwave.repository.*;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-public class LikeService {
-    private final LikeRepository likeRepository;
-    private final AuthService authService;
-    private final MusicalEntityRepository musicalEntityRepository;
-    private AlbumRepository albumRepository;
-    private final SongRepository songRepository;
-    private final ListenerRepository listenerRepository;
-
-    public List<MusicalEntityDto> findLikedEntitiesWithTypeByListenerId(Long currentUserId,Long listenerId){
-        return likeRepository.findLikedEntitiesWithTypeByListenerId(currentUserId,listenerId);
-    }
-
-    public LikeStatusDto toggleLike(Long entityId){
-        Long currentUserId=authService.getCurrentUserID();
-
-
-        LikeId likeId=new LikeId(currentUserId,entityId);
-        boolean isLiked;
-        if (likeRepository.existsById(likeId)){
-            likeRepository.deleteById(likeId);
-            isLiked=false;
-        }
-        else{
-            Listener listener=listenerRepository.findById(currentUserId).orElseThrow(
-                    ()->new UserNotFoundException("Listener not found")
-            );
-            MusicalEntity entity=musicalEntityRepository.findById(entityId).orElseThrow(
-                    ()->new MusicalEntityNotFoundException("Entity not found")
-            );
-            likeRepository.save(new Like(entity,listener));
-            isLiked=true;
-        }
-        return new LikeStatusDto(entityId,isLiked,determineType(entityId));
-
-    }
-
-    private String determineType(Long id){
-        if (albumRepository.existsById(id)){
-            return "ALBUM";
-        }else if(songRepository.existsById(id)){
-            return "SONG";
-        }return "UNDEFINED";
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ListenerService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ListenerService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,37 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.model.Playlist;
-import com.ukim.finki.develop.finkwave.model.dto.ListenerLikesDto;
-import com.ukim.finki.develop.finkwave.model.dto.MusicalEntityDto;
-import com.ukim.finki.develop.finkwave.repository.LikeRepository;
-import com.ukim.finki.develop.finkwave.repository.PlaylistRepository;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-@Transactional(readOnly = true)
-public class ListenerService {
-    private final LikeService likeService;
-    private final PlaylistService playlistService;
-
-    public List<MusicalEntityDto> getLikedEntities(Long currentUserId,Long listenerId) {
-        return  likeService.findLikedEntitiesWithTypeByListenerId(currentUserId,listenerId);
-
-
-    }
-
-
-    public List<Playlist>getPlaylistsCreatedByUser(Long listenerId){
-        return playlistService.findByCreatorId(listenerId);
-    }
-
-
-    public List<Playlist>getPlaylistsSavedByUser(Long listenerId){
-        return playlistService.findSavedByUser(listenerId);
-    }
-}
-
-
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/MusicalEntityService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/MusicalEntityService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,208 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.time.LocalDate;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.multipart.MultipartFile;
-
-import com.ukim.finki.develop.finkwave.exceptions.InvalidFileException;
-import com.ukim.finki.develop.finkwave.model.Album;
-import com.ukim.finki.develop.finkwave.model.Artist;
-import com.ukim.finki.develop.finkwave.model.ArtistContribution;
-import com.ukim.finki.develop.finkwave.model.ArtistContributionId;
-import com.ukim.finki.develop.finkwave.model.MusicalEntity;
-import com.ukim.finki.develop.finkwave.model.Song;
-import com.ukim.finki.develop.finkwave.model.dto.AlbumSongsDto;
-import com.ukim.finki.develop.finkwave.model.dto.ArtistContributionSummaryDto;
-import com.ukim.finki.develop.finkwave.model.dto.PublishAlbumRequestDto;
-import com.ukim.finki.develop.finkwave.model.dto.PublishSongRequestDto;
-import com.ukim.finki.develop.finkwave.repository.AlbumRepository;
-import com.ukim.finki.develop.finkwave.repository.ArtistContributionRepository;
-import com.ukim.finki.develop.finkwave.repository.MusicalEntityRepository;
-import com.ukim.finki.develop.finkwave.repository.SongRepository;
-
-import lombok.AllArgsConstructor;
-
-@AllArgsConstructor
-@Service
-public class MusicalEntityService {
-    private final AuthService authService;
-    private final ArtistService artistService;
-    private final SongRepository songRepository;
-    private final AlbumRepository albumRepository;
-    private final ArtistContributionRepository artistContributionRepository;
-    MusicalEntityRepository musicalEntityRepository;
-
-    private static final long MAX_FILE_SIZE = 2_000_000;
-    private static final String MAIN_VOCAL_ROLE = "MAIN VOCAL";
-    
-    @Transactional
-    public void handleSongPublish(PublishSongRequestDto requestDto) throws IOException {
-        Long userId = authService.getCurrentUserID();
-        Artist artist = artistService.getArtistById(userId);
-
-        MusicalEntity musicalEntity = createMusicalEntity(
-                requestDto.getTitle(),
-                requestDto.getGenre(),
-                requestDto.getCover(),
-                artist
-        );
-
-        Song song = new Song();
-        song.setAlbum(null);
-        song.setLink(requestDto.getLink());
-        song.setMusicalEntities(musicalEntity);
-        songRepository.save(song);
-
-        // add publishing artist
-        saveContribution(artist, musicalEntity, MAIN_VOCAL_ROLE);
-
-        // add additional contributors
-        saveContributionsFromDto(musicalEntity, requestDto.getContributors());
-    }
-
-    @Transactional
-    protected MusicalEntity createMusicalEntity(String title, String genre, MultipartFile cover, Artist releasedBy)
-            throws IOException {
-        MusicalEntity.MusicalEntityBuilder builder = MusicalEntity.builder()
-                .title(title)
-                .genre(genre)
-                .releaseDate(LocalDate.now())
-                .releasedBy(releasedBy);
-
-        if (cover != null && !cover.isEmpty()) {
-            try {
-                String filename = saveCoverPhoto(cover);
-                builder.cover("profile-pictures/" + filename);
-            } catch (Exception ignored) {}
-        }
-
-        return musicalEntityRepository.save(builder.build());
-    }
-
-    @Transactional
-    protected void saveContribution(Artist artist, MusicalEntity musicalEntity, String role) {
-        ArtistContributionId id = new ArtistContributionId();
-        id.setArtistId(artist.getId());
-        id.setMusicalEntityId(musicalEntity.getId());
-
-        ArtistContribution contribution = new ArtistContribution();
-        contribution.setId(id);
-        contribution.setArtist(artist);
-        contribution.setMusicalEntity(musicalEntity);
-        contribution.setRole(role);
-
-        artistContributionRepository.save(contribution);
-    }
-
-    @Transactional
-    protected void saveContributionsFromDto(MusicalEntity musicalEntity, List<ArtistContributionSummaryDto> contributors) {
-        if (contributors == null) return;
-
-        for (ArtistContributionSummaryDto contributorDto : contributors) {
-            if (contributorDto.getId() == null) continue;
-
-            Artist contributor = artistService.getArtistById(contributorDto.getId());
-            saveContribution(contributor, musicalEntity, contributorDto.getRole());
-        }
-    }
-    // todo: add business logic (max songs per album, max contributors etc.)
-
-    @Transactional
-    public void handleAlbumPublish(PublishAlbumRequestDto requestDto) throws IOException {
-        Long userId = authService.getCurrentUserID();
-        Artist artist = artistService.getArtistById(userId);
-
-        MusicalEntity albumMusicalEntity = createMusicalEntity(
-                requestDto.getTitle(),
-                requestDto.getGenre(),
-                requestDto.getCover(),
-                artist
-        );
-
-        Album album = new Album();
-        album.setMusicalEntities(albumMusicalEntity);
-        album = albumRepository.save(album);
-
-        // add publishing artist
-        saveContribution(artist, albumMusicalEntity, MAIN_VOCAL_ROLE);
-
-        // track artists already added to avoid duplicates
-        Set<Long> albumContributorIds = new HashSet<>();
-        albumContributorIds.add(artist.getId());
-
-        List<AlbumSongsDto> albumSongs = requestDto.getAlbumSongs();
-        for (AlbumSongsDto songDto : albumSongs) {
-            createSongForAlbum(albumMusicalEntity, album, songDto, artist, albumContributorIds);
-        }
-    }
-
-
-    @Transactional
-    protected void createSongForAlbum(MusicalEntity albumMe, Album album, AlbumSongsDto songDto,
-                                     Artist publishingArtist, Set<Long> albumContributorIds) {
-        MusicalEntity songMusicalEntity = MusicalEntity.builder()
-                .title(songDto.getTitle())
-                .releaseDate(albumMe.getReleaseDate())
-                .releasedBy(albumMe.getReleasedBy())
-                .cover(albumMe.getCover())
-                .genre(albumMe.getGenre())
-                .build();
-        songMusicalEntity = musicalEntityRepository.save(songMusicalEntity);
-
-        Song song = new Song();
-        song.setLink(songDto.getLink());
-        song.setAlbum(album);
-        song.setMusicalEntities(songMusicalEntity);
-        songRepository.save(song);
-
-        // add publishing artist as MAIN VOCAL to this song
-        saveContribution(publishingArtist, songMusicalEntity, MAIN_VOCAL_ROLE);
-
-        // add song-specific contributors
-        List<ArtistContributionSummaryDto> songContributors = songDto.getContributors();
-        if (songContributors != null) {
-            for (ArtistContributionSummaryDto contributorDto : songContributors) {
-                if (contributorDto.getId() == null) continue;
-                
-                Artist contributor = artistService.getArtistById(contributorDto.getId());
-                
-                // first add to song
-                saveContribution(contributor, songMusicalEntity, contributorDto.getRole());
-                
-                // then add to album if not already added
-                if (!albumContributorIds.contains(contributor.getId())) {
-                    saveContribution(contributor, album.getMusicalEntities(), contributorDto.getRole());
-                    albumContributorIds.add(contributor.getId());
-                }
-            }
-        }
-    }
-
-
-
-    private String saveCoverPhoto(MultipartFile coverPhoto) throws IOException {
-        String contentType = coverPhoto.getContentType();
-        if (contentType == null || !contentType.startsWith("image/")) {
-            throw InvalidFileException.invalidType();
-        }
-
-        if (coverPhoto.getSize() > MAX_FILE_SIZE) {
-            throw InvalidFileException.tooLarge(MAX_FILE_SIZE);
-        }
-
-        String filename = UUID.randomUUID() + "-" + coverPhoto.getOriginalFilename();
-        Path path = Paths.get("uploads/profile-pictures", filename);
-        Files.copy(coverPhoto.getInputStream(), path);
-        return filename;
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/NonAdminUserService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/NonAdminUserService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,145 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
-import com.ukim.finki.develop.finkwave.model.*;
-import com.ukim.finki.develop.finkwave.model.dto.*;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.FollowStatusDto;
-import com.ukim.finki.develop.finkwave.repository.*;
-import com.ukim.finki.develop.finkwave.service.mappers.NonAdminUserMapper;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-@Service
-@AllArgsConstructor
-public class NonAdminUserService {
-    private final NonAdminUserRepository nonAdminUserRepository;
-    private final ListenerRepository listenerRepository;
-    private final ArtistRepository artistRepository;
-    private final NonAdminUserMapper mapper;
-    private final ArtistService artistService;
-    private final ListenerService listenerService;
-    private final FollowRepository followRepository;
-    private final AuthService authService;
-    private final SavedPlaylistRepository savedPlaylistRepository;
-
-    @Transactional(readOnly = true)
-    public List<NonAdminUserDto> getAllUsers() {
-        return nonAdminUserRepository.findAllWithUser().stream()
-                .map(user -> {
-                    String type = determineType(user.getId());
-                    return mapper.toDto(user, type, new FollowStatusDto(false,null,null));
-                })
-                .collect(Collectors.toList());
-    }
-
-    @Transactional(readOnly = true)
-    public NonAdminUserDto getNonAdminUserProfile(String username) {
-        Long currentUserId = authService.getCurrentUserIDOptional().orElse(null);
-
-        Optional<Artist>artistOptional=artistRepository.findByUsername(username);
-    
-        if (artistOptional.isPresent()) {
-            Artist artist = artistOptional.get();
-            return getArtistProfile(artist, currentUserId);
-        }
-
-        Optional<Listener>listenerOptional=listenerRepository.findByUsername(username);
-      
-        if (listenerOptional.isPresent()) {
-            Listener listener=listenerOptional.get();
-            return getListenerProfile(listener,currentUserId);
-        }
-
-        throw new UserNotFoundException("User not found: " + username);
-    }
-
-    private FollowStatusDto getFollowingInfo(Long id,Long currentUserId){
-
-        Long followers = followRepository.countByFolloweeId(id);
-        Long following = followRepository.countByFollowerId(id);
-        boolean isFollowing = currentUserId != null && followRepository.isFollowing(currentUserId, id);
-        return new FollowStatusDto(isFollowing,followers,following);
-    }
-
-    private NonAdminUserDto getArtistProfile(Artist artist,Long currentUserId) {
-        Long artistId=artist.getId();
-
-        List<ArtistContributionDto>artistContributionDtos=artistService.getArtistContributions(artistId, currentUserId);
-        FollowStatusDto followStatusDto=getFollowingInfo(artistId,currentUserId);
-
-        return mapper.toArtistDTO(artist, artistContributionDtos,followStatusDto);
-    }
-
-    private NonAdminUserDto getListenerProfile(Listener listener, Long currentUserId) {
-        Long profileId = listener.getId();
-
-        FollowStatusDto followStatusDto = getFollowingInfo(profileId, currentUserId);
-
-
-        List<MusicalEntityDto> likedEntities = listenerService.getLikedEntities(currentUserId, profileId);
-
-        Set<Long> visitorSavedPlaylistIds = (currentUserId != null)
-                ? savedPlaylistRepository.findAllByListener_Id(currentUserId).stream()
-                .map(sp -> sp.getPlaylist().getId())
-                .collect(Collectors.toSet())
-                : Collections.emptySet();
-
-
-        List<PlaylistDto> createdPlaylists = listenerService.getPlaylistsCreatedByUser(profileId).stream()
-                .map(p -> mapToPlaylistDto(p, visitorSavedPlaylistIds))
-                .toList();
-
-
-        List<PlaylistDto> savedPlaylists = savedPlaylistRepository.findSavedPlaylistsMetadata(profileId).stream()
-                .map(p -> mapToPlaylistDto(p, visitorSavedPlaylistIds))
-                .toList();
-
-        return mapper.toListenerDTO(listener, likedEntities, followStatusDto, createdPlaylists, savedPlaylists);
-    }
-
-
-    public List<NonAdminUserDto>searchUsers(String name){
-
-        List<NonAdminUser>nonAdminUsers=nonAdminUserRepository.searchByName(name);
-        if (nonAdminUsers.isEmpty()){
-            throw new UserNotFoundException("No users matched the criteria");
-        }
-
-        return nonAdminUserRepository.searchByName(name).stream()
-                .map(user -> {
-                    Long userId= user.getId();
-                    String type = determineType(userId);
-                    FollowStatusDto followStatusDto=getFollowingInfo(userId,null);
-                    return mapper.toDto(user, type,followStatusDto);
-                })
-                .collect(Collectors.toList());
-    }
-
-
-    private PlaylistDto mapToPlaylistDto(Playlist p, Set<Long> visitorSavedPlaylistIds) {
-        return new PlaylistDto(
-                p.getId(),
-                p.getName(),
-                p.getCover(),
-                p.getCreatedBy().getNonAdminUser().getUser().getFullName(),
-                p.getCreatedBy().getNonAdminUser().getUser().getUsername(),
-                null,
-                visitorSavedPlaylistIds.contains(p.getId())
-        );
-    }
-    private String determineType(Long id) {
-        if (artistRepository.existsById(id)) {
-            return "Artist";
-        } else if (listenerRepository.existsById(id)) {
-            return "Listener";
-        }
-        return "Admin";
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/PlaylistService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/PlaylistService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,164 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.*;
-import com.ukim.finki.develop.finkwave.model.*;
-import com.ukim.finki.develop.finkwave.model.dto.BasicPlaylistDto;
-import com.ukim.finki.develop.finkwave.model.dto.PlaylistDto;
-import com.ukim.finki.develop.finkwave.model.dto.SongWithLinkDto;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.AddSongToPlaylistStatusDto;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.SavePlaylistStatusDto;
-import com.ukim.finki.develop.finkwave.repository.*;
-import lombok.AllArgsConstructor;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.server.ResponseStatusException;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-@Service
-@AllArgsConstructor
-
-public class PlaylistService {
-    private final PlaylistRepository playlistRepository;
-    private final SongRepository songRepository;
-    private final AuthService authService;
-    private final SavedPlaylistRepository savedPlaylistRepository;
-    private final ListenerRepository listenerRepository;
-    private final PlaylistSongRepository playlistSongRepository;
-
-    public List<Playlist>findByCreatorId(Long id){
-        return playlistRepository.findByCreatorId(id);
-    }
-
-    public List<Playlist>findSavedByUser(Long id){
-        return savedPlaylistRepository.findSavedPlaylistsMetadata(id);
-    }
-
-    public PlaylistDto getPlaylist(Long id){
-        Long currentUserId=authService.getCurrentUserIDOptional().orElse(null);
-        Playlist playlist = playlistRepository.findById(id).orElseThrow(()-> new PlaylistNotFoundException(id));
-        List<SongWithLinkDto>songsInPlaylist=songRepository.findSongsByPlaylistId(id,currentUserId);
-        Set<Long> savedIds = savedPlaylistRepository.findAllByListener_Id(currentUserId)
-                .stream().map(sp -> sp.getPlaylist().getId()).collect(Collectors.toSet());
-        return new PlaylistDto(
-                playlist.getId(),
-                playlist.getName(),
-                playlist.getCover(),
-                playlist.getCreatedBy().getNonAdminUser().getUser().getFullName(),
-                playlist.getCreatedBy().getNonAdminUser().getUser().getUsername(),
-                songsInPlaylist,
-                savedIds.contains(playlist.getId())
-
-        );
-    }
-
-    public List<BasicPlaylistDto> getBasicPlaylists(){
-        Long userId = authService.getCurrentUserIDOptional().orElse(null);
-        return playlistRepository.getPlaylistsByIdIs(userId);
-    }
-
-    @Transactional
-    public SavePlaylistStatusDto savePlaylist(Long playlistId) throws Exception {
-        Long currentUserId=authService.getCurrentUserID();
-        SavedPlaylistId savedPlaylistId=new SavedPlaylistId(currentUserId,playlistId);
-        Playlist playlist=playlistRepository.findById(playlistId).orElseThrow(
-                ()->new PlaylistNotFoundException(playlistId)
-        );
-        if (playlist.getCreatedBy().getId().equals(currentUserId)) {
-            throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"Cannot save playlist created by the current user!");
-        }
-
-
-
-        boolean isSaved;
-
-        if (savedPlaylistRepository.existsById(savedPlaylistId)){
-            savedPlaylistRepository.deleteById(savedPlaylistId);
-            isSaved=false;
-        }
-        else{
-            Listener listener=listenerRepository.findById(currentUserId).orElseThrow(
-                    ()->new UserNotFoundException("Listener not found")
-            );
-
-            savedPlaylistRepository.save(new SavedPlaylist(listener,playlist));
-            isSaved=true;
-        }
-        return new SavePlaylistStatusDto(playlistId,isSaved);
-
-    }
-
-
-
-    public List<Long>getPlaylistIdsThatContainSong(Long songId){
-
-        Long currentUserId=authService.getCurrentUserIDOptional().orElse(null);
-        return playlistSongRepository.getPlaylistsIdsWithSong(songId,currentUserId);
-
-    }
-
-
-    public void createPlaylist(String playlistName, Long songId){
-        Long currentUserId=authService.getCurrentUserID();
-
-        Optional<Playlist>playlistOptional=playlistRepository.getPlaylistByName(playlistName,currentUserId);
-        if (playlistOptional.isPresent()){
-            throw new PlaylistAlreadyExistsException("You already have a playlist named '"+playlistName+"'");
-        }
-        Listener listener=listenerRepository.findById(currentUserId).orElseThrow(
-                UserNotFoundException::new
-        );
-        Playlist playlist=playlistRepository.save(new Playlist(null,playlistName,listener));
-        if (songId!=null){
-
-            addSongToPlaylist(playlist.getId(),songId);
-        }
-
-
-
-    }
-
-
-    public AddSongToPlaylistStatusDto addSongToPlaylist(Long playlistId, Long songId){
-        Playlist playlist=playlistRepository.findById(playlistId).orElseThrow(()->new PlaylistNotFoundException(playlistId));
-        Long currentUserId=authService.getCurrentUserID();
-        if (!Objects.equals(playlist.getCreatedBy().getId(), currentUserId)){
-            throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"Cannot add songs to playlists NOT created by the current user!");
-        }
-        PlaylistSongId playlistSongId=new PlaylistSongId(songId,playlistId);
-
-        boolean isSongAddedToPlaylist;
-
-        if (playlistSongRepository.existsById(playlistSongId)){
-            playlistSongRepository.deleteById(playlistSongId);
-            isSongAddedToPlaylist=false;
-        }else {
-            Song song=songRepository.findById(songId).orElseThrow(
-                    ()->new MusicalEntityNotFoundException(String.format("Cannot find song with id %d.", songId)));
-
-            playlistSongRepository.save(new PlaylistSong(playlistSongId,song,playlist));
-            isSongAddedToPlaylist=true;
-        }
-        return new AddSongToPlaylistStatusDto(playlistId,isSongAddedToPlaylist);
-
-    }
-
-    public void deletePlaylist(Long id){
-        Playlist playlist=playlistRepository.findById(id).orElseThrow(
-                ()->new PlaylistNotFoundException(id)
-        );
-
-        if (!playlist.getCreatedBy().getId().equals(authService.getCurrentUserID())){
-            throw new NotAuthorizedException("CANNOT delete a playlist created by another user!");
-        }
-
-        playlistRepository.deleteById(id);
-
-
-    }
-
-
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/RefreshTokenService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,55 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Optional;
-import java.util.UUID;
-
-import org.springframework.stereotype.Service;
-
-import com.ukim.finki.develop.finkwave.config.AuthProperties;
-import com.ukim.finki.develop.finkwave.exceptions.InvalidTokenException;
-import com.ukim.finki.develop.finkwave.model.RefreshToken;
-import com.ukim.finki.develop.finkwave.model.User;
-import com.ukim.finki.develop.finkwave.repository.RefreshTokenRepository;
-
-import lombok.RequiredArgsConstructor;
-
-@Service
-@RequiredArgsConstructor
-public class RefreshTokenService {
-    private final RefreshTokenRepository refreshTokenRepository;
-    private final AuthProperties authProperties;
-
-    public RefreshToken createRefreshToken(User user){
-        RefreshToken refreshToken = new RefreshToken();
-        refreshToken.setUser(user);
-        refreshToken.setToken(UUID.randomUUID().toString());
-        refreshToken.setExpiresAt(Instant.now().plus(authProperties.getRefreshTokenMaxAge(), ChronoUnit.SECONDS));
-        return refreshTokenRepository.save(refreshToken);
-    }
-
-    public Optional<RefreshToken> findByToken(String token){
-        return refreshTokenRepository.findByToken(token);
-    }
-
-    public RefreshToken validateRefreshToken(String token){
-        RefreshToken refreshToken = findByToken(token)
-                .orElseThrow(() -> new InvalidTokenException("Invalid refresh token."));
-        if (refreshToken.isRevoked()){
-            throw new InvalidTokenException("Refresh token has been revoked.");
-        }
-        if (refreshToken.getExpiresAt().isBefore(Instant.now())){
-            throw new InvalidTokenException("Refresh token has expired.");
-        }
-        return refreshToken;
-    }
-
-    public void revokeToken(String token){
-        findByToken(token).ifPresent(t -> {
-            t.setRevoked(true);
-            refreshTokenRepository.save(t);
-        });
-    }
-
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ReviewService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/ReviewService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,59 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.exceptions.UserNotFoundException;
-import com.ukim.finki.develop.finkwave.model.Listener;
-import com.ukim.finki.develop.finkwave.model.MusicalEntity;
-import com.ukim.finki.develop.finkwave.model.Review;
-import com.ukim.finki.develop.finkwave.model.ReviewId;
-import com.ukim.finki.develop.finkwave.model.dto.ReviewDto;
-import com.ukim.finki.develop.finkwave.model.dto.ReviewPostDto;
-import com.ukim.finki.develop.finkwave.repository.ListenerRepository;
-import com.ukim.finki.develop.finkwave.repository.MusicalEntityRepository;
-import com.ukim.finki.develop.finkwave.repository.ReviewRepository;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-public class ReviewService {
-    private final ReviewRepository reviewRepository;
-    private final AuthService authService;
-    private final ListenerRepository listenerRepository;
-    private final MusicalEntityRepository musicalEntityRepository;
-
-    public List<ReviewDto> getReviewsForSongId(Long songId){
-        return reviewRepository.getReviewsForSongId(songId);
-    }
-
-    public void createReview(Long songId, ReviewPostDto reviewPostDto){
-        Long userId = authService.getCurrentUserID();
-
-        // todo: custom exceptions
-        Listener listener = listenerRepository.findById(userId)
-                .orElseThrow(UserNotFoundException::new);
-
-        MusicalEntity musicalEntity = musicalEntityRepository
-                .findById(songId)
-                .orElseThrow();
-
-        // show proper error for doubled reviews from user
-
-        Review review = new Review();
-        review.setId(new ReviewId());
-        review.setListener(listener);
-        review.setMusicalEntity(musicalEntity);
-        review.setComment(reviewPostDto.getComment());
-        review.setGrade(reviewPostDto.getGrade());
-
-        reviewRepository.save(review);
-    }
-
-    public void deleteReview(Long songId){
-        Long userId = authService.getCurrentUserID();
-        Review review = reviewRepository.getReviewById_ListenerIdAndId_MusicalEntityId(userId, songId);
-
-        reviewRepository.delete(review);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/SongService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/SongService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,61 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.model.dto.*;
-import com.ukim.finki.develop.finkwave.repository.SongRepository;
-import com.ukim.finki.develop.finkwave.service.mappers.SongDetailsMapper;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-public class SongService {
-    private final SongRepository songRepository;
-    private final AuthService authService;
-    private final ArtistContributionService artistContributionService;
-    private final ReviewService reviewService;
-    private final SongDetailsMapper songDetailsMapper;
-
-    public List<SongDto> getTopSongs(){
-        Long userId = null;
-        try {
-            userId = authService.getCurrentUserID();
-        } catch (Exception ignored) {}
-        return songRepository.findTopByListens(userId);
-    }
-
-    public List<SongDto> searchSongs(String searchTerm){
-        Long userId = authService.getCurrentUserIDOptional().orElse(null);
-        return songRepository.searchSongs(userId, searchTerm);
-    }
-
-    public List<BasicSongDto> getRecentlyListened(){
-        Long userId = authService.getCurrentUserID();
-        return songRepository.getRecentlyListened(userId);
-    }
-
-//    public MusicalEntityDto getSongById(Long songId){
-//        Long userId = null;
-//        try {
-//            userId = authService.getCurrentUserID();
-//        } catch (Exception ignored) {}
-//        return songRepository.getSongById(songId, userId);
-//    }
-
-    public SongDetailsDto getSongDetails(Long songId){
-        Long userId = null;
-        try {
-            userId = authService.getCurrentUserID();
-        } catch (Exception ignored){}
-        SongDto songDto = songRepository.getSongById(songId, userId);
-        List<ArtistContributionSummaryDto> contributionsBySongId = artistContributionService.getContributionsBySongId(songId);
-        List<ReviewDto> reviewsForSongId = reviewService.getReviewsForSongId(songId);
-        return songDetailsMapper.toSongDetailsDto(songDto, contributionsBySongId, reviewsForSongId);
-    }
-
-    public List<MusicalEntitesByArtistDto> getArtistCatalog(){
-        Long userId = authService.getCurrentUserID();
-        return songRepository.getMusicalEntitiesReleasedByArtist(userId);
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/UserService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/UserService.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,29 +1,0 @@
-package com.ukim.finki.develop.finkwave.service;
-
-import com.ukim.finki.develop.finkwave.model.User;
-import com.ukim.finki.develop.finkwave.model.dto.UserSearchResultDto;
-import com.ukim.finki.develop.finkwave.model.enums.UserType;
-import com.ukim.finki.develop.finkwave.repository.UserRepository;
-import lombok.AllArgsConstructor;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-@AllArgsConstructor
-public class UserService {
-    private final UserRepository usersRepository;
-
-    public List<User> getAll(){
-        return usersRepository.findAll();
-    }
-
-    public List<UserSearchResultDto> search(UserType userType, String searchTerm, int limit){
-        return switch (userType) {
-            case ARTIST -> usersRepository.searchArtists(searchTerm, limit);
-            case LISTENER -> usersRepository.searchListeners(searchTerm, limit);
-            case null -> throw new IllegalArgumentException("Invalid userType");
-        };
-    }
-
-}
Index: finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/UsersService.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/UsersService.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/UsersService.java	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,21 @@
+package com.ukim.finki.develop.finkwave.service;
+
+import com.ukim.finki.develop.finkwave.model.Users;
+import com.ukim.finki.develop.finkwave.repository.UsersRepository;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class UsersService {
+    private final UsersRepository usersRepository;
+
+    public UsersService(UsersRepository usersRepository) {
+        this.usersRepository = usersRepository;
+    }
+
+    public List<Users> getAll(){
+        return usersRepository.findAll();
+    }
+
+}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/mappers/NonAdminUserMapper.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/mappers/NonAdminUserMapper.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,55 +1,0 @@
-package com.ukim.finki.develop.finkwave.service.mappers;
-
-import com.ukim.finki.develop.finkwave.model.Artist;
-
-import com.ukim.finki.develop.finkwave.model.Listener;
-
-import com.ukim.finki.develop.finkwave.model.dto.*;
-import com.ukim.finki.develop.finkwave.model.NonAdminUser;
-import com.ukim.finki.develop.finkwave.model.dto.statusDto.FollowStatusDto;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-
-@Component
-public class NonAdminUserMapper {
-
-    public NonAdminUserDto toArtistDTO(Artist artist, List<ArtistContributionDto> entitiesDTO, FollowStatusDto followStatusDto) {
-        ArtistDto dto=new ArtistDto();
-        populateBaseClassFields(dto,artist.getNonAdminUser(),"ARTIST",followStatusDto);
-        dto.setContributions(entitiesDTO);
-        return dto;
-    }
-
-    public NonAdminUserDto toListenerDTO(Listener listener,
-                                         List<MusicalEntityDto> musicalEntityDtos,
-                                         FollowStatusDto followStatusDto,
-                                         List<PlaylistDto>createdPlaylists,
-                                         List<PlaylistDto>savedPlaylists) {
-        ListenerDto dto=new ListenerDto();
-        populateBaseClassFields(dto,listener.getNonAdminUser(),"LISTENER",followStatusDto);
-        dto.setLikedEntities(musicalEntityDtos);
-        dto.setCreatedPlaylists(createdPlaylists);
-        dto.setSavedPlaylists(savedPlaylists);
-        return dto;
-    }
-
-    public NonAdminUserDto toDto(NonAdminUser user,String type, FollowStatusDto followStatusDto){
-       NonAdminUserDto dto=new NonAdminUserDto();
-       populateBaseClassFields(dto,user,type,followStatusDto);
-       return dto;
-    }
-
-
-
-    private void populateBaseClassFields(NonAdminUserDto dto,NonAdminUser user,String type,FollowStatusDto followStatusDto){
-        dto.setUsername(user.getUser().getUsername());
-        dto.setFullName(user.getUser().getFullName());
-        dto.setProfilePhoto(user.getUser().getProfilePhoto());
-        dto.setUserType(type);
-        dto.setFollowers(followStatusDto.followerCount());
-        dto.setFollowing(followStatusDto.followingCount());
-        dto.setIsFollowedByCurrentUser(followStatusDto.isFollowing());
-    }
-}
Index: nkwave/src/main/java/com/ukim/finki/develop/finkwave/service/mappers/SongDetailsMapper.java
===================================================================
--- finkwave/src/main/java/com/ukim/finki/develop/finkwave/service/mappers/SongDetailsMapper.java	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,28 +1,0 @@
-package com.ukim.finki.develop.finkwave.service.mappers;
-
-import com.ukim.finki.develop.finkwave.model.dto.*;
-import org.springframework.stereotype.Component;
-
-import java.util.List;
-
-@Component
-public class SongDetailsMapper {
-    public SongDetailsDto toSongDetailsDto(SongDto songDto,
-                                           List<ArtistContributionSummaryDto> artistContributionSummaryDtos,
-                                           List<ReviewDto> reviewDtos){
-        SongDetailsDto songDetailsDto = new SongDetailsDto();
-        songDetailsDto.setId(songDto.getId());
-        songDetailsDto.setTitle(songDto.getTitle());
-        songDetailsDto.setAlbum(songDto.getAlbum());
-        songDetailsDto.setCover(songDto.getCover());
-        songDetailsDto.setGenre(songDto.getGenre());
-        songDetailsDto.setType(songDto.getType());
-        songDetailsDto.setAlbum(songDto.getAlbum());
-        songDetailsDto.setLink(songDto.getLink());
-        songDetailsDto.setIsLikedByCurrentUser(songDto.getIsLikedByCurrentUser());
-        songDetailsDto.setReleasedBy(songDto.getReleasedBy());
-        songDetailsDto.setContributions(artistContributionSummaryDtos);
-        songDetailsDto.setReviews(reviewDtos);
-        return songDetailsDto;
-    }
-}
Index: finkwave/src/main/resources/application-example.properties
===================================================================
--- finkwave/src/main/resources/application-example.properties	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ finkwave/src/main/resources/application-example.properties	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -5,12 +5,2 @@
 spring.datasource.password=x
 spring.datasource.hikari.schema=x
-
-auth.secret=x
-
-# 15 minutes
-auth.access-token-max-age=900
-
-# 10 days = 10 * 24 * 60 * 60
-auth.refresh-token-max-age=864000
-
-spring.web.resources.static-locations=file:uploads/
Index: ontend/.env.example
===================================================================
--- frontend/.env.example	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,1 +1,0 @@
-VITE_API_BASE_URL=http://localhost:8080
Index: frontend/README.md
===================================================================
--- frontend/README.md	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ frontend/README.md	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,73 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## React Compiler
+
+The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default defineConfig([
+  globalIgnores(['dist']),
+  {
+    files: ['**/*.{ts,tsx}'],
+    extends: [
+      // Other configs...
+
+      // Remove tseslint.configs.recommended and replace with this
+      tseslint.configs.recommendedTypeChecked,
+      // Alternatively, use this for stricter rules
+      tseslint.configs.strictTypeChecked,
+      // Optionally, add this for stylistic rules
+      tseslint.configs.stylisticTypeChecked,
+
+      // Other configs...
+    ],
+    languageOptions: {
+      parserOptions: {
+        project: ['./tsconfig.node.json', './tsconfig.app.json'],
+        tsconfigRootDir: import.meta.dirname,
+      },
+      // other options...
+    },
+  },
+])
+```
+
+You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
+
+```js
+// eslint.config.js
+import reactX from 'eslint-plugin-react-x'
+import reactDom from 'eslint-plugin-react-dom'
+
+export default defineConfig([
+  globalIgnores(['dist']),
+  {
+    files: ['**/*.{ts,tsx}'],
+    extends: [
+      // Other configs...
+      // Enable lint rules for React
+      reactX.configs['recommended-typescript'],
+      // Enable lint rules for React DOM
+      reactDom.configs.recommended,
+    ],
+    languageOptions: {
+      parserOptions: {
+        project: ['./tsconfig.node.json', './tsconfig.app.json'],
+        tsconfigRootDir: import.meta.dirname,
+      },
+      // other options...
+    },
+  },
+])
+```
Index: frontend/index.html
===================================================================
--- frontend/index.html	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ frontend/index.html	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -1,13 +1,13 @@
 <!doctype html>
 <html lang="en">
-	<head>
-		<meta charset="UTF-8" />
-		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-		<link rel="icon" type="image/png" href="/favicon.png" />
-		<title>Finkwave</title>
-	</head>
-	<body>
-		<div id="root"></div>
-		<script type="module" src="/src/main.tsx"></script>
-	</body>
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>frontend</title>
+  </head>
+  <body>
+    <div id="root"></div>
+    <script type="module" src="/src/main.tsx"></script>
+  </body>
 </html>
Index: frontend/package-lock.json
===================================================================
--- frontend/package-lock.json	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ frontend/package-lock.json	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -1,4133 +1,3762 @@
 {
-	"name": "frontend",
-	"version": "0.0.0",
-	"lockfileVersion": 3,
-	"requires": true,
-	"packages": {
-		"": {
-			"name": "frontend",
-			"version": "0.0.0",
-			"dependencies": {
-				"@tailwindcss/vite": "^4.1.18",
-				"axios": "^1.13.3",
-				"lucide-react": "^0.563.0",
-				"react": "^19.2.0",
-				"react-dom": "^19.2.0",
-				"react-router-dom": "^7.13.0",
-				"react-toastify": "^11.0.5",
-				"tailwindcss": "^4.1.18"
-			},
-			"devDependencies": {
-				"@eslint/js": "^9.39.1",
-				"@types/node": "^24.10.1",
-				"@types/react": "^19.2.5",
-				"@types/react-dom": "^19.2.3",
-				"@vitejs/plugin-react": "^5.1.1",
-				"eslint": "^9.39.1",
-				"eslint-plugin-react-hooks": "^7.0.1",
-				"eslint-plugin-react-refresh": "^0.4.24",
-				"globals": "^16.5.0",
-				"typescript": "~5.9.3",
-				"typescript-eslint": "^8.46.4",
-				"vite": "^7.2.4"
-			}
-		},
-		"node_modules/@babel/code-frame": {
-			"version": "7.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
-			"integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
-			"dev": true,
-			"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.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
-			"integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/core": {
-			"version": "7.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
-			"integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/code-frame": "^7.28.6",
-				"@babel/generator": "^7.28.6",
-				"@babel/helper-compilation-targets": "^7.28.6",
-				"@babel/helper-module-transforms": "^7.28.6",
-				"@babel/helpers": "^7.28.6",
-				"@babel/parser": "^7.28.6",
-				"@babel/template": "^7.28.6",
-				"@babel/traverse": "^7.28.6",
-				"@babel/types": "^7.28.6",
-				"@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/generator": {
-			"version": "7.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
-			"integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/parser": "^7.28.6",
-				"@babel/types": "^7.28.6",
-				"@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==",
-			"dev": true,
-			"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-globals": {
-			"version": "7.28.0",
-			"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
-			"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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",
-			"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/helper-validator-identifier": {
-			"version": "7.28.5",
-			"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
-			"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"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==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/helpers": {
-			"version": "7.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
-			"integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/template": "^7.28.6",
-				"@babel/types": "^7.28.6"
-			},
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/parser": {
-			"version": "7.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
-			"integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/types": "^7.28.6"
-			},
-			"bin": {
-				"parser": "bin/babel-parser.js"
-			},
-			"engines": {
-				"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
-			"integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/code-frame": "^7.28.6",
-				"@babel/generator": "^7.28.6",
-				"@babel/helper-globals": "^7.28.0",
-				"@babel/parser": "^7.28.6",
-				"@babel/template": "^7.28.6",
-				"@babel/types": "^7.28.6",
-				"debug": "^4.3.1"
-			},
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@babel/types": {
-			"version": "7.28.6",
-			"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
-			"integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/helper-string-parser": "^7.27.1",
-				"@babel/helper-validator-identifier": "^7.28.5"
-			},
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/@esbuild/aix-ppc64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
-			"integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
-			"cpu": [
-				"ppc64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"aix"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/android-arm": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
-			"integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
-			"cpu": [
-				"arm"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"android"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/android-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
-			"integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"android"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/android-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
-			"integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"android"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/darwin-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
-			"integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/darwin-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
-			"integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/freebsd-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
-			"integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"freebsd"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/freebsd-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
-			"integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"freebsd"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-arm": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
-			"integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
-			"cpu": [
-				"arm"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
-			"integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-ia32": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
-			"integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
-			"cpu": [
-				"ia32"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-loong64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
-			"integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
-			"cpu": [
-				"loong64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-mips64el": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
-			"integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
-			"cpu": [
-				"mips64el"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-ppc64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
-			"integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
-			"cpu": [
-				"ppc64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-riscv64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
-			"integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
-			"cpu": [
-				"riscv64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-s390x": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
-			"integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
-			"cpu": [
-				"s390x"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/linux-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
-			"integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/netbsd-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
-			"integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"netbsd"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/netbsd-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
-			"integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"netbsd"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/openbsd-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
-			"integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"openbsd"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/openbsd-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
-			"integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"openbsd"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/openharmony-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
-			"integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"openharmony"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/sunos-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
-			"integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"sunos"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/win32-arm64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
-			"integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/win32-ia32": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
-			"integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
-			"cpu": [
-				"ia32"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@esbuild/win32-x64": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
-			"integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			],
-			"engines": {
-				"node": ">=18"
-			}
-		},
-		"node_modules/@eslint-community/eslint-utils": {
-			"version": "4.9.1",
-			"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
-			"integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"eslint-visitor-keys": "^3.4.3"
-			},
-			"engines": {
-				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-			},
-			"funding": {
-				"url": "https://opencollective.com/eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
-			}
-		},
-		"node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
-			"version": "3.4.3",
-			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-			"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"engines": {
-				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-			},
-			"funding": {
-				"url": "https://opencollective.com/eslint"
-			}
-		},
-		"node_modules/@eslint-community/regexpp": {
-			"version": "4.12.2",
-			"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
-			"integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
-			}
-		},
-		"node_modules/@eslint/config-array": {
-			"version": "0.21.1",
-			"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
-			"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"dependencies": {
-				"@eslint/object-schema": "^2.1.7",
-				"debug": "^4.3.1",
-				"minimatch": "^3.1.2"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			}
-		},
-		"node_modules/@eslint/config-helpers": {
-			"version": "0.4.2",
-			"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
-			"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"dependencies": {
-				"@eslint/core": "^0.17.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			}
-		},
-		"node_modules/@eslint/core": {
-			"version": "0.17.0",
-			"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
-			"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"dependencies": {
-				"@types/json-schema": "^7.0.15"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			}
-		},
-		"node_modules/@eslint/eslintrc": {
-			"version": "3.3.3",
-			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
-			"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"ajv": "^6.12.4",
-				"debug": "^4.3.2",
-				"espree": "^10.0.1",
-				"globals": "^14.0.0",
-				"ignore": "^5.2.0",
-				"import-fresh": "^3.2.1",
-				"js-yaml": "^4.1.1",
-				"minimatch": "^3.1.2",
-				"strip-json-comments": "^3.1.1"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"url": "https://opencollective.com/eslint"
-			}
-		},
-		"node_modules/@eslint/eslintrc/node_modules/globals": {
-			"version": "14.0.0",
-			"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
-			"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=18"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/@eslint/js": {
-			"version": "9.39.2",
-			"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
-			"integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"url": "https://eslint.org/donate"
-			}
-		},
-		"node_modules/@eslint/object-schema": {
-			"version": "2.1.7",
-			"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
-			"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			}
-		},
-		"node_modules/@eslint/plugin-kit": {
-			"version": "0.4.1",
-			"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
-			"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"dependencies": {
-				"@eslint/core": "^0.17.0",
-				"levn": "^0.4.1"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			}
-		},
-		"node_modules/@humanfs/core": {
-			"version": "0.19.1",
-			"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
-			"integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"engines": {
-				"node": ">=18.18.0"
-			}
-		},
-		"node_modules/@humanfs/node": {
-			"version": "0.16.7",
-			"resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
-			"integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"dependencies": {
-				"@humanfs/core": "^0.19.1",
-				"@humanwhocodes/retry": "^0.4.0"
-			},
-			"engines": {
-				"node": ">=18.18.0"
-			}
-		},
-		"node_modules/@humanwhocodes/module-importer": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"engines": {
-				"node": ">=12.22"
-			},
-			"funding": {
-				"type": "github",
-				"url": "https://github.com/sponsors/nzakas"
-			}
-		},
-		"node_modules/@humanwhocodes/retry": {
-			"version": "0.4.3",
-			"resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
-			"integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"engines": {
-				"node": ">=18.18"
-			},
-			"funding": {
-				"type": "github",
-				"url": "https://github.com/sponsors/nzakas"
-			}
-		},
-		"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/@rolldown/pluginutils": {
-			"version": "1.0.0-beta.53",
-			"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
-			"integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/@rollup/rollup-android-arm-eabi": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz",
-			"integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==",
-			"cpu": [
-				"arm"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"android"
-			]
-		},
-		"node_modules/@rollup/rollup-android-arm64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz",
-			"integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"android"
-			]
-		},
-		"node_modules/@rollup/rollup-darwin-arm64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz",
-			"integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			]
-		},
-		"node_modules/@rollup/rollup-darwin-x64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz",
-			"integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			]
-		},
-		"node_modules/@rollup/rollup-freebsd-arm64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz",
-			"integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"freebsd"
-			]
-		},
-		"node_modules/@rollup/rollup-freebsd-x64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz",
-			"integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"freebsd"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz",
-			"integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==",
-			"cpu": [
-				"arm"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-arm-musleabihf": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz",
-			"integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==",
-			"cpu": [
-				"arm"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-arm64-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz",
-			"integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-arm64-musl": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz",
-			"integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-loong64-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz",
-			"integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==",
-			"cpu": [
-				"loong64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-loong64-musl": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz",
-			"integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==",
-			"cpu": [
-				"loong64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-ppc64-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz",
-			"integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==",
-			"cpu": [
-				"ppc64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-ppc64-musl": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz",
-			"integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==",
-			"cpu": [
-				"ppc64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-riscv64-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz",
-			"integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==",
-			"cpu": [
-				"riscv64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-riscv64-musl": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz",
-			"integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==",
-			"cpu": [
-				"riscv64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-s390x-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz",
-			"integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==",
-			"cpu": [
-				"s390x"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-x64-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz",
-			"integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-linux-x64-musl": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz",
-			"integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			]
-		},
-		"node_modules/@rollup/rollup-openbsd-x64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz",
-			"integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"openbsd"
-			]
-		},
-		"node_modules/@rollup/rollup-openharmony-arm64": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz",
-			"integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"openharmony"
-			]
-		},
-		"node_modules/@rollup/rollup-win32-arm64-msvc": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz",
-			"integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			]
-		},
-		"node_modules/@rollup/rollup-win32-ia32-msvc": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz",
-			"integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==",
-			"cpu": [
-				"ia32"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			]
-		},
-		"node_modules/@rollup/rollup-win32-x64-gnu": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz",
-			"integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			]
-		},
-		"node_modules/@rollup/rollup-win32-x64-msvc": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz",
-			"integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			]
-		},
-		"node_modules/@tailwindcss/node": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
-			"integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
-			"license": "MIT",
-			"dependencies": {
-				"@jridgewell/remapping": "^2.3.4",
-				"enhanced-resolve": "^5.18.3",
-				"jiti": "^2.6.1",
-				"lightningcss": "1.30.2",
-				"magic-string": "^0.30.21",
-				"source-map-js": "^1.2.1",
-				"tailwindcss": "4.1.18"
-			}
-		},
-		"node_modules/@tailwindcss/oxide": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
-			"integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 10"
-			},
-			"optionalDependencies": {
-				"@tailwindcss/oxide-android-arm64": "4.1.18",
-				"@tailwindcss/oxide-darwin-arm64": "4.1.18",
-				"@tailwindcss/oxide-darwin-x64": "4.1.18",
-				"@tailwindcss/oxide-freebsd-x64": "4.1.18",
-				"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
-				"@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
-				"@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
-				"@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
-				"@tailwindcss/oxide-linux-x64-musl": "4.1.18",
-				"@tailwindcss/oxide-wasm32-wasi": "4.1.18",
-				"@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
-				"@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-android-arm64": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
-			"integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"android"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-darwin-arm64": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
-			"integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-darwin-x64": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
-			"integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-freebsd-x64": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
-			"integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"freebsd"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
-			"integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
-			"cpu": [
-				"arm"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
-			"integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
-			"integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
-			"integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-linux-x64-musl": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
-			"integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"linux"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-wasm32-wasi": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
-			"integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
-			"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.7.1",
-				"@emnapi/runtime": "^1.7.1",
-				"@emnapi/wasi-threads": "^1.1.0",
-				"@napi-rs/wasm-runtime": "^1.1.0",
-				"@tybys/wasm-util": "^0.10.1",
-				"tslib": "^2.4.0"
-			},
-			"engines": {
-				"node": ">=14.0.0"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
-			"integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
-			"cpu": [
-				"arm64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
-			"integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
-			"cpu": [
-				"x64"
-			],
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"win32"
-			],
-			"engines": {
-				"node": ">= 10"
-			}
-		},
-		"node_modules/@tailwindcss/vite": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz",
-			"integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==",
-			"license": "MIT",
-			"dependencies": {
-				"@tailwindcss/node": "4.1.18",
-				"@tailwindcss/oxide": "4.1.18",
-				"tailwindcss": "4.1.18"
-			},
-			"peerDependencies": {
-				"vite": "^5.2.0 || ^6 || ^7"
-			}
-		},
-		"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/types": "^7.28.2"
-			}
-		},
-		"node_modules/@types/estree": {
-			"version": "1.0.8",
-			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
-			"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
-			"license": "MIT"
-		},
-		"node_modules/@types/json-schema": {
-			"version": "7.0.15",
-			"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
-			"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/@types/node": {
-			"version": "24.10.9",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz",
-			"integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
-			"devOptional": true,
-			"license": "MIT",
-			"dependencies": {
-				"undici-types": "~7.16.0"
-			}
-		},
-		"node_modules/@types/react": {
-			"version": "19.2.8",
-			"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz",
-			"integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==",
-			"dev": true,
-			"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==",
-			"dev": true,
-			"license": "MIT",
-			"peerDependencies": {
-				"@types/react": "^19.2.0"
-			}
-		},
-		"node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz",
-			"integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@eslint-community/regexpp": "^4.12.2",
-				"@typescript-eslint/scope-manager": "8.53.0",
-				"@typescript-eslint/type-utils": "8.53.0",
-				"@typescript-eslint/utils": "8.53.0",
-				"@typescript-eslint/visitor-keys": "8.53.0",
-				"ignore": "^7.0.5",
-				"natural-compare": "^1.4.0",
-				"ts-api-utils": "^2.4.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"@typescript-eslint/parser": "^8.53.0",
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
-			"version": "7.0.5",
-			"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
-			"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 4"
-			}
-		},
-		"node_modules/@typescript-eslint/parser": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz",
-			"integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/scope-manager": "8.53.0",
-				"@typescript-eslint/types": "8.53.0",
-				"@typescript-eslint/typescript-estree": "8.53.0",
-				"@typescript-eslint/visitor-keys": "8.53.0",
-				"debug": "^4.4.3"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/project-service": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.0.tgz",
-			"integrity": "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/tsconfig-utils": "^8.53.0",
-				"@typescript-eslint/types": "^8.53.0",
-				"debug": "^4.4.3"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/scope-manager": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz",
-			"integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/types": "8.53.0",
-				"@typescript-eslint/visitor-keys": "8.53.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/@typescript-eslint/tsconfig-utils": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.0.tgz",
-			"integrity": "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/type-utils": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz",
-			"integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/types": "8.53.0",
-				"@typescript-eslint/typescript-estree": "8.53.0",
-				"@typescript-eslint/utils": "8.53.0",
-				"debug": "^4.4.3",
-				"ts-api-utils": "^2.4.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/types": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz",
-			"integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/@typescript-eslint/typescript-estree": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz",
-			"integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/project-service": "8.53.0",
-				"@typescript-eslint/tsconfig-utils": "8.53.0",
-				"@typescript-eslint/types": "8.53.0",
-				"@typescript-eslint/visitor-keys": "8.53.0",
-				"debug": "^4.4.3",
-				"minimatch": "^9.0.5",
-				"semver": "^7.7.3",
-				"tinyglobby": "^0.2.15",
-				"ts-api-utils": "^2.4.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
-			"version": "2.0.2",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
-			"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"balanced-match": "^1.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
-			"version": "9.0.5",
-			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
-			"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"brace-expansion": "^2.0.1"
-			},
-			"engines": {
-				"node": ">=16 || 14 >=14.17"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/isaacs"
-			}
-		},
-		"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
-			"version": "7.7.3",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
-			"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
-			"dev": true,
-			"license": "ISC",
-			"bin": {
-				"semver": "bin/semver.js"
-			},
-			"engines": {
-				"node": ">=10"
-			}
-		},
-		"node_modules/@typescript-eslint/utils": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz",
-			"integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.9.1",
-				"@typescript-eslint/scope-manager": "8.53.0",
-				"@typescript-eslint/types": "8.53.0",
-				"@typescript-eslint/typescript-estree": "8.53.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/@typescript-eslint/visitor-keys": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz",
-			"integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/types": "8.53.0",
-				"eslint-visitor-keys": "^4.2.1"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			}
-		},
-		"node_modules/@vitejs/plugin-react": {
-			"version": "5.1.2",
-			"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz",
-			"integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/core": "^7.28.5",
-				"@babel/plugin-transform-react-jsx-self": "^7.27.1",
-				"@babel/plugin-transform-react-jsx-source": "^7.27.1",
-				"@rolldown/pluginutils": "1.0.0-beta.53",
-				"@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"
-			}
-		},
-		"node_modules/acorn": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
-			"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
-			"dev": true,
-			"license": "MIT",
-			"bin": {
-				"acorn": "bin/acorn"
-			},
-			"engines": {
-				"node": ">=0.4.0"
-			}
-		},
-		"node_modules/acorn-jsx": {
-			"version": "5.3.2",
-			"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-			"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-			"dev": true,
-			"license": "MIT",
-			"peerDependencies": {
-				"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
-			}
-		},
-		"node_modules/ajv": {
-			"version": "6.12.6",
-			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"fast-deep-equal": "^3.1.1",
-				"fast-json-stable-stringify": "^2.0.0",
-				"json-schema-traverse": "^0.4.1",
-				"uri-js": "^4.2.2"
-			},
-			"funding": {
-				"type": "github",
-				"url": "https://github.com/sponsors/epoberezkin"
-			}
-		},
-		"node_modules/ansi-styles": {
-			"version": "4.3.0",
-			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-			"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"color-convert": "^2.0.1"
-			},
-			"engines": {
-				"node": ">=8"
-			},
-			"funding": {
-				"url": "https://github.com/chalk/ansi-styles?sponsor=1"
-			}
-		},
-		"node_modules/argparse": {
-			"version": "2.0.1",
-			"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-			"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-			"dev": true,
-			"license": "Python-2.0"
-		},
-		"node_modules/asynckit": {
-			"version": "0.4.0",
-			"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-			"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
-			"license": "MIT"
-		},
-		"node_modules/axios": {
-			"version": "1.13.3",
-			"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.3.tgz",
-			"integrity": "sha512-ERT8kdX7DZjtUm7IitEyV7InTHAF42iJuMArIiDIV5YtPanJkgw4hw5Dyg9fh0mihdWNn1GKaeIWErfe56UQ1g==",
-			"license": "MIT",
-			"dependencies": {
-				"follow-redirects": "^1.15.6",
-				"form-data": "^4.0.4",
-				"proxy-from-env": "^1.1.0"
-			}
-		},
-		"node_modules/balanced-match": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/baseline-browser-mapping": {
-			"version": "2.9.15",
-			"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz",
-			"integrity": "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"bin": {
-				"baseline-browser-mapping": "dist/cli.js"
-			}
-		},
-		"node_modules/brace-expansion": {
-			"version": "1.1.12",
-			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
-			"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"balanced-match": "^1.0.0",
-				"concat-map": "0.0.1"
-			}
-		},
-		"node_modules/browserslist": {
-			"version": "4.28.1",
-			"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
-			"integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
-			"dev": true,
-			"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.9.0",
-				"caniuse-lite": "^1.0.30001759",
-				"electron-to-chromium": "^1.5.263",
-				"node-releases": "^2.0.27",
-				"update-browserslist-db": "^1.2.0"
-			},
-			"bin": {
-				"browserslist": "cli.js"
-			},
-			"engines": {
-				"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-			}
-		},
-		"node_modules/call-bind-apply-helpers": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
-			"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
-			"license": "MIT",
-			"dependencies": {
-				"es-errors": "^1.3.0",
-				"function-bind": "^1.1.2"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/callsites": {
-			"version": "3.1.0",
-			"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-			"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/caniuse-lite": {
-			"version": "1.0.30001764",
-			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz",
-			"integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==",
-			"dev": true,
-			"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/chalk": {
-			"version": "4.1.2",
-			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-			"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"ansi-styles": "^4.1.0",
-				"supports-color": "^7.1.0"
-			},
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/chalk/chalk?sponsor=1"
-			}
-		},
-		"node_modules/clsx": {
-			"version": "2.1.1",
-			"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
-			"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/color-convert": {
-			"version": "2.0.1",
-			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-			"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"color-name": "~1.1.4"
-			},
-			"engines": {
-				"node": ">=7.0.0"
-			}
-		},
-		"node_modules/color-name": {
-			"version": "1.1.4",
-			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/combined-stream": {
-			"version": "1.0.8",
-			"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-			"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-			"license": "MIT",
-			"dependencies": {
-				"delayed-stream": "~1.0.0"
-			},
-			"engines": {
-				"node": ">= 0.8"
-			}
-		},
-		"node_modules/concat-map": {
-			"version": "0.0.1",
-			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-			"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"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==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/cookie": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
-			"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=18"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/express"
-			}
-		},
-		"node_modules/cross-spawn": {
-			"version": "7.0.6",
-			"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
-			"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"path-key": "^3.1.0",
-				"shebang-command": "^2.0.0",
-				"which": "^2.0.1"
-			},
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"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==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/debug": {
-			"version": "4.4.3",
-			"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
-			"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"ms": "^2.1.3"
-			},
-			"engines": {
-				"node": ">=6.0"
-			},
-			"peerDependenciesMeta": {
-				"supports-color": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/deep-is": {
-			"version": "0.1.4",
-			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/delayed-stream": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-			"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.4.0"
-			}
-		},
-		"node_modules/detect-libc": {
-			"version": "2.1.2",
-			"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
-			"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
-			"license": "Apache-2.0",
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/dunder-proto": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
-			"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
-			"license": "MIT",
-			"dependencies": {
-				"call-bind-apply-helpers": "^1.0.1",
-				"es-errors": "^1.3.0",
-				"gopd": "^1.2.0"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/electron-to-chromium": {
-			"version": "1.5.267",
-			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
-			"integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
-			"dev": true,
-			"license": "ISC"
-		},
-		"node_modules/enhanced-resolve": {
-			"version": "5.18.4",
-			"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
-			"integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
-			"license": "MIT",
-			"dependencies": {
-				"graceful-fs": "^4.2.4",
-				"tapable": "^2.2.0"
-			},
-			"engines": {
-				"node": ">=10.13.0"
-			}
-		},
-		"node_modules/es-define-property": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
-			"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/es-errors": {
-			"version": "1.3.0",
-			"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
-			"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/es-object-atoms": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
-			"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
-			"license": "MIT",
-			"dependencies": {
-				"es-errors": "^1.3.0"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/es-set-tostringtag": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
-			"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
-			"license": "MIT",
-			"dependencies": {
-				"es-errors": "^1.3.0",
-				"get-intrinsic": "^1.2.6",
-				"has-tostringtag": "^1.0.2",
-				"hasown": "^2.0.2"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/esbuild": {
-			"version": "0.27.2",
-			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
-			"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
-			"hasInstallScript": true,
-			"license": "MIT",
-			"bin": {
-				"esbuild": "bin/esbuild"
-			},
-			"engines": {
-				"node": ">=18"
-			},
-			"optionalDependencies": {
-				"@esbuild/aix-ppc64": "0.27.2",
-				"@esbuild/android-arm": "0.27.2",
-				"@esbuild/android-arm64": "0.27.2",
-				"@esbuild/android-x64": "0.27.2",
-				"@esbuild/darwin-arm64": "0.27.2",
-				"@esbuild/darwin-x64": "0.27.2",
-				"@esbuild/freebsd-arm64": "0.27.2",
-				"@esbuild/freebsd-x64": "0.27.2",
-				"@esbuild/linux-arm": "0.27.2",
-				"@esbuild/linux-arm64": "0.27.2",
-				"@esbuild/linux-ia32": "0.27.2",
-				"@esbuild/linux-loong64": "0.27.2",
-				"@esbuild/linux-mips64el": "0.27.2",
-				"@esbuild/linux-ppc64": "0.27.2",
-				"@esbuild/linux-riscv64": "0.27.2",
-				"@esbuild/linux-s390x": "0.27.2",
-				"@esbuild/linux-x64": "0.27.2",
-				"@esbuild/netbsd-arm64": "0.27.2",
-				"@esbuild/netbsd-x64": "0.27.2",
-				"@esbuild/openbsd-arm64": "0.27.2",
-				"@esbuild/openbsd-x64": "0.27.2",
-				"@esbuild/openharmony-arm64": "0.27.2",
-				"@esbuild/sunos-x64": "0.27.2",
-				"@esbuild/win32-arm64": "0.27.2",
-				"@esbuild/win32-ia32": "0.27.2",
-				"@esbuild/win32-x64": "0.27.2"
-			}
-		},
-		"node_modules/escalade": {
-			"version": "3.2.0",
-			"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
-			"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/escape-string-regexp": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-			"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/eslint": {
-			"version": "9.39.2",
-			"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
-			"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@eslint-community/eslint-utils": "^4.8.0",
-				"@eslint-community/regexpp": "^4.12.1",
-				"@eslint/config-array": "^0.21.1",
-				"@eslint/config-helpers": "^0.4.2",
-				"@eslint/core": "^0.17.0",
-				"@eslint/eslintrc": "^3.3.1",
-				"@eslint/js": "9.39.2",
-				"@eslint/plugin-kit": "^0.4.1",
-				"@humanfs/node": "^0.16.6",
-				"@humanwhocodes/module-importer": "^1.0.1",
-				"@humanwhocodes/retry": "^0.4.2",
-				"@types/estree": "^1.0.6",
-				"ajv": "^6.12.4",
-				"chalk": "^4.0.0",
-				"cross-spawn": "^7.0.6",
-				"debug": "^4.3.2",
-				"escape-string-regexp": "^4.0.0",
-				"eslint-scope": "^8.4.0",
-				"eslint-visitor-keys": "^4.2.1",
-				"espree": "^10.4.0",
-				"esquery": "^1.5.0",
-				"esutils": "^2.0.2",
-				"fast-deep-equal": "^3.1.3",
-				"file-entry-cache": "^8.0.0",
-				"find-up": "^5.0.0",
-				"glob-parent": "^6.0.2",
-				"ignore": "^5.2.0",
-				"imurmurhash": "^0.1.4",
-				"is-glob": "^4.0.0",
-				"json-stable-stringify-without-jsonify": "^1.0.1",
-				"lodash.merge": "^4.6.2",
-				"minimatch": "^3.1.2",
-				"natural-compare": "^1.4.0",
-				"optionator": "^0.9.3"
-			},
-			"bin": {
-				"eslint": "bin/eslint.js"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"url": "https://eslint.org/donate"
-			},
-			"peerDependencies": {
-				"jiti": "*"
-			},
-			"peerDependenciesMeta": {
-				"jiti": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/eslint-plugin-react-hooks": {
-			"version": "7.0.1",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
-			"integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@babel/core": "^7.24.4",
-				"@babel/parser": "^7.24.4",
-				"hermes-parser": "^0.25.1",
-				"zod": "^3.25.0 || ^4.0.0",
-				"zod-validation-error": "^3.5.0 || ^4.0.0"
-			},
-			"engines": {
-				"node": ">=18"
-			},
-			"peerDependencies": {
-				"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
-			}
-		},
-		"node_modules/eslint-plugin-react-refresh": {
-			"version": "0.4.26",
-			"resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz",
-			"integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==",
-			"dev": true,
-			"license": "MIT",
-			"peerDependencies": {
-				"eslint": ">=8.40"
-			}
-		},
-		"node_modules/eslint-scope": {
-			"version": "8.4.0",
-			"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
-			"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
-			"dev": true,
-			"license": "BSD-2-Clause",
-			"dependencies": {
-				"esrecurse": "^4.3.0",
-				"estraverse": "^5.2.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"url": "https://opencollective.com/eslint"
-			}
-		},
-		"node_modules/eslint-visitor-keys": {
-			"version": "4.2.1",
-			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
-			"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"url": "https://opencollective.com/eslint"
-			}
-		},
-		"node_modules/espree": {
-			"version": "10.4.0",
-			"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
-			"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
-			"dev": true,
-			"license": "BSD-2-Clause",
-			"dependencies": {
-				"acorn": "^8.15.0",
-				"acorn-jsx": "^5.3.2",
-				"eslint-visitor-keys": "^4.2.1"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"url": "https://opencollective.com/eslint"
-			}
-		},
-		"node_modules/esquery": {
-			"version": "1.7.0",
-			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
-			"integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
-			"dev": true,
-			"license": "BSD-3-Clause",
-			"dependencies": {
-				"estraverse": "^5.1.0"
-			},
-			"engines": {
-				"node": ">=0.10"
-			}
-		},
-		"node_modules/esrecurse": {
-			"version": "4.3.0",
-			"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-			"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-			"dev": true,
-			"license": "BSD-2-Clause",
-			"dependencies": {
-				"estraverse": "^5.2.0"
-			},
-			"engines": {
-				"node": ">=4.0"
-			}
-		},
-		"node_modules/estraverse": {
-			"version": "5.3.0",
-			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-			"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-			"dev": true,
-			"license": "BSD-2-Clause",
-			"engines": {
-				"node": ">=4.0"
-			}
-		},
-		"node_modules/esutils": {
-			"version": "2.0.3",
-			"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-			"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-			"dev": true,
-			"license": "BSD-2-Clause",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/fast-deep-equal": {
-			"version": "3.1.3",
-			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/fast-json-stable-stringify": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-			"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/fast-levenshtein": {
-			"version": "2.0.6",
-			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/fdir": {
-			"version": "6.5.0",
-			"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
-			"integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=12.0.0"
-			},
-			"peerDependencies": {
-				"picomatch": "^3 || ^4"
-			},
-			"peerDependenciesMeta": {
-				"picomatch": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/file-entry-cache": {
-			"version": "8.0.0",
-			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
-			"integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"flat-cache": "^4.0.0"
-			},
-			"engines": {
-				"node": ">=16.0.0"
-			}
-		},
-		"node_modules/find-up": {
-			"version": "5.0.0",
-			"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
-			"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"locate-path": "^6.0.0",
-				"path-exists": "^4.0.0"
-			},
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/flat-cache": {
-			"version": "4.0.1",
-			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
-			"integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"flatted": "^3.2.9",
-				"keyv": "^4.5.4"
-			},
-			"engines": {
-				"node": ">=16"
-			}
-		},
-		"node_modules/flatted": {
-			"version": "3.3.3",
-			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
-			"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
-			"dev": true,
-			"license": "ISC"
-		},
-		"node_modules/follow-redirects": {
-			"version": "1.15.11",
-			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
-			"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
-			"funding": [
-				{
-					"type": "individual",
-					"url": "https://github.com/sponsors/RubenVerborgh"
-				}
-			],
-			"license": "MIT",
-			"engines": {
-				"node": ">=4.0"
-			},
-			"peerDependenciesMeta": {
-				"debug": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/form-data": {
-			"version": "4.0.5",
-			"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
-			"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
-			"license": "MIT",
-			"dependencies": {
-				"asynckit": "^0.4.0",
-				"combined-stream": "^1.0.8",
-				"es-set-tostringtag": "^2.1.0",
-				"hasown": "^2.0.2",
-				"mime-types": "^2.1.12"
-			},
-			"engines": {
-				"node": ">= 6"
-			}
-		},
-		"node_modules/fsevents": {
-			"version": "2.3.3",
-			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-			"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-			"hasInstallScript": true,
-			"license": "MIT",
-			"optional": true,
-			"os": [
-				"darwin"
-			],
-			"engines": {
-				"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-			}
-		},
-		"node_modules/function-bind": {
-			"version": "1.1.2",
-			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-			"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-			"license": "MIT",
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"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==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6.9.0"
-			}
-		},
-		"node_modules/get-intrinsic": {
-			"version": "1.3.0",
-			"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
-			"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
-			"license": "MIT",
-			"dependencies": {
-				"call-bind-apply-helpers": "^1.0.2",
-				"es-define-property": "^1.0.1",
-				"es-errors": "^1.3.0",
-				"es-object-atoms": "^1.1.1",
-				"function-bind": "^1.1.2",
-				"get-proto": "^1.0.1",
-				"gopd": "^1.2.0",
-				"has-symbols": "^1.1.0",
-				"hasown": "^2.0.2",
-				"math-intrinsics": "^1.1.0"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/get-proto": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
-			"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
-			"license": "MIT",
-			"dependencies": {
-				"dunder-proto": "^1.0.1",
-				"es-object-atoms": "^1.0.0"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/glob-parent": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-			"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"is-glob": "^4.0.3"
-			},
-			"engines": {
-				"node": ">=10.13.0"
-			}
-		},
-		"node_modules/globals": {
-			"version": "16.5.0",
-			"resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
-			"integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=18"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/gopd": {
-			"version": "1.2.0",
-			"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
-			"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"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/has-flag": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-			"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/has-symbols": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
-			"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/has-tostringtag": {
-			"version": "1.0.2",
-			"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
-			"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
-			"license": "MIT",
-			"dependencies": {
-				"has-symbols": "^1.0.3"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/ljharb"
-			}
-		},
-		"node_modules/hasown": {
-			"version": "2.0.2",
-			"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
-			"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
-			"license": "MIT",
-			"dependencies": {
-				"function-bind": "^1.1.2"
-			},
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/hermes-estree": {
-			"version": "0.25.1",
-			"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
-			"integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/hermes-parser": {
-			"version": "0.25.1",
-			"resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
-			"integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"hermes-estree": "0.25.1"
-			}
-		},
-		"node_modules/ignore": {
-			"version": "5.3.2",
-			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
-			"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 4"
-			}
-		},
-		"node_modules/import-fresh": {
-			"version": "3.3.1",
-			"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
-			"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"parent-module": "^1.0.0",
-				"resolve-from": "^4.0.0"
-			},
-			"engines": {
-				"node": ">=6"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/imurmurhash": {
-			"version": "0.1.4",
-			"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-			"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.8.19"
-			}
-		},
-		"node_modules/is-extglob": {
-			"version": "2.1.1",
-			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-			"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/is-glob": {
-			"version": "4.0.3",
-			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-			"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"is-extglob": "^2.1.1"
-			},
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/isexe": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-			"dev": true,
-			"license": "ISC"
-		},
-		"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==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/js-yaml": {
-			"version": "4.1.1",
-			"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
-			"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"argparse": "^2.0.1"
-			},
-			"bin": {
-				"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==",
-			"dev": true,
-			"license": "MIT",
-			"bin": {
-				"jsesc": "bin/jsesc"
-			},
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/json-buffer": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-			"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/json-schema-traverse": {
-			"version": "0.4.1",
-			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/json-stable-stringify-without-jsonify": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-			"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/json5": {
-			"version": "2.2.3",
-			"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
-			"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
-			"dev": true,
-			"license": "MIT",
-			"bin": {
-				"json5": "lib/cli.js"
-			},
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/keyv": {
-			"version": "4.5.4",
-			"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
-			"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"json-buffer": "3.0.1"
-			}
-		},
-		"node_modules/levn": {
-			"version": "0.4.1",
-			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"prelude-ls": "^1.2.1",
-				"type-check": "~0.4.0"
-			},
-			"engines": {
-				"node": ">= 0.8.0"
-			}
-		},
-		"node_modules/lightningcss": {
-			"version": "1.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
-			"integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
-			"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.30.2",
-				"lightningcss-darwin-arm64": "1.30.2",
-				"lightningcss-darwin-x64": "1.30.2",
-				"lightningcss-freebsd-x64": "1.30.2",
-				"lightningcss-linux-arm-gnueabihf": "1.30.2",
-				"lightningcss-linux-arm64-gnu": "1.30.2",
-				"lightningcss-linux-arm64-musl": "1.30.2",
-				"lightningcss-linux-x64-gnu": "1.30.2",
-				"lightningcss-linux-x64-musl": "1.30.2",
-				"lightningcss-win32-arm64-msvc": "1.30.2",
-				"lightningcss-win32-x64-msvc": "1.30.2"
-			}
-		},
-		"node_modules/lightningcss-android-arm64": {
-			"version": "1.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
-			"integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
-			"integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
-			"integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
-			"integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
-			"integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
-			"integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
-			"integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
-			"integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
-			"integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
-			"integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
-			"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.30.2",
-			"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
-			"integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
-			"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/locate-path": {
-			"version": "6.0.0",
-			"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
-			"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"p-locate": "^5.0.0"
-			},
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/lodash.merge": {
-			"version": "4.6.2",
-			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"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==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"yallist": "^3.0.2"
-			}
-		},
-		"node_modules/lucide-react": {
-			"version": "0.563.0",
-			"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.563.0.tgz",
-			"integrity": "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA==",
-			"license": "ISC",
-			"peerDependencies": {
-				"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
-			}
-		},
-		"node_modules/magic-string": {
-			"version": "0.30.21",
-			"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
-			"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
-			"license": "MIT",
-			"dependencies": {
-				"@jridgewell/sourcemap-codec": "^1.5.5"
-			}
-		},
-		"node_modules/math-intrinsics": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
-			"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.4"
-			}
-		},
-		"node_modules/mime-db": {
-			"version": "1.52.0",
-			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
-			"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.6"
-			}
-		},
-		"node_modules/mime-types": {
-			"version": "2.1.35",
-			"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
-			"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-			"license": "MIT",
-			"dependencies": {
-				"mime-db": "1.52.0"
-			},
-			"engines": {
-				"node": ">= 0.6"
-			}
-		},
-		"node_modules/minimatch": {
-			"version": "3.1.2",
-			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-			"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"brace-expansion": "^1.1.7"
-			},
-			"engines": {
-				"node": "*"
-			}
-		},
-		"node_modules/ms": {
-			"version": "2.1.3",
-			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-			"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/nanoid": {
-			"version": "3.3.11",
-			"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
-			"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
-			"funding": [
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/ai"
-				}
-			],
-			"license": "MIT",
-			"bin": {
-				"nanoid": "bin/nanoid.cjs"
-			},
-			"engines": {
-				"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-			}
-		},
-		"node_modules/natural-compare": {
-			"version": "1.4.0",
-			"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-			"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/node-releases": {
-			"version": "2.0.27",
-			"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
-			"integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
-			"dev": true,
-			"license": "MIT"
-		},
-		"node_modules/optionator": {
-			"version": "0.9.4",
-			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
-			"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"deep-is": "^0.1.3",
-				"fast-levenshtein": "^2.0.6",
-				"levn": "^0.4.1",
-				"prelude-ls": "^1.2.1",
-				"type-check": "^0.4.0",
-				"word-wrap": "^1.2.5"
-			},
-			"engines": {
-				"node": ">= 0.8.0"
-			}
-		},
-		"node_modules/p-limit": {
-			"version": "3.1.0",
-			"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-			"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"yocto-queue": "^0.1.0"
-			},
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/p-locate": {
-			"version": "5.0.0",
-			"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
-			"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"p-limit": "^3.0.2"
-			},
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/parent-module": {
-			"version": "1.0.1",
-			"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-			"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"callsites": "^3.0.0"
-			},
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/path-exists": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-			"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/path-key": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-			"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/picocolors": {
-			"version": "1.1.1",
-			"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
-			"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
-			"license": "ISC"
-		},
-		"node_modules/picomatch": {
-			"version": "4.0.3",
-			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
-			"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=12"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/jonschlinkert"
-			}
-		},
-		"node_modules/postcss": {
-			"version": "8.5.6",
-			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
-			"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
-			"funding": [
-				{
-					"type": "opencollective",
-					"url": "https://opencollective.com/postcss/"
-				},
-				{
-					"type": "tidelift",
-					"url": "https://tidelift.com/funding/github/npm/postcss"
-				},
-				{
-					"type": "github",
-					"url": "https://github.com/sponsors/ai"
-				}
-			],
-			"license": "MIT",
-			"dependencies": {
-				"nanoid": "^3.3.11",
-				"picocolors": "^1.1.1",
-				"source-map-js": "^1.2.1"
-			},
-			"engines": {
-				"node": "^10 || ^12 || >=14"
-			}
-		},
-		"node_modules/prelude-ls": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">= 0.8.0"
-			}
-		},
-		"node_modules/proxy-from-env": {
-			"version": "1.1.0",
-			"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
-			"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
-			"license": "MIT"
-		},
-		"node_modules/punycode": {
-			"version": "2.3.1",
-			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
-			"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=6"
-			}
-		},
-		"node_modules/react": {
-			"version": "19.2.3",
-			"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
-			"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/react-dom": {
-			"version": "19.2.3",
-			"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
-			"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
-			"license": "MIT",
-			"dependencies": {
-				"scheduler": "^0.27.0"
-			},
-			"peerDependencies": {
-				"react": "^19.2.3"
-			}
-		},
-		"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==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/react-router": {
-			"version": "7.13.0",
-			"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz",
-			"integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==",
-			"license": "MIT",
-			"dependencies": {
-				"cookie": "^1.0.1",
-				"set-cookie-parser": "^2.6.0"
-			},
-			"engines": {
-				"node": ">=20.0.0"
-			},
-			"peerDependencies": {
-				"react": ">=18",
-				"react-dom": ">=18"
-			},
-			"peerDependenciesMeta": {
-				"react-dom": {
-					"optional": true
-				}
-			}
-		},
-		"node_modules/react-router-dom": {
-			"version": "7.13.0",
-			"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz",
-			"integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==",
-			"license": "MIT",
-			"dependencies": {
-				"react-router": "7.13.0"
-			},
-			"engines": {
-				"node": ">=20.0.0"
-			},
-			"peerDependencies": {
-				"react": ">=18",
-				"react-dom": ">=18"
-			}
-		},
-		"node_modules/react-toastify": {
-			"version": "11.0.5",
-			"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz",
-			"integrity": "sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA==",
-			"license": "MIT",
-			"dependencies": {
-				"clsx": "^2.1.1"
-			},
-			"peerDependencies": {
-				"react": "^18 || ^19",
-				"react-dom": "^18 || ^19"
-			}
-		},
-		"node_modules/resolve-from": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-			"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=4"
-			}
-		},
-		"node_modules/rollup": {
-			"version": "4.55.1",
-			"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz",
-			"integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==",
-			"license": "MIT",
-			"dependencies": {
-				"@types/estree": "1.0.8"
-			},
-			"bin": {
-				"rollup": "dist/bin/rollup"
-			},
-			"engines": {
-				"node": ">=18.0.0",
-				"npm": ">=8.0.0"
-			},
-			"optionalDependencies": {
-				"@rollup/rollup-android-arm-eabi": "4.55.1",
-				"@rollup/rollup-android-arm64": "4.55.1",
-				"@rollup/rollup-darwin-arm64": "4.55.1",
-				"@rollup/rollup-darwin-x64": "4.55.1",
-				"@rollup/rollup-freebsd-arm64": "4.55.1",
-				"@rollup/rollup-freebsd-x64": "4.55.1",
-				"@rollup/rollup-linux-arm-gnueabihf": "4.55.1",
-				"@rollup/rollup-linux-arm-musleabihf": "4.55.1",
-				"@rollup/rollup-linux-arm64-gnu": "4.55.1",
-				"@rollup/rollup-linux-arm64-musl": "4.55.1",
-				"@rollup/rollup-linux-loong64-gnu": "4.55.1",
-				"@rollup/rollup-linux-loong64-musl": "4.55.1",
-				"@rollup/rollup-linux-ppc64-gnu": "4.55.1",
-				"@rollup/rollup-linux-ppc64-musl": "4.55.1",
-				"@rollup/rollup-linux-riscv64-gnu": "4.55.1",
-				"@rollup/rollup-linux-riscv64-musl": "4.55.1",
-				"@rollup/rollup-linux-s390x-gnu": "4.55.1",
-				"@rollup/rollup-linux-x64-gnu": "4.55.1",
-				"@rollup/rollup-linux-x64-musl": "4.55.1",
-				"@rollup/rollup-openbsd-x64": "4.55.1",
-				"@rollup/rollup-openharmony-arm64": "4.55.1",
-				"@rollup/rollup-win32-arm64-msvc": "4.55.1",
-				"@rollup/rollup-win32-ia32-msvc": "4.55.1",
-				"@rollup/rollup-win32-x64-gnu": "4.55.1",
-				"@rollup/rollup-win32-x64-msvc": "4.55.1",
-				"fsevents": "~2.3.2"
-			}
-		},
-		"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": "6.3.1",
-			"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
-			"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
-			"dev": true,
-			"license": "ISC",
-			"bin": {
-				"semver": "bin/semver.js"
-			}
-		},
-		"node_modules/set-cookie-parser": {
-			"version": "2.7.2",
-			"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
-			"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
-			"license": "MIT"
-		},
-		"node_modules/shebang-command": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-			"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"shebang-regex": "^3.0.0"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/shebang-regex": {
-			"version": "3.0.0",
-			"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-			"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/source-map-js": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
-			"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
-			"license": "BSD-3-Clause",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/strip-json-comments": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-			"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=8"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/supports-color": {
-			"version": "7.2.0",
-			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-			"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"has-flag": "^4.0.0"
-			},
-			"engines": {
-				"node": ">=8"
-			}
-		},
-		"node_modules/tailwindcss": {
-			"version": "4.1.18",
-			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
-			"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
-			"license": "MIT"
-		},
-		"node_modules/tapable": {
-			"version": "2.3.0",
-			"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
-			"integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
-			"license": "MIT",
-			"engines": {
-				"node": ">=6"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/webpack"
-			}
-		},
-		"node_modules/tinyglobby": {
-			"version": "0.2.15",
-			"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
-			"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
-			"license": "MIT",
-			"dependencies": {
-				"fdir": "^6.5.0",
-				"picomatch": "^4.0.3"
-			},
-			"engines": {
-				"node": ">=12.0.0"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/SuperchupuDev"
-			}
-		},
-		"node_modules/ts-api-utils": {
-			"version": "2.4.0",
-			"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
-			"integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=18.12"
-			},
-			"peerDependencies": {
-				"typescript": ">=4.8.4"
-			}
-		},
-		"node_modules/type-check": {
-			"version": "0.4.0",
-			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"prelude-ls": "^1.2.1"
-			},
-			"engines": {
-				"node": ">= 0.8.0"
-			}
-		},
-		"node_modules/typescript": {
-			"version": "5.9.3",
-			"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
-			"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
-			"dev": true,
-			"license": "Apache-2.0",
-			"bin": {
-				"tsc": "bin/tsc",
-				"tsserver": "bin/tsserver"
-			},
-			"engines": {
-				"node": ">=14.17"
-			}
-		},
-		"node_modules/typescript-eslint": {
-			"version": "8.53.0",
-			"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.53.0.tgz",
-			"integrity": "sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==",
-			"dev": true,
-			"license": "MIT",
-			"dependencies": {
-				"@typescript-eslint/eslint-plugin": "8.53.0",
-				"@typescript-eslint/parser": "8.53.0",
-				"@typescript-eslint/typescript-estree": "8.53.0",
-				"@typescript-eslint/utils": "8.53.0"
-			},
-			"engines": {
-				"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
-			},
-			"funding": {
-				"type": "opencollective",
-				"url": "https://opencollective.com/typescript-eslint"
-			},
-			"peerDependencies": {
-				"eslint": "^8.57.0 || ^9.0.0",
-				"typescript": ">=4.8.4 <6.0.0"
-			}
-		},
-		"node_modules/undici-types": {
-			"version": "7.16.0",
-			"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
-			"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
-			"devOptional": true,
-			"license": "MIT"
-		},
-		"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==",
-			"dev": true,
-			"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/uri-js": {
-			"version": "4.4.1",
-			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-			"dev": true,
-			"license": "BSD-2-Clause",
-			"dependencies": {
-				"punycode": "^2.1.0"
-			}
-		},
-		"node_modules/vite": {
-			"version": "7.3.1",
-			"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
-			"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
-			"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/which": {
-			"version": "2.0.2",
-			"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-			"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-			"dev": true,
-			"license": "ISC",
-			"dependencies": {
-				"isexe": "^2.0.0"
-			},
-			"bin": {
-				"node-which": "bin/node-which"
-			},
-			"engines": {
-				"node": ">= 8"
-			}
-		},
-		"node_modules/word-wrap": {
-			"version": "1.2.5",
-			"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
-			"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=0.10.0"
-			}
-		},
-		"node_modules/yallist": {
-			"version": "3.1.1",
-			"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
-			"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
-			"dev": true,
-			"license": "ISC"
-		},
-		"node_modules/yocto-queue": {
-			"version": "0.1.0",
-			"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-			"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=10"
-			},
-			"funding": {
-				"url": "https://github.com/sponsors/sindresorhus"
-			}
-		},
-		"node_modules/zod": {
-			"version": "4.3.5",
-			"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz",
-			"integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==",
-			"dev": true,
-			"license": "MIT",
-			"funding": {
-				"url": "https://github.com/sponsors/colinhacks"
-			}
-		},
-		"node_modules/zod-validation-error": {
-			"version": "4.0.2",
-			"resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
-			"integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
-			"dev": true,
-			"license": "MIT",
-			"engines": {
-				"node": ">=18.0.0"
-			},
-			"peerDependencies": {
-				"zod": "^3.25.0 || ^4.0.0"
-			}
-		}
-	}
+  "name": "frontend",
+  "version": "0.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "frontend",
+      "version": "0.0.0",
+      "dependencies": {
+        "@tailwindcss/vite": "^4.1.18",
+        "react": "^19.2.0",
+        "react-dom": "^19.2.0",
+        "tailwindcss": "^4.1.18"
+      },
+      "devDependencies": {
+        "@eslint/js": "^9.39.1",
+        "@types/node": "^24.10.1",
+        "@types/react": "^19.2.5",
+        "@types/react-dom": "^19.2.3",
+        "@vitejs/plugin-react": "^5.1.1",
+        "eslint": "^9.39.1",
+        "eslint-plugin-react-hooks": "^7.0.1",
+        "eslint-plugin-react-refresh": "^0.4.24",
+        "globals": "^16.5.0",
+        "typescript": "~5.9.3",
+        "typescript-eslint": "^8.46.4",
+        "vite": "^7.2.4"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
+      "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+      "dev": true,
+      "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.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz",
+      "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz",
+      "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.28.6",
+        "@babel/generator": "^7.28.6",
+        "@babel/helper-compilation-targets": "^7.28.6",
+        "@babel/helper-module-transforms": "^7.28.6",
+        "@babel/helpers": "^7.28.6",
+        "@babel/parser": "^7.28.6",
+        "@babel/template": "^7.28.6",
+        "@babel/traverse": "^7.28.6",
+        "@babel/types": "^7.28.6",
+        "@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/generator": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz",
+      "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.28.6",
+        "@babel/types": "^7.28.6",
+        "@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==",
+      "dev": true,
+      "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-globals": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+      "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.28.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+      "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "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==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+      "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
+      "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.28.6"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz",
+      "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.28.6",
+        "@babel/generator": "^7.28.6",
+        "@babel/helper-globals": "^7.28.0",
+        "@babel/parser": "^7.28.6",
+        "@babel/template": "^7.28.6",
+        "@babel/types": "^7.28.6",
+        "debug": "^4.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
+      "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.28.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
+      "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
+      "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
+      "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
+      "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
+      "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
+      "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
+      "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
+      "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
+      "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
+      "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
+      "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
+      "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
+      "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
+      "cpu": [
+        "mips64el"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
+      "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
+      "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
+      "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
+      "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
+      "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
+      "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
+      "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
+      "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openharmony-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
+      "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
+      "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
+      "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
+      "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
+      "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.9.1",
+      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+      "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "eslint-visitor-keys": "^3.4.3"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.12.2",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+      "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@eslint/config-array": {
+      "version": "0.21.1",
+      "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+      "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/object-schema": "^2.1.7",
+        "debug": "^4.3.1",
+        "minimatch": "^3.1.2"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/config-helpers": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+      "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/core": "^0.17.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/core": {
+      "version": "0.17.0",
+      "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+      "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@types/json-schema": "^7.0.15"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/eslintrc": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+      "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^10.0.1",
+        "globals": "^14.0.0",
+        "ignore": "^5.2.0",
+        "import-fresh": "^3.2.1",
+        "js-yaml": "^4.1.1",
+        "minimatch": "^3.1.2",
+        "strip-json-comments": "^3.1.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/globals": {
+      "version": "14.0.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+      "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@eslint/js": {
+      "version": "9.39.2",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
+      "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
+      }
+    },
+    "node_modules/@eslint/object-schema": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+      "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/plugin-kit": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+      "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/core": "^0.17.0",
+        "levn": "^0.4.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@humanfs/core": {
+      "version": "0.19.1",
+      "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+      "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/@humanfs/node": {
+      "version": "0.16.7",
+      "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+      "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@humanfs/core": "^0.19.1",
+        "@humanwhocodes/retry": "^0.4.0"
+      },
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/retry": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+      "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "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/@rolldown/pluginutils": {
+      "version": "1.0.0-beta.53",
+      "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.53.tgz",
+      "integrity": "sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz",
+      "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz",
+      "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz",
+      "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz",
+      "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz",
+      "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz",
+      "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz",
+      "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz",
+      "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz",
+      "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz",
+      "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz",
+      "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-musl": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz",
+      "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz",
+      "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz",
+      "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz",
+      "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz",
+      "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz",
+      "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz",
+      "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz",
+      "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-openbsd-x64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz",
+      "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-openharmony-arm64": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz",
+      "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz",
+      "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz",
+      "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-gnu": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz",
+      "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz",
+      "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@tailwindcss/node": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz",
+      "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/remapping": "^2.3.4",
+        "enhanced-resolve": "^5.18.3",
+        "jiti": "^2.6.1",
+        "lightningcss": "1.30.2",
+        "magic-string": "^0.30.21",
+        "source-map-js": "^1.2.1",
+        "tailwindcss": "4.1.18"
+      }
+    },
+    "node_modules/@tailwindcss/oxide": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz",
+      "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10"
+      },
+      "optionalDependencies": {
+        "@tailwindcss/oxide-android-arm64": "4.1.18",
+        "@tailwindcss/oxide-darwin-arm64": "4.1.18",
+        "@tailwindcss/oxide-darwin-x64": "4.1.18",
+        "@tailwindcss/oxide-freebsd-x64": "4.1.18",
+        "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18",
+        "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18",
+        "@tailwindcss/oxide-linux-arm64-musl": "4.1.18",
+        "@tailwindcss/oxide-linux-x64-gnu": "4.1.18",
+        "@tailwindcss/oxide-linux-x64-musl": "4.1.18",
+        "@tailwindcss/oxide-wasm32-wasi": "4.1.18",
+        "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18",
+        "@tailwindcss/oxide-win32-x64-msvc": "4.1.18"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-android-arm64": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz",
+      "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-darwin-arm64": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz",
+      "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-darwin-x64": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz",
+      "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-freebsd-x64": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz",
+      "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz",
+      "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz",
+      "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz",
+      "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz",
+      "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-linux-x64-musl": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz",
+      "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-wasm32-wasi": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz",
+      "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==",
+      "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.7.1",
+        "@emnapi/runtime": "^1.7.1",
+        "@emnapi/wasi-threads": "^1.1.0",
+        "@napi-rs/wasm-runtime": "^1.1.0",
+        "@tybys/wasm-util": "^0.10.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz",
+      "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz",
+      "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@tailwindcss/vite": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz",
+      "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==",
+      "license": "MIT",
+      "dependencies": {
+        "@tailwindcss/node": "4.1.18",
+        "@tailwindcss/oxide": "4.1.18",
+        "tailwindcss": "4.1.18"
+      },
+      "peerDependencies": {
+        "vite": "^5.2.0 || ^6 || ^7"
+      }
+    },
+    "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.28.2"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+      "license": "MIT"
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/node": {
+      "version": "24.10.9",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz",
+      "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==",
+      "devOptional": true,
+      "license": "MIT",
+      "dependencies": {
+        "undici-types": "~7.16.0"
+      }
+    },
+    "node_modules/@types/react": {
+      "version": "19.2.8",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz",
+      "integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==",
+      "dev": true,
+      "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==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "@types/react": "^19.2.0"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz",
+      "integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/regexpp": "^4.12.2",
+        "@typescript-eslint/scope-manager": "8.53.0",
+        "@typescript-eslint/type-utils": "8.53.0",
+        "@typescript-eslint/utils": "8.53.0",
+        "@typescript-eslint/visitor-keys": "8.53.0",
+        "ignore": "^7.0.5",
+        "natural-compare": "^1.4.0",
+        "ts-api-utils": "^2.4.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "@typescript-eslint/parser": "^8.53.0",
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+      "version": "7.0.5",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+      "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/@typescript-eslint/parser": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz",
+      "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/scope-manager": "8.53.0",
+        "@typescript-eslint/types": "8.53.0",
+        "@typescript-eslint/typescript-estree": "8.53.0",
+        "@typescript-eslint/visitor-keys": "8.53.0",
+        "debug": "^4.4.3"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/project-service": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.0.tgz",
+      "integrity": "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/tsconfig-utils": "^8.53.0",
+        "@typescript-eslint/types": "^8.53.0",
+        "debug": "^4.4.3"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/scope-manager": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz",
+      "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/types": "8.53.0",
+        "@typescript-eslint/visitor-keys": "8.53.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/tsconfig-utils": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.0.tgz",
+      "integrity": "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/type-utils": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz",
+      "integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/types": "8.53.0",
+        "@typescript-eslint/typescript-estree": "8.53.0",
+        "@typescript-eslint/utils": "8.53.0",
+        "debug": "^4.4.3",
+        "ts-api-utils": "^2.4.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/types": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz",
+      "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz",
+      "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/project-service": "8.53.0",
+        "@typescript-eslint/tsconfig-utils": "8.53.0",
+        "@typescript-eslint/types": "8.53.0",
+        "@typescript-eslint/visitor-keys": "8.53.0",
+        "debug": "^4.4.3",
+        "minimatch": "^9.0.5",
+        "semver": "^7.7.3",
+        "tinyglobby": "^0.2.15",
+        "ts-api-utils": "^2.4.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+      "version": "7.7.3",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+      "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@typescript-eslint/utils": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz",
+      "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.9.1",
+        "@typescript-eslint/scope-manager": "8.53.0",
+        "@typescript-eslint/types": "8.53.0",
+        "@typescript-eslint/typescript-estree": "8.53.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/@typescript-eslint/visitor-keys": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz",
+      "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/types": "8.53.0",
+        "eslint-visitor-keys": "^4.2.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
+    "node_modules/@vitejs/plugin-react": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.2.tgz",
+      "integrity": "sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/core": "^7.28.5",
+        "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+        "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+        "@rolldown/pluginutils": "1.0.0-beta.53",
+        "@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"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.15.0",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+      "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "fast-json-stable-stringify": "^2.0.0",
+        "json-schema-traverse": "^0.4.1",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true,
+      "license": "Python-2.0"
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/baseline-browser-mapping": {
+      "version": "2.9.15",
+      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz",
+      "integrity": "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "baseline-browser-mapping": "dist/cli.js"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.12",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+      "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.28.1",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+      "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+      "dev": true,
+      "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.9.0",
+        "caniuse-lite": "^1.0.30001759",
+        "electron-to-chromium": "^1.5.263",
+        "node-releases": "^2.0.27",
+        "update-browserslist-db": "^1.2.0"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001764",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz",
+      "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==",
+      "dev": true,
+      "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/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "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==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "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==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.4.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/detect-libc": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+      "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.267",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
+      "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/enhanced-resolve": {
+      "version": "5.18.4",
+      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz",
+      "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==",
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.4",
+        "tapable": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.27.2",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
+      "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.27.2",
+        "@esbuild/android-arm": "0.27.2",
+        "@esbuild/android-arm64": "0.27.2",
+        "@esbuild/android-x64": "0.27.2",
+        "@esbuild/darwin-arm64": "0.27.2",
+        "@esbuild/darwin-x64": "0.27.2",
+        "@esbuild/freebsd-arm64": "0.27.2",
+        "@esbuild/freebsd-x64": "0.27.2",
+        "@esbuild/linux-arm": "0.27.2",
+        "@esbuild/linux-arm64": "0.27.2",
+        "@esbuild/linux-ia32": "0.27.2",
+        "@esbuild/linux-loong64": "0.27.2",
+        "@esbuild/linux-mips64el": "0.27.2",
+        "@esbuild/linux-ppc64": "0.27.2",
+        "@esbuild/linux-riscv64": "0.27.2",
+        "@esbuild/linux-s390x": "0.27.2",
+        "@esbuild/linux-x64": "0.27.2",
+        "@esbuild/netbsd-arm64": "0.27.2",
+        "@esbuild/netbsd-x64": "0.27.2",
+        "@esbuild/openbsd-arm64": "0.27.2",
+        "@esbuild/openbsd-x64": "0.27.2",
+        "@esbuild/openharmony-arm64": "0.27.2",
+        "@esbuild/sunos-x64": "0.27.2",
+        "@esbuild/win32-arm64": "0.27.2",
+        "@esbuild/win32-ia32": "0.27.2",
+        "@esbuild/win32-x64": "0.27.2"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "9.39.2",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
+      "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.8.0",
+        "@eslint-community/regexpp": "^4.12.1",
+        "@eslint/config-array": "^0.21.1",
+        "@eslint/config-helpers": "^0.4.2",
+        "@eslint/core": "^0.17.0",
+        "@eslint/eslintrc": "^3.3.1",
+        "@eslint/js": "9.39.2",
+        "@eslint/plugin-kit": "^0.4.1",
+        "@humanfs/node": "^0.16.6",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@humanwhocodes/retry": "^0.4.2",
+        "@types/estree": "^1.0.6",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.6",
+        "debug": "^4.3.2",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^8.4.0",
+        "eslint-visitor-keys": "^4.2.1",
+        "espree": "^10.4.0",
+        "esquery": "^1.5.0",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^8.0.0",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
+      },
+      "peerDependencies": {
+        "jiti": "*"
+      },
+      "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-plugin-react-hooks": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+      "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/core": "^7.24.4",
+        "@babel/parser": "^7.24.4",
+        "hermes-parser": "^0.25.1",
+        "zod": "^3.25.0 || ^4.0.0",
+        "zod-validation-error": "^3.5.0 || ^4.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-react-refresh": {
+      "version": "0.4.26",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz",
+      "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "eslint": ">=8.40"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "8.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+      "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+      "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/espree": {
+      "version": "10.4.0",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+      "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "acorn": "^8.15.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^4.2.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+      "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/file-entry-cache": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+      "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "flat-cache": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+      "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "flatted": "^3.2.9",
+        "keyv": "^4.5.4"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+      "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "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==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/globals": {
+      "version": "16.5.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
+      "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "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/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/hermes-estree": {
+      "version": "0.25.1",
+      "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+      "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/hermes-parser": {
+      "version": "0.25.1",
+      "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+      "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "hermes-estree": "0.25.1"
+      }
+    },
+    "node_modules/ignore": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+      "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+      "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "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==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/js-yaml": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+      "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "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==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/json-buffer": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/keyv": {
+      "version": "4.5.4",
+      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "json-buffer": "3.0.1"
+      }
+    },
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/lightningcss": {
+      "version": "1.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
+      "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
+      "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.30.2",
+        "lightningcss-darwin-arm64": "1.30.2",
+        "lightningcss-darwin-x64": "1.30.2",
+        "lightningcss-freebsd-x64": "1.30.2",
+        "lightningcss-linux-arm-gnueabihf": "1.30.2",
+        "lightningcss-linux-arm64-gnu": "1.30.2",
+        "lightningcss-linux-arm64-musl": "1.30.2",
+        "lightningcss-linux-x64-gnu": "1.30.2",
+        "lightningcss-linux-x64-musl": "1.30.2",
+        "lightningcss-win32-arm64-msvc": "1.30.2",
+        "lightningcss-win32-x64-msvc": "1.30.2"
+      }
+    },
+    "node_modules/lightningcss-android-arm64": {
+      "version": "1.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
+      "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
+      "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
+      "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
+      "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
+      "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
+      "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
+      "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
+      "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
+      "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
+      "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
+      "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.30.2",
+      "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
+      "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
+      "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/locate-path": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "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==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.27",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+      "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/optionator": {
+      "version": "0.9.4",
+      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+      "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0",
+        "word-wrap": "^1.2.5"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/picomatch": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.6",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+      "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/react": {
+      "version": "19.2.3",
+      "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
+      "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-dom": {
+      "version": "19.2.3",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
+      "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
+      "license": "MIT",
+      "dependencies": {
+        "scheduler": "^0.27.0"
+      },
+      "peerDependencies": {
+        "react": "^19.2.3"
+      }
+    },
+    "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==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.55.1",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz",
+      "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.8"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.55.1",
+        "@rollup/rollup-android-arm64": "4.55.1",
+        "@rollup/rollup-darwin-arm64": "4.55.1",
+        "@rollup/rollup-darwin-x64": "4.55.1",
+        "@rollup/rollup-freebsd-arm64": "4.55.1",
+        "@rollup/rollup-freebsd-x64": "4.55.1",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.55.1",
+        "@rollup/rollup-linux-arm-musleabihf": "4.55.1",
+        "@rollup/rollup-linux-arm64-gnu": "4.55.1",
+        "@rollup/rollup-linux-arm64-musl": "4.55.1",
+        "@rollup/rollup-linux-loong64-gnu": "4.55.1",
+        "@rollup/rollup-linux-loong64-musl": "4.55.1",
+        "@rollup/rollup-linux-ppc64-gnu": "4.55.1",
+        "@rollup/rollup-linux-ppc64-musl": "4.55.1",
+        "@rollup/rollup-linux-riscv64-gnu": "4.55.1",
+        "@rollup/rollup-linux-riscv64-musl": "4.55.1",
+        "@rollup/rollup-linux-s390x-gnu": "4.55.1",
+        "@rollup/rollup-linux-x64-gnu": "4.55.1",
+        "@rollup/rollup-linux-x64-musl": "4.55.1",
+        "@rollup/rollup-openbsd-x64": "4.55.1",
+        "@rollup/rollup-openharmony-arm64": "4.55.1",
+        "@rollup/rollup-win32-arm64-msvc": "4.55.1",
+        "@rollup/rollup-win32-ia32-msvc": "4.55.1",
+        "@rollup/rollup-win32-x64-gnu": "4.55.1",
+        "@rollup/rollup-win32-x64-msvc": "4.55.1",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "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": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tailwindcss": {
+      "version": "4.1.18",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
+      "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
+      "license": "MIT"
+    },
+    "node_modules/tapable": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+      "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/tinyglobby": {
+      "version": "0.2.15",
+      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+      "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+      "license": "MIT",
+      "dependencies": {
+        "fdir": "^6.5.0",
+        "picomatch": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev"
+      }
+    },
+    "node_modules/ts-api-utils": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz",
+      "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.12"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.8.4"
+      }
+    },
+    "node_modules/type-check": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/typescript-eslint": {
+      "version": "8.53.0",
+      "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.53.0.tgz",
+      "integrity": "sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@typescript-eslint/eslint-plugin": "8.53.0",
+        "@typescript-eslint/parser": "8.53.0",
+        "@typescript-eslint/typescript-estree": "8.53.0",
+        "@typescript-eslint/utils": "8.53.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^8.57.0 || ^9.0.0",
+        "typescript": ">=4.8.4 <6.0.0"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "7.16.0",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+      "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+      "devOptional": true,
+      "license": "MIT"
+    },
+    "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==",
+      "dev": true,
+      "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/uri-js": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/vite": {
+      "version": "7.3.1",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
+      "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
+      "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/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/word-wrap": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+      "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/zod": {
+      "version": "4.3.5",
+      "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz",
+      "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/colinhacks"
+      }
+    },
+    "node_modules/zod-validation-error": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+      "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "peerDependencies": {
+        "zod": "^3.25.0 || ^4.0.0"
+      }
+    }
+  }
 }
Index: frontend/package.json
===================================================================
--- frontend/package.json	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ frontend/package.json	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -1,36 +1,32 @@
 {
-	"name": "frontend",
-	"private": true,
-	"version": "0.0.0",
-	"type": "module",
-	"scripts": {
-		"dev": "vite",
-		"build": "tsc -b && vite build",
-		"lint": "eslint .",
-		"preview": "vite preview"
-	},
-	"dependencies": {
-		"@tailwindcss/vite": "^4.1.18",
-		"axios": "^1.13.3",
-		"lucide-react": "^0.563.0",
-		"react": "^19.2.0",
-		"react-dom": "^19.2.0",
-		"react-router-dom": "^7.13.0",
-		"react-toastify": "^11.0.5",
-		"tailwindcss": "^4.1.18"
-	},
-	"devDependencies": {
-		"@eslint/js": "^9.39.1",
-		"@types/node": "^24.10.1",
-		"@types/react": "^19.2.5",
-		"@types/react-dom": "^19.2.3",
-		"@vitejs/plugin-react": "^5.1.1",
-		"eslint": "^9.39.1",
-		"eslint-plugin-react-hooks": "^7.0.1",
-		"eslint-plugin-react-refresh": "^0.4.24",
-		"globals": "^16.5.0",
-		"typescript": "~5.9.3",
-		"typescript-eslint": "^8.46.4",
-		"vite": "^7.2.4"
-	}
+  "name": "frontend",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "tsc -b && vite build",
+    "lint": "eslint .",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@tailwindcss/vite": "^4.1.18",
+    "react": "^19.2.0",
+    "react-dom": "^19.2.0",
+    "tailwindcss": "^4.1.18"
+  },
+  "devDependencies": {
+    "@eslint/js": "^9.39.1",
+    "@types/node": "^24.10.1",
+    "@types/react": "^19.2.5",
+    "@types/react-dom": "^19.2.3",
+    "@vitejs/plugin-react": "^5.1.1",
+    "eslint": "^9.39.1",
+    "eslint-plugin-react-hooks": "^7.0.1",
+    "eslint-plugin-react-refresh": "^0.4.24",
+    "globals": "^16.5.0",
+    "typescript": "~5.9.3",
+    "typescript-eslint": "^8.46.4",
+    "vite": "^7.2.4"
+  }
 }
Index: frontend/public/vite.svg
===================================================================
--- frontend/public/vite.svg	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
+++ frontend/public/vite.svg	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -0,0 +1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
Index: frontend/src/App.tsx
===================================================================
--- frontend/src/App.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ frontend/src/App.tsx	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -1,136 +1,19 @@
-import { useEffect, useState } from "react";
-import {
-	createBrowserRouter,
-	Outlet,
-	RouterProvider,
-	useLocation,
-} from "react-router-dom";
-import { ToastContainer } from "react-toastify";
-import "react-toastify/dist/ReactToastify.css";
-import LoadingSpinner from "./components/LoadingSpinner";
-import MiniPlayer from "./components/MiniPlayer";
-import Sidebar from "./components/Sidebar";
-import { useAuth } from "./context/authContext";
-import { usePlayer } from "./context/playerContext";
-// import AllUsers from "./pages/AllUsers";
-import LandingPage from "./pages/LandingPage";
-import Login from "./pages/Login";
-import MusicalCollection from "./pages/MusicalCollection";
-import MySongs from "./pages/MySongs";
-import Nav from "./pages/Nav";
-import PublishSong from "./pages/PublishSong";
-import Register from "./pages/Register";
-import SongDetail from "./pages/SongDetail";
-import UserDetail from "./pages/UserDetail";
+import { useEffect } from "react";
 
-const MainLayout = () => {
-	const { user } = useAuth();
-	const { currentSong } = usePlayer();
-	const location = useLocation();
-	// show sidebar only if user is logged in and is on the landing page
-	const isLandingPage = location.pathname === "/";
-	const [isSidebarOpen, setIsSidebarOpen] = useState(
-		!!user && isLandingPage && !user?.isArtist && !user?.isAdmin,
-	);
-
-	// Open sidebar when user logs in and navigates to landing page
+function App() {
 	useEffect(() => {
-		if (user && isLandingPage && !user.isArtist && !user.isAdmin) {
-			setIsSidebarOpen(true);
-		}
-	}, [user, isLandingPage]);
+		const fetchData = async () => {
+			const response = await fetch("http://localhost:8080/");
+			const data = await response.json();
+			console.log(data);
+		};
+		fetchData();
+	});
 
 	return (
-		<div className="flex flex-col min-h-screen bg-[#121212]">
-			<Nav
-				isSidebarOpen={isSidebarOpen}
-				onToggleSidebar={() => setIsSidebarOpen(!isSidebarOpen)}
-			/>
-			<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
-			<ToastContainer
-				position="top-right"
-				autoClose={2000}
-				hideProgressBar={false}
-				newestOnTop={false}
-				closeOnClick
-				rtl={false}
-				pauseOnFocusLoss
-				draggable
-				pauseOnHover
-				theme="light"
-			/>
-			<main
-				className={`grow transition-all duration-300 pt-20 ${
-					isSidebarOpen ? "ml-64" : "ml-0"
-				} ${currentSong ? "pb-20" : ""}`}
-			>
-				<Outlet />
-			</main>
-			<MiniPlayer />
-		</div>
+		<>
+			<p className="text-red-500">ok</p>
+		</>
 	);
-};
-
-const Layout = () => {
-	const { isAuthLoading } = useAuth();
-
-	if (isAuthLoading) {
-		return <LoadingSpinner />;
-	}
-
-	return <MainLayout />;
-};
-
-const router = createBrowserRouter([
-	{
-		path: "",
-		element: <Layout />,
-		children: [
-			{
-				path: "/",
-				element: <LandingPage />,
-			},
-			{
-				path: "/login",
-				element: <Login />,
-			},
-			// {
-			// 	path: "/users",
-			// 	element: <AllUsers />,
-			// },
-			{
-				path: "/users/:username",
-				element: <UserDetail />,
-			},
-			{
-				path: "/register",
-				element: <Register />,
-			},
-			{
-				path: "/my-songs",
-				element: <MySongs />,
-			},
-			{
-				path: "/publish",
-				element: <PublishSong />,
-			},
-			{
-				path: "/songs/:id",
-				element: <SongDetail />,
-			},
-			{
-				path: "/collection/:type/:id",
-				element: <MusicalCollection />,
-			},
-			{
-				path: "/me",
-				element: <UserDetail />,
-			},
-		],
-	},
-]);
-
-function App() {
-	return <RouterProvider router={router} />;
 }
 
Index: ontend/src/api/axiosInstance.ts
===================================================================
--- frontend/src/api/axiosInstance.ts	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,90 +1,0 @@
-import axios from "axios";
-
-export const baseURL = import.meta.env.VITE_API_BASE_URL;
-
-export const axiosInstance = axios.create({
-	baseURL,
-	withCredentials: true,
-});
-
-// set content-type to application/json unless sending FormData
-axiosInstance.interceptors.request.use((config) => {
-	if (!(config.data instanceof FormData)) {
-		config.headers["Content-Type"] = "application/json";
-	}
-	return config;
-});
-
-let refreshPromise: Promise<void> | null = null;
-let refreshTimeout: number | null = null;
-
-export const clearRefreshTimeout = () => {
-	if (refreshTimeout) {
-		clearTimeout(refreshTimeout);
-		refreshTimeout = null;
-	}
-};
-
-export const scheduleTokenRefresh = (expiryTimeSeconds: number) => {
-	clearRefreshTimeout();
-
-	if (!expiryTimeSeconds || expiryTimeSeconds <= 0) {
-		return;
-	}
-
-	const refreshTime = (expiryTimeSeconds - 60) * 1000;
-	if (refreshTime <= 0) {
-		refreshTokenMethod();
-	} else {
-		refreshTimeout = setTimeout(refreshTokenMethod, refreshTime);
-	}
-};
-
-export const refreshTokenMethod = async (): Promise<void | null> => {
-	if (refreshPromise) {
-		return refreshPromise;
-	}
-
-	refreshPromise = (async () => {
-		try {
-			const refreshResponse = await axiosInstance.post<{
-				tokenExpiresIn: number;
-			}>("/auth/refresh");
-			scheduleTokenRefresh(refreshResponse.data.tokenExpiresIn);
-		} catch (err) {
-			clearRefreshTimeout();
-			console.error(err);
-			throw err;
-		} finally {
-			refreshPromise = null;
-		}
-	})();
-	return refreshPromise;
-};
-
-axiosInstance.interceptors.response.use(
-	(response) => response,
-	async (error) => {
-		const originalConfig = error.config;
-		if (
-			[401, 403].includes(error.response?.status) &&
-			!originalConfig._retry &&
-			originalConfig.url !== "/auth/refresh" &&
-			originalConfig.url !== "/auth/login" &&
-			originalConfig.url !== "/auth/register"
-		) {
-			originalConfig._retry = true;
-
-			try {
-				await refreshTokenMethod();
-				return axiosInstance(originalConfig);
-			} catch (err) {
-				clearRefreshTimeout();
-				return Promise.reject(err);
-			}
-		}
-		return Promise.reject(error);
-	},
-);
-
-export default axiosInstance;
Index: ontend/src/components/LoadingSpinner.tsx
===================================================================
--- frontend/src/components/LoadingSpinner.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,9 +1,0 @@
-const LoadingSpinner = () => {
-	return (
-		<div className="flex h-screen items-center justify-center bg-[#121212]">
-			<div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
-		</div>
-	);
-};
-
-export default LoadingSpinner;
Index: ontend/src/components/MiniPlayer.tsx
===================================================================
--- frontend/src/components/MiniPlayer.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,214 +1,0 @@
-import { baseURL } from "../api/axiosInstance";
-import { usePlayer } from "../context/playerContext";
-
-const MiniPlayer = () => {
-	const { currentSong, isMinimized, stop, toggleMinimize } = usePlayer();
-
-	if (!currentSong) return null;
-
-	return (
-		<>
-			{/* Fullscreen overlay - only visible when not minimized */}
-			<div
-				className={`fixed inset-0 z-100 bg-[#0a0a0f] flex flex-col transition-opacity duration-300 ${
-					isMinimized
-						? "opacity-0 pointer-events-none"
-						: "opacity-100 pointer-events-auto"
-				}`}
-			>
-				{/* Header bar */}
-				<div className="flex items-center justify-between px-6 py-4 bg-[#1a1a2e]/80 backdrop-blur-sm">
-					<div className="flex items-center gap-4">
-						<img
-							src={
-								currentSong.cover
-									? `${baseURL}/${currentSong.cover}`
-									: "/favicon.png"
-							}
-							alt={currentSong.title}
-							className="w-12 h-12 rounded-lg object-cover shadow-lg"
-							onError={(e) => {
-								(e.target as HTMLImageElement).src = "/favicon.png";
-							}}
-						/>
-						<div>
-							<p className="text-white font-semibold text-lg">
-								{currentSong.title}
-							</p>
-							<p className="text-gray-400 text-sm">{currentSong.artist}</p>
-						</div>
-					</div>
-
-					<div className="flex items-center gap-2">
-						{/* Minimize */}
-						<button
-							onClick={toggleMinimize}
-							className="text-gray-400 hover:text-white p-2.5 rounded-full hover:bg-white/10 transition-all"
-							aria-label="Minimize player"
-						>
-							<svg
-								className="w-6 h-6"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M19 14l-7 7m0 0l-7-7m7 7V3"
-								/>
-							</svg>
-						</button>
-
-						{/* Close */}
-						<button
-							onClick={stop}
-							className="text-gray-400 hover:text-red-400 p-2.5 rounded-full hover:bg-white/10 transition-all"
-							aria-label="Close player"
-						>
-							<svg
-								className="w-6 h-6"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M6 18L18 6M6 6l12 12"
-								/>
-							</svg>
-						</button>
-					</div>
-				</div>
-
-				{/* Video container - visible only in fullscreen */}
-				<div className="flex-1 flex items-center justify-center p-4">
-					<div
-						className={`w-full max-w-5xl aspect-video rounded-xl overflow-hidden shadow-2xl ${
-							isMinimized ? "invisible" : "visible"
-						}`}
-					>
-						{/* Single iframe - always mounted to preserve playback state */}
-						<iframe
-							key={currentSong.embedUrl}
-							src={`${currentSong.embedUrl}?autoplay=1`}
-							title={currentSong.title}
-							className="w-full h-full"
-							allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
-							allowFullScreen
-						/>
-					</div>
-				</div>
-			</div>
-
-			{/* Minimized bar - always visible at bottom */}
-			<div
-				className={`fixed bottom-0 left-0 right-0 z-100 h-16 bg-[#1a1a2e] border-t border-white/10 shadow-lg transition-transform duration-300 ${
-					isMinimized ? "translate-y-0" : "translate-y-full"
-				}`}
-			>
-				<div className="flex items-center justify-between px-4 h-full max-w-7xl mx-auto">
-					{/* Song info */}
-					<div className="flex items-center gap-3 min-w-0 flex-1">
-						<img
-							src={
-								currentSong.cover
-									? `${baseURL}/${currentSong.cover}`
-									: "/favicon.png"
-							}
-							alt={currentSong.title}
-							className="w-10 h-10 rounded object-cover shrink-0"
-							onError={(e) => {
-								(e.target as HTMLImageElement).src = "/favicon.png";
-							}}
-						/>
-						<div className="min-w-0">
-							<p className="text-white text-sm font-medium truncate">
-								{currentSong.title}
-							</p>
-							<p className="text-gray-400 text-xs truncate">
-								{currentSong.artist}
-							</p>
-						</div>
-					</div>
-
-					{/* Now playing indicator */}
-					<div className="hidden sm:flex items-center gap-1.5 px-4">
-						<div className="flex items-end gap-0.5 h-4">
-							<div
-								className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite]"
-								style={{ height: "60%" }}
-							/>
-							<div
-								className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite_0.1s]"
-								style={{ height: "100%" }}
-							/>
-							<div
-								className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite_0.2s]"
-								style={{ height: "40%" }}
-							/>
-							<div
-								className="w-1 bg-[#1db954] rounded-full animate-[bounce_0.6s_ease-in-out_infinite_0.3s]"
-								style={{ height: "80%" }}
-							/>
-						</div>
-						<span className="text-[#1db954] text-xs font-medium ml-1">
-							Playing
-						</span>
-					</div>
-
-					{/* Controls */}
-					<div className="flex items-center gap-1">
-						{/* Expand - shows fullscreen to allow seeking */}
-						<button
-							onClick={toggleMinimize}
-							className="text-gray-400 hover:text-white p-2 rounded-full hover:bg-white/10 transition-all"
-							aria-label="Expand player to seek"
-							title="Expand to seek in video"
-						>
-							<svg
-								className="w-5 h-5"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4"
-								/>
-							</svg>
-						</button>
-
-						{/* Close */}
-						<button
-							onClick={stop}
-							className="text-gray-400 hover:text-red-400 p-2 rounded-full hover:bg-white/10 transition-all"
-							aria-label="Close player"
-						>
-							<svg
-								className="w-5 h-5"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M6 18L18 6M6 6l12 12"
-								/>
-							</svg>
-						</button>
-					</div>
-				</div>
-			</div>
-		</>
-	);
-};
-
-export default MiniPlayer;
Index: ontend/src/components/Sidebar.tsx
===================================================================
--- frontend/src/components/Sidebar.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,281 +1,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import { useAuth } from "../context/authContext";
-import { usePlayer } from "../context/playerContext";
-import { useCreatedPlaylists } from "../context/playlistContext";
-import { getErrorMessage } from "../utils/error";
-import type { BasicSong, SidebarProps } from "../utils/types";
-import { toEmbedUrl } from "../utils/utils";
-import CreatePlaylistModal from "./playlist/CreatePlaylistModal";
-
-const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
-	const { user } = useAuth();
-	const {
-		createdPlaylists,
-		isLoading: playlistsLoading,
-		refreshPlaylists,
-	} = useCreatedPlaylists();
-	const navigate = useNavigate();
-	const { play, currentSong } = usePlayer();
-	const [recentlyListened, setRecentlyListened] = useState<BasicSong[]>([]);
-	const [songsLoading, setSongsLoading] = useState(false);
-	const [isModalOpen, setIsModalOpen] = useState(false);
-
-	useEffect(() => {
-		const fetchData = async () => {
-			setSongsLoading(true);
-			try {
-				const data = await axiosInstance.get<BasicSong[]>("/songs/recent");
-				setRecentlyListened(data.data);
-			} catch (error) {
-				toast.error(getErrorMessage(error));
-			} finally {
-				setSongsLoading(false);
-			}
-		};
-		if (user) {
-			fetchData();
-		} else {
-			setRecentlyListened([]);
-			setSongsLoading(false);
-		}
-	}, [user]);
-
-	const isLoading = songsLoading || playlistsLoading;
-
-	return (
-		<>
-			<div
-				className={`fixed left-0 top-0 h-full bg-[#121212] border-r border-white/10 transition-transform duration-300 ease-in-out z-40 ${
-					isOpen ? "translate-x-0" : "-translate-x-full"
-				} w-64 overflow-y-auto`}
-			>
-				<div className="p-6">
-					{/* Sidebar Header */}
-					<div className="flex justify-between items-center mb-6 pt-2">
-						<h2 className="text-xl font-bold text-white">Library</h2>
-						<button
-							onClick={onClose}
-							className="text-gray-400 hover:text-white transition-colors cursor-pointer"
-							aria-label="Close sidebar"
-						>
-							<svg
-								className="w-6 h-6"
-								fill="none"
-								stroke="currentColor"
-								viewBox="0 0 24 24"
-							>
-								<path
-									strokeLinecap="round"
-									strokeLinejoin="round"
-									strokeWidth={2}
-									d="M6 18L18 6M6 6l12 12"
-								/>
-							</svg>
-						</button>
-					</div>
-
-					{/* Loading State */}
-					{isLoading ? (
-						<div className="flex items-center justify-center py-16">
-							<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#1db954]"></div>
-						</div>
-					) : (
-						<>
-							{/* Recently Listened */}
-							<div className="mb-8">
-								<h3 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">
-									Recently Played
-								</h3>
-								<div className="space-y-3">
-									{recentlyListened.map((song) => (
-										<div
-											key={song.id}
-											className="flex items-center gap-3 p-2 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group relative"
-										>
-											<img
-												src={
-													song.cover
-														? `${baseURL}/${song.cover}`
-														: "/favicon.png"
-												}
-												alt={song.title}
-												className="w-10 h-10 rounded object-cover"
-												onError={(e) => {
-													(e.target as HTMLImageElement).src = "/favicon.png";
-												}}
-											/>
-											<div className="flex-1 min-w-0">
-												<p
-													onClick={() => navigate(`/songs/${song.id}`)}
-													className="text-sm font-medium text-white truncate hover:underline cursor-pointer"
-												>
-													{song.title}
-												</p>
-												<div className="flex items-center gap-1 text-xs text-gray-400">
-													<span
-														onClick={(e) => {
-															e.stopPropagation();
-															if (song.artistUsername) {
-																navigate(`/users/${song.artistUsername}`);
-															}
-														}}
-														className={`truncate ${
-															song.artistUsername
-																? "hover:underline cursor-pointer hover:text-white"
-																: ""
-														}`}
-													>
-														{song.artist}
-													</span>
-													{song.album && (
-														<>
-															<span>•</span>
-															<span
-																onClick={(e) => {
-																	e.stopPropagation();
-																	if (song.albumId) {
-																		navigate(
-																			`/collection/album/${song.albumId}`,
-																		);
-																	}
-																}}
-																className={`truncate ${
-																	song.albumId
-																		? "hover:underline cursor-pointer hover:text-white"
-																		: ""
-																}`}
-															>
-																{song.album}
-															</span>
-														</>
-													)}
-												</div>
-											</div>
-											{song.link && (
-												<button
-													onClick={(e) => {
-														e.stopPropagation();
-														play({
-															id: song.id,
-															title: song.title,
-															artist: song.artist,
-															cover: song.cover,
-															embedUrl: toEmbedUrl(song.link!),
-														});
-													}}
-													className={`p-1.5 rounded-full transition-all opacity-0 group-hover:opacity-100  ${
-														currentSong?.id === song.id
-															? "bg-white text-[#1db954]"
-															: "bg-[#1db954] text-black hover:scale-110 cursor-pointer"
-													}`}
-													aria-label={
-														currentSong?.id === song.id
-															? "Now playing"
-															: "Play song"
-													}
-												>
-													{currentSong?.id === song.id ? (
-														<svg
-															className="w-4 h-4"
-															fill="currentColor"
-															viewBox="0 0 24 24"
-														>
-															<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-														</svg>
-													) : (
-														<svg
-															className="w-4 h-4"
-															fill="currentColor"
-															viewBox="0 0 24 24"
-														>
-															<path d="M8 5v14l11-7z" />
-														</svg>
-													)}
-												</button>
-											)}
-										</div>
-									))}
-								</div>
-							</div>
-
-							{/* Playlists */}
-							<div>
-								<h3 className="text-sm font-semibold text-gray-400 uppercase tracking-wider mb-4">
-									Your Playlists
-								</h3>
-								<div className="space-y-2">
-									{createdPlaylists?.map((playlist) => (
-										<div
-											key={playlist.id}
-											onClick={() => {
-												navigate(`/collection/playlist/${playlist.id}`);
-											}}
-											className="flex items-center justify-between p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors"
-										>
-											<div className="flex items-center gap-3">
-												<div className="w-10 h-10 bg-linear-to-br from-purple-500 to-pink-500 rounded flex items-center justify-center">
-													<svg
-														className="w-5 h-5 text-white"
-														fill="currentColor"
-														viewBox="0 0 20 20"
-													>
-														<path d="M18 3a1 1 0 00-1.196-.98l-10 2A1 1 0 006 5v9.114A4.369 4.369 0 005 14c-1.657 0-3 .895-3 2s1.343 2 3 2 3-.895 3-2V7.82l8-1.6v5.894A4.37 4.37 0 0015 12c-1.657 0-3 .895-3 2s1.343 2 3 2 3-.895 3-2V3z" />
-													</svg>
-												</div>
-												<div>
-													<p className="text-sm font-medium text-white">
-														{playlist.name}
-													</p>
-													<p className="text-xs text-gray-400">
-														{playlist.songCount} songs
-													</p>
-												</div>
-											</div>
-										</div>
-									))}
-
-									{/* Create Playlist Button */}
-									<button
-										onClick={() => setIsModalOpen(true)}
-										className="w-full flex items-center gap-3 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group mt-2"
-									>
-										<div className="w-10 h-10 bg-[#282828] group-hover:bg-[#3a3a3a] rounded flex items-center justify-center transition-colors">
-											<svg
-												className="w-5 h-5 text-gray-400 group-hover:text-white transition-colors"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M12 4v16m8-8H4"
-												/>
-											</svg>
-										</div>
-										<p className="text-sm font-medium text-gray-400 group-hover:text-white transition-colors">
-											Create Playlist
-										</p>
-									</button>
-								</div>
-							</div>
-						</>
-					)}
-				</div>
-			</div>
-
-			<CreatePlaylistModal
-				isOpen={isModalOpen}
-				onClose={() => setIsModalOpen(false)}
-				onSuccess={() => refreshPlaylists(false)}
-				songId={null}
-			/>
-		</>
-	);
-};
-
-export default Sidebar;
Index: ontend/src/components/SongItem.tsx
===================================================================
--- frontend/src/components/SongItem.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,248 +1,0 @@
-import { use, useRef, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import { baseURL } from "../api/axiosInstance";
-import { usePlayer } from "../context/playerContext";
-import { toEmbedUrl } from "../utils/utils";
-import PlaylistDropdown from "./playlist/PlaylistDropdown";
-import { useAuth } from "../context/authContext";
-
-export interface SongItemData {
-  id: number;
-  title: string;
-  cover?: string | null;
-  genre?: string;
-  link?: string | null;
-  releasedBy?: string;
-  isLikedByCurrentUser?: boolean;
-}
-
-interface SongItemProps {
-  song: SongItemData;
-  /** Optional label shown before the artist, e.g. "Song" for search results */
-  label?: string;
-  /** Optional role badge for artist contributions, e.g. "PERFORMER" */
-  role?: string;
-  /** Optional index number for playlist/collection views */
-  index?: number;
-  /** Callback when the like button is clicked */
-  onLikeToggle?: (songId: number) => void;
-  /** Controlled: whether the playlist dropdown is open */
-  isDropdownOpen?: boolean;
-  /** Controlled: callback when dropdown should open/close */
-  onDropdownToggle?: (songId: number | null) => void;
-}
-
-const ROLE_COLORS: { [key: string]: string } = {
-  COMPOSER: "bg-purple-500/20 text-purple-300",
-  PERFORMER: "bg-blue-500/20 text-blue-300",
-  PRODUCER: "bg-green-500/20 text-green-300",
-  MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
-};
-
-const SongItem = ({
-  song,
-  label,
-  role,
-  index,
-  onLikeToggle,
-  isDropdownOpen,
-  onDropdownToggle,
-}: SongItemProps) => {
-  const navigate = useNavigate();
-  const { play, currentSong } = usePlayer();
-  const { user } = useAuth();
-  const [internalOpen, setInternalOpen] = useState(false);
-  const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
-  const [dropdownDirection, setDropdownDirection] = useState<"above" | "below">(
-    "below",
-  );
-  const buttonRef = useRef<HTMLButtonElement>(null);
-
-  const playlistOpen = isDropdownOpen ?? internalOpen;
-  const setPlaylistOpen = (open: boolean) => {
-    if (onDropdownToggle) {
-      onDropdownToggle(open ? song.id : null);
-    } else {
-      setInternalOpen(open);
-    }
-  };
-
-  const isPlaying = currentSong?.id === song.id;
-
-  const subtitleParts: string[] = [];
-  if (label) subtitleParts.push(label);
-  if (song.releasedBy) subtitleParts.push(song.releasedBy);
-  const subtitle = subtitleParts.join(" • ");
-
-  return (
-    <div
-      onClick={() => navigate(`/songs/${song.id}`)}
-      onMouseEnter={() => {
-        if (onDropdownToggle && !playlistOpen) {
-          onDropdownToggle(null);
-        }
-      }}
-      className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
-    >
-      {/* Optional index */}
-      {index != null && (
-        <span className="text-gray-500 font-medium w-8 text-center text-sm shrink-0">
-          {index}
-        </span>
-      )}
-
-      {/* Cover */}
-      <img
-        src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
-        alt={song.title}
-        className="w-12 h-12 rounded object-cover shrink-0"
-        onError={(e) => {
-          (e.target as HTMLImageElement).src = "/favicon.png";
-        }}
-      />
-
-      {/* Title & subtitle */}
-      <div className="flex-1 min-w-0">
-        <p
-          className={`font-medium truncate ${
-            isPlaying ? "text-[#1db954]" : "text-white"
-          }`}
-        >
-          {song.title}
-        </p>
-        {subtitle && (
-          <p className="text-sm text-gray-400 truncate">{subtitle}</p>
-        )}
-      </div>
-
-      {/* Role badge (artist contributions) */}
-      {role && (
-        <span
-          className={`px-3 py-1 rounded-full text-xs font-medium hidden sm:block ${
-            ROLE_COLORS[role] || "bg-white/10 text-gray-300"
-          }`}
-        >
-          {role.replace("_", " ")}
-        </span>
-      )}
-
-      {/* Genre */}
-      {song.genre && (
-        <span className="text-xs text-gray-500 uppercase tracking-wider mr-2 hidden sm:block">
-          {song.genre}
-        </span>
-      )}
-
-      {/* Play button */}
-      {song.link && (
-        <button
-          onClick={(e) => {
-            e.stopPropagation();
-            play({
-              id: song.id,
-              title: song.title,
-              artist: song.releasedBy || "",
-              cover: song.cover,
-              embedUrl: toEmbedUrl(song.link!),
-            });
-          }}
-          className={`p-2 rounded-full transition-all cursor-pointer ${
-            isPlaying
-              ? "bg-white text-[#1db954] opacity-100"
-              : "bg-[#1db954] text-black hover:scale-110 opacity-0 group-hover:opacity-100"
-          }`}
-          aria-label={isPlaying ? "Now playing" : "Play song"}
-        >
-          {isPlaying ? (
-            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-              <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-            </svg>
-          ) : (
-            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-              <path d="M8 5v14l11-7z" />
-            </svg>
-          )}
-        </button>
-      )}
-
-      {/* Like button */}
-      {user && onLikeToggle && (
-        <button
-          onClick={(e) => {
-            e.stopPropagation();
-            onLikeToggle(song.id);
-          }}
-          className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer"
-          aria-label={song.isLikedByCurrentUser ? "Unlike" : "Like"}
-        >
-          <svg
-            className="w-5 h-5"
-            fill={song.isLikedByCurrentUser ? "#ef4444" : "none"}
-            stroke={song.isLikedByCurrentUser ? "#ef4444" : "#6b7280"}
-            strokeWidth="2"
-            viewBox="0 0 24 24"
-          >
-            <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-          </svg>
-        </button>
-      )}
-
-      {/* Three-dot menu */}
-      {user && (
-        <div className="relative">
-          <button
-            ref={buttonRef}
-            onClick={(e) => {
-              e.stopPropagation();
-              if (playlistOpen) {
-                setPlaylistOpen(false);
-              } else {
-                if (buttonRef.current) {
-                  const rect = buttonRef.current.getBoundingClientRect();
-                  const spaceBelow = window.innerHeight - rect.bottom;
-                  const dropdownHeight = 260;
-
-                  if (spaceBelow < dropdownHeight) {
-                    setDropdownDirection("above");
-                    setDropdownPosition({
-                      top: rect.top - 8,
-                      left: rect.right - 224,
-                    });
-                  } else {
-                    setDropdownDirection("below");
-                    setDropdownPosition({
-                      top: rect.bottom + 8,
-                      left: rect.right - 224,
-                    });
-                  }
-                }
-                setPlaylistOpen(true);
-              }
-            }}
-            className="p-2 hover:bg-white/10 rounded-full transition-colors cursor-pointer text-gray-400 hover:text-white"
-            aria-label="More options"
-          >
-            <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
-              <circle cx="12" cy="5" r="1.5" />
-              <circle cx="12" cy="12" r="1.5" />
-              <circle cx="12" cy="19" r="1.5" />
-            </svg>
-          </button>
-
-          <PlaylistDropdown
-            songId={song.id}
-            isOpen={playlistOpen}
-            onClose={() => setPlaylistOpen(false)}
-            position={dropdownPosition}
-            usePortal={true}
-            direction={dropdownDirection}
-          />
-        </div>
-      )}
-
-      {/* Three-dot menu */}
-    </div>
-  );
-};
-
-export default SongItem;
Index: ontend/src/components/playlist/CreatePlaylistModal.tsx
===================================================================
--- frontend/src/components/playlist/CreatePlaylistModal.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,174 +1,0 @@
-import { useState, useEffect } from "react";
-import { toast } from "react-toastify";
-import axiosInstance from "../../api/axiosInstance";
-import type { CreatePlaylistModalProps } from "../../utils/types";
-
-const CreatePlaylistModal = ({
-  isOpen,
-  onClose,
-  onSuccess,
-  songId,
-}: CreatePlaylistModalProps) => {
-  const [playlistName, setPlaylistName] = useState("");
-  const [isClosing, setIsClosing] = useState(false);
-  const [isOpening, setIsOpening] = useState(false);
-  const [isSubmitting, setIsSubmitting] = useState(false);
-  const [error, setError] = useState("");
-
-  useEffect(() => {
-    if (isOpen) {
-      setIsClosing(false);
-      setPlaylistName("");
-      setError("");
-      setIsOpening(true);
-      setTimeout(() => setIsOpening(false), 10);
-    }
-  }, [isOpen]);
-
-  const handleClose = () => {
-    setIsClosing(true);
-    setTimeout(() => {
-      onClose();
-      setIsClosing(false);
-    }, 200);
-  };
-
-  const handleSubmit = async (e: React.FormEvent) => {
-    e.preventDefault();
-    if (!playlistName.trim() || isSubmitting) return;
-
-    setIsSubmitting(true);
-    try {
-      await axiosInstance.post("/playlists", null, {
-        params: {
-          playlistName: playlistName.trim(),
-          ...(songId != null && { songId }),
-        },
-      });
-
-      toast.success("Playlist created successfully!");
-      await onSuccess();
-      handleClose();
-    } catch (err: any) {
-      setError(err?.response?.data?.error || "Failed to create playlist");
-    } finally {
-      setIsSubmitting(false);
-    }
-  };
-
-  if (!isOpen && !isClosing) return null;
-
-  return (
-    <div
-      className={`fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 px-4 transition-opacity duration-200 ${
-        isClosing || isOpening ? "opacity-0" : "opacity-100"
-      }`}
-      onClick={handleClose}
-    >
-      <div
-        className={`bg-[#181818] rounded-xl p-8 w-full max-w-md border border-white/10 transition-all duration-200 ${
-          isClosing || isOpening
-            ? "scale-95 opacity-0"
-            : "scale-100 opacity-100"
-        }`}
-        onClick={(e) => e.stopPropagation()}
-      >
-        <div className="flex justify-between items-center mb-6">
-          <h2 className="text-2xl font-bold text-white">Create Playlist</h2>
-          <button
-            onClick={handleClose}
-            className="text-gray-400 hover:text-white transition-colors cursor-pointer"
-            aria-label="Close modal"
-          >
-            <svg
-              className="w-6 h-6"
-              fill="none"
-              stroke="currentColor"
-              viewBox="0 0 24 24"
-            >
-              <path
-                strokeLinecap="round"
-                strokeLinejoin="round"
-                strokeWidth={2}
-                d="M6 18L18 6M6 6l12 12"
-              />
-            </svg>
-          </button>
-        </div>
-
-        <form onSubmit={handleSubmit} className="space-y-6">
-          <div>
-            <label
-              className="block text-sm font-medium text-gray-300 mb-2"
-              htmlFor="playlistName"
-            >
-              Playlist Name
-            </label>
-            <input
-              type="text"
-              id="playlistName"
-              autoFocus
-              className={`w-full bg-[#282828] border rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none transition-all ${
-                error
-                  ? "border-red-500 focus:border-red-500 focus:ring-1 focus:ring-red-500"
-                  : "border-white/10 focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954]"
-              }`}
-              placeholder="Enter playlist name"
-              value={playlistName}
-              onChange={(e) => {
-                setPlaylistName(e.target.value);
-              }}
-            />
-            <div
-              className={`overflow-hidden transition-all duration-200 ease-out ${
-                error ? "max-h-20 opacity-100 mt-2" : "max-h-0 opacity-0"
-              }`}
-            >
-              <p className="text-sm text-red-400 flex items-center gap-1.5">
-                <svg
-                  className="w-4 h-4 shrink-0"
-                  fill="currentColor"
-                  viewBox="0 0 20 20"
-                >
-                  <path
-                    fillRule="evenodd"
-                    d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
-                    clipRule="evenodd"
-                  />
-                </svg>
-                {error}
-              </p>
-            </div>
-          </div>
-
-          <div className="flex gap-3">
-            <button
-              type="button"
-              onClick={handleClose}
-              disabled={isSubmitting}
-              className="flex-1 py-3 bg-[#282828] rounded-full text-white font-semibold hover:bg-[#3a3a3a] transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed"
-            >
-              Cancel
-            </button>
-            <button
-              type="submit"
-              disabled={!playlistName.trim() || isSubmitting}
-              className="flex-1 py-3 bg-[#1db954] rounded-full text-black font-semibold hover:bg-[#1ed760] transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-[#1db954] cursor-pointer flex items-center justify-center gap-2"
-            >
-              {isSubmitting ? (
-                <>
-                  <div className="w-4 h-4 border-2 border-black/20 border-t-black rounded-full animate-spin"></div>
-                  Creating...
-                </>
-              ) : (
-                "Create"
-              )}
-            </button>
-          </div>
-        </form>
-      </div>
-    </div>
-  );
-};
-
-export default CreatePlaylistModal;
Index: ontend/src/components/playlist/PlaylistDropdown.tsx
===================================================================
--- frontend/src/components/playlist/PlaylistDropdown.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,267 +1,0 @@
-import { useEffect, useRef, useState } from "react";
-import { createPortal } from "react-dom";
-import axiosInstance from "../../api/axiosInstance";
-import { useCreatedPlaylists } from "../../context/playlistContext";
-import CreatePlaylistModal from "./CreatePlaylistModal";
-
-interface PlaylistDropdownProps {
-  songId: number;
-  isOpen: boolean;
-  onClose: () => void;
-  position?: { top: number; left: number };
-
-  usePortal?: boolean;
-
-  direction?: "above" | "below";
-}
-
-const PlaylistDropdown = ({
-  songId,
-  isOpen,
-  onClose,
-  position,
-  usePortal = false,
-  direction = "above",
-}: PlaylistDropdownProps) => {
-  const { createdPlaylists, refreshPlaylists } = useCreatedPlaylists();
-  const [containingPlaylistIds, setContainingPlaylistIds] = useState<number[]>(
-    [],
-  );
-  const [loading, setLoading] = useState(false);
-  const [processingIds, setProcessingIds] = useState<Set<number>>(new Set());
-  const [isModalOpen, setIsModalOpen] = useState(false);
-  const dropdownRef = useRef<HTMLDivElement>(null);
-
-  useEffect(() => {
-    if (isOpen && songId) {
-      const fetchPlaylistIds = async () => {
-        setLoading(true);
-        setContainingPlaylistIds([]);
-        try {
-          const response = await axiosInstance.get<number[]>(
-            `/playlists/song/${songId}`,
-          );
-          setContainingPlaylistIds(response.data);
-        } catch (error) {
-          console.error("Failed to fetch song presence:", error);
-        } finally {
-          setLoading(false);
-        }
-      };
-      fetchPlaylistIds();
-    } else {
-      setContainingPlaylistIds([]);
-    }
-  }, [isOpen, songId]);
-
-  useEffect(() => {
-    const handleClickOutside = (event: MouseEvent) => {
-      if (
-        dropdownRef.current &&
-        !dropdownRef.current.contains(event.target as Node)
-      ) {
-        onClose();
-      }
-    };
-
-    if (isOpen) {
-      document.addEventListener("mousedown", handleClickOutside);
-    }
-    return () => document.removeEventListener("mousedown", handleClickOutside);
-  }, [isOpen, onClose]);
-
-  const handleTogglePlaylist = async (playlistId: number, songId: number) => {
-    if (processingIds.has(playlistId)) return;
-
-    setProcessingIds((prev) => new Set(prev).add(playlistId));
-
-    try {
-      const response = await axiosInstance.post<{
-        playlistId: number;
-        isSongAddedToPlaylist: boolean;
-      }>(`/playlists/${playlistId}/song/${songId}`);
-
-      const { playlistId: returnedPlaylistId, isSongAddedToPlaylist } =
-        response.data;
-
-      if (isSongAddedToPlaylist) {
-        setContainingPlaylistIds((prev) =>
-          prev.includes(returnedPlaylistId)
-            ? prev
-            : [...prev, returnedPlaylistId],
-        );
-      } else {
-        setContainingPlaylistIds((prev) =>
-          prev.filter((id) => id !== returnedPlaylistId),
-        );
-      }
-    } catch (error) {
-      console.error("Failed to toggle playlist:", error);
-    } finally {
-      refreshPlaylists(true);
-      setTimeout(() => {
-        setProcessingIds((prev) => {
-          const next = new Set(prev);
-          next.delete(playlistId);
-          return next;
-        });
-      }, 500);
-    }
-  };
-
-  const handleCreateNew = () => {
-    onClose();
-    setIsModalOpen(true);
-  };
-
-  const handleModalSuccess = async () => {
-    await refreshPlaylists(false);
-  };
-
-  const inlinePositionClass =
-    direction === "below"
-      ? "absolute left-0 top-full mt-2"
-      : "absolute right-0 bottom-full mb-2";
-
-  const dropdownContent = !isOpen ? null : (
-    <div
-      ref={dropdownRef}
-      className={`${usePortal ? "fixed" : inlinePositionClass} w-56 bg-[#282828] rounded-lg shadow-2xl py-2 z-9999 border border-white/10 max-h-60 overflow-y-auto custom-scrollbar`}
-      style={
-        usePortal && position
-          ? {
-              top: position.top,
-              left: position.left,
-              transform:
-                direction === "below" ? undefined : "translateY(-100%)",
-            }
-          : undefined
-      }
-      onClick={(e) => e.stopPropagation()}
-    >
-      <div className="px-4 py-2 text-xs font-bold text-gray-400 uppercase tracking-wider border-b border-white/5 mb-1">
-        Add to playlist
-      </div>
-
-      {loading ? (
-        <div className="flex items-center justify-center py-4">
-          <div className="w-5 h-5 border-2 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
-        </div>
-      ) : createdPlaylists && createdPlaylists.length > 0 ? (
-        createdPlaylists.map((playlist) => {
-          const isProcessing = processingIds.has(playlist.id);
-          const isChecked = containingPlaylistIds.includes(playlist.id);
-
-          return (
-            <label
-              key={playlist.id}
-              className={`flex items-center gap-1.5 px-4 py-2 hover:bg-white/10 transition-colors group/item ${
-                isProcessing ? "pointer-events-none" : "cursor-pointer"
-              }`}
-              onClick={(e) => e.stopPropagation()}
-            >
-              <div className="relative flex items-center justify-center  shrink-0">
-                <input
-                  type="checkbox"
-                  className="peer sr-only"
-                  checked={isChecked}
-                  disabled={isProcessing}
-                  onChange={() => handleTogglePlaylist(playlist.id, songId)}
-                />
-                <div
-                  className={`w-5 h-5 border-2 rounded bg-[#181818] transition-all ${
-                    isProcessing
-                      ? "border-[#1db954] animate-pulse"
-                      : isChecked
-                        ? "bg-[#1db954] border-[#1db954]"
-                        : "border-gray-500 text=wjot"
-                  }`}
-                >
-                  {isProcessing && (
-                    <div className="absolute inset-0 flex items-center justify-center">
-                      <div className="w-3 h-3 border-2 border-transparent border-t-[#1db954] rounded-full animate-spin"></div>
-                    </div>
-                  )}
-                </div>
-                <svg
-                  className={`absolute w-3 h-3 transition-opacity ${
-                    isChecked && !isProcessing ? "opacity-100" : "opacity-0"
-                  }`}
-                  fill="none"
-                  stroke="white"
-                  strokeWidth="3"
-                  viewBox="0 0 24 24"
-                >
-                  <path
-                    strokeLinecap="round"
-                    strokeLinejoin="round"
-                    d="M5 13l4 4L19 7"
-                  />
-                </svg>
-              </div>
-              <span
-                className={`text-sm truncate transition-all ${
-                  isProcessing
-                    ? "text-[#1db954] animate-pulse"
-                    : "text-gray-200 group-hover/item:text-white"
-                }`}
-              >
-                {playlist.name}
-              </span>
-            </label>
-          );
-        })
-      ) : (
-        <div className="px-4 py-3 text-sm text-gray-500 italic">
-          No playlists created
-        </div>
-      )}
-
-      <button
-        onClick={(e) => {
-          e.stopPropagation();
-          handleCreateNew();
-        }}
-        className="w-full text-left px-4 py-2 mt-1 text-sm text-[#1db954] hover:bg-white/5 transition-colors border-t border-white/5 flex items-center gap-2 font-medium cursor-pointer"
-      >
-        <svg
-          className="w-4 h-4"
-          fill="none"
-          stroke="currentColor"
-          viewBox="0 0 24 24"
-        >
-          <path
-            strokeLinecap="round"
-            strokeLinejoin="round"
-            strokeWidth={2}
-            d="M12 4v16m8-8H4"
-          />
-        </svg>
-        Create new playlist
-      </button>
-    </div>
-  );
-
-  const dropdown = dropdownContent
-    ? usePortal
-      ? createPortal(dropdownContent, document.body)
-      : dropdownContent
-    : null;
-
-  return (
-    <>
-      {dropdown}
-      {createPortal(
-        <CreatePlaylistModal
-          isOpen={isModalOpen}
-          onClose={() => setIsModalOpen(false)}
-          onSuccess={handleModalSuccess}
-          songId={songId}
-        />,
-        document.body,
-      )}
-    </>
-  );
-};
-
-export default PlaylistDropdown;
Index: ontend/src/components/search/AlbumResult.tsx
===================================================================
--- frontend/src/components/search/AlbumResult.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,38 +1,0 @@
-import { useNavigate } from "react-router-dom";
-import { baseURL } from "../../api/axiosInstance";
-import type { Album } from "../../utils/types";
-
-interface AlbumResultProps {
-	album: Album;
-}
-
-const AlbumResult = ({ album }: AlbumResultProps) => {
-	const navigate = useNavigate();
-
-	return (
-		<div
-			onClick={() => navigate(`/collection/album/${album.id}`)}
-			className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
-		>
-			<img
-				src={album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"}
-				alt={album.title}
-				className="w-12 h-12 rounded object-cover"
-				onError={(e) => {
-					(e.target as HTMLImageElement).src = "/favicon.png";
-				}}
-			/>
-			<div className="flex-1 min-w-0">
-				<p className="text-white font-medium truncate">{album.title}</p>
-				<p className="text-sm text-gray-400 truncate">
-					Album • {album.releasedBy}
-				</p>
-			</div>
-			<span className="text-xs text-gray-500 uppercase tracking-wider">
-				{album.genre}
-			</span>
-		</div>
-	);
-};
-
-export default AlbumResult;
Index: ontend/src/components/search/SongResult.tsx
===================================================================
--- frontend/src/components/search/SongResult.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,26 +1,0 @@
-import axiosInstance from "../../api/axiosInstance";
-import type { Song } from "../../utils/types";
-import SongItem from "../SongItem";
-
-interface SongResultProps {
-	song: Song;
-	/** Propagate like state change upward if needed */
-	onLikeToggled?: (songId: number, isLiked: boolean) => void;
-}
-
-const SongResult = ({ song, onLikeToggled }: SongResultProps) => {
-	const handleLike = async (songId: number) => {
-		try {
-			const response = await axiosInstance.post(
-				`/musical-entity/${songId}/like`,
-			);
-			onLikeToggled?.(songId, response.data.isLiked);
-		} catch (err) {
-			console.error("Error toggling like:", err);
-		}
-	};
-
-	return <SongItem song={song} label="Song" onLikeToggle={handleLike} />;
-};
-
-export default SongResult;
Index: ontend/src/components/search/UserResult.tsx
===================================================================
--- frontend/src/components/search/UserResult.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,41 +1,0 @@
-import { useNavigate } from "react-router-dom";
-import { baseURL } from "../../api/axiosInstance";
-import type { BaseNonAdminUser } from "../../utils/types";
-
-interface UserResultProps {
-	user: BaseNonAdminUser;
-	label: "Artist" | "User";
-}
-
-const UserResult = ({ user, label }: UserResultProps) => {
-	const navigate = useNavigate();
-
-	return (
-		<div
-			onClick={() => navigate(`/users/${user.username}`)}
-			className="flex items-center gap-4 p-3 rounded-lg hover:bg-white/5 cursor-pointer transition-colors group"
-		>
-			{user.profilePhoto ? (
-				<img
-					src={`${baseURL}/${user.profilePhoto}`}
-					alt={user.username}
-					className="w-12 h-12 rounded-full object-cover"
-				/>
-			) : (
-				<div className="w-12 h-12 bg-blue-500 rounded-full flex items-center justify-center">
-					<span className="text-white text-lg font-semibold">
-						{user.username.charAt(0).toUpperCase()}
-					</span>
-				</div>
-			)}
-			<div className="flex-1 min-w-0">
-				<p className="text-white font-medium truncate">{user.fullName}</p>
-				<p className="text-sm text-gray-400 truncate">
-					{label} • @{user.username}
-				</p>
-			</div>
-		</div>
-	);
-};
-
-export default UserResult;
Index: ontend/src/components/userProfile/ArtistView.tsx
===================================================================
--- frontend/src/components/userProfile/ArtistView.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,158 +1,0 @@
-import { Disc3, Music } from "lucide-react";
-import { useState } from "react";
-import { useNavigate } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { baseURL } from "../../api/axiosInstance";
-import type { ArtistContribution } from "../../utils/types";
-import SongItem from "../SongItem";
-import { useAuth } from "../../context/authContext";
-
-interface ArtistViewProps {
-  contributions: ArtistContribution[];
-}
-
-const ArtistView = ({ contributions }: ArtistViewProps) => {
-  const navigate = useNavigate();
-  const [items, setItems] = useState(contributions);
-  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
-    null,
-  );
-
-  const albums = items.filter((c) => c.entityType === "ALBUM");
-  const songs = items.filter((c) => c.entityType === "SONG");
-
-  const getRoleColor = (role: string) => {
-    const colors: { [key: string]: string } = {
-      COMPOSER: "bg-purple-500/20 text-purple-300",
-      PERFORMER: "bg-blue-500/20 text-blue-300",
-      PRODUCER: "bg-green-500/20 text-green-300",
-      MAIN_VOCAL: "bg-pink-500/20 text-pink-300",
-    };
-    return colors[role] || "bg-white/10 text-gray-300";
-  };
-
-  const handleLike = async (id: number, title: string) => {
-    try {
-      const response = await axiosInstance.post(`/musical-entity/${id}/like`);
-      const data = response.data;
-
-      setItems((prevItems) =>
-        prevItems.map((item) =>
-          item.id === data.entityId
-            ? { ...item, isLikedByCurrentUser: data.isLiked }
-            : item,
-        ),
-      );
-      toast.success(
-        data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
-      );
-    } catch (err: any) {
-      toast.error(err.response?.data?.error || "Failed to like the item");
-    }
-  };
-
-  return (
-    <div className="mt-8">
-      {albums.length > 0 && (
-        <div className="mb-12">
-          <div className="flex items-center gap-3 mb-6">
-            <Disc3 className="w-6 h-6 text-[#1db954]" />
-            <h2 className="text-2xl font-bold text-white">Albums</h2>
-          </div>
-          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
-            {albums.map((album) => (
-              <div
-                key={album.id}
-                className="group cursor-pointer"
-                onClick={() => navigate(`/collection/album/${album.id}`)}
-              >
-                <div className="relative aspect-square rounded-lg mb-3 overflow-hidden shadow-md group-hover:shadow-xl transition-all duration-300 bg-[#181818]">
-                  <img
-                    src={
-                      album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
-                    }
-                    alt={album.title}
-                    className="w-full h-full object-cover"
-                    onError={(e) => {
-                      (e.target as HTMLImageElement).src = "/favicon.png";
-                    }}
-                  />
-
-                  <button
-                    className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-                    title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
-                    onClick={(e) => {
-                      e.stopPropagation();
-                      handleLike(album.id, album.title);
-                    }}
-                  >
-                    <svg
-                      className="w-5 h-5"
-                      fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
-                      stroke={
-                        album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
-                      }
-                      strokeWidth="2"
-                      viewBox="0 0 24 24"
-                    >
-                      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-                    </svg>
-                  </button>
-
-                  <div className="absolute bottom-0 left-0 right-0 bg-linear-to-t from-black/80 to-transparent p-3">
-                    <span
-                      className={`text-xs px-2 py-1 rounded-full font-medium ${getRoleColor(album.role)}`}
-                    >
-                      {album.role.replace("_", " ")}
-                    </span>
-                  </div>
-                </div>
-                <h3 className="font-semibold text-sm line-clamp-2 text-white group-hover:text-[#1db954] transition-colors">
-                  {album.title}
-                </h3>
-              </div>
-            ))}
-          </div>
-        </div>
-      )}
-
-      {songs.length > 0 && (
-        <div className="mb-12">
-          <div className="flex items-center gap-3 mb-6">
-            <Music className="w-6 h-6 text-[#1db954]" />
-            <h2 className="text-2xl font-bold text-white">Songs</h2>
-          </div>
-          <div className="space-y-1">
-            {songs.map((song) => (
-              <SongItem
-                key={song.id}
-                song={{
-                  id: song.id,
-                  title: song.title,
-                  cover: song.cover,
-                  genre: song.genre,
-                  link: song.link,
-                  isLikedByCurrentUser: song.isLikedByCurrentUser,
-                }}
-                role={song.role}
-                onLikeToggle={() => handleLike(song.id, song.title)}
-                isDropdownOpen={openDropdownSongId === song.id}
-                onDropdownToggle={setOpenDropdownSongId}
-              />
-            ))}
-          </div>
-        </div>
-      )}
-
-      {contributions.length === 0 && (
-        <div className="flex flex-col items-center justify-center py-16 text-gray-500">
-          <Music className="w-20 h-20 mb-4 opacity-20" />
-          <p className="text-lg font-medium">No contributions yet</p>
-          <p className="text-sm mt-2">Start creating music to see it here</p>
-        </div>
-      )}
-    </div>
-  );
-};
-
-export default ArtistView;
Index: ontend/src/components/userProfile/ListenerView.tsx
===================================================================
--- frontend/src/components/userProfile/ListenerView.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,380 +1,0 @@
-import { Album, Bookmark, Heart, ListMusic, Music, Trash2 } from "lucide-react";
-import { useState } from "react";
-import { useNavigate, useParams } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { baseURL } from "../../api/axiosInstance";
-import type { MusicalEntity, Playlist } from "../../utils/types";
-import SongItem from "../SongItem";
-import { useAuth } from "../../context/authContext";
-import { useCreatedPlaylists } from "../../context/playlistContext";
-
-interface ListenerViewProps {
-  likedEntities: MusicalEntity[] | [];
-  createdPlaylists: Playlist[] | [];
-  savedPlaylists: Playlist[] | [];
-}
-
-const ListenerView = ({
-  likedEntities,
-  createdPlaylists,
-  savedPlaylists,
-}: ListenerViewProps) => {
-  const navigate = useNavigate();
-  const { refreshPlaylists } = useCreatedPlaylists();
-  const { username: usernameParam } = useParams();
-  const { user: currentUser } = useAuth();
-  const [items, setItems] = useState(likedEntities);
-  const [createdItems, setCreatedItems] = useState(createdPlaylists);
-  const [savedItems, setSavedItems] = useState(savedPlaylists);
-  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
-    null,
-  );
-
-  const likedSongs = items.filter((e) => e.type === "SONG");
-  const likedAlbums = items.filter((e) => e.type === "ALBUM");
-  const username = usernameParam || currentUser?.username;
-  const isOwnProfile = currentUser?.username === username;
-
-  const handleSavePlaylist = async (
-    e: React.MouseEvent,
-    playlistId: number,
-    playlistName: string,
-  ) => {
-    e.stopPropagation();
-
-    try {
-      const response = await axiosInstance.post(
-        `/playlists/${playlistId}/save`,
-      );
-      const data = response.data;
-
-      setCreatedItems((prevItems) =>
-        prevItems.map((p) =>
-          p.id === playlistId
-            ? { ...p, isSavedByCurrentUser: data.isSavedByCurrentUser }
-            : p,
-        ),
-      );
-
-      setSavedItems((prevItems) =>
-        prevItems.map((p) =>
-          p.id === playlistId
-            ? { ...p, isSavedByCurrentUser: data.isSavedByCurrentUser }
-            : p,
-        ),
-      );
-
-      if (isOwnProfile) {
-        if (data.isSavedByCurrentUser) {
-          const playlistToAdd = createdItems.find((p) => p.id === playlistId);
-          if (playlistToAdd && !savedItems.find((p) => p.id === playlistId)) {
-            setSavedItems((prevItems) => [
-              ...prevItems,
-              { ...playlistToAdd, isSavedByCurrentUser: true },
-            ]);
-          }
-        } else {
-          setSavedItems((prevItems) =>
-            prevItems.filter((p) => p.id !== playlistId),
-          );
-        }
-      }
-
-      toast.success(
-        data.isSavedByCurrentUser
-          ? `Saved "${playlistName}" to your library`
-          : `Removed "${playlistName}" from your library`,
-      );
-    } catch (err: any) {
-      toast.error(err.response?.data?.error || "Failed to save the playlist");
-    }
-  };
-
-  const handleDeletePlaylist = async (
-    e: React.MouseEvent,
-    playlistId: number,
-    playlistName: string,
-  ) => {
-    e.stopPropagation();
-
-    try {
-      await axiosInstance.delete(`/playlists/${playlistId}`);
-      refreshPlaylists(false);
-
-      setCreatedItems((prev) => prev.filter((p) => p.id !== playlistId));
-      toast.success(`Deleted "${playlistName}"`);
-    } catch (err: any) {
-      toast.error(err.response?.data?.error || "Failed to delete playlist");
-    }
-  };
-
-  const handleLike = async (id: number, title: string) => {
-    try {
-      const response = await axiosInstance.post(`/musical-entity/${id}/like`);
-      const data = response.data;
-
-      setItems((prevItems) =>
-        prevItems.map((item) =>
-          item.id === data.entityId
-            ? { ...item, isLikedByCurrentUser: data.isLiked }
-            : item,
-        ),
-      );
-
-      toast.success(
-        data.isLiked ? `Liked "${title}"` : `Removed "${title}" from likes`,
-      );
-    } catch (err: any) {
-      toast.error(err.response?.data?.error || "Failed to like the item");
-    }
-  };
-
-  return (
-    <div className="mt-8 space-y-12">
-      {createdItems && createdItems.length > 0 && (
-        <section>
-          <div className="flex items-center gap-3 mb-6">
-            <ListMusic className="w-6 h-6 text-[#1db954]" />
-            <h3 className="text-2xl font-bold text-white">Created Playlists</h3>
-            <span className="text-sm text-gray-500">
-              ({createdItems.length})
-            </span>
-          </div>
-
-          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
-            {createdItems.map((playlist) => (
-              <div
-                key={playlist.id}
-                className="group cursor-pointer"
-                onClick={() => navigate(`/collection/playlist/${playlist.id}`)}
-              >
-                <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
-                  <img
-                    src={
-                      playlist.cover
-                        ? `${baseURL}/${playlist.cover}`
-                        : "/favicon.png"
-                    }
-                    alt={playlist.name}
-                    className="w-full h-full object-cover"
-                    onError={(e) => {
-                      (e.target as HTMLImageElement).src = "/favicon.png";
-                    }}
-                  />
-                  {isOwnProfile ? (
-                    <button
-                      onClick={(e) =>
-                        handleDeletePlaylist(e, playlist.id, playlist.name)
-                      }
-                      className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-red-600/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-                      title="Delete playlist"
-                    >
-                      <Trash2 className="w-5 h-5 text-gray-400 hover:text-white transition-colors" />
-                    </button>
-                  ) : (
-                    currentUser?.username != playlist.creatorUsername && (
-                      <button
-                        onClick={(e) =>
-                          handleSavePlaylist(e, playlist.id, playlist.name)
-                        }
-                        className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-                        title={
-                          playlist.isSavedByCurrentUser ? "Unsave" : "Save"
-                        }
-                      >
-                        <Bookmark
-                          className={`w-5 h-5 ${
-                            playlist.isSavedByCurrentUser
-                              ? "fill-[#1db954] text-[#1db954]"
-                              : "text-gray-400"
-                          }`}
-                        />
-                      </button>
-                    )
-                  )}
-                </div>
-                <p className="text-sm font-semibold text-white truncate group-hover:text-[#1db954] transition-colors">
-                  {playlist.name}
-                </p>
-                <p className="text-xs text-gray-400 truncate">
-                  {playlist.creatorName}
-                </p>
-              </div>
-            ))}
-          </div>
-        </section>
-      )}
-
-      {savedItems && savedItems.length > 0 && (
-        <section>
-          <div className="flex items-center gap-3 mb-6">
-            <Bookmark className="w-6 h-6 text-[#1db954] fill-[#1db954]" />
-            <h3 className="text-2xl font-bold text-white">Saved Playlists</h3>
-            <span className="text-sm text-gray-500">({savedItems.length})</span>
-          </div>
-
-          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
-            {savedItems.map((playlist) => (
-              <div
-                key={playlist.id}
-                className="group cursor-pointer"
-                onClick={() => navigate(`/collection/playlist/${playlist.id}`)}
-              >
-                <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
-                  <img
-                    src={
-                      playlist.cover
-                        ? `${baseURL}/${playlist.cover}`
-                        : "/favicon.png"
-                    }
-                    alt={playlist.name}
-                    className="w-full h-full object-cover"
-                    onError={(e) => {
-                      (e.target as HTMLImageElement).src = "/favicon.png";
-                    }}
-                  />
-
-                  {currentUser?.username != playlist.creatorUsername && (
-                    <button
-                      onClick={(e) =>
-                        handleSavePlaylist(e, playlist.id, playlist.name)
-                      }
-                      className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-                      title={playlist.isSavedByCurrentUser ? "Unsave" : "Save"}
-                    >
-                      <Bookmark
-                        className={`w-5 h-5 ${
-                          playlist.isSavedByCurrentUser
-                            ? "fill-[#1db954] text-[#1db954]"
-                            : "text-gray-400"
-                        }`}
-                      />
-                    </button>
-                  )}
-                </div>
-                <p className="text-sm font-semibold text-white truncate group-hover:text-[#1db954] transition-colors">
-                  {playlist.name}
-                </p>
-                <p className="text-xs text-gray-400 truncate">
-                  {playlist.creatorName}
-                </p>
-              </div>
-            ))}
-          </div>
-        </section>
-      )}
-
-      {likedSongs && likedSongs.length > 0 && (
-        <section>
-          <div className="flex items-center gap-3 mb-6">
-            <Heart className="w-6 h-6 text-red-500 fill-red-500" />
-            <h3 className="text-2xl font-bold text-white">Liked Songs</h3>
-            <span className="text-sm text-gray-500">
-              ({likedSongs?.length})
-            </span>
-          </div>
-
-          <div className="space-y-1">
-            {likedSongs.map((song, index) => (
-              <SongItem
-                key={song.id}
-                song={{
-                  id: song.id,
-                  title: song.title,
-                  cover: song.cover
-                    ? `${baseURL}/${song.cover}`
-                    : "/favicon.png",
-                  genre: song.genre,
-                  link: (song as any).link,
-                  releasedBy: song.releasedBy,
-                  isLikedByCurrentUser: song.isLikedByCurrentUser,
-                }}
-                index={index + 1}
-                onLikeToggle={() => handleLike(song.id, song.title)}
-                isDropdownOpen={openDropdownSongId === song.id}
-                onDropdownToggle={setOpenDropdownSongId}
-              />
-            ))}
-          </div>
-        </section>
-      )}
-
-      {likedAlbums && likedAlbums.length > 0 && (
-        <section>
-          <div className="flex items-center gap-3 mb-6">
-            <Album className="w-6 h-6 text-[#1db954]" />
-            <h3 className="text-2xl font-bold text-white">Liked Albums</h3>
-            <span className="text-sm text-gray-500">
-              ({likedAlbums.length})
-            </span>
-          </div>
-
-          <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
-            {likedAlbums.map((album) => (
-              <div
-                key={album.id}
-                className="group cursor-pointer"
-                onClick={() => navigate(`/collection/album/${album.id}`)}
-              >
-                <div className="relative aspect-square rounded-lg overflow-hidden bg-[#181818] mb-3 shadow-md group-hover:shadow-xl transition-all">
-                  <img
-                    src={
-                      album.cover ? `${baseURL}/${album.cover}` : "/favicon.png"
-                    }
-                    alt={album.title}
-                    className="w-full h-full object-cover"
-                    onError={(e) => {
-                      (e.target as HTMLImageElement).src = "/favicon.png";
-                    }}
-                  />
-
-                  <button
-                    onClick={(e) => {
-                      e.stopPropagation();
-                      handleLike(album.id, album.title);
-                    }}
-                    className="absolute top-2 right-2 p-2 bg-black/70 hover:bg-black/90 rounded-full shadow-md transition-all duration-200 opacity-0 group-hover:opacity-100 cursor-pointer"
-                    title={album.isLikedByCurrentUser ? "Unlike" : "Like"}
-                  >
-                    <svg
-                      className="w-5 h-5"
-                      fill={album.isLikedByCurrentUser ? "#ef4444" : "none"}
-                      stroke={
-                        album.isLikedByCurrentUser ? "#ef4444" : "#9ca3af"
-                      }
-                      strokeWidth="2"
-                      viewBox="0 0 24 24"
-                    >
-                      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-                    </svg>
-                  </button>
-                </div>
-                <p className="font-semibold text-sm text-white truncate group-hover:text-[#1db954] transition-colors">
-                  {album.title}
-                </p>
-                <p className="text-xs text-gray-400 truncate mt-1">
-                  {album.releasedBy}
-                </p>
-              </div>
-            ))}
-          </div>
-        </section>
-      )}
-
-      {likedEntities &&
-        likedEntities.length === 0 &&
-        (!createdItems || createdItems.length === 0) &&
-        (!savedItems || savedItems.length === 0) && (
-          <div className="flex flex-col items-center justify-center py-16 text-gray-500">
-            <Music className="w-20 h-20 mb-4 opacity-20" />
-            <p className="text-lg font-medium">Nothing here yet</p>
-            <p className="text-sm mt-2">
-              Start exploring music to build your collection
-            </p>
-          </div>
-        )}
-    </div>
-  );
-};
-
-export default ListenerView;
Index: ontend/src/components/userProfile/UserListModal.tsx
===================================================================
--- frontend/src/components/userProfile/UserListModal.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,98 +1,0 @@
-import { useEffect } from "react";
-import { useNavigate } from "react-router-dom";
-import { baseURL } from "../../api/axiosInstance";
-import { useAuth } from "../../context/authContext";
-import type { BaseNonAdminUser } from "../../utils/types";
-
-interface ModalProps {
-	title: string;
-	users: BaseNonAdminUser[];
-	onClose: () => void;
-	onFollowToggle: (targetUsername: string) => Promise<void>;
-}
-
-const UserListModal = ({
-	title,
-	users,
-	onClose,
-	onFollowToggle,
-}: ModalProps) => {
-	const navigate = useNavigate();
-	const { user } = useAuth();
-	useEffect(() => {
-		document.body.style.overflow = "hidden";
-		return () => {
-			document.body.style.overflow = "";
-		};
-	}, []);
-
-	return (
-		<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
-			<div className="bg-[#1a1a2e] border border-white/10 rounded-xl shadow-2xl w-full max-w-md max-h-[70vh] flex flex-col">
-				<div className="p-4 border-b border-white/10 flex justify-between items-center">
-					<h2 className="text-xl font-bold text-white">{title}</h2>
-					<button
-						onClick={onClose}
-						className="text-gray-400 hover:text-white text-2xl cursor-pointer transition-colors"
-					>
-						&times;
-					</button>
-				</div>
-
-				<div className="overflow-y-auto p-4 flex-1">
-					{users.length === 0 ? (
-						<p className="text-center text-gray-500 py-8">No users found.</p>
-					) : (
-						users.map((u) => (
-							<div
-								key={u.username}
-								className="flex items-center justify-between p-3 hover:bg-white/5 rounded-lg transition-colors"
-							>
-								<div
-									className="flex items-center gap-4 cursor-pointer flex-1"
-									onClick={() => {
-										onClose();
-										navigate(`/users/${u.username}`);
-									}}
-								>
-									<div className="w-10 h-10 rounded-full bg-[#282828] overflow-hidden shrink-0 flex items-center justify-center">
-										{u.profilePhoto ? (
-											<img
-												src={`${baseURL}/${u.profilePhoto}`}
-												className="w-full h-full object-cover"
-												alt=""
-											/>
-										) : (
-											<span className="text-[#1db954] font-bold">
-												{u.fullName.charAt(0)}
-											</span>
-										)}
-									</div>
-									<div>
-										<p className="font-semibold text-white">{u.fullName}</p>
-										<p className="text-sm text-gray-400">@{u.username}</p>
-									</div>
-								</div>
-								{user && user.username !== u.username && (
-									<button
-										onClick={() => onFollowToggle(u.username)}
-										className={`px-4 py-1.5 text-sm font-medium rounded-full transition-colors cursor-pointer ${
-											u.isFollowedByCurrentUser
-												? "bg-white/10 text-white hover:bg-white/20"
-												: "bg-[#1db954] text-black hover:bg-[#1ed760]"
-										}`}
-									>
-										{u.isFollowedByCurrentUser ? "Following" : "Follow"}
-									</button>
-								)}
-							</div>
-						))
-					)}
-				</div>
-			</div>
-			<div className="absolute inset-0 -z-10" onClick={onClose}></div>
-		</div>
-	);
-};
-
-export default UserListModal;
Index: ontend/src/context/authContext.tsx
===================================================================
--- frontend/src/context/authContext.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,63 +1,0 @@
-import {
-	createContext,
-	useContext,
-	useEffect,
-	useState,
-	type Dispatch,
-	type ReactNode,
-	type SetStateAction,
-} from "react";
-import axiosInstance, {
-	refreshTokenMethod,
-	scheduleTokenRefresh,
-} from "../api/axiosInstance";
-import { type User } from "../utils/types";
-
-interface AuthContextType {
-	user: User | undefined;
-	setUser: Dispatch<SetStateAction<User | undefined>>;
-	isAuthLoading: boolean;
-}
-
-const AuthContext = createContext<AuthContextType>({
-	user: undefined,
-	setUser: () => {},
-	isAuthLoading: false,
-});
-
-interface AuthProviderProps {
-	children: ReactNode;
-}
-
-export const AuthProvider = ({ children }: AuthProviderProps) => {
-	const [user, setUser] = useState<User | undefined>(undefined);
-	const [isAuthLoading, setIsAuthLoading] = useState(true);
-
-	useEffect(() => {
-		const fetchUserDetails = async () => {
-			try {
-				await refreshTokenMethod();
-				const response = await axiosInstance.get<{
-					tokenExpiresIn: number;
-					user: User;
-				}>("/auth/user");
-				setUser(response.data.user);
-				scheduleTokenRefresh(response.data.tokenExpiresIn);
-			} catch (error) {
-				setUser(undefined);
-			} finally {
-				setIsAuthLoading(false);
-			}
-		};
-
-		fetchUserDetails();
-	}, []);
-
-	return (
-		<AuthContext.Provider value={{ user, setUser, isAuthLoading }}>
-			{children}
-		</AuthContext.Provider>
-	);
-};
-
-export const useAuth = () => useContext(AuthContext);
Index: ontend/src/context/playerContext.tsx
===================================================================
--- frontend/src/context/playerContext.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,70 +1,0 @@
-import {
-	createContext,
-	useCallback,
-	useContext,
-	useState,
-	type ReactNode,
-} from "react";
-
-export interface PlayerSong {
-	id: number;
-	title: string;
-	artist: string;
-	cover?: string | null;
-	embedUrl: string;
-}
-
-interface PlayerContextType {
-	currentSong: PlayerSong | null;
-	isMinimized: boolean;
-	play: (song: PlayerSong) => void;
-	stop: () => void;
-	toggleMinimize: () => void;
-	isPlaying: boolean;
-}
-
-const PlayerContext = createContext<PlayerContextType>({
-	currentSong: null,
-	isMinimized: false,
-	isPlaying: false,
-	play: () => {},
-	stop: () => {},
-	toggleMinimize: () => {},
-});
-
-export const PlayerProvider = ({ children }: { children: ReactNode }) => {
-	const [currentSong, setCurrentSong] = useState<PlayerSong | null>(null);
-	const [isMinimized, setIsMinimized] = useState(true);
-	const [isPlaying, setIsPlaying] = useState(false);
-
-	const play = useCallback((song: PlayerSong) => {
-		setCurrentSong(song);
-		setIsPlaying(true);
-	}, []);
-
-	const stop = useCallback(() => {
-		setIsPlaying(false);
-		setCurrentSong(null);
-	}, []);
-
-	const toggleMinimize = useCallback(() => {
-		setIsMinimized((prev) => !prev);
-	}, []);
-
-	return (
-		<PlayerContext.Provider
-			value={{
-				currentSong,
-				isMinimized,
-				isPlaying,
-				play,
-				stop,
-				toggleMinimize,
-			}}
-		>
-			{children}
-		</PlayerContext.Provider>
-	);
-};
-
-export const usePlayer = () => useContext(PlayerContext);
Index: ontend/src/context/playlistContext.tsx
===================================================================
--- frontend/src/context/playlistContext.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,78 +1,0 @@
-import {
-  createContext,
-  useContext,
-  useEffect,
-  useState,
-  type Dispatch,
-  type ReactNode,
-  type SetStateAction,
-} from "react";
-import type { BasicPlaylist } from "../utils/types";
-import axiosInstance from "../api/axiosInstance";
-import { toast } from "react-toastify";
-import { getErrorMessage } from "../utils/error";
-import { useAuth } from "./authContext";
-interface PlaylistContextType {
-  createdPlaylists: BasicPlaylist[] | undefined;
-  setCreatedPlaylists: Dispatch<SetStateAction<BasicPlaylist[] | undefined>>;
-  isLoading: boolean;
-  refreshPlaylists: (addedSong: boolean) => Promise<void>;
-}
-
-interface PlaylistProviderProps {
-  children: ReactNode;
-}
-
-const PlaylistContext = createContext<PlaylistContextType>({
-  createdPlaylists: undefined,
-  setCreatedPlaylists: () => {},
-  isLoading: false,
-  refreshPlaylists: async (addedSong: boolean) => {},
-});
-
-const PlaylistProvider = ({ children }: PlaylistProviderProps) => {
-  const { user } = useAuth();
-  const [createdPlaylists, setCreatedPlaylists] = useState<
-    BasicPlaylist[] | undefined
-  >(undefined);
-  const [isLoading, setIsLoading] = useState(false);
-
-  const fetchCreatedPlaylists = async (addedSong: boolean) => {
-    if (!addedSong) {
-      setIsLoading(true);
-    }
-    try {
-      const data = await axiosInstance.get<BasicPlaylist[]>("/playlists/user");
-      setCreatedPlaylists(data.data);
-    } catch (error: any) {
-      toast.error(getErrorMessage(error));
-    } finally {
-      setIsLoading(false);
-    }
-  };
-
-  useEffect(() => {
-    if (user) {
-      fetchCreatedPlaylists(false);
-    } else {
-      setCreatedPlaylists(undefined);
-    }
-  }, [user]);
-
-  return (
-    <PlaylistContext.Provider
-      value={{
-        createdPlaylists,
-        setCreatedPlaylists,
-        isLoading,
-        refreshPlaylists: fetchCreatedPlaylists,
-      }}
-    >
-      {children}
-    </PlaylistContext.Provider>
-  );
-};
-
-export const useCreatedPlaylists = () => useContext(PlaylistContext);
-
-export default PlaylistProvider;
Index: frontend/src/main.tsx
===================================================================
--- frontend/src/main.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ frontend/src/main.tsx	(revision 15ec67f0faa204c0c5d0e1f4d4979ee8ff4fcd4a)
@@ -2,18 +2,9 @@
 import { createRoot } from "react-dom/client";
 import App from "./App.tsx";
-import { AuthProvider } from "./context/authContext.tsx";
-import { PlayerProvider } from "./context/playerContext.tsx";
 import "./index.css";
-import PlaylistProvider from "./context/playlistContext.tsx";
 
 createRoot(document.getElementById("root")!).render(
-  <StrictMode>
-    <AuthProvider>
-      <PlayerProvider>
-        <PlaylistProvider>
-          <App />
-        </PlaylistProvider>
-      </PlayerProvider>
-    </AuthProvider>
-  </StrictMode>,
+	<StrictMode>
+		<App />
+	</StrictMode>,
 );
Index: ontend/src/pages/AllUsers.tsx
===================================================================
--- frontend/src/pages/AllUsers.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,89 +1,0 @@
-import React, { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import axiosInstance from "../api/axiosInstance";
-import LoadingSpinner from "../components/LoadingSpinner";
-
-interface User {
-	username: string;
-	fullName: string;
-}
-
-const AllUsers = () => {
-	const [users, setUsers] = useState<User[]>([]);
-	const [searchedUser, setSearchedUser] = useState<string>("");
-	const [error, setError] = useState<string | null>(null);
-	const navigate = useNavigate();
-
-	useEffect(() => {
-		const fetchUsers = async () => {
-			const response = axiosInstance.get("/users/na/all");
-			setUsers((await response).data);
-		};
-		fetchUsers();
-	}, []);
-
-	const handleUserClick = (username: string) => {
-		navigate(`/users/${username}`);
-	};
-
-	const handleSearch = async (e: React.FormEvent) => {
-		e.preventDefault();
-		try {
-			const response = await axiosInstance.get(`/users/na/search`, {
-				params: { name: searchedUser },
-			});
-			setUsers(response.data);
-		} catch (err: any) {
-			const errorMessage = err.response?.data?.error || "Search failed";
-			setError(errorMessage);
-		}
-	};
-
-	if (users.length == 0) {
-		return <LoadingSpinner />;
-	}
-	if (error) {
-		return (
-			<div className="p-6 bg-red-50 border border-red-200 text-red-700 rounded-lg">
-				<h2 className="font-bold">Error</h2>
-				<p>{error}</p>
-			</div>
-		);
-	}
-
-	return (
-		<div className="container mx-auto p-6">
-			<h1 className="text-3xl font-bold mb-6">All Users</h1>
-			<form onSubmit={handleSearch} className="flex gap-2 mb-10">
-				<input
-					type="text"
-					value={searchedUser}
-					onChange={(e) => setSearchedUser(e.target.value)}
-					className="border p-2 rounded w-full"
-					placeholder="Search for a user..."
-				/>
-				<button
-					type="submit"
-					className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700 transition-colors"
-				>
-					Search
-				</button>
-			</form>
-
-			<div className="grid gap-4">
-				{users.map((u) => (
-					<div
-						key={u.username}
-						onClick={() => handleUserClick(u.username)}
-						className="bg-white shadow-md rounded-lg p-4 hover:shadow-lg hover:bg-gray-50 cursor-pointer transition-all"
-					>
-						<h2 className="text-xl font-semibold">{u.fullName}</h2>
-						<p className="text-gray-600">@{u.username}</p>
-					</div>
-				))}
-			</div>
-		</div>
-	);
-};
-
-export default AllUsers;
Index: ontend/src/pages/LandingPage.tsx
===================================================================
--- frontend/src/pages/LandingPage.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,504 +1,0 @@
-import { useEffect, useState } from "react";
-import { useNavigate } from "react-router-dom";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import PlaylistDropdown from "../components/playlist/PlaylistDropdown";
-import AlbumResult from "../components/search/AlbumResult";
-import SongResult from "../components/search/SongResult";
-import UserResult from "../components/search/UserResult";
-import { useAuth } from "../context/authContext";
-import { usePlayer } from "../context/playerContext";
-import type {
-	Album,
-	BaseNonAdminUser,
-	SearchCategory,
-	Song,
-} from "../utils/types";
-import { toEmbedUrl } from "../utils/utils";
-
-const CATEGORIES: { value: SearchCategory; label: string }[] = [
-	{ value: "songs", label: "Songs" },
-	{ value: "albums", label: "Albums" },
-	{ value: "artists", label: "Artists" },
-	{ value: "users", label: "Users" },
-];
-
-const LandingPage = () => {
-	const navigate = useNavigate();
-	const { play, currentSong } = usePlayer();
-	const { user } = useAuth();
-	const [songs, setSongs] = useState<Song[]>([]);
-	const [loading, setLoading] = useState<boolean>(true);
-
-	const [searchInput, setSearchInput] = useState("");
-	const [activeQuery, setActiveQuery] = useState("");
-	const [searchCategory, setSearchCategory] = useState<SearchCategory>("songs");
-	const [searchResults, setSearchResults] = useState<unknown[]>([]);
-	const [searchLoading, setSearchLoading] = useState(false);
-	const [hasSearched, setHasSearched] = useState(false);
-
-	const [openPlaylistDropdown, setOpenPlaylistDropdown] = useState<
-		number | null
-	>(null);
-
-	useEffect(() => {
-		const fetchSongs = async () => {
-			try {
-				const response = await axiosInstance.get("/songs/top");
-				setSongs(response.data);
-			} catch (error) {
-				console.error("Error fetching songs:", error);
-			} finally {
-				setLoading(false);
-			}
-		};
-		fetchSongs();
-	}, []);
-
-	const toggleLike = async (songId: number) => {
-		try {
-			await axiosInstance.post(`/musical-entity/${songId}/like`);
-			setSongs((prevSongs) =>
-				prevSongs.map((song) =>
-					song.id === songId
-						? { ...song, isLikedByCurrentUser: !song.isLikedByCurrentUser }
-						: song,
-				),
-			);
-		} catch (error) {
-			console.error("Error toggling like:", error);
-		}
-	};
-
-	const togglePlaylistDropdown = (songId: number) => {
-		if (openPlaylistDropdown === songId) {
-			setOpenPlaylistDropdown(null);
-		} else {
-			setOpenPlaylistDropdown(songId);
-		}
-	};
-
-	const performSearch = async (query: string, category: SearchCategory) => {
-		if (!query.trim()) return;
-
-		setSearchLoading(true);
-		setHasSearched(true);
-		setActiveQuery(query);
-		setSearchCategory(category);
-
-		try {
-			let endpoint = "";
-			switch (category) {
-				case "songs":
-					endpoint = `/songs/search?q=${encodeURIComponent(query)}`;
-					break;
-				case "albums":
-					endpoint = `/albums/search?q=${encodeURIComponent(query)}`;
-					break;
-				case "artists":
-					endpoint = `/users/search?type=ARTIST&q=${encodeURIComponent(query)}`;
-					break;
-				case "users":
-					endpoint = `/users/search?type=LISTENER&q=${encodeURIComponent(query)}`;
-					break;
-			}
-
-			const response = await axiosInstance.get(endpoint);
-			setSearchResults(response.data);
-		} catch (error) {
-			console.error("Search error:", error);
-			setSearchResults([]);
-		} finally {
-			setSearchLoading(false);
-		}
-	};
-
-	const handleSearch = () => {
-		performSearch(searchInput, searchCategory);
-	};
-
-	const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
-		if (e.key === "Enter") {
-			handleSearch();
-		}
-	};
-
-	const handleCategorySwitch = (category: SearchCategory) => {
-		performSearch(activeQuery, category);
-	};
-
-	const clearSearch = () => {
-		setSearchInput("");
-		setActiveQuery("");
-		setHasSearched(false);
-		setSearchResults([]);
-	};
-
-	const renderResults = () => {
-		if (searchLoading) {
-			return (
-				<div className="flex justify-center py-12">
-					<div className="w-10 h-10 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
-				</div>
-			);
-		}
-
-		if (searchResults.length === 0) {
-			return (
-				<div className="text-center py-12 text-gray-400">
-					<p className="text-lg">
-						No {searchCategory} found for "{activeQuery}"
-					</p>
-				</div>
-			);
-		}
-
-		return (
-			<div className="divide-y divide-white/5">
-				{searchResults.map((result, index) => {
-					switch (searchCategory) {
-						case "songs":
-							return (
-								<SongResult key={(result as Song).id} song={result as Song} />
-							);
-						case "albums":
-							return (
-								<AlbumResult
-									key={(result as Album).id}
-									album={result as Album}
-								/>
-							);
-						case "artists":
-							return (
-								<UserResult
-									key={(result as BaseNonAdminUser).username ?? index}
-									user={result as BaseNonAdminUser}
-									label="Artist"
-								/>
-							);
-						case "users":
-							return (
-								<UserResult
-									key={(result as BaseNonAdminUser).username ?? index}
-									user={result as BaseNonAdminUser}
-									label="User"
-								/>
-							);
-					}
-				})}
-			</div>
-		);
-	};
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white flex">
-			<div className="flex-1">
-				<div className="p-8">
-					<div className="max-w-7xl mx-auto">
-						{/* Search Bar */}
-						<div className="mb-8 flex flex-col md:flex-row gap-3">
-							<div className="flex flex-1 gap-0">
-								{/* Category Dropdown */}
-								<select
-									value={searchCategory}
-									onChange={(e) =>
-										setSearchCategory(e.target.value as SearchCategory)
-									}
-									className="bg-[#282828] border border-white/10 border-r-0 rounded-l-full py-2 px-4 text-white text-sm focus:outline-none focus:border-[#1db954] appearance-none cursor-pointer"
-								>
-									{CATEGORIES.map((cat) => (
-										<option key={cat.value} value={cat.value}>
-											{cat.label}
-										</option>
-									))}
-								</select>
-
-								{/* Search Input */}
-								<input
-									type="text"
-									placeholder={`Search ${searchCategory}...`}
-									value={searchInput}
-									onChange={(e) => setSearchInput(e.target.value)}
-									onKeyDown={handleKeyDown}
-									className="flex-1 bg-[#282828] border border-white/10 border-r-0 py-2 px-4 text-white focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-								/>
-
-								{/* Search Button */}
-								<button
-									onClick={handleSearch}
-									className="bg-[#1db954] hover:bg-[#1ed760] text-black font-medium px-6 rounded-r-full transition-colors flex items-center gap-2 cursor-pointer"
-								>
-									<svg
-										className="w-5 h-5"
-										fill="none"
-										stroke="currentColor"
-										viewBox="0 0 24 24"
-									>
-										<path
-											strokeLinecap="round"
-											strokeLinejoin="round"
-											strokeWidth={2}
-											d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
-										/>
-									</svg>
-									<span className="hidden sm:inline">Search</span>
-								</button>
-							</div>
-						</div>
-
-						{/* Search Results Section */}
-						{hasSearched ? (
-							<div>
-								<div className="flex items-center justify-between mb-4">
-									<h2 className="text-2xl font-bold text-white">
-										Results for "{activeQuery}"
-									</h2>
-									<button
-										onClick={clearSearch}
-										className="text-sm text-gray-400 hover:text-white transition-colors"
-									>
-										Clear search
-									</button>
-								</div>
-
-								{/* Quick category switch buttons */}
-								<div className="flex gap-2 mb-6">
-									{CATEGORIES.map((cat) => (
-										<button
-											key={cat.value}
-											onClick={() => handleCategorySwitch(cat.value)}
-											className={`px-4 py-1.5 rounded-full text-sm font-medium transition-colors cursor-pointer ${
-												searchCategory === cat.value
-													? "bg-[#1db954] text-black"
-													: "bg-white/10 text-white hover:bg-white/20"
-											}`}
-										>
-											{cat.label}
-										</button>
-									))}
-								</div>
-
-								{/* Results list */}
-								<div className="bg-[#1a1a2e]/50 rounded-xl overflow-hidden">
-									{renderResults()}
-								</div>
-							</div>
-						) : (
-							/* Default song grid */
-							<>
-								<div className="mb-8 border-b border-white/10 pb-6">
-									<h1 className="text-5xl font-bold mb-3 pb-1 bg-linear-to-r from-[#1db954] to-[#1ed760] bg-clip-text text-transparent">
-										Top Songs
-									</h1>
-									<p className="text-xl text-gray-400">
-										Listen to the newest tracks on FinkWave
-									</p>
-								</div>
-
-								{loading ? (
-									<div className="flex flex-col items-center justify-center min-h-[40vh] gap-6">
-										<div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin"></div>
-										<p className="text-xl text-gray-400">Loading songs...</p>
-									</div>
-								) : (
-									<div className="grid grid-cols-[repeat(auto-fill,minmax(220px,1fr))] gap-8 py-4">
-										{songs.map((song) => (
-											<div
-												key={song.id}
-												onClick={() => navigate(`/songs/${song.id}`)}
-												onMouseEnter={() => {
-													if (
-														openPlaylistDropdown !== null &&
-														openPlaylistDropdown !== song.id
-													) {
-														setOpenPlaylistDropdown(null);
-													}
-												}}
-												className="bg-[#282828] rounded-xl cursor-pointer shadow-lg transition-all duration-300 ease-in-out hover:-translate-y-2 hover:shadow-2xl group relative"
-											>
-												<div className="relative w-full pt-[100%] overflow-hidden bg-[#181818] rounded-t-xl">
-													<img
-														src={
-															song.cover
-																? `${baseURL}/${song.cover}`
-																: "/favicon.png"
-														}
-														alt={song.title}
-														className="absolute top-0 left-0 w-full h-full object-cover"
-														onError={(e) => {
-															(e.target as HTMLImageElement).src =
-																"/favicon.png";
-														}}
-													/>
-													<div className="absolute top-0 left-0 w-full h-full bg-black/60 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
-														{song.link ? (
-															<button
-																onClick={(e) => {
-																	e.stopPropagation();
-																	play({
-																		id: song.id,
-																		title: song.title,
-																		artist: song.releasedBy,
-																		cover: song.cover,
-																		embedUrl: toEmbedUrl(song.link!),
-																	});
-																}}
-																className={`w-14 h-14 rounded-full flex items-center justify-center text-xl shadow-[0_4px_12px_rgba(29,185,84,0.5)] transition-all cursor-pointer ${
-																	currentSong?.id === song.id
-																		? "bg-white text-[#1db954]"
-																		: "bg-[#1db954] text-black hover:scale-105"
-																}`}
-																aria-label={
-																	currentSong?.id === song.id
-																		? "Now playing"
-																		: "Play song"
-																}
-															>
-																{currentSong?.id === song.id ? (
-																	<svg
-																		className="w-6 h-6"
-																		fill="currentColor"
-																		viewBox="0 0 24 24"
-																	>
-																		<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-																	</svg>
-																) : (
-																	<svg
-																		className="w-6 h-6"
-																		fill="currentColor"
-																		viewBox="0 0 24 24"
-																	>
-																		<path d="M8 5v14l11-7z" />
-																	</svg>
-																)}
-															</button>
-														) : (
-															<div className="w-14 h-14 rounded-full bg-[#1db954] flex items-center justify-center text-xl text-black shadow-[0_4px_12px_rgba(29,185,84,0.5)]">
-																▶
-															</div>
-														)}
-													</div>
-												</div>
-												<div className="p-4">
-													<h3 className="text-lg font-semibold mb-2 text-white overflow-hidden text-ellipsis whitespace-nowrap">
-														{song.title}
-													</h3>
-													{song.album && (
-														<p
-															onClick={(e) => {
-																e.stopPropagation();
-																if (song.albumId) {
-																	navigate(`/collection/album/${song.albumId}`);
-																}
-															}}
-															className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${
-																song.albumId
-																	? "hover:underline cursor-pointer hover:text-white"
-																	: ""
-															}`}
-														>
-															{song.album}
-														</p>
-													)}
-													<p
-														onClick={(e) => {
-															e.stopPropagation();
-															if (song.artistUsername) {
-																navigate(`/users/${song.artistUsername}`);
-															}
-														}}
-														className={`text-sm text-gray-400 mb-3 overflow-hidden text-ellipsis whitespace-nowrap ${
-															song.artistUsername
-																? "hover:underline cursor-pointer hover:text-white"
-																: ""
-														}`}
-													>
-														{song.releasedBy}
-													</p>
-													{user && (
-														<div className="flex items-center justify-between mt-4 pt-3 border-t border-white/10">
-															{/* Like button */}
-															<button
-																onClick={(e) => {
-																	e.stopPropagation();
-																	toggleLike(song.id);
-																}}
-																className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
-																aria-label={
-																	song.isLikedByCurrentUser
-																		? "Unlike song"
-																		: "Like song"
-																}
-															>
-																{song.isLikedByCurrentUser ? (
-																	<svg
-																		className="w-6 h-6 fill-[#1db954]"
-																		viewBox="0 0 24 24"
-																	>
-																		<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
-																	</svg>
-																) : (
-																	<svg
-																		className="w-6 h-6"
-																		fill="none"
-																		stroke="currentColor"
-																		viewBox="0 0 24 24"
-																	>
-																		<path
-																			strokeLinecap="round"
-																			strokeLinejoin="round"
-																			strokeWidth={2}
-																			d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
-																		/>
-																	</svg>
-																)}
-															</button>
-
-															{/* Add to playlist button */}
-															<div className="relative">
-																<button
-																	onClick={(e) => {
-																		e.stopPropagation();
-																		togglePlaylistDropdown(song.id);
-																	}}
-																	className="text-gray-400 hover:text-[#1db954] transition-colors cursor-pointer"
-																	aria-label="Add to playlist"
-																>
-																	<svg
-																		className="w-6 h-6"
-																		fill="none"
-																		stroke="currentColor"
-																		viewBox="0 0 24 24"
-																	>
-																		<path
-																			strokeLinecap="round"
-																			strokeLinejoin="round"
-																			strokeWidth={2}
-																			d="M12 4v16m8-8H4"
-																		/>
-																	</svg>
-																</button>
-
-																<PlaylistDropdown
-																	songId={song.id}
-																	isOpen={openPlaylistDropdown === song.id}
-																	onClose={() => setOpenPlaylistDropdown(null)}
-																	direction="above"
-																/>
-															</div>
-														</div>
-													)}
-												</div>
-											</div>
-										))}
-									</div>
-								)}
-							</>
-						)}
-					</div>
-				</div>
-			</div>
-		</div>
-	);
-};
-
-export default LandingPage;
Index: ontend/src/pages/Login.tsx
===================================================================
--- frontend/src/pages/Login.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,109 +1,0 @@
-import { useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
-import { useAuth } from "../context/authContext";
-import type { User } from "../utils/types";
-
-const Login = () => {
-	const [username, setUsername] = useState("");
-	const [password, setPassword] = useState("");
-	const [error, setError] = useState<string | null>(null);
-	const { setUser } = useAuth();
-	const navigate = useNavigate();
-
-	const handleLogin = async (e: React.FormEvent) => {
-		e.preventDefault();
-		try {
-			const response = await axiosInstance.post<{
-				user: User;
-				tokenExpiresIn: number;
-			}>("/auth/login", { username, password });
-			scheduleTokenRefresh(response.data.tokenExpiresIn);
-			setUser(response.data.user);
-			navigate("/");
-			toast.success("Login successful!");
-		} catch (error: any) {
-			const errorMessage =
-				error.response?.data?.error ||
-				"Login failed. Please check your credentials.";
-			setError(`Login failed: ${errorMessage}`);
-		}
-	};
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center px-4">
-			<div className="w-full max-w-md">
-				<div className="text-center mb-8">
-					<h1 className="text-4xl font-extrabold text-white mb-2">
-						Welcome Back
-					</h1>
-					<p className="text-gray-400">Log in to continue to FinkWave</p>
-				</div>
-
-				<form
-					onSubmit={handleLogin}
-					className="bg-[#181818] rounded-xl p-8 space-y-6"
-				>
-					{error && (
-						<div className="bg-red-500/10 border border-red-500/20 rounded-lg p-3">
-							<p className="text-red-400 text-sm">{error}</p>
-						</div>
-					)}
-
-					<div>
-						<label
-							className="block text-sm font-medium text-gray-300 mb-2"
-							htmlFor="username"
-						>
-							Username
-						</label>
-						<input
-							type="text"
-							id="username"
-							className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							placeholder="Enter your username"
-							value={username}
-							onChange={(e) => setUsername(e.target.value)}
-						/>
-					</div>
-
-					<div>
-						<label
-							className="block text-sm font-medium text-gray-300 mb-2"
-							htmlFor="password"
-						>
-							Password
-						</label>
-						<input
-							type="password"
-							id="password"
-							className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							placeholder="Enter your password"
-							value={password}
-							onChange={(e) => setPassword(e.target.value)}
-						/>
-					</div>
-
-					<button
-						type="submit"
-						className="w-full py-3 bg-[#1db954] rounded-full text-black font-semibold hover:bg-[#1ed760] transition-colors cursor-pointer"
-					>
-						Log In
-					</button>
-
-					<p className="text-center text-sm text-gray-400">
-						Don't have an account?{" "}
-						<Link
-							to="/register"
-							className="text-[#1db954] hover:underline font-medium"
-						>
-							Sign up
-						</Link>
-					</p>
-				</form>
-			</div>
-		</div>
-	);
-};
-
-export default Login;
Index: ontend/src/pages/MusicalCollection.tsx
===================================================================
--- frontend/src/pages/MusicalCollection.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,257 +1,0 @@
-import { useEffect, useState } from "react";
-import { Link, useParams } from "react-router-dom";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import SongItem from "../components/SongItem";
-import { getErrorMessage } from "../utils/error";
-import type { Album, Playlist, Song } from "../utils/types";
-interface CollectionView {
-  id: number;
-  title: string;
-  cover?: string | null;
-  genre?: string;
-  type: string;
-  releasedBy: string;
-  isLikedByCurrentUser?: boolean;
-  songs: Song[];
-}
-
-const MusicalCollection = () => {
-  const { type, id } = useParams();
-  const [collection, setCollection] = useState<CollectionView | null>(null);
-  const [isLoading, setIsLoading] = useState(true);
-  const [error, setError] = useState<string | null>(null);
-  const [openDropdownSongId, setOpenDropdownSongId] = useState<number | null>(
-    null,
-  );
-
-  const normalizeCollection = (
-    data: Album | Playlist,
-    type: string,
-  ): CollectionView => {
-    if (type === "album") {
-      const album = data as Album;
-      return {
-        id: album.id,
-        title: album.title,
-        cover: album.cover,
-        genre: album.genre,
-        type: album.type,
-        releasedBy: album.releasedBy,
-        isLikedByCurrentUser: album.isLikedByCurrentUser,
-        songs: album.songs,
-      };
-    } else {
-      const playlist = data as Playlist;
-      return {
-        id: playlist.id,
-        title: playlist.name,
-        cover: playlist.cover,
-        genre: undefined,
-        type: "PLAYLIST",
-        releasedBy: playlist.creatorName,
-        isLikedByCurrentUser: undefined,
-        songs: playlist.songsInPlaylist,
-      };
-    }
-  };
-
-  const toggleLike = async (songId: number) => {
-    try {
-      await axiosInstance.post(`/musical-entity/${songId}/like`);
-      setCollection((prev) => {
-        if (!prev) return null;
-        return {
-          ...prev,
-          songs: prev.songs.map((s) =>
-            s.id === songId
-              ? { ...s, isLikedByCurrentUser: !s.isLikedByCurrentUser }
-              : s,
-          ),
-        };
-      });
-    } catch (err) {
-      console.error("Error toggling like:", err);
-    }
-  };
-
-  const toggleCollectionLike = async () => {
-    if (!collection) return;
-    try {
-      await axiosInstance.post(`/musical-entity/${collection.id}/like`);
-      setCollection((prev) => {
-        if (!prev) return null;
-        return { ...prev, isLikedByCurrentUser: !prev.isLikedByCurrentUser };
-      });
-    } catch (err) {
-      console.error("Error toggling collection like:", err);
-    }
-  };
-
-  useEffect(() => {
-    const fetchData = async () => {
-      setIsLoading(true);
-      setError(null);
-      try {
-        const endpoint =
-          type === "album" ? `/albums/${id}` : `/playlists/${id}`;
-        const response = await axiosInstance.get(endpoint);
-
-        const normalized = normalizeCollection(response.data, type!);
-        setCollection(normalized);
-      } catch (err: any) {
-        setError(getErrorMessage(err));
-      } finally {
-        setIsLoading(false);
-      }
-    };
-    fetchData();
-  }, [id, type]);
-
-  if (isLoading) {
-    return (
-      <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-        <div className="flex flex-col items-center gap-4">
-          <div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin" />
-          <p className="text-gray-400 text-lg">Loading collection…</p>
-        </div>
-      </div>
-    );
-  }
-
-  if (error) {
-    return (
-      <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-        <div className="text-center">
-          <p className="text-red-400 text-xl mb-4">{error}</p>
-          <Link to="/" className="text-[#1db954] hover:underline text-sm">
-            ← Back to Home
-          </Link>
-        </div>
-      </div>
-    );
-  }
-
-  if (!collection) return null;
-
-  return (
-    <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
-      <div className="max-w-5xl mx-auto px-6 py-10">
-        {/* Back link */}
-        <Link
-          to="/"
-          className="inline-flex items-center gap-1 text-gray-400 hover:text-white text-sm mb-8 transition-colors"
-        >
-          <svg
-            className="w-4 h-4"
-            fill="none"
-            stroke="currentColor"
-            viewBox="0 0 24 24"
-          >
-            <path
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              strokeWidth={2}
-              d="M15 19l-7-7 7-7"
-            />
-          </svg>
-          Back to Home
-        </Link>
-
-        {/* Hero section */}
-        <div className="flex flex-col md:flex-row gap-8 mb-10">
-          {/* Cover art */}
-          <div className="w-full md:w-72 shrink-0">
-            <div className="relative w-full pt-[100%] rounded-xl overflow-hidden shadow-2xl bg-[#181818]">
-              <img
-                src={
-                  collection.cover
-                    ? `${baseURL}/${collection.cover}`
-                    : "/favicon.png"
-                }
-                alt={collection.title}
-                className="absolute inset-0 w-full h-full object-cover"
-                onError={(e) => {
-                  (e.target as HTMLImageElement).src = "/favicon.png";
-                }}
-              />
-            </div>
-          </div>
-
-          {/* Collection info */}
-          <div className="flex flex-col justify-end gap-3 min-w-0">
-            <span className="text-xs uppercase tracking-widest text-gray-400 font-medium">
-              {collection.genre ? `${collection.genre} • ` : ""}
-              {collection.type === "PLAYLIST" ? "Playlist" : "Album"}
-            </span>
-            <h1 className="text-4xl md:text-5xl font-extrabold leading-tight truncate">
-              {collection.title}
-            </h1>
-
-            <p className="text-xl text-gray-300 font-semibold">
-              {collection.releasedBy}
-            </p>
-
-            {collection.songs && (
-              <p className="text-sm text-gray-500">
-                {collection.songs.length} song
-                {collection.songs.length !== 1 ? "s" : ""}
-              </p>
-            )}
-
-            {/* Action buttons */}
-            <div className="flex items-center gap-3 mt-4">
-              {type === "album" && (
-                <button
-                  onClick={toggleCollectionLike}
-                  className={`flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold transition-colors cursor-pointer ${
-                    collection.isLikedByCurrentUser
-                      ? "bg-[#1db954] text-black"
-                      : "bg-white/10 text-white hover:bg-white/20"
-                  }`}
-                >
-                  <svg
-                    className="w-5 h-5"
-                    fill={
-                      collection.isLikedByCurrentUser ? "currentColor" : "none"
-                    }
-                    stroke="currentColor"
-                    viewBox="0 0 24 24"
-                  >
-                    <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
-                  </svg>
-                  {collection.isLikedByCurrentUser ? "Liked" : "Like"}
-                </button>
-              )}
-            </div>
-          </div>
-        </div>
-
-        {/* Songs list */}
-        <div className="border-t border-white/10 pt-6">
-          <h2 className="text-2xl font-bold mb-4">Songs</h2>
-
-          {collection.songs && collection.songs.length > 0 ? (
-            <div className="space-y-1">
-              {collection.songs.map((song, index) => (
-                <SongItem
-                  key={song.id}
-                  song={song}
-                  index={index + 1}
-                  onLikeToggle={() => toggleLike(song.id)}
-                  isDropdownOpen={openDropdownSongId === song.id}
-                  onDropdownToggle={setOpenDropdownSongId}
-                />
-              ))}
-            </div>
-          ) : (
-            <div className="text-center py-12 text-gray-400">
-              <p className="text-lg">No songs available</p>
-            </div>
-          )}
-        </div>
-      </div>
-    </div>
-  );
-};
-
-export default MusicalCollection;
Index: ontend/src/pages/MySongs.tsx
===================================================================
--- frontend/src/pages/MySongs.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,257 +1,0 @@
-import { useEffect, useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import { useAuth } from "../context/authContext";
-import type { CatalogItem } from "../utils/types";
-
-const MySongs = () => {
-	const { user } = useAuth();
-	const navigate = useNavigate();
-	const [artistCatalog, setArtistCatalog] = useState<CatalogItem[]>([]);
-	const [loading, setLoading] = useState(true);
-	const [activeTab, setActiveTab] = useState<"singles" | "albums">("singles");
-
-	useEffect(() => {
-		const fetchArtistCatalog = async () => {
-			try {
-				setLoading(true);
-				const response =
-					await axiosInstance.get<CatalogItem[]>("/songs/catalog");
-				const data = response.data;
-				setArtistCatalog(data);
-			} catch (error) {
-				console.error("Error fetching music:", error);
-			} finally {
-				setLoading(false);
-			}
-		};
-
-		if (user?.isArtist) {
-			fetchArtistCatalog();
-		}
-	}, [user]);
-
-	if (!user?.isArtist) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="text-center">
-					<p className="text-red-400 text-xl mb-4">
-						You need to be an artist to access this page.
-					</p>
-					<Link to="/" className="text-[#1db954] hover:underline text-sm">
-						← Back to Home
-					</Link>
-				</div>
-			</div>
-		);
-	}
-
-	if (loading) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="flex flex-col items-center gap-4">
-					<div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin" />
-					<p className="text-gray-400 text-lg">Loading your music…</p>
-				</div>
-			</div>
-		);
-	}
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
-			<div className="max-w-6xl mx-auto px-6 py-10">
-				{/* Header */}
-				<div className="flex flex-col md:flex-row md:items-center justify-between gap-4 mb-8">
-					<div>
-						<h1 className="text-4xl font-extrabold mb-2">My Music</h1>
-						<p className="text-gray-400">Manage your songs and albums</p>
-					</div>
-					<button
-						onClick={() => navigate("/publish")}
-						className="flex items-center gap-2 px-6 py-3 bg-[#1db954] text-black rounded-full font-semibold hover:bg-[#1ed760] hover:scale-105 transition-all cursor-pointer"
-					>
-						<svg
-							className="w-5 h-5"
-							fill="none"
-							stroke="currentColor"
-							viewBox="0 0 24 24"
-						>
-							<path
-								strokeLinecap="round"
-								strokeLinejoin="round"
-								strokeWidth={2}
-								d="M12 4v16m8-8H4"
-							/>
-						</svg>
-						Publish New
-					</button>
-				</div>
-
-				{/* Tabs */}
-				<div className="flex gap-1 mb-8 bg-[#181818] rounded-lg p-1 w-fit">
-					<button
-						onClick={() => setActiveTab("singles")}
-						className={`px-6 py-2.5 rounded-md text-sm font-medium transition-colors cursor-pointer ${
-							activeTab === "singles"
-								? "bg-[#282828] text-white"
-								: "text-gray-400 hover:text-white"
-						}`}
-					>
-						Singles (
-						{artistCatalog.filter((item) => item.type === "SONG").length})
-					</button>
-					<button
-						onClick={() => setActiveTab("albums")}
-						className={`px-6 py-2.5 rounded-md text-sm font-medium transition-colors cursor-pointer ${
-							activeTab === "albums"
-								? "bg-[#282828] text-white"
-								: "text-gray-400 hover:text-white"
-						}`}
-					>
-						Albums (
-						{artistCatalog.filter((item) => item.type === "ALBUM").length})
-					</button>
-				</div>
-
-				{/* Content */}
-				{activeTab === "singles" ? (
-					<div className="space-y-2">
-						{artistCatalog.filter((item) => item.type === "SONG").length ===
-						0 ? (
-							<div className="text-center py-16">
-								<svg
-									className="w-16 h-16 mx-auto text-gray-600 mb-4"
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={1.5}
-										d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zM9 10l12-3"
-									/>
-								</svg>
-								<p className="text-gray-400 text-lg mb-4">
-									You haven't published any singles yet
-								</p>
-								<button
-									onClick={() => navigate("/publish")}
-									className="text-[#1db954] hover:underline"
-								>
-									Publish your first song
-								</button>
-							</div>
-						) : (
-							artistCatalog
-								.filter((item) => item.type === "SONG")
-								.map((song, index) => (
-									<div
-										key={song.id}
-										className="flex items-center gap-4 p-4 rounded-lg hover:bg-white/5 transition-colors group"
-									>
-										<span className="w-8 text-center text-gray-500 text-sm">
-											{index + 1}
-										</span>
-										<img
-											src={
-												song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"
-											}
-											alt={song.title}
-											className="w-12 h-12 rounded object-cover"
-											onError={(e) => {
-												(e.target as HTMLImageElement).src = "/favicon.png";
-											}}
-										/>
-										<div className="flex-1 min-w-0">
-											<Link
-												to={`/songs/${song.id}`}
-												className="text-white font-medium hover:underline truncate block"
-											>
-												{song.title}
-											</Link>
-											<p className="text-gray-400 text-sm">{song.genre}</p>
-										</div>
-										<p className="text-gray-400 text-sm">{song.releaseDate}</p>
-									</div>
-								))
-						)}
-					</div>
-				) : (
-					<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
-						{artistCatalog.filter((item) => item.type === "ALBUM").length ===
-						0 ? (
-							<div className="col-span-full text-center py-16">
-								<svg
-									className="w-16 h-16 mx-auto text-gray-600 mb-4"
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={1.5}
-										d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
-									/>
-								</svg>
-								<p className="text-gray-400 text-lg mb-4">
-									You haven't published any albums yet
-								</p>
-								<button
-									onClick={() => navigate("/publish")}
-									className="text-[#1db954] hover:underline"
-								>
-									Publish your first album
-								</button>
-							</div>
-						) : (
-							artistCatalog
-								.filter((item) => item.type === "ALBUM")
-								.map((album) => (
-									<Link
-										key={album.id}
-										to={`/collection/album/${album.id}`}
-										className="bg-[#181818] rounded-xl p-4 hover:bg-[#282828] transition-colors group"
-									>
-										<div className="relative w-full pt-[100%] rounded-lg overflow-hidden mb-4 bg-[#282828]">
-											<img
-												src={
-													album.cover
-														? `${baseURL}/${album.cover}`
-														: "/favicon.png"
-												}
-												alt={album.title}
-												className="absolute inset-0 w-full h-full object-cover"
-												onError={(e) => {
-													(e.target as HTMLImageElement).src = "/favicon.png";
-												}}
-											/>
-											<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
-												<div className="w-12 h-12 bg-[#1db954] rounded-full flex items-center justify-center shadow-xl transform translate-y-2 group-hover:translate-y-0 transition-transform">
-													<svg
-														className="w-6 h-6 text-black"
-														fill="currentColor"
-														viewBox="0 0 24 24"
-													>
-														<path d="M8 5v14l11-7z" />
-													</svg>
-												</div>
-											</div>
-										</div>
-										<h3 className="font-semibold text-white truncate mb-1">
-											{album.title}
-										</h3>
-										<p className="text-gray-400 text-sm">{album.genre}</p>
-										<p className="text-gray-400 text-sm">{album.releaseDate}</p>
-									</Link>
-								))
-						)}
-					</div>
-				)}
-			</div>
-		</div>
-	);
-};
-
-export default MySongs;
Index: ontend/src/pages/Nav.tsx
===================================================================
--- frontend/src/pages/Nav.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,156 +1,0 @@
-import { useEffect, useRef, useState } from "react";
-import { Link } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import Logo from "../assets/logo-finkwave.png";
-import { useAuth } from "../context/authContext";
-
-interface NavProps {
-	isSidebarOpen?: boolean;
-	onToggleSidebar?: () => void;
-}
-
-const Nav = ({ isSidebarOpen = false, onToggleSidebar }: NavProps) => {
-	const { user, setUser, isAuthLoading } = useAuth();
-	const [isDropdownOpen, setIsDropdownOpen] = useState(false);
-	const dropdownRef = useRef<HTMLDivElement>(null);
-
-	const handleLogout = async (e: React.MouseEvent<HTMLButtonElement>) => {
-		e.preventDefault();
-		try {
-			await axiosInstance.post("/auth/logout");
-			setUser(undefined);
-			setIsDropdownOpen(false);
-			window.location.href = "/";
-			// toast.success("Logout successful!");
-		} catch (error) {
-			console.error("Logout failed:", error);
-			toast.error("Logout failed!");
-		}
-	};
-
-	useEffect(() => {
-		const handleClickOutside = (event: MouseEvent) => {
-			if (
-				dropdownRef.current &&
-				!dropdownRef.current.contains(event.target as Node)
-			) {
-				setIsDropdownOpen(false);
-			}
-		};
-
-		document.addEventListener("mousedown", handleClickOutside);
-		return () => {
-			document.removeEventListener("mousedown", handleClickOutside);
-		};
-	}, []);
-
-	return (
-		<div
-			className={`bg-gray-800 p-4 flex justify-between items-center fixed top-0 right-0 z-50 transition-all duration-300 ${
-				isSidebarOpen ? "left-64" : "left-0"
-			}`}
-		>
-			<div className="flex items-center gap-4">
-				{onToggleSidebar && user && (
-					<button
-						onClick={onToggleSidebar}
-						className="text-white hover:text-[#1db954] transition-colors p-2 cursor-pointer"
-						aria-label="Toggle sidebar"
-					>
-						<svg
-							className="w-6 h-6"
-							fill="none"
-							stroke="currentColor"
-							viewBox="0 0 24 24"
-						>
-							<path
-								strokeLinecap="round"
-								strokeLinejoin="round"
-								strokeWidth={2}
-								d="M4 6h16M4 12h16M4 18h16"
-							/>
-						</svg>
-					</button>
-				)}
-				<Link to="/" className="text-white text-lg font-semibold">
-					<img src={Logo} alt="Finkwave Logo" className="h-12 w-auto" />
-				</Link>
-			</div>
-
-			<div className="flex items-center space-x-4">
-				{!isAuthLoading && (
-					<div className="flex items-center space-x-3">
-						{user?.isArtist && (
-							<Link
-								to="/my-songs"
-								className="text-white hover:text-[#1db954] px-4 py-2 text-sm font-medium transition-colors"
-							>
-								My Songs
-							</Link>
-						)}
-						{user ? (
-							<div className="relative" ref={dropdownRef}>
-								<button
-									onClick={() => setIsDropdownOpen(!isDropdownOpen)}
-									className="focus:outline-none focus:ring-2 focus:ring-blue-500 rounded-full"
-								>
-									{user.profilePhoto ? (
-										<img
-											src={`${baseURL}/${user.profilePhoto}`}
-											alt={`${user.username}'s profile`}
-											className="w-10 h-10 rounded-full object-cover cursor-pointer hover:ring-2 hover:ring-blue-400 transition-all"
-										/>
-									) : (
-										<div className="w-10 h-10 bg-blue-500 rounded-full flex items-center justify-center cursor-pointer hover:ring-2 hover:ring-blue-400 transition-all">
-											<span className="text-white text-lg font-semibold">
-												{user.username.charAt(0).toUpperCase()}
-											</span>
-										</div>
-									)}
-								</button>
-
-								{isDropdownOpen && (
-									<div className="absolute right-0 mt-2 w-48 bg-gray-700 rounded-lg shadow-lg py-1 z-50">
-										<Link
-											to="/me"
-											className="block px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
-											onClick={() => setIsDropdownOpen(false)}
-										>
-											Account
-										</Link>
-										<button
-											onClick={handleLogout}
-											className="w-full text-left px-4 py-2 text-sm text-white hover:bg-gray-600 transition-colors"
-										>
-											Log out
-										</button>
-									</div>
-								)}
-							</div>
-						) : (
-							<div className="flex items-center space-x-4">
-								<Link
-									to="/login"
-									className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm 
-                                    font-medium transition-colors duration-200 cursor-pointer"
-								>
-									Login
-								</Link>
-								<Link
-									to="/register"
-									className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-lg text-sm
-                                    font-medium transition-colors duration-200 cursor-pointer"
-								>
-									Register
-								</Link>
-							</div>
-						)}
-					</div>
-				)}
-			</div>
-		</div>
-	);
-};
-
-export default Nav;
Index: ontend/src/pages/PublishSong.tsx
===================================================================
--- frontend/src/pages/PublishSong.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,1041 +1,0 @@
-import { useCallback, useEffect, useRef, useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance from "../api/axiosInstance";
-import { useAuth } from "../context/authContext";
-import { GENRE_OPTIONS, ROLE_OPTIONS } from "../utils/consts";
-import type {
-	ArtistSearchResult,
-	Contributor,
-	SongEntry,
-} from "../utils/types";
-
-const MAX_CONTRIBUTORS = 5;
-const MAX_ALBUM_SONGS = 20;
-
-const PublishSong = () => {
-	const { user } = useAuth();
-	const navigate = useNavigate();
-
-	// Form state
-	const [releaseType, setReleaseType] = useState<"single" | "album">("single");
-	const [title, setTitle] = useState("");
-	const [genre, setGenre] = useState("");
-	const [link, setLink] = useState("");
-	const [coverFile, setCoverFile] = useState<File | null>(null);
-	const [coverPreview, setCoverPreview] = useState<string | null>(null);
-	const [contributors, setContributors] = useState<Contributor[]>([]);
-	const [isSubmitting, setIsSubmitting] = useState(false);
-
-	// Album-specific state
-	const [albumSongs, setAlbumSongs] = useState<SongEntry[]>([
-		{ title: "", link: "", contributors: [] },
-	]);
-
-	// Contributor search state
-	const [contributorSearch, setContributorSearch] = useState("");
-	const [searchResults, setSearchResults] = useState<ArtistSearchResult[]>([]);
-	const [isSearching, setIsSearching] = useState(false);
-	const [showSearchDropdown, setShowSearchDropdown] = useState(false);
-	const [selectedContributorRole, setSelectedContributorRole] = useState(
-		ROLE_OPTIONS[0].value,
-	);
-	const searchDropdownRef = useRef<HTMLDivElement>(null);
-	const searchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
-
-	// Album song contributor search state
-	const [albumSongContributorSearch, setAlbumSongContributorSearch] = useState<{
-		[key: number]: string;
-	}>({});
-	const [albumSongSearchResults, setAlbumSongSearchResults] = useState<{
-		[key: number]: ArtistSearchResult[];
-	}>({});
-	const [albumSongShowDropdown, setAlbumSongShowDropdown] = useState<{
-		[key: number]: boolean;
-	}>({});
-	const [albumSongSelectedRole, setAlbumSongSelectedRole] = useState<{
-		[key: number]: string;
-	}>({});
-
-	// Cleanup cover preview URL on unmount
-	useEffect(() => {
-		return () => {
-			if (coverPreview) {
-				URL.revokeObjectURL(coverPreview);
-			}
-		};
-	}, [coverPreview]);
-
-	// Click outside handler for search dropdown
-	useEffect(() => {
-		const handleClickOutside = (event: MouseEvent) => {
-			if (
-				searchDropdownRef.current &&
-				!searchDropdownRef.current.contains(event.target as Node)
-			) {
-				setShowSearchDropdown(false);
-			}
-		};
-		document.addEventListener("mousedown", handleClickOutside);
-		return () => document.removeEventListener("mousedown", handleClickOutside);
-	}, []);
-
-	// Search for artists (mock implementation)
-	const searchArtists = useCallback(async (query: string) => {
-		if (!query.trim()) {
-			setSearchResults([]);
-			return;
-		}
-
-		setIsSearching(true);
-		try {
-			const response = await axiosInstance.get(
-				`/users/search?type=ARTIST&q=${encodeURIComponent(query)}&limit=5`,
-			);
-			const filtered = response.data.filter(
-				(artist: ArtistSearchResult) =>
-					artist.fullName.toLowerCase().includes(query.toLowerCase()) ||
-					artist.username.toLowerCase().includes(query.toLowerCase()),
-			);
-			setSearchResults(filtered);
-		} catch (error) {
-			console.error("Error searching artists:", error);
-			setSearchResults([]);
-		} finally {
-			setIsSearching(false);
-		}
-	}, []);
-
-	// Debounced search
-	const handleContributorSearchChange = (value: string) => {
-		setContributorSearch(value);
-		setShowSearchDropdown(true);
-
-		if (searchTimeoutRef.current) {
-			clearTimeout(searchTimeoutRef.current);
-		}
-
-		searchTimeoutRef.current = setTimeout(() => {
-			searchArtists(value);
-		}, 300);
-	};
-
-	// Add contributor
-	const handleAddContributor = (artist: ArtistSearchResult) => {
-		if (contributors.length >= MAX_CONTRIBUTORS) {
-			toast.error(`Maximum ${MAX_CONTRIBUTORS} contributors allowed`);
-			return;
-		}
-
-		if (contributors.some((c) => c.id === artist.id)) {
-			toast.error("This contributor is already added");
-			return;
-		}
-
-		setContributors([
-			...contributors,
-			{
-				id: artist.id,
-				fullName: artist.fullName,
-				role: selectedContributorRole,
-			},
-		]);
-		setContributorSearch("");
-		setSearchResults([]);
-		setShowSearchDropdown(false);
-	};
-
-	// Remove contributor
-	const handleRemoveContributor = (id: number) => {
-		setContributors(contributors.filter((c) => c.id !== id));
-	};
-
-	// Handle cover file
-	const handleCoverChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-		const file = e.target.files?.[0];
-		if (file) {
-			if (file.size > 2 * 1024 * 1024) {
-				toast.error("Max file size is 5MB");
-				return;
-			}
-			if (!file.type.startsWith("image/")) {
-				toast.error("Only images allowed");
-				return;
-			}
-			if (coverPreview) {
-				URL.revokeObjectURL(coverPreview);
-			}
-			setCoverFile(file);
-			setCoverPreview(URL.createObjectURL(file));
-		}
-	};
-
-	const handleRemoveCover = () => {
-		if (coverPreview) {
-			URL.revokeObjectURL(coverPreview);
-		}
-		setCoverFile(null);
-		setCoverPreview(null);
-	};
-
-	// Album song handlers
-	const handleAddAlbumSong = () => {
-		if (albumSongs.length >= MAX_ALBUM_SONGS) {
-			toast.error(`Maximum ${MAX_ALBUM_SONGS} songs per album`);
-			return;
-		}
-		setAlbumSongs([...albumSongs, { title: "", link: "", contributors: [] }]);
-	};
-
-	const handleRemoveAlbumSong = (index: number) => {
-		if (albumSongs.length === 1) {
-			toast.error("Album must have at least one song");
-			return;
-		}
-		setAlbumSongs(albumSongs.filter((_, i) => i !== index));
-	};
-
-	const handleAlbumSongChange = (
-		index: number,
-		field: keyof SongEntry,
-		value: string | Contributor[],
-	) => {
-		const updated = [...albumSongs];
-		updated[index] = { ...updated[index], [field]: value };
-		setAlbumSongs(updated);
-	};
-
-	// Album song contributor search
-	const handleAlbumSongContributorSearch = useCallback(
-		async (index: number, query: string) => {
-			setAlbumSongContributorSearch((prev) => ({ ...prev, [index]: query }));
-			setAlbumSongShowDropdown((prev) => ({ ...prev, [index]: true }));
-
-			if (!query.trim()) {
-				setAlbumSongSearchResults((prev) => ({ ...prev, [index]: [] }));
-				return;
-			}
-
-			// TODO: replace with api call
-			const response = await axiosInstance.get(
-				`/users/search?type=ARTIST&q=${encodeURIComponent(query)}&limit=5`,
-			);
-			const filtered = response.data.filter(
-				(artist: ArtistSearchResult) =>
-					artist.fullName.toLowerCase().includes(query.toLowerCase()) ||
-					artist.username.toLowerCase().includes(query.toLowerCase()),
-			);
-			setAlbumSongSearchResults((prev) => ({ ...prev, [index]: filtered }));
-		},
-		[],
-	);
-
-	const handleAddAlbumSongContributor = (
-		songIndex: number,
-		artist: ArtistSearchResult,
-	) => {
-		const song = albumSongs[songIndex];
-		if (song.contributors.length >= MAX_CONTRIBUTORS) {
-			toast.error(`Maximum ${MAX_CONTRIBUTORS} contributors per song`);
-			return;
-		}
-
-		if (song.contributors.some((c) => c.id === artist.id)) {
-			toast.error("This contributor is already added");
-			return;
-		}
-
-		const role = albumSongSelectedRole[songIndex] || ROLE_OPTIONS[0].value;
-		const newContributor: Contributor = {
-			id: artist.id,
-			fullName: artist.fullName,
-			role,
-		};
-
-		handleAlbumSongChange(songIndex, "contributors", [
-			...song.contributors,
-			newContributor,
-		]);
-		setAlbumSongContributorSearch((prev) => ({ ...prev, [songIndex]: "" }));
-		setAlbumSongSearchResults((prev) => ({ ...prev, [songIndex]: [] }));
-		setAlbumSongShowDropdown((prev) => ({ ...prev, [songIndex]: false }));
-	};
-
-	const handleRemoveAlbumSongContributor = (songIndex: number, id: number) => {
-		const song = albumSongs[songIndex];
-		handleAlbumSongChange(
-			songIndex,
-			"contributors",
-			song.contributors.filter((c) => c.id !== id),
-		);
-	};
-
-	const handleSubmit = async (e: React.FormEvent) => {
-		e.preventDefault();
-
-		if (!title.trim()) {
-			toast.error("Please enter a title");
-			return;
-		}
-		if (!genre) {
-			toast.error("Please select a genre");
-			return;
-		}
-
-		if (releaseType === "single") {
-			if (!link.trim()) {
-				toast.error("Please enter a song link");
-				return;
-			}
-		} else {
-			for (let i = 0; i < albumSongs.length; i++) {
-				if (!albumSongs[i].title.trim()) {
-					toast.error(`Please enter a title for song ${i + 1}`);
-					return;
-				}
-				if (!albumSongs[i].link.trim()) {
-					toast.error(`Please enter a link for song ${i + 1}`);
-					return;
-				}
-			}
-		}
-
-		setIsSubmitting(true);
-
-		try {
-			const formData = new FormData();
-			formData.append("title", title);
-			formData.append("genre", genre);
-			if (coverFile) formData.append("cover", coverFile);
-
-			// Helper to append contributors in indexed format for Spring @ModelAttribute
-			const appendContributors = (
-				formData: FormData,
-				contributors: Contributor[],
-				prefix: string,
-			) => {
-				contributors.forEach((c, i) => {
-					formData.append(`${prefix}[${i}].id`, c.id.toString());
-					formData.append(`${prefix}[${i}].artistName`, c.fullName);
-					formData.append(`${prefix}[${i}].role`, c.role);
-				});
-			};
-
-			if (releaseType === "album") {
-				// Append album songs in indexed format
-				albumSongs.forEach((song, songIndex) => {
-					formData.append(`albumSongs[${songIndex}].title`, song.title);
-					formData.append(`albumSongs[${songIndex}].link`, song.link);
-					// Append nested contributors for each song
-					song.contributors.forEach((c, contribIndex) => {
-						formData.append(
-							`albumSongs[${songIndex}].contributors[${contribIndex}].id`,
-							c.id.toString(),
-						);
-						formData.append(
-							`albumSongs[${songIndex}].contributors[${contribIndex}].artistName`,
-							c.fullName,
-						);
-						formData.append(
-							`albumSongs[${songIndex}].contributors[${contribIndex}].role`,
-							c.role,
-						);
-					});
-				});
-				await axiosInstance.post("/musical-entity/publish/album", formData, {
-					headers: { "Content-Type": "multipart/form-data" },
-				});
-			} else {
-				formData.append("link", link);
-				appendContributors(formData, contributors, "contributors");
-				await axiosInstance.post("/musical-entity/publish/song", formData, {
-					headers: { "Content-Type": "multipart/form-data" },
-				});
-			}
-
-			toast.success(
-				releaseType === "single"
-					? "Song published successfully!"
-					: "Album published successfully!",
-			);
-			navigate("/my-songs");
-		} catch (error) {
-			console.error("Error publishing:", error);
-			toast.error("Failed to publish. Please try again.");
-		} finally {
-			setIsSubmitting(false);
-		}
-	};
-
-	if (!user?.isArtist) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="text-center">
-					<p className="text-red-400 text-xl mb-4">
-						You need to be an artist to publish music.
-					</p>
-					<Link to="/" className="text-[#1db954] hover:underline text-sm">
-						← Back to Home
-					</Link>
-				</div>
-			</div>
-		);
-	}
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
-			<div className="max-w-3xl mx-auto px-6 py-10">
-				{/* Back link */}
-				<Link
-					to="/my-songs"
-					className="inline-flex items-center gap-1 text-gray-400 hover:text-white text-sm mb-8 transition-colors"
-				>
-					<svg
-						className="w-4 h-4"
-						fill="none"
-						stroke="currentColor"
-						viewBox="0 0 24 24"
-					>
-						<path
-							strokeLinecap="round"
-							strokeLinejoin="round"
-							strokeWidth={2}
-							d="M15 19l-7-7 7-7"
-						/>
-					</svg>
-					Back to My Songs
-				</Link>
-
-				{/* Header */}
-				<h1 className="text-4xl font-extrabold mb-8">Publish New Music</h1>
-
-				<form onSubmit={handleSubmit} className="space-y-8">
-					{/* Release Type Selection */}
-					<div className="bg-[#181818] rounded-xl p-6">
-						<h2 className="text-lg font-semibold mb-4">
-							What are you releasing?
-						</h2>
-						<div className="flex gap-4">
-							<label
-								className={`flex-1 flex items-center justify-center gap-3 p-4 rounded-lg border-2 cursor-pointer transition-all ${
-									releaseType === "single"
-										? "border-[#1db954] bg-[#1db954]/10"
-										: "border-white/10 hover:border-white/20"
-								}`}
-							>
-								<input
-									type="radio"
-									name="releaseType"
-									value="single"
-									checked={releaseType === "single"}
-									onChange={() => setReleaseType("single")}
-									className="hidden"
-								/>
-								<svg
-									className={`w-8 h-8 ${releaseType === "single" ? "text-[#1db954]" : "text-gray-400"}`}
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={1.5}
-										d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2z"
-									/>
-								</svg>
-								<div>
-									<p className="font-medium">Single</p>
-									<p className="text-sm text-gray-400">One song</p>
-								</div>
-							</label>
-
-							<label
-								className={`flex-1 flex items-center justify-center gap-3 p-4 rounded-lg border-2 cursor-pointer transition-all ${
-									releaseType === "album"
-										? "border-[#1db954] bg-[#1db954]/10"
-										: "border-white/10 hover:border-white/20"
-								}`}
-							>
-								<input
-									type="radio"
-									name="releaseType"
-									value="album"
-									checked={releaseType === "album"}
-									onChange={() => setReleaseType("album")}
-									className="hidden"
-								/>
-								<svg
-									className={`w-8 h-8 ${releaseType === "album" ? "text-[#1db954]" : "text-gray-400"}`}
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={1.5}
-										d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
-									/>
-								</svg>
-								<div>
-									<p className="font-medium">Album</p>
-									<p className="text-sm text-gray-400">Multiple songs</p>
-								</div>
-							</label>
-						</div>
-					</div>
-
-					{/* Basic Info */}
-					<div className="bg-[#181818] rounded-xl p-6 space-y-6">
-						<h2 className="text-lg font-semibold">
-							{releaseType === "single" ? "Song Details" : "Album Details"}
-						</h2>
-
-						{/* Title */}
-						<div>
-							<label
-								htmlFor="title"
-								className="block text-sm font-medium text-gray-300 mb-2"
-							>
-								{releaseType === "single" ? "Song Title" : "Album Name"} *
-							</label>
-							<input
-								type="text"
-								id="title"
-								value={title}
-								onChange={(e) => setTitle(e.target.value)}
-								placeholder={
-									releaseType === "single"
-										? "Enter song title"
-										: "Enter album name"
-								}
-								className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							/>
-						</div>
-
-						{/* Genre */}
-						<div>
-							<label
-								htmlFor="genre"
-								className="block text-sm font-medium text-gray-300 mb-2"
-							>
-								Genre *
-							</label>
-							<select
-								id="genre"
-								value={genre}
-								onChange={(e) => setGenre(e.target.value)}
-								className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all appearance-none cursor-pointer"
-							>
-								<option value="">Select a genre</option>
-								{GENRE_OPTIONS.map((g) => (
-									<option key={g} value={g}>
-										{g}
-									</option>
-								))}
-							</select>
-						</div>
-
-						{/* Cover Art */}
-						<div>
-							<label className="block text-sm font-medium text-gray-300 mb-2">
-								Cover Art (optional)
-							</label>
-							<div className="flex items-start gap-4">
-								{coverPreview ? (
-									<div className="relative">
-										<img
-											src={coverPreview}
-											alt="Cover preview"
-											className="w-32 h-32 rounded-lg object-cover"
-										/>
-										<button
-											type="button"
-											onClick={handleRemoveCover}
-											className="absolute -top-2 -right-2 w-6 h-6 bg-red-500 rounded-full flex items-center justify-center text-white hover:bg-red-600 transition-colors"
-										>
-											<svg
-												className="w-4 h-4"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M6 18L18 6M6 6l12 12"
-												/>
-											</svg>
-										</button>
-									</div>
-								) : (
-									<label
-										htmlFor="cover"
-										className="w-32 h-32 rounded-lg border-2 border-dashed border-white/20 flex flex-col items-center justify-center cursor-pointer hover:border-[#1db954] transition-colors"
-									>
-										<svg
-											className="w-8 h-8 text-gray-400 mb-2"
-											fill="none"
-											stroke="currentColor"
-											viewBox="0 0 24 24"
-										>
-											<path
-												strokeLinecap="round"
-												strokeLinejoin="round"
-												strokeWidth={1.5}
-												d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"
-											/>
-										</svg>
-										<span className="text-xs text-gray-400">Upload</span>
-									</label>
-								)}
-								<input
-									type="file"
-									id="cover"
-									accept="image/*"
-									onChange={handleCoverChange}
-									className="hidden"
-								/>
-								<div className="text-sm text-gray-400">
-									<p>Recommended: 1400x1400px</p>
-									<p>Max size: 5MB</p>
-									<p>JPG, PNG, or WebP</p>
-								</div>
-							</div>
-						</div>
-
-						{/* Single: Link */}
-						{releaseType === "single" && (
-							<div>
-								<label
-									htmlFor="link"
-									className="block text-sm font-medium text-gray-300 mb-2"
-								>
-									Song Link (YouTube) *
-								</label>
-								<input
-									type="url"
-									id="link"
-									value={link}
-									onChange={(e) => setLink(e.target.value)}
-									placeholder="https://www.youtube.com/watch?v=..."
-									className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-								/>
-							</div>
-						)}
-					</div>
-
-					{/* Single: Contributors */}
-					{releaseType === "single" && (
-						<div className="bg-[#181818] rounded-xl p-6 space-y-4">
-							<div className="flex items-center justify-between">
-								<h2 className="text-lg font-semibold">
-									Contributors (optional)
-								</h2>
-								<span className="text-sm text-gray-400">
-									{contributors.length}/{MAX_CONTRIBUTORS}
-								</span>
-							</div>
-
-							{/* Added contributors */}
-							{contributors.length > 0 && (
-								<div className="flex flex-wrap gap-2 mb-4">
-									{contributors.map((contributor) => (
-										<div
-											key={contributor.id}
-											className="flex items-center gap-2 bg-[#282828] rounded-full py-1.5 px-3"
-										>
-											<span className="text-sm">{contributor.fullName}</span>
-											<span className="text-xs text-gray-400">
-												(
-												{
-													ROLE_OPTIONS.find((r) => r.value === contributor.role)
-														?.label
-												}
-												)
-											</span>
-											<button
-												type="button"
-												onClick={() => handleRemoveContributor(contributor.id)}
-												className="text-gray-400 hover:text-red-400 transition-colors"
-											>
-												<svg
-													className="w-4 h-4"
-													fill="none"
-													stroke="currentColor"
-													viewBox="0 0 24 24"
-												>
-													<path
-														strokeLinecap="round"
-														strokeLinejoin="round"
-														strokeWidth={2}
-														d="M6 18L18 6M6 6l12 12"
-													/>
-												</svg>
-											</button>
-										</div>
-									))}
-								</div>
-							)}
-
-							{/* Add contributor */}
-							{contributors.length < MAX_CONTRIBUTORS && (
-								<div className="flex gap-3">
-									<select
-										value={selectedContributorRole}
-										onChange={(e) => setSelectedContributorRole(e.target.value)}
-										className="bg-[#282828] border border-white/10 rounded-lg py-2.5 px-3 text-white text-sm focus:outline-none focus:border-[#1db954] appearance-none cursor-pointer"
-									>
-										{ROLE_OPTIONS.map((role) => (
-											<option key={role.value} value={role.value}>
-												{role.label}
-											</option>
-										))}
-									</select>
-
-									<div className="flex-1 relative" ref={searchDropdownRef}>
-										<input
-											type="text"
-											value={contributorSearch}
-											onChange={(e) =>
-												handleContributorSearchChange(e.target.value)
-											}
-											onFocus={() => setShowSearchDropdown(true)}
-											placeholder="Search for an artist..."
-											className="w-full bg-[#282828] border border-white/10 rounded-lg py-2.5 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-										/>
-
-										{/* Search dropdown */}
-										{showSearchDropdown && contributorSearch && (
-											<div className="absolute top-full left-0 right-0 mt-1 bg-[#282828] border border-white/10 rounded-lg shadow-xl z-10 max-h-48 overflow-y-auto">
-												{isSearching ? (
-													<div className="p-3 text-center text-gray-400">
-														<div className="w-5 h-5 border-2 border-white/10 border-t-[#1db954] rounded-full animate-spin mx-auto" />
-													</div>
-												) : searchResults.length > 0 ? (
-													searchResults.map((artist) => (
-														<button
-															key={artist.id}
-															type="button"
-															onClick={() => handleAddContributor(artist)}
-															className="w-full text-left px-4 py-2.5 hover:bg-white/10 transition-colors flex items-center gap-3"
-														>
-															<div className="w-8 h-8 bg-gray-600 rounded-full flex items-center justify-center">
-																{artist.profilePhoto ? (
-																	<img
-																		src={artist.profilePhoto}
-																		alt={artist.fullName}
-																		className="w-full h-full rounded-full object-cover"
-																	/>
-																) : (
-																	<span className="text-xs">
-																		{artist.fullName.charAt(0).toUpperCase()}
-																	</span>
-																)}
-															</div>
-															<div>
-																<p className="text-sm font-medium">
-																	{artist.fullName}
-																</p>
-																<p className="text-xs text-gray-400">
-																	@{artist.username}
-																</p>
-															</div>
-														</button>
-													))
-												) : (
-													<div className="p-3 text-center text-gray-400 text-sm">
-														No artists found
-													</div>
-												)}
-											</div>
-										)}
-									</div>
-								</div>
-							)}
-						</div>
-					)}
-
-					{/* Album: Songs */}
-					{releaseType === "album" && (
-						<div className="bg-[#181818] rounded-xl p-6 space-y-6">
-							<div className="flex items-center justify-between">
-								<h2 className="text-lg font-semibold">Album Songs</h2>
-								<span className="text-sm text-gray-400">
-									{albumSongs.length}/{MAX_ALBUM_SONGS} songs
-								</span>
-							</div>
-
-							{albumSongs.map((song, index) => (
-								<div
-									key={index}
-									className="bg-[#282828] rounded-lg p-4 space-y-4"
-								>
-									<div className="flex items-center justify-between">
-										<h3 className="font-medium text-gray-300">
-											Song {index + 1}
-										</h3>
-										{albumSongs.length > 1 && (
-											<button
-												type="button"
-												onClick={() => handleRemoveAlbumSong(index)}
-												className="text-gray-400 hover:text-red-400 transition-colors"
-											>
-												<svg
-													className="w-5 h-5"
-													fill="none"
-													stroke="currentColor"
-													viewBox="0 0 24 24"
-												>
-													<path
-														strokeLinecap="round"
-														strokeLinejoin="round"
-														strokeWidth={2}
-														d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
-													/>
-												</svg>
-											</button>
-										)}
-									</div>
-
-									{/* Song title */}
-									<input
-										type="text"
-										value={song.title}
-										onChange={(e) =>
-											handleAlbumSongChange(index, "title", e.target.value)
-										}
-										placeholder="Song title"
-										className="w-full bg-[#1a1a2e] border border-white/10 rounded-lg py-2.5 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-									/>
-
-									{/* Song link */}
-									<input
-										type="url"
-										value={song.link}
-										onChange={(e) =>
-											handleAlbumSongChange(index, "link", e.target.value)
-										}
-										placeholder="Song link (YouTube)"
-										className="w-full bg-[#1a1a2e] border border-white/10 rounded-lg py-2.5 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-									/>
-
-									{/* Contributors */}
-									<div>
-										<div className="flex items-center justify-between mb-2">
-											<label className="text-sm text-gray-400">
-												Contributors (optional)
-											</label>
-											<span className="text-xs text-gray-500">
-												{song.contributors.length}/{MAX_CONTRIBUTORS}
-											</span>
-										</div>
-
-										{/* Added contributors */}
-										{song.contributors.length > 0 && (
-											<div className="flex flex-wrap gap-2 mb-3">
-												{song.contributors.map((contributor) => (
-													<div
-														key={contributor.id}
-														className="flex items-center gap-2 bg-[#1a1a2e] rounded-full py-1 px-2.5 text-sm"
-													>
-														<span>{contributor.fullName}</span>
-														<span className="text-xs text-gray-400">
-															(
-															{
-																ROLE_OPTIONS.find(
-																	(r) => r.value === contributor.role,
-																)?.label
-															}
-															)
-														</span>
-														<button
-															type="button"
-															onClick={() =>
-																handleRemoveAlbumSongContributor(
-																	index,
-																	contributor.id,
-																)
-															}
-															className="text-gray-400 hover:text-red-400 transition-colors"
-														>
-															<svg
-																className="w-3.5 h-3.5"
-																fill="none"
-																stroke="currentColor"
-																viewBox="0 0 24 24"
-															>
-																<path
-																	strokeLinecap="round"
-																	strokeLinejoin="round"
-																	strokeWidth={2}
-																	d="M6 18L18 6M6 6l12 12"
-																/>
-															</svg>
-														</button>
-													</div>
-												))}
-											</div>
-										)}
-
-										{/* Add contributor */}
-										{song.contributors.length < MAX_CONTRIBUTORS && (
-											<div className="flex gap-2">
-												<select
-													value={
-														albumSongSelectedRole[index] ||
-														ROLE_OPTIONS[0].value
-													}
-													onChange={(e) =>
-														setAlbumSongSelectedRole((prev) => ({
-															...prev,
-															[index]: e.target.value,
-														}))
-													}
-													className="bg-[#1a1a2e] border border-white/10 rounded-lg py-2 px-2.5 text-white text-sm focus:outline-none focus:border-[#1db954] appearance-none cursor-pointer"
-												>
-													{ROLE_OPTIONS.map((role) => (
-														<option key={role.value} value={role.value}>
-															{role.label}
-														</option>
-													))}
-												</select>
-
-												<div className="flex-1 relative">
-													<input
-														type="text"
-														value={albumSongContributorSearch[index] || ""}
-														onChange={(e) =>
-															handleAlbumSongContributorSearch(
-																index,
-																e.target.value,
-															)
-														}
-														onFocus={() =>
-															setAlbumSongShowDropdown((prev) => ({
-																...prev,
-																[index]: true,
-															}))
-														}
-														placeholder="Search artist..."
-														className="w-full bg-[#1a1a2e] border border-white/10 rounded-lg py-2 px-3 text-white text-sm placeholder-gray-500 focus:outline-none focus:border-[#1db954] transition-all"
-													/>
-
-													{/* Dropdown */}
-													{albumSongShowDropdown[index] &&
-														albumSongContributorSearch[index] && (
-															<div className="absolute top-full left-0 right-0 mt-1 bg-[#1a1a2e] border border-white/10 rounded-lg shadow-xl z-10 max-h-40 overflow-y-auto">
-																{(albumSongSearchResults[index] || []).length >
-																0 ? (
-																	albumSongSearchResults[index].map(
-																		(artist) => (
-																			<button
-																				key={artist.id}
-																				type="button"
-																				onClick={() =>
-																					handleAddAlbumSongContributor(
-																						index,
-																						artist,
-																					)
-																				}
-																				className="w-full text-left px-3 py-2 hover:bg-white/10 transition-colors flex items-center gap-2"
-																			>
-																				<div className="w-6 h-6 bg-gray-600 rounded-full flex items-center justify-center text-xs">
-																					{artist.fullName
-																						.charAt(0)
-																						.toUpperCase()}
-																				</div>
-																				<span className="text-sm">
-																					{artist.fullName}
-																				</span>
-																			</button>
-																		),
-																	)
-																) : (
-																	<div className="p-2 text-center text-gray-400 text-sm">
-																		No artists found
-																	</div>
-																)}
-															</div>
-														)}
-												</div>
-											</div>
-										)}
-									</div>
-								</div>
-							))}
-
-							{/* Add song button */}
-							{albumSongs.length < MAX_ALBUM_SONGS && (
-								<button
-									type="button"
-									onClick={handleAddAlbumSong}
-									className="w-full py-3 border-2 border-dashed border-white/20 rounded-lg text-gray-400 hover:text-white hover:border-[#1db954] transition-all flex items-center justify-center gap-2"
-								>
-									<svg
-										className="w-5 h-5"
-										fill="none"
-										stroke="currentColor"
-										viewBox="0 0 24 24"
-									>
-										<path
-											strokeLinecap="round"
-											strokeLinejoin="round"
-											strokeWidth={2}
-											d="M12 4v16m8-8H4"
-										/>
-									</svg>
-									Add Another Song
-								</button>
-							)}
-						</div>
-					)}
-
-					{/* Submit */}
-					<div className="flex gap-4">
-						<button
-							type="button"
-							onClick={() => navigate("/my-songs")}
-							className="flex-1 py-3 px-6 border border-white/20 rounded-full text-white font-semibold hover:bg-white/5 transition-colors cursor-pointer"
-						>
-							Cancel
-						</button>
-						<button
-							type="submit"
-							disabled={isSubmitting}
-							className="flex-1 py-3 px-6 bg-[#1db954] rounded-full text-black font-semibold hover:bg-[#1ed760] transition-colors disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer flex items-center justify-center gap-2"
-						>
-							{isSubmitting ? (
-								<>
-									<div className="w-5 h-5 border-2 border-black/30 border-t-black rounded-full animate-spin" />
-									Publishing...
-								</>
-							) : (
-								<>
-									<svg
-										className="w-5 h-5"
-										fill="none"
-										stroke="currentColor"
-										viewBox="0 0 24 24"
-									>
-										<path
-											strokeLinecap="round"
-											strokeLinejoin="round"
-											strokeWidth={2}
-											d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"
-										/>
-									</svg>
-									Publish {releaseType === "single" ? "Song" : "Album"}
-								</>
-							)}
-						</button>
-					</div>
-				</form>
-			</div>
-		</div>
-	);
-};
-
-export default PublishSong;
Index: ontend/src/pages/Register.tsx
===================================================================
--- frontend/src/pages/Register.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,359 +1,0 @@
-import { useEffect, useState } from "react";
-import { Link, useNavigate } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { scheduleTokenRefresh } from "../api/axiosInstance";
-import { useAuth } from "../context/authContext";
-import type { User, UserRegisterType } from "../utils/types";
-
-const Register = () => {
-	const { setUser } = useAuth();
-	const [username, setUsername] = useState("");
-	const [password, setPassword] = useState("");
-	const [fullname, setFullname] = useState("");
-	const [userType, setUserType] = useState<UserRegisterType[]>([]);
-	const [email, setEmail] = useState("");
-	const [profilePhotoFile, setProfilePhotoFile] = useState<File | null>(null);
-	const [previewProfilePhoto, setPreviewProfilePhoto] = useState<string | null>(
-		null,
-	);
-	const [error, setError] = useState<string | null>(null);
-
-	const navigate = useNavigate();
-
-	useEffect(() => {
-		return () => {
-			if (previewProfilePhoto) {
-				URL.revokeObjectURL(previewProfilePhoto);
-			}
-		};
-	}, [previewProfilePhoto]);
-
-	const handleRemoveFile = () => {
-		if (previewProfilePhoto) {
-			URL.revokeObjectURL(previewProfilePhoto);
-		}
-		setProfilePhotoFile(null);
-		setPreviewProfilePhoto(null);
-	};
-
-	const handleRegister = async (e: React.FormEvent) => {
-		e.preventDefault();
-		if (profilePhotoFile && profilePhotoFile.size > 5 * 1024 * 1024) {
-			toast.error("Max file size is 5MB");
-			return;
-		}
-
-		if (
-			username === "" ||
-			password === "" ||
-			fullname === "" ||
-			email === "" ||
-			userType.length === 0
-		) {
-			setError("Please fill in all required fields.");
-			return;
-		}
-		if (profilePhotoFile && !profilePhotoFile.type.startsWith("image/")) {
-			toast.error("Only images allowed");
-			return;
-		}
-		const formData = new FormData();
-		if (profilePhotoFile) formData.append("profilePhoto", profilePhotoFile);
-		formData.append("username", username);
-		formData.append("fullname", fullname);
-		formData.append("email", email);
-		formData.append("password", password);
-		userType.forEach((type) => formData.append("userType", type));
-
-		try {
-			const response = await axiosInstance.post<{
-				user: User;
-				tokenExpiresIn: number;
-			}>("/auth/register", formData);
-			scheduleTokenRefresh(response.data.tokenExpiresIn);
-			setUser(response.data.user);
-			navigate("/");
-			toast.success("Registration successful!");
-		} catch (error: any) {
-			const errorMessage = error.response?.data?.error || "Please try again.";
-			setError(`Registration failed: ${errorMessage}`);
-		}
-	};
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center px-4 py-10">
-			<div className="w-full max-w-md">
-				<div className="text-center mb-8">
-					<h1 className="text-4xl font-extrabold text-white mb-2">
-						Create Account
-					</h1>
-					<p className="text-gray-400">Join FinkWave and discover music</p>
-				</div>
-
-				<form
-					className="bg-[#181818] rounded-xl p-8 space-y-6"
-					onSubmit={handleRegister}
-				>
-					{error && (
-						<div className="bg-red-500/10 border border-red-500/20 rounded-lg p-3">
-							<p className="text-red-400 text-sm">{error}</p>
-						</div>
-					)}
-
-					<div>
-						<label
-							className="block text-sm font-medium text-gray-300 mb-2"
-							htmlFor="username"
-						>
-							Username *
-						</label>
-						<input
-							type="text"
-							id="username"
-							className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							placeholder="Choose a username"
-							value={username}
-							onChange={(e) => setUsername(e.target.value)}
-						/>
-					</div>
-
-					<div>
-						<label
-							className="block text-sm font-medium text-gray-300 mb-2"
-							htmlFor="password"
-						>
-							Password *
-						</label>
-						<input
-							type="password"
-							id="password"
-							className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							placeholder="Create a password"
-							value={password}
-							onChange={(e) => setPassword(e.target.value)}
-						/>
-					</div>
-
-					<div>
-						<label
-							className="block text-sm font-medium text-gray-300 mb-2"
-							htmlFor="fullName"
-						>
-							Full Name *
-						</label>
-						<input
-							type="text"
-							id="fullName"
-							className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							placeholder="Enter your full name"
-							value={fullname}
-							onChange={(e) => setFullname(e.target.value)}
-						/>
-					</div>
-
-					<div>
-						<label
-							className="block text-sm font-medium text-gray-300 mb-2"
-							htmlFor="email"
-						>
-							Email *
-						</label>
-						<input
-							type="email"
-							id="email"
-							className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
-							placeholder="Enter your email"
-							value={email}
-							onChange={(e) => setEmail(e.target.value)}
-						/>
-					</div>
-
-					<div>
-						<label className="block text-sm font-medium text-gray-300 mb-3">
-							I want to be a... *
-						</label>
-						<div className="flex gap-3">
-							<label
-								className={`flex-1 flex items-center justify-center gap-2 p-3 rounded-lg border-2 cursor-pointer transition-all ${
-									userType.includes("ARTIST")
-										? "border-[#1db954] bg-[#1db954]/10"
-										: "border-white/10 hover:border-white/20"
-								}`}
-							>
-								<input
-									type="checkbox"
-									value="ARTIST"
-									checked={userType.includes("ARTIST")}
-									onChange={(e) => {
-										if (e.target.checked) {
-											setUserType((prev) => [...prev, "ARTIST"]);
-										} else {
-											setUserType((prev) =>
-												prev.filter((type) => type !== "ARTIST"),
-											);
-										}
-									}}
-									className="hidden"
-								/>
-								<svg
-									className={`w-5 h-5 ${userType.includes("ARTIST") ? "text-[#1db954]" : "text-gray-400"}`}
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={1.5}
-										d="M9 19V6l12-3v13M9 19c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2zm12-3c0 1.105-1.343 2-3 2s-3-.895-3-2 1.343-2 3-2 3 .895 3 2z"
-									/>
-								</svg>
-								<span
-									className={`text-sm font-medium ${userType.includes("ARTIST") ? "text-white" : "text-gray-400"}`}
-								>
-									Artist
-								</span>
-							</label>
-
-							<label
-								className={`flex-1 flex items-center justify-center gap-2 p-3 rounded-lg border-2 cursor-pointer transition-all ${
-									userType.includes("LISTENER")
-										? "border-[#1db954] bg-[#1db954]/10"
-										: "border-white/10 hover:border-white/20"
-								}`}
-							>
-								<input
-									type="checkbox"
-									value="LISTENER"
-									checked={userType.includes("LISTENER")}
-									onChange={(e) => {
-										if (e.target.checked) {
-											setUserType((prev) => [...prev, "LISTENER"]);
-										} else {
-											setUserType((prev) =>
-												prev.filter((type) => type !== "LISTENER"),
-											);
-										}
-									}}
-									className="hidden"
-								/>
-								<svg
-									className={`w-5 h-5 ${userType.includes("LISTENER") ? "text-[#1db954]" : "text-gray-400"}`}
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={1.5}
-										d="M15.536 8.464a5 5 0 010 7.072M12 12h.01M18.364 5.636a9 9 0 010 12.728M5.636 18.364a9 9 0 010-12.728"
-									/>
-								</svg>
-								<span
-									className={`text-sm font-medium ${userType.includes("LISTENER") ? "text-white" : "text-gray-400"}`}
-								>
-									Listener
-								</span>
-							</label>
-						</div>
-					</div>
-
-					{/* Profile Photo - PublishSong style */}
-					<div>
-						<label className="block text-sm font-medium text-gray-300 mb-2">
-							Profile Photo (optional)
-						</label>
-						<div className="flex items-center justify-start gap-4">
-							{previewProfilePhoto ? (
-								<div className="relative">
-									<img
-										src={previewProfilePhoto}
-										alt="Profile Preview"
-										className="w-24 h-24 rounded-full object-cover"
-									/>
-									<button
-										type="button"
-										onClick={handleRemoveFile}
-										className="absolute -top-2 -right-2 w-6 h-6 bg-red-500 rounded-full flex items-center justify-center text-white hover:bg-red-600 transition-colors"
-									>
-										<svg
-											className="w-4 h-4"
-											fill="none"
-											stroke="currentColor"
-											viewBox="0 0 24 24"
-										>
-											<path
-												strokeLinecap="round"
-												strokeLinejoin="round"
-												strokeWidth={2}
-												d="M6 18L18 6M6 6l12 12"
-											/>
-										</svg>
-									</button>
-								</div>
-							) : (
-								<label
-									htmlFor="profilePhoto"
-									className="w-24 h-24 rounded-full border-2 border-dashed border-white/20 flex flex-col items-center justify-center cursor-pointer hover:border-[#1db954] transition-colors"
-								>
-									<svg
-										className="w-8 h-8 text-gray-400 mb-1"
-										fill="none"
-										stroke="currentColor"
-										viewBox="0 0 24 24"
-									>
-										<path
-											strokeLinecap="round"
-											strokeLinejoin="round"
-											strokeWidth={1.5}
-											d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
-										/>
-									</svg>
-									<span className="text-xs text-gray-400">Upload</span>
-								</label>
-							)}
-							<input
-								type="file"
-								accept="image/*"
-								id="profilePhoto"
-								className="hidden"
-								onChange={(e) => {
-									if (e.target.files && e.target.files[0]) {
-										setProfilePhotoFile(e.target.files[0]);
-										setPreviewProfilePhoto(
-											URL.createObjectURL(e.target.files[0]),
-										);
-									}
-								}}
-							/>
-							<div className="text-sm text-gray-400 pt-2">
-								<p>Max size: 2MB</p>
-								<p>JPG, PNG, or WebP</p>
-							</div>
-						</div>
-					</div>
-
-					<button
-						type="submit"
-						className="w-full py-3 bg-[#1db954] rounded-full text-black font-semibold hover:bg-[#1ed760] transition-colors cursor-pointer"
-					>
-						Create Account
-					</button>
-
-					<p className="text-center text-sm text-gray-400">
-						Already have an account?{" "}
-						<Link
-							to="/login"
-							className="text-[#1db954] hover:underline font-medium"
-						>
-							Log in
-						</Link>
-					</p>
-				</form>
-			</div>
-		</div>
-	);
-};
-
-export default Register;
Index: ontend/src/pages/SongDetail.tsx
===================================================================
--- frontend/src/pages/SongDetail.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,595 +1,0 @@
-import { useEffect, useState } from "react";
-import { Link, useParams } from "react-router-dom";
-import { toast } from "react-toastify";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import PlaylistDropdown from "../components/playlist/PlaylistDropdown";
-import { useAuth } from "../context/authContext";
-import { usePlayer } from "../context/playerContext";
-import type { SongDetail as SongDetailType } from "../utils/types";
-import { toEmbedUrl } from "../utils/utils";
-
-const ROLE_LABELS: Record<string, string> = {
-	MAIN_VOCAL: "Main Vocal",
-	FEATURED: "Featured",
-	PRODUCER: "Producer",
-	SONGWRITER: "Songwriter",
-	COMPOSER: "Composer",
-	MIXER: "Mixer",
-	ENGINEER: "Engineer",
-};
-
-const formatRole = (role: string): string => {
-	return ROLE_LABELS[role] || role.replace(/_/g, " ");
-};
-
-const renderStars = (grade: number) => {
-	return (
-		<div className="flex gap-0.5">
-			{[1, 2, 3, 4, 5].map((star) => (
-				<svg
-					key={star}
-					className={`w-4 h-4 ${star <= grade ? "text-yellow-400" : "text-gray-600"}`}
-					fill="currentColor"
-					viewBox="0 0 20 20"
-				>
-					<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
-				</svg>
-			))}
-		</div>
-	);
-};
-
-const SongDetail = () => {
-	const { id } = useParams<{ id: string }>();
-	const { user } = useAuth();
-	const { play, currentSong } = usePlayer();
-	const [song, setSong] = useState<SongDetailType | null>(null);
-	const [loading, setLoading] = useState(true);
-	const [error, setError] = useState<string | null>(null);
-	const [showReviewModal, setShowReviewModal] = useState(false);
-	const [reviewRating, setReviewRating] = useState(0);
-	const [reviewComment, setReviewComment] = useState("");
-	const [hoverRating, setHoverRating] = useState(0);
-	const [showPlaylistDropdown, setShowPlaylistDropdown] = useState(false);
-	console.log(user);
-	useEffect(() => {
-		const fetchSong = async () => {
-			try {
-				setLoading(true);
-				const response = await axiosInstance.get(`/songs/${id}/details`);
-				setSong(response.data);
-			} catch (err) {
-				console.error("Error fetching song details:", err);
-				setError("Failed to load song details.");
-			} finally {
-				setLoading(false);
-			}
-		};
-		if (id) fetchSong();
-	}, [id]);
-
-	const handleSubmitReview = async () => {
-		if (reviewRating === 0) {
-			// todo: replace with toast
-			alert("Please select a rating");
-			return;
-		}
-		try {
-			await axiosInstance.post(`reviews/${song?.id}`, {
-				grade: reviewRating,
-				comment: reviewComment,
-			});
-			const response = await axiosInstance.get(`/songs/${id}/details`);
-			setSong(response.data);
-		} catch (err) {
-			// todo: replace with toast
-			console.error("Error submitting review:", err);
-		} finally {
-			setShowReviewModal(false);
-			setReviewRating(0);
-			setReviewComment("");
-			setHoverRating(0);
-		}
-	};
-
-	const deleteReview = async () => {
-		try {
-			await axiosInstance.delete(`reviews/${song?.id}`);
-			const response = await axiosInstance.get(`/songs/${id}/details`);
-			setSong(response.data);
-		} catch (err) {
-			toast.error("Failed to delete review");
-			console.error("Error deleting review:", err);
-		}
-	};
-
-	const toggleLike = async () => {
-		if (!song) return;
-		try {
-			await axiosInstance.post(`/musical-entity/${song.id}/like`);
-			setSong((prev) =>
-				prev
-					? { ...prev, isLikedByCurrentUser: !prev.isLikedByCurrentUser }
-					: prev,
-			);
-		} catch (err) {
-			toast.error("Failed to toggle like");
-			console.error("Error toggling like:", err);
-		}
-	};
-
-	if (loading) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="flex flex-col items-center gap-4">
-					<div className="w-12 h-12 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin" />
-					<p className="text-gray-400 text-lg">Loading song…</p>
-				</div>
-			</div>
-		);
-	}
-
-	if (error || !song) {
-		return (
-			<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-				<div className="text-center">
-					<p className="text-red-400 text-xl mb-4">
-						{error ?? "Song not found"}
-					</p>
-					<Link to="/" className="text-[#1db954] hover:underline text-sm">
-						← Back to Home
-					</Link>
-				</div>
-			</div>
-		);
-	}
-
-	const otherContributors = song.contributions.filter(
-		(c) => c.artistName !== song.releasedBy,
-	);
-
-	const avgRating =
-		song.reviews.length > 0
-			? (
-					song.reviews.reduce((sum, r) => sum + r.grade, 0) /
-					song.reviews.length
-				).toFixed(1)
-			: null;
-
-	return (
-		<div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
-			<div className="max-w-5xl mx-auto px-6 py-10">
-				{/* Back link */}
-				<Link
-					to="/"
-					className="inline-flex items-center gap-1 text-gray-400 hover:text-white text-sm mb-8 transition-colors"
-				>
-					<svg
-						className="w-4 h-4"
-						fill="none"
-						stroke="currentColor"
-						viewBox="0 0 24 24"
-					>
-						<path
-							strokeLinecap="round"
-							strokeLinejoin="round"
-							strokeWidth={2}
-							d="M15 19l-7-7 7-7"
-						/>
-					</svg>
-					Back to Home
-				</Link>
-
-				{/* Hero section */}
-				<div className="flex flex-col md:flex-row gap-8 mb-10">
-					{/* Cover art */}
-					<div className="w-full md:w-72 shrink-0">
-						<div className="relative w-full pt-[100%] rounded-xl overflow-hidden shadow-2xl bg-[#181818]">
-							<img
-								src={song.cover ? `${baseURL}/${song.cover}` : "/favicon.png"}
-								alt={song.title}
-								className="absolute inset-0 w-full h-full object-cover"
-								onError={(e) => {
-									(e.target as HTMLImageElement).src = "/favicon.png";
-								}}
-							/>
-						</div>
-					</div>
-
-					{/* Song info */}
-					<div className="flex flex-col justify-end gap-3 min-w-0">
-						<span className="text-xs uppercase tracking-widest text-gray-400 font-medium">
-							{song.genre} • Song
-						</span>
-						<h1 className="text-4xl md:text-5xl font-extrabold leading-tight truncate">
-							{song.title}
-						</h1>
-
-						{/* Main artist */}
-						<p className="text-xl text-gray-300 font-semibold">
-							{song.releasedBy}
-						</p>
-
-						{/* Album */}
-						{song.album && (
-							<p className="text-sm text-gray-500">
-								Album: <span className="text-gray-300">{song.album}</span>
-							</p>
-						)}
-
-						{/* Rating summary */}
-						{avgRating && (
-							<div className="flex items-center gap-2 mt-1">
-								{renderStars(Math.round(Number(avgRating)))}
-								<span className="text-sm text-gray-400">
-									{avgRating} · {song.reviews.length}{" "}
-									{song.reviews.length === 1 ? "review" : "reviews"}
-								</span>
-							</div>
-						)}
-
-						{/* Action buttons */}
-						<div className="flex items-center gap-3 mt-4">
-							{/* Play button */}
-							{song.link && (
-								<button
-									onClick={() =>
-										play({
-											id: song.id,
-											title: song.title,
-											artist: song.releasedBy,
-											cover: song.cover,
-											embedUrl: toEmbedUrl(song.link!),
-										})
-									}
-									className={`flex items-center gap-2 px-6 py-3 rounded-full text-sm font-semibold transition-all cursor-pointer ${
-										currentSong?.id === song.id
-											? "bg-white text-[#1db954]"
-											: "bg-[#1db954] text-black hover:bg-[#1ed760] hover:scale-105"
-									}`}
-								>
-									{currentSong?.id === song.id ? (
-										<>
-											<svg
-												className="w-5 h-5"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
-											</svg>
-											Now Playing
-										</>
-									) : (
-										<>
-											<svg
-												className="w-5 h-5"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path d="M8 5v14l11-7z" />
-											</svg>
-											Play Song
-										</>
-									)}
-								</button>
-							)}
-
-							{user && (
-								<>
-									<button
-										onClick={toggleLike}
-										className={`flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold transition-colors cursor-pointer ${
-											song.isLikedByCurrentUser
-												? "bg-[#1db954] text-black"
-												: "bg-white/10 text-white hover:bg-white/20"
-										}`}
-									>
-										{song.isLikedByCurrentUser ? (
-											<svg
-												className="w-5 h-5"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" />
-											</svg>
-										) : (
-											<svg
-												className="w-5 h-5"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
-												/>
-											</svg>
-										)}
-										{song.isLikedByCurrentUser ? "Liked" : "Like"}
-									</button>
-
-									{/* Add to Playlist button */}
-									<div className="relative">
-										<button
-											onClick={() => setShowPlaylistDropdown((prev) => !prev)}
-											className="flex items-center gap-2 px-5 py-3 rounded-full text-sm font-semibold bg-white/10 text-white hover:bg-white/20 transition-colors cursor-pointer"
-										>
-											<svg
-												className="w-5 h-5"
-												fill="none"
-												stroke="currentColor"
-												viewBox="0 0 24 24"
-											>
-												<path
-													strokeLinecap="round"
-													strokeLinejoin="round"
-													strokeWidth={2}
-													d="M12 4v16m8-8H4"
-												/>
-											</svg>
-											Add to Playlist
-										</button>
-
-										<PlaylistDropdown
-											songId={song.id}
-											isOpen={showPlaylistDropdown}
-											onClose={() => setShowPlaylistDropdown(false)}
-											direction="below"
-										/>
-									</div>
-								</>
-							)}
-						</div>
-					</div>
-				</div>
-
-				{/* Credits / Contributions */}
-				{song.contributions.length > 0 && (
-					<section className="mb-10">
-						<h2 className="text-2xl font-bold mb-4">Credits</h2>
-						<div className="bg-[#1a1a2e]/60 rounded-xl p-5 divide-y divide-white/5">
-							{/* Main artist first */}
-							{song.contributions
-								.filter((c) => c.artistName === song.releasedBy)
-								.map((c, i) => (
-									<div
-										key={`main-${i}`}
-										className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
-									>
-										<div className="flex items-center gap-3">
-											<div className="w-10 h-10 bg-[#1db954] rounded-full flex items-center justify-center text-black font-bold text-sm">
-												{c.artistName.charAt(0).toUpperCase()}
-											</div>
-											<div>
-												<p className="text-white font-semibold text-lg">
-													{c.artistName}
-												</p>
-											</div>
-										</div>
-										<span className="text-sm text-gray-400 bg-white/5 px-3 py-1 rounded-full">
-											{formatRole(c.role)}
-										</span>
-									</div>
-								))}
-
-							{/* Other contributors */}
-							{otherContributors.map((c, i) => (
-								<div
-									key={`contrib-${i}`}
-									className="flex items-center justify-between py-3 first:pt-0 last:pb-0"
-								>
-									<div className="flex items-center gap-3">
-										<div className="w-9 h-9 bg-white/10 rounded-full flex items-center justify-center text-white font-medium text-sm">
-											{c.artistName.charAt(0).toUpperCase()}
-										</div>
-										<p className="text-gray-300 font-medium">{c.artistName}</p>
-									</div>
-									<span className="text-sm text-gray-500 bg-white/5 px-3 py-1 rounded-full">
-										{formatRole(c.role)}
-									</span>
-								</div>
-							))}
-						</div>
-					</section>
-				)}
-
-				{/* Reviews */}
-				<section>
-					<div className="flex items-center justify-between mb-4">
-						<h2 className="text-2xl font-bold">
-							Reviews
-							{song.reviews.length > 0 && (
-								<span className="text-base font-normal text-gray-500 ml-2">
-									({song.reviews.length})
-								</span>
-							)}
-						</h2>
-						{user != null && (
-							<button
-								onClick={() => setShowReviewModal(true)}
-								className="flex items-center gap-2 bg-[#1db954] hover:bg-[#1ed760] text-black text-sm font-semibold px-4 py-2 rounded-full transition-colors cursor-pointer"
-							>
-								<svg
-									className="w-4 h-4"
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={2}
-										d="M12 4v16m8-8H4"
-									/>
-								</svg>
-								Add Review
-							</button>
-						)}
-					</div>
-
-					{song.reviews.length === 0 ? (
-						<div className="bg-[#1a1a2e]/60 rounded-xl p-10 text-center">
-							<p className="text-gray-500 text-lg">No reviews yet.</p>
-							<p className="text-gray-600 text-sm mt-1">
-								Be the first to share your thoughts!
-							</p>
-						</div>
-					) : (
-						<div className="space-y-4">
-							{song.reviews.map((review) => (
-								<div
-									key={`${review.id.listenerId}-${review.id.musicalEntityId}`}
-									className="bg-[#1a1a2e]/60 rounded-xl p-5 hover:bg-[#1a1a2e]/80 transition-colors"
-								>
-									<div className="flex items-start justify-between mb-2">
-										<div className="flex items-center gap-3">
-											<div className="w-9 h-9 bg-blue-500/20 rounded-full flex items-center justify-center">
-												<span className="text-blue-400 font-semibold text-sm">
-													{review.author.charAt(0).toUpperCase()}
-												</span>
-											</div>
-											<div>
-												<p className="text-white font-medium">
-													{review.author}
-												</p>
-												{renderStars(review.grade)}
-											</div>
-										</div>
-										{user?.username === review.authorUsername && (
-											<button
-												onClick={deleteReview}
-												className="text-gray-500 hover:text-red-400 transition-colors p-2 rounded-lg hover:bg-red-400/10 cursor-pointer"
-												title="Delete review"
-											>
-												<svg
-													className="w-5 h-5"
-													fill="none"
-													stroke="currentColor"
-													viewBox="0 0 24 24"
-												>
-													<path
-														strokeLinecap="round"
-														strokeLinejoin="round"
-														strokeWidth={2}
-														d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
-													/>
-												</svg>
-											</button>
-										)}
-									</div>
-									<p className="text-gray-300 text-sm leading-relaxed mt-3 pl-12">
-										{review.comment}
-									</p>
-								</div>
-							))}
-						</div>
-					)}
-				</section>
-			</div>
-
-			{/* Review Modal */}
-			{showReviewModal && (
-				<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/70 backdrop-blur-sm">
-					<div className="bg-[#1a1a2e] rounded-2xl p-6 max-w-md w-full shadow-2xl">
-						<div className="flex items-center justify-between mb-6">
-							<h3 className="text-2xl font-bold">Add Review</h3>
-							<button
-								onClick={() => {
-									setShowReviewModal(false);
-									setReviewRating(0);
-									setReviewComment("");
-									setHoverRating(0);
-								}}
-								className="text-gray-400 hover:text-white transition-colors cursor-pointer"
-							>
-								<svg
-									className="w-6 h-6"
-									fill="none"
-									stroke="currentColor"
-									viewBox="0 0 24 24"
-								>
-									<path
-										strokeLinecap="round"
-										strokeLinejoin="round"
-										strokeWidth={2}
-										d="M6 18L18 6M6 6l12 12"
-									/>
-								</svg>
-							</button>
-						</div>
-
-						{/* Star Rating */}
-						<div className="mb-6">
-							<label className="block text-sm font-medium mb-3">
-								Rating <span className="text-red-400">*</span>
-							</label>
-							<div className="flex gap-2">
-								{[1, 2, 3, 4, 5].map((star) => (
-									<button
-										key={star}
-										onClick={() => setReviewRating(star)}
-										onMouseEnter={() => setHoverRating(star)}
-										onMouseLeave={() => setHoverRating(0)}
-										className="transition-transform hover:scale-110 cursor-pointer"
-									>
-										<svg
-											className={`w-10 h-10 ${
-												star <= (hoverRating || reviewRating)
-													? "text-yellow-400"
-													: "text-gray-600"
-											}`}
-											fill="currentColor"
-											viewBox="0 0 20 20"
-										>
-											<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
-										</svg>
-									</button>
-								))}
-							</div>
-						</div>
-
-						{/* Comment */}
-						<div className="mb-6">
-							<label className="block text-sm font-medium mb-2">
-								Comment <span className="text-gray-500">(optional)</span>
-							</label>
-							<textarea
-								value={reviewComment}
-								onChange={(e) => setReviewComment(e.target.value)}
-								placeholder="Share your thoughts about this song..."
-								rows={4}
-								className="w-full bg-[#0f0f1e] border border-white/10 rounded-lg px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] transition-colors resize-none"
-							/>
-						</div>
-
-						{/* Actions */}
-						<div className="flex gap-3 justify-end">
-							<button
-								onClick={() => {
-									setShowReviewModal(false);
-									setReviewRating(0);
-									setReviewComment("");
-									setHoverRating(0);
-								}}
-								className="px-5 py-2.5 rounded-full text-sm font-semibold bg-white/10 hover:bg-white/20 transition-colors cursor-pointer"
-							>
-								Cancel
-							</button>
-							<button
-								onClick={handleSubmitReview}
-								disabled={reviewRating === 0}
-								className="px-5 py-2.5 rounded-full text-sm font-semibold bg-[#1db954] hover:bg-[#1ed760] text-black transition-colors disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"
-							>
-								Submit
-							</button>
-						</div>
-					</div>
-				</div>
-			)}
-		</div>
-	);
-};
-
-export default SongDetail;
Index: ontend/src/pages/UserDetail.tsx
===================================================================
--- frontend/src/pages/UserDetail.tsx	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,339 +1,0 @@
-import { useEffect, useState } from "react";
-import { Link, useNavigate, useParams } from "react-router-dom";
-import axiosInstance, { baseURL } from "../api/axiosInstance";
-import LoadingSpinner from "../components/LoadingSpinner";
-import ArtistView from "../components/userProfile/ArtistView";
-import ListenerView from "../components/userProfile/ListenerView";
-import UserListModal from "../components/userProfile/UserListModal";
-import { useAuth } from "../context/authContext";
-import { getErrorMessage } from "../utils/error";
-import type {
-  ArtistContribution,
-  BaseNonAdminUser,
-  MusicalEntity,
-  Playlist,
-} from "../utils/types";
-
-interface FollowStatus {
-  isFollowing: boolean;
-  followerCount: number;
-  followingCount: number;
-}
-
-interface Artist extends BaseNonAdminUser {
-  userType: "ARTIST";
-  contributions: ArtistContribution[];
-}
-interface Listener extends BaseNonAdminUser {
-  userType: "LISTENER";
-  likedEntities: MusicalEntity[];
-  createdPlaylists: Playlist[];
-  savedPlaylists: Playlist[];
-}
-
-type UserProfile = Artist | Listener;
-
-const UserDetail = () => {
-  const { username: usernameParam } = useParams();
-  const { user: currentUser } = useAuth();
-
-  const navigate = useNavigate();
-  const [user, setUser] = useState<UserProfile | null>(null);
-  const [error, setError] = useState<string | null>(null);
-  const [showModal, setShowModal] = useState(false);
-  const [modalTitle, setModalTitle] = useState("");
-  const [modalUsers, setModalUsers] = useState<any[]>([]);
-  const [isLoadingModal, setIsLoadingModal] = useState(false);
-  const [isFollowing, setIsFollowing] = useState(false);
-
-  const username = usernameParam || currentUser?.username;
-  const isOwnProfile = currentUser?.username === username;
-
-  if (!usernameParam && !currentUser) {
-    return (
-      <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-        <div className="text-center">
-          <p className="text-red-400 text-xl mb-4">
-            You must be logged in to view your profile.
-          </p>
-          <button
-            onClick={() => navigate("/login")}
-            className="text-[#1db954] hover:underline text-sm cursor-pointer"
-          >
-            Go to Login
-          </button>
-        </div>
-      </div>
-    );
-  }
-
-  const handleFollow = async () => {
-    if (!user) return;
-
-    setIsFollowing(true);
-    try {
-      const response = await axiosInstance.post<FollowStatus>(
-        `/users/na/${username}/follow`,
-      );
-      setUser((prev) => {
-        if (!prev) return null;
-        return {
-          ...prev,
-          isFollowedByCurrentUser: response.data.isFollowing,
-          followers: response.data.followerCount,
-          following: response.data.followingCount,
-        };
-      });
-    } catch (err: any) {
-      setError(getErrorMessage(err));
-    } finally {
-      setIsFollowing(false);
-    }
-  };
-
-  const handleFollowInModal = async (targetUsername: string) => {
-    try {
-      const response = await axiosInstance.post<FollowStatus>(
-        `/users/na/${targetUsername}/follow`,
-      );
-
-      setModalUsers((prevUsers) =>
-        prevUsers.map((u) =>
-          u.username === targetUsername
-            ? { ...u, isFollowedByCurrentUser: response.data.isFollowing }
-            : u,
-        ),
-      );
-    } catch (err: any) {
-      setError(getErrorMessage(err));
-    }
-  };
-
-  const displayFollowers = async () => {
-    setIsLoadingModal(true);
-    try {
-      const response = await axiosInstance.get(
-        `/users/na/${username}/followers`,
-      );
-      setModalUsers(response.data);
-      setModalTitle("Followers");
-      setShowModal(true);
-    } catch (err) {
-      setError(getErrorMessage(err));
-    } finally {
-      setIsLoadingModal(false);
-    }
-  };
-  const displayFollowing = async () => {
-    setIsLoadingModal(true);
-    try {
-      const response = await axiosInstance.get(
-        `/users/na/${username}/following`,
-      );
-      setModalUsers(response.data);
-      setModalTitle("Following");
-      setShowModal(true);
-    } catch (err: any) {
-      setError(getErrorMessage(err));
-    } finally {
-      setIsLoadingModal(false);
-    }
-  };
-
-  useEffect(() => {
-    const fetchUser = async () => {
-      setError(null);
-      setUser(null);
-      try {
-        const response = await axiosInstance.get(`/users/na/${username}`);
-
-        setUser(response.data);
-      } catch (err: any) {
-        setError(getErrorMessage(err));
-      }
-    };
-    fetchUser();
-  }, [username]);
-
-  if (error) {
-    return (
-      <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] flex items-center justify-center">
-        <div className="text-center">
-          <p className="text-red-400 text-xl mb-4">{error}</p>
-          <Link to="/" className="text-[#1db954] hover:underline text-sm">
-            ← Back to Home
-          </Link>
-        </div>
-      </div>
-    );
-  }
-
-  if (!user) {
-    return <LoadingSpinner />;
-  }
-
-  return (
-    <div className="min-h-screen bg-linear-to-br from-[#1e1e2e] to-[#0f0f1e] text-white">
-      {isLoadingModal && (
-        <div className="fixed inset-0 z-40 bg-black/50 backdrop-blur-sm flex items-center justify-center">
-          <div className="w-10 h-10 border-4 border-white/10 border-t-[#1db954] rounded-full animate-spin" />
-        </div>
-      )}
-
-      <div className="max-w-5xl mx-auto px-6 py-10">
-        {/* Back link */}
-        <Link
-          to="/"
-          className="inline-flex items-center gap-1 text-gray-400 hover:text-white text-sm mb-8 transition-colors"
-        >
-          <svg
-            className="w-4 h-4"
-            fill="none"
-            stroke="currentColor"
-            viewBox="0 0 24 24"
-          >
-            <path
-              strokeLinecap="round"
-              strokeLinejoin="round"
-              strokeWidth={2}
-              d="M15 19l-7-7 7-7"
-            />
-          </svg>
-          Back to Home
-        </Link>
-
-        {/* Hero section */}
-        <div className="flex flex-col md:flex-row gap-8 mb-10">
-          {/* Profile photo */}
-          <div className="w-full md:w-48 shrink-0">
-            <div className="relative w-48 h-48 rounded-full overflow-hidden shadow-2xl bg-[#181818] mx-auto md:mx-0">
-              {user.profilePhoto ? (
-                <img
-                  src={`${baseURL}/${user.profilePhoto}`}
-                  alt={user.fullName}
-                  className="w-full h-full object-cover"
-                />
-              ) : (
-                <div className="w-full h-full bg-linear-to-br from-[#1db954] to-[#1ed760] flex items-center justify-center text-white text-5xl font-bold">
-                  {user.fullName.charAt(0).toUpperCase()}
-                </div>
-              )}
-            </div>
-          </div>
-
-          {/* User info */}
-          <div className="flex flex-col justify-end gap-3 min-w-0">
-            <span className="text-xs uppercase tracking-widest text-gray-400 font-medium">
-              {user.userType === "ARTIST" ? "Artist" : "Listener"} • Profile
-            </span>
-            <h1 className="text-4xl md:text-5xl font-extrabold leading-tight">
-              {user.fullName}
-            </h1>
-            <p className="text-gray-400">@{user.username}</p>
-
-            {/* Stats */}
-            <div className="flex items-center gap-6 mt-2">
-              <div
-                className={`${user.userType === "LISTENER" ? "cursor-pointer hover:text-white" : ""} transition-colors`}
-                onClick={
-                  user.userType === "LISTENER" ? displayFollowers : undefined
-                }
-              >
-                <span className="text-xl font-bold text-white">
-                  {user.followers}
-                </span>
-                <span className="text-sm text-gray-400 ml-1">Followers</span>
-              </div>
-              <div
-                className={`${user.userType === "LISTENER" ? "cursor-pointer hover:text-white" : ""} transition-colors`}
-                onClick={
-                  user.userType === "LISTENER" ? displayFollowing : undefined
-                }
-              >
-                <span className="text-xl font-bold text-white">
-                  {user.following}
-                </span>
-                <span className="text-sm text-gray-400 ml-1">Following</span>
-              </div>
-            </div>
-
-            {/* Follow button - hidden on own profile */}
-            {currentUser && !isOwnProfile && (
-              <div className="mt-4">
-                <button
-                  onClick={handleFollow}
-                  disabled={isFollowing}
-                  className={`flex items-center gap-2 px-6 py-3 rounded-full text-sm font-semibold transition-all cursor-pointer ${
-                    isFollowing
-                      ? "bg-gray-700 text-gray-400 cursor-not-allowed"
-                      : user.isFollowedByCurrentUser
-                        ? "bg-white/10 text-white hover:bg-white/20"
-                        : "bg-[#1db954] text-black hover:bg-[#1ed760] hover:scale-105"
-                  }`}
-                >
-                  {user.isFollowedByCurrentUser ? (
-                    <>
-                      <svg
-                        className="w-5 h-5"
-                        fill="none"
-                        stroke="currentColor"
-                        viewBox="0 0 24 24"
-                      >
-                        <path
-                          strokeLinecap="round"
-                          strokeLinejoin="round"
-                          strokeWidth={2}
-                          d="M5 13l4 4L19 7"
-                        />
-                      </svg>
-                      Following
-                    </>
-                  ) : (
-                    <>
-                      <svg
-                        className="w-5 h-5"
-                        fill="none"
-                        stroke="currentColor"
-                        viewBox="0 0 24 24"
-                      >
-                        <path
-                          strokeLinecap="round"
-                          strokeLinejoin="round"
-                          strokeWidth={2}
-                          d="M12 4v16m8-8H4"
-                        />
-                      </svg>
-                      Follow
-                    </>
-                  )}
-                </button>
-              </div>
-            )}
-          </div>
-        </div>
-
-        {/* Content */}
-        {user.userType === "ARTIST" ? (
-          <ArtistView contributions={user.contributions} />
-        ) : (
-          <ListenerView
-            likedEntities={user.likedEntities}
-            createdPlaylists={user.createdPlaylists}
-            savedPlaylists={user.savedPlaylists}
-          />
-        )}
-
-        {showModal && (
-          <UserListModal
-            title={modalTitle}
-            users={modalUsers}
-            onClose={() => setShowModal(false)}
-            onFollowToggle={handleFollowInModal}
-          />
-        )}
-      </div>
-    </div>
-  );
-};
-
-export default UserDetail;
Index: ontend/src/utils/consts.ts
===================================================================
--- frontend/src/utils/consts.ts	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,34 +1,0 @@
-export const ROLE_OPTIONS = [
-	{ value: "FEATURED", label: "Featured" },
-	{ value: "PRODUCER", label: "Producer" },
-	{ value: "SONGWRITER", label: "Songwriter" },
-	{ value: "COMPOSER", label: "Composer" },
-	{ value: "MIXER", label: "Mixer" },
-	{ value: "ENGINEER", label: "Engineer" },
-];
-
-export const GENRE_OPTIONS = [
-	"Pop",
-	"Rock",
-	"Hip-Hop",
-	"R&B",
-	"Electronic",
-	"Jazz",
-	"Classical",
-	"Country",
-	"Folk",
-	"Latin",
-	"Metal",
-	"Punk",
-	"Indie",
-	"Alternative",
-	"Blues",
-	"Soul",
-	"Reggae",
-	"Funk",
-	"Disco",
-	"House",
-	"Techno",
-	"Ambient",
-	"Other",
-];
Index: ontend/src/utils/error.ts
===================================================================
--- frontend/src/utils/error.ts	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,4 +1,0 @@
-export const getErrorMessage = (err: any) => {
-  const errorMessage = err.response?.data?.error || "Failed to fetch user";
-  return errorMessage;
-};
Index: ontend/src/utils/types.ts
===================================================================
--- frontend/src/utils/types.ts	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,147 +1,0 @@
-export interface User {
-  username: string;
-  fullName: string;
-  email?: string;
-  profilePhoto?: string | null;
-  isAdmin: boolean;
-  isArtist: boolean;
-}
-
-export interface ArtistContribution {
-  id: number;
-  title: string;
-  genre: string;
-  role: string;
-  entityType: string;
-  isLikedByCurrentUser: boolean;
-  cover?: string | null;
-  link?: string | null;
-}
-
-export interface MusicalEntity {
-  id: number;
-  title: string;
-  genre: string;
-  type: string;
-  releasedBy: string;
-  artistUsername?: string;
-  cover?: string | null;
-  isLikedByCurrentUser?: boolean;
-}
-
-export interface Song extends MusicalEntity {
-  type: "SONG";
-  album?: string;
-  albumId?: number;
-  link?: string;
-}
-
-export interface Album extends MusicalEntity {
-  type: "ALBUM";
-  songs: Song[];
-}
-
-export interface Playlist {
-  id: number;
-  name: string;
-  cover: string;
-  creatorName: string;
-  creatorUsername: string;
-  songsInPlaylist: Song[];
-  isSavedByCurrentUser: boolean;
-}
-
-export interface BaseNonAdminUser {
-  username: string;
-  fullName: string;
-  userType: string;
-  profilePhoto: string;
-  followers: number;
-  following: number;
-  isFollowedByCurrentUser: boolean;
-}
-
-export type UserRegisterType = "ARTIST" | "LISTENER";
-
-export type SearchCategory = "songs" | "albums" | "artists" | "users";
-
-export interface SidebarProps {
-  isOpen: boolean;
-  onClose: () => void;
-}
-
-export interface CreatePlaylistModalProps {
-  isOpen: boolean;
-  onClose: () => void;
-  onSuccess: () => void | Promise<void>;
-  songId?: number | null;
-}
-
-export interface SongContribution {
-  artistName: string;
-  role: string;
-}
-
-export interface SongReview {
-  id: {
-    listenerId: number;
-    musicalEntityId: number;
-  };
-  author: string;
-  authorUsername: string;
-  grade: number;
-  comment: string;
-}
-
-export interface SongDetail extends MusicalEntity {
-  type: "SONG";
-  album?: string | null;
-  link?: string | null;
-  contributions: SongContribution[];
-  reviews: SongReview[];
-}
-
-export interface BasicSong {
-  id: number;
-  title: string;
-  artist: string;
-  artistUsername?: string;
-  cover?: string;
-  link?: string;
-  album?: string;
-  albumId?: number;
-}
-
-export interface BasicPlaylist {
-  id: number;
-  name: string;
-  songCount: number;
-}
-
-export interface CatalogItem {
-  id: number;
-  title: string;
-  genre: string;
-  cover: string | null;
-  type: "SONG" | "ALBUM";
-  releaseDate: string;
-}
-
-export interface Contributor {
-  id: number;
-  fullName: string;
-  role: string;
-}
-
-export interface ArtistSearchResult {
-  id: number;
-  username: string;
-  fullName: string;
-  profilePhoto?: string;
-}
-
-export interface SongEntry {
-  title: string;
-  link: string;
-  contributors: Contributor[];
-}
Index: ontend/src/utils/utils.ts
===================================================================
--- frontend/src/utils/utils.ts	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,21 +1,0 @@
-export const toEmbedUrl = (url: string): string => {
-	try {
-		const parsed = new URL(url);
-		// youtube.com/watch?v=ID
-		if (
-			(parsed.hostname === "www.youtube.com" ||
-				parsed.hostname === "youtube.com") &&
-			parsed.searchParams.has("v")
-		) {
-			return `https://www.youtube.com/embed/${parsed.searchParams.get("v")}`;
-		}
-		// youtu.be/ID
-		if (parsed.hostname === "youtu.be") {
-			return `https://www.youtube.com/embed${parsed.pathname}`;
-		}
-		// already an embed URL or other provider – return as-is
-		return url;
-	} catch {
-		return url;
-	}
-};
Index: ripts/ddl.sql
===================================================================
--- scripts/ddl.sql	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,161 +1,0 @@
-drop schema if exists project cascade;
-
-create schema project;
-
-SET search_path TO project;
-
-DROP TABLE IF EXISTS ARTIST_CONTRIBUTIONS;
-DROP TABLE IF EXISTS PLAYLIST_SONGS;
-DROP TABLE IF EXISTS SAVED_PLAYLISTS;
-DROP TABLE IF EXISTS REVIEWS;
-DROP TABLE IF EXISTS LISTENS;
-DROP TABLE IF EXISTS LIKES;
-DROP TABLE IF EXISTS PERFORMS_AT;
-DROP TABLE IF EXISTS FOLLOWS;
-DROP TABLE IF EXISTS PLAYLISTS;
-DROP TABLE IF EXISTS EVENTS;
-DROP TABLE IF EXISTS SONGS;
-DROP TABLE IF EXISTS ALBUMS;
-DROP TABLE IF EXISTS MUSICAL_ENTITIES;
-DROP TABLE IF EXISTS ARTISTS;
-DROP TABLE IF EXISTS LISTENERS;
-DROP TABLE IF EXISTS ADMINS;
-DROP TABLE IF EXISTS NON_ADMIN_USERS;
-DROP TABLE IF EXISTS USERS;
-
-
-CREATE TABLE USERS (
-    user_id BIGINT PRIMARY KEY,
-    full_name TEXT NOT NULL, 
-    email TEXT NOT NULL,
-    password TEXT NOT NULL,
-    username TEXT NOT NULL, 
-    profile_photo TEXT
-);
-
-CREATE TABLE NON_ADMIN_USERS (
-    user_id BIGINT PRIMARY KEY REFERENCES USERS(user_id) ON DELETE CASCADE
-);
-
-CREATE TABLE ADMINS (
-    user_id BIGINT PRIMARY KEY REFERENCES USERS(user_id) ON DELETE CASCADE
-);
-
-CREATE TABLE LISTENERS (
-    user_id BIGINT PRIMARY KEY REFERENCES NON_ADMIN_USERS(user_id) ON DELETE CASCADE
-);
-
-CREATE TABLE ARTISTS (
-    user_id BIGINT PRIMARY KEY REFERENCES NON_ADMIN_USERS(user_id) ON DELETE CASCADE
-);
-
-CREATE TABLE MUSICAL_ENTITIES (
-    id BIGINT PRIMARY KEY,
-    title TEXT NOT NULL,
-    genre TEXT NOT NULL,
-    release_date  DATE NOT NULL,
-    released_by BIGINT REFERENCES ARTISTS(user_id) ON DELETE CASCADE
-);
-
-
-CREATE TABLE ALBUMS (
-    id BIGINT PRIMARY KEY REFERENCES MUSICAL_ENTITIES(id) ON DELETE CASCADE
-);
-
-CREATE TABLE SONGS (
-    id BIGINT PRIMARY KEY REFERENCES MUSICAL_ENTITIES(id) ON DELETE CASCADE,
-    album_id BIGINT REFERENCES ALBUMS(id) ON DELETE CASCADE,
-    link TEXT NOT NULL
-);
-
-
-CREATE TABLE EVENTS (
-    event_id BIGINT PRIMARY KEY,
-    name TEXT NOT NULL,
-    location TEXT NOT NULL,
-    venue  TEXT NOT NULL,
-    date DATE NOT NULL,
-    time TIME NOT NULL,
-    creator_id BIGINT REFERENCES USERS(user_id) ON DELETE CASCADE
-);
-
-CREATE TABLE PLAYLISTS (
-    playlist_id  BIGINT PRIMARY KEY,
-    cover  TEXT,
-    name   TEXT NOT NULL,
-    created_by BIGINT REFERENCES LISTENERS(user_id) ON DELETE CASCADE
-);
-
--- RELACII
-
-
-CREATE TABLE FOLLOWS (
-    follower BIGINT REFERENCES NON_ADMIN_USERS(user_id) ON DELETE CASCADE,
-    followee BIGINT REFERENCES NON_ADMIN_USERS(user_id) ON DELETE CASCADE,
-
-    CONSTRAINT follows_no_self_follow
-        CHECK (follower <> followee),
-
-    CONSTRAINT follows_pk
-        PRIMARY KEY (follower, followee)
-);
-
-CREATE TABLE PERFORMS_AT (
-    event_id BIGINT REFERENCES EVENTS(event_id) ON DELETE CASCADE,
-    artist_id BIGINT REFERENCES ARTISTS(user_id) ON DELETE CASCADE,
-
-    CONSTRAINT performs_at_pk
-        PRIMARY KEY (event_id, artist_id)
-);
-
-CREATE TABLE LIKES (
-    listener_id BIGINT REFERENCES LISTENERS(user_id) ON DELETE CASCADE,
-    musical_entity_id BIGINT REFERENCES MUSICAL_ENTITIES(id) ON DELETE CASCADE,
-
-    CONSTRAINT likes_pk
-        PRIMARY KEY (listener_id, musical_entity_id)
-);
-
-CREATE TABLE LISTENS (
-    listener_id BIGINT REFERENCES LISTENERS(user_id) ON DELETE CASCADE,
-    song_id BIGINT REFERENCES SONGS(id) ON DELETE CASCADE,
-    timestamp TIMESTAMP NOT NULL,
-
-    CONSTRAINT listens_to_pk
-        PRIMARY KEY (listener_id, song_id, timestamp)
-);
-
-CREATE TABLE REVIEWS (
-    listener_id BIGINT REFERENCES LISTENERS(user_id) ON DELETE CASCADE,
-    musical_entity_id BIGINT REFERENCES MUSICAL_ENTITIES(id) ON DELETE CASCADE,
-    grade INT CHECK ( grade between 1 and 5) NOT NULL,
-    comment TEXT,
-
-    CONSTRAINT reviews_pk
-        PRIMARY KEY (listener_id, musical_entity_id)
-);
-
-CREATE TABLE SAVED_PLAYLISTS (
-    listener_id BIGINT REFERENCES LISTENERS(user_id) ON DELETE CASCADE,
-    playlist_id BIGINT REFERENCES PLAYLISTS(playlist_id) ON DELETE CASCADE,
-
-    CONSTRAINT saved_playlists_id
-        PRIMARY KEY (listener_id, playlist_id)
-);
-
-CREATE TABLE PLAYLIST_SONGS (
-    song_id BIGINT REFERENCES SONGS(id) ON DELETE CASCADE,
-    playlist_id BIGINT REFERENCES PLAYLISTS(playlist_id) ON DELETE CASCADE,
-
-    CONSTRAINT playlist_songs_id
-        PRIMARY KEY (song_id, playlist_id)
-);
-
-CREATE TABLE ARTIST_CONTRIBUTIONS (
-    artist_id BIGINT REFERENCES ARTISTS(user_id) ON DELETE CASCADE,
-    musical_entity_id BIGINT REFERENCES MUSICAL_ENTITIES(id) ON DELETE CASCADE,
-    role TEXT NOT NULL,
-
-    CONSTRAINT artist_contribution_id
-        PRIMARY KEY (artist_id, musical_entity_id)
-);
Index: ripts/dml.sql
===================================================================
--- scripts/dml.sql	(revision 947fcaadc3ddb75ae7bee1ae398ae0f43c988c1e)
+++ 	(revision )
@@ -1,150 +1,0 @@
-SET search_path TO project;
-
-INSERT INTO USERS (user_id, full_name, email, password, username, profile_photo) VALUES 
-(1, 'Dimitar Arsov', 'dimitararsov04@gmail.com', '$2a$10$Vl6VE03lIQmGL/dW2/Ly9emzc7upycbosyjBKjIY93TbN5b1rB1Ry', 'dimitar_arsov2', null),
-(2, 'Filip Gavrilovski', 'filipgavrilovski28@gmail.com','$2a$10$oxZZfDwH9ixVdLjnaopmJufBqQpcgPp9e/Bv8aN1Kp/r.EyLIfyoi', 'filip_gavrilovski1', null),
-(3, 'Marko Markovski', 'foo@bar.com', '$2a$10$V4ZA8Ka/iBbAM2EWBvJrwu063oqQqACafkQo9tN5Pc1RVJCJpGMH2', 'marko_markovski4', null),
-(4, 'Admin Adminovski', 'admin@gmail.com','$2a$10$f5eGW5DuTB82ldmke2/64uY8LSmim.2s7k3HgTRy8CNrhtbz/pEDG', 'admin', null),
-(5, 'John Doe', 'john@doe.com','$2a$10$VJg6/xNL1yQa1LNxY3SEp.0XOnbLEbT49fzsbfFk7jjfUUaQmsWpO', 'john_doe4', null),
-(6, 'Jane Doe', 'jane@doe.com','$2a$10$hxet6V8ByjTp1x4PINeCAu6rgSUqVsH7DnLHIl95ZH7UHtt5LwqGq', 'jane_doe7', null),
-(7, 'Strajk', 'str2@gmail.com','$2a$10$V/AmUSd4BsNxdIEcRrbRwOwGTBAowVebd.0WFs.tFRJ3iibT8lkVy', 'strajk5', null),
-(8, 'Kanye West', 'kanyewest@gmail.com', '$2a$10$LEY96RM.EwMf5v1b71MYy.abZLZOp4qRxQvN5ai8u5df.es3rpL3G', 'kanye_west0', null),
-(9, 'The Weeknd','weekend@yahoo.com', '$2a$10$DCKcZzfU0BN56cNPSVB8o.v6vyVNMxqXhF68c1MOr7uFY7JztWD1S', 'the_weeknd7', null),
-(10, 'Bruno Mars','brunomars@gmail.com', '$2a$10$lAPmxkmcK3gslPnC5FqKa.y55jShUa8n7FWgl04T1BqcsDnz.meRa', 'bruno_mars8', null),
-(11, 'Rihanna','rihanna@gmail.com', '$2a$10$c8uq89om6kdFbu1OCIZeveohCrZSd/NIuQc2LnYBd6cwifbmVrI92', 'rihanna_x1', null),
-(12, 'Verica Ristevska','vericaristevska@hotmail.com', '$2a$10$n3WJVg0ZUv6ikWc4HYvTNehTKTO2QMzk3FT7/fxZ3PKTFvAyE84Gm', 'verica_ristevska6', null),
-(13, 'LD Pistolero','ld@gmail.com', '$2a$10$EFAB9K.HseHZEepT0SHfR.N5B7Y.V5GOJzcChyQ54mqB9Fv64P7Ae', 'ld_pistolero1', null),
-(14, 'Andrej Ristikj','aristikj@gmail.com', '$2a$10$4TCCv4ZGTpuuveydB5bZ2evlwsNQul9PqQe0zZIT6pblpLSxirRJC', 'andrej_ristikj1', null),
-(15, 'Petar Mitrevski','pmfitness@gmail.com' ,'$2a$10$DKDhmeCKJ99aDjs05uiXvuJp8Nt0o4/m4Bj783Aid6IcOSAUl38S.', 'petar_mitrevski1', null),
-(16, 'Stefan Filipovski','steffilipovski@gmail.com', '$2a$10$uR4bOEMyrLzMXm067qI.8uwbkDcojxWkt7TqkJo8iv.X4nExtKZ7C', 'stefan_filipovski6', null),
-(17, 'Ema Arsova','arsovaema@yahoo.com', '$2a$10$HcNcruV3RzGGPs5r/XSM0uWiu9nDVFMkXY/FKMtTH2WOY1DmHUWou', 'ema_arsova0', null);
-
-INSERT INTO NON_ADMIN_USERS(user_id) VALUES 
-(1),(2),(3),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17);
-
-INSERT INTO ADMINS(user_id) VALUES (4);
-
-INSERT INTO LISTENERS(user_id) VALUES
-(1),(2),(3),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17);
-
-INSERT INTO ARTISTS(user_id) VALUES
-(7),(8),(9),(10),(11),(12),(13);
-
-INSERT INTO MUSICAL_ENTITIES (id, title, genre, release_date, released_by)
-VALUES
-(1, 'Stronger', 'Hip Hop', '2007-07-31', 8),
-(2, 'Heartless', 'Hip Hop', '2008-11-04',8),
-(3, 'Runaway', 'Hip Hop', '2010-10-04', 8),
-(4, 'Graduation', 'Hip Hop', '2007-09-11', 8),
-(5, 'My Beautiful Dark Twisted Fantasy', 'Hip Hop', '2010-11-22', 8),
-(6, 'Blinding Lights', 'R&B', '2019-11-29', 9),
-(7, 'Starboy', 'R&B', '2016-09-22', 9),
-(8, 'The Hills', 'R&B', '2015-05-27', 9),
-(9, 'After Hours', 'R&B', '2020-03-20', 9),
-(10, 'Dawn FM', 'R&B', '2022-01-07', 9),
-(11, 'Strit Poetiks', 'Rap', '2015-02-12', 7),
-(12, 'Ushte Ednash', 'Rap', '2019-05-17', 7),
-(13, 'Muzej 2', 'Rap', '2025-12-13', 7),
-(14, 'Niz Mojot Zhivot', 'Rap', '2019-10-31', 7),
-(15, 'Kutija', 'Rap', '2011-07-26', 7),
-(16, 'Ti si pesna shto kje trae', 'Pop', '1978-01-01', 12),
-(17, 'Galebe moj tazhen', 'Pop', '1978-01-01', 12),
-(18, 'Just the Way You Are', 'Pop', '2010-07-20', 10),
-(19, 'Grenade', 'Pop', '2010-09-28', 10),
-(20, '24K Magic', 'Pop', '2016-11-18', 10),
-(21, '24K Magic', 'Pop', '2016-11-18', 10);
-
-
-INSERT INTO ALBUMS (id) VALUES
-(4),(5),(9),(10),(14),(15),(20);
-
-
-INSERT INTO SONGS (id, album_id, link)
-VALUES
-(1, 4, 'https://www.youtube.com/watch?v=PsO6ZnUZI0g'),
-(2, 5, 'https://www.youtube.com/watch?v=Co0tTeuUVhU'),
-(3, 5, 'https://www.youtube.com/watch?v=Bm5iA4Zupek'),
-(6, 9, 'https://www.youtube.com/watch?v=4NRXx6U8ABQ'),
-(7, 9, 'https://www.youtube.com/watch?v=34Na4j8AVgA'),
-(8, 9, 'https://www.youtube.com/watch?v=yzTuBuRdAyA'),
-(11, NULL, 'https://www.youtube.com/watch?v=EOknxkb12lw'),
-(12, 14, 'https://www.youtube.com/watch?v=nXQbVZ4_9tQ'),
-(13, NULL, 'https://www.youtube.com/watch?v=zrB9H1TZsCU'),
-(16, NULL, 'https://www.youtube.com/watch?v=DNWtp6lpLRo'),
-(17, NULL, 'https://www.youtube.com/watch?v=QGOAhymaa3o'),
-(18, 20, 'https://www.youtube.com/watch?v=LjhCEhWiKXk'),
-(19, 20, 'https://www.youtube.com/watch?v=SR6iYWJxHqs'),
-(21, 20, 'https://www.youtube.com/watch?v=UqyT8IEBkvY');
-
-
-INSERT INTO EVENTS
-(event_id, name, location, venue, date, time, creator_id) VALUES
-(1, 'HipHop - Revolution','Skopje, Macedonia', 'SC Boris Trajkovski', '2026-02-02','21:00:00', 4),
-(2,'Event1!', 'Skopje, Macedonia', 'SC Jane Sandanski', '2026-01-30','19:00:00', 4),
-(3, 'Fiesta','Barcelona, Spain', 'Stadium Camp Nou', '2026-06-06','22:00:00', 4),
-(4, 'NYC-BreakDance','New York City, NY, United States', 'Madison Square Garden','2026-03-03','17:00:00', 4);
-
-
-INSERT INTO PLAYLISTS (playlist_id, cover, name, created_by) VALUES 
-(1, null, 'dimis-playlist', 1),
-(2, null, 'za vo kola', 15),
-(3, null, 'playlist1', 2);
-
-
-INSERT INTO FOLLOWS (follower, followee) VALUES
-(1,2), (2,1), (2,8), (1,7), (15,7), (1,17), (3,1), (17,1), (16,1), (1,14), (2,14);
-
-INSERT INTO PERFORMS_AT (event_id, artist_id) VALUES
-(1,8), (2,13), (2,7), (3,9), (4,10);
-
-INSERT INTO LIKES (listener_id, musical_entity_id) VALUES 
-(1, 13), (1, 14), (1,7), (2, 4), (15, 16), (15,17), (14, 15), (15, 12), (15,11); 
-
-INSERT INTO LISTENS (listener_id, song_id, timestamp) VALUES
-(2, 12,'2026-02-19 16:23:54+02'),
-(1, 13,'2025-12-19 11:13:54+02'),
-(13, 12,'2025-11-09 15:23:54+02'),
-(14, 13,'2025-01-16 23:23:54+02'),
-(2, 12,'2025-10-23 10:23:54+02'),
-(15, 16,'2025-11-23 19:23:54+02'),
-(9, 16,'2025-11-27 13:28:54+02'),
-(13, 19,'2025-11-30 10:10:54+02'),
-(7, 21,'2025-12-06 21:23:54+02'),
-(14, 23,'2025-12-09 23:23:54+02'),
-(15, 13,'2025-12-30 21:23:54+02'),
-(16, 17,'2025-12-28 19:23:54+02'),
-(10, 17,'2026-01-20 10:40:54+02'),
-(13, 12,'2026-01-01 10:21:54+02'),
-(7, 18,'2026-01-02 10:26:54+02'),
-(8, 16,'2026-01-05 18:23:54+02'),
-(8, 17,'2026-01-13 10:23:56+02'),
-(8, 18,'2026-01-05 11:23:54+02'),
-(2, 18,'2025-12-18 10:34:54+02'),
-(2, 12,'2026-02-19 16:23:54+02'),
-(1, 13,'2025-12-19 11:13:54+02');
-
-
-INSERT INTO REVIEWS (listener_id, musical_entity_id, grade, comment) VALUES
-(1, 13, 5, 'Najdobra pesna sto postoi!!! Strajk is back!!!!'),
-(2, 1, 5, 'i love the old kanye, bring him back...'),
-(2, 6, 3, null),
-(15, 16, 5, 'ne se pravi veke vakva muzika'),
-(15, 18, 2, null),
-(14, 12, 4, 'dobra pesna ama drugiot album bese podobar');
-
-
-INSERT INTO SAVED_PLAYLISTS (listener_id, playlist_id) VALUES
-(2,1), (1,3), (2,2), (1,2), (17,3), (16,3);
-
-INSERT INTO PLAYLIST_SONGS (song_id, playlist_id) VALUES
-(1,1), (16,1), (17,1), (11,1), (3,1), (8,1), (6,1),
-(11,2), (13,2), (16,2);
-
-INSERT INTO  ARTIST_CONTRIBUTIONS (musical_entity_id, artist_id, role) VALUES
-(1,8,'MAIN_VOCAL'), (2,8,'MAIN_VOCAL'),(3,8,'MAIN_VOCAL'),
-(4,8,'MAIN_VOCAL'),(5,8,'MAIN_VOCAL'),(6,9,'MAIN_VOCAL'),
-(7,9,'MAIN_VOCAL'),(8,9,'MAIN_VOCAL'),(9,9,'MAIN_VOCAL'),
-(10,9,'MAIN_VOCAL'),(11,7,'MAIN_VOCAL'),(12,7,'MAIN_VOCAL'),
-(13,7,'MAIN_VOCAL'),(14,7,'MAIN_VOCAL'),(15,7,'MAIN_VOCAL'),
-(16,12,'MAIN_VOCAL'),(17,12,'MAIN_VOCAL'),(18,10,'MAIN_VOCAL'),
-(19,10,'MAIN_VOCAL'),(20,10,'MAIN_VOCAL'),(21,10,'MAIN_VOCAL');
