/*
=============================================================
  style.css - 포트폴리오 메인 스타일시트
  작성 순서:
  1. CSS 변수 (색상, 폰트, 간격)
  2. 리셋 & 기본 스타일
  3. 재사용 가능한 유틸리티 클래스
  4. 섹션별 스타일 (Header → Hero → About → ...)
  5. 미디어 쿼리 (반응형)
=============================================================
*/


/* =====================================================
   1. CSS 변수 (Custom Properties)

   :root : 문서 전체에서 사용할 수 있는 최상위 선택자.
   여기에 변수를 정의하면 파일 어디서든 var()로 사용 가능.

   장점: 색상을 한 곳에서 관리하므로 테마 변경이 쉽다.
   ===================================================== */
:root {
  /* --- 색상 변수 (VisuAllSat 디자인 스타일: 네이비 + 골드) --- */
  --color-primary: #c9a961;       /* 주요 색상 (골드/앰버 계열 포인트) */
  --color-primary-dark: #b3903f;  /* 주요 색상의 어두운 버전 (hover 효과용) */
  --color-on-primary: #16233f;    /* 골드 배경 위에 올라가는 어두운 글자색 */

  /* 라이트 모드 색상 */
  --color-bg: #ffffff;            /* 배경색 */
  --color-bg-alt: #f6f7fa;        /* 대체 배경색 (섹션 구분용) */
  --color-text: #16233f;          /* 기본 글자색 (네이비 계열) */
  --color-text-light: #64748b;    /* 보조 글자색 */
  --color-border: #e2e8f0;        /* 테두리 색상 */
  --color-card-bg: #ffffff;       /* 카드 배경색 */
  --color-header-scrolled: rgba(255, 255, 255, 0.85); /* 스크롤 시 헤더 반투명 배경 */
  --color-shadow: rgba(0, 0, 0, 0.08); /* 그림자 색상 */

  /*
    --- 고정 네이비 브랜드 색상 ---
    헤더 · 히어로 · 분석 사례 · VisuAllSat 개요 · 푸터는 디자인 스타일 이미지처럼
    라이트/다크 모드 전환과 무관하게 항상 네이비 계열 배경을 유지한다.
  */
  --color-navy: #0c1c37;          /* 진한 네이비 (헤더·히어로·푸터·VisuAllSat 배경) */
  --color-navy-soft: #13284a;     /* 네이비 그라디언트 보조색 */
  --color-navy-card: #1c2d47;     /* 네이비 배경 위 카드색 */
  --color-navy-border: rgba(255, 255, 255, 0.14); /* 네이비 배경 위 테두리 */
  --color-on-navy: #f4f6fa;       /* 네이비 배경 위 기본 글자색 */
  --color-on-navy-light: #aab4c9; /* 네이비 배경 위 보조 글자색 */
  --color-slate: #55647a;         /* 분석 사례 섹션 배경 (슬레이트 블루) */
  --color-slate-card: #2f3c53;    /* 분석 사례 카드 배경 */

  /* --- 폰트 변수 --- */
  --font-family: 'Noto Sans KR', sans-serif; /* 기본 폰트 */
  --font-size-base: 16px;     /* 기본 폰트 크기 */

  /* --- 간격 변수 --- */
  --spacing-xs: 0.5rem;    /* 8px  - 아주 작은 간격 */
  --spacing-sm: 1rem;      /* 16px - 작은 간격 */
  --spacing-md: 1.5rem;    /* 24px - 중간 간격 */
  --spacing-lg: 2rem;      /* 32px - 큰 간격 */
  --spacing-xl: 4rem;      /* 64px - 아주 큰 간격 */

  /* --- 기타 변수 --- */
  --border-radius: 0.75rem;  /* 모서리 둥글기 */
  --transition: 0.3s ease;   /* 전환 애니메이션 속도 */
  --header-height: 4rem;     /* 헤더 높이 (64px) */
  --max-width: 1200px;       /* 컨테이너 최대 너비 */

  /*
    --- 페이지 전체 프레임 변수 ---
    --page-frame-margin : 프레임과 브라우저 창 사이 여백.
    box-shadow의 blur 반경(40px)이 여백 안에서 충분히 퍼질 공간이 있어야
    그림자가 잘려 보이지 않고 온전히 보이므로 여백을 넉넉하게 잡는다.
  */
  --page-frame-margin: 2rem;       /* 프레임과 브라우저 창 사이 여백 */
  --page-frame-radius: 1.25rem;    /* 프레임 모서리 둥글기 */
  --color-page-outer-bg: #e7eaf1;  /* 프레임 바깥쪽 배경색 (라이트) */
}

/* =====================================================
   다크 모드 CSS 변수

   [data-theme="dark"] : data-theme 속성이 "dark"인 요소에 적용.
   JS에서 document.documentElement.setAttribute('data-theme', 'dark') 를 실행하면
   아래 변수들이 :root의 변수를 덮어쓴다.
   ===================================================== */
[data-theme="dark"] {
  --color-bg: #0f172a;
  --color-bg-alt: #1e293b;
  --color-text: #f1f5f9;
  --color-text-light: #94a3b8;
  --color-border: #334155;
  --color-card-bg: #1e293b;
  --color-shadow: rgba(0, 0, 0, 0.3);
  --color-header-scrolled: rgba(30, 41, 59, 0.95); /* 다크모드 스크롤 시 헤더 반투명 배경 */
  --color-page-outer-bg: #05070d; /* 프레임 바깥쪽 배경색 (다크) */
}


/* =====================================================
   2. 리셋 & 기본 스타일

   브라우저마다 기본 스타일이 다르기 때문에
   통일시키기 위한 초기화 작업.
   ===================================================== */

/*
  * (전체 선택자) : 모든 HTML 요소에 적용.
  box-sizing: border-box : padding과 border가 width 안에 포함되도록 설정.
  기본값(content-box)은 padding이 width에 더해져 요소가 예상보다 커지는 문제가 있다.
*/
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;    /* 기본 바깥 여백 초기화 */
  padding: 0;   /* 기본 안쪽 여백 초기화 */
}

html {
  font-size: var(--font-size-base); /* 1rem = 16px */

  /*
    scroll-behavior: smooth : 앵커 링크(#section) 클릭 시 부드럽게 스크롤.
    CSS 한 줄로 네비게이션의 부드러운 스크롤을 구현한다!
  */
  scroll-behavior: smooth;

  /*
    scroll-padding-top : 고정 헤더가 있을 때, 스크롤 목적지가 헤더에 가려지는 문제 해결.
    헤더 높이 + header의 sticky top 오프셋(--page-frame-margin)만큼 여백을 준다.
  */
  scroll-padding-top: calc(var(--header-height) + var(--page-frame-margin));

  /*
    .page-frame이 살짝 안쪽으로 들어와 앉기 때문에, 그 바깥으로 보이는
    여백을 채우는 배경색. 라이트/다크 모드에 따라 --color-page-outer-bg가 바뀐다.
  */
  background-color: var(--color-page-outer-bg);
  transition: background-color var(--transition);
}

body {
  font-family: var(--font-family);
  font-size: var(--font-size-base);
  color: var(--color-text);
  /*
    body의 배경은 (콘텐츠 배경이 아니라) .page-frame 바깥 프레임 배경색으로 맞춘다.
    이유: .page-frame은 상하 margin이 body 바깥으로 collapse되어 html의 배경색이
    보이는 반면, 좌우 margin은 collapse되지 않고 body 영역 안에 그대로 남아
    body의 배경색이 그대로 비친다. 예전처럼 body 배경을 --color-bg(콘텐츠 흰색)로
    두면, 위쪽 여백(html 배경, 회색조)과 좌우 여백(body 배경, 흰색)의 색이 서로
    달라 header의 둥근 모서리 바로 바깥에서 색이 어긋나는 자국이 생겼다.
    body를 --color-page-outer-bg로 통일해 프레임 사방 여백 색을 하나로 맞춘다.
  */
  background-color: var(--color-page-outer-bg);
  line-height: 1.6;          /* 줄 간격: 폰트 크기의 1.6배 */
  transition: background-color var(--transition), color var(--transition);
  /*
    transition : CSS 속성이 변경될 때 부드럽게 전환하는 애니메이션.
    background-color와 color가 변경될 때(다크모드 전환 시) 0.3초에 걸쳐 서서히 변한다.
  */
}

/* 목록의 기본 점(•) 스타일 제거 */
ul, ol {
  list-style: none;
}

/* 링크의 기본 밑줄 제거 */
a {
  text-decoration: none;
  color: inherit; /* 부모 요소의 색상을 상속 */
}

/* 이미지가 부모 요소를 벗어나지 않도록 */
img {
  max-width: 100%;
  display: block; /* 이미지 아래의 불필요한 공백 제거 */
}

/* 버튼 기본 스타일 초기화 */
button {
  border: none;
  background: none;
  cursor: pointer;  /* 마우스 커서를 손가락 모양으로 */
  font-family: inherit; /* 폰트를 body에서 상속 */
}


/* =====================================================
   3. 재사용 유틸리티 클래스
   ===================================================== */

/*
  .container : 콘텐츠를 가운데 정렬하고 최대 너비를 제한하는 박스.
  여러 섹션에서 공통으로 사용한다.
*/
.container {
  max-width: var(--max-width);
  margin: 0 auto;   /* 좌우 auto = 가운데 정렬 */
  padding: 0 var(--spacing-md);
}

/*
  .section : 모든 섹션의 공통 위아래 여백.
*/
.section {
  padding: var(--spacing-xl) 0;
}

/* 섹션 제목 공통 스타일 */
.section__title {
  font-size: 2rem;
  font-weight: 700;
  text-align: center;
  margin-bottom: var(--spacing-xs);
  color: var(--color-text);
}

.section__subtitle {
  text-align: center;
  color: var(--color-text-light);
  font-size: 1rem;
  margin-bottom: var(--spacing-lg);
}

/* .hidden : JS에서 요소를 숨길 때 사용하는 클래스. */
.hidden {
  display: none !important;
  /*
    !important : 다른 모든 CSS 규칙보다 우선 적용.
    JS에서 classList.remove('hidden')으로 이 클래스를 지우면 요소가 다시 보인다.
  */
}

/* 스크롤 애니메이션: 초기 상태 (보이지 않음) */
.animate-on-scroll {
  opacity: 0;               /* 완전히 투명 */
  transform: translateY(60px); /* 60px 아래로 이동 (더 뚜렷한 효과) */
  transition: opacity 0.8s ease, transform 0.8s ease;
}

/* 화면에 들어왔을 때의 상태 (JS에서 이 클래스를 추가) */
.animate-on-scroll.visible {
  opacity: 1;
  transform: translateY(0); /* 원래 위치로 */
}


/*
  .page-frame : header~footer를 감싸는 래퍼.
  전체 페이지 외곽에 살짝 둥근 모서리 + 그림자를 주어 페이지 전체가
  하나의 카드처럼 보이게 한다.

  주의: 여기에 overflow: hidden을 쓰면 안 된다. overflow가 visible이 아닌
  요소는 그 자체로 "스크롤 컨테이너"가 되어, 안에 있는 header의
  position: sticky가 (뷰포트가 아니라) 이 래퍼를 기준으로 동작하게 된다.
  그런데 이 래퍼는 내부 콘텐츠보다 커지지 않아 실제로는 스크롤이
  발생하지 않으므로, sticky 계산 기준이 항상 그대로 있는 것처럼 취급되어
  header가 스크롤 시 고정되지 않고 그냥 같이 스크롤되어 사라져 버린다.
  그래서 모서리를 잘라내는 대신, header/footer 쪽에 직접 border-radius를
  주는 방식으로 같은 효과를 낸다 (아래 .header, .footer 참고).
*/
.page-frame {
  position: relative;
  margin: var(--page-frame-margin);
  border-radius: var(--page-frame-radius);
  transition: background-color var(--transition);
  /*
    body의 배경을 프레임 바깥 색으로 바꾸면서, 배경을 따로 지정하지 않은
    섹션(예: skills, contact)이 기존처럼 콘텐츠용 흰색/다크 배경을 보여줄 수
    있도록 .page-frame이 그 역할을 대신 맡는다.
  */
  background-color: var(--color-bg);
}

/*
  header는 position: sticky로 top: var(--page-frame-margin) 위치에 붙는다.
  즉 뷰포트 맨 위 0 ~ --page-frame-margin 구간은 header보다도 위에 있어서
  스크롤을 아무리 내려도 항상 빈 공간으로 남는데, 이 구간에는 덮는 요소가
  없어 스크롤되는 본문 콘텐츠(이미지·텍스트)가 그대로 비쳐 보였다.
  뷰포트에 고정된 얇은 띠를 프레임 바깥 배경색으로 깔아 그 구간을 항상
  가려서, 스크롤 중에도 본문이 비쳐 보이지 않게 한다.
*/
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: var(--page-frame-margin);
  background-color: var(--color-page-outer-bg);
  z-index: 150;
  pointer-events: none;
  transition: background-color var(--transition), height var(--transition);
}

/*
  header의 둥근 위쪽 모서리 바깥, 둥근 곡선이 시작되기 전의 네모난 빈틈에
  본문 콘텐츠가 비쳐 보이는 자국을 없애기 위한 흰색 사각형.
  header와 가로·세로 크기, 위치를 정확히 동일하게 맞춘다.

  - top/left/width/height를 header와 완전히 동일하게 맞춰, header와 정확히
    같은 자리에 같은 크기로 겹치도록 한다.
  - z-index: 50 (header의 100보다 작음) → header 바로 뒤에 깔린다. header의
    네이비 배경이 있는 부분은 이 사각형이 그 뒤에 가려 보이지 않고, header가
    border-radius 때문에 색을 칠하지 않는 네모난 모서리 구석에서만 이
    흰색이 드러나 보인다.
  - header::after(= header의 자식)로 만들지 않은 이유: header 안의 로고·메뉴
    글자는 z-index가 없는 일반 콘텐츠라서, header의 자식으로 만들면 오히려
    이 사각형이 로고·메뉴 위를 덮어버린다. body의 자식(형제 관계)으로 만들어야
    header(100)가 이 사각형(50)보다 위에 그려진다.
  - 스크롤 여부와 상관없이 페이지가 열릴 때부터 항상 보인다(.scrolled 조건 없음).
*/
body::after {
  content: '';
  position: fixed;
  top: var(--page-frame-margin);
  left: var(--page-frame-margin);
  width: calc(100% - (var(--page-frame-margin) * 2));
  height: var(--header-height);
  /* 콘텐츠 흰색(--color-bg)이 아니라 페이지 프레임 바깥 배경색으로 맞춘다 */
  background-color: var(--color-page-outer-bg);
  z-index: 50;
  pointer-events: none;
  transition: background-color var(--transition);
}


/* =====================================================
   버튼 스타일 (BEM 방식)

   BEM (Block Element Modifier):
   - Block   : .btn (독립적인 컴포넌트)
   - Element : .btn__icon (Block의 자식 요소, __ 사용)
   - Modifier: .btn--primary (Block의 변형, -- 사용)
   ===================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--spacing-xs);
  padding: 0.75rem 1.5rem;
  border-radius: var(--border-radius);
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  transition: all var(--transition);
  /*
    transition: all : 모든 변경 가능한 CSS 속성에 전환 효과 적용.
    var(--transition) = 0.3s ease
  */
}

/* 채워진 버튼 (골드 포인트) */
.btn--primary {
  background-color: var(--color-primary);
  color: var(--color-on-primary);
}

.btn--primary:hover {
  /*
    :hover : 마우스를 올렸을 때 적용되는 CSS 가상 클래스(pseudo-class).
    다른 가상 클래스: :focus, :active, :visited, :nth-child() 등
  */
  background-color: var(--color-primary-dark);
  transform: translateY(-2px);
  /*
    transform: translateY(-2px) : 요소를 2px 위로 올린다.
    hover 시 떠오르는 효과를 준다.
  */
  box-shadow: 0 4px 15px rgba(201, 169, 97, 0.4);
}

/* 테두리만 있는 버튼 (네이비 배경 위에서 골드 테두리로 표시) */
.btn--outline {
  background-color: transparent;
  color: var(--color-primary);
  border: 2px solid var(--color-primary);
}

.btn--outline:hover {
  background-color: var(--color-primary);
  color: var(--color-on-primary);
}

/* 전체 너비 버튼 */
.btn--full {
  width: 100%;
  justify-content: center;
}


/* =====================================================
   4. HEADER & NAVIGATION
   ===================================================== */
.header {
  position: sticky;
  /*
    position: sticky : 스크롤해도 화면 상단에 붙어있는다.
    position 속성 종류:
    - static   : 기본값. 문서 흐름대로 배치.
    - relative : 원래 위치를 기준으로 이동. 공간은 유지.
    - absolute : 가장 가까운 positioned 부모를 기준으로 배치. 공간 없음.
    - fixed    : 뷰포트(화면)를 기준으로 배치. 스크롤해도 고정.
    - sticky   : 스크롤 위치에 따라 relative ↔ fixed 전환.

    페이지 전체를 감싸는 .page-frame이 둥근 모서리 + 그림자를 갖도록
    바뀌면서, header도 fixed(뷰포트 기준) 대신 sticky로 바꿔
    .page-frame의 둥근 상단 모서리 안쪽에 자연스럽게 붙어있게 했다.

    top을 0이 아니라 --page-frame-margin으로 주는 이유:
    top:0이면 스크롤 시 header가 뷰포트 맨 위에 완전히 딱 붙어버려
    프레임 바깥 배경(outer-bg)의 여백이 사라지고 "떠있는 카드" 느낌이
    깨진다. margin만큼 띄워서 스크롤 중에도 프레임 여백이 유지되게 한다.
  */
  top: var(--page-frame-margin);
  width: 100%;
  height: var(--header-height);
  /*
    .page-frame이 더 이상 overflow: hidden으로 모서리를 잘라주지 않으므로
    (sticky가 깨지기 때문), 페이지 맨 위에 놓이는 header 자체에 같은
    반지름의 border-radius를 직접 줘서 프레임의 둥근 위쪽 모서리를 만든다.
  */
  border-top-left-radius: var(--page-frame-radius);
  border-top-right-radius: var(--page-frame-radius);
  /*
    디자인 스타일 이미지처럼 헤더는 라이트/다크 모드와 무관하게
    항상 진한 네이비 배경을 유지한다.
  */
  background-color: rgba(12, 28, 55, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--color-navy-border);
  z-index: 100;
  /*
    z-index : 요소의 쌓임 순서. 숫자가 클수록 위에 표시된다.
    position이 static이 아닌 경우에만 동작한다.
  */
  transition: background-color var(--transition), box-shadow var(--transition),
              border-color var(--transition), backdrop-filter var(--transition);
}

/* 스크롤 60px 이상 시 그림자/테두리를 강조 (JS에서 .scrolled 클래스 추가) */
.header.scrolled {
  border-bottom: 2px solid var(--color-primary);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
}


.nav {
  display: flex;
  /*
    display: flex : Flexbox 레이아웃 활성화.
    자식 요소들이 기본적으로 가로로 나열된다.

    Flexbox 핵심 개념:
    - 컨테이너(부모)와 아이템(자식)으로 구성.
    - justify-content : 가로 축(주축) 정렬
    - align-items     : 세로 축(교차축) 정렬
    - flex-wrap       : 줄바꿈 여부
    - gap             : 아이템 사이 간격
  */
  align-items: center;        /* 세로 중앙 정렬 */
  justify-content: space-between; /* 첫 아이템은 왼쪽, 마지막은 오른쪽 끝으로 */
  height: var(--header-height);
}

.nav__logo {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-on-navy);
}

.nav__logo-sub {
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--color-on-navy-light);
}

.nav__menu {
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  /*
    gap : Flexbox/Grid에서 아이템 사이의 간격.
    margin 대신 gap을 사용하면 마지막 아이템에 불필요한 여백이 생기지 않는다.
  */
}

.nav__link {
  color: var(--color-on-navy);
  font-weight: 500;
  padding: var(--spacing-xs) 0;
  position: relative; /* ::after 가상 요소의 기준점 */
  transition: color var(--transition);
}

/*
  ::after : 가상 요소(Pseudo-element). 실제 HTML 없이 CSS만으로 요소를 추가한다.
  네비게이션 링크 아래 밑줄 애니메이션 효과.
*/
.nav__link::after {
  content: '';         /* 가상 요소는 반드시 content 속성이 필요 (비워도 됨) */
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0;            /* 처음에는 너비 0 (보이지 않음) */
  height: 2px;
  background-color: var(--color-primary);
  transition: width var(--transition);
}

.nav__link:hover::after {
  width: 100%; /* hover 시 너비가 100%로 늘어남 = 밑줄이 그어지는 효과 */
}

.nav__link:hover {
  color: var(--color-primary);
}

/* 다크 모드 토글 버튼 */
.theme-toggle {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;   /* 50% = 원형 */
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(255, 255, 255, 0.08);
  color: var(--color-on-navy);
  transition: all var(--transition);
}

.theme-toggle:hover {
  background-color: var(--color-primary);
  color: var(--color-on-primary);
}

/* 햄버거 버튼 (모바일) */
.nav__hamburger {
  display: none; /* 기본적으로 숨김. 모바일에서만 표시 */
  flex-direction: column;
  gap: 5px;
  padding: var(--spacing-xs);
}

.nav__hamburger span {
  display: block;
  width: 25px;
  height: 3px;
  background-color: var(--color-on-navy);
  border-radius: 3px;
  transition: all var(--transition);
}

/* 햄버거 → X 변환 애니메이션 (active 클래스가 추가될 때) */
.nav__hamburger.active span:nth-child(1) {
  /*
    :nth-child(n) : n번째 자식 요소 선택.
    :nth-child(1) = 첫 번째 자식
    :nth-child(2) = 두 번째 자식
    :nth-child(odd) = 홀수 번째 자식
    :nth-child(even) = 짝수 번째 자식
  */
  transform: rotate(45deg) translate(5px, 6px);
  /* rotate : 회전 (45도) */
  /* translate : 이동 (가로 5px, 세로 6px) */
}

.nav__hamburger.active span:nth-child(2) {
  opacity: 0; /* 가운데 줄 숨기기 */
}

.nav__hamburger.active span:nth-child(3) {
  transform: rotate(-45deg) translate(5px, -6px);
}


/* =====================================================
   5. HERO 섹션
   ===================================================== */
.hero {
  min-height: 100vh;
  /*
    min-height: 100vh : 최소 높이가 뷰포트(화면) 높이의 100%.
    vh = viewport height. 100vh = 화면 전체 높이.
  */
  display: flex;
  align-items: center;
  padding-top: var(--header-height); /* 고정 헤더 아래에서 시작 */
  /*
    디자인 스타일 이미지처럼 히어로는 라이트/다크 모드와 무관하게
    항상 진한 네이비 그라디언트 배경을 유지한다.
  */
  background: linear-gradient(135deg, var(--color-navy) 0%, var(--color-navy-soft) 100%);
  position: relative;
  /*
    overflow: hidden : 우측에 깔리는 지구·위성 배경 이미지가
    히어로 섹션 밖으로(가로 스크롤 유발) 새어 나가지 않도록 잘라낸다.
  */
  overflow: hidden;
}

/*
  히어로 상단 우측 배경 (지구+위성 참고 이미지).
  가장자리가 투명하게 페더링된 PNG를 히어로 섹션 우측에 배치해
  텍스트 영역을 가리지 않으면서 네이비 배경과 자연스럽게 섞이도록 한다.
*/
.hero::before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 62%;
  height: 78%;
  /*
    background-size: contain : 이미지를 잘라내지 않고 비율 그대로 축소해
    박스 안에 맞춘다. cover를 쓰면 이미지가 과하게 확대되며 잘려서
    지구 표면이 CTA 버튼 영역까지 침범해 보이는 문제가 있었다.
  */
  background-image: url('../images/hero-space-bg.webp?v=5');
  background-size: contain;
  background-position: top right;
  background-repeat: no-repeat;
  z-index: 0;
  pointer-events: none;
}

.hero__container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-xl);
  position: relative;
  z-index: 1;
  /* 배경 이미지(.hero::before, z-index:0)보다 위에 그려지도록 */
}

.hero__text {
  flex: 1;
  /*
    flex: 1 : 남은 공간을 모두 차지하라는 의미.
    flex는 flex-grow, flex-shrink, flex-basis의 단축 속성.
    flex: 1 = flex-grow: 1; flex-shrink: 1; flex-basis: 0%;
  */
}

.hero__eyebrow {
  font-size: 1.1rem;
  color: var(--color-on-navy-light);
  margin-bottom: var(--spacing-sm);
}

.hero__title {
  font-size: clamp(2rem, 5vw, 3.5rem);
  /*
    clamp(최솟값, 선호값, 최댓값) : 반응형 폰트 크기.
    화면이 작으면 최솟값(2rem), 크면 최댓값(3.5rem) 사이에서 5vw로 유동적으로 변함.
    vw = viewport width. 1vw = 화면 너비의 1%.
  */
  font-weight: 700;
  line-height: 1.2;
  margin-bottom: var(--spacing-md);
  color: var(--color-on-navy);
  /*
    "·"로 이어진 긴 구간은 띄어쓰기가 없어 word-break: keep-all만으로는
    줄바꿈 지점을 찾지 못해 화면 밖으로 넘칠 수 있다.
    overflow-wrap: anywhere로 좁은 화면에서도 항상 컨테이너 안에서 줄바꿈되게 한다.
  */
  overflow-wrap: anywhere;
}

.hero__name {
  display: inline-block;
  font-weight: 700;
  color: var(--color-primary);
}

.hero__subtitle {
  font-size: 1.1rem;
  color: var(--color-on-navy-light);
  margin-bottom: var(--spacing-lg);
  line-height: 1.8;
}

.hero__buttons {
  display: flex;
  gap: var(--spacing-sm);
  flex-wrap: wrap;
  /*
    flex-wrap: wrap : 공간이 부족하면 자동으로 다음 줄로 내려간다.
    기본값 nowrap은 한 줄을 유지하며 요소가 넘치거나 줄어든다.
  */
}

.hero__image {
  flex: 0 0 350px;
  /*
    flex: 0 0 350px :
    - flex-grow: 0   (늘어나지 않음)
    - flex-shrink: 0 (줄어들지 않음)
    - flex-basis: 350px (기본 너비 350px)
    → 항상 정확히 350px를 유지한다.
  */
}

.hero__img {
  width: 100%;
  aspect-ratio: 1 / 1;
  /*
    aspect-ratio: 1 / 1 : 가로:세로 비율 1:1 = 정사각형 유지.
    너비에 맞춰 높이가 자동으로 설정된다.
  */
  object-fit: cover;
  object-position: center top;
  /*
    object-fit: cover : 이미지를 잘라내서 요소를 꽉 채운다.
    이미지 비율을 유지하면서 빈 공간 없이 채운다.
    contain은 이미지를 잘라내지 않고 전체를 보여준다 (여백 생길 수 있음).
    object-position: center top : 크롭 기준점을 위쪽으로 설정해 머리가 잘리지 않게 한다.
  */
  border-radius: 50%;
  border: 3px solid rgba(201, 169, 97, 0.5);
  box-shadow: 0 0 0 10px rgba(201, 169, 97, 0.08), 0 20px 60px rgba(0, 0, 0, 0.45);
}


/* =====================================================
   7. SKILLS 섹션
   ===================================================== */
.skills__container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  /*
    auto-fit + minmax : 카드 5개가 화면 너비에 맞춰 2~3열로 자동 배치된다.
  */
  gap: var(--spacing-lg);
}

.skills__card {
  background-color: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius);
  /* 상단 타이틀 바가 카드 모서리에 맞춰 둥글게 보이도록 카드 자체 패딩은 없애고
     내부 body에 패딩을 준다 (디자인 스타일 이미지의 카드 헤더 바 구조 참고). */
  padding: 0;
  overflow: hidden;
  box-shadow: 0 4px 6px var(--color-shadow);
  transition: transform var(--transition), box-shadow var(--transition);
}

.skills__card:hover {
  transform: translateY(-5px); /* 위로 5px 이동 (떠오르는 효과) */
  box-shadow: 0 10px 25px var(--color-shadow);
}

/* 카드 상단 네이비 타이틀 바 (디자인 스타일 이미지의 카드 헤더 참고) */
.skills__card-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  padding: var(--spacing-md) var(--spacing-lg);
  background-color: var(--color-navy-card);
}

.skills__card-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.skills__category-icon {
  font-size: 1.3rem;
  color: var(--color-primary);
  flex-shrink: 0;
}

.skills__category {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--color-on-navy);
}

.skills__features {
  padding: var(--spacing-lg);
  padding-top: var(--spacing-md);
}

/* 도메인 역량 목록 (숙련도 퍼센트 막대 대신 기능 목록으로 표시) */
.skills__features {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.skills__features li {
  position: relative;
  padding-left: 1.1rem;
  color: var(--color-text-light);
  font-size: 0.92rem;
  line-height: 1.5;
}

.skills__features li::before {
  content: '•';
  position: absolute;
  left: 0;
  color: var(--color-primary);
  font-weight: 700;
}

/*
  상태 배지 (status-badge)
  숙련도 퍼센트 대신 "구현 완료 / 검증 진행 중 / 시범 운용" 같은
  실제 진행 상태를 표시한다. Skills 카드와 Projects 카드에서 공통으로 쓴다.
*/
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.75rem;
  border-radius: 2rem;
  font-size: 0.78rem;
  font-weight: 600;
  white-space: nowrap;
}

/*
  배지는 항상 네이비 배경(카드 헤더 바 · 분석 사례 카드) 위에 올라가므로
  옅은 틴트 대신 또렷한 필 배경 + 밝은 글자색을 사용한다.
*/
.status-badge--done {
  background-color: rgba(34, 197, 94, 0.22);
  color: #4ade80;
}

.status-badge--verifying {
  background-color: rgba(234, 179, 8, 0.22);
  color: #fbbf24;
}

.status-badge--pilot {
  background-color: rgba(201, 169, 97, 0.22);
  color: var(--color-primary);
}


/* =====================================================
   8. PROJECTS 섹션
   ===================================================== */
/*
  디자인 스타일 이미지의 "분석 사례" 섹션은 슬레이트 블루 배경 위에
  네이비 카드가 놓이는 구조라 라이트/다크 모드와 무관하게 고정색을 쓴다.
*/
.projects {
  background-color: var(--color-slate);
}

.projects .section__title,
.projects .section__subtitle {
  color: var(--color-on-navy);
}

.projects .section__subtitle {
  color: var(--color-on-navy-light);
}

.projects__subheading {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--color-on-navy);
  margin-bottom: var(--spacing-xs);
}

.projects__subnote {
  color: var(--color-on-navy-light);
  font-size: 0.9rem;
  margin-bottom: var(--spacing-md);
}

.projects__grid--cases {
  margin-bottom: var(--spacing-sm);
}

/*
  Grid를 사용한 카드 레이아웃 (반응형 자동 조절)
*/
.projects__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  /*
    auto-fit + minmax : 가장 강력한 반응형 Grid 패턴.
    - minmax(300px, 1fr) : 최소 300px, 최대 1fr의 너비를 가진 열
    - auto-fit : 컨테이너 너비에 맞게 열 수를 자동으로 결정
    → 넓으면 3열, 좁으면 2열, 더 좁으면 1열로 자동 변환!
    미디어 쿼리 없이도 반응형이 된다.
  */
  gap: var(--spacing-md);
}

/* JS로 생성되는 프로젝트 카드 스타일 (네이비 카드, 슬레이트 섹션 배경 위) */
.project-card {
  background-color: var(--color-slate-card);
  border: 1px solid var(--color-navy-border);
  border-radius: var(--border-radius);
  padding: var(--spacing-md);
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
  transition: transform var(--transition), box-shadow var(--transition);
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
}

.project-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
}

.project-card__title {
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--color-on-navy);
}

.project-card__desc {
  font-size: 0.9rem;
  color: var(--color-on-navy-light);
  flex: 1; /* 설명이 카드 안에서 최대한 공간을 차지 → 버튼이 항상 아래 */
}

.project-card__desc small {
  display: block;
  margin-top: 0.5rem;
  color: var(--color-on-navy-light);
  font-size: 0.78rem;
}

.project-card__footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.project-card__footer a {
  color: var(--color-primary);
  font-weight: 600;
  font-size: 0.9rem;
}

.project-card__footer a:hover {
  color: var(--color-primary-dark);
}

/* =====================================================
   7-1. VISUALLSAT 소개영상 (Hero 바로 아래)
   ===================================================== */
.visuallsat-video-top {
  background-color: var(--color-bg-alt);
  text-align: center;
}

.visuallsat-video-top__title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--color-text);
  margin-bottom: var(--spacing-md);
}

.visuallsat-video-top__player {
  display: block;
  width: 100%;
  max-width: 900px;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  margin: 0 auto;
  border-radius: var(--border-radius);
  box-shadow: 0 10px 30px var(--color-shadow);
}


/* =====================================================
   8-1. VISUALLSAT 소개 섹션
   디자인 스타일 이미지의 "통합 플랫폼 개요" 섹션처럼
   라이트/다크 모드와 무관하게 항상 네이비 배경을 유지한다.
   ===================================================== */
.visuallsat {
  background-color: var(--color-navy);
}

.visuallsat .section__title {
  color: var(--color-on-navy);
}

.visuallsat .section__subtitle {
  color: var(--color-on-navy-light);
}

.visuallsat__showcase {
  display: flex;
  align-items: center;
  gap: var(--spacing-xl);
}

.visuallsat__poster-link {
  flex: 0 0 46%;
  display: block;
  border-radius: var(--border-radius);
  overflow: hidden;
  border: 1px solid var(--color-navy-border);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
  transition: transform var(--transition), box-shadow var(--transition);
}

.visuallsat__poster-link:hover {
  transform: translateY(-6px) scale(1.01);
  box-shadow: 0 15px 40px rgba(0, 0, 0, 0.5);
}

.visuallsat__poster {
  width: 100%;
  display: block;
}

.visuallsat__info {
  flex: 1;
}

.visuallsat__desc {
  color: var(--color-on-navy-light);
  font-size: 1.05rem;
  line-height: 1.8;
  margin-bottom: var(--spacing-lg);
}

.visuallsat__stats {
  display: flex;
  gap: var(--spacing-lg);
  margin-bottom: var(--spacing-lg);
  flex-wrap: wrap;
}

.visuallsat__stats li {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  max-width: 220px;
}

.visuallsat__stats strong {
  /* 디자인 스타일 이미지의 "30,000+"처럼 크고 굵은 골드 숫자로 강조 */
  font-size: 2.25rem;
  font-weight: 700;
  color: var(--color-primary);
  line-height: 1.15;
}

.visuallsat__stats span {
  font-size: 0.85rem;
  color: var(--color-on-navy-light);
}

.visuallsat__stat-basis {
  font-size: 0.75rem;
  color: var(--color-on-navy-light);
  opacity: 0.85;
}

/* 수치 근거 안내 박스 */
.visuallsat__basis-note {
  background-color: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius);
  padding: var(--spacing-md);
  margin-bottom: var(--spacing-lg);
}

.visuallsat__basis-note-title {
  font-weight: 700;
  color: var(--color-text);
  margin-bottom: var(--spacing-xs);
}

.visuallsat__basis-note ul {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding-left: 1.1rem;
  list-style: disc;
}

.visuallsat__basis-note li {
  color: var(--color-text-light);
  font-size: 0.85rem;
  line-height: 1.6;
}

.visuallsat__buttons {
  display: flex;
  gap: var(--spacing-sm);
  flex-wrap: wrap;
}

.visuallsat__youtube-note {
  margin-top: var(--spacing-sm);
  font-size: 0.9rem;
  color: var(--color-on-navy-light);
}

.visuallsat__youtube-note a {
  color: var(--color-primary);
  text-decoration: underline;
}

.visuallsat__youtube-note a:hover {
  color: var(--color-primary-dark);
}


/* =====================================================
   9. CONTACT 섹션
   ===================================================== */
.contact {
  background-color: var(--color-bg-alt);
}

.contact__container {
  display: grid;
  grid-template-columns: 1fr 2fr;
  /* 정보 영역(1fr) : 폼 영역(2fr) = 1:2 비율 */
  gap: var(--spacing-xl);
  align-items: stretch;
  /*
    align-items: stretch : 좌측 연락처 카드가 우측 폼과 같은 높이로 늘어나,
    카드 안의 내용을 세로 중앙에 배치해 균형 잡힌 2단 레이아웃을 만든다.
  */
}

.contact__info {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--spacing-md);
}

.contact__card {
  background-color: var(--color-card-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--border-radius);
  padding: var(--spacing-xl) var(--spacing-md);
  text-align: center;
  box-shadow: 0 4px 6px var(--color-shadow);
}

.contact__icon {
  font-size: 2.5rem;
  color: var(--color-primary);
  margin-bottom: var(--spacing-sm);
  display: block;
}

.contact__card h3 {
  margin-bottom: 0.5rem;
  font-weight: 600;
  font-size: 1.15rem;
}

.contact__card a {
  color: var(--color-primary);
  font-size: 1rem;
  font-weight: 500;
}

/* 폼 스타일 */
.contact__form {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

.form__group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.form__label {
  font-weight: 500;
  font-size: 0.95rem;
}

.form__input {
  padding: 0.875rem var(--spacing-sm);
  border: 2px solid var(--color-border);
  border-radius: var(--border-radius);
  background-color: var(--color-bg);
  color: var(--color-text);
  font-size: 1rem;
  font-family: inherit;
  transition: border-color var(--transition);
  width: 100%;
}

.form__input:focus {
  /*
    :focus : 요소가 포커스(클릭하거나 Tab키로 이동)되었을 때.
  */
  outline: none; /* 기본 outline 제거 */
  border-color: var(--color-primary);
}

.form__textarea {
  resize: vertical;
  /*
    resize : 사용자가 요소 크기를 조절할 수 있는지 여부.
    vertical = 세로 방향으로만 크기 조절 가능.
    none = 불가, horizontal = 가로만, both = 양방향
  */
  min-height: 120px;
}

/* 유효성 검사 에러 상태 */
.form__input.error {
  border-color: #ef4444; /* 빨간색 */
}

.form__error {
  color: #ef4444;
  font-size: 0.85rem;
  min-height: 1.2rem; /* 에러가 없을 때도 공간 확보 → 레이아웃 흔들림 방지 */
}

/* 전송 성공 메시지 */
.form__success {
  text-align: center;
  color: #22c55e;  /* 초록색 */
  font-weight: 600;
  padding: var(--spacing-md);
  background-color: rgba(34, 197, 94, 0.1);
  border-radius: var(--border-radius);
}


/* =====================================================
   10. FOOTER
   ===================================================== */
/*
  디자인 스타일 이미지처럼 푸터도 헤더와 동일하게
  라이트/다크 모드와 무관하게 항상 네이비 배경을 유지한다.
*/
.footer {
  background-color: var(--color-navy);
  border-top: 1px solid var(--color-navy-border);
  padding: var(--spacing-lg) 0;
  /* 페이지 맨 아래에 놓이므로 .page-frame의 둥근 아래쪽 모서리를 직접 만든다 */
  border-bottom-left-radius: var(--page-frame-radius);
  border-bottom-right-radius: var(--page-frame-radius);
}

.footer__container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--spacing-sm);
}

.footer__copy {
  color: var(--color-on-navy-light);
  font-size: 0.9rem;
}

.footer__socials {
  display: flex;
  gap: var(--spacing-sm);
}

.footer__social {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--color-navy-border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-on-navy);
  font-size: 1.1rem;
  transition: all var(--transition);
}

.footer__social:hover {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-on-primary);
  transform: translateY(-3px);
}

.footer__visitors {
  display: flex;
  align-items: center;
}

.footer__visitors img {
  height: 1.4rem;
  border-radius: 4px;
}


/* =====================================================
   11. 스크롤 탑 버튼
   ===================================================== */
.scroll-top {
  position: fixed; /* 화면에 고정 */
  bottom: 2rem;
  right: 2rem;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background-color: var(--color-primary);
  color: var(--color-on-primary);
  font-size: 1.2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 15px rgba(201, 169, 97, 0.4);
  transition: all var(--transition);
  z-index: 99;
}

.scroll-top:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(201, 169, 97, 0.5);
}


/* =====================================================
   12. 반응형 디자인 (미디어 쿼리)

   모바일 퍼스트(Mobile First) 전략:
   - 기본 스타일을 모바일용으로 작성
   - min-width 미디어 쿼리로 큰 화면 스타일을 추가

   브레이크포인트:
   - 768px  : 태블릿
   - 1024px : 데스크톱
   ===================================================== */

/*
  @media 규칙: 특정 조건(화면 크기 등)에서만 적용되는 CSS.
  min-width: 768px = 화면 너비가 768px 이상일 때 적용.
*/

/* ===== 모바일 기본 (0px ~ 767px) ===== */

/* 모바일: 햄버거 버튼 표시, 메뉴 숨김 */
@media (max-width: 767px) {
  /*
    max-width: 767px = 화면 너비가 767px 이하일 때 적용.
  */

  /* 모바일에서는 좁은 화면 폭을 더 확보하도록 프레임 여백·모서리를 살짝 줄인다 */
  :root {
    --page-frame-margin: 1rem;
    --page-frame-radius: 0.85rem;
  }

  .nav__hamburger {
    display: flex; /* 햄버거 버튼 표시 */
  }

  .nav__menu {
    /* 모바일 드롭다운 메뉴 */
    position: fixed;
    /* header가 --page-frame-margin만큼 아래에서 시작하므로 그만큼 더해준다 */
    top: calc(var(--header-height) + var(--page-frame-margin));
    left: 0;
    width: 100%;
    background-color: var(--color-navy);
    border-bottom: 1px solid var(--color-navy-border);
    flex-direction: column; /* 세로 배치 */
    padding: var(--spacing-md) 0;

    /* 처음에 화면 위로 숨기기 */
    transform: translateY(-100%);
    opacity: 0;
    pointer-events: none;
    /*
      pointer-events: none : 클릭, hover 등 마우스 이벤트를 무시.
      숨겨진 메뉴를 클릭 불가 상태로 만든다.
    */
    transition: transform var(--transition), opacity var(--transition);
  }

  /* 햄버거 클릭 후 메뉴가 열릴 때 (JS에서 active 클래스 추가) */
  .nav__menu.active {
    transform: translateY(0); /* 원래 위치로 */
    opacity: 1;
    pointer-events: all; /* 클릭 가능 */
  }

  /* 모바일: Hero 섹션을 세로로 쌓기 */
  .hero__container {
    flex-direction: column;
    /*
      align-items: center(기본값)를 그대로 두면 flex-direction이 column일 때
      교차축(가로)이 stretch가 아니라 내용물 너비만큼만 차지하게 되어,
      hero__text가 화면 너비만큼 줄어들지 못하고 h1 텍스트가 옆으로 넘친다.
      stretch로 바꿔 hero__text가 컨테이너 전체 너비를 채우도록 한다.
    */
    align-items: stretch;
    text-align: center;
  }

  .hero__text {
    /*
      flex 아이템은 기본적으로 min-width: auto를 가져서, 내부 텍스트의
      "줄바꿈 없는 최소 너비"보다 작게 줄어들지 않는다. 그러면
      overflow-wrap을 걸어도 컨테이너 밖으로 넘칠 수 있다.
      min-width: 0으로 이 제한을 없애 텍스트가 실제 화면 너비 안에서
      줄바꿈되도록 한다.
    */
    min-width: 0;
  }

  .hero__image {
    flex: unset; /* flex 설정 초기화 */
    align-self: center; /* 부모 align-items: stretch와 무관하게 이미지는 가운데 정렬 유지 */
    width: 200px;
    order: -1;
    /*
      order : Flexbox 아이템의 배치 순서.
      기본값은 0. 숫자가 작을수록 먼저 배치.
      -1 = 이미지를 텍스트보다 먼저(위에) 배치.
    */
  }

  .hero__buttons {
    justify-content: center;
  }

  /*
    모바일: 세로로 쌓이는 레이아웃에서는 우측 정렬된 배경이
    사진 뒤가 아니라 엉뚱한 위치(텍스트 옆)에 걸쳐 보이므로
    화면 상단 전체 폭에 은은하게 깔리도록 조정한다.
  */
  .hero::before {
    width: 100%;
    height: 60%;
    background-position: center top;
    opacity: 0.7;
  }

  /* 모바일: Skills 1열 */
  .skills__container {
    grid-template-columns: 1fr;
  }

  /* 모바일: Contact 1열 */
  .contact__container {
    grid-template-columns: 1fr;
  }

  /* 모바일: VisuAllSat 세로 배치 */
  .visuallsat__showcase {
    flex-direction: column;
  }

  .visuallsat__poster-link {
    flex: unset;
    width: 100%;
  }

  /* 모바일: Footer 세로 정렬 */
  .footer__container {
    flex-direction: column;
    gap: var(--spacing-sm);
    text-align: center;
  }
}

/* ===== 태블릿 (768px ~ 1023px) ===== */
@media (min-width: 768px) and (max-width: 1023px) {
  .hero__image {
    flex: 0 0 280px;
  }

  .contact__container {
    grid-template-columns: 1fr;
  }
}

/* ===== 데스크톱 (1024px 이상) ===== */
@media (min-width: 1024px) {
  /* 데스크톱에서는 기본 스타일(위에서 작성한 것)이 그대로 적용 */
}