@charset "UTF-8";
/*
 Theme Name:   GeneratePress EP Theme
 Theme URI:    https://generatepress.com
 Description:  Default GeneratePress child theme made by EP.
 Author:       EVERYDAY PRACTICE
 Author URI:   http://everyday-practice.com
 License:      GNU General Public License v3.0 (or later)
 License URI:  https://www.gnu.org/licenses/gpl-3.0.html
 Template:     generatepress
 Version:      0.1
*/
/* Initialize */
:root {
  --color-white: #fff;
  --color-black: #000;
  --font-body:
    "kigsans", -apple-system, BlinkMacSystemFont, "Apple SD Gothic Neo",
    "Malgun Gothic", "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-display: "PP Formula", var(--font-body);
  --font-title: "PP Formula Fit", var(--font-body);
  --title-l: 56px;
  --title-m: 34px;
  --title-s: 30px;
  --title-xs: 24px;
  /* 국영문 타이틀에서 국문만 살짝 올리는 양 (styles/_title.scss 의 .ff-ko) */
  --ff-title-koLift: 0.02em;
  --ep-rowHoverShift: 8px;
  --ep-rowHoverSpeed: 0.2s;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  --ep-bodySize: 1rem;
  --ep-margin: 15px;
  --ep-header-padY: 25px;
  /* 좁은 화면에서 본문이 시작하는 높이 — 헤더(또는 그 아래에 붙은 띠 · 탭 바 ·
     제목 면)의 아랫선에서 본문 첫 요소까지. 페이지마다 따로 잡던 값을 하나로
     모았다. 각 파티셜의 모바일 블록이 이 값을 쓴다. */
  --ep-contentTop: 20px;
  --ep-header-lineW: 4px;
  --ep-header-lineColor: #6f14ff;
  /* 동그란 조작 버튼의 지름 — 슬라이더 좌우 화살표(.ff-slider__nav),
     맨 위로 버튼(.ff-totop)처럼 "누르는 동그라미"는 모두 이 값을 쓴다.
     한 벌로 보이게 하려고 한 곳에서만 정한다. 화면 크기와 무관하게 같다 —
     손가락으로 누르는 모바일에서 오히려 작아지면 안 된다. */
  --ep-controlSize: 48px;
}

/* ==================================================================
   EP Gradient System — Mesh
   ------------------------------------------------------------------
   디자인 팔레트 (Figma: "gradient")
     #8132FF · #30007B · #7C31F2 · #430B9B

   [원리]
   한 방향으로 흐르는 선형 띠 대신, 색 덩어리(블롭) 네 개를 겹쳐 면을
   만든다. 각 블롭은 배경 레이어 하나이고, 레이어마다 타일 크기를 박스보다
   작게 잡아(--ep-grad-mesh-size) 남는 공간만큼 자리를 옮길 수 있게 했다.
   그 자리를 A → B → C → A 로 돌리면 색 덩어리들이 서로 다른 방향으로
   천천히 밀리면서 섞인다.

   블롭은 closest-side 라 타일의 네 변에서 정확히 투명해진다. 그래서 타일
   경계가 사각형으로 드러나지 않는다. 맨 아래에는 기본 선형 레이어를 깔아
   블롭이 비껴간 자리도 비지 않는다.

   [심리스 루프]
   시작(A)과 끝(A)이 같은 왕복 구조라 어디서 끊어도 이어진다. 선형 띠처럼
   "정확히 1주기만 밀어야" 하는 제약이 없으므로 easing 을 써도 된다 —
   오히려 linear 로 두면 A·B·C 지점에서 방향이 꺾이는 게 보인다.

   [사용법]
   1) 배경        : class="ep-gradient"
   2) 텍스트      : class="ep-gradient-text"
   2b) 타이틀 마스킹: class="ep-gradient-title" (면 1개 + 글자 마스크, 권장)
   3) 테두리      : class="ep-gradient-border"   (안쪽 색은 --ep-grad-inner)
   4) 큰 섹션/히어로: class="ep-gradient-layer"   (transform 기반, GPU 합성)
   5) 정지 버전   : class="ep-gradient-still"  또는 background: var(--ep-grad-still)

   [조절]
   속도 : style="--ep-grad-duration: 30s"  또는 .ep-gradient--slow / --fast
   방향 : .ep-gradient--reverse
   색   : --ep-grad-c1 ~ --ep-grad-c4 재정의 (모든 변형에 일괄 반영)
   배치 : @property --ep-grad-b1x ~ b6y 의 initial-value (덩어리 집 자리)
   궤도 : @keyframes ep-grad-orbit-1 ~ 6 (집 자리 둘레를 도는 반경)

   [SCSS]
   임의의 셀렉터에 적용하려면 @include ep-gradient-bg;  /  ep-gradient-text;
================================================================== */
:root {
  /* --- 팔레트 (여기만 바꾸면 전체 시스템에 반영) --- */
  --ep-grad-c1: #8132ff;
  --ep-grad-c2: #30007b;
  --ep-grad-c3: #7c31f2;
  --ep-grad-c4: #430b9b;
  /* --- 모션 ---
     한 바퀴 도는 데 걸리는 기준 시간. 덩어리마다 이 값의 0.8~2.2 배를 쓴다.
     배수가 서로 나누어떨어지지 않아 여섯 궤도가 같은 자리로 다시 모이려면
     수십 분이 걸린다 — 보는 동안에는 같은 그림이 반복되지 않는다. */
  --ep-grad-duration: 16s;
  --ep-grad-direction: normal;
  /* --- 대비 폭 ---
     팔레트 네 색만으로는 밝기 범위가 좁아 덩어리가 움직여도 명암 차가
     잘 안 읽힌다. 가장 밝은 색은 조금 더 밝게, 가장 어두운 색은 조금 더
     어둡게 벌려 하이라이트·그림자로 쓴다. 색상(hue)은 그대로다.
     퍼센트를 100% 로 두면 팔레트 원색 그대로가 된다. */
  /* 덩어리 크기 배율 — 판 크기(--ep-grad-mesh-size)가 자리를 정하고,
     이 값이 덩어리 자체의 크기를 정한다. 둘을 나눠 둔 이유는, 판만으로
     크기를 키우면 판이 박스에 가까워지면서 덩어리가 한가운데로 몰리기
     때문이다(자리 계산이 판 - 박스 차이에서 나온다).
     넓은 띠처럼 덩어리를 크고 넉넉하게 깔아야 하는 곳에서 올려 쓴다. */
  --ep-grad-blob-scale: 1;
  --ep-grad-hi: color-mix(in srgb, var(--ep-grad-c1) 90%, #fff);
  --ep-grad-lo: color-mix(in srgb, var(--ep-grad-c2) 86%, #000);
  /* 바닥 선형 레이어 각도 */
  --ep-grad-angle: 160deg;
  /* --- 블롭 판 크기 ---
     모든 블롭 레이어를 박스의 2배로 깐다. 판이 박스보다 커야 덩어리를
     가장자리 밖까지 밀어낼 수 있고, 움직일 거리도 박스 하나만큼 생긴다.
     판이 박스와 같거나 작으면 덩어리가 안쪽에만 갇혀 테두리가 바닥색으로
     남고, 여섯 개가 한가운데서 겹쳐 빛무리 하나로 보인다.
     마지막 100% 100% 는 바닥 레이어. */
  --ep-grad-mesh-size:
    200% 200%, 200% 200%, 200% 200%, 200% 200%, 200% 200%, 200% 200%,
    100% 100%;
  /* 블롭의 자리(x·y)와 농도(a)는 아래 @property 변수가 들고 있다.
     그 값을 엮은 background-image / background-position 목록은 :root 변수로
     두지 않고 믹스인이 규칙마다 직접 찍는다.

     ⚠ :root 에 선언한 사용자 정의 속성 안의 var() 는 그 자리(:root)에서
     먼저 치환되고, 치환된 결과가 자식에게 상속된다. 즉 요소에서 도는
     애니메이션 값이 아니라 :root 의 기본값으로 굳어버린다. 실제로 이 구조로
     한 번 만들었다가 그림이 통째로 멈췄다. 목록을 규칙 안에 직접 써야
     요소 자신의 값으로 치환된다. */
  /* 덩어리를 부드럽게 만드는 것들
     · 중간 정지점 없이 중심에서 바로 투명으로 — 단색 코어가 있으면
       가장자리가 동그라미로 또렷하게 보인다.
     · color-mix 로 농도를 낮춘다 — 바닥색이 비쳐 덩어리끼리 스민다.
     · 반지름은 판 기준이라 박스 기준의 절반 값이다(판이 2배라서).
       세로를 가로보다 크게 잡아 가로로 긴 박스에서도 위아래가 꽉 찬다.
     바닥 레이어는 팔레트 중간 톤으로 깐다. 바닥이 가장 어두우면 밝은 덩어리
     몇 개만 떠 보이고 어두운 덩어리는 묻힌다. 중간 톤 위에서는 밝은 쪽이
     highlight, 어두운 쪽이 shadow 로 같이 읽힌다. */
  /* 정지 메시 — 배치 A 와 같은 그림. 크기·위치를 이미지 안에 박아 두어
     background-size/position 없이 이 변수 하나로 쓸 수 있다. */
  --ep-grad-still:
    radial-gradient(
      26% 42% at 8% 22%,
      color-mix(in srgb, var(--ep-grad-hi) 86%, transparent) 0%,
      color-mix(in srgb, var(--ep-grad-hi) 86%, transparent) 32%,
      transparent 100%
    ),
    radial-gradient(
      24% 40% at 88% 14%,
      color-mix(in srgb, var(--ep-grad-c3) 80%, transparent) 0%,
      color-mix(in srgb, var(--ep-grad-c3) 80%, transparent) 32%,
      transparent 100%
    ),
    radial-gradient(
      28% 46% at 72% 90%,
      color-mix(in srgb, var(--ep-grad-lo) 85%, transparent) 0%,
      color-mix(in srgb, var(--ep-grad-lo) 85%, transparent) 32%,
      transparent 100%
    ),
    radial-gradient(
      22% 38% at 20% 84%,
      color-mix(in srgb, var(--ep-grad-c4) 76%, transparent) 0%,
      color-mix(in srgb, var(--ep-grad-c4) 76%, transparent) 32%,
      transparent 100%
    ),
    radial-gradient(
      20% 34% at 58% 44%,
      color-mix(in srgb, var(--ep-grad-hi) 72%, transparent) 0%,
      color-mix(in srgb, var(--ep-grad-hi) 72%, transparent) 32%,
      transparent 100%
    ),
    radial-gradient(
      21% 36% at 34% 8%,
      color-mix(in srgb, var(--ep-grad-lo) 77%, transparent) 0%,
      color-mix(in srgb, var(--ep-grad-lo) 77%, transparent) 32%,
      transparent 100%
    ),
    linear-gradient(
      var(--ep-grad-angle),
      var(--ep-grad-c4) 0%,
      var(--ep-grad-lo) 100%
    );
  /* ep-gradient-border 안쪽 면 색 */
  --ep-grad-inner: var(--color-white);
  --ep-grad-border-w: 2px;
}

/* ------------------------------------------------------------------
   블롭 변수 — @property 로 등록해야 애니메이션이 값 사이를 보간한다.
   등록하지 않은 사용자 정의 속성은 중간값 없이 절반 지점에서 툭 바뀐다.
   x·y 는 자리, a 는 농도다. initial-value 가 곧 각 덩어리의 기본 상태이고,
   애니메이션을 끄면 여기로 선다.
------------------------------------------------------------------ */
@property --ep-grad-b1x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 92%;
}
@property --ep-grad-b1y {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 78%;
}
@property --ep-grad-b1a {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 34%;
}
@property --ep-grad-b2x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 12%;
}
@property --ep-grad-b2y {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 86%;
}
@property --ep-grad-b2a {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 30%;
}
@property --ep-grad-b3x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 28%;
}
@property --ep-grad-b3y {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 10%;
}
@property --ep-grad-b3a {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 38%;
}
@property --ep-grad-b4x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 80%;
}
@property --ep-grad-b4y {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 16%;
}
@property --ep-grad-b4a {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 28%;
}
@property --ep-grad-b5x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 42%;
}
@property --ep-grad-b5y {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 56%;
}
@property --ep-grad-b5a {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 26%;
}
@property --ep-grad-b6x {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 66%;
}
@property --ep-grad-b6y {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 92%;
}
@property --ep-grad-b6a {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 32%;
}
/* ------------------------------------------------------------------
   Keyframes
   ------------------------------------------------------------------
   덩어리마다 자기 자리를 중심으로 타원 궤도를 천천히 돌고, 그와 별개로
   밝기(a)가 한 바퀴에 두세 번 짧게 피었다 사그라든다 — 소프트 스트로브.
   자리는 0·25·50·75·100% 에서만 찍고 밝기는 그 사이사이에 피크를 넣는다.
   CSS 애니메이션은 속성마다 "그 속성이 적힌 키프레임" 사이를 각각 보간하므로
   한 애니메이션 안에서 느린 이동과 빠른 명멸을 함께 줄 수 있다.
   피어오를 때는 ease-out(빠르게), 질 때는 ease-in(천천히) 으로 두어
   딱딱한 점멸이 아니라 빛이 번지는 느낌이 나게 했다. 자리만 움직이면 같은 밝기의 덩어리가 미끄러질
   뿐이라 "밀린다"로 읽힌다 — 농도가 함께 변해야 진한 곳이 옅어지고 옅은 곳이
   차오르면서 면 안에서 명암이 살아난다.

   농도의 최고점은 궤도의 어느 지점에 둘지 덩어리마다 다르게 잡았다.
   (어떤 것은 한 바퀴에 한 번, 어떤 것은 두 번 밝아진다)

   시작과 끝이 같은 닫힌 궤도라서 멈추거나 되돌아오는 지점이 없다 —
   왕복시키면 방향이 꺾이는 순간이 보여 "숨쉬는" 느낌이 된다.
   그래서 타이밍도 linear 가 맞다.
------------------------------------------------------------------ */
@keyframes ep-grad-orbit-1 {
  0% {
    --ep-grad-b1x: 110%;
    --ep-grad-b1y: 78%;
    --ep-grad-b1a: 34%;
  }
  5% {
    --ep-grad-b1a: 34%;
    animation-timing-function: ease-out;
  }
  12% {
    --ep-grad-b1a: 100%;
    animation-timing-function: ease-in;
  }
  25% {
    --ep-grad-b1x: 92%;
    --ep-grad-b1y: 89%;
  }
  27% {
    --ep-grad-b1a: 34%;
  }
  50% {
    --ep-grad-b1x: 74%;
    --ep-grad-b1y: 78%;
  }
  51% {
    --ep-grad-b1a: 34%;
    animation-timing-function: ease-out;
  }
  58% {
    --ep-grad-b1a: 100%;
    animation-timing-function: ease-in;
  }
  73% {
    --ep-grad-b1a: 34%;
  }
  75% {
    --ep-grad-b1x: 92%;
    --ep-grad-b1y: 67%;
  }
  100% {
    --ep-grad-b1x: 110%;
    --ep-grad-b1y: 78%;
    --ep-grad-b1a: 34%;
  }
}
@keyframes ep-grad-orbit-2 {
  0% {
    --ep-grad-b2x: 28%;
    --ep-grad-b2y: 86%;
    --ep-grad-b2a: 30%;
  }
  23% {
    --ep-grad-b2a: 30%;
    animation-timing-function: ease-out;
  }
  25% {
    --ep-grad-b2x: 12%;
    --ep-grad-b2y: 73%;
  }
  30% {
    --ep-grad-b2a: 94%;
    animation-timing-function: ease-in;
  }
  45% {
    --ep-grad-b2a: 30%;
  }
  50% {
    --ep-grad-b2x: -4%;
    --ep-grad-b2y: 86%;
  }
  69% {
    --ep-grad-b2a: 30%;
    animation-timing-function: ease-out;
  }
  75% {
    --ep-grad-b2x: 12%;
    --ep-grad-b2y: 99%;
  }
  76% {
    --ep-grad-b2a: 94%;
    animation-timing-function: ease-in;
  }
  91% {
    --ep-grad-b2a: 30%;
  }
  100% {
    --ep-grad-b2x: 28%;
    --ep-grad-b2y: 86%;
    --ep-grad-b2a: 30%;
  }
}
@keyframes ep-grad-orbit-3 {
  0% {
    --ep-grad-b3x: 50%;
    --ep-grad-b3y: 10%;
    --ep-grad-b3a: 38%;
  }
  13% {
    --ep-grad-b3a: 38%;
    animation-timing-function: ease-out;
  }
  20% {
    --ep-grad-b3a: 100%;
    animation-timing-function: ease-in;
  }
  25% {
    --ep-grad-b3x: 28%;
    --ep-grad-b3y: 20%;
  }
  35% {
    --ep-grad-b3a: 38%;
  }
  50% {
    --ep-grad-b3x: 6%;
    --ep-grad-b3y: 10%;
  }
  59% {
    --ep-grad-b3a: 38%;
    animation-timing-function: ease-out;
  }
  66% {
    --ep-grad-b3a: 100%;
    animation-timing-function: ease-in;
  }
  75% {
    --ep-grad-b3x: 28%;
    --ep-grad-b3y: 0%;
  }
  81% {
    --ep-grad-b3a: 38%;
  }
  100% {
    --ep-grad-b3x: 50%;
    --ep-grad-b3y: 10%;
    --ep-grad-b3a: 38%;
  }
}
@keyframes ep-grad-orbit-4 {
  0% {
    --ep-grad-b4x: 94%;
    --ep-grad-b4y: 16%;
    --ep-grad-b4a: 28%;
  }
  25% {
    --ep-grad-b4x: 80%;
    --ep-grad-b4y: 1%;
  }
  37% {
    --ep-grad-b4a: 28%;
    animation-timing-function: ease-out;
  }
  44% {
    --ep-grad-b4a: 90%;
    animation-timing-function: ease-in;
  }
  50% {
    --ep-grad-b4x: 66%;
    --ep-grad-b4y: 16%;
  }
  59% {
    --ep-grad-b4a: 28%;
  }
  75% {
    --ep-grad-b4x: 80%;
    --ep-grad-b4y: 31%;
  }
  77% {
    --ep-grad-b4a: 28%;
    animation-timing-function: ease-out;
  }
  84% {
    --ep-grad-b4a: 90%;
    animation-timing-function: ease-in;
  }
  99% {
    --ep-grad-b4a: 28%;
  }
  100% {
    --ep-grad-b4x: 94%;
    --ep-grad-b4y: 16%;
    --ep-grad-b4a: 28%;
  }
}
@keyframes ep-grad-orbit-5 {
  0% {
    --ep-grad-b5x: 62%;
    --ep-grad-b5y: 56%;
    --ep-grad-b5a: 26%;
  }
  7% {
    --ep-grad-b5a: 26%;
    animation-timing-function: ease-out;
  }
  14% {
    --ep-grad-b5a: 92%;
    animation-timing-function: ease-in;
  }
  25% {
    --ep-grad-b5x: 42%;
    --ep-grad-b5y: 70%;
  }
  29% {
    --ep-grad-b5a: 26%;
  }
  39% {
    --ep-grad-b5a: 26%;
    animation-timing-function: ease-out;
  }
  46% {
    --ep-grad-b5a: 92%;
    animation-timing-function: ease-in;
  }
  50% {
    --ep-grad-b5x: 22%;
    --ep-grad-b5y: 56%;
  }
  61% {
    --ep-grad-b5a: 26%;
  }
  67% {
    --ep-grad-b5a: 26%;
    animation-timing-function: ease-out;
  }
  74% {
    --ep-grad-b5a: 92%;
    animation-timing-function: ease-in;
  }
  75% {
    --ep-grad-b5x: 42%;
    --ep-grad-b5y: 42%;
  }
  89% {
    --ep-grad-b5a: 26%;
  }
  100% {
    --ep-grad-b5x: 62%;
    --ep-grad-b5y: 56%;
    --ep-grad-b5a: 26%;
  }
}
@keyframes ep-grad-orbit-6 {
  0% {
    --ep-grad-b6x: 83%;
    --ep-grad-b6y: 92%;
    --ep-grad-b6a: 32%;
  }
  19% {
    --ep-grad-b6a: 32%;
    animation-timing-function: ease-out;
  }
  25% {
    --ep-grad-b6x: 66%;
    --ep-grad-b6y: 80%;
  }
  26% {
    --ep-grad-b6a: 96%;
    animation-timing-function: ease-in;
  }
  41% {
    --ep-grad-b6a: 32%;
  }
  50% {
    --ep-grad-b6x: 49%;
    --ep-grad-b6y: 92%;
  }
  55% {
    --ep-grad-b6a: 32%;
    animation-timing-function: ease-out;
  }
  62% {
    --ep-grad-b6a: 96%;
    animation-timing-function: ease-in;
  }
  75% {
    --ep-grad-b6x: 66%;
    --ep-grad-b6y: 104%;
  }
  77% {
    --ep-grad-b6a: 32%;
  }
  100% {
    --ep-grad-b6x: 83%;
    --ep-grad-b6y: 92%;
    --ep-grad-b6a: 32%;
  }
}
/* 넓은 면적용 — 위치를 매 프레임 다시 칠하지 않고 면 전체를 transform 으로
   움직인다. 이쪽도 닫힌 궤도라 이어서 흐른다.
   scale 은 항상 1 이상이라 가장자리가 비지 않는다. */
@keyframes ep-grad-drift {
  0% {
    transform: translate3d(-2%, -6%, 0) scale(1.12);
  }
  25% {
    transform: translate3d(-8%, -6%, 0) scale(1.16);
  }
  50% {
    transform: translate3d(-8%, 0%, 0) scale(1.12);
  }
  75% {
    transform: translate3d(-2%, 0%, 0) scale(1.08);
  }
  100% {
    transform: translate3d(-2%, -6%, 0) scale(1.12);
  }
}
/* ------------------------------------------------------------------
   Mixins
------------------------------------------------------------------ */
/* 여섯 궤도 목록 — 믹스인 두 곳에서 같은 값을 써야 해서 변수로 뺀다 */
/* 여섯 궤도를 한 요소에서 동시에 돌린다. 주기가 서로 달라 겹치는 모양이
   계속 바뀐다 — 하나의 타임라인으로 묶으면 여섯이 같이 움직여 뭉쳐 보인다.
   $extra 로 면 전체를 미는 애니메이션을 하나 더 얹을 수 있다. */
/* 메시 이미지 한 벌 — 덩어리 여섯 + 바닥 레이어.
   농도(a)를 변수로 받아 도는 동안 진하기가 같이 변한다.
   (자리·농도 변수는 반드시 규칙 안에서 풀려야 한다 — 위 :root 주석 참고) */
/* 여섯 덩어리의 현재 자리. 마지막 50% 50% 는 움직이지 않는 바닥 레이어. */
/* 메시 면 한 벌 — 이미지·크기·자리를 한 묶음으로 깐다 */
/* 글자 뒤로 "하나의" 메시 면이 흐르고, 글자가 그 면을 오려내는 마스크가 된다.
   면의 크기/위치는 이 클래스가 붙은 요소의 박스 하나로 결정되므로,
   여러 줄이든 중첩 마크업이든 전부 같은 면을 공유한다.
   블롭 자리를 박스 비율로 잡아두어 작은 글자 상자에도 네 색이 모두 들어온다. */
/* 자식 요소가 자기 글자색·배경을 위에 덮어쓰면 "글자별로 따로 칠해진" 느낌이 난다.
   전부 투명 상속으로 눌러서 부모의 단일 면이 모든 글리프를 통과하게 만든다. */
/* ------------------------------------------------------------------
   Utility classes
------------------------------------------------------------------ */
.ep-gradient {
  background-color: var(--ep-grad-c4);
  background-image: radial-gradient(calc(13% * var(--ep-grad-blob-scale, 1)) calc(21% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 32%, transparent 100%), radial-gradient(calc(12% * var(--ep-grad-blob-scale, 1)) calc(20% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 32%, transparent 100%), radial-gradient(calc(14% * var(--ep-grad-blob-scale, 1)) calc(23% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 32%, transparent 100%), radial-gradient(calc(11% * var(--ep-grad-blob-scale, 1)) calc(19% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 32%, transparent 100%), radial-gradient(calc(10% * var(--ep-grad-blob-scale, 1)) calc(17% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 32%, transparent 100%), radial-gradient(calc(10.5% * var(--ep-grad-blob-scale, 1)) calc(18% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 32%, transparent 100%), linear-gradient(var(--ep-grad-angle), var(--ep-grad-c4) 0%, var(--ep-grad-lo) 100%);
  background-size: var(--ep-grad-mesh-size);
  background-position: var(--ep-grad-b1x) var(--ep-grad-b1y), var(--ep-grad-b2x) var(--ep-grad-b2y), var(--ep-grad-b3x) var(--ep-grad-b3y), var(--ep-grad-b4x) var(--ep-grad-b4y), var(--ep-grad-b5x) var(--ep-grad-b5y), var(--ep-grad-b6x) var(--ep-grad-b6y), 50% 50%;
  background-repeat: no-repeat;
  animation: ep-grad-orbit-1 calc(var(--ep-grad-duration) * 0.8) linear infinite, ep-grad-orbit-2 calc(var(--ep-grad-duration) * 1) linear infinite, ep-grad-orbit-3 calc(var(--ep-grad-duration) * 1.25) linear infinite, ep-grad-orbit-4 calc(var(--ep-grad-duration) * 1.55) linear infinite, ep-grad-orbit-5 calc(var(--ep-grad-duration) * 1.9) linear infinite, ep-grad-orbit-6 calc(var(--ep-grad-duration) * 2.2) linear infinite;
  animation-direction: var(--ep-grad-direction);
}

/* 인라인 강조 / 단일 요소 텍스트 */
.ep-gradient-text {
  background-color: transparent;
  background-image: radial-gradient(calc(13% * var(--ep-grad-blob-scale, 1)) calc(21% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 32%, transparent 100%), radial-gradient(calc(12% * var(--ep-grad-blob-scale, 1)) calc(20% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 32%, transparent 100%), radial-gradient(calc(14% * var(--ep-grad-blob-scale, 1)) calc(23% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 32%, transparent 100%), radial-gradient(calc(11% * var(--ep-grad-blob-scale, 1)) calc(19% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 32%, transparent 100%), radial-gradient(calc(10% * var(--ep-grad-blob-scale, 1)) calc(17% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 32%, transparent 100%), radial-gradient(calc(10.5% * var(--ep-grad-blob-scale, 1)) calc(18% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 32%, transparent 100%), linear-gradient(var(--ep-grad-angle), var(--ep-grad-c4) 0%, var(--ep-grad-lo) 100%);
  background-size: var(--ep-grad-mesh-size);
  background-position: var(--ep-grad-b1x) var(--ep-grad-b1y), var(--ep-grad-b2x) var(--ep-grad-b2y), var(--ep-grad-b3x) var(--ep-grad-b3y), var(--ep-grad-b4x) var(--ep-grad-b4y), var(--ep-grad-b5x) var(--ep-grad-b5y), var(--ep-grad-b6x) var(--ep-grad-b6y), 50% 50%;
  background-repeat: no-repeat;
  /* background-clip 미지원 브라우저 폴백 */
  color: var(--ep-grad-c1);
  animation: ep-grad-orbit-1 calc(var(--ep-grad-duration) * 0.8) linear infinite, ep-grad-orbit-2 calc(var(--ep-grad-duration) * 1) linear infinite, ep-grad-orbit-3 calc(var(--ep-grad-duration) * 1.25) linear infinite, ep-grad-orbit-4 calc(var(--ep-grad-duration) * 1.55) linear infinite, ep-grad-orbit-5 calc(var(--ep-grad-duration) * 1.9) linear infinite, ep-grad-orbit-6 calc(var(--ep-grad-duration) * 2.2) linear infinite;
  animation-direction: var(--ep-grad-direction);
}

/* 타이틀 전용 — 메시 면 위에 텍스트로 마스킹한 것과 동일한 결과.
   display:block 으로 박스를 하나로 확정해 글자 전체(여러 줄 포함)가 같은 면을
   공유하게 만든다. 인라인 요소는 줄마다 박스가 쪼개져 면이 끊기므로 필수.
   기존 h1~h6 에 클래스만 얹어도 레이아웃은 그대로고 페인트만 바뀐다. */
.ep-gradient-title {
  background-color: transparent;
  background-image: radial-gradient(calc(13% * var(--ep-grad-blob-scale, 1)) calc(21% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 32%, transparent 100%), radial-gradient(calc(12% * var(--ep-grad-blob-scale, 1)) calc(20% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 32%, transparent 100%), radial-gradient(calc(14% * var(--ep-grad-blob-scale, 1)) calc(23% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 32%, transparent 100%), radial-gradient(calc(11% * var(--ep-grad-blob-scale, 1)) calc(19% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 32%, transparent 100%), radial-gradient(calc(10% * var(--ep-grad-blob-scale, 1)) calc(17% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 32%, transparent 100%), radial-gradient(calc(10.5% * var(--ep-grad-blob-scale, 1)) calc(18% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 32%, transparent 100%), linear-gradient(var(--ep-grad-angle), var(--ep-grad-c4) 0%, var(--ep-grad-lo) 100%);
  background-size: var(--ep-grad-mesh-size);
  background-position: var(--ep-grad-b1x) var(--ep-grad-b1y), var(--ep-grad-b2x) var(--ep-grad-b2y), var(--ep-grad-b3x) var(--ep-grad-b3y), var(--ep-grad-b4x) var(--ep-grad-b4y), var(--ep-grad-b5x) var(--ep-grad-b5y), var(--ep-grad-b6x) var(--ep-grad-b6y), 50% 50%;
  background-repeat: no-repeat;
  /* background-clip 미지원 브라우저 폴백 */
  color: var(--ep-grad-c1);
  animation: ep-grad-orbit-1 calc(var(--ep-grad-duration) * 0.8) linear infinite, ep-grad-orbit-2 calc(var(--ep-grad-duration) * 1) linear infinite, ep-grad-orbit-3 calc(var(--ep-grad-duration) * 1.25) linear infinite, ep-grad-orbit-4 calc(var(--ep-grad-duration) * 1.55) linear infinite, ep-grad-orbit-5 calc(var(--ep-grad-duration) * 1.9) linear infinite, ep-grad-orbit-6 calc(var(--ep-grad-duration) * 2.2) linear infinite;
  animation-direction: var(--ep-grad-direction);
  display: block;
}

/* 짧은 타이틀에서 글자 안에 팔레트 전체를 담고 싶을 때 — 면을 글자 폭에 맞춘다.
   블록 폭이 줄어드므로 부모의 text-align 대신 margin 으로 정렬한다. */
.ep-gradient-title--hug {
  width: -moz-fit-content;
  width: fit-content;
}
.ep-gradient-title--hug.ep-gradient-title--center {
  margin-inline: auto;
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
  .ep-gradient-text,
  .ep-gradient-title {
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
  }
  .ep-gradient-text > *,
  .ep-gradient-text > * > * {
    background: none;
    color: inherit;
    -webkit-text-fill-color: inherit;
    -webkit-background-clip: border-box;
    background-clip: border-box;
  }
  /* 타이틀은 자식에 걸린 그라디언트 애니메이션까지 끊어
     "면 하나 + 마스크 하나" 를 강제한다. */
  .ep-gradient-title *,
  .ep-gradient-title *::before,
  .ep-gradient-title *::after {
    background: none;
    color: inherit;
    -webkit-text-fill-color: inherit;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    animation: none;
  }
}
.ep-gradient-border {
  border: var(--ep-grad-border-w) solid transparent;
  /* 안쪽 면(단색) + 메시 — 메시 목록 앞에 레이어가 하나 더 붙으므로
     크기·자리 목록도 그만큼 앞에 한 칸씩 밀어 넣는다. */
  background-image: linear-gradient(var(--ep-grad-inner), var(--ep-grad-inner)), radial-gradient(calc(13% * var(--ep-grad-blob-scale, 1)) calc(21% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 32%, transparent 100%), radial-gradient(calc(12% * var(--ep-grad-blob-scale, 1)) calc(20% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 32%, transparent 100%), radial-gradient(calc(14% * var(--ep-grad-blob-scale, 1)) calc(23% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 32%, transparent 100%), radial-gradient(calc(11% * var(--ep-grad-blob-scale, 1)) calc(19% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 32%, transparent 100%), radial-gradient(calc(10% * var(--ep-grad-blob-scale, 1)) calc(17% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 32%, transparent 100%), radial-gradient(calc(10.5% * var(--ep-grad-blob-scale, 1)) calc(18% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 32%, transparent 100%), linear-gradient(var(--ep-grad-angle), var(--ep-grad-c4) 0%, var(--ep-grad-lo) 100%);
  background-origin: border-box;
  background-clip: padding-box, border-box;
  background-size: auto, var(--ep-grad-mesh-size);
  background-position: 0 0, var(--ep-grad-b1x) var(--ep-grad-b1y), var(--ep-grad-b2x) var(--ep-grad-b2y), var(--ep-grad-b3x) var(--ep-grad-b3y), var(--ep-grad-b4x) var(--ep-grad-b4y), var(--ep-grad-b5x) var(--ep-grad-b5y), var(--ep-grad-b6x) var(--ep-grad-b6y), 50% 50%;
  background-repeat: no-repeat;
  animation: ep-grad-orbit-1 calc(var(--ep-grad-duration) * 0.8) linear infinite, ep-grad-orbit-2 calc(var(--ep-grad-duration) * 1) linear infinite, ep-grad-orbit-3 calc(var(--ep-grad-duration) * 1.25) linear infinite, ep-grad-orbit-4 calc(var(--ep-grad-duration) * 1.55) linear infinite, ep-grad-orbit-5 calc(var(--ep-grad-duration) * 1.9) linear infinite, ep-grad-orbit-6 calc(var(--ep-grad-duration) * 2.2) linear infinite;
  animation-direction: var(--ep-grad-direction);
}

/* 정지 버전 — 위치·크기가 이미지 안에 들어있어 따로 지정할 것이 없다 */
.ep-gradient-still {
  background-color: var(--ep-grad-c4);
  background-image: var(--ep-grad-still);
}

/* 넓은 면적(히어로/풀블리드 섹션)용 GPU 합성 레이어.
   부모에 overflow:hidden 을 걸고 자식은 z-index 로 띄운다.
   배경 위치를 매 프레임 다시 칠하는 대신 면 전체를 transform 으로 움직여서,
   화면을 덮는 크기에서도 합성만으로 처리된다. */
.ep-gradient-layer {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background-color: var(--ep-grad-c4);
}

.ep-gradient-layer::before {
  content: "";
  position: absolute;
  /* 움직이고 확대해도 가장자리가 비지 않도록 사방으로 넉넉히 넘긴다 */
  inset: -14%;
  background-image: radial-gradient(calc(13% * var(--ep-grad-blob-scale, 1)) calc(21% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b1a), transparent) 32%, transparent 100%), radial-gradient(calc(12% * var(--ep-grad-blob-scale, 1)) calc(20% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c3) var(--ep-grad-b2a), transparent) 32%, transparent 100%), radial-gradient(calc(14% * var(--ep-grad-blob-scale, 1)) calc(23% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b3a), transparent) 32%, transparent 100%), radial-gradient(calc(11% * var(--ep-grad-blob-scale, 1)) calc(19% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 0%, color-mix(in srgb, var(--ep-grad-c4) var(--ep-grad-b4a), transparent) 32%, transparent 100%), radial-gradient(calc(10% * var(--ep-grad-blob-scale, 1)) calc(17% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 0%, color-mix(in srgb, var(--ep-grad-hi) var(--ep-grad-b5a), transparent) 32%, transparent 100%), radial-gradient(calc(10.5% * var(--ep-grad-blob-scale, 1)) calc(18% * var(--ep-grad-blob-scale, 1)) at 50% 50%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 0%, color-mix(in srgb, var(--ep-grad-lo) var(--ep-grad-b6a), transparent) 32%, transparent 100%), linear-gradient(var(--ep-grad-angle), var(--ep-grad-c4) 0%, var(--ep-grad-lo) 100%);
  background-size: var(--ep-grad-mesh-size);
  background-position: var(--ep-grad-b1x) var(--ep-grad-b1y), var(--ep-grad-b2x) var(--ep-grad-b2y), var(--ep-grad-b3x) var(--ep-grad-b3y), var(--ep-grad-b4x) var(--ep-grad-b4y), var(--ep-grad-b5x) var(--ep-grad-b5y), var(--ep-grad-b6x) var(--ep-grad-b6y), 50% 50%;
  background-repeat: no-repeat;
  /* 덩어리 궤도(면 안쪽 변화) + 느린 드리프트(면 전체 이동)를 함께 돌린다.
     드리프트만 있으면 면이 통째로 한 방향으로 밀리기만 해서, 위에서 흐르는
     마키와 속도가 비슷해 보이고 배경이 같이 미끄러지는 느낌이 된다.
     궤도가 더해지면 면 안에서 진한 곳·옅은 곳이 따로 움직여 마키와 분리된다.
     드리프트는 궤도 중 가장 느린 것(2.2배)보다도 느리게 둔다. */
  animation: ep-grad-orbit-1 calc(var(--ep-grad-duration) * 0.8) linear infinite, ep-grad-orbit-2 calc(var(--ep-grad-duration) * 1) linear infinite, ep-grad-orbit-3 calc(var(--ep-grad-duration) * 1.25) linear infinite, ep-grad-orbit-4 calc(var(--ep-grad-duration) * 1.55) linear infinite, ep-grad-orbit-5 calc(var(--ep-grad-duration) * 1.9) linear infinite, ep-grad-orbit-6 calc(var(--ep-grad-duration) * 2.2) linear infinite, ep-grad-drift calc(var(--ep-grad-duration) * 2.6) linear infinite;
  animation-direction: var(--ep-grad-direction);
  will-change: transform;
  z-index: 0;
  pointer-events: none;
}

.ep-gradient-layer > * {
  position: relative;
  z-index: 1;
}

/* ------------------------------------------------------------------
   Modifiers
------------------------------------------------------------------ */
.ep-gradient--slow {
  --ep-grad-duration: 34s;
}

.ep-gradient--fast {
  --ep-grad-duration: 10s;
}

.ep-gradient--reverse {
  --ep-grad-direction: reverse;
}

/* 그라디언트 면 위의 기본 텍스트 색 */
.ep-gradient.ep-gradient--on-dark,
.ep-gradient-still.ep-gradient--on-dark,
.ep-gradient-layer.ep-gradient--on-dark {
  color: var(--color-white);
}
.ep-gradient.ep-gradient--on-dark h1,
.ep-gradient.ep-gradient--on-dark h2,
.ep-gradient.ep-gradient--on-dark h3,
.ep-gradient.ep-gradient--on-dark h4,
.ep-gradient.ep-gradient--on-dark h5,
.ep-gradient.ep-gradient--on-dark h6,
.ep-gradient.ep-gradient--on-dark a,
.ep-gradient-still.ep-gradient--on-dark h1,
.ep-gradient-still.ep-gradient--on-dark h2,
.ep-gradient-still.ep-gradient--on-dark h3,
.ep-gradient-still.ep-gradient--on-dark h4,
.ep-gradient-still.ep-gradient--on-dark h5,
.ep-gradient-still.ep-gradient--on-dark h6,
.ep-gradient-still.ep-gradient--on-dark a,
.ep-gradient-layer.ep-gradient--on-dark h1,
.ep-gradient-layer.ep-gradient--on-dark h2,
.ep-gradient-layer.ep-gradient--on-dark h3,
.ep-gradient-layer.ep-gradient--on-dark h4,
.ep-gradient-layer.ep-gradient--on-dark h5,
.ep-gradient-layer.ep-gradient--on-dark h6,
.ep-gradient-layer.ep-gradient--on-dark a {
  color: var(--color-white);
}

/* ------------------------------------------------------------------
   Accessibility — 모션 최소화 설정 시 정지 상태로 고정
------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .ep-gradient,
  .ep-gradient-text,
  .ep-gradient-title,
  .ep-gradient-border,
  .ep-gradient-layer::before {
    animation: none;
  }
  .ep-gradient-layer::before {
    transform: none;
  }
}
/* ==================================================================
   Title Typography — 국영문 혼용 타이틀
   ------------------------------------------------------------------
   국문 kigsans + 영문 PP Formula 를 한 줄에 섞어 쓰는 타이틀 체계.

   [원리] 두 폰트는 같은 font-size 에서 크기감이 다르다(영문이 작아 보인다).
   그래서 영문용 PP Formula 를 size-adjust: 111.9% 로 한 번 더 등록해두고
   (fonts/font.css 참고) 그 패밀리를 먼저 둔다. 영문 글리프만 PP Formula 가
   맡고 국문은 kigsans 로 폴백되므로, font-size 는 "국문 기준" 하나만 주면
   영문은 자동으로 47/42 배로 커진다. 마크업을 쪼갤 필요가 없다.

   [사용법]
     제목 태그(h1~h6)  : 자동 적용. 크기는 각 태그의 기존 값 그대로.
     임의 요소         : class="title"  (+ --l / --s / --xs)
     영문만 쓰는 디스플레이: class="font-display" (크기 보정 없음)

   [조절]
     크기 --title-l / --title-m / --title-s / --title-xs  (_asset.scss)
     국영문 비율 fonts/font.css 의 size-adjust 값 (영문만 커지고 작아진다)
     국문 높이  --ff-title-koLift (국문만 위로 올리는 양)
================================================================== */
h1,
h2,
h3,
h4,
h5,
h6,
.title {
  font-family: var(--font-title);
  font-synthesis: none;
}

/* 국문만 살짝 올린다.
   ── 왜 span 이 필요한가 ──
   한 줄 안의 글자는 국문·영문이 같은 기준선(baseline) 위에 놓인다. 글꼴
   설정(size-adjust·metric override)은 크기와 줄 높이를 바꿀 뿐 기준선 자체를
   옮기지 못하므로, 한쪽만 올리려면 그 글자를 감싸야 한다.
   감싸는 일은 script.js 가 한다(제목 안의 한글 덩어리 → span.ff-ko).
   글자 내용은 그대로라 복사·검색·스크린리더에는 영향이 없다.

   위치만 바꾸고 배치는 건드리지 않도록 relative 오프셋을 쓴다
   (테마 전역에 position: relative 가 걸려 있다). */
.ff-ko {
  top: calc(var(--ff-title-koLift) * -1);
}

.title {
  font-size: var(--title-m);
  font-weight: var(--fw-bold);
  line-height: 1.2;
}

.title--l {
  font-size: var(--title-l);
}

.title--s {
  font-size: var(--title-s);
}

.title--xs {
  font-size: var(--title-xs);
}

@media (max-width: 768px) {
  :root {
    --title-l: 40px;
    --title-m: 30px;
    --title-s: 24px;
    --title-xs: 20px;
  }
}
/* ----- Title Typography End ----- */
/* ==================================================================
   Language Switch  (inc/lang.php · script.js)
   ------------------------------------------------------------------
   한 페이지에 국문·영문을 나란히 넣어 두고 한쪽만 보여준다.

   [구조]
     .ff-lang-switch            ← 본문 맨 위에 자동으로 붙는 전환 버튼
     .ff-lang.ff-lang--ko       ← 국문 묶음
     .ff-lang.ff-lang--en       ← 영문 묶음

   [전환] <html data-ff-lang="en"> 이면 영문만 보인다. 값이 없으면 국문이다 —
   JS 가 없어도 국문은 그대로 읽힌다.

   [영문 서체] 영문 묶음 안에서는 타이틀 서체를 본문 서체(kigsans)로 바꾼다.
   사이트의 타이틀 서체(--font-title)는 영문 글리프를 PP Formula 로 그리는데,
   영문 본문까지 그 글꼴로 나가면 디스플레이 서체로 긴 글을 읽게 된다.
   토큰만 덮어쓰므로 제목·표 등 안쪽 요소를 하나하나 고칠 필요가 없다.
================================================================== */
.ff-lang--en {
  display: none;
}

[data-ff-lang=en] .ff-lang--ko {
  display: none;
}

[data-ff-lang=en] .ff-lang--en {
  display: block;
}

.ff-lang--en {
  --font-title: var(--font-body);
}

/* ----- 전환 버튼 ----- */
/* 알약 안에서 동그라미가 두 칸 사이를 미끄러진다.
   - 동그라미는 알약 안에 깔린 한 겹(.ff-lang-switch__knob)이고, 글자 두 개는
     그 위에 떠 있다. 지금 언어 쪽 글자만 흰색이 된다.
   - 동그라미를 움직이는 것은 <html data-ff-lang> 뿐이다. JS 는 지금까지처럼
     그 값과 버튼 상태만 바꾸고, 위치 계산은 하지 않는다.
   - 칸 두 개가 붙어 있으므로 옮길 거리는 정확히 동그라미 지름(=translateX
     100%)이다. 칸 폭을 바꿔도 따라간다.

   [스크롤] 본문을 읽는 내내 헤더 밑에 붙어 있다(position: sticky). 멈추는
   높이는 --ff-headerBottom — script.js 가 재는 "지금 보이는 헤더의 아랫선"
   이라 PC/모바일 헤더 교대와 타이틀 접힘까지 따라간다.
   띠 자체는 본문 폭을 다 차지하므로 pointer-events 를 꺼 둔다. 그렇지 않으면
   알약 왼쪽의 빈 자리가 본문 위를 덮어 글자를 고를 수 없다.

   [모바일] 1024px 이하에서는 헤더 밑이 아니라 화면 오른쪽 아래에 떠 있는다.
   좁은 화면에서 본문 위를 가리지 않고 어디서나 같은 자리에서 누를 수 있다.
   오른쪽 아래는 "맨 위로" 버튼 자리이므로 알약은 왼쪽 아래 모서리에 둔다.
   둘 다 가장자리에서 사이트 좌우 마진과 같은 간격으로 떨어진다.

   [조절]
     동그라미 지름  --ff-lang-size
     글자 크기      --ff-lang-fontSize
     알약 여백      --ff-lang-pad
     멈추는 높이    --ff-lang-stickyGap
     모바일 모서리  --ff-lang-edge
     색             --ff-lang-color
================================================================== */
:root {
  --ff-lang-color: #6f14ff;
  --ff-lang-size: 32px;
  --ff-lang-fontSize: 13px;
  --ff-lang-pad: 3px;
  --ff-lang-stickyGap: 12px;
  /* 모바일에서 알약이 화면 바닥에 뜰 때 가장자리에서 떨어진 거리.
     오른쪽 아래는 "맨 위로" 버튼 자리라 알약은 왼쪽 아래를 쓴다. */
  --ff-lang-edge: var(--ep-margin);
  --ff-lang-speed: 0.35s;
  /* 끝에서 살짝 넘쳤다 돌아온다 — 손으로 민 듯한 느낌 */
  --ff-lang-ease: cubic-bezier(0.34, 1.4, 0.64, 1);
}

.ff-lang-switch {
  position: sticky;
  top: calc(var(--ff-headerBottom, var(--ep-headerH, 0px)) + var(--ff-lang-stickyGap));
  /* 헤더(999)·맨 위로 버튼(900)보다 아래, 본문보다 위 */
  z-index: 500;
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
  pointer-events: none;
}

.ff-lang-switch__pill {
  position: relative;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: var(--ff-lang-size);
  padding: var(--ff-lang-pad);
  border: 1.5px solid var(--ff-lang-color);
  border-radius: 999px;
  background-color: color-mix(in srgb, var(--ff-lang-color) 8%, #fff);
  pointer-events: auto;
}

/* 자리를 잡는 기준은 알약의 안쪽 상자(padding box)라, 여백만큼 들여 둔다 */
.ff-lang-switch__knob {
  position: absolute;
  top: var(--ff-lang-pad);
  left: var(--ff-lang-pad);
  width: var(--ff-lang-size);
  height: var(--ff-lang-size);
  border-radius: 50%;
  background-color: var(--ff-lang-color);
}

[data-ff-lang=en] .ff-lang-switch__knob {
  transform: translateX(100%);
}

.ff-lang-switch__btn {
  position: relative; /* 동그라미 위 */
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ff-lang-size);
  height: var(--ff-lang-size);
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ff-lang-color);
  font-family: var(--font-body);
  /* !important 가 필요하다 — style.scss 의 전역 규칙이
     button 의 font-size·line-height 를 !important 로 잡고 있어서
     (본문 크기 --ep-bodySize), 클래스 선택자로는 이길 수 없다. */
  font-size: var(--ff-lang-fontSize) !important;
  font-weight: var(--fw-bold);
  line-height: 1 !important;
  letter-spacing: 0.02em;
  cursor: pointer;
}

/* GP 기본 button 규칙(회색 배경)이 hover·focus 에서 되살아나므로 함께 잡는다 */
.ff-lang-switch__btn:hover,
.ff-lang-switch__btn:focus-visible {
  background: none;
  color: var(--ff-lang-color);
}

.ff-lang-switch__btn.is-current,
.ff-lang-switch__btn.is-current:hover,
.ff-lang-switch__btn.is-current:focus-visible {
  color: var(--color-white);
}

.ff-lang-switch__btn:focus-visible {
  outline: 2px solid var(--ff-lang-color);
  outline-offset: 2px;
}

/* 움직임은 화면이 준비된 뒤에만 — script.js 가 첫 상태를 맞춘 다음
   .is-ready 를 붙인다. 이게 없으면 ?lang=en 으로 들어왔을 때 동그라미가
   왼쪽에서 오른쪽으로 한 번 미끄러지는 게 보인다. */
.ff-lang-switch.is-ready .ff-lang-switch__knob {
  transition: transform var(--ff-lang-speed) var(--ff-lang-ease);
}

.ff-lang-switch.is-ready .ff-lang-switch__btn {
  transition: color var(--ff-lang-speed) var(--ff-lang-ease);
}

@media (max-width: 768px) {
  :root {
    --ff-lang-size: 29px;
    --ff-lang-fontSize: 10px;
  }
}
/* ----- 모바일 — 화면 오른쪽 아래 고정 ----- */
@media (max-width: 1024px) {
  /* sticky 해제. 알약이 화면 바닥으로 빠지므로 띠는 흐름에서 자리를
     차지하지 않는다 — 빈 칸이 남으면 배너와 본문 사이가 그만큼 벌어진다.
     (요소 자체는 지워지면 안 된다. 알약이 그 안에 들어 있다) */
  .ff-lang-switch,
  .ff-rolling + .ff-lang-switch {
    position: static;
    min-height: 0;
    margin: 0;
  }
  /* 본문(국문 · 영문 묶음)에는 위 여백을 따로 주지 않는다 — 배너 바로 아래에서
     시작한다. 띄울 만큼은 묶음 안의 첫 요소가 가진 여백이 맡는다. */
  .ff-lang-switch__pill {
    position: fixed;
    /* 왼쪽 아래 — 오른쪽 아래는 "맨 위로" 버튼(.ff-totop)이 쓴다 */
    left: var(--ff-lang-edge);
    right: auto;
    bottom: var(--ff-lang-edge);
    /* 헤더(999)·메가메뉴보다 아래, 본문보다 위 */
    z-index: 500;
    /* 본문 글자 위에 떠 있으므로 반투명(기본값 8% 틴트)을 쓰면 글자가 비친다.
       흰 면 + "맨 위로" 버튼과 같은 그림자로 본문과 떼어 놓는다. */
    background-color: var(--color-white);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.16);
  }
}
@media (prefers-reduced-motion: reduce) {
  .ff-lang-switch.is-ready .ff-lang-switch__knob,
  .ff-lang-switch.is-ready .ff-lang-switch__btn {
    transition: none;
  }
}
/* 롤링 배너가 있는 화면에서는 배너 바로 아래에 붙으므로 위 여백을 줄인다.
   모바일은 알약이 바닥으로 빠져 이 줄 자체가 자리를 비우므로 제외한다
   (파일 뒤쪽이라 위 미디어쿼리보다 나중이고, 특이도도 같아서 여기서 막아야 한다). */
@media (min-width: 1025px) {
  .ff-rolling + .ff-lang-switch {
    margin-top: 20px;
  }
}
/* ----- Language Switch End ----- */
/* ----- Site header — fixed + 사이트 마진 ----- */
#pc-header {
  /* sticky 가 아니라 fixed 다.
     ── 왜 바꿨나 ──
     sticky 헤더는 문서 흐름 안(문서 최상단)에 남아 있어서, 접히거나 펼쳐질 때
     그 높이 차(≈40px)만큼 문서 전체가 줄었다 늘었다 한다. 브라우저는 보던
     위치를 지키려고 스크롤을 보정하고(스크롤 앵커링 · 최대 스크롤 클램프),
     특히 맨 위로 되돌아오는 구간에서 그 보정이 한 박자 늦게 따라와 걸리는
     느낌이 났다. fixed 면 헤더가 흐름에서 완전히 빠지므로 문서 높이가 아예
     변하지 않는다. 대신 비워둘 자리를 본문이 padding 으로 가진다(아래 body). */
  position: fixed;
  top: 0;
  /* fixed 는 폭이 내용에 맞춰 줄어든다 — 좌우를 물려 화면 폭을 채운다 */
  right: 0;
  left: 0;
  z-index: 999;
  background-color: var(--color-white);
  /* 좌우는 사이트 마진과 같은 값 — 헤더와 본문의 왼쪽 선을 맞춘다 */
  padding: var(--ep-margin);
  /* 스크롤 앵커링 후보에서 제외.
     fixed 요소는 규격상 이미 후보에서 빠지므로 지금은 없어도 된다. 한 줄이라
     남겨둔다 — 이 헤더가 다시 흐름 안으로 돌아오면 예전 증상(붙어 있는 sticky
     안쪽 노드가 앵커로 뽑혀 보정이 수렴하지 않고 헤더 하단 선이 떠는 현상)이
     바로 재발하기 때문이다. */
  overflow-anchor: none;
}

/* fixed 헤더가 비운 자리를 본문이 대신 갖는다.

   [왜 JS 가 재나] 헤더 높이는 화면 폭(--ff-header-fs)에 비례하고 웹폰트가
   로드되면 또 달라져서 CSS 로 정확히 쓸 수 없다. script.js 의 measure() 가
   "풀 상태 헤더 높이"를 재서 --ff-headerSpace 로 넘긴다.

   [접혀도 값은 그대로] 스크롤 중 헤더가 접혀도 이 값은 바뀌지 않는다. 그래야
   본문이 스크롤 도중 위아래로 움직이지 않는다 — fixed 로 바꾼 목적 자체다.

   [폴백] 스크립트가 값을 넣기 전 첫 페인트용 근사값. 로고 두 줄
   (--ff-logo-size 3em × line-height 0.92 × 2) + 상하 패딩.
   띠배너가 있는 페이지는 _topbar.scss 에서 배너 높이까지 더한다. */
body {
  padding-top: var(--ff-headerSpace, var(--ff-headerSpace-fallback));
}

/* 헤더 하단 라인 — 클래스로 켜고 끈다.
   body 에 붙이면 페이지 단위로(예: 메인), #pc-header 에 직접 붙이면 그 헤더만.

   border 는 요소 폭 전체를 채워 화면 끝까지 닿는다. 사이트 마진만큼 안쪽으로
   들여야 하므로 border 대신 ::after 로 그린다. 선이 차지하는 만큼 아래쪽
   패딩을 키워 내용과 선 사이 간격은 --ep-header-padY 그대로 유지한다. */
.ff-header-line #pc-header::after,
#pc-header.ff-header-line::after {
  content: "";
  position: absolute;
  right: var(--ep-margin);
  bottom: 0;
  left: var(--ep-margin);
  height: 2px;
  background-color: var(--ep-header-lineColor);
}

/* GP 기본 헤더를 쓰는 경우에도 같은 여백·동작 */
.site-header {
  position: sticky;
  top: 0;
  z-index: 999;
  background-color: var(--color-white);
}

.inside-header {
  padding-top: var(--ep-header-padY);
  padding-bottom: var(--ep-header-padY);
}

/* ==================================================================
   Festival Header  (shortcode: [print_header])
   ------------------------------------------------------------------
   스크롤을 내리면 풀 버전 타이틀 → 축약형(SIFF)으로,
   맨 위로 돌아오면 다시 풀 버전으로 전환된다.

   [구조] "세트" 단위로 전환한다.
     .ff-set[data-ff-set="full"]  = 풀 로고 + ff-title
     .ff-set[data-ff-set="short"] = 축약 로고 + ff-title
   두 세트를 같은 그리드 칸에 겹쳐 두고 세트째로 교차 페이드한다.
   ff-title 은 두 세트에 각각 들어가므로 로고와 한 덩어리로 같이 전환된다.
     - 박스 크기 : script.js 가 각 세트의 실제 크기를 재서 넣는다
     - 페이드    : data-ff-state 에 따른 세트 단위 opacity + blur
                  (위치 이동은 없다 — 제자리 교차)
   중복 출력된 쪽은 aria-hidden + tabindex=-1 로 접근성 트리에서 빼
   스크린리더가 한 번만 읽고 링크도 한 번만 잡히게 한다.

   [비례 크기] 화면 폭에 비례해 커지고 작아진다.
   헤더의 기준 글자 크기(--ff-header-fs) 하나만 vw 로 움직이고, 로고·타이틀·
   간격은 전부 그 값의 em 배수다. 그래서 크기가 바뀌어도 서로의 비율 —
   로고와 타이틀의 크기 차, 둘 사이 간격, 줄 맞춤 — 은 항상 같다.
   script.js 가 잰 박스 크기도 em 으로 저장하므로 리사이즈 중에 글자와
   박스가 따로 놀지 않는다.
     기준 폭 --ff-header-ref 에서 예전 고정값(18px 기준)과 같은 크기가 된다.
     너무 작아지거나 커지지 않게 clamp 의 최솟값·최댓값으로 막는다.
     (타이틀이 기준 크기의 0.78배라 최솟값이 곧 타이틀 가독성의 하한이다)

   [조절]
     색       --ff-accent
     비례     --ff-header-ref(기준 폭) / --ff-header-fs(최소·최대)
     크기     --ff-logo-size / --ff-logo-size-short  (em — 기준 크기의 배수)
     간격     --ff-title-gap
     속도     --ff-duration(크기·높이) / --ff-fade(세트 교차)
     흐림     --ff-blur (교차 순간의 모션블러 흉내)
     전환지점 script.js 의 collapseAt / expandAt
================================================================== */
:root {
  --ff-accent: #7b2ff7;
  /* 이 화면 폭(px, 단위 없이)에서 기준 크기가 18px — 예전 고정 크기와 같다 */
  --ff-header-ref: 1440;
  /* 최솟값 17px: PC 헤더는 1024px 위에서만 보이므로, 그 언저리에서도 로고가
     43px · 회차 타이틀이 13px 은 되도록 하한을 잡았다 (≈1360px 폭 이하 고정).
     최댓값 32px: 2560px 폭. 그 위로는 더 커지지 않는다 */
  --ff-header-fs: clamp(17px, calc(100vw * 18 / var(--ff-header-ref)), 32px);
  /* 아래 크기는 전부 --ff-header-fs 기준 em. 기준 18px 일 때 예전 값과 같다 */
  --ff-logo-size: 3em;
  /* 시각 보정량(로고 글자 크기의 배수).
     PP Formula 는 descent 0.28em 이 ascent−capHeight 0.08em 보다 0.20em 크다.
     그래서 글자 블록이 박스 안에서 위로 0.10em 치우쳐 보인다. 그만큼 내린다. */
  --ff-optical-shift: 0.1;
  /* 축약형도 같은 활자 크기 — 접힘은 "두 줄 → 한 줄"로만 읽히게 한다.
       따로 줄이려면 여기에 독립 값을 넣으면 된다. */
  --ff-logo-size-short: var(--ff-logo-size);
  --ff-title-gap: 0.5556em; /* 10px ÷ 18px */
  /* background-clip: text 로 칠할 면을 글자 위아래로 넓히는 여유분 */
  --ff-logo-bleed: 0.22em;
  /* 회차 타이틀은 로고 크기에 비례한다. 계수 0.306 은 예전 비율
     (로고 2.55em 일 때 타이틀 0.78em)을 옮긴 값이라, 로고를 키우면 타이틀도
     같이 커지고 "두 줄이 로고 한 줄 높이 안에" 라는 조건도 유지된다. */
  /* 계수를 올릴수록 타이틀 두 줄의 윗선이 로고 대문자 윗선에 가까워진다.
     다만 "타이틀 박스 ≤ 로고 한 줄 높이(0.92em)" 를 넘으면 script.js 의 겹침
     가드가 발동해 타이틀이 로고 아래로 밀려난다.
       박스 = 계수 × (2 × 줄간격 + 0.2)  →  0.345 × 2.6 = 0.897em (한계 0.92) */
  --ff-title-size: calc(var(--ff-logo-size) * 0.345);
  /* ff-title 을 위로 살짝 올리는 양. 아래쪽 정렬이라 로고 밑선에 붙는데,
     조금 들어올려야 로고 마지막 줄과 시각적으로 가운데가 맞는다.
     .ff-title 에서 쓰이므로 em 은 타이틀 폰트 크기(--ff-title-size) 기준이다. */
  --ff-title-lift: 0.2em;
  /* 본문 padding-top 폴백 (위 body 규칙 설명 참고) */
  --ff-headerSpace-fallback: calc(var(--ff-header-fs) * 5.52 + var(--ep-margin) * 2);
  --ff-duration: 0.34s;
  /* 세트 교차는 크기 변화보다 짧게 끝낸다. 위치 이동이 없으니
     너무 길면 두 세트가 겹쳐 보이는 구간만 늘어난다. */
  --ff-fade: 0.22s;
  /* 사라지는·나타나는 세트에 거는 흐림. CSS 로는 방향성 있는 모션블러를
     보간할 수 없어서(SVG 필터의 stdDeviation 은 전환 대상이 아니다)
     등방 blur 로 대신한다. 짧은 교차 중에만 걸려 번지는 잔상처럼 읽힌다. */
  --ff-blur: 5px;
  --ff-ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* 두 세트를 같은 칸에 겹쳐 두는 스택.
   박스 크기는 JS 가 잰 "현재 세트"의 크기로 애니메이션한다.

   ⚠ 이 height 전환은 #pc-header 의 overflow-anchor: none 에 의존한다 ⚠
   #pc-header 는 position: sticky 이면서 문서 흐름 안(문서 최상단)에 있다.
   이 박스의 height 가 바뀌면 문서 높이도 바뀌고, 브라우저는 보던 위치를 지키려고
   앵커 노드를 하나 잡아 scrollTop 을 보정한다. 그 앵커가 헤더 안쪽 노드
   (= 붙어 있는 sticky 요소 안)로 뽑히면, 앵커의 화면 위치는 스크롤이 아니라
   sticky 가 붙잡고 있어서 보정이 수렴하지 않는다. 브라우저는 프레임마다 다시
   보정하고 → 헤더 하단 선이 떤다.
   #pc-header 의 overflow-anchor: none 이 헤더 전체를 앵커 후보에서 빼
   이 폭주를 막는다. 그 선언을 지우면 떨림이 그대로 돌아온다. */
.ff-header {
  /* 안쪽 em 이 전부 이 값을 기준으로 계산된다 */
  font-size: var(--ff-header-fs);
  /* 글자 블록을 박스 세로 가운데로 내린다(위 --ff-optical-shift 설명).
     로고와 ff-title 이 같은 박스 안에서 함께 내려가므로 둘의 정렬선은 그대로다.
     transform 이라 레이아웃·측정값(script.js)에는 영향이 없다. */
  transform: translateY(calc(var(--ff-logo-size) * var(--ff-optical-shift)));
  display: grid;
  justify-items: start;
  align-items: start;
  width: var(--ff-set-w, auto);
  height: var(--ff-set-h, auto);
  transition: width var(--ff-duration) var(--ff-ease), height var(--ff-duration) var(--ff-ease);
}

/* 한 세트 = 로고 한 변형 + ff-title.
   아래쪽 기준으로 맞춰 ff-title 이 로고 마지막 줄 옆에 온다. */
.ff-set {
  grid-area: 1/1;
  display: flex;
  align-items: flex-end;
  gap: 5px;
  /* 위치 이동 없이 투명도 + 흐림으로만 교차한다 */
  transition: opacity var(--ff-fade) var(--ff-ease), filter var(--ff-fade) var(--ff-ease);
}

.ff-logo {
  /* 두 변형을 같은 그리드 칸에 겹쳐 아래쪽 기준으로 맞춘다 */
  display: grid;
  align-items: end;
  justify-items: start;
  /* 글자색은 .ep-gradient-title (그라디언트 면 + 글자 마스크)가 칠한다.
       --ff-accent 는 유틸 클래스를 뗐을 때의 기준색으로 남겨둔다. */
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-synthesis: none;
  line-height: 0.92;
  text-transform: uppercase;
  /* JS 측정값. 값이 들어오기 전에는 풀 버전의 자연 크기를 그대로 쓴다 */
  width: var(--ff-logo-w, auto);
  height: var(--ff-logo-h, auto);
  /* 축약형은 ff-title 보다 낮아서 아래쪽 정렬만으로는 가라앉아 보인다.
     JS 가 두 요소 높이차의 절반을 넣어 한 줄에 맞춘다. */
  transform: translateY(var(--ff-logo-shift, 0px));
  /* 값 자체는 세트별 상수지만, 측정 재실행(리사이즈 · 웹폰트 로드)으로
     바뀔 때 부드럽게 따라가도록 전환을 걸어둔다. */
  transition: width var(--ff-duration) var(--ff-ease), height var(--ff-duration) var(--ff-ease), transform var(--ff-duration) var(--ff-ease);
}

.ff-logo__variant {
  grid-area: 1/1;
  display: block;
  white-space: nowrap;
  /* .ep-gradient-title 의 그라디언트 면은 요소 박스 안에서만 칠해진다.
       line-height 가 1 보다 작아 글자가 박스 위로 넘치면 그 부분이 칠해지지 않아
       잘려 보인다. 위아래로 면을 넓히고, 음수 margin 으로 배치는 그대로 둔다.
       (JS 는 padding 을 뺀 content 높이를 재므로 헤더 높이도 변하지 않는다) */
  padding-top: var(--ff-logo-bleed);
  padding-bottom: var(--ff-logo-bleed);
  margin-top: calc(var(--ff-logo-bleed) * -1);
  margin-bottom: calc(var(--ff-logo-bleed) * -1);
}

/* JS 가 크기를 넣기 전에는 둘 중 큰 쪽(풀 버전)이 자연 크기를 결정한다 */
.ff-logo__full {
  font-size: var(--ff-logo-size);
}

/* 줄 단위 요소 — 마지막 줄 폭을 재기 위해 각 줄이 자기 폭을 갖는다 */
.ff-logo__line {
  display: block;
  width: max-content;
}

.ff-logo__short {
  font-size: var(--ff-logo-size-short);
}

.ff-header[data-ff-state=full] .ff-set[data-ff-set=full],
.ff-header[data-ff-state=short] .ff-set[data-ff-set=short] {
  opacity: 1;
  /* 제자리에서는 filter 레이어를 만들지 않는다(글자 래스터화 방지).
     none ↔ blur() 는 blur(0) 기준으로 보간되므로 전환은 그대로 이어진다. */
  filter: none;
}

.ff-header[data-ff-state=full] .ff-set[data-ff-set=short] {
  opacity: 0;
  filter: blur(var(--ff-blur));
  pointer-events: none;
}

.ff-header[data-ff-state=short] .ff-set[data-ff-set=full] {
  opacity: 0;
  filter: blur(var(--ff-blur));
  pointer-events: none;
}

/* 측정 중에는 애니메이션을 멈춘다 (초기 로드·리사이즈·웹폰트 로드) */
.ff-header[data-ff-measuring],
.ff-header[data-ff-measuring] .ff-set,
.ff-header[data-ff-measuring] .ff-logo {
  transition: none;
}

/* ff-components-reveal 이 true 일 때만 출력되는 영화제 타이틀 */
.ff-title {
  margin: 0;
  padding-bottom: 0.2em;
  font-family: var(--font-body);
  /* 로고(PP Formula Bold)와 무게 차이를 둬서 위계를 만든다.
     kigsans 는 Medium(500) · SemiBold(600) · Bold(700) 세 종이 있다. */
  font-weight: var(--fw-semibold);
  font-size: var(--ff-title-size);
  line-height: 1.2;
  /* ACF 텍스트영역에 입력한 줄바꿈만 반영하고 자동 줄바꿈은 막는다.
       pre-line 이면 줄이 한 번 더 접혀 로고 높이를 넘어서고, 그러면
       마지막 줄 기준으로 좁혀둔 로고 박스 밖으로 넘친 윗줄과 글자가 겹친다. */
  white-space: pre;
  /* flex 로 눌리면 안 된다 — 부모 폭이 1px 만 부족해도 줄이 접힌다 */
  flex: 0 0 auto;
  /* 레이아웃은 그대로 두고 시각적으로만 올린다(transform 이라 리플로우 없음).
     너무 키우면 로고 박스 밖으로 넘친 윗줄 글자와 겹친다. JS 의 겹침 가드는
     이 보정을 계산에 넣지 않으므로, 값을 크게 바꿀 때는 눈으로 확인할 것. */
  transform: translateY(calc(var(--ff-title-lift) * -1));
}

/* 모바일은 로고와 타이틀의 비율 자체가 달라서 기준을 따로 둔다.
   390px 폭에서 예전 모바일 크기와 같고, 그보다 좁으면 함께 줄어든다.
   넓어지는 쪽은 18px 에서 멈춘다 — 태블릿 폭까지 키우면 메뉴와 부딪힌다. */
@media (max-width: 768px) {
  :root {
    --ff-header-ref: 390;
    --ff-header-fs: clamp(15px, calc(100vw * 18 / var(--ff-header-ref)), 18px);
    --ff-logo-size: 1.6em;
    --ff-title-gap: 0.4444em; /* 8px ÷ 18px */
    --ff-title-size: 0.62em;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ff-header,
  .ff-set,
  .ff-logo {
    transition: none;
  }
  /* 위 상태 규칙(0,4,0)과 같은 특이도로, 뒤에 와서 흐림만 끈다 */
  .ff-header[data-ff-state] .ff-set[data-ff-set] {
    filter: none;
  }
}
/* ----- Festival Header End ----- */
/* ==================================================================
   PC Header — Main Menu + Hover Submenu
   ------------------------------------------------------------------
   마크업 (child theme [menu] 숏코드 → wp_nav_menu 기본 출력)
   #pc-header > .menu-main-menu-container > ul#menu-main-menu.menu
     └ li.menu-item.menu-item-has-children
         ├ a                  ← 주메뉴
         └ ul.sub-menu         ← 호버 시 하단에 뜨는 서브메뉴 행
             └ li.menu-item > a

   [인터랙션]
   · 주메뉴 호버(또는 키보드 포커스) → 해당 서브메뉴가 주메뉴 행 하단에 표시
   · 호버 / 키보드 포커스 / 현재 페이지 → opacity 1
   · 그 외 전부 → opacity 0.5  (--ep-menu-dim)
   · 서브메뉴 안에서도 같은 규칙이 독립적으로 적용된다

   [구현 메모]
   · ul.menu 가 서브메뉴의 기준 박스다. 테마 전역에 * { position: relative }
   가 걸려 있어 li 를 position:static 으로 되돌려야 서브메뉴가 li 가 아닌
   ul 기준(= 주메뉴 행 전체 폭)으로 잡힌다. 이게 두 행의 오른쪽 끝을 맞춘다.
   · 주메뉴와 서브메뉴 사이 간격은 margin 이 아니라 서브메뉴의 padding-top 으로
   만든다. margin 이면 그 틈에서 호버가 끊겨 마우스를 내리는 중 닫혀버린다.
   · 닫힌 상태에 visibility:hidden 을 쓰지 않는다. 그러면 서브메뉴 링크가
   포커스를 못 받아 :focus-within 이 영원히 발동하지 않는다(키보드 접근 불가).
   opacity 0 + pointer-events:none 으로 처리해 포커스 가능 상태를 유지한다.
================================================================== */
:root {
  --ep-menu-color: #6f14ff;
  --ep-menu-dim: 0.5;
  /* 오픈 전 메뉴(hide)의 투명도. 호버 때 흐려지는 다른 메뉴(--ep-menu-dim)보다
     한 단계 더 흐리게 둬서 "지금은 못 누르는 메뉴"로 구분된다. */
  --ep-menu-disabled: 0.3;
  --ep-menu-speed: 0.25s;
  --ep-menu-size: 1.2rem;
  --ep-menu-weight: var(--fw-semibold);
  --ep-menu-gap: 1rem;
  --ep-submenu-size: 0.95rem;
  --ep-submenu-weight: var(--fw-semibold);
  --ep-submenu-gap: 1rem;
  /* 주메뉴 행과 서브메뉴 행 사이 간격.
     서브메뉴의 padding-top 이라 이 틈에서도 호버가 끊기지 않는다(0 이면 안 된다).
     헤더가 자리를 잡아두는 높이도 이 값을 따라간다(아래 .menu-main-menu-container). */
  --ep-submenu-offset: 0.5rem;
  /* 서브메뉴 글자 아래에 두는 여유.
     헤더가 축약되면 로고가 작아져 "주메뉴 + 서브메뉴" 블록이 헤더 높이를 정한다.
     이 값이 0 이면 서브메뉴가 헤더 아래 선에 바짝 붙는다. */
  --ep-submenu-gapBottom: 0.5rem;
}

/* 로고(.ff-header)와 메뉴를 한 행에 좌/우로 배치.
   위쪽 "Site header" 블록의 #pc-header 규칙(sticky · z-index · padding ·
   background)은 그대로 살리고 여기서는 레이아웃만 얹는다.
   position 을 다시 선언하면 sticky 가 깨지므로 건드리지 않는다.
   sticky 자체가 배치 기준(positioned ancestor)이 되므로 서브메뉴 위치도 문제없다.
   .ff-header 내부는 별도 작업 영역이라 손대지 않는다. */
#pc-header {
  display: flex;
  align-items: flex-start;
  gap: var(--ep-menu-gap);
}

/* 메뉴 영역이 로고 오른쪽 남은 폭을 전부 차지한다.
   그래야 주메뉴 행과 서브메뉴 행의 오른쪽 끝이 항목 개수와 무관하게
   페이지 우측 여백에 똑같이 맞는다. */
/* .ff-header 는 절대 줄어들면 안 된다.
   JS 가 잰 세트 폭(--ff-set-w)을 width 로 넣어도, flex 아이템의 기본
   flex-shrink 는 1 이라 한 줄이 좁아지면 그 아래로 눌린다. 그러면
   ff-title 이 한 줄 더 접히고(2줄 → 3줄), 더 나쁜 건 측정 자체가
   눌린 상태에서 이뤄져 잘못된 폭이 그대로 굳는다는 점이다. */
#pc-header > .ff-header {
  flex: 0 0 auto;
}

#pc-header > .menu-main-menu-container {
  flex: 1 1 auto;
  min-width: 0;
}

/* ----- 주메뉴 행 ----- */
#pc-header ul.menu {
  /* 서브메뉴의 기준 박스 */
  position: relative;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: 0 var(--ep-menu-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

#pc-header ul.menu > li {
  /* 서브메뉴의 기준 박스 — 서브메뉴 왼쪽 선을 이 주메뉴 항목에 맞춘다.
     (전역 * { position: relative } 과 같은 값이지만, 기준이라는 뜻이라 적어 둔다) */
  position: relative;
  margin: 0;
  padding: 0;
  white-space: nowrap;
}

#pc-header ul.menu > li > a {
  display: block;
  font-size: var(--ep-menu-size);
  font-weight: var(--ep-menu-weight);
  line-height: 1.2;
  color: var(--ep-menu-color);
  opacity: var(--ep-menu-rest);
  transition: opacity var(--ep-menu-speed) ease;
}

/* ----- 서브메뉴 행 (주메뉴 행 하단) ----- */
#pc-header ul.menu > li > ul.sub-menu {
  position: absolute;
  top: 100%;
  left: 0;
  right: auto;
  /* 기준 박스가 주메뉴 항목(좁다)이라, 폭을 두지 않으면 그 폭에 맞춰
     한 줄짜리 서브메뉴가 여러 줄로 접힌다. 내용 폭으로 펴 둔다. */
  width: max-content;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  align-items: baseline;
  gap: 0 10px;
  /* 주메뉴와의 간격은 padding 으로 — 호버 경로가 끊기지 않게.
     왼쪽 음수 마진은 화면 밖으로 나가는 경우의 보정이다. 오른쪽 끝 항목의
     서브메뉴가 길면 script.js 가 넘친 만큼 --ep-submenu-shift 를 넣는다.
     넘치지 않으면 0 — 그대로 주메뉴 항목 왼쪽 정렬이다.
     (margin 단축 속성이라 margin-left 를 따로 쓰면 여기서 덮인다) */
  margin: 0 0 0 calc(var(--ep-submenu-shift, 0px) * -1);
  padding: var(--ep-submenu-offset) 0 0;
  list-style: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--ep-menu-speed) ease;
}

#pc-header ul.menu > li:hover > ul.sub-menu,
#pc-header ul.menu > li:focus-within > ul.sub-menu {
  opacity: 1;
  pointer-events: auto;
  z-index: 1;
}

/* ----- 현재 섹션의 서브메뉴는 기본 노출 -----
   지금 보고 있는 페이지가 속한 주메뉴(WP 가 붙이는 current-* / current_page_* 클래스)의
   서브메뉴를 호버 없이도 띄워둔다. */
#pc-header ul.menu > li:is(.current-menu-item,
.current-menu-parent,
.current-menu-ancestor,
.current_page_item,
.current_page_parent,
.current_page_ancestor) > ul.sub-menu {
  opacity: 1;
  pointer-events: auto;
  z-index: 1;
}

/* 다른 주메뉴를 호버·포커스하는 동안에는 그 서브메뉴에 자리를 내준다.
   서브메뉴 행은 주메뉴 항목마다 제자리(각 항목의 왼쪽 선, top: 100%)에 뜨는데
   같은 줄을 공유하므로, 숨기지 않으면 두 서브메뉴가 나란히/겹쳐 보인다. opacity 전환이 있어 교차 페이드된다.
   현재 섹션 자신을 호버할 때는 :not(:hover) 에 걸리지 않아 그대로 보인다. */
#pc-header ul.menu:has(> li:hover, > li:focus-within) > li:is(.current-menu-item,
.current-menu-parent,
.current-menu-ancestor,
.current_page_item,
.current_page_parent,
.current_page_ancestor):not(:hover):not(:focus-within) > ul.sub-menu {
  opacity: 0;
  pointer-events: none;
}

/* 현재 섹션 서브메뉴가 있으면 헤더가 서브메뉴 행 높이만큼 자리를 잡는다.
   서브메뉴 행은 absolute 라 원래는 헤더 높이에 포함되지 않는다. 풀 버전에서는
   두 줄짜리 로고(약 85px) 안에 주메뉴 행 + 서브메뉴 행(약 62px)이 들어가서
   문제가 없지만, 축약형 로고(약 43px)만으로는 서브메뉴가 헤더 아래로 삐져나와
   흰 배경 밖, 본문 위에 떠 버린다.
   메뉴 영역 아래에 서브메뉴 행 높이(위 간격 + 글자 줄 높이 1.2)만큼 패딩을 줘서
   헤더 높이가 max(로고, 주메뉴 + 서브메뉴) 가 되게 한다. 풀 버전은 로고가 더 커서
   그대로이고, 축약형만 약 43px → 62px 로 서브메뉴를 품는다.
   활성 메뉴가 없는 페이지(메인 등)는 영향이 없다. */
#pc-header:has(ul.menu > li:is(.current-menu-item,
.current-menu-parent,
.current-menu-ancestor,
.current_page_item,
.current_page_parent,
.current_page_ancestor) > ul.sub-menu) > .menu-main-menu-container {
  padding-bottom: calc(var(--ep-submenu-offset) + var(--ep-submenu-size) * 1.2 + var(--ep-submenu-gapBottom));
}

#pc-header ul.menu ul.sub-menu > li {
  position: static;
  margin: 0;
  padding: 0;
  white-space: nowrap;
}

#pc-header ul.menu ul.sub-menu > li > a {
  display: block;
  font-size: var(--ep-submenu-size);
  font-weight: var(--ep-submenu-weight);
  line-height: 1.2;
  color: var(--ep-menu-color);
  opacity: var(--ep-menu-rest);
  transition: opacity var(--ep-menu-speed) ease;
}

/* ----- opacity 인터랙션 -----
   기본값은 전부 opacity 1. 같은 목록 안에 호버 / 키보드 포커스 / 현재 페이지
   항목이 "있을 때만" 나머지가 --ep-menu-dim 으로 흐려진다.

   조건 판정(:has)과 값 적용을 --ep-menu-rest 변수로 분리한 이유:
   :has() 를 넣은 선택자는 특이도가 li:hover 선택자보다 높아져서, 한 선택자로
   흐리게 처리하면 호버한 항목까지 같이 흐려진다. 조건은 변수로 넘기고
   적용 규칙끼리는 단순한 특이도 관계(li > a  <  li:hover > a)만 남긴다.

   :has() 미지원 브라우저에서는 변수가 1로 남아 전부 opacity 1 —
   즉 기본 상태로 degrade 한다.

   WP 는 메뉴 항목에 하이픈(current-menu-*)과 언더스코어(current_page_*)
   두 계열의 클래스를 모두 붙이므로 양쪽을 다 받는다.

   주메뉴와 서브메뉴는 각자 변수를 따로 선언해 독립적으로 판정한다.
   (선언하지 않으면 주메뉴의 값이 서브메뉴로 상속돼, 주메뉴를 호버하는 순간
  서브메뉴 항목이 전부 흐려진다) */
#pc-header ul.menu,
#pc-header ul.sub-menu {
  --ep-menu-rest: 1;
}

#pc-header ul.menu:has(> li:hover),
#pc-header ul.menu:has(> li:focus-within),
#pc-header ul.menu:has(> li.current-menu-item),
#pc-header ul.menu:has(> li.current-menu-parent),
#pc-header ul.menu:has(> li.current-menu-ancestor),
#pc-header ul.menu:has(> li.current_page_item),
#pc-header ul.menu:has(> li.current_page_parent),
#pc-header ul.menu:has(> li.current_page_ancestor),
#pc-header ul.sub-menu:has(> li:hover),
#pc-header ul.sub-menu:has(> li:focus-within),
#pc-header ul.sub-menu:has(> li.current-menu-item),
#pc-header ul.sub-menu:has(> li.current_page_item) {
  --ep-menu-rest: var(--ep-menu-dim);
}

/* 흐려진 목록 안에서 호버 · 포커스 · 현재 페이지 항목만 다시 1 */
#pc-header ul.menu > li:hover > a,
#pc-header ul.menu > li:focus-within > a,
#pc-header ul.menu > li.current-menu-item > a,
#pc-header ul.menu > li.current-menu-parent > a,
#pc-header ul.menu > li.current-menu-ancestor > a,
#pc-header ul.menu > li.current_page_item > a,
#pc-header ul.menu > li.current_page_parent > a,
#pc-header ul.menu > li.current_page_ancestor > a,
#pc-header ul.menu ul.sub-menu > li:hover > a,
#pc-header ul.menu ul.sub-menu > li:focus-within > a,
#pc-header ul.menu ul.sub-menu > li.current-menu-item > a,
#pc-header ul.menu ul.sub-menu > li.current_page_item > a {
  opacity: 1;
}

/* 키보드 포커스 링 — 마우스 사용 시엔 GP 가 body.using-mouse 를 붙인다 */
/* ----- 오픈 전 메뉴 — 메뉴 항목 CSS 클래스 hide -----
   마우스 반응을 끄고 항상 흐리게 둔다. li 에 pointer-events: none 을 걸어
   그 아래 서브메뉴까지 호버로 열리지 않는다. 링크(href) 제거와 하위 항목 처리는
   functions.php 의 ep_menu_mark_hidden 이 맡는다 (키보드 · 스크린리더 차단).

   특이도 (1,3,3) — 기본 투명도 규칙(주메뉴 1,1,3 / 서브메뉴 1,2,4)을 이긴다.
   호버 · 포커스 · 현재 페이지 규칙은 이 항목에 걸릴 수 없어 겨룰 일이 없다. */
#pc-header ul.menu li.menu-item.hide,
#pc-header ul.menu li.menu-item.hide-inherit {
  pointer-events: none;
}

#pc-header ul.menu li.menu-item.hide > a,
#pc-header ul.menu li.menu-item.hide-inherit > a {
  opacity: var(--ep-menu-disabled);
  cursor: default;
}

#pc-header ul.menu a:focus-visible {
  outline: 2px solid var(--ep-menu-color);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  #pc-header ul.menu a,
  #pc-header ul.menu ul.sub-menu {
    transition: none;
  }
}
/* ----- 오픈 전 잠금 항목 (inc/menu.php) -----
   메뉴 항목에 menu-locked 클래스를 주면 서버가 href 를 빼고 is-locked 를
   붙인다(하위 항목까지). 여기서는 "아직 열리지 않았다"는 모양만 잡는다.
   - 늘 흐린 상태로 두고, 호버해도 밝아지지 않는다
   - 하위 메뉴는 열지 않는다
   관리자(페이지 편집 권한)에게는 is-locked 가 붙지 않아 평소처럼 보인다. */
#pc-header ul.menu li.is-locked > a,
#pc-header ul.menu ul.sub-menu > li.is-locked > a {
  opacity: var(--ep-menu-dim);
  cursor: default;
}

#pc-header ul.menu > li.is-locked > ul.sub-menu {
  display: none;
}

/* ----- PC Header End ----- */
/* ==================================================================
   Top Banner  (shortcode: [print_top_banner])
   ------------------------------------------------------------------
   화면 최상단 고정 띠배너. position: fixed 라 문서 흐름에서 빠지므로
   body 에 배너 높이만큼 padding-top 을 주어 그 아래로 메인 헤더가 온다.
   #pc-header(역시 fixed)는 기준점(top)을 배너 높이로 옮긴다. 그러면 헤더가
   배너 바로 아래에 붙고, 헤더 자신의 위쪽 패딩(--ep-header-padY)이
   배너와 타이틀 사이 간격이 된다.

   [조절]
     배율  --ep-topbar-scale — 국문 · 영문 · SNS 아이콘 · 간격을 한꺼번에 키우고 줄인다.
           아래 크기 변수들은 전부 "기준값 × 배율"이라 서로의 비율이 유지된다.
     높이  --ep-topbar-h
     글자  --ep-topbar-size (PC 고정값 · 모바일 보라 띠는 따로 덮는다)
     간격  --ep-topbar-gap
================================================================== */
:root {
  --ep-topbar-scale: 1.3;
  --ep-topbar-h: 40px;
  /* PC 탑 바 문구 크기. 배율(--ep-topbar-scale)을 따르지 않는 고정값.
     모바일 헤더의 보라 띠도 이 변수를 쓰는데, 거기서는 12px 로 되돌린다
     (_mobile-header.scss 의 #mo-header). */
  --ep-topbar-size: 19px;
  --ep-topbar-gap: calc(0.8rem * var(--ep-topbar-scale));
  --ep-topbar-itemGap: calc(0.45rem * var(--ep-topbar-scale));
  --ep-sns-h: calc(17.5px * var(--ep-topbar-scale));
  --ep-sns-gap: 10px;
}

/* 배너가 실제로 있을 때만 자리를 비운다.
   (숏코드를 넣지 않은 페이지에서 상단이 비어 보이지 않게) */
body:has(.ff-topbar) {
  /* 배너(fixed) + 메인 헤더(fixed) 높이. 헤더 쪽 몫은 _festival-header.scss
     의 body 규칙과 같은 값이다 — 배너가 있는 페이지는 둘을 더해야 하므로
     따로 선언하지 못하고 여기서 한 번에 계산한다. */
  padding-top: calc(var(--ep-topbar-h) + var(--ff-headerSpace, var(--ff-headerSpace-fallback)));
}

/* 메인 헤더는 띠배너 아래에 고정된다 */
body:has(.ff-topbar) #pc-header {
  top: var(--ep-topbar-h);
}

.ff-topbar {
  position: fixed;
  top: 0;
  right: 0;
  left: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ep-topbar-gap);
  height: var(--ep-topbar-h);
  padding: 0 var(--ep-margin);
  background-color: var(--color-black);
  color: var(--color-white);
  font-size: var(--ep-topbar-size);
  font-weight: var(--fw-semibold);
  line-height: 1;
}

.ff-topbar a {
  color: inherit;
}

.ff-topbar__left,
.ff-topbar__right {
  display: flex;
  align-items: center;
  gap: var(--ep-topbar-gap);
  min-width: 0;
}

/* 문구 — 세로선 — 기간 은 같은 위계라 간격을 따로 좁게 둔다 */
.ff-topbar__left {
  gap: var(--ep-topbar-itemGap);
}

/* 좁은 화면에서 좌측 문구가 우측 링크를 밀어내지 않게 한다 */
.ff-topbar__left {
  overflow: hidden;
}

.ff-topbar__text {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 구분자 — 3px 세로선 */
.ff-topbar__sep {
  flex: 0 0 auto;
  width: 2px;
  height: 1em;
  background-color: currentColor;
}

.ff-topbar__period {
  flex: 0 0 auto;
  white-space: nowrap;
}

.ff-topbar__right {
  flex: 0 0 auto;
}

/* ----- SNS 아이콘 ----- */
/* 아이콘마다 원본 비율이 달라(ig 27 / youtube·x 19 / facebook 25 높이)
   높이를 하나로 맞추면 디자인상의 크기 관계가 깨진다.
   가장 큰 27 을 기준(--ep-sns-h)으로 두고 나머지는 원본 비율만큼 줄인다. */
.ff-topbar__sns {
  display: flex;
  align-items: center;
  gap: var(--ep-sns-gap);
  flex: 0 0 auto;
}

.ff-topbar__sns-item {
  display: flex;
  align-items: center;
  color: inherit;
  transition: opacity 0.2s ease;
}

.ff-topbar__sns-item:hover,
.ff-topbar__sns-item:focus-visible {
  opacity: 0.6;
}

.ff-topbar__sns svg {
  display: block;
  width: auto;
  height: var(--ep-sns-h);
}

/* SVG 에 박혀 있는 fill="white" 대신 배너 글자색을 따르게 한다 */
.ff-topbar__sns svg path {
  fill: currentColor;
}

/* 인스타그램은 --ep-sns-h 기준(비율 1)인데, 사각형 마크라 같은 높이에서도
   다른 아이콘보다 커 보인다. 시각적으로 맞춰 조금 줄인다. */
.ff-topbar__sns-item--ig svg {
  height: calc(var(--ep-sns-h) * 0.85);
}

.ff-topbar__sns-item--youtube svg {
  height: calc(var(--ep-sns-h) * 0.704);
}

/* X 아이콘은 24 뷰박스 안에서 글리프가 21.75 만 차지한다(위아래 여백 포함).
   그래서 다른 아이콘과 같은 방식으로 높이를 주면 글리프가 작아 보인다.
   여백만큼 키워 글리프 크기를 기존 트위터 아이콘(19/27)과 맞춘다. */
.ff-topbar__sns-item--x svg {
  height: calc(var(--ep-sns-h) * 0.777);
}

.ff-topbar__sns-item--facebook svg {
  height: calc(var(--ep-sns-h) * 0.926);
}

.ff-topbar__menu {
  display: flex;
  align-items: center;
  gap: var(--ep-topbar-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ff-topbar__menu li {
  margin: 0;
  padding: 0;
  list-style: none;
  white-space: nowrap;
}

@media (max-width: 768px) {
  :root {
    --ep-topbar-h: 30px;
    --ep-topbar-gap: calc(0.7rem * var(--ep-topbar-scale));
    --ep-topbar-itemGap: calc(0.45rem * var(--ep-topbar-scale));
    --ep-sns-h: calc(15px * var(--ep-topbar-scale));
    --ep-sns-gap: calc(8px * var(--ep-topbar-scale));
  }
}
/* ----- 페이지 링크 · SEARCH 버튼 -----
   SNS 오른쪽에 SEARCH → SIFF PLUS → ARCHIVE 순으로 이어진다.
   영문 대문자 디스플레이 서체(PP Formula)로, 좌측 문구보다 한 단계 크게 둔다. */
:root {
  /* PC 탑 바 링크·SEARCH 글자 크기. 배율을 따르지 않는 고정값.
     1024px 이하는 .ff-topbar__link 규칙에서 15px 로 덮는다. */
  --ep-topbar-link-size: 22px;
  /* PP Formula 는 line-height: 1 에서 대문자가 박스 중앙보다 0.1em 위에 뜬다.
       폰트 메트릭(unitsPerEm 1000, ascent 880 / descent 280 / capHeight 800 —
       hhea · typo · win 셋 다 같다)으로 계산한 값이다.
         콘텐츠 영역 1160 이 줄 높이 1000 보다 커서 위아래로 80 씩 넘치고,
         베이스라인은 박스 위에서 0.8em → 대문자 중심은 0.4em (박스 중앙 0.5em)
       글자만 이만큼 내려 대문자 중심을 박스 중앙에 맞춘다. */
  --ep-display-cap-shift: 0.1em;
}

.ff-topbar__links {
  display: flex;
  align-items: center;
  gap: var(--ep-topbar-gap);
  flex: 0 0 auto;
}
@media (max-width: 780px) {
  .ff-topbar__links {
    gap: 10px;
  }
}

/* 전역 button 규칙이 font-family / font-size / line-height 를 !important 로
   고정하고, GP 는 button 에 배경·패딩을 입힌다. 클래스 선택자는 타입 선택자보다
   특이도가 높으므로 !important 끼리 맞서도 이쪽이 이긴다.
   .ff-topbar 로 스코프를 좁히지 않는다 — 모바일 헤더(#mo-header)도 같은
   SEARCH 버튼과 페이지 링크를 쓰기 때문이다. */
.ff-topbar__link,
.ff-topbar__search {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  font-family: var(--font-display) !important;
  font-size: var(--ep-topbar-link-size) !important;
  font-weight: var(--fw-bold);
  font-synthesis: none;
  line-height: 1 !important;
  text-transform: uppercase;
  white-space: nowrap;
  color: inherit;
  transition: opacity 0.2s ease;
}
@media (max-width: 1024px) {
  .ff-topbar__link,
  .ff-topbar__search {
    font-size: 18px !important;
  }
}

.ff-topbar__search {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  cursor: pointer;
}

.ff-topbar__search:hover,
.ff-topbar__search:focus {
  background: none;
  color: inherit;
}

.ff-topbar__link:hover,
.ff-topbar__search:hover {
  opacity: 0.6;
}

.ff-topbar__link:focus-visible,
.ff-topbar__search:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* 아이콘을 대문자 높이에 맞춘다 */
.ff-topbar__search svg {
  display: block;
  width: auto;
  height: 0.72em;
}

/* 글자만 내린다. SEARCH 는 아이콘이 이미 박스 중앙에 있으므로 버튼 전체가 아니라
   라벨만 옮겨야 아이콘과 글자 중심이 맞는다. transform 이라 레이아웃은 그대로다. */
.ff-topbar__link,
.ff-topbar__search-label {
  transform: translateY(var(--ep-display-cap-shift));
}

/* ==================================================================
   Search Overlay  (#ff-search — functions.php 가 wp_footer 에 출력)
   ------------------------------------------------------------------
   SEARCH 를 누르면 탑 바 아래부터 화면 끝까지 덮는 레이어가 깔린다.
   시작 지점(--ff-search-top)은 script.js 가 탑 바(모바일은 고정된 헤더
   덩어리)의 아래쪽 좌표를 재서 넣는다. 폭·로고 크기에 따라 높이가 달라져
   CSS 만으로는 알 수 없다.

   위에 입력창, 그 아래로 결과가 이어진다. 입력하는 동안 script.js 가
   /wp-json/siff/v1/search 를 불러 목록을 채운다. 스크롤은 결과 영역만 한다.

   [조절]
     배경/글자  --ep-search-bg / --ep-search-fg
     입력 글자  --ep-search-size
     결과 글자  --ep-search-item / --ep-search-meta
     속도       --ep-search-duration
================================================================== */
:root {
  --ep-search-bg: rgba(0, 0, 0, 0.7);
  --ep-search-fg: var(--color-white);
  --ep-search-blur: 18px;
  --ep-search-size: clamp(1.5rem, 3.2vw, 2.4rem);
  --ep-search-item: clamp(0.95rem, 1.5vw, 1.15rem);
  --ep-search-meta: 0.8rem;
  --ep-search-duration: 0.3s;
  --ep-search-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* 오버레이(검색 · 모바일 메뉴)가 열려 있는 동안 뒤 페이지 스크롤을 막는다 */
html.ff-overlay-open {
  overflow: hidden;
}

.ff-search {
  position: fixed;
  top: var(--ff-search-top, 0px);
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  padding: 1.1rem var(--ep-margin) 0;
  background-color: var(--ep-search-bg);
  -webkit-backdrop-filter: blur(var(--ep-search-blur));
  backdrop-filter: blur(var(--ep-search-blur));
  color: var(--ep-search-fg);
  /* 스크롤은 결과 영역만 한다 */
  overflow: hidden;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--ep-search-duration) var(--ep-search-ease), visibility 0s linear var(--ep-search-duration);
}

.ff-search.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--ep-search-duration) var(--ep-search-ease), visibility 0s;
}

/* ----- 입력 줄 ----- */
.ff-search__bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.4em;
  margin: 0;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid currentColor;
  font-size: var(--ep-search-size);
}

/* 전역 input 규칙(!important)과 GP 의 search 입력 스타일을 모두 덮는다 */
.ff-search .ff-search__input {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font-family: var(--font-body) !important;
  font-size: 1em !important;
  font-weight: var(--fw-bold);
  line-height: 1.25 !important;
  -webkit-appearance: none;
  appearance: none;
}

.ff-search .ff-search__input:focus {
  outline: none;
  background: none;
  color: inherit;
}

.ff-search .ff-search__input::placeholder {
  color: currentColor;
  opacity: 0.45;
}

.ff-search .ff-search__input::-webkit-search-cancel-button {
  display: none;
}

.ff-search .ff-search__submit,
.ff-search .ff-search__close {
  /* 전역 button 규칙이 font-size 를 1rem 으로 못박아서, em 으로 잡은 아이콘
     크기가 입력창 글자 크기를 따라가지 못한다. 부모(입력 줄) 기준으로 되돌린다. */
  font-size: 1em !important;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.ff-search .ff-search__submit:hover,
.ff-search .ff-search__submit:focus-visible,
.ff-search .ff-search__close:hover,
.ff-search .ff-search__close:focus-visible {
  background: none;
  color: inherit;
  opacity: 0.6;
}

.ff-search .ff-search__submit:focus-visible,
.ff-search .ff-search__close:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
}

.ff-search__submit svg,
.ff-search__close svg {
  display: block;
  width: 0.7em;
  height: 0.7em;
}

/* ----- 결과 ----- */
.ff-search__results {
  flex: 1 1 auto;
  /* flex 아이템 기본 min-height: auto 를 풀어야 안에서 스크롤된다 */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: var(--ep-margin);
}

.ff-search__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ff-search__item {
  margin: 0;
  list-style: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.16);
}

.ff-search__item > a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem 0;
  color: inherit;
  transition: opacity 0.2s ease;
}

.ff-search__item > a:hover,
.ff-search__item > a:focus-visible {
  opacity: 0.6;
}

.ff-search__title {
  font-size: var(--ep-search-item);
  font-weight: var(--fw-bold);
  line-height: 1.35;
}

.ff-search__meta {
  flex: 0 0 auto;
  font-size: var(--ep-search-meta);
  font-weight: var(--fw-medium);
  opacity: 0.55;
  white-space: nowrap;
}

.ff-search__empty {
  margin: 1.2rem 0 0;
  font-size: var(--ep-search-meta);
  opacity: 0.55;
}

@media (max-width: 768px) {
  /* 좁은 화면에서는 SEARCH 글자를 숨기고 아이콘만 남긴다 (스크린리더에는 남김) */
  .ff-topbar .ff-topbar__search-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .ff-topbar__search svg {
    height: 0.8em;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ff-search,
  .ff-search.is-open,
  .ff-search__item > a {
    transition: none;
  }
}
/* ==================================================================
   임시 — 정식 오픈 전까지 검색을 감춘다
   ------------------------------------------------------------------
   PC 탑 바  : SEARCH 버튼을 숨긴다.
   모바일 메뉴: 레이어 하단의 SEARCH FILMS 입력창을 숨긴다.
   (SIFF PLUS · ARCHIVE 링크는 2026-10-06 에 다시 열었다 — PC 탑 바·모바일 검정 줄 모두.)
                .mo-nav 는 flex 열 + gap 이라 숨기면 그 자리와 간격이 함께
                사라지고, 카드 격자(.mo-nav__body → flex: 1)가 남는 높이를
                그대로 받아 버튼이 자연스럽게 높아진다.
   오픈할 때 이 블록만 통째로 지우면 원래대로 돌아온다.
================================================================== */
.ff-topbar .ff-topbar__search,
.mo-nav .mo-nav__foot {
  display: none;
}

/* ----- Top Banner End ----- */
/* ==================================================================
   Mobile Header  (shortcode: [print_mobile_header] / GP Element)
   ------------------------------------------------------------------
   PC 헤더(#pc-header)와 구조가 달라 GP Element 를 따로 둔다.
   어느 쪽을 보여줄지는 화면 폭이 정하고, 둘 다 문서에는 출력된다.
   display: none 인 쪽은 접근성 트리에서도 빠져 스크린리더에 중복되지 않는다.

   [구조]
     #mo-header
       .mo-header__band   보라 띠 — 회차 · 기간. 문서 흐름에 그대로 둬서
                          스크롤하면 나머지와 함께 위로 올라가 사라진다.
       .mo-header__bar    sticky(top: 0) — 아래 두 줄이 한 덩어리로 붙는다.
         .mo-header__util   검정 줄 — SNS · 페이지 링크 · SEARCH
         .mo-header__main   보라 줄 — 로고 + ff-title + 메뉴(+) 버튼
         .mo-subnav         보라 줄 — 지금 섹션의 하위 항목 (있을 때만)

   [조절]
     전환 폭   $mo-bp (styles/_asset.scss 에 정의 — 여러 파티셜이 함께 쓴다)
     줄 높이   --mo-band-padY / --mo-util-padY / --mo-main-padY
               (높이를 직접 정하지 않고 위아래 패딩으로 잡는다. 글자·아이콘
                크기가 바뀌면 줄 높이도 따라 늘고 준다)
     색        --mo-main-bg / --mo-toggle-bg
               (보라 띠는 그라디언트 시스템 .ep-gradient 유틸을 그대로 쓴다)
================================================================== */
:root {
  /* 실제 내용 높이(보라 띠 13px · 검정 줄 18px)에 더해 기존 줄 높이
     32px / 36px 이 그대로 나오는 값 */
  --mo-band-padY: 9.5px;
  --mo-util-padY: 6px;
  --mo-main-padY: 18px;
  --mo-toggle-w: 28px;
  /* 서브메뉴 띠 */
  --mo-subnav-size: 0.95rem;
  --mo-subnav-gap: 1rem;
  --mo-subnav-padY: 8px;
  --mo-main-bg: #6f14ff;
  --mo-toggle-bg: rgba(255, 255, 255, 0.9);
  /* 메뉴 + 아이콘 — 선 길이 15px, 두께 2px, 색은 헤더 배경과 같은 값 */
  --mo-toggle-icon-w: 15px;
  --mo-toggle-icon-h: 2px;
  --mo-toggle-icon-color: var(--mo-main-bg);
  /* 화면 폭을 따라간다. 좁아져도 "로고 마지막 줄 + 회차 타이틀"이 한 줄에 남게.
     회차 타이틀이 커진 만큼(아래 참고) vw 계수를 9.2 → 8.5 로 낮췄다. */
  --mo-logo-size: clamp(1.4rem, 8.5vw, 2.6rem);
  /* 회차 타이틀 두 줄 높이가 로고 한 줄 높이를 넘으면, script.js 의 겹침 가드가
     로고 박스를 "가장 긴 줄" 폭으로 넓혀 타이틀이 로고 아래로 밀려난다.
     로고 크기에 비례시켜 항상 한 줄 높이 안에 들어오게 한다
     (0.3 × 로고 → 두 줄 = 0.3 × 2 × 1.35 = 0.81em < 로고 줄 높이 0.92em). */
  /* 회차 타이틀 두 줄이 로고 마지막 줄의 대문자 높이에 딱 맞게 들어가는 값.
     두 서체의 실제 수치로 계산했다.
       PP Formula  ascent .88  descent .28  capHeight .80   (줄간격 --mo-logo-lh)
       kigsans     ascent 1.08 descent .23  capHeight .846
     보이는 두 줄 높이 = 글자크기 × (줄간격 + capHeight) = 로고 대문자 높이(0.8em)
       → 줄간격 1.25 일 때 글자크기 = 0.382 × 로고
     줄간격을 1.35 로 두면 타이틀 박스가 로고 한 줄 높이를 넘어서, script.js 의
     겹침 가드가 로고 박스를 넓혀 타이틀이 아래로 밀려난다. 1.25 가 상한이다. */
  --mo-title-size: calc(var(--mo-logo-size) * 0.382);
  --mo-title-lh: 1.25;
  /* 아래 정렬 상태에서 글자 윗선을 로고 대문자 윗선에 맞추는 보정값 */
  --mo-title-lift: 0.19em;
  /* 사이트 타이틀(로고) 두 줄 간격. PC 기본값(0.92)보다 넓게. */
  --mo-logo-lh: 1.05;
  /* 메가메뉴 카드 격자 */
  --mo-nav-gap: 5px;
  --mo-nav-radius: 10px;
  --mo-nav-card-bg: #dfcbff;
  --mo-nav-ko-size: 0.95rem;
  --mo-nav-en-size: 0.9rem;
  /* 하단 검색 바 — 높이는 글자 + 패딩으로 정해진다 */
  --mo-nav-search-size: 20px;
  --mo-nav-search-padY: 0.7rem;
  --mo-nav-search-padX: 0.9rem;
  /* 돋보기는 글자 크기에 비례. 1 이면 글자 높이와 같다 */
  --mo-nav-search-icon: 1.1em;
  /* 열고 닫는 전환.
     배경(패널)이 먼저 깔리고, 카드 → 검색 바 순으로 조금씩 늦게 떠오른다.
     닫을 때는 지연 없이 한꺼번에, 그리고 조금 빠르게 사라진다. */
  /* 배경(패널)과 버튼(카드 · 검색 바)의 시간을 따로 둔다.
     배경이 먼저 자리를 잡고 버튼이 뒤따라오면 층이 나뉘어 보인다.
       열 때  : 배경 0.42s → 0.18s 뒤 버튼 0.6s (버튼이 더 천천히 맺힌다)
       닫을 때: 버튼 0.22s 먼저 → 배경 0.32s 로 조금 더 남아 있다 사라진다 */
  --mo-nav-bg-in: 0.42s;
  --mo-nav-bg-out: 0.32s;
  --mo-nav-in: 0.6s;
  --mo-nav-out: 0.22s;
  --mo-nav-lead: 0.18s;
  /* 끝으로 갈수록 천천히 멎는 곡선 — 떠오르다 사뿐히 내려앉는 느낌 */
  --mo-nav-ease: cubic-bezier(0.16, 1, 0.3, 1);
  /* 메뉴 패널 — 헤더에 쓰인 보라를 연하게 만들고 뒤를 흐린다.
     color-mix 를 못 쓰는 환경을 위해 같은 값의 rgba 를 먼저 선언해 둔다. */
  --mo-nav-tint: #a377ff;
  --mo-nav-tint: color-mix(in srgb, var(--mo-main-bg) 55%, #fff);
  --mo-nav-bg: rgba(163, 119, 255, 0.72);
  --mo-nav-bg: color-mix(in srgb, var(--mo-nav-tint) 72%, transparent);
  --mo-nav-blur: 16px;
  --mo-nav-fg: var(--ep-menu-color);
}

/* 기본(데스크톱)에서는 모바일 헤더와 메뉴 오버레이를 감춘다 */
#mo-header,
.mo-nav {
  display: none;
}

@media (max-width: 1024px) {
  /* ----- PC 헤더를 감추고 그 흔적을 지운다 -----
     #pc-header 안의 띠배너는 position: fixed 라 감춰도 body:has(.ff-topbar) 규칙이
     그대로 살아 padding-top 을 남긴다(:has 는 display: none 요소도 매칭한다).
     PC 헤더 몫(--ff-headerSpace 폴백)까지 들어 있으므로 둘 다 되돌린다.
     (JS 가 재는 --ff-headerSpace 는 헤더가 감춰져 있으면 0 이지만, 스크립트
     전 첫 페인트에서 폴백값이 남으므로 CSS 로도 끊어 준다.) */
  #pc-header {
    display: none;
  }
  body,
  body:has(.ff-topbar) {
    padding-top: 0;
  }
  /* display: contents — 이 요소는 박스를 만들지 않고 자식(.mo-header__band,
     .mo-header__bar)이 body 의 자식처럼 배치된다.
     sticky 는 "부모 박스 안에서만" 붙는다. #mo-header 가 박스를 만들면 그 높이가
     헤더 자신(약 225px)뿐이라, 그만큼 지나가는 순간 .mo-header__bar 도 같이
     스크롤되어 사라진다. 박스를 없애면 기준이 body 가 되어 페이지 끝까지 붙는다.
     박스가 없어도 색 상속은 그대로 내려간다. */
  #mo-header {
    display: contents;
    color: var(--color-white);
    /* 보라 띠 문구는 PC 탑 바(19px)보다 작게 — 좁은 폭에서 회차·기간이
       한 줄에 들어가야 해서 따로 둔다. */
    --ep-topbar-size: 13px;
  }
  #mo-header a {
    color: inherit;
  }
  /* ----- 보라 띠 : 회차 · 기간 (스크롤하면 사라진다) ----- */
  .mo-header__band {
    display: flex;
    align-items: center;
    gap: var(--ep-topbar-itemGap);
    padding: 8px var(--ep-margin) 6px;
    /* 배경은 그라디언트 시스템이 칠한다 — functions.php 가 .ep-gradient 유틸
       클래스를 붙인다. 여기서 background-color 를 선언하면 그 위를 덮는다. */
    /* ── 덩어리를 크고 부드럽게 ──
       덩어리 반지름은 "판(--ep-grad-mesh-size) 대비 비율"이다. 이 띠는
       가로 390px · 세로 26px 쯤이라, 판을 박스에 맞춰 두면 가로 반지름만
       100px 가까이 나오고 세로는 띠 높이에 갇혀 10px 대에 머문다 — 덩어리가
       가로로 늘어난 띠처럼 보이는 이유다.

       그래서 세로 판을 띠보다 훨씬 크게(약 500%) 잡아, 덩어리가 띠 위아래로
       넘치게 둔다. 화면에 보이는 것은 지름 200px 짜리 원의 가운데 26px
       토막이고, 원이 위아래로도 흘러다니므로 같은 자리라도 밝기가 변한다.

       [세로 판 값] 가로·세로 반지름이 픽셀로 같아지는(=진짜 원) 값이다.
         세로판% = (가로기준% / 세로기준%) × 가로판% × 15
         15 는 띠 비율(390 / 26)에서 나온 상수다.
       더 길쭉한 타원이 좋으면 이 값에 배수를 곱하면 된다.

       [배율 3.5 는 천장] 반지름이 판의 절반을 넘으면 덩어리가 판 밖으로
       나가는데, 레이어가 no-repeat 이라 그 바깥은 그려지지 않아 판 경계에서
       직각으로 잘린다. 가로 기준이 가장 큰 레이어가 14% 이므로
       14 × 3.5 = 49% 로 아슬아슬하게 안에 들어온다. 더 키우려면 배율이
       아니라 가로 판 %를 올려야 한다. */
    --ep-grad-mesh-size:
      56% 520%, 60% 540%, 54% 490%, 64% 560%, 66% 580%, 62% 540%, 100% 100%;
    --ep-grad-blob-scale: 3.5;
    font-size: var(--ep-topbar-size);
    font-weight: var(--fw-bold);
    line-height: 1;
    overflow: hidden;
  }
  .mo-header__text {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .mo-header__sep {
    flex: 0 0 auto;
    width: 3px;
    height: 0.95em;
    background-color: currentColor;
  }
  .mo-header__period {
    flex: 0 0 auto;
    white-space: nowrap;
  }
  /* ----- 서브메뉴 띠 : 지금 섹션의 하위 항목 (functions.php ep_get_mobile_subnav) -----
     메뉴를 2단까지 그대로 깔아두고, 현재 섹션의 서브메뉴만 드러낸다. PC 헤더의
     둘째 줄과 같은 방식이라 현재 위치 판정을 CSS 한 곳에서만 본다(_header.scss).
     항목이 많으면 옆으로 민다 — 줄바꿈으로 띠가 두 줄이 되면 헤더 높이가
     페이지마다 달라진다. */
  .mo-subnav {
    background-color: var(--mo-main-bg);
  }
  .mo-subnav__menu {
    margin: 0;
    padding: 0;
    list-style: none;
  }
  /* 1단 항목은 띠에 쓰지 않는다 — 서브메뉴를 담는 그릇으로만 둔다 */
  .mo-subnav__menu > li > a {
    display: none;
  }
  .mo-subnav__menu > li > ul.sub-menu {
    display: none;
  }
  /* 지금 보고 있는 섹션의 서브메뉴만 펼친다 */
  .mo-subnav__menu > li:is(.current-menu-item,
  .current-menu-parent,
  .current-menu-ancestor,
  .current_page_item,
  .current_page_parent,
  .current_page_ancestor) > ul.sub-menu {
    display: flex;
    gap: var(--mo-subnav-gap);
    margin: 0;
    padding: var(--mo-subnav-padY) var(--ep-margin);
    list-style: none;
    overflow-x: auto;
    /* 띠 안에서만 옆으로 밀리고, 끝에서 페이지가 따라 움직이지 않게 */
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .mo-subnav__menu ul.sub-menu::-webkit-scrollbar {
    display: none;
  }
  .mo-subnav__menu ul.sub-menu > li {
    flex: 0 0 auto;
  }
  .mo-subnav__menu ul.sub-menu > li > a {
    display: block;
    font-size: var(--mo-subnav-size);
    font-weight: var(--ep-menu-weight);
    line-height: 1;
    color: var(--color-white);
    opacity: 0.4;
    white-space: nowrap;
    transition: opacity var(--ep-menu-speed) ease;
  }
  .mo-subnav__menu ul.sub-menu > li:is(.current-menu-item, .current_page_item) > a,
  .mo-subnav__menu ul.sub-menu > li > a:hover,
  .mo-subnav__menu ul.sub-menu > li > a:focus-visible {
    opacity: 1;
  }
  /* 오픈 전 잠금 항목 — PC 메뉴와 같은 모양으로 (inc/menu.php · _header.scss) */
  .mo-subnav__menu ul.sub-menu > li:is(.hide, .hide-inherit, .is-locked) {
    pointer-events: none;
  }
  .mo-subnav__menu ul.sub-menu > li:is(.hide, .hide-inherit, .is-locked) > a {
    opacity: var(--ep-menu-disabled);
    cursor: default;
  }
  /* 펼칠 서브메뉴가 없는 화면(하위 항목이 없는 섹션·섹션 밖 화면)에서는
     빈 보라 줄만 남으므로 띠째로 뺀다 */
  .mo-subnav:not(:has(> ul > li:is(.current-menu-item,
  .current-menu-parent,
  .current-menu-ancestor,
  .current_page_item,
  .current_page_parent,
  .current_page_ancestor) > ul.sub-menu)) {
    display: none;
  }
  /* ----- 검정 줄 + 보라 줄 : 한 덩어리로 화면 위에 붙는다 ----- */
  .mo-header__bar {
    position: sticky;
    top: 0;
    /* PC 헤더(#pc-header)와 같은 층. 페이지 안의 sticky 서브메뉴(.ff-subnav, 998)
       보다 위에 있어야 메뉴 패널이 그 아래로 가려지지 않는다. */
    z-index: 999;
    background-color: var(--mo-main-bg);
    /* 띠가 스크롤로 사라질 때 이 덩어리가 그 자리를 이어받는다.
       overflow-anchor 는 PC 헤더와 같은 이유로 끈다 — 붙어 있는 sticky 안쪽
       노드가 스크롤 앵커로 뽑히면 브라우저의 위치 보정이 수렴하지 않는다. */
    overflow-anchor: none;
  }
  .mo-header__util {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ep-topbar-gap);
    padding: var(--mo-util-padY) var(--ep-margin);
    background-color: var(--color-black);
    color: var(--color-white);
  }
  .mo-header__util-right {
    display: flex;
    align-items: center;
    gap: var(--ep-topbar-gap);
    flex: 0 0 auto;
  }
  /* ----- 보라 줄 : 로고 + ff-title + 메뉴 버튼 ----- */
  .mo-header__main {
    display: flex;
    align-items: stretch;
    padding-left: var(--ep-margin);
    background-color: var(--mo-main-bg);
  }
  /* 위아래 여백은 padding 이 아니라 margin 으로 준다.
     전역 box-sizing: border-box 라서, script.js 가 높이를 고정해둔 .ff-header 에
     padding 을 주면 그만큼 내용 영역이 줄어 ff-title 아래가 잘린다. */
  .mo-header__main .ff-header {
    flex: 1 1 auto;
    min-width: 0;
    margin: 7px 0;
  }
  /* 로고 · 타이틀 크기는 festival-header 의 변수를 덮어서 바꾼다.
     ⚠ .ff-logo 에 font-size 를 직접 주면 안 된다. script.js 는 로고 박스 크기를
     --ff-logo-w / --ff-logo-h 에 em 으로 써넣고, 그 기준은 .ff-header 의 글자
     크기다. .ff-logo 의 글자 크기를 따로 키우면 같은 em 이 그만큼 크게 풀려
     로고 박스가 부풀고 글자가 잘린다. */
  .mo-header__main {
    --ff-logo-size: var(--mo-logo-size);
    --ff-title-size: var(--mo-title-size);
    --ff-title-lift: var(--mo-title-lift);
  }
  .mo-header__main .ff-title {
    line-height: var(--mo-title-lh);
  }
  /* 로고 줄간격만 모바일에서 넓힌다. 줄 높이가 커지면 script.js 가 다시 재서
     로고 박스 높이(--ff-logo-h)도 따라 늘어난다. */
  .mo-header__main .ff-logo {
    line-height: var(--mo-logo-lh);
  }
  /* 폭이 모자라면 ff-title 이 로고 아래로 내려간다.
     좁은 화면에서 "로고 마지막 줄 + 타이틀"이 한 줄에 들어가지 않기 때문이다.
     넉넉한 폭(태블릿 등)에서는 그대로 마지막 줄 옆에 붙는다. */
  .mo-header__main .ff-set {
    flex-wrap: wrap;
    row-gap: 0.35rem;
  }
  /* 보라 배경 위에서는 그라디언트 마스킹 대신 흰 글자로 칠한다.
     .ep-gradient-title 이 color 와 -webkit-text-fill-color 를 transparent 로
     잡아두므로 둘 다 되돌리고, 흐르는 애니메이션도 끈다. */
  .mo-header__main .ep-gradient-title,
  .mo-nav .ep-gradient-title {
    background: none;
    color: var(--color-white);
    -webkit-text-fill-color: currentColor;
    animation: none;
  }
  /* ----- 메뉴 열기 버튼 (+) ----- */
  .mo-header__toggle {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--mo-toggle-w);
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background-color: var(--mo-toggle-bg);
    color: var(--mo-toggle-icon-color);
    cursor: pointer;
  }
  .mo-header__toggle:hover,
  .mo-header__toggle:focus {
    background-color: var(--mo-toggle-bg);
    color: var(--mo-toggle-icon-color);
  }
  /* + 모양을 선 두 개로 그린다. 열리면 45도 돌려 × 가 된다. */
  .mo-header__toggle-icon {
    position: relative;
    display: block;
    width: var(--mo-toggle-icon-w);
    height: var(--mo-toggle-icon-w);
  }
  .mo-header__toggle-icon::before,
  .mo-header__toggle-icon::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 100%;
    height: var(--mo-toggle-icon-h);
    margin-top: calc(var(--mo-toggle-icon-h) / -2);
    background-color: currentColor;
  }
  .mo-header__toggle-icon::before,
  .mo-header__toggle-icon::after {
    transition: transform var(--ep-search-duration) var(--ep-search-ease);
  }
  .mo-header__toggle-icon::after {
    transform: rotate(90deg);
  }
  /* 메뉴가 열리면 + 가 × 로 돌아간다 */
  .mo-header__toggle[aria-expanded=true] .mo-header__toggle-icon::before {
    transform: rotate(45deg);
  }
  .mo-header__toggle[aria-expanded=true] .mo-header__toggle-icon::after {
    transform: rotate(135deg);
  }
  /* ==================================================================
     모바일 메뉴 패널 (#mo-nav — 헤더 바 안에 있다)
     헤더 아래에서 시작해 화면 아래끝까지 채운다. 열려 있는 동안에는 뒤 페이지
     스크롤을 막는다 — 안 막으면 보라 띠가 올라가며 헤더 높이가 바뀌는데
     패널의 시작 지점은 열 때 잰 값이라 헤더와 패널 사이가 벌어진다.
     닫힌 상태는 visibility: hidden + inert.
  ================================================================== */
  .mo-nav {
    /* 헤더 바와 같은 층(999) — 페이지 안의 sticky 요소(.ff-subnav 998,
       국영문 알약 500)보다 위에 덮여야 한다. 바보다 DOM 뒤에 있지만
       헤더 바 아래에서 시작하므로 바를 가리지는 않는다. */
    z-index: 999;
    /* 데스크톱 기본값(display: none)을 되돌린다.
       세로 배치 — 메뉴가 남는 공간을 채우고 검색 버튼은 바닥에 붙는다. */
    display: flex;
    flex-direction: column;
    /* 헤더 아래에서 시작해 뷰포트 끝까지 채운다.
       시작 지점(--mo-nav-top)은 script.js 가 헤더 바의 아래쪽 좌표를 재서 넣는다.
       헤더 높이는 로고 크기(화면 폭에 따라 변함)와 보라 띠 노출 여부에 따라
       달라져서 CSS 만으로는 알 수 없다. bottom: 0 이라 주소창이 접히고 펴져도
       아래쪽은 항상 화면 끝에 맞는다. */
    position: fixed;
    top: var(--mo-nav-top, 0px);
    right: 0;
    bottom: 0;
    left: 0;
    /* 헤더에 쓰인 보라를 연하게 + 뒤를 흐리게 */
    background-color: var(--mo-main-bg);
    -webkit-backdrop-filter: blur(var(--mo-nav-blur));
    backdrop-filter: blur(var(--mo-nav-blur));
    color: var(--mo-nav-fg);
    gap: var(--mo-nav-gap);
    padding: var(--mo-nav-gap) var(--ep-margin) var(--ep-margin);
    /* 스크롤은 메뉴 목록(.mo-nav__body)만 한다. 그래야 항목이 많아져도
       하단 검색 버튼이 화면 밖으로 밀리지 않는다. */
    overflow: hidden;
    overscroll-behavior: contain;
    /* 레이어 전체가 미끄러지면 덩어리째 움직여 둔해 보인다.
       배경은 페이드만 하고, 움직임은 안쪽 카드가 담당한다. */
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--mo-nav-bg-out) var(--mo-nav-ease), visibility 0s linear var(--mo-nav-bg-out);
  }
  .mo-nav.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--mo-nav-bg-in) var(--mo-nav-ease), visibility 0s;
  }
  /* ----- 카드 · 검색 바 : 배경보다 조금 늦게, 한꺼번에 페이드인 -----
     위치 이동 없이 투명도만 바뀐다.
     닫을 때는 지연이 0 이라(아래 .is-open 에서만 지연을 준다) 곧바로 사라진다. */
  .mo-nav__menu > li,
  .mo-nav__foot {
    opacity: 0;
    transition: opacity var(--mo-nav-out) var(--mo-nav-ease);
  }
  .mo-nav.is-open .mo-nav__menu > li,
  .mo-nav.is-open .mo-nav__foot {
    opacity: 1;
    transition-duration: var(--mo-nav-in);
    transition-delay: var(--mo-nav-lead);
  }
  /* 카드와 검색 바는 같은 시점에 함께 올라온다(순차 등장 아님) */
  .mo-nav__body {
    flex: 1 1 auto;
    /* flex 아이템은 기본 min-height: auto 라 내용만큼 늘어나 스크롤이 생기지 않는다 */
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* 카드 격자가 남는 높이를 채우려면 이 사이의 요소들도 함께 늘어나야 한다.
       (검색 결과를 넣으면서 메뉴가 <nav> 로 한 겹 더 감싸졌다) */
    display: flex;
    flex-direction: column;
  }
  .mo-nav__list {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
  }
  /* ----- 레이어 하단 검색 바 — 카드와 같은 면·같은 모서리 -----
     모바일은 오버레이를 띄우지 않고 이 입력창에서 바로 검색한다.
     결과가 나오면 카드 격자를 감추고 그 자리에 목록을 보여준다. */
  .mo-nav__foot {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.5em;
    margin: 0;
    padding: var(--mo-nav-search-padY) var(--mo-nav-search-padX);
    border-radius: var(--mo-nav-radius);
    background-color: var(--mo-nav-card-bg);
    color: inherit;
    font-size: var(--mo-nav-search-size);
  }
  /* 전역 input 규칙(!important)과 GP 의 search 입력 스타일을 덮는다 */
  .mo-nav .mo-nav__search {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    color: inherit;
    font-family: var(--font-display) !important;
    font-size: 1em !important;
    font-weight: var(--fw-bold);
    font-synthesis: none;
    line-height: 1.1 !important;
    text-transform: uppercase;
    /* PP Formula 는 대문자가 박스 중앙보다 0.1em 위에 뜬다
       (descent 0.28em > ascent−capHeight 0.08em, 차이의 절반).
       탑 바 링크와 같은 보정값을 쓴다. 돋보기는 이미 가운데라 손대지 않는다. */
    transform: translateY(var(--ep-display-cap-shift));
    -webkit-appearance: none;
    appearance: none;
  }
  .mo-nav .mo-nav__search:focus {
    outline: none;
    background: none;
    color: inherit;
  }
  .mo-nav .mo-nav__search::placeholder {
    color: currentColor;
    opacity: 0.55;
  }
  .mo-nav .mo-nav__search::-webkit-search-cancel-button {
    display: none;
  }
  .mo-nav .mo-nav__search-submit {
    /* 전역 button 규칙이 font-size 를 1rem 으로 못박는다. 부모 기준으로 되돌린다. */
    font-size: 1em !important;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    color: inherit;
    cursor: pointer;
  }
  .mo-nav .mo-nav__search-submit:hover,
  .mo-nav .mo-nav__search-submit:focus {
    background: none;
    color: inherit;
    opacity: 0.6;
  }
  .mo-nav__search-submit svg {
    display: block;
    width: auto;
    height: var(--mo-nav-search-icon);
  }
  /* ----- 검색 결과 (카드 자리에 들어간다) ----- */
  .mo-nav__results {
    display: none;
  }
  .mo-nav[data-searching] .mo-nav__list {
    display: none;
  }
  .mo-nav[data-searching] .mo-nav__results {
    display: block;
  }
  /* 결과는 보라 패널 위에 바로 놓인다. 패널 글자색(--mo-nav-fg)은 배경과 같은
     계열이라 그대로 두면 묻힌다. 이 영역만 흰 글자로 뒤집는다. */
  .mo-nav__results {
    color: var(--color-white);
  }
  .mo-nav__results .ff-search__item {
    border-bottom-color: rgba(255, 255, 255, 0.24);
  }
  .mo-nav__results .ff-search__title {
    font-size: var(--mo-nav-ko-size);
  }
  .mo-nav__results .ff-search__meta,
  .mo-nav__results .ff-search__empty {
    opacity: 0.6;
  }
  /* ----- 카드 격자 -----
     2열 · 행 높이를 균등하게(1fr) 나눠 한 화면에 모두 들어간다.
     항목 수가 바뀌면 행 수만 달라지고 높이는 자동으로 다시 나뉜다. */
  .mo-nav__menu {
    /* 높이를 %로 잡으면 중간 요소가 auto 일 때 풀리지 않는다. flex 로 늘린다. */
    flex: 1 1 auto;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 1fr;
    gap: var(--mo-nav-gap);
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .mo-nav__menu > li {
    display: flex;
    min-width: 0;
    min-height: 0;
    margin: 0;
    padding: 0;
    list-style: none;
  }
  .mo-nav__menu > li > a {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15em;
    min-width: 0;
    padding: 0.6rem;
    border-radius: var(--mo-nav-radius);
    background-color: var(--mo-nav-card-bg);
    color: inherit;
    text-align: center;
    line-height: 1.25;
  }
  .mo-nav__ko {
    font-size: var(--mo-nav-ko-size);
    font-weight: var(--fw-medium);
  }
  .mo-nav__en {
    font-size: var(--mo-nav-en-size);
    font-weight: var(--fw-semibold);
  }
  /* 오픈 전 메뉴 — PC 와 같은 규칙(링크는 functions.php 가 이미 걷어낸다) */
  .mo-nav li.menu-item.hide,
  .mo-nav li.menu-item.hide-inherit {
    pointer-events: none;
  }
  /* 서브메뉴 기본 투명도(0.75)보다 뒤에 와야 이긴다 */
  .mo-nav li.menu-item.hide > a,
  .mo-nav li.menu-item.hide-inherit > a {
    opacity: var(--ep-menu-disabled);
  }
  .mo-header__toggle:focus-visible,
  .mo-nav a:focus-visible,
  #mo-header a:focus-visible,
  #mo-header button:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
  }
}
@media (max-width: 1024px) and (prefers-reduced-motion: reduce) {
  .mo-nav,
  .mo-nav.is-open,
  .mo-nav__menu > li,
  .mo-nav__foot,
  .mo-nav.is-open .mo-nav__menu > li,
  .mo-nav.is-open .mo-nav__foot,
  .mo-header__toggle-icon::before,
  .mo-header__toggle-icon::after {
    transition: none;
  }
}
/* ----- Mobile Header End ----- */
/* ==================================================================
   Site Footer  (shortcode: [print_footer])
   ------------------------------------------------------------------
   4단 그리드. 그리드는 "단" 만 나누고 행은 만들지 않는다.
   각 단 안에서 두 덩어리가 자기 내용 높이대로 쌓이므로, 한 단의 내용이
   길어져도 다른 단이 끌려 내려가지 않는다.

   [조절]
     단 간격 --ep-footer-colGap / 단 안쪽 덩어리 간격 --ep-footer-rowGap
     상하 여백 --ep-footer-padY   (좌우는 사이트 마진 --ep-margin)
     로고 폭 --ep-footer-logoW
================================================================== */
:root {
  --ep-footer-padY: 15px;
  --ep-footer-colGap: 30px;
  --ep-footer-rowGap: 34px;
  --ep-footer-size: 12px;
  --ep-footer-lh: 1.5;
  --ep-footer-logoW: 230px;
}

body.home .site-footer {
  margin-top: 0px !important;
}

@media (max-width: 780px) {
  .site-footer {
    margin-top: 30px;
  }
}

.ff-footer {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: var(--ep-footer-colGap);
  row-gap: var(--ep-footer-rowGap);
  padding: var(--ep-margin);
  background-color: var(--color-black);
  color: var(--color-white);
  /* 글자 크기·줄 높이는 여기 한 곳에서만 정하고 안쪽은 모두 상속받는다.
     p 뿐 아니라 div(주소 · 캡션)·a·span 까지 함께 적용되려면 이래야 한다. */
  font-size: var(--ep-footer-size);
  font-weight: var(--fw-medium);
  line-height: var(--ep-footer-lh);
}

.ff-footer__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.ff-footer p {
  margin: 0;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
}

.ff-footer a {
  color: inherit;
  transition: opacity 0.2s ease;
}

.ff-footer a:hover,
.ff-footer a:focus-visible {
  opacity: 0.6;
}

/* 로고 — 원본 271×84 비율 유지 */
.ff-footer__logo {
  display: block;
  width: 100%;
  max-width: var(--ep-footer-logoW);
}

.ff-footer__logo svg {
  display: block;
  width: 100%;
  height: auto;
}

/* 로고와 그 아래 문구는 붙여 둔다 */
.ff-footer__col--brand {
  gap: 10px;
}

@media (max-width: 1024px) {
  :root {
    --ep-footer-size: 10px;
    --ep-footer-lh: 1.5;
  }
  .ff-footer {
    grid-template-columns: repeat(2, 1fr);
    /* 화면 바닥 양쪽 모서리에 떠 있는 버튼("맨 위로" · 국영문 알약)이
       푸터 마지막 줄을 가리지 않게 그 높이만큼 아래를 비운다.
       푸터 끝까지 스크롤하면 버튼과 글자가 같은 자리에서 만나기 때문이다.
       (두 버튼 중 큰 쪽인 "맨 위로" 기준 — 알약은 그보다 낮다) */
    padding-bottom: calc(var(--ep-margin) + var(--ff-totop-offset) + var(--ff-totop-size));
  }
}
/* ----- 모바일 -----
   1단으로 펴면 덩어리 8개가 세로로 쌓여 지나치게 길어진다.
   단(.ff-footer__col)을 display: contents 로 해체해 각 덩어리가 직접 격자에
   놓이게 하고, 짧은 것끼리 2열로 짝지어 행 수를 줄인다.

     로고   | 캡션(로고 옆 빈 자리에)
     주소   | 주최·주관
     연락처 | 문의시간
     정책 링크        ─ 전체 폭(가로 나열)
     카피라이트       ─ 전체 폭
================================================================== */
@media (max-width: 768px) {
  :root {
    --ep-footer-logoW: 150px;
  }
  .ff-footer {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 16px;
    row-gap: 14px;
  }
  /* 단을 해체 — 자식(덩어리)이 푸터 격자의 직접 항목이 된다 */
  .ff-footer__col {
    display: contents;
  }
  .ff-footer__group--policy,
  .ff-footer__group--copyright {
    grid-column: 1/-1;
  }
  /* 캡션은 로고 오른쪽 빈 자리에 넣고 아래를 맞춘다 (한 행을 아낀다) */
  .ff-footer__logo {
    grid-column: 1;
  }
  .ff-footer__caption {
    grid-column: 2;
    align-self: end;
  }
  /* 정책 링크 두 개는 가로로 */
  .ff-footer__group--policy {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
  }
  /* 카피라이트도 자리가 되면 한 줄로 */
  .ff-footer__group--copyright {
    display: flex;
    flex-wrap: wrap;
    gap: 0 6px;
  }
}
/* ----- Site Footer End ----- */
/* ==================================================================
   Main Slider  (shortcode: [print_main_slider])
   ------------------------------------------------------------------
   notice 의 "메인 노출" 글 대표 이미지를 가운데 정렬로 흘린다.

   [크기] 한 번에 한 장만, 내용 폭을 꽉 채워 보여준다. 높이는
   --ff-slide-ratio(가로형)로 정하되 --ff-slide-maxH 를 넘지 않는다.
   이미지는 원본 비율이 제각각이라 cover 로 채운다 — 비율이 다른 이미지가
   섞여도 칸 크기는 같고, 남는 부분은 가운데 기준으로 잘린다.

   [조절]
     보이는 수 --ff-slides-per-view
     칸 비율   --ff-slide-ratio (가로 / 세로) · 높이 상한 --ff-slide-maxH
     간격     --ff-slide-gap
     버튼     --ff-slider-navSize
     페이지네이션 선 --ff-slider-dotW / --ff-slider-dotH
     헤더와의 간격 --ff-slider-topGap
================================================================== */
:root {
  /* 한 화면에 보일 슬라이드 수. 폭을 Swiper 가 이 값으로 계산하므로
     화면이 넓어지면 슬라이드도 같이 커진다. (script.js 가 읽어간다) */
  --ff-slides-per-view: 1;
  /* 가로형. 값을 키울수록 납작해진다 (1 / 1 이면 정사각).
     화면 크기와 상관없이 하나로 쓴다 — 배너 그림도 PC·모바일 구분 없이
     한 장이라(inc/main-slider.php), 비율까지 같아야 디자인한 판형이
     그대로 나온다.
     3 / 1 은 1440 화면에서 높이 470px, 390 화면에서 123px 다. 높이 상한
     (--ff-slide-maxH)에는 걸리지 않으므로 어느 쪽도 잘리지 않는다. */
  --ff-slide-ratio: 3 / 1;
  /* 높이 상한 — 슬라이더가 첫 화면을 넘지 않게 한다.
     빼는 값은 위에 깔리는 것들(띠배너·헤더·페이지네이션) 몫이다.
     svh 는 모바일 주소창이 펼쳐진 상태(가장 짧은 화면) 기준이라 안전하다. */
  --ff-slide-maxH: calc(100svh - 220px);
  --ff-slide-gap: 15px;
  /* 좌우 화살표 지름 — 사이트 공통 조작 버튼 크기를 따른다(_asset.scss).
     이 슬라이더만 다르게 하고 싶을 때만 여기서 덮어쓴다. */
  --ff-slider-navSize: var(--ep-controlSize);
  --ff-slider-dotW: 56px;
  --ff-slider-dotH: 2px;
  --ff-slider-dotColor: #d9d9d9;
  /* 헤더(아래 보라 선)와 페이지네이션 사이 */
  --ff-slider-topGap: 22px;
}

.ff-slider__viewport {
  overflow: hidden;
}

/* 폭은 Swiper 가 --ff-slides-per-view 를 기준으로 인라인 스타일로 넣는다.
   높이는 이미지 비율에 맡겨 포스터가 잘리지 않게 한다.
   (Swiper 기본 CSS 가 테마 CSS 보다 뒤에 로드되므로 한 단계 더 좁힌 선택자다) */
.ff-slider .ff-slider__slide {
  display: block;
  /* 폭은 Swiper 가 인라인으로 넣고, 높이는 이 비율에서 나온다.
     화면이 낮으면 상한이 먼저 걸려 비율보다 납작해진다(이미지는 cover 라
     잘릴 뿐 찌그러지지 않는다). */
  aspect-ratio: var(--ff-slide-ratio);
  height: auto;
  max-height: var(--ff-slide-maxH);
  overflow: hidden;
}

.ff-slider .ff-slider__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ----- 페이지네이션 (슬라이드 위 우측 선) ----- */
.ff-slider__pagination {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
  margin-top: var(--ff-slider-topGap);
  margin-bottom: 14px;
}

/* Swiper 기본 CSS 가 가로 페이지네이션에 주는 위치값을 되돌린다.
   ── 왜 필요한가 ──
   Swiper 는 페이지네이션을 슬라이드 위에 absolute 로 띄우는 것을 전제로
   .swiper-pagination-horizontal 에 bottom: 8px · left: 0 을 준다. 우리는
   슬라이드 위 문서 흐름 안에 두므로 absolute 가 아닌데, 테마 전역의
   * { position: relative } 때문에 이 bottom 이 "위로 8px 이동" 으로 작동해
   선이 헤더 아래로 들어가 가려졌다.
   Swiper CSS 는 숏코드 출력 뒤(우리 CSS 보다 늦게) 로드되고 선택자도
   클래스 두 개라, 클래스 세 개로 좁혀야 이긴다. */
.ff-slider .ff-slider__pagination.swiper-pagination-horizontal {
  top: auto;
  bottom: auto;
  left: auto;
}

/* 같은 이유로 Swiper 가 선마다 좌우 4px 여백을 더해, 선 사이가 의도한
   6px(gap)이 아니라 14px 로 벌어졌다. 간격은 gap 하나로만 관리한다. */
.ff-slider .ff-slider__pagination.swiper-pagination-horizontal .swiper-pagination-bullet {
  margin: 0;
}

/* 복제된 슬라이드 몫의 선은 감춘다 (script.js 의 highlight 참고) */
.ff-slider__pagination .swiper-pagination-bullet.ff-is-extra {
  display: none;
}

.ff-slider__pagination .swiper-pagination-bullet {
  width: var(--ff-slider-dotW);
  height: var(--ff-slider-dotH);
  margin: 0;
  border-radius: 0;
  background-color: var(--ff-slider-dotColor);
  opacity: 1;
  transition: background-color 0.2s ease;
}

/* 온전히 보이는 슬라이드 수만큼 활성화된다 — 지금은 한 장이라 하나.
   ff-is-active 는 script.js 가 붙인다. JS 가 없으면 Swiper 기본 1개만 켜진다. */
.ff-slider__pagination .swiper-pagination-bullet-active,
.ff-slider__pagination .swiper-pagination-bullet.ff-is-active {
  background-color: var(--ep-header-lineColor);
}

/* ----- 좌우 버튼 ----- */
.ff-slider__nav {
  position: absolute;
  top: 50%;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ff-slider-navSize);
  height: var(--ff-slider-navSize);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--ep-header-lineColor);
  color: var(--color-white);
  cursor: pointer;
  transform: translateY(-50%);
  transition: opacity 0.2s ease;
}

.ff-slider__nav:hover,
.ff-slider__nav:focus-visible {
  background-color: var(--ep-header-lineColor);
  opacity: 0.8;
}

.ff-slider__nav--prev {
  left: 16px;
}

.ff-slider__nav--next {
  right: 16px;
}

/* 아이콘(arrow.svg)은 오른쪽을 향한다 — 이전 버튼만 뒤집는다 */
.ff-slider__nav--prev svg {
  transform: scaleX(-1);
}

.ff-slider__nav svg {
  width: 42%;
  height: auto;
}

/* SVG 에 박혀 있는 fill="white" 대신 버튼 글자색을 따르게 한다 */
.ff-slider__nav svg path {
  fill: currentColor;
}

/* Swiper 가 끝에 도달해 버튼을 비활성화했을 때 */
.ff-slider__nav.swiper-button-disabled {
  opacity: 0.25;
  cursor: default;
}

/* ----- 좁은 화면 -----
   한 번에 한 장만 보여주고, 페이지네이션은 슬라이드 아래에서 너비를 꽉 채운다.
   (마크업은 페이지네이션이 위에 있으므로 flex order 로 뒤집는다) */
@media (max-width: 768px) {
  :root {
    --ff-slide-gap: 12px;
  }
  .ff-slider {
    display: flex;
    flex-direction: column;
    /* 헤더와의 간격은 페이지네이션이 위에 있을 때만 그 margin 이 맡는다.
       아래로 내려가므로 여기서 대신 띄운다.
       다른 화면은 헤더 아래 20px(--ep-contentTop)에서 본문이 시작하지만, 메인의
       배너만 예외로 10px 다 — 헤더 바로 밑을 가득 채우는 큰 그림이라 헤더에
       더 붙여 둔다. */
    padding-top: 10px;
  }
  /* .ff-slider 가 flex 가 되면 .swiper 도 flex 아이템이 된다. 그러면 폭이
     부모가 아니라 내용(슬라이드 폭의 합)에서 나올 수 있고, Swiper 가 그
     폭으로 슬라이드를 다시 넓히는 되먹임이 생겨 슬라이드가 수천 px 로
     불어난다. 폭을 부모 기준으로 못박아 고리를 끊는다. */
  .ff-slider__viewport {
    width: 100%;
    min-width: 0;
  }
  .ff-slider__pagination {
    order: 2;
    margin-top: 12px;
    margin-bottom: 0;
  }
  /* 선 너비를 고정하지 않고 남은 폭을 똑같이 나눠 갖게 한다.
     Swiper 기본 CSS 보다 뒤에서 이겨야 하므로 선택자를 좁혀 둔다. */
  .ff-slider .ff-slider__pagination.swiper-pagination-horizontal .swiper-pagination-bullet {
    flex: 1 1 0;
    width: auto;
  }
  /* 좌우 버튼은 두지 않는다 — 손가락으로 넘기는 화면이고, 한 장이 꽉 차서
     버튼이 포스터를 가린다. 스와이프·키보드 넘김은 그대로 동작한다.
     display: none 이라 스크린리더와 탭 이동에서도 빠진다. */
  .ff-slider__nav {
    display: none;
  }
}
/* ----- Main Slider End ----- */
/* ==================================================================
   Back To Top  (inc/back-to-top.php · script.js 의 BackToTop)
   ------------------------------------------------------------------
   화면 오른쪽 아래 고정 버튼. 스크롤을 한 화면 이상 내리면 나타난다.

   [보이기/숨기기] script.js 가 .is-visible 을 붙였다 뗀다.
   숨어 있는 동안에는 opacity 0 에 더해 visibility: hidden 을 준다 —
   투명하기만 하면 탭 이동으로 눌리고 스크린리더도 읽기 때문이다.
   visibility 는 전환되지 않는 값이라, 사라질 때만 전환이 끝난 뒤
   바뀌도록 지연을 준다(그래야 페이드아웃이 보인다).

   [층위] 헤더(999)보다 낮고 본문보다 높게 둔다. 검색 오버레이가 열리면
   그 위로 덮인다.

   [배경과의 구분] 테두리 없이 옅은 그림자만 둔다. 같은 보라를 쓰는
   뉴스레터 띠 위에서는 동그라미 경계가 거의 보이지 않고 흰 화살표만
   떠 보인다 — 테두리를 빼기로 한 결과다.

   [조절]
     크기   --ff-totop-size (모바일은 아래 미디어쿼리에서 따로)
     위치   --ff-totop-offset (화면 가장자리에서 떨어진 거리)
     색     --ff-totop-bg / --ff-totop-fg
================================================================== */
:root {
  /* 공통 조작 버튼 크기(--ep-controlSize: 48px)보다 한 단계 크게 둔다.
     화면 구석에 혼자 떠 있어 다른 버튼과 나란히 보이는 일이 없고, 누르는
     자리이므로 손가락·마우스 모두 집기 쉬운 편이 낫다. */
  --ff-totop-size: 60px;
  --ff-totop-offset: var(--ep-margin);
  --ff-totop-bg: var(--ep-header-lineColor);
  --ff-totop-fg: var(--color-white);
  --ff-totop-speed: 0.25s;
}

.ff-totop {
  position: fixed;
  right: var(--ff-totop-offset);
  bottom: var(--ff-totop-offset);
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ff-totop-size);
  height: var(--ff-totop-size);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: var(--ff-totop-bg);
  color: var(--ff-totop-fg);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.16);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--ff-totop-speed) ease, transform var(--ff-totop-speed) ease, visibility 0s linear var(--ff-totop-speed);
}

.ff-totop.is-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity var(--ff-totop-speed) ease, transform var(--ff-totop-speed) ease, visibility 0s linear 0s;
}

/* GP 기본 button 규칙(회색 배경)이 hover·focus 에서 되살아나므로 함께 잡는다 */
.ff-totop:hover,
.ff-totop:focus {
  background-color: var(--ff-totop-bg);
  color: var(--ff-totop-fg);
}

.ff-totop.is-visible:hover {
  transform: translateY(-2px);
}

.ff-totop:focus-visible {
  outline: 2px solid var(--ff-totop-bg);
  outline-offset: 3px;
}

/* 아이콘은 오른쪽을 향하는 화살표(arrow.svg)라 위로 돌려 쓴다.
   42% 는 슬라이더 화살표(.ff-slider__nav svg)와 같은 비율이다 — 같은
   arrow.svg 를 쓰므로 버튼 지름이 같으면 화살표도 똑같은 크기로 보인다. */
.ff-totop svg {
  display: block;
  width: 42%;
  height: auto;
  transform: rotate(-90deg);
}

.ff-totop svg path {
  fill: currentColor;
}

/* 모바일 — 좁은 화면에서 60px 은 본문을 많이 가린다. 한 단계 줄인다
   (화살표는 지름의 42% 라 따라서 같이 작아진다). */
@media (max-width: 1024px) {
  :root {
    --ff-totop-size: 52px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ff-totop,
  .ff-totop.is-visible {
    transition: opacity var(--ff-totop-speed) ease, visibility 0s;
    transform: none;
  }
}
/* ----- Back To Top End ----- */
/* ==================================================================
   Rolling Text Banner  (GenerateBlocks 블록 — 패턴 "롤링 배너")
   ------------------------------------------------------------------
   헤더 아래 그라디언트 띠. 큰 타이틀이 옆으로 끊김 없이 계속 흐른다.

   [원리] 같은 문구 묶음(.ff-rolling__group)을 여러 벌 이어 붙이고,
   트랙 전체가 아니라 "묶음 한 벌" 만큼만 옮긴다. 옮긴 자리에는 다음 벌이
   똑같은 그림으로 이미 들어와 있으므로 되돌아오는 순간이 보이지 않는다.
   → 이동량 --ff-rolling-shift 는 "-100% ÷ 벌 수". 2벌이면 -50%.
     벌 수를 바꾸면 이 값도 같이 바꿔야 한다(script.js 가 함께 갱신한다).
   → 그래서 easing 은 반드시 linear.

   [간격] 항목 사이 간격은 flex gap 이 아니라 항목의 오른쪽 padding 으로 준다.
   gap 으로 주면 "한 벌" 너비에 끝 간격이 빠져서 이동량이 그만큼 어긋난다.

   [벌 수] 본문(에디터)에는 문구 묶음을 "한 벌"만 둔다. 화면을 채우는 데
   필요한 복제는 script.js 가 실제 폭을 재서 만든다. 편집자가 여러 벌을
   똑같이 맞춰 고쳐야 하는 상황을 만들지 않기 위해서다.
   그래서 흐름은 JS 가 준비를 마친 뒤(data-ff-ready)에만 시작한다.
   JS 가 없으면 복제본이 없어 이음매가 드러나므로 흐르지 않고 멈춰 있는다.

   [속도] --ff-rolling-speed(초당 px)를 기준으로 script.js 가 실제 폭을 재서
   재생 시간을 계산한다. 문구가 길어져도 체감 속도는 같다.

   [세로 위치] 글자는 라인박스 세로 가운데에 앉는다. 타이틀 글꼴(PP Formula
   Fit)의 세로 메트릭을 fonts/font.css 에서 보정해 두었기 때문이다. 여기서
   따로 내리면 이중 보정이 된다. 띠 높이는 --ff-rolling-lineH 로 잡는다.

   [배경] 테마 그라디언트 시스템(.ep-gradient-layer)을 그대로 쓴다.
   색·속도는 --ep-grad-c1~c4 / --ep-grad-duration 로 조절한다.

   [조절]
     글자 크기 --ff-rolling-size
     띠 높이   --ff-rolling-lineH + --ff-rolling-padY
     항목 간격 --ff-rolling-gap
     흐름 속도 --ff-rolling-speed
================================================================== */
:root {
  --ff-rolling-size: clamp(30px, 4.6vw, 80px);
  --ff-rolling-gap: 0.55em;
  /* 띠 바로 아래에서 본문이 시작하는 간격.
     띠 다음에 오는 블록(정의형 표 · 국영문 묶음)이 이 값으로 띄운다 —
     페이지마다 구조가 달라도 본문 첫 줄의 높이는 같아진다.
     PC 값 60px 은 국·영문 알약 줄(20px 여백 + 40px 알약)이 차지하던 높이다. */
  --ff-pageTop: 60px;
  --ff-rolling-padY: 20px;
  /* 띠 높이 = 이 값(글자 크기 배수) + 위아래 padY */
  --ff-rolling-lineH: 1.05;
  /* 초당 px. script.js 가 읽어 재생 시간으로 환산한다 */
  --ff-rolling-speed: 90;
  /* script.js 가 실제 폭에 맞춰 덮어쓴다 */
  --ff-rolling-duration: 20s;
  --ff-rolling-shift: -50%;
  --ff-rolling-direction: normal;
}

.ff-rolling {
  /* 움직이는 것이 둘(배경 그라디언트 · 흐르는 글자)이라 배경은 한 단계
     느리게 둔다. 글자 흐름이 주인공이고 배경은 천천히 도는 면으로 읽힌다.
     다만 타이틀만큼 명멸이 읽히려면 너무 느려서도 안 된다. */
  --ep-grad-duration: 18s;
  /* 덩어리 판을 박스보다 작게 잡는다 (기본값은 200% 200%).
     ── 왜 ──
     덩어리 크기는 요소 박스 대비 비율이라, 타이틀처럼 작은 상자에서는 여섯
     개가 화면을 꽉 채우지만 배너처럼 넓은 면에서는 같은 여섯 개가 넓게 퍼져
     하나하나가 옅게 깔린다. 그래서 같은 명멸이 배너에서는 잘 안 읽힌다.
     판을 줄이면 덩어리가 작아지고, 가로로 반복시켜 화면에 보이는 개수를
     늘린다. 다만 너무 줄이면 자잘한 점처럼 보여 넓은 띠에 어울리지 않는다 —
     덩어리 하나가 띠 가로의 4분의 1쯤 되는 선에서 멈춘다. 판 크기를 레이어마다 다르게 둬서 반복 주기가
     서로 어긋나므로 타일이 깔린 것처럼 보이지 않는다.
     세로는 100% 를 넘겨 한 줄만 보이게 한다(가로 반복만 쓴다). */
  --ep-grad-mesh-size:
    64% 150%, 73% 164%, 58% 140%, 80% 172%, 54% 132%, 68% 156%, 100% 100%;
  /* 판은 작게 두되(자리가 넓게 퍼지고 가로 반복이 생긴다) 덩어리 자체는
     키운다. 판만 키워 크기를 올리면 판이 박스만 해지면서 덩어리가 전부
     한가운데로 몰린다. */
  --ep-grad-blob-scale: 1.8;
  display: flex;
  align-items: center;
  width: 100%;
  padding-top: var(--ff-rolling-padY);
  padding-bottom: var(--ff-rolling-padY);
  color: var(--color-white);
  /* 글자 크기는 띠 전체에 준다. 안쪽 em 값(--ff-rolling-gap 등)이 본문
     크기(18px)가 아니라 이 표시 크기를 기준으로 계산되게 하기 위해서다. */
  font-size: var(--ff-rolling-size);
}
@media (max-width: 1024px) {
  .ff-rolling {
    font-size: 9.5dvw;
  }
}

/* 위 판 크기와 짝 — 가로로만 반복시킨다. 기본 믹스인은 no-repeat 이다. */
.ff-rolling.ep-gradient-layer::before {
  background-repeat: repeat-x;
}

/* 사이트 좌우 마진을 넘어 화면 끝까지 채운다.
   .site-content 의 좌우 패딩(--ep-margin)을 음수 마진으로 되돌리는 방식이라,
   그 안쪽에 또 패딩을 주는 래퍼가 생기면 그만큼 모자란다. */
.ff-rolling--bleed {
  margin-left: calc(var(--ep-margin) * -1);
  margin-right: calc(var(--ep-margin) * -1);
  width: auto;
}

.ff-rolling--reverse {
  --ff-rolling-direction: reverse;
}

/* 글자를 띠 세로 가운데에 앉히는 보정값.
   script.js 가 실제로 그려진 글자의 잉크 범위를 재서 px 로 넣는다(아래 참고).
   그 전(또는 JS 가 없을 때)에는 국문 배너만 계산값으로 올려둔다 — 국문
   글자는 라인박스 가운데보다 0.028em 아래에 앉기 때문이다. */
.ff-rolling--hangul {
  --ff-rolling-shiftY: -0.028em;
}

/* [왜 JS 로 재는가] 이 띠의 세로 정렬은 글꼴이 신고하는 수치(ascent/descent)를
   따른다. 우리는 그 수치를 fonts/font.css 의 ascent-override·descent-override 로
   보정해 두었는데, 이 기능은 구형 사파리(iOS 17 이전)가 무시한다. 그러면 같은
   CSS 인데도 글자가 위로 14px 가량 치우친다(모바일 폭 기준 실측).
   그래서 "글꼴이 이렇다더라" 대신 "지금 이 브라우저가 실제로 그린 결과"를 재서
   맞춘다. script.js 의 alignRollingText 참고. */
.ff-rolling__item {
  position: relative;
  top: var(--ff-rolling-shiftY, 0px);
}

/* 트랙 — 실제로 움직이는 레이어.
   .ep-gradient-layer > * 규칙이 z-index 를 올려주므로 배경 위에 그려진다. */
.ff-rolling__track {
  display: flex;
  flex: 0 0 auto;
  width: -moz-max-content;
  width: max-content;
  will-change: transform;
}

/* 복제와 이동량 계산이 끝난 뒤에 흐르기 시작한다(script.js).
   준비 전에 돌리면 한 벌짜리 트랙이 흘러가며 빈 자리가 드러난다. */
.ff-rolling[data-ff-ready] .ff-rolling__track {
  animation: ff-rolling-move var(--ff-rolling-duration) linear infinite;
  animation-direction: var(--ff-rolling-direction);
}

.ff-rolling__group {
  display: flex;
  flex: 0 0 auto;
}

.ff-rolling__item {
  flex: 0 0 auto;
  padding-right: var(--ff-rolling-gap);
  font-family: var(--font-title);
  font-weight: var(--fw-bold);
  font-synthesis: none;
  line-height: var(--ff-rolling-lineH);
  white-space: nowrap;
}

/* 옵션에서 채우는 항목([ff_slogan] 등)이 비면 간격만 남지 않게 뺀다 */
.ff-rolling__item:empty {
  display: none;
}

@keyframes ff-rolling-move {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(var(--ff-rolling-shift), 0, 0);
  }
}
@media (max-width: 768px) {
  :root {
    --ff-rolling-padY: 12px;
    --ff-rolling-speed: 60;
  }
}
/* 모바일에서는 알약이 화면 바닥으로 빠져(_lang.scss) 자리를 비우므로,
   본문 시작 간격도 그만큼 줄여 잡는다. 모바일 헤더가 나오는 폭과 같은 기준이다. */
@media (max-width: 1024px) {
  :root {
    --ff-pageTop: 28px;
  }
}
/* 모션 최소화 설정이면 흐르지 않고 첫 벌만 보인다 */
@media (prefers-reduced-motion: reduce) {
  .ff-rolling[data-ff-ready] .ff-rolling__track {
    animation: none;
  }
}
/* ----- Rolling Text Banner End ----- */
/* ==================================================================
   Definition List  (GenerateBlocks 블록 — 패턴 "정의형 표")
   ------------------------------------------------------------------
   "개최 개요" 의 행사 개요·특징처럼 왼쪽 항목명 / 오른쪽 내용이
   줄줄이 이어지는 표. 시상·심사, 조직구성 등에도 그대로 쓴다.

   [구조] 본문에 블록으로 들어간다. 조립은 inc/blocks.php 참고.
     .ff-deflist (section)
       ├ .ff-deflist__title            ← 표 제목 (행사 개요)
       ├ .ff-deflist__head             ← 표 첫 줄 소제목 (서울독립영화제2025)
       └ .ff-deflist__body (dl)
           └ .ff-deflist__row (div)    ← dt(항목명) + dd(내용)

   [행 구분선] border-bottom 으로 각 행 아래에 긋는다. 소제목 줄도 같은 선을
   쓰므로 제목 아래 첫 선이 자연스럽게 따라온다.

   [항목명 칸] 폭은 고정이다. 길면 두 줄로 접히고 내용 칸의 시작선은
   표 전체에서 흐트러지지 않는다. 기본 250px, 반반 레이아웃(.ff-split) 안에서는
   150px. 표마다 다르게 하려면 그 표의 .ff-deflist 블록에
   --ff-deflist-labelW 를 덮어쓴다.

   [블록 안쪽] dt·dd 는 글자를 직접 담을 수 없는 컨테이너 블록이라
   안에 텍스트 블록(span·p)이 한 겹 더 들어간다. 그래서 색·굵기는
   dt·dd 에 주고 안쪽은 상속받게 둔다.

   [조절]
     강조색     --ff-deflist-color
     항목명 폭  --ff-deflist-labelW
     칸 사이    --ff-deflist-gap
     행 높이    --ff-deflist-rowPadY
     선 두께    --ff-deflist-lineW
     목록 간격  --ff-deflist-listGap
     이름 칸 폭 --ff-deflist-nameW
================================================================== */
:root {
  --ff-deflist-color: #6f14ff;
  --ff-deflist-labelW: 250px;
  --ff-deflist-gap: 30px;
  --ff-deflist-rowPadY: 10px;
  --ff-deflist-lineW: 1.5px;
  /* 표 제목 — 메뉴 서브메뉴(PC 둘째 줄 · 모바일 띠)와 같은 크기로 맞춘다.
     서브메뉴 크기를 바꾸면 표 제목도 따라온다(_header.scss). */
  --ff-deflist-titleSize: 1rem;
  /* 표와 표 사이 */
  --ff-deflist-gapY: 46px;
  /* 목록 행(ff-deflist__value--list) — 항목 사이 · 이름 칸 폭 */
  --ff-deflist-listGap: 10px;
  --ff-deflist-nameW: 130px;
}

.ff-deflist {
  margin-top: 0;
  margin-bottom: var(--ff-deflist-gapY);
}
@media (max-width: 1024px) {
  .ff-deflist {
    margin-top: 0px;
    margin-bottom: 10px;
  }
}

/* 롤링 배너 다음에 표가 바로 오는 페이지(개인정보취급방침 등) — 배너에
   글자가 붙지 않게, 국·영문 페이지와 같은 높이에서 본문이 시작하게 띄운다.
   간격 값은 _rolling.scss 의 --ff-pageTop 하나로 모아 둔다.
   국·영문 페이지는 사이에 알약 줄이 들어가 이 규칙에 걸리지 않는다. */
.ff-rolling + .ff-deflist {
  margin-top: var(--ff-pageTop);
}

.ff-deflist__title {
  margin: 0 0 18px;
  color: var(--ff-deflist-color);
  font-size: var(--ff-deflist-titleSize);
  line-height: 1.2;
}

/* 소제목 줄 — 표(dl) 바깥의 한 줄이라 항목명 칸에 갇히지 않는다.
   행과 같은 선·여백을 써서 표의 첫 줄처럼 읽힌다. */
.ff-deflist__head {
  margin: 0;
  padding: var(--ff-deflist-rowPadY) 0;
  border-bottom: var(--ff-deflist-lineW) solid var(--ff-deflist-color);
  color: var(--ff-deflist-color);
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.5;
}

.ff-deflist__body {
  margin: 0;
}

/* 반반 레이아웃(조직구성) 안에서는 항목명 칸을 좁힌다 — 표가 화면의 절반
   폭에 들어가므로 250px 를 그대로 두면 내용 칸이 눌린다. (styles/_split.scss) */
.ff-split .ff-deflist {
  --ff-deflist-labelW: 150px;
}

.ff-deflist__row {
  display: grid;
  grid-template-columns: var(--ff-deflist-labelW) minmax(0, 1fr);
  column-gap: var(--ff-deflist-gap);
  padding: var(--ff-deflist-rowPadY) 0;
  border-bottom: var(--ff-deflist-lineW) solid var(--ff-deflist-color);
}

.ff-deflist__label {
  color: var(--ff-deflist-color);
  font-weight: var(--fw-medium);
  line-height: 1.5;
}

.ff-deflist__value {
  margin: 0;
  color: var(--color-black);
  line-height: 1.6;
}

/* 한 행 안에서 문단이 나뉘어도 줄 간격은 그대로 이어지게 둔다.
   (본문의 p 규칙이 위아래 여백을 넣기 때문에 여기서 되돌린다) */
.ff-deflist__value p {
  margin: 0;
  font-size: inherit;
  line-height: inherit;
}

.ff-deflist__value a {
  color: var(--ff-deflist-color);
  text-decoration: underline;
}

/* 표(dl) 없이 문단만 들어가는 절 — 이메일무단수집거부처럼 제목 한 줄 +
   설명 한 문단인 페이지다. 내용 칸(dd)과 같은 글줄로 맞춰, 표가 있는
   페이지와 본문 인상이 달라지지 않게 한다.
   (__head 는 표의 첫 줄 소제목이라 제외한다) */
.ff-deflist > p:not(.ff-deflist__head) {
  margin: 0;
  color: var(--color-black);
  font-size: inherit;
  line-height: 1.6;
}

/* 문단이 여럿이면 한 문단 사이만큼 띄운다 */
.ff-deflist > p:not(.ff-deflist__head) + p:not(.ff-deflist__head) {
  margin-top: 0.8em;
}

/* 목록 행 — 내용 칸에 항목이 줄줄이 선다 (조직구성의 위원 명단·메일 주소).
   항목 사이는 한 문단 안의 줄바꿈보다 조금 더 띄워 항목 단위로 읽히게 한다. */
.ff-deflist__value--list {
  display: grid;
  row-gap: 3px;
}

/* 이름 · 설명 두 열. 이름 칸은 고정 폭이라 설명의 시작선이 한 줄로 선다 */
.ff-deflist__pair {
  display: grid;
  grid-template-columns: var(--ff-deflist-nameW) minmax(0, 1fr);
  column-gap: var(--ff-deflist-gap);
}

@media (max-width: 768px) {
  :root {
    --ff-deflist-gapY: 32px;
    --ff-deflist-rowPadY: 8px;
  }
  /* 좁은 화면에서는 항목명을 내용 위로 올린다 */
  .ff-deflist__row {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 5px;
  }
  .ff-deflist__title {
    margin-bottom: 12px;
  }
  :root {
    --ff-deflist-listGap: 6px;
    --ff-deflist-nameW: 72px;
  }
}
/* 좁은 화면 — 롤링 배너 바로 아래 표가 오는 페이지(개인정보취급방침 등).
   표 제목(h2)이 style.scss 에서 위 패딩 20px 를 이미 갖고 있어, 위의 margin-top 까지
   더하면 48px 로 벌어진다. 여기서는 margin 을 빼고 제목의 패딩만 남긴다
   (= --ep-contentTop 과 같은 20px). */
@media (max-width: 1024px) {
  .ff-rolling + .ff-deflist {
    margin-top: 0;
  }
}
/* ----- Definition List End ----- */
/* ==================================================================
   Info Grid  (GenerateBlocks 블록 — 패턴 "정보 그리드")
   ------------------------------------------------------------------
   아이덴티티 페이지의 메인슬로건·슬로건·포스터처럼 왼쪽 항목명 /
   오른쪽 소제목 + 긴 본문(또는 이미지)이 선 없이 이어지는 목록.
   선으로 칸을 나누는 표는 정의형 표(_deflist.scss)를 쓴다.

   [구조] 본문에 블록으로 들어간다. 조립은 inc/blocks.php 참고.
     .ff-infogrid (section)
       └ .ff-infogrid__row (div)          ← 12칸 그리드
           ├ .ff-infogrid__label (h2)     ← 1~3칸
           └ .ff-infogrid__body (div)     ← 4~12칸
               ├ .ff-infogrid__head (p)   ← 소제목 (본문 중간에 또 올 수 있다)
               ├ p                        ← 문단
               ├ figure.wp-block-image    ← 이미지 (포스터)
               ├ .ff-logobox              ← 테두리 안 로고 SVG
               └ .ff-swatches > .ff-swatch ← 색상 칩 (CMYK / RGB)

   [본문 칸] 본문도 9칸 그리드다. 글은 9칸을 다 쓰고, 이미지·로고 박스·
   색상 칩 묶음은 앞 6칸만 쓴다. 색상 칩은 그 6칸을 반씩 = 3칸씩 차지하므로
   화면 폭이 바뀌어도 바깥 12칸 그리드의 세로선에 맞는다.

   [문단] 한 연(聯)은 문단 하나, 연 안의 줄은 <br> 로 나눈다.
   문단과 문단 사이에만 여백이 생긴다.

   [조절]
     강조색     --ff-infogrid-color
     칸 사이    --ff-infogrid-gap
     행 사이    --ff-infogrid-rowGap
     매체 칸 수 --ff-infogrid-mediaSpan  (본문 9칸 중)
     항목명 고정 위치 --ff-infogrid-stickyGap (헤더 아랫선에서 띄울 만큼)
     이미지 아래 설명 --ff-infogrid-captionGap
================================================================== */
:root {
  --ff-infogrid-color: #6f14ff;
  --ff-infogrid-gap: 15px;
  --ff-infogrid-rowGap: 40px;
  --ff-infogrid-mediaSpan: 6;
  --ff-infogrid-stickyGap: 20px;
  /* 이미지와 그 아래 설명 글 사이 */
  --ff-infogrid-captionGap: 14px;
  --ff-infogrid-lineW: 1.5px;
  /* 아이덴티티 전용색 — 로고 가이드의 인쇄용 값을 화면에 옮긴 것 */
  --ff-swatch-purple: rgb(111, 34, 212);
  --ff-swatch-black: rgb(32, 26, 42);
}

.ff-infogrid {
  margin-top: 0px;
  margin-bottom: 60px;
}

.ff-infogrid__row {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--ff-infogrid-gap);
}

.ff-infogrid__row + .ff-infogrid__row {
  margin-top: 30px;
}
@media (max-width: 780px) {
  .ff-infogrid__row + .ff-infogrid__row {
    margin-top: 0px;
  }
}

/* 항목명은 그 행이 지나가는 동안 헤더 밑에 붙어 있다가, 행이 끝나면 본문과
   함께 밀려 올라간다. 긴 본문을 읽는 동안 "무엇에 대한 글인지"가 남는다.
   - align-self: start 가 있어야 한다. 그리드 칸은 기본이 stretch 라 항목명
     상자가 행 높이만큼 늘어나고, 그러면 상자가 움직일 자리가 없어 sticky 가
     아무 일도 하지 않는다.
   - 멈추는 높이는 헤더 아랫선(--ff-headerBottom, script.js 가 잰다)이다.
     PC/모바일 헤더 교대와 타이틀 접힘까지 따라간다. */
.ff-infogrid__label {
  position: sticky;
  top: calc(var(--ff-headerBottom, var(--ep-headerH, 0px)) + var(--ff-infogrid-stickyGap));
  align-self: start;
  grid-column: 1/span 3;
  margin: 0;
  color: var(--ff-infogrid-color);
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.6;
}

.ff-infogrid__body {
  display: grid;
  grid-template-columns: repeat(9, minmax(0, 1fr));
  align-content: start;
  column-gap: var(--ff-infogrid-gap);
  grid-column: 4/span 9;
  color: var(--color-black);
  line-height: 1.6;
}

.ff-infogrid__body > * {
  grid-column: 1/-1;
}

.ff-infogrid__body > .wp-block-image,
.ff-infogrid__body > .ff-logobox,
.ff-infogrid__body > .ff-swatches {
  grid-column: 1/span var(--ff-infogrid-mediaSpan);
}

/* 본문의 p 규칙이 넣는 여백을 되돌리고, 연 사이에만 여백을 둔다 */
.ff-infogrid__body p {
  margin: 0;
  font-size: inherit;
  line-height: inherit;
}

.ff-infogrid__body > * + * {
  margin-top: 1em;
}

.ff-infogrid__body > .ff-infogrid__head + * {
  margin-top: 5px;
}

/* 이미지(포스터 묶음 · 로고 박스 등) 바로 아래에 오는 설명 글.
   위의 "p 여백 되돌리기"가 문단의 위 여백까지 0 으로 만들어서, 그대로 두면
   글이 이미지 아랫변에 딱 붙는다. 문단이 아닌 것 뒤에 오는 문단만 띄운다
   (소제목도 p 라서 소제목 → 본문 간격은 위 규칙 그대로다). */
.ff-infogrid__body > :not(p) + p {
  margin-top: var(--ff-infogrid-captionGap);
}

.ff-infogrid__body > .ff-infogrid__head {
  color: var(--ff-infogrid-color);
  font-weight: var(--fw-medium);
}

/* 옵션에서 채우는 소제목([ff_slogan])이 비면 자리만 남지 않게 뺀다 */
.ff-infogrid__head:empty {
  display: none;
}

.ff-infogrid__body .wp-block-image {
  margin-left: 0;
  margin-right: 0;
  margin-bottom: 0;
}

.ff-infogrid__body .wp-block-image img {
  display: block;
  width: 100%;
  height: auto;
}

.ff-infogrid__body .wp-block-image figcaption {
  margin: var(--ff-infogrid-captionGap) 0 0;
  color: var(--color-black);
  font-size: inherit;
  line-height: inherit;
  text-align: left;
}

/* 로고 박스 — 3:2 테두리 박스 가운데에 로고 */
.ff-logobox {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 3/2;
  border: var(--ff-infogrid-lineW) solid var(--ff-infogrid-color);
  background-color: var(--color-white);
}

.ff-logobox__mark {
  display: block;
  width: 92%;
  line-height: 0;
}

.ff-logobox__mark .ep-svg,
.ff-logobox__mark svg {
  display: block;
  width: 100%;
  height: auto;
}

/* 색상 칩 — 두 칸, 칩 안은 CMYK / RGB 두 열 */
.ff-swatches {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ff-infogrid-gap);
}
@media (max-width: 780px) {
  .ff-swatches {
    grid-template-columns: repeat(1, minmax(0, 1fr));
    gap: 0px;
  }
}

.ff-infogrid__body > .ff-logobox + .ff-swatches {
  margin: 15px 0;
}

.ff-swatch {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--ff-infogrid-gap);
  padding: 12px 18px;
  color: var(--color-white);
  font-weight: var(--fw-medium);
  line-height: 1.5;
}

.ff-swatch--purple {
  background-color: var(--ff-swatch-purple);
}

.ff-swatch--black {
  background-color: var(--ff-swatch-black);
}

@media (max-width: 768px) {
  :root {
    --ff-infogrid-rowGap: 32px;
  }
  .ff-infogrid {
    margin-top: 0px;
    margin-bottom: 40px;
  }
  /* 좁은 화면에서는 항목명을 내용 위로 올린다.
     한 줄 위에 얹히는 모양이라 붙잡아둘 자리가 없어 고정도 푼다. */
  .ff-infogrid__label,
  .ff-infogrid__body {
    grid-column: 1/-1;
  }
  .ff-infogrid__label {
    position: static;
  }
  .ff-infogrid__label {
    margin-bottom: 6px;
  }
  .ff-infogrid__body > .wp-block-image,
  .ff-infogrid__body > .ff-logobox,
  .ff-infogrid__body > .ff-swatches {
    grid-column: 1/-1;
  }
  .ff-swatch {
    padding: 10px 12px;
  }
}
/* ----- Info Grid End ----- */
/* ==================================================================
   Split  (GenerateBlocks 블록 — 반반 레이아웃)
   ------------------------------------------------------------------
   페이지 제목 아래를 12칸 그리드로 나눠 왼쪽 6칸 / 오른쪽 6칸.
   조직구성의 "명단 표 | 조직도" 처럼 두 덩어리를 나란히 둘 때 쓴다.

   [구조] 조립은 inc/blocks.php 의 siff_block_split() 참고.
     .ff-split (section)
       ├ .ff-deflist__title     ← 페이지 제목 (정의형 표 제목과 같은 모양)
       └ .ff-split__grid
           ├ .ff-split__main    ← 1~6칸 (정의형 표 등)
           └ .ff-split__aside   ← 7~12칸 (이미지 등)

   [제목] 칸 밖에 둔다. 그래야 오른쪽 윗선이 왼쪽 첫 표의 소제목과 맞는다.
   그래서 왼쪽 첫 표는 위 여백(--ff-deflist-gapY)을 빼고 붙인다.
================================================================== */
:root {
  --ff-split-gap: 15px;
}

.ff-split {
  margin-top: 30px;
  margin-bottom: var(--ff-deflist-gapY);
}
@media (max-width: 780px) {
  .ff-split {
    margin-top: 10px;
  }
}

.ff-split__grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--ff-split-gap);
  align-items: start;
}

.ff-split__main {
  grid-column: 1/span 6;
}

.ff-split__aside {
  grid-column: 7/span 6;
}

.ff-split__main > .ff-deflist:first-child {
  margin-top: 0;
}

.ff-split__main > .ff-deflist:last-child {
  margin-bottom: 0;
}

.ff-split__aside .wp-block-image {
  margin: 0;
}

.ff-split__aside .wp-block-image img {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 1024px) {
  /* 좁아지면 오른쪽 덩어리를 표 아래로 내린다 */
  .ff-split__main,
  .ff-split__aside {
    grid-column: 1/-1;
  }
  .ff-split__aside {
    margin-top: var(--ff-deflist-gapY);
  }
}
/* ----- Split End ----- */
/* ==================================================================
   Program Films  (shortcode: [print_program_films])
   ------------------------------------------------------------------
   메인의 "프로그램 PROGRAM" 아래 상영작 3단 그리드 + 오른쪽 세로 링크.

   [구조]
     .ff-program                     ← 2칸: 그리드 | MORE FILMS
       ├ .ff-program__stage
       │   └ .ff-program__grid (ul)
       │       └ .ff-program__item   ← 썸네일 + 캡션(제목 __name · 정보 __meta)
       │           └ .ff-program__soon ← coming_soon 일 때만. 호버 시 덮는 막
       └ .ff-program__more           ← 세로선 + 세로 글자 + "+"

   [COMING SOON] 오픈 전에는 카드가 링크가 아니고(PHP 에서 a 대신 span),
   마우스를 올린 카드의 썸네일에만 막이 덮인다. 썸네일 박스 안에 넣었으므로
   캡션과 오른쪽 MORE FILMS 는 덮이지 않는다.

   [조절]
     막 색·흐림  --ff-program-veil / --ff-program-blur
     막 글자색   --ff-program-soonColor
     막 문구 크기 --ff-program-soonSize
     단 수·간격  --ff-program-cols / --ff-program-gapX / --ff-program-gapY
     썸네일 비율 --ff-program-ratio
     강조색     --ff-program-color
================================================================== */
:root {
  /* 카드 제목 크기 (아래 줄은 캡션 크기 그대로) */
  --ff-program-nameSize: 1.15rem;
  --ff-program-color: var(--ep-header-lineColor);
  --ff-program-cols: 3;
  --ff-program-gapX: 10px;
  --ff-program-gapY: 20px;
  --ff-program-ratio: 5 / 3;
  --ff-program-radius: 15px;
  /* 오픈 전, 카드 위 막 — 검은 막에 흰 글자.
     포스터가 밝든 어둡든 글자가 읽히려면 막이 어느 정도 어두워야 한다.
     더 연하게 하려면 마지막 숫자(투명도)를 낮춘다. */
  --ff-program-veil: rgba(0, 0, 0, 0.35);
  --ff-program-soonColor: var(--color-white);
  --ff-program-blur: 5px;
  /* 카드 한 장 폭에 맞춘 문구 크기 (그리드 전체를 덮던 때보다 작다) */
  --ff-program-soonSize: clamp(18px, 1.8vw, 30px);
  /* 세로 링크 — 그리드와 선 사이, 선과 글자 사이, 글자와 오른쪽 여백선 사이.
     셋 다 같은 값이라 글자가 선과 페이지 끝 사이 가운데에 선다. */
  --ff-program-moreGap: 20px;
  --ff-program-lineW: var(--ep-header-lineW);
  /* COMING SOON 글자 크기 */
  --ff-program-display: clamp(34px, 3.4vw, 64px);
  /* MORE FILMS 글자 크기 — 좁은 화면에서는 따로 잡는다(아래 미디어쿼리) */
  --ff-program-moreSize: var(--ff-program-display);
}

.ff-program {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--ff-program-moreGap);
  margin-bottom: 60px;
}
@media (max-width: 780px) {
  .ff-program {
    margin-bottom: 20px;
  }
}

/* ----- 그리드 ----- */
.ff-program__stage {
  min-width: 0;
}

.ff-program__grid {
  display: grid;
  grid-template-columns: repeat(var(--ff-program-cols), minmax(0, 1fr));
  column-gap: var(--ff-program-gapX);
  row-gap: var(--ff-program-gapY);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (max-width: 780px) {
  .ff-program__grid {
    row-gap: 15px;
    column-gap: 10px;
  }
}

.ff-program__item {
  margin: 0;
}

.ff-program__link {
  display: block;
  color: inherit;
}

.ff-program__thumb {
  display: block;
  aspect-ratio: var(--ff-program-ratio);
  overflow: hidden;
  border-radius: var(--ff-program-radius);
  /* 이미지가 없거나 로드 전일 때의 면 */
  background-color: #e6e6e6;
}

.ff-program__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 썸네일 아래 두 줄 — 제목(__name), 그 아래 감독 / 제작연도 / 러닝타임(__meta).
   제목이 먼저 읽히도록 한 단계 크고 굵게, 아래 줄은 작게 둔다. */
.ff-program__caption {
  display: block;
  margin-top: 10px;
  color: var(--color-black);
}

.ff-program__name {
  display: block;
  font-size: var(--ff-program-nameSize);
  font-weight: var(--fw-bold);
  line-height: 1.35;
}

.ff-program__meta {
  display: block;
  margin-top: 2px;
  font-size: 0.875rem;
  font-weight: var(--fw-medium);
  line-height: 1.5;
}

/* ----- 오픈 전, 카드 위 COMING SOON 막 -----
   썸네일 박스 안에 깔려 그 크기만큼만 덮는다(썸네일이 overflow: hidden +
   둥근 모서리라 막도 같은 모양으로 잘린다).
   평소에는 opacity 0 이고 마우스를 올린 카드에서만 보인다.
   pointer-events: none — 막이 마우스를 가로채면 카드에서 벗어났다고 판단해
   깜빡인다. */
.ff-program__soon {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0 10px;
  background-color: var(--ff-program-veil);
  -webkit-backdrop-filter: blur(var(--ff-program-blur));
  backdrop-filter: blur(var(--ff-program-blur));
  color: var(--ff-program-soonColor);
  font-family: var(--font-display);
  font-size: var(--ff-program-soonSize);
  font-weight: var(--fw-bold);
  font-synthesis: none;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

.ff-program--soon .ff-program__item:hover .ff-program__soon {
  opacity: 1;
}

/* 오픈 전 카드는 링크가 아니다 — 손가락 커서가 뜨지 않게 한다 */
.ff-program--soon .ff-program__link {
  cursor: default;
}

@media (prefers-reduced-motion: reduce) {
  .ff-program__soon {
    transition: none;
  }
}
/* ----- 오른쪽 세로 링크 -----
   선은 border 라 그리드 높이(행 2개 + 캡션)만큼 자동으로 늘어난다.
   글자는 위, "+" 는 아래 끝에 붙는다. 좌우 여백을 같게 둬서 글자와 "+" 가
   선과 페이지 오른쪽 여백선 사이 한가운데 축에 선다. */
.ff-program__more {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  padding-left: var(--ff-program-moreGap);
  padding-right: var(--ff-program-moreGap);
  border-left: var(--ff-program-lineW) solid var(--ff-program-color);
  color: var(--ff-program-color);
}

a.ff-program__more:hover,
a.ff-program__more:focus-visible {
  color: var(--ff-program-color);
  opacity: 0.8;
}

.ff-program__more-text {
  /* 위에서 아래로 읽히게 시계 방향으로 눕힌다 */
  writing-mode: vertical-rl;
  font-family: var(--font-display);
  font-size: var(--ff-program-moreSize);
  font-weight: var(--fw-bold);
  font-synthesis: none;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  /* 글자를 자기 박스 가운데로 옮긴다.
     ── 왜 필요한가 ──
     PP Formula 는 베이스라인 위 88% / 아래 28% 를 라인박스로 잡는데
     대문자는 베이스라인 아래를 쓰지 않는다. 세로로 눕히면(vertical-rl)
     글자 윗부분이 오른쪽을 향하므로, 비어 있는 아래 몫(약 0.22em)이
     박스 왼쪽에 몰린다 → 좌우 여백을 같게 줘도 글자는 오른쪽으로 붙어
     보이고 아래 "+" 와도 축이 어긋난다. 그 절반만큼 왼쪽으로 옮긴다.
     (타이틀 글꼴은 fonts/font.css 에서 메트릭을 바로잡았지만, 이 글꼴은
      헤더 로고가 같이 쓰고 있어 여기서만 보정한다.) */
  left: -0.11em;
}

.ff-program__plus {
  display: block;
  width: 0.9em;
  height: 0.9em;
  font-size: var(--ff-program-moreSize);
}

/* ----- 좁은 화면 -----
   세로 링크를 그리드 아래 오른쪽 끝에 붙는 검정 버튼으로 바꾼다.
   글자가 눕지 않으므로 세로쓰기 보정(left)도 되돌린다. */
@media (max-width: 768px) {
  :root {
    --ff-program-cols: 2;
    --ff-program-gapX: 12px;
    --ff-program-gapY: 24px;
    --ff-program-moreSize: 24px;
  }
  .ff-program {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 20px;
  }
  /* 좁은 화면 — 제목은 본문 크기보다 한 단계만 크게, 아래 줄은 작게 */
  :root {
    --ff-program-nameSize: 16px;
  }
  .ff-program__meta {
    font-size: 13px;
  }
  .ff-program__more {
    /* 섹션 오른쪽 끝에 붙인다. 폭은 글자만큼만 */
    justify-self: end;
    flex-direction: row;
    align-items: center;
    gap: 6px;
    /* 아래 패딩이 작은 이유: 이 글꼴(PP Formula)은 대문자가 쓰지 않는
       디센더 몫을 글자 아래에 남긴다. 위아래를 같게 주면 아래가 더 넓어
       보이므로, 그만큼(약 4px) 빼서 눈에 보이는 여백을 맞춘다. */
    padding: 7px 6px 2px 8px;
    border: 0;
    background-color: var(--color-black);
    color: var(--color-white);
  }
  a.ff-program__more:hover,
  a.ff-program__more:focus-visible {
    color: var(--color-white);
  }
  .ff-program__more-text {
    writing-mode: horizontal-tb;
    left: 0;
    font-size: 22px;
  }
  /* 글자 옆 "+" — 작게, 그리고 글자와 눈높이를 맞춘다.
     이 글꼴은 대문자가 쓰지 않는 디센더 몫을 글자 아래에 남겨서, 글자 잉크의
     가운데가 줄 박스 가운데보다 약 0.1em 위에 있다. 아이콘은 자기 박스
     정중앙에 놓이므로 그대로 두면 아래로 처져 보인다. 그만큼 올린다. */
  .ff-program__plus {
    width: 0.55em;
    height: 0.55em;
    top: -0.1em;
  }
}
/* ----- Program Films End ----- */
/* ==================================================================
   Notice Columns  (shortcode: [print_notice_columns])
   ------------------------------------------------------------------
   메인의 공지 · 상영소식 최신 글 목록. 카테고리마다 한 칸, 기본 1:1.

   [구조]
     .ff-notice-cols                  ← 칸 수는 --ff-notice-cols (PHP 가 넣는다)
       └ .ff-notice-col (section)
           ├ .ff-notice-col__title    ← 칸 제목. 링크가 아닌 글자다
           │   ├ __title-ko             ← 국문. 숨김(display:none) — 데이터만 남겨 둔다
           │   └ __title-en             ← 영문. 화면에 보이는 쪽
           └ .ff-notice-col__list (ul)
               └ li > a.ff-notice-col__link
                   ├ .ff-notice-col__name   ← 글 제목 (길면 여러 줄)
                   └ .ff-notice-col__badge  ← 상단고정 글에만 "Notice"

   [선] 목록 맨 위와 각 행 아래에 검정 선. 행 위아래 여백이 같아서
   제목이 두 줄이 되어도 배지는 행 가운데에 머문다.

   [조절]
     선         --ff-notice-line / --ff-notice-lineW
     행 배경    --ff-notice-bg (선 색을 흰색에 섞은 연한 색)
     행 여백    --ff-notice-rowPadY
     글 크기    --ff-notice-size
     칸 사이    --ff-notice-gap
     제목 아래  --ff-notice-titleGap
================================================================== */
:root {
  --ff-notice-line: var(--ep-header-lineColor);
  /* 행 배경 — 같은 보라를 흰색에 섞은 연한 색.
     보라 값(--ep-header-lineColor)을 바꾸면 배경도 같이 따라간다. */
  --ff-notice-bg: color-mix(in srgb, var(--ff-notice-line) 8%, #fff);
  --ff-notice-lineW: 1.5px;
  --ff-notice-rowPadY: 6px;
  /* 본문 글자 크기를 따라간다 — 데스크톱 1rem, 모바일 15px
     (style.scss 의 --ep-bodySize) */
  --ff-notice-size: var(--ep-bodySize);
  --ff-notice-gap: var(--ep-margin);
  --ff-notice-hover: var(--ep-header-lineColor);
  /* 칸 제목과 목록 맨 윗선 사이 */
  --ff-notice-titleGap: 20px;
}

.ff-notice-cols {
  display: grid;
  grid-template-columns: repeat(var(--ff-notice-cols, 2), minmax(0, 1fr));
  column-gap: var(--ff-notice-gap);
  row-gap: 30px;
  margin-bottom: 60px;
}

.ff-notice-col {
  min-width: 0;
}

/* 페이지의 다른 섹션 제목(h1 — 프로그램 PROGRAM 등)과 같은 모양 */
.ff-notice-col__title {
  margin: 0 0 var(--ff-notice-titleGap);
  padding: 0;
  color: var(--color-black);
  font-size: var(--title-m);
  line-height: 1.1;
  text-transform: uppercase;
}
@media (max-width: 1024px) {
  .ff-notice-col__title {
    font-size: 22px;
  }
}
.ff-notice-col__title {
  /* 국문은 숨기고 영문만 보인다 (2026-10 결정). 마크업은 inc/notice-columns.php
     siff_notice_column_title_html — 국문 span 을 남겨 두는 이유도 거기 적혀 있다. */
}
.ff-notice-col__title .ff-notice-col__title-ko {
  display: none;
}

/* ----- 목록 ----- */
.ff-notice-col__list {
  margin: 0;
  padding-top: 10px;
  padding: 0;
  border-top: var(--ff-notice-lineW) solid var(--ff-notice-line);
  list-style: none;
}

.ff-notice-col__item {
  margin: 0;
  border-bottom: var(--ff-notice-lineW) solid var(--ff-notice-line);
}

.ff-notice-col__link {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 8px 5px;
  color: var(--color-black);
  font-size: var(--ff-notice-size);
  font-weight: 500;
  line-height: 1.45;
  text-decoration: none;
  background-color: var(--ff-notice-bg);
}
@media (max-width: 1024px) {
  .ff-notice-col__link {
    padding: 5px 0;
  }
}

.ff-notice-col__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.ff-notice-col__link:hover .ff-notice-col__name,
.ff-notice-col__link:focus-visible .ff-notice-col__name {
  color: var(--ff-notice-hover);
}

/* 마우스를 올리면 글자가 안쪽으로 밀린다 — 공지 상세의 첨부파일 줄과 같은
   움직임(styles/_notice-single.scss). 마우스가 있는 기기에만 건다. 손가락으로
   쓰는 기기는 눌렀다 뗀 뒤에도 그 상태가 남아 어느 줄을 건드렸는지 헷갈린다. */
@media (hover: hover) and (pointer: fine) {
  .ff-notice-col__link {
    transition: padding-left var(--ep-rowHoverSpeed) ease;
  }
  .ff-notice-col__link:hover,
  .ff-notice-col__link:focus-visible {
    /* 기본 좌 패딩(5px)에 밀리는 만큼을 더한다 */
    padding-left: calc(5px + var(--ep-rowHoverShift));
  }
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  .ff-notice-col__link {
    transition: none;
  }
}
.ff-notice-col__badge {
  flex: 0 0 auto;
  padding: 3px 8px;
  border: var(--ff-notice-lineW) solid var(--ff-notice-line);
  color: var(--color-black);
  font-size: 0.85rem;
  font-weight: var(--fw-medium);
  line-height: 1.3;
}

.ff-notice-col__empty {
  margin: 0;
  padding: var(--ff-notice-rowPadY) 0;
  border-top: var(--ff-notice-lineW) solid var(--ff-notice-line);
  border-bottom: var(--ff-notice-lineW) solid var(--ff-notice-line);
  color: #8c8c8c;
  font-size: var(--ff-notice-size);
  line-height: 1.3;
}

/* 좁은 화면: 칸을 위아래로 */
@media (max-width: 768px) {
  :root {
    --ff-notice-rowPadY: 14px;
  }
  .ff-notice-cols {
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: 20px;
  }
  .ff-notice-col__link {
    gap: 12px;
  }
}
/* ----- Notice Columns End ----- */
/* ==================================================================
   Notice Single  (템플릿: single-notice.php · 마크업: inc/notice-single.php)
   ------------------------------------------------------------------
   공지사항 상세. 헤더 아래 제목 묶음이 오고, 그 아래로 포스터와 본문이
   위에서 아래로 차례로 쌓인다.

   [구조]
     .ff-notice
       ├ .ff-notice__head      ← 카테고리 · 제목(h1) · 날짜
       └ .ff-notice__body      ← 한 칸. 위에서 아래로 쌓인다
           ├ .ff-notice__visual  포스터
           └ .ff-notice__main    본문 + 첨부파일

   [글 폭] 본문은 --ff-notice-single-maxW 에서 멈추고 가운데 선다. 넓은
   화면에서 한 줄이 끝없이 길어지면 읽기 어렵기 때문이다. 제목 묶음의 보라
   면은 화면 끝까지 가되, 그 안의 글자는 본문과 같은 선에서 시작한다 —
   좌우 패딩을 max() 로 잡아 좁은 화면에서는 사이트 마진, 넓은 화면에서는
   본문이 들어오는 자리까지 벌린다.

   [그림 크기] 가로형은 칸 폭을 꽉 채운다. 세로형은 그대로 두면 화면을 다
   먹으므로 높이(--ff-notice-single-visualMaxH)에서 멈추고 가운데 선다.
   방향을 따로 판정하지 않는다 — max-width 와 max-height 를 함께 두면
   가로로 긴 그림은 폭에서, 세로로 긴 그림은 높이에서 먼저 걸린다.

   [조절]
     세로 간격     --ff-notice-single-gapY
     그림 높이 상한 --ff-notice-single-visualMaxH
     본문 최대 폭  --ff-notice-single-maxW
     그림 사이     --ff-notice-galleryGap
     제목 크기     --ff-notice-single-titleSize
     카테고리 태그 --ff-notice-single-tagPadY / -tagPadX / -tagLineW

   [이름] 토큰 이름에 single 을 넣는다 — 목록(_notice-columns.scss)이 같은
   --ff-notice-* 이름을 쓰고 있어, 겹치면 목록 쪽 값을 덮어버린다.
================================================================== */
:root {
  /* 본문이 가장 넓어질 수 있는 폭 */
  --ff-notice-single-maxW: 1200px;
  /* 썸네일 줄 */
  /* 그림과 그림 사이 */
  --ff-notice-galleryGap: 20px;
  --ff-notice-single-color: #6f14ff;
  --ff-notice-single-titleSize: 28px;
  /* 카테고리 태그 */
  --ff-notice-single-tagPadY: 4px;
  --ff-notice-single-tagPadX: 10px;
  --ff-notice-single-tagLineW: 1.5px;
  /* 태그와 날짜 사이 */
  --ff-notice-single-labelGap: 12px;
  /* 보라 면의 위아래 여백 */
  --ff-notice-single-headPadY: 26px;
  --ff-notice-single-line: #d5d5d5;
  --ff-notice-single-gapY: 40px;
  /* 그림 높이 상한 — 세로로 긴 포스터가 화면을 다 먹지 않도록 */
  --ff-notice-single-visualMaxH: min(80svh, 720px);
}

/* 푸터와의 간격. margin 으로 주면 GeneratePress 의
   ".separate-containers .site-main > :last-child { margin-bottom: 0 }" 에
   눌려 사라진다(특이도가 더 높다). padding 은 그 규칙과 겹치지 않는다.
   값은 섹션 화면(_archive.scss)과 같은 토큰을 써서 페이지마다 다르지 않게. */
.ff-notice {
  padding-bottom: var(--ff-section-footerGap);
}

/* ----- 제목 묶음 -----
   보라 면 위에 흰 글자. 면은 사이트 좌우 마진을 넘어 화면 끝까지 채운다
   (띠배너·하위 탭 바와 같은 방식) — 음수 마진으로 .site-content 의 좌우
   패딩을 되돌리고, 글은 같은 값만큼 안쪽 패딩으로 밀어 본문과 선을 맞춘다. */
.ff-notice__head {
  margin-right: calc(var(--ep-margin) * -1);
  margin-bottom: var(--ff-notice-single-gapY);
  margin-left: calc(var(--ep-margin) * -1);
  padding: var(--ep-margin);
  /* 면은 화면 끝까지, 글자는 본문과 같은 선에서.
     본문(.ff-notice__body)은 부모 안에서 최대 폭까지만 넓어지고 가운데
     서므로, 왼쪽에 (부모 폭 - 최대 폭) / 2 만큼 빈자리가 생긴다. 이 면은
     음수 마진으로 사이트 마진만큼 더 왼쪽에서 시작하니, 그만큼을 더해야
     글자가 본문과 같은 선에 온다.
     퍼센트는 자기 폭이 아니라 부모 폭 기준이다 — 이 면이 화면 끝까지
     늘어나 있어도 100% 는 부모(본문과 같은 폭)를 가리킨다.
     좁은 화면에서는 이 값이 사이트 마진보다 작아지므로 max() 로 받는다. */
  padding-inline: max(var(--ep-margin), (100% - var(--ff-notice-single-maxW)) / 2 + var(--ep-margin));
  background-color: var(--ff-notice-single-color);
  color: var(--color-white);
}

/* 카테고리 태그와 날짜는 제목 아래 한 행에 나란히 둔다 */
.ff-notice__label {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--ff-notice-single-labelGap);
  margin-top: 8px;
}

/* 카테고리는 글자가 아니라 태그로 읽히게 — 테두리를 두르고 글자만큼만 차지한다.
   (목록의 "Notice" 배지와 같은 모양 — styles/_notice-columns.scss) */
.ff-notice__category {
  display: inline-block;
  margin: 0;
  padding: var(--ff-notice-single-tagPadY) var(--ff-notice-single-tagPadX);
  color: var(--ff-notice-single-color);
  font-size: 14px;
  font-weight: var(--fw-semibold);
  line-height: 1.2;
  background-color: var(--color-white);
  border-radius: 5px;
}

/* 제목은 타이틀 서체(PP Formula Fit + kigsans 혼용)를 쓰지 않는다 — 국문
   본문 서체 하나로 간다. h1 은 _title.scss 에서 타이틀 서체를 받고
   style.scss 에서 위 패딩을 받으므로 둘 다 여기서 되돌린다. */
.ff-notice__title {
  margin: 0;
  padding-top: 0;
  color: inherit;
  font-family: var(--font-body);
  font-size: var(--ff-notice-single-titleSize);
  font-weight: var(--fw-semibold);
  /* 제목은 줄이 길어지므로 타이틀 기본(1.2)보다 조금 넉넉하게 */
  line-height: 1.3;
}

.ff-notice__meta {
  margin: 0 0;
  color: inherit;
  font-size: inherit;
  font-weight: var(--fw-semibold);
  line-height: 1.4;
}

/* ----- 두 칸 ----- */
.ff-notice__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: var(--ff-notice-single-gapY);
  max-width: var(--ff-notice-single-maxW);
  margin-inline: auto;
}

.ff-notice__main {
  min-width: 0;
}

/* 그림 크기 — 한 장이든 여러 장이든 같은 규칙이다.
   폭과 높이 모두 상한만 두고 크기는 그림이 정한다(width/height: auto).
     가로형 : 칸 폭(--ff-notice-single-maxW, 1200px)에서 멈춘다.
     세로형 : 높이 상한에서 먼저 멈추고, 그만큼 폭도 비율대로 줄어든다.
   폭을 100% 로 못박지 않는 이유 — 상자가 칸 폭 그대로인데 높이만 잘리면
   세로형 그림이 상자 안에서 작아지면서 좌우에 빈 띠가 남는다. 상한만
   두면 상자가 그림에 맞으므로 빈자리 없이 가운데 선다.
   높이 기준은 svh 다. dvh 로 두면 모바일에서 주소창이 접힐 때마다 값이
   바뀌어 스크롤 중에 그림 크기가 변한다. */
.ff-notice__visual img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: var(--ff-notice-single-visualMaxH);
  margin-inline: auto;
}

/* ----- 이미지 묶음 (상세 이미지 필드) -----
   넘겨 보는 슬라이드가 아니라, 위에서 아래로 쭉 쌓는다. 한 화면에 한 장만
   보이면 몇 장이 더 있는지 알기 어렵고, 공지의 그림은 대개 끝까지 읽어야
   하는 안내문이라 스크롤로 내려보는 쪽이 맞다. 장치가 없으니 Swiper 도
   싣지 않는다. */
.ff-notice-gallery {
  display: grid;
  row-gap: var(--ff-notice-galleryGap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ff-notice-gallery__item {
  margin: 0;
}

/* 그림 크기는 위 .ff-notice__visual img 규칙이 그대로 받는다
   (이 묶음도 .ff-notice__visual 안에 들어간다) */
/* ----- 본문 ----- */
.ff-notice__content {
  line-height: 1.7;
}

.ff-notice__content > *:first-child {
  margin-top: 0;
}

.ff-notice__content img {
  max-width: 100%;
  height: auto;
}

.ff-notice__content a {
  color: var(--ff-notice-single-color);
  text-decoration: underline;
  word-break: break-all;
}

/* ----- 원문 링크 (언론보도 · SIFF 데일리) ----- */
.ff-notice__external {
  margin: var(--ff-notice-single-gapY) 0 0;
}

.ff-notice__external-link {
  display: inline-block;
  padding: 10px 18px;
  border: 1.5px solid var(--ff-notice-single-color);
  color: var(--ff-notice-single-color);
  font-weight: var(--fw-bold);
  line-height: 1.2;
}

/* ----- 첨부파일 ----- */
.ff-notice-files {
  margin-top: var(--ff-notice-single-gapY);
  border-top: 1.5px solid var(--ff-notice-single-color);
}

.ff-notice-files__title {
  margin: 14px 0 6px;
  color: var(--ff-notice-single-color);
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.4;
}

.ff-notice-files__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ff-notice-files__item {
  border-bottom: 1px solid var(--ff-notice-single-line);
}
.ff-notice-files__item:first-child {
  border-top: 1px solid var(--ff-notice-single-line);
}

.ff-notice-files__link {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 0;
  color: var(--color-black);
  line-height: 1.4;
  transition: background-color var(--ep-rowHoverSpeed) ease, padding-left var(--ep-rowHoverSpeed) ease;
}

.ff-notice-files__name {
  flex: 1 1 auto;
  min-width: 0;
  word-break: break-all;
}

.ff-notice-files__action {
  flex: 0 0 auto;
  color: var(--ff-notice-single-color);
  font-weight: var(--fw-bold);
  white-space: nowrap;
}

/* ----- 호버 (마우스가 있는 기기에서만) -----
   손가락으로 쓰는 기기는 호버가 "눌렀다 뗀 뒤에도 남는 상태"가 되어 어느 줄을
   건드렸는지 헷갈린다. hover·pointer 질의로 마우스가 달린 기기에만 건다.
   움직임은 한 줄이 통째로 반응하는 쪽으로 — 줄 전체가 링크이기 때문이다. */
@media (hover: hover) and (pointer: fine) {
  .ff-notice-files__link:hover,
  .ff-notice-files__link:focus-visible {
    /* 보라를 흰색에 옅게 섞은 면. 선 색을 바꾸면 이 면도 같이 따라간다. */
    background-color: color-mix(in srgb, var(--ff-notice-single-color) 7%, transparent);
    /* 글자가 살짝 안쪽으로 들어가며 "이 줄"이 집힌 느낌을 준다 */
    padding-left: var(--ep-rowHoverShift);
  }
  .ff-notice-files__link:hover .ff-notice-files__name,
  .ff-notice-files__link:focus-visible .ff-notice-files__name {
    color: var(--ff-notice-single-color);
  }
}
@media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: reduce) {
  .ff-notice-files__link {
    transition: none;
  }
}
@media (max-width: 768px) {
  :root {
    --ff-notice-single-gapY: 28px;
  }
}
/* 좁은 화면 — 제목 면 아래에서 본문이 시작하는 높이를 사이트 공통값으로 맞춘다.
   (--ff-notice-single-gapY 는 본문 안의 세로 간격에도 쓰여서 건드리지 않는다) */
@media (max-width: 1024px) {
  :root {
    /* 상세 화면 제목의 모바일 크기 — SIFF PLUS · 역대영화제 · 행사사진 · 상영작
       상세와 같은 16px. 모바일 헤더로 바뀌는 폭부터 건다. */
    --ff-notice-single-titleSize: 16px;
  }
  /* 제목 면은 검게 깐다. 모바일 헤더가 보라 면이라, 바로 아래 이 면까지 보라면
     둘이 한 덩어리로 붙어 어디까지가 헤더인지 갈리지 않는다(SIFF PLUS · 역대영화제 ·
     행사사진 상세와 같은 처리 — styles/_siff-plus-single.scss). */
  .ff-notice__head {
    margin-bottom: var(--ep-contentTop);
    background-color: var(--color-black);
  }
  /* 제목 아래 줄(카테고리 태그 · 날짜)은 좁은 화면에서 12px — 다른 상세 화면과 같다 */
  .ff-notice__category,
  .ff-notice__meta {
    font-size: 12px;
  }
  /* 카테고리 태그의 글자는 제목 면과 같은 검정(다른 상세 화면과 같다) */
  .ff-notice__category {
    color: var(--color-black);
  }
}
/* ----- Notice Single End ----- */
/* ==================================================================
   Sponsor Rolling  (shortcode: [print_sponsor_rolling])
   ------------------------------------------------------------------
   사이트 옵션 "후원사 롤링 배너" 로고가 옆으로 끊김 없이 흐른다.

   [원리] 텍스트 롤링 배너(_rolling.scss)의 장치를 그대로 쓴다 — 로고 한 벌을
   script.js 가 복제하고 "한 벌 너비"만큼 옮긴다. 여기서는 모양만 바꾼다.
   이음매 계산이 "한 벌 너비"에 의존하므로 로고 사이 간격은 margin/gap 이
   아니라 로고의 오른쪽 padding 으로 준다(텍스트 배너와 같은 이유).

   [로고 크기] 받은 파일마다 여백과 비율이 제각각이라 PHP 가 두 가지를 맞춰
   넘긴다(inc/sponsors.php "로고 크기 맞추기").
     - 여백: 잘라낸 파일을 쓴다 → 모든 로고가 여백 0 에서 출발한다.
     - 비율: 로고별 배율 --ff-logo-scale(0.4~1)을 인라인으로 넘긴다.
       높이 = 기준 높이 × 배율. 가로 × 세로 면적이 로고끼리 비슷해진다.
   그래서 --ff-sponsor-h 는 "정사각형 로고의 높이" 다. 가로로 긴 로고일수록
   낮게 그려진다.

   [조절]
     기준 높이 --ff-sponsor-h (최댓값을 바꾸면 PHP 의 SIFF_LOGO_BOX 도 같이)
     로고 간격 --ff-sponsor-gap
     상하 여백 --ff-sponsor-padY
     흐름 속도 숏코드 speed 속성(초당 px, 기본 50)
================================================================== */
:root {
  --ff-sponsor-h: clamp(56px, 6.5vw, 120px);
  --ff-sponsor-gap: clamp(40px, 5vw, 96px);
  --ff-sponsor-padY: 24px;
}

/* 텍스트 배너는 그라디언트 레이어(.ep-gradient-layer)가 넘친 트랙을 잘라주는데
   로고 배너에는 그 레이어가 없으므로 직접 자른다. 안 자르면 복제된 트랙이
   화면 오른쪽으로 삐져나가 가로 스크롤이 생긴다. */
.ff-rolling--logos {
  overflow: hidden;
  padding-top: var(--ff-sponsor-padY);
  padding-bottom: var(--ff-sponsor-padY);
  color: inherit;
}

.ff-rolling--logos .ff-rolling__group {
  align-items: center;
}

/* 테마·GP 의 img { max-width: 100%; height: auto } 를 되돌린다.
   max-width 가 살아 있으면 트랙 폭에 눌려 로고가 줄어든다. */
.ff-rolling--logos .ff-rolling__logo {
  display: block;
  flex: 0 0 auto;
  box-sizing: content-box;
  width: auto;
  max-width: none;
  height: calc(var(--ff-sponsor-h) * var(--ff-logo-scale, 1));
  padding-right: var(--ff-sponsor-gap);
  object-fit: contain;
}

@media (max-width: 768px) {
  :root {
    --ff-sponsor-padY: 16px;
  }
}
/* ----- Sponsor Rolling End ----- */
/* ==================================================================
   Sponsor Grid  (shortcode: [print_sponsor_grid])
   ------------------------------------------------------------------
   스폰서 페이지. 영역(후원·협찬·협력)마다 제목 + 로고 테두리 박스 격자.

   [로고 크기] 롤링 배너와 같은 방식이다 — 여백 자른 파일 + 로고별 배율
   (--ff-logo-scale). 다른 점은 기준 높이가 고정값이 아니라 박스 폭의 비율
   (--ff-sponsor-cellH, 컨테이너 단위 cqw)이라는 것. 칸 수가 바뀌어 박스가
   커지거나 작아져도 로고가 박스 안에서 같은 비중으로 앉는다.
   아주 긴 로고는 박스 폭의 --ff-sponsor-cellMaxW 에서 멈춘다.

   [조절]
     칸 수         --ff-sponsor-cols
     칸 사이       --ff-sponsor-gridGap
     박스 비율     --ff-sponsor-cellRatio
     로고 기준 높이 --ff-sponsor-cellH   (박스 폭 대비)
     로고 최대 폭   --ff-sponsor-cellMaxW (박스 폭 대비)
================================================================== */
:root {
  --ff-sponsor-cols: 6;
  --ff-sponsor-gridGap: 15px;
  --ff-sponsor-cellRatio: 16 / 9;
  --ff-sponsor-cellH: 37cqw;
  --ff-sponsor-cellMaxW: 80%;
}

.ff-sponsor-grid {
  margin-top: var(--ff-deflist-gapY);
  margin-bottom: var(--ff-deflist-gapY);
}

/* 좁은 화면 — 페이지의 첫 묶음은 위 여백을 뺀다. 묶음 제목(h2)이 style.scss 에서
   위 패딩 20px 를 이미 갖고 있어(= --ep-contentTop), 여백까지 더하면 헤더 아래가
   52px 로 벌어진다. 앞에 감춰 둔 롤링 띠가 있을 수 있어 두 경우를 다 잡는다. */
@media (max-width: 1024px) {
  .ff-sponsor-grid:first-child,
  .ff-rolling + .ff-sponsor-grid {
    margin-top: 0;
  }
}
.ff-sponsor-grid__list {
  display: grid;
  grid-template-columns: repeat(var(--ff-sponsor-cols), minmax(0, 1fr));
  gap: var(--ff-sponsor-gridGap);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ff-sponsor-grid__item {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: var(--ff-sponsor-cellRatio);
  margin: 0;
  border: var(--ff-deflist-lineW) solid var(--ff-deflist-color);
  background-color: var(--color-white);
  container-type: inline-size;
}

/* 테마의 img { max-width: 100%; height: auto } 를 되돌리고 박스 기준으로 잡는다 */
.ff-sponsor-grid__logo {
  display: block;
  width: auto;
  max-width: var(--ff-sponsor-cellMaxW);
  height: calc(var(--ff-sponsor-cellH) * var(--ff-logo-scale, 1));
  object-fit: contain;
}

@media (max-width: 1024px) {
  :root {
    --ff-sponsor-cols: 4;
  }
}
@media (max-width: 768px) {
  :root {
    --ff-sponsor-cols: 3;
    --ff-sponsor-gridGap: 10px;
  }
}
@media (max-width: 480px) {
  :root {
    --ff-sponsor-cols: 2;
  }
}
/* ----- Sponsor Grid End ----- */
/* ==================================================================
   Newsletter  (shortcode: [print_newsletter] — 스티비 구독 폼)
   ------------------------------------------------------------------
   메인 맨 아래, 푸터 바로 위 보라색 띠. 폼 마크업과 동작은 스티비 것이고
   (inc/newsletter.php), 여기서는 모양만 사이트 디자인에 맞춘다.

   [구조]
     .ff-newsletter.apply-newsletter      ← 보라 띠, 2칸: 제목 | 폼
       ├ .ff-newsletter__head             ← 뉴스레터 NEWSLETTER + 안내 문장
       └ #stb_subscribe > form.stb_form   ← 한 줄씩 세로로
             이메일 (밑줄)
             이름   (밑줄)
             □ 개인정보 수집 및 이용에 동의합니다.
             □ 광고성 정보 수신에 동의합니다.
             [구독하기]
             결과 메시지

   [범위] 스티비 기본 CSS 는 #stb_subscribe 아이디 선택자라 우선순위가 높고,
   숏코드가 본문 밖에 쓰이면 우리 CSS 보다 늦게(footer 에서) 로드되기도 한다.
   그래서 폼 규칙은 전부 $nl(.ff-newsletter.apply-newsletter #stb_subscribe)
   아래에 둬서 로드 순서와 상관없이 항상 이기게 한다. 이 래퍼 밖에는
   아무것도 덮어쓰지 않는다.

   [스티비가 직접 바꾸는 것] 에러 문구와 결과 영역의 표시 여부는 스티비 JS 가
   인라인 style(display)로, 결과 성공/실패는 success · fail 클래스로 바꾼다.
   여기서 display 를 강제하면 그 동작이 깨지므로 모양만 정한다.

   [약관 모달] 보라 띠 위에 뜨지만 흰 상자로 둔다 — 긴 글을 읽는 곳이라
   흰 바탕 검은 글자가 낫다. 그래서 모달 안쪽은 색을 따로 지정한다.

   [조절]
     배경·글자색 --ff-newsletter-bg / --ff-newsletter-fg
     오류색     --ff-newsletter-error (보라 위에서 읽히는 밝은 빨강)
     입력 높이  --ff-newsletter-h / 밑줄 두께 --ff-newsletter-lineW
     위아래 여백 --ff-newsletter-padTop / --ff-newsletter-padBottom

   [!important] 테마 전역(style.scss)이 input · button 의 글자 크기와 줄 높이를
   1rem !important 로 고정한다. 입력칸·버튼 크기를 디자인대로 주려면 이 폼
   안에서만 !important 로 되받아야 한다.
================================================================== */
:root {
  --ff-newsletter-bg: var(--ep-header-lineColor);
  --ff-newsletter-fg: var(--color-white);
  --ff-newsletter-error: #ffc9cf;
  --ff-newsletter-h: 44px;
  --ff-newsletter-lineW: 1.5px;
  --ff-newsletter-padTop: 24px;
  --ff-newsletter-padBottom: 29px;
}

/* ----- 띠 -----
   사이트 좌우 마진을 넘어 화면 끝까지 칠한다(롤링 배너와 같은 방식).
   안쪽 글자는 다시 사이트 마진만큼 들여 다른 섹션과 왼쪽 선을 맞춘다. */
.ff-newsletter {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--ep-margin);
  row-gap: 28px;
  align-items: start;
  margin: 50px calc(var(--ep-margin) * -1) 0;
  padding: var(--ff-newsletter-padTop) var(--ep-margin) var(--ff-newsletter-padBottom);
  background-color: var(--ff-newsletter-bg);
  color: var(--ff-newsletter-fg);
}

/* 다른 섹션 제목(프로그램 PROGRAM 등)과 같은 국영문 타이틀 체계 */
.ff-newsletter__title {
  margin: 0 0 14px;
  padding: 6px 0 0;
  color: var(--ff-newsletter-fg);
  font-size: var(--title-m);
  line-height: 1.1;
  text-transform: uppercase;
}
@media (max-width: 1024px) {
  .ff-newsletter__title {
    font-size: 22px;
  }
}

.ff-newsletter__desc {
  margin: 0;
  color: var(--ff-newsletter-fg);
  font-size: 1.125rem;
  font-weight: var(--fw-medium);
  line-height: 1.4;
}
@media (max-width: 1024px) {
  .ff-newsletter__desc {
    font-size: 0.8125rem;
  }
}

/* ----- 스티비 기본 모양 되돌리기 -----
   기본 CSS 는 폼 전체에 흰 박스·테두리를 치고, 모든 요소를 14px · #333 으로
   고정한다. 박스는 없애고 글자는 띠의 설정(흰색)을 이어받게 한다. */
.ff-newsletter.apply-newsletter #stb_subscribe {
  padding: 0;
  border: 0;
  background: none;
}

.ff-newsletter.apply-newsletter #stb_subscribe * {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

/* ----- 폼: 한 줄씩 세로로 ----- */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "email" "name" "policy" "submit";
  row-gap: 11px;
}

/* fieldset 은 기본 min-width 가 내용 폭이라 그리드 칸보다 커질 수 있다 */
.ff-newsletter.apply-newsletter #stb_subscribe fieldset {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.ff-newsletter.apply-newsletter #stb_subscribe .ff-newsletter__email {
  grid-area: email;
}

.ff-newsletter.apply-newsletter #stb_subscribe .ff-newsletter__name {
  grid-area: name;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_policy_wrap {
  grid-area: policy;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 7px;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_submit {
  grid-area: submit;
  padding: 12px 0 0;
}

/* 결과 영역은 줄을 미리 잡아두지 않고 버튼 다음으로 자동 배치한다.
   평소엔 숨겨져 있는데(스티비), 줄을 정의해 두면 빈 줄 앞의 간격만큼
   띠 아래가 벌어진다. 자동 배치면 숨겨져 있을 때 줄 자체가 생기지 않는다. */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result {
  grid-column: 1;
}

/* ----- 입력칸: 테두리 없이 밑줄만 ----- */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set {
  padding-bottom: 0;
  overflow: visible;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_input {
  display: block;
  width: 100%;
  height: var(--ff-newsletter-h);
  padding: 0;
  border: 0;
  border-bottom: var(--ff-newsletter-lineW) solid var(--ff-newsletter-fg);
  border-radius: 0;
  background: transparent;
  color: var(--ff-newsletter-fg);
  font-size: 1.125rem !important; /* 위 [!important] 참고 */
  font-weight: var(--fw-semibold);
  line-height: 1 !important;
}
@media (max-width: 1024px) {
  .ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_input {
    font-size: 1rem !important;
  }
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_input::placeholder {
  color: var(--ff-newsletter-fg);
  opacity: 1;
}

/* 포커스는 밑줄을 굵게 — 박스 외곽선 대신 이 디자인의 선을 그대로 쓴다 */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_input:focus {
  outline: 0;
  box-shadow: 0 var(--ff-newsletter-lineW) 0 var(--ff-newsletter-fg);
}

/* 브라우저 자동완성이 칠하는 노란/파란 바탕을 띠 색으로 덮는다 */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_input:-webkit-autofill {
  -webkit-text-fill-color: var(--ff-newsletter-fg);
  box-shadow: inset 0 0 0 100px var(--ff-newsletter-bg);
  caret-color: var(--ff-newsletter-fg);
}

/* ----- 동의 ----- */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy {
  padding: 0;
  font-size: 0.8125rem;
  font-weight: var(--fw-medium);
  line-height: 1.5;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label {
  cursor: pointer;
}

/* 흰 테두리 네모. 체크하면 흰 면에 보라 체크.
   input 자체는 그대로 두고 모양만 바꾼다(스티비가 .checked 를 읽는다). */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label input {
  -webkit-appearance: none;
  appearance: none;
  display: inline-block;
  width: 14px;
  height: 14px;
  margin: 0 5px 0 0;
  border: var(--ff-newsletter-lineW) solid var(--ff-newsletter-fg);
  border-radius: 0;
  background: transparent center/10px 10px no-repeat;
  vertical-align: -1px;
  cursor: pointer;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label input:checked {
  background-color: var(--ff-newsletter-fg);
  /* 체크 표시 색은 강조 보라(#6f14ff) — data URI 안에서는 CSS 변수를 쓸 수 없다 */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2 6.2 4.8 9 10 3' fill='none' stroke='%236f14ff' stroke-width='2'/%3E%3C/svg%3E");
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label input:focus-visible {
  outline: 2px solid var(--ff-newsletter-fg);
  outline-offset: 2px;
}

/* 약관 이름 — 누르면 모달이 열린다. 눌러서 전문을 볼 수 있다는 걸 알리려고
   밑줄을 상시 둔다. 한글 받침이 베이스라인까지 내려와 밑줄과 붙어 보이므로
   offset 으로 띄운다(아래 주석 참고).
   (라벨 안의 버튼이라 눌러도 체크박스는 토글되지 않는다) */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label button,
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label button:focus {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  /* 스티비 기본 CSS 가 동의 영역의 모든 요소에 vertical-align: middle 을 건다.
     약관 이름은 버튼이지만 뒤에 이어지는 "에 동의합니다." 는 그냥 글자라
     베이스라인에 앉는다. 버튼만 가운데 정렬되면 두 글자가 어긋나 보이므로
     (아래로 약 3px) 베이스라인 정렬로 되돌린다. 체크박스는 그대로 둔다. */
  vertical-align: baseline;
  font-size: inherit !important; /* 위 [!important] 참고 */
  font-weight: inherit;
  line-height: inherit !important;
  /* 밑줄을 글자에서 띄운다. em 이라 글자 크기가 바뀌어도 간격 비율이 같다.
     두께는 글꼴이 주는 값 대신 1px 로 고정해 얇게 유지한다. */
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.3em;
  cursor: pointer;
}

/* 이미 밑줄이 있으므로, 올렸을 때는 두께로 알린다 */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label button:hover,
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_policy label button:focus-visible {
  background: none;
  color: inherit;
  text-decoration-thickness: 2px;
}

/* ----- 구독하기: 흰 버튼 ----- */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button {
  display: inline-block;
  width: auto;
  height: auto;
  padding: 6px 15px;
  border: 0;
  border-radius: 5px;
  background: var(--ff-newsletter-fg);
  color: var(--ff-newsletter-bg);
  font-size: 1rem !important; /* 위 [!important] 참고 */
  font-weight: var(--fw-bold);
  line-height: 1.3 !important;
  white-space: nowrap;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button:hover,
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button:focus-visible {
  background: var(--ff-newsletter-fg);
  color: var(--ff-newsletter-bg);
  opacity: 0.85;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button:focus-visible {
  outline: 2px solid var(--ff-newsletter-fg);
  outline-offset: 3px;
}

/* 스티비는 전송 중 disabled 클래스를, 허니팟은 disabled 속성을 건다 */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button.disabled,
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ----- 에러 · 결과 메시지 (보라 위에서 읽히게) ----- */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_msg_error {
  padding: 6px 0 0;
  color: var(--ff-newsletter-error);
  font-size: 0.85rem;
  font-weight: var(--fw-semibold);
  line-height: 1.4;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result {
  padding: 10px 14px;
  font-size: 0.95rem;
  font-weight: var(--fw-semibold);
  line-height: 1.5;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result p {
  margin: 0;
  font-size: inherit;
  line-height: inherit;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result.success {
  background: rgba(255, 255, 255, 0.14);
  color: var(--ff-newsletter-fg);
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result.fail {
  background: rgba(0, 0, 0, 0.18);
  color: var(--ff-newsletter-error);
}

/* 스티비 기본 CSS 가 p 에 색을 다시 칠하므로 한 번 더 */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result.success p {
  color: var(--ff-newsletter-fg);
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_result.fail p {
  color: var(--ff-newsletter-error);
}

/* ----- 약관 모달 (흰 상자 — 위 [약관 모달] 참고) ----- */
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_body {
  border: 0;
  border-radius: 0;
  background: var(--color-white);
  color: var(--color-black);
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_title {
  margin: 0;
  padding: 28px 28px 16px;
  color: var(--ff-newsletter-bg);
  font-family: var(--font-title);
  font-size: 1.25rem;
  font-weight: var(--fw-bold);
  line-height: 1.3;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_text {
  margin: 0 28px;
  color: var(--color-black);
  font-size: 0.9375rem;
  line-height: 1.7;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_btn {
  padding: 24px 28px 28px;
  text-align: right;
}

.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_btn button,
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_btn button:hover,
.ff-newsletter.apply-newsletter #stb_subscribe .stb_form_modal_btn button:focus {
  width: auto;
  height: auto;
  padding: 7px 14px;
  border: 0;
  border-radius: 5px;
  background: var(--ff-newsletter-bg);
  color: var(--color-white);
  font-size: 1rem;
  font-weight: var(--fw-bold);
  line-height: 1.2;
  cursor: pointer;
}

/* ----- 허니팟 -----
   화면 밖으로 치운다. display:none 은 쓰지 않는다 — 그런 칸은 봇이
   알아보고 건너뛰기 때문이다. aria-hidden · tabindex="-1" 로 스크린리더와
   탭 이동에서도 빠져 있다. */
.ff-newsletter.apply-newsletter #stb_subscribe .ff-newsletter__trap {
  position: absolute;
  top: 0;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* ----- 좁은 화면: 제목 위, 폼 아래 ----- */
/* ----- 좁은 화면 -----
   제목 · 안내 문장이 위, 폼이 아래로 한 칸씩 쌓인다. 데스크톱보다 촘촘하고,
   구독 버튼은 폭을 꽉 채운다(손가락으로 누르는 화면이라 과녁을 크게 둔다). */
@media (max-width: 768px) {
  :root {
    --ff-newsletter-padTop: 16px;
    --ff-newsletter-padBottom: 14px;
    --ff-newsletter-h: 34px;
  }
  .ff-newsletter {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 25px;
    margin-top: 40px;
  }
  /* 데스크톱에서 제목 위에 둔 여백은 2칸 배치에서 폼과 높이를 맞추기 위한
     것이라 여기서는 필요 없다. */
  .ff-newsletter__title {
    margin-bottom: 5px;
    padding-top: 0;
  }
  .ff-newsletter.apply-newsletter #stb_subscribe .stb_policy_wrap {
    gap: 2px;
  }
  .ff-newsletter.apply-newsletter #stb_subscribe .stb_form_set_submit {
    padding-top: 8px;
  }
  .ff-newsletter.apply-newsletter #stb_subscribe .stb_form_submit_button {
    width: 100%;
    padding: 7px 15px;
    font-size: 0.8125rem !important;
  }
}
/* ----- Newsletter End ----- */
/* ==================================================================
   Archive Pages  (ARCHIVE · SIFF PLUS 섹션 — GP Loop Template 엘리먼트)
   ------------------------------------------------------------------
   섹션 화면은 다른 페이지와 테마가 다르다. 회색 배경 + 보라 바 + 왼쪽 세로 라벨.
   엘리먼트 구성은 bin/seed-archive-elements.php, 목록 마크업은
   inc/archive-views.php, 하위 탭·라벨·제목은 inc/sections.php.

   [테마] body.ff-section (섹션 안의 모든 화면, 단일 글 포함)
     배경을 회색으로 바꾸고 헤더 배경도 같이 맞춘다. 헤더는 흰 면을 깔고 있어서
     따로 덮어야 한다(_festival-header.scss).

   [구조]
     .ff-archive-page
       ├ .ff-subnav                     ← 보라 바 (화면 폭 전체)
       │   ├ .ff-subnav__list           ← 하위 탭
       │   ├ .ff-subnav__list--sub      ← 제작·배급처럼 하위가 있으면 한 줄 더
       │   └ .ff-subnav__list--years    ← 연도 필터(ALL · 2026 …). 같은 바 안
       └ .ff-archive-page__body         ← 2칸: 세로 라벨 | 본문
           ├ .ff-section-label          ← ARCHIVE · SIFF PLUS. 아래→위로 읽힘
           └ .ff-archive-page__main
               ├ .ff-archive__title     ← h1 (역대영화제, 제작지원 …)
               ├ .ff-archive__subtitle / __intro / __heading
               ├ .ff-rowtable           ← 여러 칸 표 (연혁)
               └ .ff-archive            ← 카드/링크 목록 · 페이지 번호

   [카드 이미지] poster · download 는 표지·포스터 비율이 제각각이라 자르지 않는다
   (contain, 아래 정렬). photo · still 은 칸을 꽉 채운다(cover).
   tile(SIFF PLUS)은 보라 타일 위에 이미지를 원래 비율대로 얹고 글자는 흰색이다.
   이미지 높이가 제각각이라 카드 높이도 제각각 — 윗줄에 맞춰 세운다(align-items: start).

   [조절]
     섹션 배경·선    --ff-section-bg / --ff-section-line
     강조색          --ff-archive-color
     세로 라벨       --ff-section-labelSize / --ff-section-labelGap
     표 칸 너비      --ff-rowtable-cols
     카드 단 수      --ff-cards-cols (목록마다 아래에서 덮어쓴다)
================================================================== */
:root {
  /* 페이지 번호 — 칸 크기 · 사이 · 모서리 · 글자 크기 · 색(테두리와 글자, 지금 쪽은 이 색으로 채운다) · 테두리 두께 */
  --ff-pager-size: 28px;
  --ff-pager-gap: 5px;
  --ff-pager-radius: 4px;
  --ff-pager-fontSize: 14px;
  --ff-pager-color: var(--ff-archive-color);
  --ff-pager-lineW: 1.5px;
  /* 연도 필터 접기(좁은 화면) — "+" 줄 높이 · 접고 펼치는 시간 */
  /* 하위 탭 · 연도 태그(좁은 화면) — 글자 크기 · 모서리 · 태그 사이 */
  --ff-subnav-tagSize: 13px;
  --ff-subnav-tagRadius: 4px;
  --ff-subnav-tagGap: 6px;
  --ff-subnav-moreH: 30px;
  --ff-subnav-foldSpeed: 0.35s;
  --ff-section-bg: #e8e8e8;
  --ff-section-line: #606060;
  --ff-section-labelSize: clamp(48px, 4vw, 72px);
  --ff-section-labelGap: clamp(30px, 4.4vw, 80px);
  /* 세로 라벨 위 "+" 표시 — 선 두 개. 크기는 라벨 글자에 맞춘다.
     기준은 font-size 가 아니라 대문자 높이다(kigsans 의 대문자는 글자 크기의
     0.8). 그래야 "+" 가 옆 글자와 같은 크기로 보인다. 굵기는 글자 획과
     비슷하게, 아래 여백은 크기에 비례해서 정한다. */
  --ff-section-plusSize: calc(var(--ff-section-labelSize) * 0.8);
  --ff-section-plusW: calc(var(--ff-section-plusSize) * 0.15);
  --ff-section-plusGap: calc(var(--ff-section-plusSize) * 0.25);
  /* 세로 라벨·SIFF PLUS 포스터가 헤더 아래에서 멈추는 자리(헤더 아랫선에서
     띄울 만큼). 둘이 같은 높이에 서도록 한 값을 함께 쓴다. */
  --ff-section-stickyGap: 20px;
  /* 하위 탭 바 — 줄 위아래 여백과 연도 필터 줄(거르기)의 배경 */
  --ff-subnav-padY: 13px;
  --ff-subnav-filterBg: var(--color-black);
  --ff-archive-color: var(--ep-menu-color);
  --ff-archive-gapY: 40px;
  /* 본문과 푸터 사이 */
  --ff-section-footerGap: 120px;
  --ff-rowtable-cols: 8em 16.5em 16.5em minmax(0, 1fr);
  --ff-rowtable-padY: 10px;
  --ff-cards-cols: 4;
  --ff-cards-gapX: 10px;
  --ff-cards-gapY: 36px;
  --ff-cards-radius: 13px;
  --ff-cards-posterRatio: 5 / 7;
  --ff-cards-photoRatio: 3 / 2;
  --ff-cards-stillRatio: 5 / 3;
  /* 이미지가 없을 때의 면 */
  --ff-cards-surface: #d9d9d9;
}

/* ----- 테마: 회색 배경 ----- */
body.ff-section {
  background-color: var(--ff-section-bg);
}

body.ff-section #pc-header,
body.ff-section .site-header {
  background-color: var(--ff-section-bg);
}

/* ----- 페이지 뼈대 ----- */
/* 푸터와의 간격. margin 으로 주면 GeneratePress 의
   ".separate-containers .site-main > :last-child { margin-bottom: 0 }" 에
   눌려 사라진다(특이도가 더 높다). padding 은 그 규칙과 겹치지 않는다.
   섹션 배경은 body 가 칠하므로 padding 이 늘어도 빈 면으로만 보인다. */
.ff-archive-page {
  padding-bottom: var(--ff-section-footerGap);
}

.ff-archive-page__body {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--ff-section-labelGap);
  margin-top: 30px;
}

/* 섹션 본문의 h2 — 전역 제목 줄간격(1.1)은 두 줄이 되면 글줄이 붙어 보인다 */
.ff-archive-page__body h2 {
  line-height: 1.5;
}

.ff-archive-page__main {
  min-width: 0;
}

/* ----- 보라 바 (하위 탭 · 연도 필터) -----
   헤더 바로 아래에 멈춘다. 멈추는 높이는 "지금 보이는 헤더의 아랫선"
   (--ff-headerBottom, script.js 가 잰다)이다. PC 헤더는 스크롤에 따라 타이틀이
   접히며 높이가 변하고, 모바일에서는 PC 헤더 대신 모바일 헤더(.mo-header__bar)가
   화면 맨 위에 붙는다. PC 헤더 높이만 재던 때에는 모바일에서 그 값이 0 이라
   바가 모바일 헤더 뒤로 들어갔다. 띠배너 높이도 이 값에 들어 있다.

   [-1px] 화면 배율(devicePixelRatio)이 1이 아니면 헤더 아래 선과 바 윗선의 반올림이
   어긋나 1px 틈이 비친다. 1px 겹쳐 두면 어느 배율에서도 틈이 없다. 겹친 부분은
   헤더(z-index 999)가 위에 있고 불투명해서 가려진다. 바는 그 아래(998)라
   본문만 바 밑으로 지나간다. */
.ff-archive-page > .ff-subnav {
  position: sticky;
  top: calc(var(--ff-headerBottom, calc(var(--ep-topbar-h, 0px) + var(--ep-headerH, 0px))) - 1px);
  z-index: 998;
  margin-right: calc(var(--ep-margin) * -1);
  margin-left: calc(var(--ep-margin) * -1);
  /* 좌우 여백은 바가 아니라 줄(.ff-subnav__list)이 가진다. 줄이 옆으로
     흐를 때 항목이 화면 끝까지 이어지게 하기 위해서다.
     위아래 여백도 줄이 가진다 — 연도 필터 줄만 검은 면으로 깔리는데,
     바에 여백이 있으면 그 면 위아래로 보라가 비친다. */
  padding: 0;
  background-color: var(--ff-archive-color);
}

/* 하위 탭 — 줄바꿈하지 않고 옆으로 흐른다. 접으면 화면이 좁을수록 바가
   두세 줄로 두꺼워져 본문을 밀어낸다. 항목이 많으면 옆으로 밀어서 본다.
   (헤더 밑 서브메뉴 띠 .mo-subnav 와 같은 방식 — styles/_mobile-header.scss)
   현재 항목이 화면 밖이면 script.js 가 보이는 자리로 밀어둔다. */
.ff-subnav__list {
  display: flex;
  flex-wrap: nowrap;
  gap: 0.3em var(--ep-menu-gap);
  margin: 0;
  padding: 8px var(--ep-margin);
  list-style: none;
  overflow-x: auto;
  /* 줄 안에서만 밀리고, 끝에서 페이지가 따라 움직이지 않게 */
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.ff-subnav__list::-webkit-scrollbar {
  display: none;
}

.ff-subnav__item {
  flex: 0 0 auto;
}

/* 하위 탭 줄은 위 탭과 한 덩어리다 — 사이 여백만 지운다 */
.ff-subnav__list--sub {
  padding-top: 0;
}

/* 연도 필터 — 성격이 다르다. 위 탭은 "어디로 갈지"를 고르고 이 줄은 "지금
   목록을 어떻게 거를지"를 고른다. 그래서 검은 면에 흰 글자로 깔아 보라 탭과
   눈으로 갈리게 한다. 바가 화면 끝까지 닿아 있어 이 면도 그대로 끝까지 간다.
   서체는 바 전체가 본문 서체(kigsans) 하나다 — 숫자만 디스플레이 서체로
   뽑지 않는다. 해가 쌓이면 한 줄을 넘기므로 여기서만 접어서 다음 줄로
   내린다 — 위 탭과 달리 연도는 끝까지 한눈에 보이는 편이 고르기 쉽다. */
.ff-subnav__list--years {
  flex-wrap: wrap;
  overflow-x: visible;
  gap: 0.2em 0.8em;
  background-color: var(--ff-subnav-filterBg);
  color: var(--color-white);
}

/* 연도 줄 아래의 얇은 "+" 줄 — 좁은 화면에서만 쓴다(아래 반응형 블록).
   줄 전체가 버튼이다. "+" 는 선 두 개로 그리고, 펼치면 45° 돌아 "×" 가 된다. */
.ff-subnav__more {
  display: none;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: var(--ff-subnav-moreH);
  padding: 0;
  border: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 0;
  background-color: var(--ff-subnav-filterBg);
  color: var(--color-white);
  cursor: pointer;
}

/* GP 기본 button 규칙(회색 배경)이 hover·focus 에서 되살아나므로 함께 잡는다 */
.ff-subnav__more:hover,
.ff-subnav__more:focus-visible {
  background-color: var(--ff-subnav-filterBg);
  color: var(--color-white);
}

.ff-subnav__more-icon {
  display: block;
  width: 11px;
  height: 11px;
  background-image: linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 1.5px, 1.5px 100%;
  transition: transform var(--ff-subnav-foldSpeed) ease;
}

.ff-subnav__years.is-open .ff-subnav__more-icon {
  transform: rotate(45deg);
}

@media (prefers-reduced-motion: reduce) {
  .ff-subnav__years .ff-subnav__list--years,
  .ff-subnav__years .ff-subnav__item,
  .ff-subnav__more-icon {
    transition: none !important;
  }
}
.ff-subnav__link {
  display: inline-block;
  white-space: nowrap;
  font-size: 1rem;
  font-weight: var(--ep-menu-weight);
  color: var(--color-white);
  opacity: 0.4;
  transition: opacity var(--ep-menu-speed) ease;
}

.ff-subnav__list--sub .ff-subnav__link {
  font-size: 1rem;
}

/* 오픈 전 잠금 탭 — 주소가 없어 눌리지도, 탭 이동으로 닿지도 않는다
   (inc/sections.php). 보이기는 하되 "지금은 못 들어가는 곳"으로 읽히게
   주메뉴의 잠금 항목과 같은 투명도를 쓴다(--ep-menu-disabled). */
.ff-subnav__item.is-locked > .ff-subnav__link {
  opacity: var(--ep-menu-disabled);
  cursor: default;
  pointer-events: none;
}

.ff-subnav__item.is-current > .ff-subnav__link,
.ff-subnav__link:focus-visible {
  opacity: 1;
}

/* 글자색은 어떤 상태에서도 그대로다. 테마 기본 링크 규칙(a:hover · a:focus ·
   a:active)이 글자를 어둡게 바꾸는데, 이 바에서 상태를 말하는 것은 색이 아니라
   투명도다 — 올리면 또렷해질 뿐 색은 흰색 그대로여야 한다. */
.ff-subnav__link:hover,
.ff-subnav__link:focus,
.ff-subnav__link:active {
  color: var(--color-white);
}

/* 마우스를 올렸을 때 또렷해지는 것은 마우스가 있는 기기에서만 한다.
   손가락으로 누르는 화면에는 "올려둔 상태"가 없어서, 브라우저가 마지막으로
   누른 자리에 hover 를 남겨 둔다 — 누른 탭이 다른 곳을 누를 때까지 켜진 채로
   남아 현재 탭이 둘인 것처럼 보인다. */
@media (hover: hover) {
  .ff-subnav__link:hover {
    opacity: 1;
  }
}
/* 손가락으로 누르는 화면 — 브라우저의 누름 표시(회색 번쩍임)가 탭 · 연도 ·
   "+" 줄에 남지 않게 한다. */
@media (hover: none) {
  .ff-subnav__link,
  .ff-subnav__more {
    -webkit-tap-highlight-color: transparent;
  }
}
/* ----- 세로 라벨 -----
   본문이 지나가는 동안 헤더 밑에 붙어 있다가, 본문이 끝나면 같이 밀려
   올라간다. 멈추는 높이는 SIFF PLUS 상세의 포스터와 같은 값이다
   (styles/_siff-plus-single.scss) — 둘이 한 화면에 있을 때 윗선이 어긋나지
   않게. 헤더 높이와 보라 하위 탭 바 높이는 화면마다 달라지므로 스크립트가
   잰 값을 쓴다(--ff-headerBottom — script.js · --ff-sectionNavH — assets/js/section-sticky.js).
   목록 화면에는 바가 있고 상세에는 없는데, 없으면 0 이라 같은 식으로 둔다.
   align-self: start 가 함께 있어야 한다. 그리드 칸은 기본이 stretch 라
   라벨 상자가 본문 높이만큼 늘어나면 sticky 가 움직일 자리가 없다. */
.ff-section-label {
  position: sticky;
  top: calc(var(--ff-headerBottom, calc(var(--ep-topbar-h, 0px) + var(--ep-headerH, 0px))) + var(--ff-sectionNavH, 0px) + var(--ff-section-stickyGap));
  align-self: start;
}

/* SIFF PLUS 는 라벨 위에 "+" 가 붙는다. 선 두 개를 그라디언트로 겹쳐 그린다
   (글리프가 아니라 선이라 두께를 --ff-section-plusW 로 정확히 맞춘다). */
.ff-section--siff-plus .ff-section-label::before {
  content: "";
  display: block;
  width: var(--ff-section-plusSize);
  height: var(--ff-section-plusSize);
  /* em 을 쓰면 라벨 글자 크기가 아니라 부모의 기본 글자 크기를 기준으로 잡혀
     간격이 의도보다 훨씬 좁아진다(::before 는 글자 크기를 물려받지 않는다).
     가로는 가운데(auto)가 아니라 왼쪽에 붙인다. 세로쓰기 글자의 잉크가
     줄상자 왼쪽에서 시작하므로, 그대로 두면 "+" 의 왼쪽 선과 글자의 왼쪽
     선이 한 줄로 선다(auto 로 두면 "+" 만 오른쪽으로 밀린다). */
  margin: 0 0 var(--ff-section-plusGap);
  background-image: linear-gradient(var(--ff-archive-color), var(--ff-archive-color)), linear-gradient(var(--ff-archive-color), var(--ff-archive-color));
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% var(--ff-section-plusW), var(--ff-section-plusW) 100%;
}

.ff-section-label__text {
  display: block;
  /* 세로쓰기 + 180° 회전 = 글자가 옆으로 누운 채 아래에서 위로 읽힌다.
     sideways 를 함께 주는 이유: 한글을 섞으면 세로쓰기에서 똑바로 서서(upright)
     회전 때문에 거꾸로 뒤집힌다. 눕혀두면 어떤 글자를 넣어도 방향이 같다. */
  writing-mode: vertical-rl;
  text-orientation: sideways;
  transform: rotate(180deg);
  color: var(--ff-archive-color);
  font-size: var(--ff-section-labelSize);
  font-weight: var(--fw-bold);
  line-height: 1;
  white-space: nowrap;
}

/* ----- 제목 · 소개 ----- */
.ff-archive__title {
  margin: 0 0 30px;
  color: var(--ff-archive-color);
  line-height: 1.1;
  /* h1 이 style.scss 에서 받는 위 패딩을 뺀다. 그대로 두면 제목만 그만큼 내려가
     왼쪽 세로 라벨(.ff-section-label)과 윗선이 어긋난다 — 둘은 같은 줄의 두 칸이다. */
  padding-top: 0;
}

.ff-archive__intro {
  margin: 0;
}

.ff-archive__intro > :last-child {
  margin-bottom: 0;
}

.ff-archive__heading {
  margin: 20px 0 16px;
  color: var(--ff-archive-color);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: var(--fw-bold);
}

/* 화면 제목 바로 뒤에 소제목이 오는 경우(SIFF PLUS 하위 페이지들)에는 둘 사이를
   좁힌다. 같은 보라 글자 두 줄이 이어지는 자리라 30px 은 떨어져 보인다.
   소제목이 .ff-archive__head 로 한 겹 싸인 쪽(인디피크닉)과 바로 놓인 쪽
   (출판 · 베스트컬렉션 등)이 섞여 있어 둘 다 건다.
   목록·필터가 바로 오는 페이지(역대영화제 등)는 그대로 둔다. */
.ff-archive__title:has(+ .ff-archive > :is(.ff-archive__head, .ff-archive__heading):first-child) {
  margin-bottom: 14px;
}

/* 제목 바로 아래(부제 자리)에 오는 소제목은 위 여백을 겹치지 않게 한다.
   목록 블록의 첫 자식으로 바로 놓인 경우(출판 · 베스트컬렉션 등)도 같다 —
   그렇지 않으면 제목 여백 위에 --ff-archive-gapY(40px)가 한 번 더 얹힌다. */
.ff-archive__title + .ff-archive__heading,
.ff-archive__head > .ff-archive__heading:first-child,
.ff-archive > .ff-archive__heading:first-child {
  margin-top: 0;
}

.ff-archive__heading + .ff-archive__intro {
  margin-top: -8px;
}

.ff-archive__empty {
  padding: 60px 0;
  color: #8c8c8c;
  text-align: center;
}

/* ----- 여러 칸 표 (연혁) ----- */
.ff-rowtable {
  border-top: 1px solid var(--ff-section-line);
}

.ff-rowtable__row {
  display: grid;
  grid-template-columns: var(--ff-rowtable-cols);
  padding: var(--ff-rowtable-padY) 0;
  border-bottom: 1px solid var(--ff-section-line);
}

.ff-rowtable__cell {
  min-width: 0;
  padding-right: 20px;
}

.ff-rowtable__cell > p {
  margin: 0;
}

/* ----- 목록 영역 ----- */
.ff-archive {
  margin-top: var(--ff-archive-gapY);
}

/* 제목 바로 아래 오는 목록(역대상영작·행사사진·SIFF PLUS)은 위 여백을 줄인다. */
.ff-archive__title + .ff-archive,
.ff-archive__heading + .ff-archive {
  margin-top: 0;
}

.ff-archive__head {
  margin-bottom: var(--ff-archive-gapY);
}
@media (max-width: 780px) {
  .ff-archive__head {
    margin-bottom: 20px;
  }
}

/* ----- 카드 ----- */
.ff-cards {
  display: grid;
  grid-template-columns: repeat(var(--ff-cards-cols), minmax(0, 1fr));
  column-gap: var(--ff-cards-gapX);
  row-gap: var(--ff-cards-gapY);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media screen and (max-width: 1024px) {
  .ff-cards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
@media (max-width: 780px) {
  .ff-cards {
    column-gap: 10px;
    row-gap: 15px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.ff-archive--festival .ff-cards,
.ff-cards--photo,
.ff-cards--still {
  --ff-cards-cols: 4;
}

/* SIFF PLUS — 보라 타일. 이미지 높이가 달라 카드 높이도 다르므로 윗변을 맞춘다. */
.ff-cards--tile {
  align-items: start;
}

.ff-cards--tile .ff-card__link {
  background-color: var(--ff-archive-color);
  color: var(--color-white);
}

.ff-cards--tile .ff-card__thumb {
  display: block;
  aspect-ratio: auto;
}

.ff-cards--tile .ff-card__img {
  width: 100%;
  border-radius: 0;
}

.ff-cards--tile .ff-card__thumb.is-empty {
  aspect-ratio: var(--ff-cards-posterRatio);
  border-radius: 0;
  background-color: rgba(255, 255, 255, 0.15);
}

.ff-cards--tile .ff-card__body {
  gap: 2px;
  margin-top: 0;
  padding: 12px;
}

.ff-cards--tile .ff-card__meta {
  color: inherit;
}

/* 제목 아래 두 줄(카테고리 · 사업 연도)은 같은 급의 부가 정보다 — 크기와 굵기를
   하나로 맞춘다. 따로 두면 카테고리만 작고 굵어 서로 다른 종류로 읽힌다. */
.ff-cards--tile .ff-card__badge,
.ff-cards--tile .ff-card__meta {
  font-size: 15px;
  font-weight: var(--fw-medium);
}

/* SIFF PLUS 카드 제목 — 넓은 화면에서 공통 크기(1.5rem)는 타일 폭에 비해 커서
   긴 사업명이 서너 줄로 접힌다. 한 단계 줄인다. 좁은 화면의 크기는 아래
   반응형 블록이 따로 정하므로 넓은 화면에서만 건다. */
@media (min-width: 1024px) {
  /* 매거진(다운로드 카드)도 같은 SIFF PLUS 목록이라 제목 크기를 맞춘다 */
  .ff-cards--tile .ff-card__title,
  .ff-cards--download .ff-card__title {
    font-size: 1.2rem;
  }
}
.ff-card {
  margin: 0;
}

.ff-card__link {
  display: block;
  color: var(--ff-archive-color);
}

.ff-card__thumb {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  aspect-ratio: var(--ff-cards-posterRatio);
  overflow: hidden;
}

.ff-card__thumb.is-empty {
  border-radius: var(--ff-cards-radius);
  background-color: var(--ff-cards-surface);
}

.ff-card__img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: var(--ff-cards-radius);
  transition: transform 0.4s ease;
}

/* 사진·스틸은 칸을 꽉 채운다 */
.ff-cards--photo .ff-card__thumb,
.ff-cards--still .ff-card__thumb {
  aspect-ratio: var(--ff-cards-photoRatio);
  border-radius: var(--ff-cards-radius);
}

.ff-cards--still .ff-card__thumb {
  aspect-ratio: var(--ff-cards-stillRatio);
}

.ff-cards--photo .ff-card__img,
.ff-cards--still .ff-card__img {
  width: 100%;
  height: 100%;
  border-radius: 0;
  object-fit: cover;
}

/* 마우스를 올렸을 때의 반응은 마우스가 있는 기기에서만 한다. 손가락으로 누르는
   화면에는 "올려둔 상태"가 없어 마지막으로 누른 자리에 hover 가 남는다. */
@media (hover: hover) {
  .ff-card__link:hover .ff-card__img {
    transform: scale(1.02);
  }
}
.ff-card__link:focus-visible .ff-card__img {
  transform: scale(1.02);
}

.ff-card__body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 8px;
}

.ff-card__badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.5em;
}

.ff-card__badge {
  font-size: 0.875rem;
  font-weight: var(--fw-semibold);
}

.ff-card__title {
  font-size: 1.5rem;
  font-weight: var(--fw-bold);
  line-height: 1.3;
}
@media screen and (max-width: 1400px) {
  .ff-card__title {
    font-size: 1.125rem;
  }
}

/* 역대영화제 목록 — 썸네일을 카드 폭에 꽉 채운다.
   포스터는 해마다 비율이 달라서 기본 규칙(잘리지 않게 넣고 아래 정렬)대로 두면
   세로로 긴 해는 좌우에, 가로로 긴 해는 위아래에 빈자리가 생겨 줄이 들쭉날쭉해
   보인다. 이 목록에서는 칸을 꽉 채우고 넘치는 쪽만 잘라낸다. */
.ff-archive--festival .ff-card__thumb {
  align-items: stretch;
}

.ff-archive--festival .ff-card__img {
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
  object-position: center;
}

/* 역대영화제: 슬로건이 큰 글씨 */
.ff-archive--festival .ff-card__title {
  font-family: var(--font-title);
  font-size: var(--title-s);
  line-height: 1.2;
}

.ff-card__meta {
  font-size: 1rem;
}

.ff-archive--festival .ff-card__meta {
  font-size: 1rem;
}

.ff-card__action {
  font-size: 0.875rem;
  font-weight: var(--fw-semibold);
}

.ff-card__action::before {
  content: "↓ ";
}

/* ----- 링크 목록 (데일리) ----- */
.ff-linklist {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--ff-section-line);
}

.ff-linklist__item {
  border-bottom: 1px solid var(--ff-section-line);
}

.ff-linklist__link {
  display: grid;
  grid-template-columns: 8em minmax(0, 1fr) auto;
  gap: 20px;
  align-items: baseline;
  padding: 12px 0;
  color: inherit;
}

.ff-linklist__date,
.ff-linklist__icon {
  color: var(--ff-archive-color);
}

.ff-linklist__date {
  font-weight: var(--fw-semibold);
}

@media (hover: hover) {
  a.ff-linklist__link:hover .ff-linklist__title {
    text-decoration: underline;
  }
}
a.ff-linklist__link:focus-visible .ff-linklist__title {
  text-decoration: underline;
}

/* 쪽을 넘기는 동안(script.js 가 목록만 갈아 끼운다) — 지금 목록을 흐리게 해
   "바뀌는 중"임을 알리고, 그동안 다시 눌리지 않게 한다. */
.ff-archive {
  transition: opacity 0.2s ease;
}

.ff-archive.is-loading {
  opacity: 0.4;
  pointer-events: none;
}

/* 넘긴 뒤 초점을 목록으로 옮긴다 — 누를 수 있는 것이 아니라서 테두리는 긋지 않는다 */
.ff-archive:focus {
  outline: none;
}

/* ----- 페이지 번호 ----- */
.ff-pagination {
  margin-top: 60px;
}

.ff-pagination__list {
  display: flex;
  flex-wrap: wrap;
  /* 목록(카드 줄)의 가운데에 선다 */
  justify-content: center;
  gap: var(--ff-pager-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* 번호 하나 = 정방형 칸. 한 자리든 세 자리든 칸 크기가 같아 줄이 고르다
   (세 자리가 넘어 칸보다 길어지면 옆으로만 늘어난다 — min-width).
   모양은 좁은 화면의 하위 탭 · 연도 태그와 같은 방식이다: 고르지 않은 칸은
   테두리만, 지금 쪽만 채운다. 색은 섹션 강조색(보라) 하나다.
   숫자는 영문 디스플레이 서체(--font-title 은 국문 기준으로 크기를 맞춘 쪽). */
.ff-pagination .page-numbers {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--ff-pager-size);
  height: var(--ff-pager-size);
  padding: 0 4px;
  border: var(--ff-pager-lineW) solid var(--ff-pager-color);
  background-color: transparent;
  color: var(--ff-pager-color);
  font-family: var(--font-title);
  font-size: var(--ff-pager-fontSize);
  font-weight: var(--fw-bold);
  line-height: 1;
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* ----- 숫자를 칸의 세로 가운데에 -----
   숫자 서체(PP Formula Fit)는 줄 상자 안에서 글자가 위로 치우쳐 있다. 이 치우침을
   fonts/font.css 의 ascent-override · descent-override 로 바로잡아 두었는데,
   사파리(아이폰 포함)는 그 두 설정을 읽지 않는다 — 그래서 실제 기기에서 숫자가
   칸 위쪽으로 붙어 보인다.

   글꼴 메트릭에 기대지 않고 가운데를 잡는다: 줄 상자를 "대문자 높이 ~ 기준선"으로
   잘라내면(text-box) 내용 높이가 숫자의 잉크 높이(1cap)와 같아진다. 그 위아래에
   같은 패딩을 주면 어느 브라우저에서도 정확히 가운데다. flex 는 푼다 — 자르기는
   글줄을 직접 담는 블록에만 걸린다. */
@supports (text-box: trim-both cap alphabetic) {
  .ff-pagination .page-numbers {
    display: block;
    height: auto;
    padding-block: calc((var(--ff-pager-size) - 1cap) / 2 - var(--ff-pager-lineW));
    text-align: center;
    text-box: trim-both cap alphabetic;
  }
}
/* 자르기를 모르는 예전 아이폰 사파리 — 위 설정도, 글꼴의 메트릭 보정도 듣지 않는다.
   치우친 만큼(글자 크기의 약 0.11em)을 위 패딩으로 내려 준다. 가운데 정렬에서는
   패딩의 절반만큼 내려가므로 두 배를 준다. */
@supports (-webkit-touch-callout: none) and (not (text-box: trim-both cap alphabetic)) {
  .ff-pagination .page-numbers {
    padding-top: 0.22em;
  }
}
/* 테마 기본 링크 규칙(a:hover · a:focus · a:active)이 글자를 어둡게 바꾼다 —
   누르거나 올려도 글자색은 그대로 둔다. (아래 "채운 칸" 규칙보다 앞에 둬야
   그쪽의 흰 글자가 이긴다) */
.ff-pagination a.page-numbers:hover,
.ff-pagination a.page-numbers:focus,
.ff-pagination a.page-numbers:active {
  color: var(--ff-pager-color);
}

/* 지금 쪽은 채운 칸에 흰 글자 */
.ff-pagination .page-numbers.current {
  background-color: var(--ff-pager-color);
  color: var(--color-white);
}

/* 마우스가 있는 기기에서만 — 손가락으로 누르는 화면에서는 누른 칸에 hover 가 남는다 */
@media (hover: hover) {
  .ff-pagination a.page-numbers:hover {
    background-color: var(--ff-pager-color);
    color: var(--color-white);
  }
}
.ff-pagination a.page-numbers:focus-visible {
  background-color: var(--ff-pager-color);
  color: var(--color-white);
}

/* 줄임표(…)는 누르는 칸이 아니다 — 테두리도 면도 두지 않는다 */
.ff-pagination .page-numbers.dots {
  border-color: transparent;
  background: none;
}

/* ----- 반응형 ----- */
@media (max-width: 1024px) {
  :root {
    --ff-cards-cols: 3;
  }
  /* 모바일에서는 헤더 밑 서브메뉴 띠와 같은 크기로 맞춘다.
     일반 페이지는 .mo-subnav(메뉴의 하위 항목), 섹션 페이지는 이 바가
     같은 자리에 같은 역할로 붙기 때문이다(styles/_mobile-header.scss).
     하위 줄(제작·배급 등)은 PC 에서의 비율(0.95 / 1.2)을 그대로 유지한다. */
  .ff-subnav__link {
    font-size: var(--mo-subnav-size);
  }
  .ff-subnav__list--sub .ff-subnav__link {
    font-size: calc(var(--mo-subnav-size) * 0.79);
  }
  /* ----- 연도 필터 접기 -----
     해가 쌓이면 연도 줄이 서너 줄이 되고, 바가 헤더 밑에 붙어 있어 본문이
     보일 자리를 그만큼 가린다. 좁은 화면에서는 한 줄만 두고 아래 얇은 "+" 줄을
     누르면 전부 펼친다. 한 줄에 다 들어가면 버튼이 필요 없으므로 script.js 가
     넘칠 때만 is-collapsible 을 붙인다.

     연도들은 접혀 있어도 제자리(여러 줄)에 그대로 있고, 한 줄 높이만 보인다.
     그래서 여닫을 때 글자가 자리를 옮기지 않는다 — 높이가 변하는 동안 나머지
     줄(is-extra)이 같이 흐려지고 또렷해질 뿐이다.
     높이 두 값은 스크립트가 준다: 접힌 높이 --ff-years-lineH, 펼친 높이는
     list 의 max-height(인라인). */
  .ff-subnav__years.is-collapsible .ff-subnav__list--years {
    max-height: var(--ff-years-lineH, none);
    overflow: hidden;
    transition: max-height var(--ff-subnav-foldSpeed) ease;
  }
  .ff-subnav__years.is-collapsible .ff-subnav__item {
    transition: opacity var(--ff-subnav-foldSpeed) ease;
  }
  .ff-subnav__years.is-collapsible:not(.is-open) .ff-subnav__item.is-extra {
    opacity: 0;
  }
  .ff-subnav__years.is-collapsible .ff-subnav__more {
    display: flex;
  }
  /* ----- 하위 탭 · 연도 필터: 태그 모양 -----
     좁은 화면에서는 둘째 줄부터(제작·배급의 하위 탭, 연도 필터)를 작은 태그로
     만든다. 맨 윗줄 탭과 글자 크기 · 모양이 같으면 세 줄이 한 덩어리로 읽혀
     어느 줄이 무엇을 고르는지 갈리지 않는다. 투명도 대신 테두리 칸으로 세우고,
     지금 고른 것만 흰 칸으로 채운다. 채운 칸의 글자는 그 줄의 바탕색을 따른다 —
     하위 탭은 보라 면 위라 보라, 연도는 검은 면 위라 검정. */
  .ff-subnav__list--sub,
  .ff-subnav__list--years {
    gap: var(--ff-subnav-tagGap);
  }
  .ff-subnav__list--sub .ff-subnav__link,
  .ff-subnav__list--years .ff-subnav__link {
    padding: 4px 9px;
    border: 1px solid rgba(255, 255, 255, 0.4);
    border-radius: var(--ff-subnav-tagRadius);
    color: rgba(255, 255, 255, 0.75);
    font-size: var(--ff-subnav-tagSize);
    line-height: 1.2;
    opacity: 1;
  }
  .ff-subnav__list--sub .ff-subnav__item.is-current > .ff-subnav__link,
  .ff-subnav__list--years .ff-subnav__item.is-current > .ff-subnav__link {
    border-color: var(--color-white);
    background-color: var(--color-white);
    color: var(--color-black);
  }
  .ff-subnav__list--sub .ff-subnav__item.is-current > .ff-subnav__link {
    color: var(--ff-archive-color);
  }
  /* 세로 라벨(ARCHIVE · SIFF PLUS)은 좁은 화면에서 숨긴다 — 본문 폭을 한 칸
     차지하는데, 어느 섹션인지는 헤더의 버튼과 바로 위 탭이 이미 말해 준다.
     라벨이 빠지면 본문이 폭을 다 쓰도록 칸도 하나로 줄인다(그대로 두면 본문이
     라벨 자리였던 좁은 칸으로 들어간다). 상세 화면도 같은 뼈대라 함께 적용된다. */
  .ff-section-label {
    display: none;
  }
  .ff-archive-page__body {
    grid-template-columns: minmax(0, 1fr);
  }
  /* 화면 제목 — 모바일 헤더로 바뀌는 폭부터 다른 페이지의 h1 과 같은 크기
     (style.scss 의 h1 · 메인의 칸 제목이 모두 22px). */
  .ff-archive__title {
    margin-bottom: 20px;
    /* h1 이 style.scss 에서 받는 위 패딩(20px)을 뺀다. 바 아래 간격은
       .ff-archive-page__body 의 margin-top 하나가 맡는다 — 둘이 겹쳐 40px 였다. */
    padding-top: 0;
    font-size: 22px;
  }
  /* 보라 바(또는 상세의 제목 면) 아래에서 본문이 시작하는 높이 — 사이트 공통 */
  .ff-archive-page__body {
    margin-top: var(--ep-contentTop);
  }
  .ff-archive__title:has(+ .ff-archive > :is(.ff-archive__head, .ff-archive__heading):first-child) {
    margin-bottom: 10px;
  }
  /* 카드 글자 — 단 수가 줄어 카드가 좁아지므로 PC 크기(1.5rem)를 그대로 두면
     제목 한 줄에 서너 자밖에 못 들어간다. */
  .ff-card__title,
  .ff-archive--festival .ff-card__title {
    font-size: 16px;
  }
  /* 연도 | 명칭 한 줄, 주최·설명은 명칭 칸 아래로 */
  .ff-rowtable__row {
    grid-template-columns: 7em minmax(0, 1fr);
    row-gap: 4px;
  }
  .ff-rowtable__cell:nth-child(n+3) {
    grid-column: 2;
  }
}
@media (max-width: 780px) {
  :root {
    --ff-cards-cols: 2;
    --ff-cards-gapY: 28px;
    --ff-archive-gapY: 32px;
    --ff-section-footerGap: 64px;
    --ff-section-labelSize: 34px;
    --ff-section-labelGap: 16px;
  }
  .ff-archive--festival .ff-cards,
  .ff-cards--photo,
  .ff-cards--still {
    --ff-cards-cols: 2;
  }
  /* 두 단 카드 — 제목 아래 줄은 본문 크기로 (제목은 위 블록에서 16px) */
  .ff-card__meta,
  .ff-archive--festival .ff-card__meta {
    font-size: 12px;
    line-height: 1.4;
  }
  .ff-archive__heading {
    font-size: 16px;
  }
  .ff-rowtable__row {
    grid-template-columns: 5.5em minmax(0, 1fr);
  }
  .ff-linklist__link {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 4px 12px;
  }
  .ff-linklist__date {
    grid-column: 1/-1;
    font-size: 0.875rem;
  }
}
@media (max-width: 480px) {
  .ff-cards--photo,
  .ff-cards--still {
    --ff-cards-cols: 1;
  }
}
/* 좁은 화면 — 여러 칸 표(연혁)를 한 열로 쌓는다.
   위에서 두 칸(연도 | 나머지)으로 줄여 두었지만, 이 폭에서는 연도 칸만큼
   내용 칸이 좁아져 한 줄에 몇 자 들어가지 않는다. 정의형 표(_deflist.scss)가
   같은 폭에서 항목명을 내용 위로 올리는 것과 맞춘다. 맨 윗칸(연도)은 그 행의
   머리글 노릇을 하므로 굵게 둔다. */
@media (max-width: 768px) {
  .ff-rowtable__row {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 4px;
  }
  .ff-rowtable__cell,
  .ff-rowtable__cell:nth-child(n+3) {
    grid-column: auto;
    padding-right: 0;
  }
  /* 칸 안의 글은 p 로 한 겹 싸여 있고, p 는 style.scss 에서 굵기를 따로 받는다 */
  .ff-rowtable__cell:first-child,
  .ff-rowtable__cell:first-child > p {
    font-weight: var(--fw-bold);
  }
}
/* ----- Archive Pages End ----- */
/* ==================================================================
   SIFF PLUS Single  (템플릿: single-siff-plus.php · 마크업: inc/siff-plus-single.php)
   ------------------------------------------------------------------
   SIFF PLUS 상세. 섹션 목록 화면과 같은 뼈대(.ff-archive-page — 회색 배경 ·
   보라 바 · 왼쪽 세로 라벨, styles/_archive.scss)를 쓰고, 보라 바에는 하위 탭
   대신 이 글의 제목과 부가 정보가 들어간다.

   [구조]
     .ff-archive-page.ff-siff-plus (article)
       ├ .ff-siff-plus__head            ← 보라 바. 제목(h1) · 카테고리 · 사업 연도
       └ .ff-archive-page__body         ← 2칸: 세로 라벨 | 본문
           ├ .ff-section-label
           └ .ff-archive-page__main
               ├ .ff-siff-plus__body    ← 2칸: 포스터 | 내용
               │   ├ .ff-siff-plus__poster   포스터 + 버튼(__actions)
               │   └ .ff-siff-plus__main
               │       ├ .ff-siff-plus__table    라벨 | 내용 표 (dl)
               │       └ .ff-siff-plus__section  상영작 · 세부설명

   [표] 행은 정의형 표(styles/_deflist.scss)의 dl 부분을 그대로 쓴다
   (.ff-deflist__body / __row / __label / __value). 여기서는 토큰만 덮어쓴다 —
   포스터 옆이라 항목명 칸을 좁히고, 색은 섹션 강조색으로 맞춘다.

   [편집기 글] 표의 내용 칸과 상영작·세부설명은 편집기(wysiwyg)에서 온 HTML 이다.
   문단 · 굵은 글씨 · 링크 · 표 안의 표가 섞여 있어 .ff-siff-plus__rich 로 묶어 다룬다.

   [포스터] 원래 비율 그대로 둔다(세로형이 대부분이지만 정사각·가로형도 있다).
   넓은 화면에서는 헤더 아래에 붙어, 상영작이 긴 글에서도 버튼과 함께 보인다.

   [조절]
     포스터 칸 폭   --ff-siff-plus-posterW
     칸 사이        --ff-siff-plus-gapX
     절 사이        --ff-siff-plus-gapY
     보라 바 여백   --ff-siff-plus-headPadY
     제목 크기      --ff-siff-plus-titleSize
================================================================== */
:root {
  --ff-siff-plus-posterW: clamp(320px, 36vw, 560px);
  --ff-siff-plus-gapX: clamp(24px, 3vw, 48px);
  --ff-siff-plus-gapY: 40px;
  --ff-siff-plus-headPadY: 22px;
  --ff-siff-plus-titleSize: 28px;
  /* 포스터가 헤더 아래에 붙을 때 띄우는 간격 */
  /* 세로 라벨과 같은 자리에 선다 — 값은 _archive.scss 의 한 곳에서 정한다 */
  --ff-siff-plus-stickyGap: var(--ff-section-stickyGap, 20px);
}

.ff-siff-plus, .ff-festival {
  --ff-deflist-color: var(--ff-archive-color);
  --ff-deflist-labelW: 150px;
}

/* 항목명은 정의형 표 기본(medium)보다 굵게 — 상세 화면의 절 제목 · 부문 소제목과
   같은 굵기로 맞춘다. 역대영화제 상세도 이 규칙을 물려받는다. */
.ff-siff-plus .ff-deflist__label, .ff-festival .ff-deflist__label {
  font-weight: var(--fw-bold);
}

/* ----- 보라 바 -----
   목록 화면의 하위 탭 바(.ff-subnav)와 같은 자리 · 같은 면이다. 사이트 좌우
   마진을 넘어 화면 끝까지 채우고, 글은 같은 값만큼 안쪽으로 밀어 본문과 선을 맞춘다. */
.ff-siff-plus__head, .ff-gallery__head, .ff-festival__head {
  margin-right: calc(var(--ep-margin) * -1);
  margin-left: calc(var(--ep-margin) * -1);
  padding: 18px var(--ep-margin) 22px;
  background-color: var(--ff-archive-color);
  color: var(--color-white);
}

/* 제목은 길어서 타이틀 서체 대신 본문 서체로 간다(공지 상세와 같다).
   h1 이 _title.scss · style.scss 에서 받는 서체와 위 패딩을 되돌린다. */
.ff-siff-plus__title, .ff-gallery__title, .ff-festival__title {
  margin: 0;
  padding-top: 0;
  color: inherit;
  font-family: var(--font-body);
  font-size: var(--ff-siff-plus-titleSize);
  font-weight: var(--fw-semibold);
  line-height: 1.3;
  text-transform: none;
}

.ff-siff-plus__label, .ff-gallery__label, .ff-festival__label {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 10px;
  margin-top: 10px;
}

/* 카테고리 태그 — 공지 상세의 태그(.ff-notice__category)와 같은 모양.
   누르면 그 카테고리 목록으로 간다. */
.ff-siff-plus__category, .ff-gallery__category, .ff-festival__category {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 5px;
  background-color: var(--color-white);
  color: var(--ff-archive-color);
  font-size: 14px;
  font-weight: var(--fw-semibold);
  line-height: 1.2;
}
@media (max-width: 780px) {
  .ff-siff-plus__category, .ff-gallery__category, .ff-festival__category {
    color: var(--color-black);
  }
}

/* 글자색은 어떤 상태에서도 그대로다 — 테마 기본 링크 규칙(a:hover · a:focus ·
   a:active)이 글자를 어둡게 바꾸는 것을 막는다. */
.ff-siff-plus__category:hover, .ff-gallery__category:hover, .ff-festival__category:hover,
.ff-siff-plus__category:focus,
.ff-gallery__category:focus,
.ff-festival__category:focus,
.ff-siff-plus__category:active,
.ff-gallery__category:active,
.ff-festival__category:active {
  color: var(--ff-archive-color);
}

/* 마우스를 올렸을 때의 반응은 마우스가 있는 기기에서만 한다. 손가락으로 누르는
   화면에는 "올려둔 상태"가 없어 마지막으로 누른 자리에 hover 가 남는다. */
@media (hover: hover) {
  .ff-siff-plus__category:hover, .ff-gallery__category:hover, .ff-festival__category:hover {
    text-decoration: underline;
  }
}
.ff-siff-plus__category:focus-visible, .ff-gallery__category:focus-visible, .ff-festival__category:focus-visible {
  text-decoration: underline;
}

.ff-siff-plus__meta, .ff-gallery__meta, .ff-festival__meta {
  margin: 0 0 0 2px;
  color: inherit;
  font-size: inherit;
  font-weight: var(--fw-semibold);
  line-height: 1.4;
}

/* ----- 두 칸: 포스터 | 내용 ----- */
.ff-siff-plus__body, .ff-festival__body {
  display: grid;
  grid-template-columns: var(--ff-siff-plus-posterW) minmax(0, 1fr);
  column-gap: var(--ff-siff-plus-gapX);
  align-items: start;
}

/* 포스터도 버튼도 없는 글은 내용이 폭을 다 쓴다 */
.ff-siff-plus--text .ff-siff-plus__body, .ff-siff-plus--text .ff-festival__body, .ff-festival--text .ff-siff-plus__body, .ff-festival--text .ff-festival__body {
  grid-template-columns: minmax(0, 1fr);
}

.ff-siff-plus__poster, .ff-festival__poster {
  position: sticky;
  /* 세로 라벨과 같은 식 — 하위 탭 바가 있는 화면에서는 그 아래에 선다
     (--ff-sectionNavH, 없으면 0). styles/_archive.scss 참고. */
  top: calc(var(--ff-headerBottom, calc(var(--ep-topbar-h, 0px) + var(--ep-headerH, 0px))) + var(--ff-sectionNavH, 0px) + var(--ff-siff-plus-stickyGap));
}

.ff-siff-plus__poster img, .ff-festival__poster img {
  display: block;
  width: 100%;
  height: auto;
}

.ff-siff-plus__main, .ff-festival__main {
  min-width: 0;
}

/* ----- 버튼 (구매하기 등) ----- */
.ff-siff-plus__actions, .ff-festival__actions {
  display: grid;
  row-gap: 8px;
}

.ff-siff-plus__poster img + .ff-siff-plus__actions, .ff-siff-plus__poster img + .ff-festival__actions, .ff-festival__poster img + .ff-siff-plus__actions, .ff-festival__poster img + .ff-festival__actions {
  margin-top: 14px;
}

.ff-siff-plus__button, .ff-festival__button {
  display: block;
  padding: 12px 18px;
  border: 1.5px solid var(--ff-archive-color);
  background-color: var(--ff-archive-color);
  color: var(--color-white);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  text-align: center;
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* 테마 기본 링크 규칙이 누르거나 올렸을 때 글자를 어둡게 바꾼다 — 채운 버튼
   위에서는 글자가 묻히므로 흰색으로 붙들어 둔다. (아래 "뒤집기"보다 앞에 둔다) */
.ff-siff-plus__button:hover, .ff-festival__button:hover,
.ff-siff-plus__button:focus,
.ff-festival__button:focus,
.ff-siff-plus__button:active,
.ff-festival__button:active {
  color: var(--color-white);
}

/* 올리면 뒤집힌다(빈 칸 + 강조색 글자) — 마우스가 있는 기기에서만 */
@media (hover: hover) {
  .ff-siff-plus__button:hover, .ff-festival__button:hover {
    background-color: transparent;
    color: var(--ff-archive-color);
  }
}
.ff-siff-plus__button:focus-visible, .ff-festival__button:focus-visible {
  background-color: transparent;
  color: var(--ff-archive-color);
}

/* ----- 표 -----
   행 아래 선은 정의형 표가 긋는다. 여기서는 맨 윗선만 더한다. */
.ff-siff-plus__table, .ff-festival__table {
  border-top: var(--ff-deflist-lineW) solid var(--ff-deflist-color);
}

/* ----- 상영작 · 세부설명 ----- */
.ff-siff-plus__section, .ff-festival__section {
  margin-top: var(--ff-siff-plus-gapY);
}

.ff-siff-plus__section:first-child, .ff-festival__section:first-child {
  margin-top: 0;
}

/* 절 제목 — 표의 항목명과 같은 글자, 아래에 표와 같은 선 */
.ff-siff-plus__heading {
  margin: 0 0 14px;
  padding: 0 0 var(--ff-deflist-rowPadY);
  border-bottom: var(--ff-deflist-lineW) solid var(--ff-deflist-color);
  color: var(--ff-deflist-color);
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.5;
}

/* ----- 편집기 글 ----- */
.ff-siff-plus__rich, .ff-festival__rich {
  line-height: 1.6;
}

.ff-siff-plus__rich > :first-child, .ff-festival__rich > :first-child {
  margin-top: 0;
}

.ff-siff-plus__rich > :last-child, .ff-festival__rich > :last-child {
  margin-bottom: 0;
}

/* 정의형 표는 내용 칸의 문단 여백을 없앤다(한 행 = 한 문단이라서). 여기는
   한 칸에 문단이 여럿이라(수록작 목록 등) 문단 사이를 되살린다. */
.ff-siff-plus__rich p, .ff-festival__rich p {
  margin: 0 0 0.9em;
  font-size: inherit;
  line-height: inherit;
}

.ff-siff-plus__rich a, .ff-festival__rich a {
  color: var(--ff-archive-color);
  text-decoration: underline;
}

.ff-siff-plus__rich h6, .ff-festival__rich h6 {
  margin: 1.4em 0 0.4em;
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.5;
}

.ff-siff-plus__rich ul, .ff-festival__rich ul,
.ff-siff-plus__rich ol,
.ff-festival__rich ol {
  margin: 0 0 0.9em 1.2em;
}

/* 표 안의 표 (제작지원의 공모 기간 · 지원 대상 …). 바깥 표보다 한 단계 낮게 —
   얇은 회색 선, 항목명 칸은 좁게. 테마 기본 표 테두리는 걷어낸다. */
.ff-siff-plus__rich table, .ff-festival__rich table {
  width: 100%;
  margin: 0 0 0.9em;
  border: 0;
  border-collapse: collapse;
}

.ff-siff-plus__rich th, .ff-festival__rich th,
.ff-siff-plus__rich td,
.ff-festival__rich td {
  padding: 6px 0;
  border: 0;
  border-bottom: 1px solid var(--ff-section-line);
  background: none;
  font-weight: inherit;
  text-align: left;
  vertical-align: top;
}

.ff-siff-plus__rich tr:last-child > th, .ff-festival__rich tr:last-child > th,
.ff-siff-plus__rich tr:last-child > td,
.ff-festival__rich tr:last-child > td {
  border-bottom: 0;
}

.ff-siff-plus__rich tr:first-child > th, .ff-festival__rich tr:first-child > th,
.ff-siff-plus__rich tr:first-child > td,
.ff-festival__rich tr:first-child > td {
  padding-top: 0;
}

.ff-siff-plus__rich th, .ff-festival__rich th {
  width: 7em;
  padding-right: 16px;
  font-weight: var(--fw-semibold);
}

.ff-siff-plus__rich td > :last-child, .ff-festival__rich td > :last-child {
  margin-bottom: 0;
}

/* ----- 반응형 -----
   모바일 헤더로 바뀌는 지점에서 한 칸으로 쌓는다. 포스터는 붙지 않고 위에 선다. */
@media (max-width: 1024px) {
  :root {
    --ff-siff-plus-gapY: 32px;
    --ff-siff-plus-headPadY: 16px;
    /* 상세 화면 제목의 모바일 크기 — 공지 · 상영작 상세와 같은 16px */
    --ff-siff-plus-titleSize: 16px;
  }
  .ff-siff-plus__body, .ff-festival__body {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 28px;
  }
  .ff-siff-plus__poster, .ff-festival__poster {
    position: static;
    max-width: 480px;
  }
}
/* 좁은 화면 — 표 안의 표도 한 열로 쌓는다(항목명 위, 내용 아래).
   바깥의 정의형 표가 같은 폭에서 이미 쌓이므로, 안쪽만 두 칸으로 남으면
   내용 칸이 유독 좁아진다. 선은 한 쌍(항목명 + 내용) 아래에만 남긴다. */
@media (max-width: 768px) {
  .ff-siff-plus__rich table, .ff-festival__rich table,
  .ff-siff-plus__rich tbody,
  .ff-festival__rich tbody,
  .ff-siff-plus__rich tr,
  .ff-festival__rich tr,
  .ff-siff-plus__rich th,
  .ff-festival__rich th,
  .ff-siff-plus__rich td,
  .ff-festival__rich td {
    display: block;
    width: auto;
  }
  .ff-siff-plus__rich colgroup, .ff-festival__rich colgroup {
    display: none;
  }
  .ff-siff-plus__rich th, .ff-festival__rich th {
    padding: 6px 0 0;
    border-bottom: 0;
  }
  .ff-siff-plus__rich td, .ff-festival__rich td {
    padding: 2px 0 6px;
  }
  .ff-siff-plus__rich tr:first-child > th, .ff-festival__rich tr:first-child > th {
    padding-top: 0;
  }
  .ff-siff-plus__rich tr:first-child > td, .ff-festival__rich tr:first-child > td {
    padding-top: 2px;
  }
}
/* 좁은 화면 — 제목 면을 검게 깐다.
   모바일 헤더가 보라 면이라(styles/_mobile-header.scss), 바로 아래 이 면까지
   보라면 둘이 한 덩어리로 붙어 어디까지가 헤더인지 갈리지 않는다.
   역대영화제 · 행사사진 상세의 제목 면도 이 규칙을 물려받는다(@extend). */
@media (max-width: 1024px) {
  .ff-siff-plus__head, .ff-gallery__head, .ff-festival__head {
    padding: 8px var(--ep-margin) 12px;
    background-color: var(--color-black);
  }
  /* 제목 아래 줄(카테고리 태그 · 연도 등)은 좁은 화면에서 12px 로 통일한다 —
     공지 · 상영작 상세도 같은 값이다. 역대영화제 · 행사사진 상세가 물려받는다. */
  .ff-siff-plus__category, .ff-gallery__category, .ff-festival__category,
  .ff-siff-plus__meta,
  .ff-gallery__meta,
  .ff-festival__meta {
    font-size: 12px;
  }
  /* 카테고리 태그의 글자는 제목 면과 같은 검정 — 흰 칸이 면에서 오려낸 것처럼
     읽힌다. 누르거나 올린 상태에서도 같은 색이다(위쪽의 강조색 고정 규칙과
     테마 기본 링크 규칙을 이 폭에서 덮는다). */
  .ff-siff-plus__category, .ff-gallery__category, .ff-festival__category,
  .ff-siff-plus__category:hover,
  .ff-siff-plus__category:focus,
  .ff-siff-plus__category:active {
    color: var(--color-black);
  }
}
/* ----- SIFF PLUS Single End ----- */
/* ==================================================================
   Festival Single  (템플릿: single-film-festival.php · 마크업: inc/festival-single.php)
   ------------------------------------------------------------------
   역대영화제 상세. 뼈대는 SIFF PLUS 상세와 같다 — 보라 바(제목 · 부가 정보),
   세로 라벨, 포스터 | 내용 두 칸.

   [구조]
     .ff-archive-page.ff-festival (article)
       ├ .ff-festival__head             ← 보라 바. 제목(h1) · 역대영화제 · 연도
       └ .ff-archive-page__body
           ├ .ff-section-label
           └ .ff-archive-page__main
               ├ .ff-festival__body     ← 2칸: 포스터 | 내용
               │   ├ .ff-festival__poster    포스터 + 버튼(__actions)
               │   └ .ff-festival__main
               │       ├ .ff-festival__overview   개요 표
               │       ├ .ff-festival__events     행사 정보 (긴 칸은 접힌다 — __fold)
               │       ├ .ff-festival__awards     수상작 (부문마다 __awards-section)
               │       └ .ff-festival__juries     심사위원

   [같이 쓰는 모양] 보라 바 · 두 칸 · 포스터 · 버튼 · 표 윗선 · 편집기 글은
   SIFF PLUS 상세의 규칙을 그대로 물려받는다(@extend — styles/_siff-plus-single.scss).
   포스터 폭이나 보라 바 여백을 바꾸려면 그 파일의 토큰을 고친다. 두 화면이 같이 바뀐다.
   여기에는 이 화면에만 있는 것(절 제목 · 부문 소제목 · 접기 · 아래 내비)만 적는다.

   [표] 네 절 모두 정의형 표(styles/_deflist.scss)의 dl 이다. 심사위원은 이름 · 직책
   두 열(.ff-deflist__value--list / __pair)까지 그대로 쓴다.

   [조절]
     접힌 칸 높이   --ff-festival-foldH
     접는 시간      --ff-festival-foldSpeed
     절 제목 아래   --ff-festival-headingGap
================================================================== */
:root {
  --ff-festival-foldH: 15em;
  --ff-festival-foldSpeed: 0.45s;
  --ff-festival-headingGap: 10px;
}

/* ----- SIFF PLUS 상세에서 물려받는 것 ----- */
/* ----- 절 제목 -----
   아래에 바로 표가 오고 표가 윗선을 긋는다. 제목에는 선을 두지 않는다. */
.ff-festival__heading {
  margin: 0 0 var(--ff-festival-headingGap);
  padding: 0;
  color: var(--ff-archive-color);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: var(--fw-bold);
  line-height: 1.4;
}

/* ----- 수상작: 부문 ----- */
.ff-festival__awards-section + .ff-festival__awards-section {
  margin-top: 26px;
}

.ff-festival__subheading {
  margin: 0 0 8px;
  color: var(--color-black);
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.5;
}

/* 작품 링크 옆에 덧붙는 수상자 글 */
.ff-festival__recipient {
  color: #666;
}

/* ----- 행사 정보: 긴 칸 접기 -----
   부대행사는 한 해에 열 개가 넘기도 한다. script.js 가 긴 칸에만 is-folded 를
   붙이고 "더 보기" 버튼을 단다. 접힌 끝은 흐려서 더 있다는 것을 알린다. */
/* 접을 수 있는 칸(script.js 가 is-foldable 을 붙인다)은 높이가 부드럽게 바뀐다.
   높이 값은 스크립트가 px 로 적어 준다 — 시간은 script.js 의 FOLD_SPEED 와 맞춘다. */
.ff-festival__fold.is-foldable .ff-festival__fold-body {
  overflow: hidden;
  transition: max-height var(--ff-festival-foldSpeed) ease;
}

@media (prefers-reduced-motion: reduce) {
  .ff-festival__fold.is-foldable .ff-festival__fold-body {
    transition: none;
  }
}
.ff-festival__fold.is-folded .ff-festival__fold-body {
  max-height: var(--ff-festival-foldH);
  -webkit-mask-image: linear-gradient(#000 55%, transparent);
  mask-image: linear-gradient(#000 55%, transparent);
}

.ff-festival__fold-toggle {
  margin-top: 8px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ff-archive-color);
  font-weight: var(--fw-bold);
  line-height: 1.4;
  text-decoration: underline;
  cursor: pointer;
}

/* GP 기본 button 규칙(회색 배경)이 hover·focus 에서 되살아나므로 함께 잡는다 */
.ff-festival__fold-toggle:hover,
.ff-festival__fold-toggle:focus-visible {
  background: none;
  color: var(--ff-archive-color);
}

/* ----- 보라 바의 링크 (행사사진 → 그 해 영화제) ----- */
.ff-festival__meta-link,
.ff-gallery__meta-link {
  color: inherit;
  text-decoration: underline;
}

.ff-festival__meta-link:hover,
.ff-gallery__meta-link:hover {
  color: inherit;
}

@media (hover: hover) {
  .ff-festival__meta-link:hover,
  .ff-gallery__meta-link:hover {
    opacity: 0.8;
  }
}
/* ----- Festival Single End ----- */
/* ==================================================================
   Gallery Single  (템플릿: single-festival-gallery.php · 마크업: inc/gallery-single.php)
   ------------------------------------------------------------------
   행사사진 상세. 보라 바와 아래 내비는 역대영화제 상세와 같고, 본문은
   사진 슬라이드 하나다.

   [구조]
     .ff-archive-page.ff-gallery (article)
       ├ .ff-gallery__head              ← 보라 바. 연도(h1) · 행사사진
       └ .ff-archive-page__body
           ├ .ff-section-label
           └ .ff-archive-page__main
               ├ .ff-gallery__slider
               │   ├ .ff-gallery__stage      사진 + 좌우 버튼
               │   ├ .ff-gallery__count      "3 / 92"
               │   ├ .ff-gallery__thumbs     썸네일 줄
               │   └ .ff-lightbox (dialog)   크게 보기

   [사진 크기] 높이를 맞추고 폭은 사진 비율대로 둔다 — 가로·세로 사진이 섞여
   있어 폭을 맞추면 세로 사진만 훌쩍 커진다. 높이는 화면 높이와 칸 폭 중 작은
   쪽을 따른다: 칸이 좁으면(모바일) 가로 사진이 칸을 넘지 않게 칸 폭 기준으로 줄인다.
   칸 폭은 컨테이너 단위(cqw)로 잰다 — 왼쪽 세로 라벨 때문에 칸이 화면보다 좁다.

   [가운데 사진] 가운데 사진만 또렷하고 양옆은 흐리다. 가운데를 누르면 크게 보고,
   옆 사진을 누르면 그 사진이 가운데로 온다(script.js).

   [같이 쓰는 모양] 좌우 버튼은 메인 배너(.ff-slider__nav — _slider.scss)의
   규칙을 물려받는다. 카운터와 썸네일 줄은 공지 상세에서 물려받았는데, 공지
   상세가 슬라이드를 걷어내면서(사진을 세로로 쭉 쌓는 방식으로 바뀌었다)
   이쪽으로 옮겨 왔다 — 지금은 여기가 유일한 사용처다.

   [조절]
     사진 높이     --ff-gallery-h
     사진 사이     --ff-gallery-gap (script.js 의 spaceBetween 과 같은 값)
     옆 사진 농도  --ff-gallery-dim
     썸네일 크기   --ff-gallery-thumbSize / --ff-gallery-thumbGap
================================================================== */
:root {
  --ff-gallery-h: min(62vh, 720px);
  --ff-gallery-dim: 0.4;
  --ff-gallery-thumbSize: 84px;
  --ff-gallery-thumbGap: 8px;
}

/* ----- 보라 바 · 아래 내비 (역대영화제 · SIFF PLUS 상세와 같다) ----- */
/* ----- 슬라이드 ----- */
.ff-gallery__stage {
  position: relative;
  container-type: inline-size;
}

.ff-gallery__viewport {
  width: 100%;
}

/* Swiper 기본 CSS 는 우리 CSS 뒤에 실리고 .swiper-slide 에 width: 100% 를 준다.
   클래스 하나로는 비기기만 해서 뒤에 온 쪽이 이긴다 — 한 단계 좁혀 잡는다. */
.ff-gallery .ff-gallery__slide {
  width: auto;
  height: auto;
}

.ff-gallery__open {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  opacity: var(--ff-gallery-dim);
  transition: opacity 0.3s ease;
}

.ff-gallery__open:hover,
.ff-gallery__open:focus-visible {
  background: none;
}

.swiper-slide-active > .ff-gallery__open {
  cursor: zoom-in;
  opacity: 1;
}

.ff-gallery__open:focus-visible {
  outline: 2px solid var(--ff-archive-color);
  outline-offset: -2px;
}

.ff-gallery__img {
  display: block;
  width: auto;
  height: var(--ff-gallery-h);
  /* 컨테이너 단위를 모르는 브라우저는 위 값을 그대로 쓴다 */
  height: min(var(--ff-gallery-h), 58cqw);
  max-width: none;
  object-fit: cover;
}

.ff-gallery__count {
  margin-top: 10px;
  color: var(--color-black);
  font-weight: var(--fw-semibold);
  text-align: center;
}

/* ----- 썸네일 줄 -----
   사진이 많으면 줄바꿈 대신 옆으로 민다 — 줄이 두세 줄로 늘어나면 아래
   내용이 한참 밀려나기 때문이다. 지금 사진은 script.js 가 .is-current 를
   붙여 표시하고, 줄 밖으로 나가 있으면 줄 안에서만 끌어온다. */
.ff-gallery__thumbs {
  display: flex;
  gap: var(--ff-gallery-thumbGap);
  margin: 14px 0 0;
  padding: 0;
  overflow-x: auto;
  list-style: none;
  scrollbar-width: thin;
  scroll-behavior: smooth;
}

.ff-gallery__thumbItem {
  flex: 0 0 auto;
  margin: 0;
}

.ff-gallery__thumb {
  display: block;
  width: var(--ff-gallery-thumbSize);
  height: var(--ff-gallery-thumbSize);
  padding: 0;
  /* 테두리는 처음부터 자리를 차지해 둔다. 지금 사진에만 넣으면 그 칸만
     2px 씩 커져 줄 전체가 흔들린다. */
  border: 2px solid transparent;
  background: none;
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.2s ease, border-color 0.2s ease;
}

/* GP 기본 button 규칙(회색 배경)이 hover·focus 에서 되살아나므로 함께 잡는다 */
.ff-gallery__thumb:hover,
.ff-gallery__thumb:focus-visible {
  background: none;
  opacity: 1;
}

.ff-gallery__thumb.is-current {
  border-color: var(--ff-archive-color);
  opacity: 1;
}

.ff-gallery__thumb:focus-visible {
  outline: 2px solid var(--ff-archive-color);
  outline-offset: 2px;
}

.ff-gallery__thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (prefers-reduced-motion: reduce) {
  .ff-gallery__thumbs {
    scroll-behavior: auto;
  }
}
@media (max-width: 768px) {
  :root {
    --ff-gallery-thumbSize: 64px;
  }
}
/* ----- 크게 보기 -----
   dialog 는 브라우저가 화면 맨 위 층에 올린다. 다만 이 테마는 모든 요소에
   position: relative 를 주고 있어(style.scss) 그대로 두면 화면에 고정되지 않는다.
   fixed 를 직접 적는다. */
.ff-lightbox {
  position: fixed;
  inset: 0;
  width: 100vw;
  max-width: none;
  height: 100vh;
  height: 100dvh;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: rgba(0, 0, 0, 0.92);
  color: var(--color-white);
  overflow: hidden;
}

.ff-lightbox[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}

.ff-lightbox::backdrop {
  background-color: rgba(0, 0, 0, 0.92);
}

.ff-lightbox__img {
  display: block;
  width: auto;
  max-width: calc(100vw - 32px);
  height: auto;
  max-height: calc(100vh - 120px);
  max-height: calc(100dvh - 120px);
  object-fit: contain;
}

.ff-lightbox__close {
  position: absolute;
  top: 10px;
  right: 14px;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-white);
  font-size: 34px;
  line-height: 1;
  cursor: pointer;
}

.ff-lightbox__close:hover,
.ff-lightbox__close:focus {
  background: none;
  color: var(--color-white);
}

/* 올렸을 때 흐려지는 것은 마우스가 있는 기기에서만 */
@media (hover: hover) {
  .ff-lightbox__close:hover {
    opacity: 0.7;
  }
}
/* 사진 좌우 버튼(메인 배너와 같은 .ff-slider__nav — _slider.scss)은 올리면 흐려진다.
   손가락으로 누르는 화면에서는 누른 버튼이 흐린 채로 남으므로 되돌린다. */
@media (hover: none) {
  .ff-gallery .ff-slider__nav:hover,
  .ff-gallery .ff-slider__nav:focus-visible {
    opacity: 1;
  }
  /* 썸네일도 같다 — 공지 상세에서 물려받은 규칙이 올린 썸네일을 또렷하게 하는데,
     누른 뒤 다른 사진으로 넘어가도 그 썸네일이 또렷한 채로 남는다. 지금 장
     (is-current)만 또렷하게 둔다. */
  .ff-gallery__thumb:not(.is-current):hover,
  .ff-gallery__thumb:not(.is-current):focus-visible {
    opacity: 0.55;
  }
}
.ff-lightbox__count {
  position: absolute;
  right: 0;
  bottom: 16px;
  left: 0;
  margin: 0;
  color: var(--color-white);
  font-weight: var(--fw-semibold);
  text-align: center;
}

/* ----- Gallery Single End ----- */
/* ==================================================================
   Film Single  (템플릿: single-films.php · 마크업: inc/films-single.php)
   ------------------------------------------------------------------
   상영작 상세. 위는 보라 면(제목 · 정보 · 스틸컷), 아래는 흰 바탕의 두 칸
   (글 | 예고편)이다.

   [구조]
     .ff-film (article)
       ├ .ff-film__head                 ← 보라 면. 화면 끝까지
       │   ├ .ff-film__headline         제목(h1) · 정보 한 줄 ··· 그 해 영화제
       │   └ .ff-film__stills           스틸컷 슬라이드 + 좌우 버튼(__nav)
       └ .ff-film__body                 ← 2칸
           ├ .ff-film__main
           │   └ .ff-film__section      SYNOPSIS · DIRECTING INTENTION · FESTIVALS & AWARDS ·
           │                            DIRECTOR · STAFF · PROGRAM NOTE
           └ .ff-film__aside            예고편(__trailer). 글을 읽는 동안 헤더 밑에 붙는다

   [스틸컷] 한 장이 칸의 2/3 쯤을 차지하고, 다음 장이 오른쪽 화면 끝까지 흘러
   조금 보인다 — 슬라이드 줄만 사이트 오른쪽 마진을 넘긴다. 칸 비율이 같아야
   줄이 고르므로 이미지는 cover 로 채운다(스틸마다 비율이 조금씩 다르다).

   [조절]
     강조색         --ff-film-color
     스틸 한 장 폭  --ff-film-stillW   · 비율 --ff-film-stillRatio
     스틸 높이 상한 --ff-film-stillMaxH
     스틸 사이      --ff-film-stillGap (script.js 의 spaceBetween 과 같은 값)
     모서리         --ff-film-radius
     칸 사이        --ff-film-gapX     · 절 사이 --ff-film-gapY
     스태프 역할 칸 --ff-film-roleW
     내용 최대 폭   --ff-film-maxW
================================================================== */
:root {
  --ff-film-color: var(--ep-header-lineColor);
  --ff-film-stillW: 66%;
  --ff-film-stillRatio: 7 / 4;
  /* 스틸 한 장의 높이 상한. 넓은 화면에서 스틸이 첫 화면을 다 덮지 않게 한다 */
  --ff-film-stillMaxH: 600px;
  --ff-film-stillGap: 15px;
  --ff-film-radius: 15px;
  --ff-film-gapX: 30px;
  --ff-film-gapY: 36px;
  --ff-film-roleW: 240px;
  --ff-film-navSize: 40px;
  /* 내용이 가장 넓어질 수 있는 폭 */
  --ff-film-maxW: 1600px;
}

/* 푸터와의 간격 — margin 은 GP 규칙에 눌려 사라지므로 padding 으로 준다
   (styles/_archive.scss 의 같은 설명 참고). */
.ff-film {
  padding-bottom: var(--ff-section-footerGap);
}

/* ----- 보라 면 ----- */
.ff-film__head {
  margin-right: calc(var(--ep-margin) * -1);
  margin-left: calc(var(--ep-margin) * -1);
  padding: 18px var(--ep-margin) 26px;
  background-color: var(--ff-film-color);
  color: var(--color-white);
  /* 스틸 줄이 오른쪽으로 흘러나가도 페이지에 가로 스크롤이 생기지 않게 */
  overflow: hidden;
}
@media (max-width: 780px) {
  .ff-film__head {
    background-color: #ededed;
    color: var(--color-black);
  }
}

/* 제목 줄은 본문(.ff-film__body)과 같은 최대 폭에서 멈추고 가운데 선다 — 넓은
   화면에서도 제목의 왼쪽 선이 본문과 맞는다. 스틸 줄은 여기에 묶이지 않고
   화면 왼쪽 끝(사이트 마진)에서 시작해 오른쪽 끝까지 흐른다. */
.ff-film__headline {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 3px 24px;
  max-width: var(--ff-film-maxW);
  margin-inline: auto;
}

.ff-film__titles {
  min-width: 0;
}

/* h1 이 style.scss 에서 받는 위 패딩 · 대문자 변환을 되돌린다 */
.ff-film__title {
  margin: 0;
  padding-top: 0;
  color: inherit;
  font-size: var(--title-m);
  font-weight: var(--fw-bold);
  line-height: 1.2;
  text-transform: none;
}

.ff-film__info {
  margin: 6px 0 0;
  color: inherit;
  font-size: inherit;
  font-weight: var(--fw-medium);
  line-height: 1.4;
}

.ff-film__festival {
  flex: 0 0 auto;
  padding-top: 4px;
  color: inherit;
  font-weight: var(--fw-medium);
  line-height: 1.4;
  white-space: nowrap;
}

.ff-film__festival:hover,
.ff-film__festival:focus-visible {
  color: inherit;
  text-decoration: underline;
}

/* ----- 스틸컷 ----- */
.ff-film__stills {
  position: relative;
  margin-top: 14px;
}

/* 줄은 내용 폭을 넘겨 화면 끝까지 간다. 넘친 부분은 보라 면이 자른다.
   Swiper 기본 CSS(.swiper { overflow: hidden })가 우리 CSS 뒤에 실리므로
   한 단계 좁혀 잡아야 이긴다. */
.ff-film .ff-film__viewport {
  overflow: visible;
}

/* Swiper 기본 CSS 는 우리 CSS 뒤에 실리고 .swiper-slide 에 width: 100% 를 준다 —
   한 단계 좁혀 잡아야 이긴다. */
.ff-film .ff-film__still {
  /* 폭은 줄의 --ff-film-stillW 만큼, 다만 높이가 상한을 넘지 않는 폭까지만.
     높이는 비율에서 나오므로 "상한 높이 × 비율"이 폭의 상한이 된다. */
  width: min(var(--ff-film-stillW), var(--ff-film-stillMaxH) * var(--ff-film-stillRatio));
  height: auto;
  aspect-ratio: var(--ff-film-stillRatio);
  border-radius: var(--ff-film-radius);
  overflow: hidden;
}

/* 한 장뿐이면 Swiper 를 싣지 않는다. 줄 모양만 맞춘다. */
.ff-film__stills:not([data-ff-film-slider]) .swiper-wrapper {
  display: flex;
}

.ff-film__still-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* 좌우 버튼 — 검은 네모에 흰 화살표 */
.ff-film__nav {
  position: absolute;
  top: 50%;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--ff-film-navSize);
  height: var(--ff-film-navSize);
  padding: 0;
  border: 0;
  border-radius: 0;
  background-color: var(--color-black);
  color: var(--color-white);
  cursor: pointer;
  transform: translateY(-50%);
  transition: opacity 0.2s ease;
}

/* GP 기본 button 규칙(회색 배경)이 hover·focus 에서 되살아나므로 함께 잡는다 */
.ff-film__nav:hover,
.ff-film__nav:focus-visible {
  background-color: var(--color-black);
  color: var(--color-white);
  opacity: 0.8;
}

.ff-film__nav--prev {
  left: 0;
}

.ff-film__nav--next {
  right: 0;
}

/* 아이콘(arrow.svg)은 오른쪽을 향한다 — 이전 버튼만 뒤집는다 */
.ff-film__nav--prev svg {
  transform: scaleX(-1);
}

.ff-film__nav svg {
  width: 60%;
  height: auto;
}

.ff-film__nav svg path {
  fill: currentColor;
}

/* ----- 두 칸: 글 | 예고편 ----- */
.ff-film__body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--ff-film-gapX);
  align-items: start;
  max-width: var(--ff-film-maxW);
  margin: 56px auto 0;
}

.ff-film__main {
  min-width: 0;
}

.ff-film__section + .ff-film__section {
  margin-top: var(--ff-film-gapY);
}

/* 절 제목 — 메인의 섹션 제목(PROGRAM 등)과 같은 글자.
   h2 가 style.scss 에서 받는 모바일 위 패딩을 되돌린다. */
.ff-film__heading {
  margin: 0 0 12px;
  padding-top: 0;
  color: var(--color-black);
  font-size: var(--title-m);
  font-weight: var(--fw-bold);
  line-height: 1.1;
  text-transform: uppercase;
}

.ff-film__section p {
  margin: 0 0 0.9em;
  line-height: 1.7;
}

.ff-film__section p:last-child {
  margin-bottom: 0;
}

.ff-film__section a {
  color: var(--ff-film-color);
  text-decoration: underline;
}

/* ----- 예고편 ----- */
.ff-film__aside {
  position: sticky;
  top: calc(var(--ff-headerBottom, calc(var(--ep-topbar-h, 0px) + var(--ep-headerH, 0px))) + 20px);
  min-width: 0;
}

.ff-film__trailer {
  position: relative;
  aspect-ratio: 16/9;
  border-radius: var(--ff-film-radius);
  background-color: var(--color-black);
  overflow: hidden;
}

.ff-film__trailer iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* ----- 감독 ----- */
.ff-film__director {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 12px;
  align-items: start;
}

.ff-film__director + .ff-film__director {
  margin-top: 24px;
}

.ff-film__director--text {
  grid-template-columns: minmax(0, 1fr);
}

.ff-film__director-img {
  display: block;
  width: 100%;
  height: auto;
}

.ff-film__director-name {
  margin: 0 0 12px;
  padding: 4px 0 12px;
  border-bottom: 1.5px solid var(--color-black);
  color: var(--color-black);
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: var(--fw-bold);
  line-height: 1.4;
}

/* 소개 글이 없는 감독 — 이름만 있다. 아래에 나눌 것이 없으니 선과 그 여백을 뺀다. */
.ff-film__director--plain .ff-film__director-name {
  margin-bottom: 0;
  padding-bottom: 0;
  border-bottom: 0;
}

/* 필모그래피는 한 줄에 한 편 — 본문보다 줄 사이를 좁힌다 */
.ff-film__director-bio p {
  line-height: 1.5;
}

/* ----- 스태프 ----- */
.ff-film__staff {
  margin: 0;
}

.ff-film__staff-row {
  display: grid;
  grid-template-columns: var(--ff-film-roleW) minmax(0, 1fr);
  column-gap: 12px;
  padding: 5px 0;
  font-weight: var(--fw-bold);
  line-height: 1.5;
}

.ff-film__staff-names {
  margin: 0;
}

/* ----- 반응형 -----
   모바일 헤더로 바뀌는 지점에서 한 칸으로 쌓는다. 예고편은 글 위로 올린다. */
@media (max-width: 1024px) {
  :root {
    --ff-film-stillW: 88%;
    --ff-film-stillGap: 10px;
    --ff-film-gapY: 30px;
    --ff-film-roleW: 120px;
    --ff-film-navSize: 34px;
  }
  .ff-film__headline {
    flex-direction: column;
  }
  /* 상세 화면 제목의 모바일 크기 — 다른 상세 화면과 같은 16px */
  .ff-film__title {
    font-size: 16px;
  }
  .ff-film__festival {
    padding-top: 0;
    white-space: normal;
  }
  /* 제목 아래 줄(정보 한 줄 · 그 해 영화제)은 좁은 화면에서 12px — 다른 상세 화면과 같다 */
  .ff-film__info,
  .ff-film__festival {
    font-size: 12px;
  }
  .ff-film__body {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--ff-film-gapY);
    margin-top: var(--ep-contentTop);
  }
  .ff-film__aside {
    position: static;
    order: -1;
  }
  .ff-film__heading {
    font-size: 22px;
  }
}
/* 좁은 화면 — 스태프 표를 한 열로 쌓는다(역할 위, 이름 아래).
   정의형 표 · 연혁 표와 같은 폭에서 같은 방식이다. 옆으로 나란할 때는 칸이
   둘을 갈라 주지만, 쌓이면 둘 다 굵어 어디까지가 역할인지 읽기 어렵다 —
   이름 쪽만 보통 굵기로 낮춘다. */
@media (max-width: 768px) {
  .ff-film__staff-row {
    grid-template-columns: minmax(0, 1fr);
    padding: 7px 0;
  }
  .ff-film__staff-names {
    font-weight: var(--fw-medium);
  }
}
/* ----- Film Single End ----- */
:root[data-size=desktop] {
  --ep-margin: 15px;
  --ep-pageTop: 12px;
  --ep-headerH: 64px;
}

:root[data-size=tablet],
:root[data-size=phone_large],
:root[data-size=phone] {
  --ep-margin: 10px;
  --ep-pageTop: 10px;
  --ep-headerH: 50px;
}

/* 사이트 좌우 마진 — 실제로 적용되는 건 이 미디어쿼리다.
   위 data-size 블록은 :root 에 그 속성을 붙이는 코드가 있어야 동작하는데
   지금은 없다(있으면 같은 값이 나오도록 $sizes 도 맞춰 두었다).
   전환 폭은 모바일 헤더와 같은 지점($mo-bp) — 헤더가 바뀌는 순간 본문
   왼쪽 선도 같이 움직여야 둘이 어긋나지 않는다. */
@media (max-width: 1024px) {
  :root {
    --ep-margin: 10px;
    /* 모바일 본문 글자 크기. rem 기준(html 18px)은 그대로 두고 본문만 줄인다 —
       메뉴·타이틀처럼 rem 으로 잡아둔 크기까지 함께 줄면 안 되기 때문이다.
       font-size: inherit 로 받는 컴포넌트(정의형 표·정보 그리드 등)가 따라온다. */
    --ep-bodySize: 15px;
  }
}
* {
  word-break: keep-all;
  box-sizing: border-box;
  position: relative;
}

html {
  font-size: 18px !important;
}

body,
button,
input,
select,
optgroup,
textarea {
  font-size: var(--ep-bodySize) !important;
  line-height: 1.4em !important;
  font-family: var(--font-body) !important;
  font-weight: var(--fw-medium);
}

.font-display {
  font-family: var(--font-display) !important;
  font-weight: var(--fw-bold);
  font-synthesis: none;
}

body {
  background-color: var(--icaseoul-bg-1);
}

h1,
h2,
h3,
h4,
h5,
h6 {
  color: black;
}

h1 {
  font-size: var(--title-m);
  line-height: 1.1;
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  padding-top: calc(var(--ep-margin) * 2);
}
@media (max-width: 1024px) {
  h1 {
    font-size: 22px;
    padding-top: 20px;
  }
}

h2 {
  font-size: 1.8125rem;
  line-height: 1.1;
  font-weight: var(--fw-bold);
}
@media (max-width: 1024px) {
  h2 {
    font-size: 22px;
    padding-top: 20px;
  }
}

h3 {
  font-size: 1.25rem;
  line-height: 1.4;
  font-weight: var(--fw-bold);
}

h4 {
  font-size: 1.1rem;
  line-height: 1.4;
  font-weight: var(--fw-bold);
}

p {
  font-size: var(--ep-bodySize);
  font-weight: var(--fw-medium);
  line-height: 170%;
}

strong,
b {
  font-weight: var(--fw-bold);
}

.caption {
  font-size: 0.875rem;
}

a {
  text-decoration: none;
  color: #000;
}

/* ----- Initialize End ----- */
/* Global Styles */
/* 1) GP 컨테이너 max-width 해제 */
.grid-container,
body .grid-container,
.container.grid-container,
.wp-block-group__inner-container {
  max-width: 100%;
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}

/* 2) GP 기본 내부 여백 제거 — 여백은 사이트 마진으로만 관리 */
.separate-containers .inside-article,
.separate-containers .page-header,
.separate-containers .comments-area,
.separate-containers .paging-navigation,
.inside-page-header,
.site-main .wp-block-group__inner-container,
.widget-area .widget,
.footer-widgets-container {
  padding: 0;
}

.separate-containers .site-main,
.separate-containers.no-sidebar .site-main {
  margin: 0;
}

/* 3) 좌우 사이트 마진 */
.inside-header,
.inside-top-bar,
.site-content,
.one-container .site-content,
.inside-site-info,
.nav-below-header .main-navigation .inside-navigation.grid-container,
.nav-above-header .main-navigation .inside-navigation.grid-container {
  padding-left: var(--ep-margin);
  padding-right: var(--ep-margin);
}

/* 스크롤 인터랙션 확인용 — 컨텐츠 영역 최소 높이 */
.site-content {
  min-height: 100vh;
  /* dvh 미지원 브라우저 폴백 */
  min-height: 100dvh;
}

/* 모바일 — 내용이 짧으면 푸터까지 한 화면에 담는다.
   위 min-height(100dvh)는 내용 길이와 상관없이 한 화면을 통째로 차지해서,
   짧은 페이지에서도 푸터가 늘 화면 밖으로 밀려났다(빈 흰 면을 한참 스크롤해야
   푸터가 나왔다). 모바일에서는 그 자리를 "남는 높이만큼만" 채우도록 바꾼다.

   [방식] 세로 flex 의 전형적인 푸터 붙이기다.
     - 내용이 짧으면 #page 가 남는 높이를 가져가 푸터가 화면 바닥에 붙는다
       → 헤더 + 본문 + 푸터가 한 화면에 들어가고 스크롤이 생기지 않는다.
     - 내용이 길면 flex-shrink: 0 이라 평소대로 늘어난다.
   푸터(.site-footer)는 #page 안이 아니라 body 직계라서 body 를 flex 로 잡는다.
   고정 요소(헤더 · 메가메뉴 · 떠 있는 버튼)는 흐름 밖이라 flex 아이템이 아니다.
   모바일 헤더(#mo-header)는 display: contents 라 그 자식이 flex 아이템이 되는데,
   sticky 는 flex 아이템에서도 그대로 동작한다. */
@media (max-width: 1024px) {
  body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
  }
  #page {
    flex: 1 0 auto;
  }
  .site-footer {
    flex: 0 0 auto;
  }
  .site-content {
    min-height: 0;
  }
}
/* 4) 정렬 블록 — alignwide는 마진 안쪽, alignfull은 화면 끝까지 */
.entry-content .alignwide {
  margin-left: 0;
  margin-right: 0;
  width: 100%;
  max-width: 100%;
}

.entry-content .alignfull,
.no-sidebar .entry-content .alignfull {
  margin-left: calc(var(--ep-margin) * -1);
  margin-right: calc(var(--ep-margin) * -1);
  width: auto;
  max-width: none;
}

/* ----- Layout End ----- */
/* ----- Global Styles End ----- */
/* Custom Styles */
/* ----- Custom Styles End ----- */

/*# sourceMappingURL=style.css.map */
