From e5d65f082915a85c4592f8948c37342e8980edce Mon Sep 17 00:00:00 2001 From: SDI Date: Tue, 3 Mar 2026 16:26:10 +0900 Subject: [PATCH] =?UTF-8?q?DB=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=B0=8F=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95(20260303)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/mysql/initdb/init.sql | 605 ++++++++++++++++++++++++++++++++++- src/css/common.css | 369 ++++++++++++++------- src/css/intro.css | 177 +++++++--- src/js/puzzle-onboarding.js | 17 +- src/skin/_include/_head.php | 2 +- 5 files changed, 990 insertions(+), 180 deletions(-) diff --git a/docker/mysql/initdb/init.sql b/docker/mysql/initdb/init.sql index 26d202d..944c031 100644 --- a/docker/mysql/initdb/init.sql +++ b/docker/mysql/initdb/init.sql @@ -1,12 +1,595 @@ --- 팀원들이 공통으로 사용할 초기 테이블 구조 생성 -CREATE TABLE IF NOT EXISTS users ( - id INT AUTO_INCREMENT PRIMARY KEY, - username VARCHAR(50) NOT NULL, - email VARCHAR(100) NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); +-- 컨텐츠 등록 +CREATE TABLE `edu`.`contents` ( + `content_id` VARCHAR(20) NOT NULL COMMENT '콘텐츠ID', -- 콘텐츠ID + `category_code` VARCHAR(20) NULL COMMENT '카테고리', -- 카테고리 + `category_group` VARCHAR(20) NULL COMMENT '케테고리구분', -- 케테고리구분 + `title` VARCHAR(200) NULL COMMENT '콘텐츠명', -- 콘텐츠명 + `description` TEXT NULL COMMENT '콘텐츠설명', -- 콘텐츠설명 + `description2` TEXT NULL COMMENT '콘텐츠설명2', -- 콘텐츠설명2 + `content_url` VARCHAR(200) NULL COMMENT '콘텐츠url', -- 콘텐츠url + `thumbnail_url` VARCHAR(200) NULL COMMENT '썸네일url', -- 썸네일url + `base_year` CHAR(4) NULL COMMENT '기준년도', -- 기준년도 + `start_date` DATE NULL COMMENT '기준일자', -- 기준일자 + `end_date` DATE NULL COMMENT '종료일자', -- 종료일자 + `sort_order` INTEGER NULL COMMENT '정렬순번', -- 정렬순번 + `goal_code` VARCHAR(20) NULL COMMENT '학습목표코드', -- 학습목표코드 + `image_name` VARCHAR(200) NULL COMMENT '대표이미지명', -- 대표이미지명 + `image_path` VARCHAR(200) NULL COMMENT '이미지경로', -- 이미지경로 + `is_offer` CHAR(1) NULL COMMENT '추천콘텐츠적용여부', -- 추천콘텐츠적용여부 + `offer_id` VARCHAR(20) NULL COMMENT '제안ID', -- 제안ID + `issue_type_code` VARCHAR(20) NULL COMMENT '인사이트이슈구분', -- 인사이트이슈구분 + `is_active` CHAR(1) NULL COMMENT '사용여부', -- 사용여부 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '컨텐츠 등록'; --- 초기 테스트를 위한 더미 데이터 삽입 (선택 사항) -INSERT INTO users (username, email) VALUES -('test_user_1', 'user1@hmac-edu.com'), -('test_user_2', 'user2@hmac-edu.com'); \ No newline at end of file +-- 컨텐츠 등록 +ALTER TABLE `edu`.`contents` + ADD CONSTRAINT `PK_contents` -- 컨텐츠 등록 기본키 + PRIMARY KEY ( + `content_id` -- 콘텐츠ID + ); + +-- 마이클래스 학습목표 등록 +CREATE TABLE `edu`.`learning_goals` ( + `goal_code` VARCHAR(20) NOT NULL COMMENT '학습목표 코드', -- 학습목표 코드 + `title` VARCHAR(200) NULL COMMENT '학습목표제목', -- 학습목표제목 + `base_year` CHAR(4) NULL COMMENT '기준년도', -- 기준년도 + `end_date` DATE NULL COMMENT '종료일', -- 종료일 + `is_active` CHAR(1) NULL COMMENT '사용여부', -- 사용여부 + `sort_order` INTEGER NULL COMMENT '정렬순번', -- 정렬순번 + `remarks` VARCHAR(200) NULL COMMENT '비고', -- 비고 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '마이클래스 학습목표 등록'; + +-- 마이클래스 학습목표 등록 +ALTER TABLE `edu`.`learning_goals` + ADD CONSTRAINT `PK_learning_goals` -- 마이클래스 학습목표 등록 기본키 + PRIMARY KEY ( + `goal_code` -- 학습목표 코드 + ); + +-- 코드상세 +CREATE TABLE `edu`.`codes` ( + `group_code` VARCHAR(10) NOT NULL COMMENT '메인코드', -- 메인코드 + `code` VARCHAR(10) NOT NULL COMMENT '서브코드', -- 서브코드 + `base_code` VARCHAR(20) NOT NULL COMMENT '기준코드', -- 기준코드 + `code_name` VARCHAR(250) NULL COMMENT '코드명', -- 코드명 + `is_active` CHAR(1) NULL COMMENT '사용구분', -- 사용구분 + `desc01` VARCHAR(250) NULL COMMENT '설명1', -- 설명1 + `desc02` VARCHAR(250) NULL COMMENT '설명2', -- 설명2 + `desc03` VARCHAR(250) NULL COMMENT '설명3', -- 설명3 + `desc04` VARCHAR(250) NULL COMMENT '설명4', -- 설명4 + `desc05` VARCHAR(250) NULL COMMENT '설명5', -- 설명5 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '코드상세'; + +-- 코드상세 +ALTER TABLE `edu`.`codes` + ADD CONSTRAINT `PK_codes` -- 코드상세 기본키 + PRIMARY KEY ( + `group_code`, -- 메인코드 + `code` -- 서브코드 + ); + +-- 통합인사정보 +CREATE TABLE `edu`.`users` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `name` VARCHAR(100) NULL COMMENT '성명', -- 성명 + `dept_name` VARCHAR(100) NULL COMMENT '부서', -- 부서 + `rank_name` VARCHAR(100) NULL COMMENT '직위', -- 직위 + `join_date` DATE NULL COMMENT '입사일', -- 입사일 + `belong_comp` VARCHAR(100) NULL COMMENT '소속회사', -- 소속회사 + `working_cpmp` VARCHAR(100) NULL COMMENT '근무회사', -- 근무회사 + `intra_pw` VARCHAR(20) NULL COMMENT 'password' -- password +) +COMMENT '통합인사정보'; + +-- 통합인사정보 +ALTER TABLE `edu`.`users` + ADD CONSTRAINT `PK_users` -- 통합인사정보 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 댓글정보 +CREATE TABLE `edu`.`comments` ( + `id` VARCHAR(12) NOT NULL COMMENT '댓글ID', -- 댓글ID + `parent_id` VARCHAR(12) NULL COMMENT '상위댓글ID', -- 상위댓글ID + `sys_comp_code` VARCHAR(20) NULL COMMENT '기준법인', -- 기준법인 + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `comment` VARCHAR(255) NULL COMMENT '내용', -- 내용 + `content_id` INTEGER NULL COMMENT '콘텐츠ID', -- 콘텐츠ID + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '댓글정보'; + +-- 댓글정보 +ALTER TABLE `edu`.`comments` + ADD CONSTRAINT `PK_comments` -- 댓글정보 기본키 + PRIMARY KEY ( + `id` -- 댓글ID + ); + +-- 학습이력 +CREATE TABLE `edu`.`learning_histories` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `content_id` VARCHAR(20) NOT NULL COMMENT '콘텐츠ID', -- 콘텐츠ID + `first_viewed_at` DATETIME NULL COMMENT '최초시청일시', -- 최초시청일시 + `last_viewed_at` DATETIME NULL COMMENT '최종시청일시', -- 최종시청일시 + `watch_tm` DECIMAL(18) NULL COMMENT '영상시작길이', -- 영상시작길이 + `content_tm` DECIMAL(18) NULL COMMENT '영상길이', -- 영상길이 + `all_tm` DECIMAL(18) NULL COMMENT '누적시청시간', -- 누적시청시간 + `completed_at` DATETIME NULL COMMENT '학습완료일시', -- 학습완료일시 + `comment` VARCHAR(200) NULL COMMENT '한줄소감', -- 한줄소감 + `is_watching` CHAR(1) NULL COMMENT '시청중컨텐츠여부' -- 시청중컨텐츠여부 +) +COMMENT '학습이력'; + +-- 학습이력 +ALTER TABLE `edu`.`learning_histories` + ADD CONSTRAINT `PK_learning_histories` -- 학습이력 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `content_id` -- 콘텐츠ID + ); + +-- 컨텐츠저장 +CREATE TABLE `edu`.`content_wishlist` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `content_id` INTEGER NOT NULL COMMENT '콘텐츠ID', -- 콘텐츠ID + `favorited_at` DATETIME NULL COMMENT '찜한일시', -- 찜한일시 + `is_active` CHAR(1) NULL COMMENT '사용여부', -- 사용여부 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '컨텐츠저장'; + +-- 컨텐츠저장 +ALTER TABLE `edu`.`content_wishlist` + ADD CONSTRAINT `PK_content_wishlist` -- 컨텐츠저장 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `content_id` -- 콘텐츠ID + ); + +-- 사용자 키워드 +CREATE TABLE `edu`.`user_keywords` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `keyword_code` VARCHAR(20) NOT NULL COMMENT '키워드코드', -- 키워드코드 + `keyword_name` VARCHAR(100) NULL COMMENT '키워드명', -- 키워드명 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '사용자 키워드'; + +-- 사용자 키워드 +ALTER TABLE `edu`.`user_keywords` + ADD CONSTRAINT `PK_user_keywords` -- 사용자 키워드 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `keyword_code` -- 키워드코드 + ); + +-- 컨텐츠제안하기 +CREATE TABLE `edu`.`content_offer` ( + `offer_id` VARCHAR(20) NOT NULL COMMENT '제안ID', -- 제안ID + `type_code` VARCHAR(20) NULL COMMENT '제안구분', -- 제안구분 + `title` VARCHAR(200) NULL COMMENT '제목', -- 제목 + `reference_url` VARCHAR(255) NULL COMMENT 'URL', -- URL + `reason` TEXT NULL COMMENT '추천이유', -- 추천이유 + `status_code` VARCHAR(20) NULL COMMENT '제안상태', -- 제안상태 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_at` TIMESTAMP NULL COMMENT '수정일', -- 수정일 + `member_id` VARCHAR(20) NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NULL COMMENT '기준법인' -- 기준법인 +) +COMMENT '컨텐츠제안하기'; + +-- 컨텐츠제안하기 +ALTER TABLE `edu`.`content_offer` + ADD CONSTRAINT `PK_content_offer` -- 컨텐츠제안하기 기본키 + PRIMARY KEY ( + `offer_id` -- 제안ID + ); + +-- 년도별학습레벨 +CREATE TABLE `edu`.`yearly_learning_stats` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `stats_year` CHAR(4) NOT NULL COMMENT '년도', -- 년도 + `learning_level` VARCHAR(20) NULL COMMENT '학습레벨', -- 학습레벨 + `total_minutes` DECIMAL(18) NULL COMMENT '총학습시간(분)', -- 총학습시간(분) + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '년도별학습레벨'; + +-- 년도별학습레벨 +ALTER TABLE `edu`.`yearly_learning_stats` + ADD CONSTRAINT `PK_yearly_learning_stats` -- 년도별학습레벨 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `stats_year` -- 년도 + ); + +-- 컨텐츠 키워드 +CREATE TABLE `edu`.`content_keywords` ( + `content_id` VARCHAR(20) NOT NULL COMMENT '콘텐츠ID', -- 콘텐츠ID + `keyword_code` VARCHAR(20) NOT NULL COMMENT '키워드코드', -- 키워드코드 + `is_active` CHAR(1) NULL COMMENT '사용여부', -- 사용여부 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '컨텐츠 키워드'; + +-- 컨텐츠 키워드 +ALTER TABLE `edu`.`content_keywords` + ADD CONSTRAINT `PK_content_keywords` -- 컨텐츠 키워드 기본키 + PRIMARY KEY ( + `content_id`, -- 콘텐츠ID + `keyword_code` -- 키워드코드 + ); + +-- 접속이력 +CREATE TABLE `edu`.`access_history` ( + `accessed_at` TIMESTAMP NOT NULL COMMENT '접속일시', -- 접속일시 + `member_id` VARCHAR(20) NOT NULL COMMENT '사번', -- 사번 + `sys_comp_code` VARCHAR(20) NULL COMMENT '기준법인', -- 기준법인 + `ip_address` VARCHAR(20) NULL COMMENT '접속IP' -- 접속IP +) +COMMENT '접속이력'; + +-- 접속이력 +ALTER TABLE `edu`.`access_history` + ADD CONSTRAINT `PK_access_history` -- 접속이력 기본키 + PRIMARY KEY ( + `accessed_at` -- 접속일시 + ); + +-- 코드마스터 +CREATE TABLE `edu`.`code_group` ( + `group_code` VARCHAR(10) NOT NULL COMMENT '메인코드', -- 메인코드 + `group_name` VARCHAR(250) NULL COMMENT '코드명', -- 코드명 + `is_active` CHAR(1) NULL COMMENT '사용구분', -- 사용구분 + `sort_order` INTEGER NULL COMMENT '정렬구분', -- 정렬구분 + `comment` VARCHAR(250) NULL COMMENT '코멘트', -- 코멘트 + `desc01` VARCHAR(250) NULL COMMENT '설명1', -- 설명1 + `desc02` VARCHAR(250) NULL COMMENT '설명2', -- 설명2 + `desc03` VARCHAR(250) NULL COMMENT '설명3', -- 설명3 + `desc04` VARCHAR(250) NULL COMMENT '설명4', -- 설명4 + `desc05` VARCHAR(250) NULL COMMENT '설명5', -- 설명5 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '코드마스터'; + +-- 코드마스터 +ALTER TABLE `edu`.`code_group` + ADD CONSTRAINT `PK_code_group` -- 코드마스터 기본키 + PRIMARY KEY ( + `group_code` -- 메인코드 + ); + +-- 첨부파일 +CREATE TABLE `edu`.`files` ( + `content_id` VARCHAR(20) NOT NULL COMMENT '콘텐츠ID', -- 콘텐츠ID + `id` INTEGER NOT NULL COMMENT '파일ID', -- 파일ID + `file_name` VARCHAR(200) NULL COMMENT '파일명', -- 파일명 + `file_type` VARCHAR(20) NULL COMMENT '파일구분', -- 파일구분 + `file_path` VARCHAR(200) NULL COMMENT '저장위치', -- 저장위치 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '첨부파일'; + +-- 첨부파일 +ALTER TABLE `edu`.`files` + ADD CONSTRAINT `PK_files` -- 첨부파일 기본키 + PRIMARY KEY ( + `content_id`, -- 콘텐츠ID + `id` -- 파일ID + ); + +-- 선택학습목표 +CREATE TABLE `edu`.`user_learning_goals` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `goal_code` VARCHAR(20) NOT NULL COMMENT '학습목표 코드', -- 학습목표 코드 + `quarter` VARCHAR(20) NULL COMMENT '분기', -- 분기 + `completed_date` DATE NULL COMMENT '학습완료일', -- 학습완료일 + `is_active` CHAR(1) NULL COMMENT '사용여부', -- 사용여부 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '선택학습목표'; + +-- 선택학습목표 +ALTER TABLE `edu`.`user_learning_goals` + ADD CONSTRAINT `PK_user_learning_goals` -- 선택학습목표 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `goal_code` -- 학습목표 코드 + ); + +-- 법인별키워드 +CREATE TABLE `edu`.`recommend_keywords` ( + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `keyword_code` VARCHAR(20) NOT NULL COMMENT '키워드코드', -- 키워드코드 + `is_active` CHAR(1) NULL COMMENT '사용여부', -- 사용여부 + `created_by` VARCHAR(20) NULL COMMENT '등록자', -- 등록자 + `created_at` TIMESTAMP NULL COMMENT '등록일', -- 등록일 + `updated_by` VARCHAR(20) NULL COMMENT '수정자', -- 수정자 + `updated_at` TIMESTAMP NULL COMMENT '수정일' -- 수정일 +) +COMMENT '법인별키워드'; + +-- 법인별키워드 +ALTER TABLE `edu`.`recommend_keywords` + ADD CONSTRAINT `PK_recommend_keywords` -- 법인별키워드 기본키 + PRIMARY KEY ( + `sys_comp_code`, -- 기준법인 + `keyword_code` -- 키워드코드 + ); + +-- 뱃지정보 +CREATE TABLE `edu`.`user_badges` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `seq` INTEGER NOT NULL COMMENT '순번', -- 순번 + `badge_code` VARCHAR(20) NULL COMMENT '뱃지코드', -- 뱃지코드 + `issued_at` DATETIME NULL COMMENT '지급일자' -- 지급일자 +) +COMMENT '뱃지정보'; + +-- 뱃지정보 +ALTER TABLE `edu`.`user_badges` + ADD CONSTRAINT `PK_user_badges` -- 뱃지정보 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `seq` -- 순번 + ); + +-- 검색어이력 +CREATE TABLE `edu`.`search_logs` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `sys_comp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `seq` INTEGER NOT NULL COMMENT '순번', -- 순번 + `keyword` VARCHAR(50) NULL COMMENT '검색어', -- 검색어 + `searched_at` DATETIME NULL COMMENT '등록일' -- 등록일 +) +COMMENT '검색어이력'; + +-- 검색어이력 +ALTER TABLE `edu`.`search_logs` + ADD CONSTRAINT `PK_search_logs` -- 검색어이력 기본키 + PRIMARY KEY ( + `member_id`, -- id + `sys_comp_code`, -- 기준법인 + `seq` -- 순번 + ); + +-- 알람이력 +CREATE TABLE `edu`.`notifications` ( + `member_id` VARCHAR(20) NOT NULL COMMENT 'id', -- id + `corp_code` VARCHAR(20) NOT NULL COMMENT '기준법인', -- 기준법인 + `seq` INTEGER NOT NULL COMMENT '순번', -- 순번 + `type_code` VARCHAR(20) NULL COMMENT '알람코드', -- 알람코드 + `message` VARCHAR(255) NULL COMMENT '알람내용', -- 알람내용 + `sent_at` DATETIME NULL COMMENT '알람일시' -- 알람일시 +) +COMMENT '알람이력'; + +-- 알람이력 +ALTER TABLE `edu`.`notifications` + ADD CONSTRAINT `PK_notifications` -- 알람이력 기본키 + PRIMARY KEY ( + `member_id`, -- id + `corp_code`, -- 기준법인 + `seq` -- 순번 + ); + +-- 코드상세 +ALTER TABLE `edu`.`codes` + ADD CONSTRAINT `FK_code_group_TO_codes` -- 코드마스터 -> 코드상세 + FOREIGN KEY ( + `group_code` -- 메인코드 + ) + REFERENCES `edu`.`code_group` ( -- 코드마스터 + `group_code` -- 메인코드 + ); + +-- 댓글정보 +ALTER TABLE `edu`.`comments` + ADD CONSTRAINT `FK_users_TO_comments` -- 통합인사정보 -> 댓글정보 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 학습이력 +ALTER TABLE `edu`.`learning_histories` + ADD CONSTRAINT `FK_users_TO_learning_histories` -- 통합인사정보 -> 학습이력 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 학습이력 +ALTER TABLE `edu`.`learning_histories` + ADD CONSTRAINT `FK_contents_TO_learning_histories` -- 컨텐츠 등록 -> 학습이력 + FOREIGN KEY ( + `content_id` -- 콘텐츠ID + ) + REFERENCES `edu`.`contents` ( -- 컨텐츠 등록 + `content_id` -- 콘텐츠ID + ); + +-- 컨텐츠저장 +ALTER TABLE `edu`.`content_wishlist` + ADD CONSTRAINT `FK_users_TO_content_wishlist` -- 통합인사정보 -> 컨텐츠저장 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 사용자 키워드 +ALTER TABLE `edu`.`user_keywords` + ADD CONSTRAINT `FK_users_TO_user_keywords` -- 통합인사정보 -> 사용자 키워드 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 컨텐츠제안하기 +ALTER TABLE `edu`.`content_offer` + ADD CONSTRAINT `FK_users_TO_content_offer` -- 통합인사정보 -> 컨텐츠제안하기 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 년도별학습레벨 +ALTER TABLE `edu`.`yearly_learning_stats` + ADD CONSTRAINT `FK_users_TO_yearly_learning_stats` -- 통합인사정보 -> 년도별학습레벨 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 컨텐츠 키워드 +ALTER TABLE `edu`.`content_keywords` + ADD CONSTRAINT `FK_contents_TO_content_keywords` -- 컨텐츠 등록 -> 컨텐츠 키워드 + FOREIGN KEY ( + `content_id` -- 콘텐츠ID + ) + REFERENCES `edu`.`contents` ( -- 컨텐츠 등록 + `content_id` -- 콘텐츠ID + ); + +-- 첨부파일 +ALTER TABLE `edu`.`files` + ADD CONSTRAINT `FK_contents_TO_files` -- 컨텐츠 등록 -> 첨부파일 + FOREIGN KEY ( + `content_id` -- 콘텐츠ID + ) + REFERENCES `edu`.`contents` ( -- 컨텐츠 등록 + `content_id` -- 콘텐츠ID + ); + +-- 선택학습목표 +ALTER TABLE `edu`.`user_learning_goals` + ADD CONSTRAINT `FK_users_TO_user_learning_goals` -- 통합인사정보 -> 선택학습목표 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 선택학습목표 +ALTER TABLE `edu`.`user_learning_goals` + ADD CONSTRAINT `FK_learning_goals_TO_user_learning_goals` -- 마이클래스 학습목표 등록 -> 선택학습목표 + FOREIGN KEY ( + `goal_code` -- 학습목표 코드 + ) + REFERENCES `edu`.`learning_goals` ( -- 마이클래스 학습목표 등록 + `goal_code` -- 학습목표 코드 + ); + +-- 뱃지정보 +ALTER TABLE `edu`.`user_badges` + ADD CONSTRAINT `FK_users_TO_user_badges` -- 통합인사정보 -> 뱃지정보 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 검색어이력 +ALTER TABLE `edu`.`search_logs` + ADD CONSTRAINT `FK_users_TO_search_logs` -- 통합인사정보 -> 검색어이력 + FOREIGN KEY ( + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); + +-- 알람이력 +ALTER TABLE `edu`.`notifications` + ADD CONSTRAINT `FK_users_TO_notifications` -- 통합인사정보 -> 알람이력 + FOREIGN KEY ( + `member_id`, -- id + `corp_code` -- 기준법인 + ) + REFERENCES `edu`.`users` ( -- 통합인사정보 + `member_id`, -- id + `sys_comp_code` -- 기준법인 + ); \ No newline at end of file diff --git a/src/css/common.css b/src/css/common.css index 2010d9d..bb91a4b 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -1,4 +1,5 @@ @charset "UTF-8"; + :root { /* text - 텍스트 색상 */ --text-intro-base: #1b1810; @@ -33,41 +34,32 @@ --bg-base: #e4ddcf; --bg-primary: #ece3d2; --bg-secondary: - radial-gradient( - 93.89% 93.89% at 49.32% 6.11%, + radial-gradient(93.89% 93.89% at 49.32% 6.11%, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.11) 86.06%, - rgba(134, 114, 77, 0.2) 88.94% - ), + rgba(134, 114, 77, 0.2) 88.94%), linear-gradient(180deg, #f9f6f0 0%, #e6ddcc 100%); --bg-main-card: rgba(255, 255, 255, 0.6); --bg-intro-mask: #1b1810; - --bg-intro: linear-gradient( - 180deg, - #f9f5f2 0%, - #fff 18.77%, - #fff 41.8%, - #ece8e4 100% - ); + --bg-intro: linear-gradient(180deg, + #f9f5f2 0%, + #fff 18.77%, + #fff 41.8%, + #ece8e4 100%); --bg-main: - linear-gradient( - 90deg, - #0f3025 0%, - #194335 38%, - #0b221b 87.51%, - #0d231c 100% - ) - top / 100% 114px no-repeat, + linear-gradient(90deg, + #0f3025 0%, + #194335 38%, + #0b221b 87.51%, + #0d231c 100%) top / 100% 114px no-repeat, #ece3d2; --bg-video: #1b1b1b; --bg-comment: #2a2a2a; - --bg-nav: linear-gradient( - 90deg, - #0f3025 0%, - #194335 38%, - #0b221b 87.51%, - #0d231c 100% - ); + --bg-nav: linear-gradient(90deg, + #0f3025 0%, + #194335 38%, + #0b221b 87.51%, + #0d231c 100%); --bg-nav-depth: #fff; --bg-nav-alerts: #ff2200; --bg-nav-alerts-hover: #188f6b; @@ -190,89 +182,118 @@ transform: translateY(0); } } + @keyframes arrow-next { - 0%, 100% { + + 0%, + 100% { right: 72px; } + 50% { right: 50px; } } + @keyframes bounce { - 0%, 100% { + + 0%, + 100% { transform: translateX(-50%) translateY(0); } + 50% { transform: translateX(-50%) translateY(-12px); } } + @keyframes slideUp { to { opacity: 1; transform: translateY(0); } } + @keyframes scroll-down { 0% { transform-origin: 50% 100%; transform: scaleY(1); } + 50% { transform-origin: 50% 100%; transform: scaleY(0); } + 50.1% { transform-origin: 50% 0; transform: scaleY(0); } + to { transform-origin: 50% 0; transform: scaleY(1); } } + @keyframes pulse { - 0%, 100% { + + 0%, + 100% { opacity: 0.2; } + 50% { opacity: 0.4; } } + @keyframes borderFadeIn { from { opacity: 0; transform: scale(0.95); } + to { opacity: 1; transform: scale(1); } } + @keyframes borderPulse { - 0%, 100% { + + 0%, + 100% { border-color: #fff; box-shadow: 0 0 20px rgba(255, 255, 255, 0.4); } + 50% { border-color: #fff; box-shadow: 0 0 30px rgba(255, 255, 255, 0.6); } } + html { font-size: 10px; } -html[lang=ko-KR], html[lang=ko] { + +html[lang=ko-KR], +html[lang=ko] { font-family: "Noto Sans KR", sans-serif; } + html[lang=en], html *[lang=en] { font-family: "Noto Sans KR", Arial, sans-serif, serif; } + html[lang=en] body, html *[lang=en] body { font-size: 18px; font-weight: 400; } + html body { font-size: 16px; font-weight: 400; @@ -282,65 +303,8 @@ html body { } /* ====================================================================== */ -/* [Web Font] +/* [Web Font] - Noto Sans KR & Caveat: Google Fonts CDN으로 로드 (_head.php 참조) */ /* ====================================================================== */ -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 100; - font-display: swap; - src: local("NotoKR-Thin"), url(../fonts/NotoKR-Thin/notokr-thin.ttf) format("truetype"); -} -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 300; - font-display: swap; - src: local("NotoKR-Light"), url(../fonts/NotoKR-Light/notokr-light.ttf) format("truetype"); -} -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 350; - font-display: swap; - src: local("NotoKR-DemiLight"), url(../fonts/NotoKR-DemiLight/notokr-demilight.ttf) format("truetype"); -} -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 400; - font-display: swap; - src: local("NotoKR-Regular"), url(../fonts/NotoKR-Regular/notokr-regular.ttf) format("truetype"); -} -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 500; - font-display: swap; - src: local("NotoKR-Medium"), url(../fonts/NotoKR-Medium/notokr-medium.ttf) format("truetype"); -} -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 700; - font-display: swap; - src: local("NotoKR-Bold"), url(../fonts/NotoKR-Bold/notokr-bold.ttf) format("truetype"); -} -@font-face { - font-family: "Noto Sans KR"; - font-style: normal; - font-weight: 900; - font-display: swap; - src: local("NotoKR-Black"), url(../fonts/NotoKR-Black/notokr-black.ttf) format("truetype"); -} -/* Caveat - 가변 폰트(400~700), cursive는 사용처에서 지정 */ -@font-face { - font-family: "Caveat"; - font-style: normal; - font-weight: 400 700; - font-display: swap; - src: url(../fonts/Caveat/Caveat-VariableFont_wght.ttf) format("truetype"); -} /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ html { -webkit-text-size-adjust: 100%; @@ -359,7 +323,7 @@ abbr[title] { border-bottom: none; text-decoration: underline; -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; + text-decoration: underline dotted; } b, @@ -473,7 +437,7 @@ textarea { [type=number]::-webkit-outer-spin-button { height: auto; -webkit-appearance: none; - appearance: none; + appearance: none; margin: 0; } @@ -546,8 +510,8 @@ iframe { margin: 0; padding: 0; -webkit-text-size-adjust: 100%; - -moz-text-size-adjust: 100%; - text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; } article, @@ -586,9 +550,12 @@ img { vertical-align: top; max-width: 100%; border: 0; - image-rendering: -moz-crisp-edges; /* firefox */ - image-rendering: -o-crisp-edges; /* opera */ - image-rendering: -webkit-optimize-contrast; /* chrome(비표준) */ + image-rendering: -moz-crisp-edges; + /* firefox */ + image-rendering: -o-crisp-edges; + /* opera */ + image-rendering: -webkit-optimize-contrast; + /* chrome(비표준) */ image-rendering: crisp-edges; transform: translateZ(0); } @@ -627,10 +594,15 @@ a { cursor: pointer; background-color: transparent; } + a:link { text-decoration: none; } -a:hover, a:focus, a:active, a:visited { + +a:hover, +a:focus, +a:active, +a:visited { text-decoration: none; } @@ -670,16 +642,16 @@ select { textarea { resize: none; -webkit-appearance: none; - -moz-appearance: none; - appearance: none; + -moz-appearance: none; + appearance: none; } label { cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; - -moz-user-select: none; - user-select: none; + -moz-user-select: none; + user-select: none; } table { @@ -701,6 +673,7 @@ html::-webkit-scrollbar { height: 10px; width: 7px; } + html::-webkit-scrollbar-thumb { background-color: var(--bg-scrollbar-thumb); border-radius: 8px; @@ -708,6 +681,7 @@ html::-webkit-scrollbar-thumb { border-top: 1px solid transparent; border-bottom: 1px solid transparent; } + html::-webkit-scrollbar-track { background-color: var(--bg-scrollbar-track); } @@ -750,6 +724,7 @@ html::-webkit-scrollbar-track { background-blend-mode: screen, normal; color: #fff; } + .btn-primary:disabled { background: #C4C4C4; border-color: #B1B1B1; @@ -760,7 +735,7 @@ html::-webkit-scrollbar-track { display: inline-block; width: 18px; height: 18px; - background-image: url("../img/ico/ico_watch.svg"); + background-image: url("../images/ico/ico_watch.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; @@ -770,7 +745,7 @@ html::-webkit-scrollbar-track { display: inline-block; width: 18px; height: 18px; - background-image: url("../img/ico/ico_bookmark.svg"); + background-image: url("../images/ico/ico_bookmark.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; @@ -780,7 +755,7 @@ html::-webkit-scrollbar-track { display: inline-block; width: 24px; height: 32px; - background-image: url("../img/ico/ico_pin.svg"); + background-image: url("../images/ico/ico_pin.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; @@ -790,7 +765,7 @@ html::-webkit-scrollbar-track { display: inline-block; width: 22px; height: 22px; - background-image: url("../img/ico/ico_comment.svg"); + background-image: url("../images/ico/ico_comment.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; @@ -803,6 +778,7 @@ html::-webkit-scrollbar-track { justify-content: center; flex-direction: row; } + .input-group .btn-clear { position: absolute; top: 50%; @@ -814,24 +790,29 @@ html::-webkit-scrollbar-track { background: transparent; cursor: pointer; display: none; - background-image: url("../img/ico/ico_clear.svg"); + background-image: url("../images/ico/ico_clear.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; } + .input-group .btn-clear:hover { opacity: 0.7; } + .input-group:has(input:not(:-moz-placeholder)) .input-group .btn-clear { display: block; } -.input-group:has(input[value]:not([value=""])) .input-group .btn-clear, .input-group:has(input:not(:placeholder-shown)) .input-group .btn-clear { + +.input-group:has(input[value]:not([value=""])) .input-group .btn-clear, +.input-group:has(input:not(:placeholder-shown)) .input-group .btn-clear { display: block; } .checkbox { position: relative; } + .checkbox input[type=checkbox] { position: absolute; width: 0; @@ -847,14 +828,17 @@ html::-webkit-scrollbar-track { justify-content: center; flex-direction: row; } + [class^=keyword][class*=list] { max-width: 470px; } + [class^=keyword][class*=tag] label:has(:checked) { color: var(--text-keyword-primary); background: var(--bg-keyword-primary); border: 1px solid var(--border-keyword-primary); } + [class^=keyword] label { position: relative; display: block; @@ -867,25 +851,30 @@ html::-webkit-scrollbar-track { font-weight: 500; line-height: 1; } + [class^=keyword] label:has(+ [type=checkbox]:checked) { color: var(--text-keyword-secondary); background: var(--bg-keyword-primary-hover); border: 1px solid var(--border-keyword-primary-hover); } + [class^=keyword] label:has(+ [type=checkbox]:checked):has(:checked) { color: var(--text-keyword-primary); background: var(--bg-keyword-primary); border: 1px solid var(--border-keyword-primary); } + [class^=keyword] label input[type=checkbox] { position: absolute; width: 0; height: 0; opacity: 0; } + [class^=keyword] .kw-box { position: relative; } + [class^=keyword] .kw-box label::after { content: " "; display: block; @@ -896,31 +885,36 @@ html::-webkit-scrollbar-track { height: 14px; -webkit-appearance: none; -moz-appearance: none; - appearance: none; + appearance: none; border-radius: 50%; - background-image: url("../img/ico/ico_add.svg"); + background-image: url("../images/ico/ico_add.svg"); background-size: cover; background-position: center; background-repeat: no-repeat; } + [class^=keyword] .kw-box label:has(:checked)::after { - background-image: url("../img/ico/ico_remove.svg"); + background-image: url("../images/ico/ico_remove.svg"); } + [class^=keyword] .kw-allow { color: var(--text-keyword-secondary); background: var(--bg-keyword-primary-hover); border: 1px solid var(--border-keyword-primary-hover); } + [class^=keyword] .kw-allow:has(:checked) { color: var(--text-keyword-primary); background: var(--bg-keyword-primary); border: 1px solid var(--border-keyword-primary); } + [class^=keyword] .kw-deny { color: var(--text-keyword-secondary); background: var(--bg-keyword-secondary-hover); border: 1px solid var(--border-keyword-secondary-hover); } + [class^=keyword] .kw-deny:has(:checked) { color: var(--text-keyword-primary); background: var(--bg-keyword-secondary); @@ -930,9 +924,11 @@ html::-webkit-scrollbar-track { .item-info .leader { background: var(--bg-cate-primary); } + .item-info .insight { background: var(--bg-cate-secondary); } + .item-info .biz { background: var(--bg-cate-tertiary); } @@ -941,28 +937,35 @@ html::-webkit-scrollbar-track { padding-top: 74px; text-align: center; } + .page-title p { font-size: 40px; font-weight: 400; } + .page-title p.fw-b { font-weight: 700; } + .page-title p em { font-weight: 700; color: var(--text-title-accent); } + .page-title p small { font-size: 32px; font-weight: 400; } + .page-title h3 { font-size: 32px; font-weight: 300; } + .page-title h3 span { font-weight: 400; } + .page-title h3 em { font-weight: 500; } @@ -991,21 +994,23 @@ h5 { justify-content: center; flex-direction: row; } + .bookmark input[type=checkbox] { height: 10px; -webkit-appearance: none; -moz-appearance: none; - appearance: none; + appearance: none; cursor: pointer; - background-image: url("../img/ico/ico_bookmark_off.svg"); + background-image: url("../images/ico/ico_bookmark_off.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; width: 12px; aspect-ratio: 1/1; } + .bookmark input[type=checkbox]:checked { - background-image: url("../img/ico/ico_bookmark_on.svg"); + background-image: url("../images/ico/ico_bookmark_on.svg"); background-size: contain; background-position: center; background-repeat: no-repeat; @@ -1016,6 +1021,7 @@ h5 { .m-br { display: none; } + @media only screen and (max-width: 1023px) { .m-br { display: block; @@ -1033,6 +1039,7 @@ h5 { background-color: var(--bg-modal); overflow: auto; } + .modal .modal-content { position: absolute; top: 50%; @@ -1046,6 +1053,7 @@ h5 { border-radius: 8px; text-align: center; } + .modal .close { position: absolute; right: 12px; @@ -1061,16 +1069,20 @@ h5 { filter: var(--text-shadow); transition: all 0.1s ease-in-out; } -.modal .close:hover, .modal .close:focus { + +.modal .close:hover, +.modal .close:focus { color: var(--bg-modal-close-hover); text-decoration: none; cursor: pointer; text-shadow: var(--text-stroke); } + .modal.video::-webkit-scrollbar { height: 10px; width: 7px; } + .modal.video::-webkit-scrollbar-thumb { background-color: var(--bg-scrollbar-thumb-dark); border-radius: 8px; @@ -1078,9 +1090,11 @@ h5 { border-top: 1px solid transparent; border-bottom: 1px solid transparent; } + .modal.video::-webkit-scrollbar-track { background-color: var(--bg-scrollbar-track-light); } + .modal.video .close { color: var(--text-revers); font-size: 22px; @@ -1090,6 +1104,7 @@ h5 { top: 14px; right: 16px; } + .modal.video .modal-content { width: 90%; max-width: 1720px; @@ -1101,17 +1116,20 @@ h5 { border-radius: 20px; overflow: hidden; } + .modal.video .modal-body { display: grid; grid-template-columns: 1fr 437px; height: 100%; } + .modal.video .video-contents { display: flex; flex-direction: column; height: 900px; border-right: 1px solid var(--border-video); } + .modal.video .video-area { flex: 1; border-bottom: 1px solid var(--border-video); @@ -1120,6 +1138,7 @@ h5 { justify-content: center; flex-direction: row; } + .modal.video .video-box { position: relative; flex-shrink: 0; @@ -1127,6 +1146,7 @@ h5 { padding-top: 56.0405%; overflow: hidden; } + .modal.video .video-box iframe { position: absolute; top: 0; @@ -1134,6 +1154,7 @@ h5 { width: 100%; height: 100%; } + .modal.video .video-info { height: 188px; padding: 0 36px; @@ -1141,10 +1162,12 @@ h5 { color: var(--text-revers); overflow-y: auto; } + .modal.video .video-info::-webkit-scrollbar { height: 10px; width: 7px; } + .modal.video .video-info::-webkit-scrollbar-thumb { background-color: var(--bg-scrollbar-thumb-dark); border-radius: 8px; @@ -1152,9 +1175,11 @@ h5 { border-top: 1px solid transparent; border-bottom: 1px solid transparent; } + .modal.video .video-info::-webkit-scrollbar-track { background-color: var(--bg-scrollbar-track-light); } + .modal.video .video-info .tit-box { position: sticky; top: 0; @@ -1168,42 +1193,50 @@ h5 { justify-content: center; flex-direction: column; } + .modal.video .video-info .tit-box h3 { font-size: 20px; font-weight: 700; padding-right: 80px; } + .modal.video .video-info .tit-box .bookmark { position: absolute; bottom: 18px; right: 0; color: rgba(255, 255, 255, 0.5); } + .modal.video .video-info .meta { font-size: 14px; color: var(--text-video-primary); } + .modal.video .video-info .meta span { position: relative; display: inline-block; color: var(--text-video-primary); } + .modal.video .video-info .meta span::after { content: " "; display: inline-block; width: 12px; height: 10px; - background: url("../img/ico/ico_arrow_meta.svg") no-repeat center center; + background: url("../images/ico/ico_arrow_meta.svg") no-repeat center center; } + .modal.video .video-info .meta em { font-weight: 700; } + .modal.video .video-info .desc { padding: 22px 0; font-size: 14px; font-weight: 500; color: var(--text-video-secondary); } + .modal.video .video-side { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; @@ -1211,9 +1244,11 @@ h5 { max-height: 900px; overflow: hidden; } -.modal.video .video-side > * { + +.modal.video .video-side>* { min-height: 0; } + .modal.video .video-side .comment-wrap { display: flex; flex-direction: column; @@ -1221,19 +1256,23 @@ h5 { overflow: visible; align-self: end; } + .modal.video .video-side .comment-wrap:has(.comment-list) { border-top: 1px solid var(--border-video); box-shadow: var(--shadow-comment); } + .modal.video .video-side.step:has(:not(.comment-wrap)) .video-list { padding-bottom: 20px; } + .modal.video .video-side.step .video-header { flex-direction: column; background: linear-gradient(271deg, rgba(255, 244, 233, 0.04) 1.54%, rgba(255, 244, 233, 0.09) 99.11%), #1b1b1b; height: -moz-max-content; height: max-content; } + .modal.video .video-side.step .video-header .tit-box { gap: 12px; display: flex; @@ -1241,6 +1280,7 @@ h5 { justify-content: flex-start; flex-direction: column; } + .modal.video .video-side.step .video-header .sub-txt { font-size: 20px; font-weight: 400; @@ -1252,10 +1292,12 @@ h5 { -webkit-box-orient: vertical; -webkit-line-clamp: 2; } + .modal.video .video-side.step .video-header .gauge-container { position: relative; width: 100%; } + .modal.video .video-side.step .video-header .gauge-bar { position: relative; width: 100%; @@ -1266,6 +1308,7 @@ h5 { border: 0.5px solid var(--bg-video-gauge-border); margin-bottom: 8px; } + .modal.video .video-side.step .video-header .gauge-fill { position: absolute; top: 0; @@ -1275,6 +1318,7 @@ h5 { border-radius: 4px; transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1); } + .modal.video .video-side.step .video-header .gauge-fill::after { content: ""; display: block; @@ -1287,6 +1331,7 @@ h5 { mix-blend-mode: color-dodge; opacity: 0.4; } + .modal.video .video-side.step .video-header .gauge-ticks { position: absolute; top: 0; @@ -1297,6 +1342,7 @@ h5 { mix-blend-mode: plus-lighter; opacity: 0.2; } + .modal.video .video-side.step .video-header .gauge-labels { font-size: 14px; display: flex; @@ -1304,13 +1350,16 @@ h5 { justify-content: space-between; flex-direction: row; } + .modal.video .video-side.step .video-header .gauge-labels em { font-weight: 700; margin: 0 2px; } + .modal.video .video-side.step .video-list { padding-top: 20px; } + .modal.video .video-header { padding: 38px 16px 16px; min-height: 80px; @@ -1321,9 +1370,11 @@ h5 { justify-content: flex-start; flex-direction: row; } + .modal.video .video-header .tit { line-height: 26px; } + .modal.video .video-header .badge { width: 42px; height: 26px; @@ -1336,14 +1387,17 @@ h5 { flex-direction: row; border-radius: 25px; } + .modal.video .video-list { overflow-y: auto; align-self: start; } + .modal.video .video-list::-webkit-scrollbar { height: 10px; width: 7px; } + .modal.video .video-list::-webkit-scrollbar-thumb { background-color: var(--bg-scrollbar-thumb-dark); border-radius: 8px; @@ -1351,21 +1405,26 @@ h5 { border-top: 1px solid transparent; border-bottom: 1px solid transparent; } + .modal.video .video-list::-webkit-scrollbar-track { background-color: var(--bg-scrollbar-track-light); } + .modal.video .video-list .tit { color: #fff; margin-bottom: 8px; } + .modal.video .learning-list { position: relative; color: var(--text-learning-base); } + .modal.video .learning-list::-webkit-scrollbar { height: 10px; width: 7px; } + .modal.video .learning-list::-webkit-scrollbar-thumb { background-color: var(--bg-scrollbar-thumb-dark); border-radius: 8px; @@ -1373,9 +1432,11 @@ h5 { border-top: 1px solid transparent; border-bottom: 1px solid transparent; } + .modal.video .learning-list::-webkit-scrollbar-track { background-color: var(--bg-scrollbar-track-light); } + .modal.video .learning-list::before { content: ""; display: block; @@ -1386,15 +1447,18 @@ h5 { opacity: 0.2; background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fff 10%, #fff 90%, rgba(255, 255, 255, 0) 100%); } -.modal.video .learning-list > li { + +.modal.video .learning-list>li { border: none; } + .modal.video .learning-list .list { gap: 12px; padding: 0; margin-bottom: 5px; grid-template-columns: 44px 1fr; } + .modal.video .learning-list .list .learning-box { position: relative; gap: 12px; @@ -1404,6 +1468,7 @@ h5 { justify-content: flex-start; flex-direction: row; } + .modal.video .learning-list .list .learning-box::before { content: ""; display: block; @@ -1413,6 +1478,7 @@ h5 { height: 1px; background-color: var(--bg-learning-line); } + .modal.video .learning-list .list .learning-box::after { content: ""; display: block; @@ -1424,55 +1490,70 @@ h5 { border-radius: 50%; outline: 2px solid var(--bg-learning-line); } + .modal.video .learning-list .list .learning-box .title { color: var(--text-card-author); } + .modal.video .learning-list .list .thumb { min-width: 105px; max-width: 105px; } + .modal.video .learning-list .list .sep, .modal.video .learning-list .list .state { font-size: 14px; white-space: nowrap; } + .modal.video .learning-list .active { color: var(--text-learning-primary); } + .modal.video .learning-list .active .seq, .modal.video .learning-list .active .state { font-weight: 600; } + .modal.video .learning-list .active .learning-box { background: linear-gradient(90deg, var(--bg-learning-active) 0%, rgba(255, 92, 0, 0) 100%); } + .modal.video .learning-list .active .learning-box::before { background-color: var(--bg-learning-active-line); } + .modal.video .learning-list .active .learning-box::after { background-color: var(--bg-learning-active-dot); outline-color: var(--bg-learning-active-line); } + .modal.video .learning-list .active .learning-box .title { color: var(--text-card-title-active); font-weight: 600; } + .modal.video .learning-list .complet { color: var(--text-learning-secondary); } + .modal.video .learning-list .complet .learning-box { background: linear-gradient(90deg, var(--bg-learning-complete) 0%, rgba(0, 140, 73, 0) 100%); } + .modal.video .learning-list .complet .learning-box::before { background-color: var(--bg-learning-complete-line); } + .modal.video .learning-list .complet .learning-box::after { background-color: var(--bg-learning-complete-dot); outline-color: var(--bg-learning-complete-line); } + .modal.video .learning-list .complet .learning-box .title { color: var(--text-card-title-complete); } + .modal.video .comment-box { width: 100%; padding: 8px; @@ -1483,6 +1564,7 @@ h5 { justify-content: flex-start; flex-direction: row; } + .modal.video textarea { flex-grow: 1; min-height: 32px; @@ -1498,10 +1580,12 @@ h5 { overflow-y: auto; transition: height 0.3s linear; } + .modal.video textarea::-webkit-scrollbar { height: 10px; width: 7px; } + .modal.video textarea::-webkit-scrollbar-thumb { background-color: var(--bg-scrollbar-thumb-dark); border-radius: 8px; @@ -1509,15 +1593,19 @@ h5 { border-top: 1px solid transparent; border-bottom: 1px solid transparent; } + .modal.video textarea::-webkit-scrollbar-track { background-color: var(--bg-scrollbar-track-light); } + .modal.video textarea::-moz-placeholder { color: var(--bg-textarea-placeholder); } + .modal.video textarea::placeholder { color: var(--bg-textarea-placeholder); } + .modal.video .btn-area { gap: 4px; display: flex; @@ -1525,9 +1613,11 @@ h5 { justify-content: center; flex-direction: row; } + .modal.video .btn-active { background: var(--bg-btn-primary); } + .modal.video [class^=btn] { min-width: 40px; min-height: 32px; @@ -1535,14 +1625,17 @@ h5 { color: #fff; font-size: 12px; } + .modal.video [class^=btn]:not([class*=area]) { background: var(--bg-btn-base); } + .modal.video [class^=btn]:disabled { color: #8f8f8f; background: var(--bg-btn-secondary); border: 1px solid var(--border-btn); } + .modal.video [class^=btn][class*=save]:not(:disabled) { background: var(--text-accent); border: none; @@ -1551,9 +1644,11 @@ h5 { .video-list { padding: 0 16px; } + .video-list li { border-bottom: 1px solid var(--border-video); } + .video-list .list { width: 100%; gap: 20px; @@ -1562,6 +1657,7 @@ h5 { grid-template-columns: 120px 1fr; align-items: center; } + .video-list .thumb { position: relative; min-height: 68px; @@ -1574,11 +1670,13 @@ h5 { justify-content: center; flex-direction: row; } + .video-list .thumb img { width: 100%; height: auto; max-width: auto; } + .video-list .txt-box { gap: 4px; display: flex; @@ -1586,6 +1684,7 @@ h5 { justify-content: center; flex-direction: column; } + .video-list .txt-box .checkbox { position: absolute; top: 10px; @@ -1597,23 +1696,29 @@ h5 { background-repeat: no-repeat; background-size: contain; } + .video-list .txt-box .checkbox:has(:checked) { background-image: url("data:image/svg+xml,%3Csvg width='22' height='18' viewBox='0 0 22 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.95 0C14.036 0 12.199 0.79455 11 2.04033C9.801 0.79455 7.964 0 6.05 0C2.662 0 0 2.36403 0 5.39509C0 9.09319 3.74 12.1243 9.405 16.7052L11 18L12.595 16.7052C18.26 12.1243 22 9.09319 22 5.39509C22 2.36403 19.338 0 15.95 0Z' fill='%23ff5c00'/%3E%3Cpath d='M15.9502 0.75C19.0079 0.750089 21.25 2.85803 21.25 5.39551C21.2499 6.96829 20.4613 8.47481 18.8691 10.2119C17.2723 11.9541 14.9715 13.8187 12.123 16.1221L12.1221 16.123L11 17.0332L9.87793 16.123L9.87695 16.1221L7.8457 14.4717C5.92217 12.894 4.3285 11.5185 3.13086 10.2119C1.5387 8.47481 0.750138 6.96829 0.75 5.39551C0.75 2.85803 2.99208 0.75009 6.0498 0.75C7.76714 0.75 9.40728 1.4668 10.46 2.56055L11 3.12207L11.54 2.56055C12.5927 1.4668 14.2329 0.75 15.9502 0.75Z' stroke='white' stroke-opacity='0.2' stroke-width='1.5'/%3E%3C/svg%3E%0A"); } + .video-list .txt-box .category { font-size: 12px; font-weight: 700; color: #fff; } + .video-list .txt-box .category.leader { color: var(--text-cate-primary); } + .video-list .txt-box .category.insight { color: var(--text-cate-secondary); } + .video-list .txt-box .category.biz { color: var(--text-cate-tertiary); } + .video-list .txt-box .title { font-size: 16px; font-weight: 500; @@ -1631,9 +1736,11 @@ h5 { position: relative; background: var(--bg-comment); } + .comment-box { flex-shrink: 0; } + .comment-resizer { position: absolute; left: calc(50% - 21px); @@ -1653,26 +1760,30 @@ h5 { justify-content: center; flex-direction: row; } -.comment-resizer:hover .resizer-handle, .comment-resizer.resizing .resizer-handle { + +.comment-resizer:hover .resizer-handle, +.comment-resizer.resizing .resizer-handle { background-color: var(--text-myclass); } + .comment-resizer .resizer-handle { width: 100%; height: 100%; margin: auto; transition: background 0.2s ease; background-color: var(--text-revers); - mask-image: url("../img/ico/ico_drag.svg"); + mask-image: url("../images/ico/ico_drag.svg"); mask-size: contain; mask-position: center; mask-repeat: no-repeat; - -webkit-mask-image: url("../img/ico/ico_drag.svg"); + -webkit-mask-image: url("../images/ico/ico_drag.svg"); -webkit-mask-size: contain; -webkit-mask-position: center; -webkit-mask-repeat: no-repeat; width: 18px; aspect-ratio: 1/1; } + .comment-list-wrap { flex: 1; min-height: 0; @@ -1680,22 +1791,28 @@ h5 { overflow-x: hidden; max-height: 340px; } + .comment-list-wrap::-webkit-scrollbar { width: 6px; } + .comment-list-wrap::-webkit-scrollbar-track { background: var(--bg-scrollbar-track-light); } + .comment-list-wrap::-webkit-scrollbar-thumb { background: var(--bg-scrollbar-thumb-light); border-radius: 3px; } + .comment-list-wrap::-webkit-scrollbar-thumb:hover { background: var(--bg-scrollbar-thumb-light-hover); } + .comment-list { padding: 16px 0; } + .comment-info { padding: 0 20px; gap: 12px; @@ -1704,6 +1821,7 @@ h5 { justify-content: flex-start; flex-direction: row; } + .comment-info .photo { width: 20px; height: 32px; @@ -1712,6 +1830,7 @@ h5 { justify-content: center; flex-direction: row; } + .comment-info .photo img { width: 20px; aspect-ratio: 1/1; @@ -1720,6 +1839,7 @@ h5 { background: var(--text-comment-secondary); overflow: hidden; } + .comment-info .user-comment { font-size: 14px; font-weight: 500; @@ -1729,17 +1849,20 @@ h5 { justify-content: flex-start; flex-direction: row; } + .comment-info .user-name { font-weight: 700; color: var(--text-comment-secondary); line-height: 32px; } + .comment-info .user-text { color: var(--text-comment-primary); height: 32px; word-break: keep-all; overflow-y: hidden; } + .comment-info .user-text:disabled { background: none; } @@ -1749,31 +1872,37 @@ h5 { font-size: 10px; } } + @media only screen and (max-width: 991px) { html { font-size: 14px; } } + @media only screen and (max-width: 767px) { html { font-size: 13px; } } + @media only screen and (max-width: 639px) { html { font-size: 12px; } } + @media only screen and (max-width: 479px) { html { font-size: 10px; } } + @media only screen and (max-width: 359px) { html { font-size: 9px; } } + @media only screen and (max-width: 319px) { html { font-size: 8px; diff --git a/src/css/intro.css b/src/css/intro.css index 06db20d..fb3e090 100644 --- a/src/css/intro.css +++ b/src/css/intro.css @@ -1,4 +1,5 @@ @charset "UTF-8"; + :root { /* text - 텍스트 색상 */ --text-intro-base: #1b1810; @@ -33,41 +34,32 @@ --bg-base: #e4ddcf; --bg-primary: #ece3d2; --bg-secondary: - radial-gradient( - 93.89% 93.89% at 49.32% 6.11%, + radial-gradient(93.89% 93.89% at 49.32% 6.11%, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.11) 86.06%, - rgba(134, 114, 77, 0.2) 88.94% - ), + rgba(134, 114, 77, 0.2) 88.94%), linear-gradient(180deg, #f9f6f0 0%, #e6ddcc 100%); --bg-main-card: rgba(255, 255, 255, 0.6); --bg-intro-mask: #1b1810; - --bg-intro: linear-gradient( - 180deg, - #f9f5f2 0%, - #fff 18.77%, - #fff 41.8%, - #ece8e4 100% - ); + --bg-intro: linear-gradient(180deg, + #f9f5f2 0%, + #fff 18.77%, + #fff 41.8%, + #ece8e4 100%); --bg-main: - linear-gradient( - 90deg, - #0f3025 0%, - #194335 38%, - #0b221b 87.51%, - #0d231c 100% - ) - top / 100% 114px no-repeat, + linear-gradient(90deg, + #0f3025 0%, + #194335 38%, + #0b221b 87.51%, + #0d231c 100%) top / 100% 114px no-repeat, #ece3d2; --bg-video: #1b1b1b; --bg-comment: #2a2a2a; - --bg-nav: linear-gradient( - 90deg, - #0f3025 0%, - #194335 38%, - #0b221b 87.51%, - #0d231c 100% - ); + --bg-nav: linear-gradient(90deg, + #0f3025 0%, + #194335 38%, + #0b221b 87.51%, + #0d231c 100%); --bg-nav-depth: #fff; --bg-nav-alerts: #ff2200; --bg-nav-alerts-hover: #188f6b; @@ -190,85 +182,111 @@ transform: translateY(0); } } + @keyframes arrow-next { - 0%, 100% { + + 0%, + 100% { right: 72px; } + 50% { right: 50px; } } + @keyframes bounce { - 0%, 100% { + + 0%, + 100% { transform: translateX(-50%) translateY(0); } + 50% { transform: translateX(-50%) translateY(-12px); } } + @keyframes slideUp { to { opacity: 1; transform: translateY(0); } } + @keyframes scroll-down { 0% { transform-origin: 50% 100%; transform: scaleY(1); } + 50% { transform-origin: 50% 100%; transform: scaleY(0); } + 50.1% { transform-origin: 50% 0; transform: scaleY(0); } + to { transform-origin: 50% 0; transform: scaleY(1); } } + @keyframes pulse { - 0%, 100% { + + 0%, + 100% { opacity: 0.2; } + 50% { opacity: 0.4; } } + @keyframes borderFadeIn { from { opacity: 0; transform: scale(0.95); } + to { opacity: 1; transform: scale(1); } } + @keyframes borderPulse { - 0%, 100% { + + 0%, + 100% { border-color: #fff; box-shadow: 0 0 20px rgba(255, 255, 255, 0.4); } + 50% { border-color: #fff; box-shadow: 0 0 30px rgba(255, 255, 255, 0.6); } } + @font-face { font-family: "YeogiOttaeJalnan"; src: url("https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_four@1.2/JalnanOTF00.woff") format("woff"); font-weight: normal; font-display: swap; } + .intro { background: var(--bg-intro); background-attachment: fixed; overflow: auto; } + .intro .container { position: relative; top: 0; @@ -286,12 +304,18 @@ justify-content: center; flex-direction: column; } + .intro .text-ani { display: none; } -.intro .text-ani:has(.welcome span.show), .intro .text-ani:has(.update-line span.show), .intro .text-ani:has(.card.show), .intro .text-ani.animating { + +.intro .text-ani:has(.welcome span.show), +.intro .text-ani:has(.update-line span.show), +.intro .text-ani:has(.card.show), +.intro .text-ani.animating { display: block; } + @media only screen and (max-width: 991px) { .intro .text-ani:has(.card.show) { display: flex; @@ -301,83 +325,102 @@ width: 100%; } } + .intro .text-area { min-height: 160px; margin-bottom: 34px; text-align: center; } + .intro .text-area:has(.greeting.hidden, .update-text.hidden) { min-height: 0; margin-bottom: 0; } + .intro .greeting { font-size: 36px; font-weight: 300; line-height: 1.2; } + @media only screen and (min-width: 1024px) { .intro .greeting { height: 656px; } } + @media only screen and (max-width: 1023px) { .intro .greeting { font-size: 2.8rem; min-height: 15.8rem; } - .intro .greeting p.welcome > *:nth-child(5) { + + .intro .greeting p.welcome>*:nth-child(5) { display: block; line-height: 0; } } + .intro .name { font-weight: 500; } + .intro .welcome span { display: inline-block; opacity: 0; transform: translateY(20px); } + .intro .welcome span.show { animation: fadeInUp 0.4s forwards; } + .intro .welcome em { font-weight: 500; } + @media only screen and (max-width: 1023px) { .intro .welcome { margin-top: 2rem; } } + .intro .update-text { text-align: center; } + .intro .update-line { overflow: hidden; font-size: 36px; } + @media only screen and (max-width: 1023px) { .intro .update-line { font-size: 2.8rem; } } + @media only screen and (max-width: 1023px) { .intro .update-line:last-child { margin-top: 2rem; } } + .intro .update-line.bold, .intro .update-line em { font-weight: 500; } -.intro .update-line > span { + +.intro .update-line>span { display: inline-block; opacity: 0; transform: translateY(100%); } -.intro .update-line > span.show { + +.intro .update-line>span.show { animation: slideUp 0.6s forwards; } + .intro .cta-text { position: relative; width: 100vw; @@ -387,12 +430,14 @@ line-height: 1.2; text-align: center; } + @media only screen and (max-width: 1023px) { .intro .cta-text { font-size: 2.8rem; } } -.intro .cta-text > div { + +.intro .cta-text>div { width: 100vw; height: var(--window-inner-height); display: flex; @@ -400,34 +445,41 @@ justify-content: center; flex-direction: column; } -.intro .cta-text > div:not(.mask) { + +.intro .cta-text>div:not(.mask) { position: relative; z-index: 1; cursor: default; } -.intro .cta-text > div:not(.mask) .text-section { + +.intro .cta-text>div:not(.mask) .text-section { opacity: 0; transform: translateY(20px); } -.intro .cta-text > div:not(.mask) .text-section:has(.show) { + +.intro .cta-text>div:not(.mask) .text-section:has(.show) { background-image: url(../images/intro/promise.svg); background-position: bottom; background-size: 586px auto; background-repeat: no-repeat; animation: fadeInUp 0.5s forwards; } + @media only screen and (max-width: 1023px) { - .intro .cta-text > div:not(.mask) .text-section:has(.show) { + .intro .cta-text>div:not(.mask) .text-section:has(.show) { background-size: 120% auto; } } -.intro .cta-text > div:not(.mask) p { + +.intro .cta-text>div:not(.mask) p { opacity: 0; transform: translateY(20px); } -.intro .cta-text > div:not(.mask) p.show { + +.intro .cta-text>div:not(.mask) p.show { animation: fadeInUp 0.5s forwards; } + .intro .cta-text .text-section { height: 260px; translate: 0 -35%; @@ -437,6 +489,7 @@ justify-content: center; flex-direction: column; } + @media only screen and (max-width: 1023px) { .intro .cta-text .text-section { width: calc(100% - 32px); @@ -445,12 +498,15 @@ translate: 0 -40%; } } + .intro .cta-text .text-section.show { animation: opacity 0.5s forwards; } + .intro .cta-text em { font-weight: 500; } + .intro .cta-btn { position: absolute; top: 50%; @@ -472,6 +528,7 @@ transform: translate(-50%, 25%) translateY(50px); transition: all 0.3s; } + @media only screen and (max-width: 1023px) { .intro .cta-btn { width: calc(100% - 32px); @@ -480,16 +537,19 @@ font-size: 28px; } } + @media only screen and (min-width: 992px) { .intro .cta-btn { box-shadow: 0 -4px 4px 0 #e18d36 inset, 4px 4px 12px -4px rgba(220, 196, 172, 0.85); } } + .intro .cta-btn.show { opacity: 1; transform: translate(-50%, 25%) translateY(0); transition: all 0.3s linear; } + .intro .cta-btn::after { content: " "; position: absolute; @@ -505,12 +565,13 @@ position: absolute; inset: 0; -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); - mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); + mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; border-radius: inherit; } + .intro .cta-btn .ico-arrow { position: absolute; top: 50%; @@ -526,6 +587,7 @@ transform: translateY(-50%); animation: arrow-next 3s infinite ease-in-out; } + .intro .mask { position: absolute; top: 0; @@ -554,6 +616,7 @@ transition: mask-size 0.2s linear; transition: mask-size 0.2s linear, -webkit-mask-size 0.2s linear; } + @media only screen and (max-width: 991px) { .intro .mask { -webkit-mask-image: none; @@ -561,27 +624,33 @@ clip-path: circle(0% at 50% 50%); transition: clip-path 3.5s ease-out; } + .intro .mask.expand { clip-path: circle(300% at 50% 50%); } } + .intro .mask .text-section { background-image: url(../images/intro/promise_b.svg); background-position: bottom; background-size: auto; background-repeat: no-repeat; } + @media only screen and (max-width: 1023px) { .intro .mask .text-section { background-size: 95% auto; } } + .intro .mask .mask-text { color: #fff; } + .intro .mask .mask-text em { font-style: normal; } + .intro .content-area { margin-top: 34px; display: flex; @@ -589,6 +658,7 @@ justify-content: center; flex-direction: column; } + @media only screen and (max-width: 991px) { .intro .content-area { flex: 1 1 0; @@ -597,6 +667,7 @@ align-items: stretch; } } + .intro .card { opacity: 0; transform: translateY(60px); @@ -611,12 +682,14 @@ justify-content: center; flex-direction: column; } + @media only screen and (min-width: 992px) { .intro .card { flex: 0 0 calc(50% - 12px); padding: 60px 32px 48px; } } + @media only screen and (min-width: 1200px) { .intro .card { flex: 1 1 0; @@ -624,6 +697,7 @@ padding: 86px 22px 68px; } } + @media only screen and (max-width: 991px) { .intro .card { flex: 1 1 0; @@ -640,26 +714,31 @@ border-radius: 12px; } } + .intro .card.show { opacity: 1; transform: translateY(0); } + .intro .card-list { display: flex; flex-wrap: wrap; justify-content: center; gap: 20px; } + @media only screen and (min-width: 1200px) { .intro .card-list { flex-wrap: nowrap; } } + @media only screen and (max-width: 1023px) { .intro .card-list { gap: 2.4rem; } } + @media only screen and (max-width: 991px) { .intro .card-list { flex-direction: column; @@ -671,6 +750,7 @@ align-items: stretch; } } + .intro .card-num { font-family: YeogiOttaeJalnan; font-size: 120px; @@ -682,11 +762,13 @@ -webkit-background-clip: text; background-clip: text; } + @media only screen and (max-width: 1023px) { .intro .card-num { font-size: 6rem; } } + .intro .card-title { margin-top: -46px; margin-bottom: 42px; @@ -694,30 +776,36 @@ font-weight: 300; line-height: 1.2; } + @media only screen and (max-width: 1023px) { .intro .card-title { font-size: 2.4rem; } } + @media only screen and (max-width: 991px) { .intro .card-title { margin-top: -32px; margin-bottom: 0; } } + .intro .card-desc { font-size: 24px; } + @media only screen and (max-width: 1023px) { .intro .card-desc { font-size: 1.6rem; } } + @media only screen and (max-width: 991px) { .intro .card-desc { display: none; } } + .intro .card em { font-weight: 700; } @@ -745,18 +833,22 @@ gap: 24px; transform: translateX(-50%); } + .scroll-indicator.hidden { opacity: 0; pointer-events: none; } + .scroll-indicator.sec2 .bar { height: 60px; } + .scroll-indicator span { font-size: 16px; color: var(--text-intro-base); opacity: 0.8; } + .scroll-indicator .bar { width: 2px; height: 110px; @@ -764,6 +856,7 @@ background-color: rgba(0, 0, 0, 0.3); transition: height 0.5s linear; } + .scroll-indicator .bar::before { content: " "; display: block; diff --git a/src/js/puzzle-onboarding.js b/src/js/puzzle-onboarding.js index 7954d33..83ca3ad 100644 --- a/src/js/puzzle-onboarding.js +++ b/src/js/puzzle-onboarding.js @@ -1376,6 +1376,11 @@ class ContentManager { return CONFIG.IMAGE_PATHS.BASE; } + // type이 file인 경우 YouTube 썸네일 사용 불가 → 기본 이미지 반환 + if (chapterInfo.chapter.type === 'file') { + return CONFIG.IMAGE_PATHS.BASE; + } + const firstLesson = chapterInfo.chapter.lessons[0]; if (!firstLesson.url) { return CONFIG.IMAGE_PATHS.BASE; @@ -2934,7 +2939,7 @@ class PuzzleModalManager { static _createLearningList(modal, chapter, chapterIndex, modalState) { try { const domUtils = typeof DOMUtils !== 'undefined' ? DOMUtils : null; - const eventManager = typeof eventManager !== 'undefined' ? eventManager : null; + const _eventManager = typeof eventManager !== 'undefined' ? eventManager : null; const errorHandler = typeof ErrorHandler !== 'undefined' ? ErrorHandler : null; const list = domUtils?.$(".learning-list", modal) || modal.querySelector(".learning-list"); @@ -3040,8 +3045,8 @@ class PuzzleModalManager { } }; - if (eventManager) { - const listenerId = eventManager.on(link, "click", clickHandler); + if (_eventManager) { + const listenerId = _eventManager.on(link, "click", clickHandler); // 리스너 ID를 modal에 저장하여 나중에 정리할 수 있도록 if (!modal._learningListListenerIds) { modal._learningListListenerIds = []; @@ -3927,7 +3932,7 @@ function updatePieceGaugeByCompletion(pieceId) { function initializeOverlay() { try { const domUtils = typeof DOMUtils !== 'undefined' ? DOMUtils : null; - const eventManager = typeof eventManager !== 'undefined' ? eventManager : null; + const _eventManager = typeof eventManager !== 'undefined' ? eventManager : null; const errorHandler = typeof ErrorHandler !== 'undefined' ? ErrorHandler : null; const overlay = domUtils?.$("#overlay") || document.getElementById("overlay"); @@ -3947,8 +3952,8 @@ function initializeOverlay() { } }; - if (eventManager) { - eventManager.on(overlay, "click", clickHandler); + if (_eventManager) { + _eventManager.on(overlay, "click", clickHandler); } else { overlay.addEventListener("click", clickHandler); } diff --git a/src/skin/_include/_head.php b/src/skin/_include/_head.php index a23c256..74af463 100644 --- a/src/skin/_include/_head.php +++ b/src/skin/_include/_head.php @@ -13,7 +13,7 @@ /> - +