/*
 * 상호작용·전환 효과.
 *
 * 원본 포털에 없던 추가분입니다. styles.css 는 원본 global.css 의 충실한 이식본으로
 * 남겨 두고, 새 효과만 이 파일에서 관리합니다. 이 파일 링크 한 줄만 빼면 사이트는
 * 정적인 원래 모습으로 되돌아갑니다.
 *
 * ── 브라우저 지원 원칙 ────────────────────────────────────────────
 * 원본 프로젝트가 정한 지원 기준(docs/operations/release-candidate.md)은
 * Chromium · Firefox · WebKit 3개 엔진입니다. 따라서 이 파일은 한 엔진에만 있는
 * 기능을 쓰지 않고, 세 엔진에서 같은 결과가 나오는 것만 씁니다.
 *
 * 의도적으로 쓰지 않은 것:
 *   @view-transition (문서 간 전환)
 *     → Chrome/Edge 126+, Safari 18.2+ 는 되지만 Firefox 는 아직 플래그 뒤입니다.
 *       Firefox 만 효과가 빠지면 "지원 브라우저에서 동일하게 보인다"는 기준을
 *       못 지키므로, 세 엔진에서 같이 동작하는 JS 페이드(app.js)로 대체했습니다.
 *   ::details-content 의 content-visibility 전환
 *     → 선택자 자체는 2025-09 Baseline(Chrome 131+/Firefox 143+/Safari 18.4+)이지만,
 *       닫힘 애니메이션에 필요한 content-visibility 전환 동작은 엔진마다 차이가
 *       있습니다. 메뉴 닫힘은 app.js 가 클래스로 제어해 세 엔진에서 동일하게 만듭니다.
 *   height: auto 애니메이션 (interpolate-size / calc-size)
 *     → Chromium 전용입니다. 높이 대신 transform·opacity 만 씁니다.
 *
 * 쓰는 기능은 모두 세 엔진 공통입니다: CSS transition/animation, transform,
 * opacity, custom property, :hover/:focus-visible, prefers-reduced-motion.
 *
 * ── 성능 ─────────────────────────────────────────────────────────
 * transform 과 opacity 만 애니메이션해 레이아웃 리플로우가 없습니다.
 * 인라인 style 을 쓰지 않아 CSP style-src 'self' 를 유지합니다.
 */

/* ─── 1. 페이지 사이 이동 ─────────────────────────────────────────
 * app.js 가 내부 링크 클릭을 가로채 <html> 에 data-page-leaving 을 붙인 뒤
 * 이동합니다. 도착한 페이지의 등장은 기존 스크롤 등장 모션이 담당합니다.
 * JavaScript 가 없거나 실패하면 링크는 평소처럼 즉시 이동합니다.
 */

html[data-page-leaving] main {
  opacity: 0;
  transform: translateY(-8px);
  transition:
    opacity 150ms ease,
    transform 150ms ease;
}

/* ─── 1-2. 진입 시 텍스트 순차 등장 ──────────────────────────────
 * 히어로 블록이 드러나는 순간, 그 안의 눈썹문구 → 제목 → 본문 → 버튼이 차례로
 * 올라옵니다. 블록 자체는 흐림·불투명도만 바꾸고(direction="fade") 실제 움직임은
 * 자식 요소가 담당해, 두 겹으로 움직여 산만해지는 것을 막습니다.
 *
 * 지연은 브랜드 stagger(60ms)의 배수를 씁니다. nth-child 로 지정하므로 마크업에
 * 인라인 style 이 필요 없습니다(CSP 유지).
 */

@keyframes text-rise {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
}

/*
 * data-reveal-text 가 붙은 블록이 드러나면 그 직계 자식이 차례로 올라옵니다.
 * 클래스 이름에 묶지 않고 마커를 쓰므로, 새 블록에 마커만 붙이면 적용됩니다.
 */
[data-reveal-text][data-revealed="true"] > * {
  animation: text-rise var(--duration-dynamic) var(--reveal-easing) both;
}

[data-reveal-text][data-revealed="true"] > *:nth-child(1) { animation-delay: 0ms; }
[data-reveal-text][data-revealed="true"] > *:nth-child(2) { animation-delay: calc(var(--stagger-dynamic) * 1); }
[data-reveal-text][data-revealed="true"] > *:nth-child(3) { animation-delay: calc(var(--stagger-dynamic) * 2); }
[data-reveal-text][data-revealed="true"] > *:nth-child(4) { animation-delay: calc(var(--stagger-dynamic) * 3); }
[data-reveal-text][data-revealed="true"] > *:nth-child(n + 5) { animation-delay: calc(var(--stagger-dynamic) * 4); }

/* ─── 2. 모바일 메뉴 열기·닫기 ────────────────────────────────────
 * <details> 는 닫힌 동안 내용이 렌더링되지 않아 transition 이 걸리지 않습니다.
 * 그래서 열 때는 keyframes(새로 표시되는 요소에도 동작), 닫을 때는 app.js 가
 * data-closing 을 붙여 역방향 keyframes 를 재생한 뒤 실제로 닫습니다.
 */

@keyframes menu-open {
  from {
    opacity: 0;
    transform: translateY(-10px) scale(0.97);
  }
}

@keyframes menu-close {
  to {
    opacity: 0;
    transform: translateY(-8px) scale(0.98);
  }
}

@keyframes item-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
}

.mobile-menu > nav {
  transform-origin: top right;
}

.mobile-menu[open]:not([data-closing]) > nav {
  animation: menu-open 240ms var(--reveal-easing) both;
}

.mobile-menu[open][data-closing] > nav {
  animation: menu-close 170ms ease both;
}

/* 메뉴 항목이 위에서부터 차례로 들어옵니다. */
.mobile-menu[open]:not([data-closing]) > nav > a {
  animation: item-in 260ms var(--reveal-easing) both;
}

.mobile-menu[open]:not([data-closing]) > nav > a:nth-child(2) { animation-delay: 30ms; }
.mobile-menu[open]:not([data-closing]) > nav > a:nth-child(3) { animation-delay: 60ms; }
.mobile-menu[open]:not([data-closing]) > nav > a:nth-child(4) { animation-delay: 90ms; }
.mobile-menu[open]:not([data-closing]) > nav > a:nth-child(5) { animation-delay: 120ms; }
.mobile-menu[open]:not([data-closing]) > nav > a:nth-child(6) { animation-delay: 150ms; }
.mobile-menu[open]:not([data-closing]) > nav > a:nth-child(n + 7) { animation-delay: 170ms; }

/* 햄버거 3선 → X. 닫는 중에는 다시 3선으로 돌아갑니다. */
.mobile-menu summary span {
  transition:
    transform 240ms var(--reveal-easing),
    opacity 160ms ease;
}

.mobile-menu[open]:not([data-closing]) summary span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.mobile-menu[open]:not([data-closing]) summary span:nth-child(2) {
  opacity: 0;
  transform: scaleX(0.2);
}

.mobile-menu[open]:not([data-closing]) summary span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.mobile-menu summary {
  transition:
    border-color 180ms ease,
    background-color 180ms ease;
}

.mobile-menu summary:hover {
  border-color: var(--wisdom-bronze);
}

/* ─── 3. 카드 호버 ────────────────────────────────────────────────
 * .feature-card / .principle-grid / .insight-grid 는 1px 간격 그리드 위에 있고
 * 그 간격이 테두리처럼 보입니다. 여기서 transform 을 주면 간격이 벌어져 디자인이
 * 깨지므로 배경 색조만 바꿉니다.
 */

.feature-card,
.insight-grid article,
.principle-grid article {
  transition: background-color 220ms ease;
}

.feature-card:not(.featured):hover,
.insight-grid article:hover {
  background: color-mix(in srgb, var(--wisdom-sand) 22%, var(--wisdom-ivory));
}

.feature-card.featured:hover {
  background: var(--wisdom-ink);
}

.principle-grid article:hover {
  background: color-mix(in srgb, var(--wisdom-ink) 22%, var(--wisdom-brown));
}

/* 자체 테두리와 넉넉한 간격이 있는 카드만 살짝 띄웁니다. */
.service-card,
.content-card,
.location-card {
  transition:
    transform 240ms var(--reveal-easing),
    box-shadow 240ms ease,
    border-color 240ms ease;
}

.service-card:hover,
.content-card:hover,
.location-card:hover {
  transform: translateY(-4px);
  border-color: var(--wisdom-bronze);
  box-shadow: 0 18px 44px rgba(93, 73, 54, 0.12);
}

/* ─── 4. 링크 화살표 ──────────────────────────────────────────────*/

.feature-card a span,
.service-card a span,
.service-navigator a > span:last-child {
  display: inline-block;
  transition: transform 220ms var(--reveal-easing);
}

.feature-card a:hover span,
.feature-card a:focus-visible span,
.service-card a:hover span,
.service-card a:focus-visible span {
  transform: translateX(5px);
}

.service-navigator a:hover > span:last-child,
.service-navigator a:focus-visible > span:last-child {
  transform: translate(3px, -3px);
}

.service-navigator a {
  transition:
    padding-inline 220ms var(--reveal-easing),
    background-color 220ms ease;
}

/* ─── 5. 버튼 누름 반응 ───────────────────────────────────────────*/

.button:active {
  transform: translateY(0) scale(0.98);
  transition-duration: 60ms;
}

/* ─── 6. 보조 링크 ───────────────────────────────────────────────*/

.footer-links a,
.secondary-actions a,
.office-card a {
  transition:
    color 180ms ease,
    border-color 180ms ease;
}

.secondary-actions a:hover {
  border-color: var(--wisdom-brown);
}

/* ─── 7. 폼 ──────────────────────────────────────────────────────
 * :focus-visible 외곽선(접근성)은 그대로 두고 테두리 색 전환만 더합니다.
 */

.field input:not([type="radio"]):not([type="checkbox"]),
.field select,
.field textarea {
  transition:
    border-color 180ms ease,
    background-color 180ms ease;
}

.field input:not([type="radio"]):not([type="checkbox"]):hover,
.field select:hover,
.field textarea:hover {
  border-color: var(--wisdom-bronze);
}

.form-status,
.receipt-card {
  animation: item-in 320ms var(--reveal-easing) both;
}

/* ─── 8. 브랜드 배지 ──────────────────────────────────────────────*/

.brand-mark {
  transition: transform 300ms var(--reveal-easing);
}

.brand:hover .brand-mark {
  transform: rotate(-6deg) scale(1.04);
}

/* ─── 9. 감소 설정 존중 ───────────────────────────────────────────
 * 시스템에서 "동작 줄이기"를 켜면 이 파일의 모든 효과를 끕니다.
 * app.js 도 같은 설정을 확인해 페이지 전환 페이드를 건너뜁니다.
 */

@media (prefers-reduced-motion: reduce) {
  [data-reveal-text][data-revealed="true"] > *,
  html[data-page-leaving] main,
  .mobile-menu[open] > nav,
  .mobile-menu[open] > nav > a,
  .mobile-menu summary span,
  .brand-mark,
  .form-status,
  .receipt-card {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  .service-card:hover,
  .content-card:hover,
  .location-card:hover,
  .button:active,
  .brand:hover .brand-mark {
    transform: none !important;
    box-shadow: none !important;
  }
}

/* ─── 인쇄 · PDF ──────────────────────────────────────────────────
 *
 * 등장 모션의 숨김 상태는 `opacity: 0.08 + blur(2px)` 에 ±64px 이동입니다.
 * 화면에서는 스크롤하면 풀리지만 **인쇄와 PDF 저장은 스크롤하지 않습니다.**
 * 그래서 스크롤 전에 인쇄하면 업무 분야 같은 아래쪽 본문이 유령처럼 찍히고
 * (명암비 1.16:1), 64px 이동 때문에 글자가 페이지 밖으로 잘려 나갑니다.
 *
 * 의뢰인이 업무 분야 페이지를 인쇄해 가는 경우가 실제로 있으므로,
 * 인쇄 매체에서는 모션 상태를 전부 해제합니다. 스크린샷 서비스나 보존
 * 도구처럼 스크롤하지 않는 렌더러에도 같은 문제가 있어, app.js 가
 * 일정 시간 뒤 남은 요소를 강제로 드러냅니다.
 */
@media print {
  /* transition 을 반드시 함께 끊습니다.
   *
   * CSS 캐스케이드에서 **진행 중인 transition 은 !important 보다 우선**합니다.
   * 숨김 규칙에 `transition: opacity ...` 가 걸려 있으므로, 인쇄 매체로
   * 전환되는 순간 0.08 → 1 전환이 시작되고 렌더러는 그 중간값을 찍습니다.
   * 전환을 없애야 값이 즉시 확정됩니다. */
  [data-reveal],
  html[data-page-leaving] main {
    transition: none !important;
    animation: none !important;
  }

  [data-reveal] {
    opacity: 1 !important;
    filter: none !important;
    translate: none !important;
  }

  html[data-page-leaving] main {
    opacity: 1 !important;
    transform: none !important;
  }

  /* position: fixed 라 모든 페이지에 검은 버튼으로 찍힙니다. */
  .skip-link {
    display: none !important;
  }
}
