/* ============================================================
   BLOCKFESTA 2026 — 사이트 스타일
   근거: docs/concept/README.md (승인된 v2 디자인 스펙).
   깊이는 표면 단계와 1px 헤어라인으로만 — 그림자 금지.
   모션 예산: 히어로만 연속 씬, 심(seam)은 진입 시 1회,
   마지막 CTA는 느린 펄스 1개. 나머지 지오메트리는 정지.
   ============================================================ */

* { box-sizing: border-box; }

/* 머리띠 높이는 히어로도 알아야 한다 — 첫 화면은 머리띠와 히어로
   둘이 정확히 나눠 갖는다. 그래서 :root에 둔다. */
:root { --bf-headrow: 64px; }

html { scroll-behavior: smooth; }

/* --- 대체 글꼴의 폭 맞추기(2026-09-04) ------------------------
   Pretendard 가 오기 전에는 시스템 글꼴이 선다. 그런데 Malgun Gothic
   은 Pretendard 보다 10% 넓어 히어로의 리드 문단이 두 줄이 아니라 세
   줄이 되었고, 히어로가 세로 가운데 정렬이라 그 32px 이 위아래로
   반씩 나뉘어 — 제목은 16px 위로, 단추는 16px 아래로 — 글꼴이 바뀌는
   순간 모두가 제자리로 뛰었다(사용자, 2026-09-04).
   size-adjust 로 대체 글꼴을 좁혀 두면 줄바꿈이 같아져 아무것도
   움직이지 않는다. 값은 잰 것이다: 같은 문장의 폭 비가 라틴 94%,
   한글 90%(Malgun Gothic 기준, 굵기 400과 900에서 같다).
   글자는 그만큼 작게 그려진다 — 잠깐 동안의 대체 글꼴이므로 폭이
   맞는 쪽이 낫다.
   local() 뿐이라 새 내려받기는 없다. 아무것도 없는 기기에서는 이
   @font-face 가 통째로 건너뛰어지고 예전처럼 다음 후보로 넘어간다.
   한글 판을 뒤에 적는다: 같은 이름의 두 판이 한 글자를 함께 덮으면
   나중 것이 이긴다. */
@font-face {
  font-family: "Pretendard fallback";
  src: local("Segoe UI"), local("Helvetica Neue"), local("Arial");
  font-weight: 100 799;
  size-adjust: 94%;
}
/* 굵은 라틴은 따로다(2026-09-04). Segoe UI 에는 Black 이 없어 900 을
   부르면 Semibold 를 굵게 흉내 내는데, 그 폭이 400 일 때와 다르다:
   Pretendard 와의 비가 400 에서 93~95%, 900 에서 90~91% 였다. 하나의
   size-adjust 로 둘을 함께 맞출 수 없으므로 굵기 구간을 나눈다.
   한글은 굵기와 상관없이 90% 라 아래 한 판으로 족하다. */
@font-face {
  font-family: "Pretendard fallback";
  src: local("Segoe UI"), local("Helvetica Neue"), local("Arial");
  font-weight: 800 900;
  size-adjust: 90.5%;
}
@font-face {
  font-family: "Pretendard fallback";
  src: local("Malgun Gothic"), local("Apple SD Gothic Neo"), local("Noto Sans KR");
  font-weight: 100 900;
  size-adjust: 90%;
  unicode-range: U+1100-11FF, U+3130-318F, U+A960-A97F, U+AC00-D7A3, U+D7B0-D7FF;
}

/* 무엇이 하나 넘쳐도 페이지 전체가 옆으로 밀리지 않게 하는 안전망
   (2026-09-06, 사용자). hidden 이 아니라 clip 이다: hidden 은 그 요소를
   스크롤 컨테이너로 만들고, 그러면 그 안의 position: sticky 가 이 문서의
   스크롤포트를 잃는다 — 우리 머리띠가 sticky 다. clip 은 자르기만 하고
   스크롤 컨테이너를 만들지 않으므로 머리띠가 그대로 붙어 있다.
   세로는 건드리지 않는다(clip 은 한 축만 지정해도 된다, hidden 과 달리
   다른 축이 auto 로 끌려가지 않는다).
   이것은 증상을 가리는 그물일 뿐 고침이 아니다 — 넘치는 것은 그때그때
   원인을 고친다. 오래된 사파리(16 아래)는 clip 을 모르고 그냥 지나간다:
   그물이 없는 셈이지만 부수는 것도 없다. */
body {
  overflow-x: clip;
  margin: 0;
  background: var(--bf-bg);
  color: var(--bf-fg);
  font-family: var(--bf-font);
  font-size: var(--bf-size-body);
  line-height: var(--bf-leading-latin);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--bf-300); text-decoration: none; transition: color var(--bf-dur-1) var(--bf-ease); }
a:hover { color: var(--bf-200); }
::selection { background: var(--bf-600); color: var(--bf-fg); }

:focus-visible { outline: none; box-shadow: var(--bf-focus); border-radius: var(--bf-radius-1); }

/* --- 심(seam)의 발광 — 진입 시 1회. site.js가 붙인다 --------
   레일 씬의 신호 키프레임(bfDash·bfEmerge·bfEmergeSoft)은
   지웠다(2026-08-13): 그 씬이 사라져 쓰는 곳이 없다. */
@keyframes bfSeam { 0% { stroke-dashoffset: 1000; opacity: 0; } 12% { opacity: .95; } 82% { opacity: .95; } 100% { stroke-dashoffset: 0; opacity: 0; } }

/* 모션 감소 선호 시 모든 애니메이션 정지 — 씬은 정지 프레임 */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}

/* --- 아이브로우 -------------------------------------------- */
.bf-eyebrow {
  font-size: var(--bf-size-eyebrow);
  font-weight: var(--bf-weight-eyebrow);
  letter-spacing: var(--bf-track-eyebrow);
  text-transform: uppercase;   /* 라틴 전용 */
  color: var(--bf-200);
}
/* 아이브로우 문자열은 두 언어 모두 라틴이다. 한글이 들어오면
   자간과 대문자 변환을 반드시 꺼야 한다 — 둘 다 라틴의 장치다. */
.bf-eyebrow:lang(ko) { letter-spacing: 0; text-transform: none; word-break: keep-all; }

/* --- 버튼 --------------------------------------------------
   기본 = 라이트 채움 + 그라파이트 라벨. 보조 = 아주르 아웃라인.
   블루 채움 버튼은 존재하지 않는다. */
/* 모서리는 2px다(2026-09-07; 09-06 에는 4px, 그 전에는 8px 이었다).
   8px 은 이 페이지의 곧은 선들 사이에서 말랑하고 무겁게 읽혔고, 더 각진
   쪽으로 두 번에 걸쳐 내려왔다 — 공유 카드의 그림이 그 값이다.
   언어 토글만 4px 로 남는다: 그것은 단추가 아니라 두 칸짜리 트랙이다.
   초점 고리는 4px 로 잡혀 있으나 이 규칙이 뒤에 있어 단추에서는 2px 이 이긴다. */
.bf-btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--bf-font); font-weight: 600; cursor: pointer;
  border-radius: 2px; border: 1px solid transparent;
  transition: background var(--bf-dur-1) var(--bf-ease), color var(--bf-dur-1) var(--bf-ease);
  white-space: nowrap;
}
.bf-btn--primary { background: var(--bf-cta-bg); color: var(--bf-cta-fg); }
.bf-btn--primary:hover { background: var(--bf-cta-bg-hover); color: var(--bf-cta-fg); }
.bf-btn--primary:active { background: #D8DEE9; }
/* 파란 버튼은 하나의 모양뿐이다 — 채운 아주르. 아웃라인은 버튼이
   아니라 칩(프레임 이름 등)의 것이므로, 둘이 같은 옷을 입으면 무엇이
   눌리는지 알 수 없다.
   600 위의 밝은 글자는 6.4:1, 700 위에서는 9.6:1 — 둘 다 AA를 넘는다.
   그래서 호버는 밝히지 않고 어둡게 간다: 500까지 밝히면 4.3:1로
   기준 아래로 떨어진다. */
.bf-btn--secondary { background: var(--bf-cta-2-bg); border-color: var(--bf-cta-2-border); color: var(--bf-cta-2-fg); }
.bf-btn--secondary:hover { background: var(--bf-cta-2-bg-hover); border-color: var(--bf-cta-2-border); color: var(--bf-cta-2-fg); }
/* 문의 단추 — 한 화면에서 가장 시끄러운 것. 토큰의 까닭은 tokens.css
   에 적었다. 채움 단추이므로 테두리는 없다. */
.bf-btn--hot { background: var(--bf-cta-hot-bg); color: var(--bf-cta-hot-fg); }
.bf-btn--hot:hover { background: var(--bf-cta-hot-bg-hover); color: var(--bf-cta-hot-fg); }
.bf-btn--hot:active { background: #E8850F; }
/* 세 번째 모양 — 링크다(2026-09-04). 채움도 테두리도 없고 밑줄로
   링크임을 말한다. 주 단추와 나란히 서지만 무게가 달라야 한다: 한
   화면이 부르는 일은 하나이고, 나머지는 옆길이다.
   높이는 --lg 를 그대로 받아 옆의 단추와 밑줄이 맞고, 가로 여백만
   지운다 — 단추의 26px 은 채움이 있을 때의 값이다. */
.bf-btn--link {
  background: none; border-color: transparent; padding-inline: 4px;
  color: var(--bf-300); text-decoration: underline; text-underline-offset: 4px;
}
.bf-btn--link:hover { background: none; color: var(--bf-200); }
/* 헤더에 나란히 서는 두 조각 — 언어 전환과 신청 단추 — 은 같은 높이다.
   값을 한 곳에 두어 둘이 어긋나지 않게 한다: 예전에는 각자 제 안쪽
   여백으로 높이가 생겨 32px 과 31px 로 어긋나 있었다. */
:root { --bf-ctl-h: 32px; }
.bf-btn--sm { height: var(--bf-ctl-h); padding: 0 14px; font-size: 13.5px; }
/* 머리의 등록 버튼은 너비를 고정한다 — 등록하기(≈94px)와
   Register(≈99px)의 차이만큼 언어를 바꿀 때마다 머리가 들썩였다.
   두 문구 중 넓은 쪽에 맞춘 값이며, 문구가 바뀌면 다시 잰다. */
.bf-header a.bf-btn--sm { width: 104px; padding: 0; }
.bf-btn--lg { height: 49px; padding: 0 26px; font-size: 15.5px; }

/* 어디론가 데려가는 버튼에는 오른쪽에 셰브론이 붙고, 가리키면 조금
   더 그쪽으로 간다. 폼 전송 버튼은 이동이 아니므로 붙지 않는다 —
   그래서 선택자가 a로 시작한다. */
a.bf-btn { gap: 10px; }
a.bf-btn::after {
  content: ""; flex: none; width: 7px; height: 7px; margin-top: -1px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform var(--bf-dur-1) var(--bf-ease);
}
a.bf-btn:hover::after { transform: translateX(3px) rotate(-45deg); }

/* --- 언어 토글 ---------------------------------------------
   트랙 안쪽에 여백을 두고 활성 알약이 그 안에서 움직이는 형태.
   테두리에 딱 붙은 두 칸이 아니다. */
/* 모서리는 버튼과 같은 4px다(2026-09-06) — 머리에서 등록 버튼과
   나란히 서므로 둘의 각이 어긋나면 바로 보인다. 안쪽 알약은 이미 4px. */
.bf-lang {
  display: inline-flex; align-items: stretch; gap: 2px; padding: 3px;
  height: var(--bf-ctl-h);
  border: var(--bf-border); border-radius: var(--bf-radius-1);
  background: var(--bf-surface);
}
/* 세로 여백 대신 늘어나서 채운다 — 그래야 켜진 쪽 알약이 테두리
   안쪽을 꽉 채우고, 높이는 위의 한 값만 따른다. */
.bf-lang a {
  display: inline-flex; align-items: center;
  padding: 0 11px; font-size: 12.5px; font-weight: 600; line-height: 1;
  color: var(--bf-fg-faint); border-radius: var(--bf-radius-1);
  transition: background var(--bf-dur-1) var(--bf-ease), color var(--bf-dur-1) var(--bf-ease);
}
.bf-lang a:hover { color: var(--bf-fg-muted); }
.bf-lang a.is-active { background: var(--bf-surface-hi); color: var(--bf-fg); }

/* --- 헤더 --------------------------------------------------
   헤더 위의 폴리오 스트립은 제거됨(2026-08-11). */
.bf-header {
  /* 윗줄 높이(--bf-headrow, 접힘 거리도 이 값)는 :root에 있다 */
  position: sticky; top: 0; z-index: 10;
  /* 어두운 유리 — 바탕을 덜 덮고 더 흐린다. 아래 내용이 형태로만
     비치고 글자로는 읽히지 않는 지점이 78%다. 채도를 조금 올리는
     것은 흐림이 색을 빨아 회색으로 만들기 때문이며, 새 색을 들이는
     것이 아니라 뒤에 있던 색을 되돌리는 것이다. */
  background: color-mix(in srgb, var(--bf-bg) 78%, transparent);
  backdrop-filter: blur(18px) saturate(125%);
  -webkit-backdrop-filter: blur(18px) saturate(125%);
  /* 맨 위에서는 선도 그림자도 없다 — 헤더가 히어로의 일부처럼
     보여야 한다. 페이지가 밀리는 순간에만 아래에 얇은 선과 옅은
     그림자가 생겨, 글이 헤더 밑으로 지나간다는 것을 말한다
     (2026-09-03). 자리를 지키느라 선은 늘 있고 색만 바뀐다 —
     생겼다 없어지면 헤더가 1px 씩 흔들린다.
     그림자는 새 색이 아니라 페이지 바탕색을 묽게 쓴 것이다. */
  border-bottom: 1px solid transparent;
  transition: border-color var(--bf-dur-2) var(--bf-ease),
              box-shadow var(--bf-dur-2) var(--bf-ease),
              transform var(--bf-dur-2) var(--bf-ease);
}
/* 선은 헤어라인을 그대로 쓰지 않고 바탕 쪽으로 당겨 둔다 — 헤어라인은
   상자 테두리의 굵기이고, 여기서는 경계가 아니라 기척이면 된다
   (2026-09-03). 1.63:1 이던 것이 1.28:1 이 된다. 더 얇게는 못 만든다:
   1px 이 이미 CSS 의 바닥이고, 0.5px 는 2배 화면에서만 반쪽으로
   그려지고 1배 화면에서는 사라지거나 그대로 1px 이 된다 — 화면마다
   다른 굵기가 나오느니 색으로 낮춘다. 새 색은 아니다: 토큰 둘을
   섞은 값이다. */
.bf-header.is-stuck {
  border-bottom-color: color-mix(in srgb, var(--bf-hairline) 60%, var(--bf-bg));
  box-shadow: 0 10px 22px -16px color-mix(in srgb, var(--bf-bg) 66%, transparent);
}
/* 흐림이 없는 브라우저에서는 유리가 아니라 그냥 반투명한 구멍이 된다
   — 그런 곳에서는 거의 불투명하게 덮는다. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .bf-header { background: color-mix(in srgb, var(--bf-bg) 96%, transparent); }
}
.bf-header__in {
  max-width: 1200px; margin: 0 auto; padding: 0 32px; height: var(--bf-headrow);
  display: flex; align-items: center; gap: 28px;
}
.bf-header__brand { display: flex; align-items: center; gap: 10px; color: var(--bf-fg); }
.bf-header__brand img { display: block; }
.bf-header__word { font-weight: 900; font-size: 20px; letter-spacing: var(--bf-track-display); }
.bf-header__year { font-weight: 500; font-size: 13px; color: var(--bf-fg-muted); }
/* 내비게이션 — 현재 섹션에 밑줄. 밑줄은 항목마다 새로 나타나지
   않고 하나의 선이 좌우로 미끄러져 이동한다(스크롤스파이, site.js). */
/* 마크와 언어 전환 사이의 남는 폭 한가운데에 선다 — 양쪽 auto 여백이
   남는 자리를 똑같이 나눈다. 오른쪽으로 밀어 두면 언어 전환·등록과
   한 덩어리로 뭉쳐 어디까지가 내비인지 흐려진다. */
.bf-header__nav { position: relative; display: flex; gap: 4px; margin-left: auto; margin-right: auto; }
.bf-header__nav a {
  font-size: 16px; font-weight: 500; padding: 8px 12px;
  color: var(--bf-fg-muted);
  transition: color var(--bf-dur-1) var(--bf-ease);
}
.bf-header__nav a:hover { color: var(--bf-100); }
.bf-header__nav a.is-active { color: var(--bf-100); }

/* 밑줄 하나가 세 가지로 움직인다:
   처음 나타날 때 — 왼쪽 끝에서 폭이 자라 제자리를 채우고,
   항목 사이 — 좌우로 미끄러지며,
   사라질 때 — 자란 순서를 되감아 왼쪽으로 줄어든다. */
.bf-header__ink {
  position: absolute; left: 0; bottom: 2px; height: 2px; width: 0;
  background: var(--bf-300); border-radius: 1px;
  pointer-events: none; transform-origin: left center;
  transition: transform var(--bf-dur-2) var(--bf-ease),
              width var(--bf-dur-2) var(--bf-ease);
}

/* --- 좁은 화면의 섹션 띠 -----------------------------------
   넓은 화면에서는 없다. 좁은 화면에서 밑줄 내비 대신 서며, 가로로
   밀어서 본다. 현재 섹션에 밑줄이 켜지고 화면 밖이면 스크립트가
   끌어온다(site.js). 알약이 아니라 링크다 — 넓은 화면의 내비와 같은
   말투로 말하고, 여섯 개의 테두리가 헤더를 도구 모음으로 만들지
   않는다. */
.bf-subnav { display: none; }
.bf-subnav a {
  flex: none; padding: 8px 0 6px; border-bottom: 2px solid transparent;
  color: var(--bf-fg-muted); font-size: 14.5px; font-weight: 500;
  white-space: nowrap;
  transition: color var(--bf-dur-1) var(--bf-ease), border-color var(--bf-dur-1) var(--bf-ease);
}
.bf-subnav a.is-active { color: var(--bf-100); border-bottom-color: var(--bf-300); }

/* 스크롤을 내리면 윗줄만 접히고 섹션 띠는 남는다 — 읽는 동안에도
   "여기가 어디인지"는 계속 보여야 한다. 올리면 윗줄이 돌아온다.
   좁은 화면에서만 — 넓은 화면에는 숨길 이유가 없다.

   접는 방법은 반드시 transform이어야 한다. 높이를 줄이면 스티키
   헤더도 흐름 안에 있으므로 문서가 그만큼 짧아지고, 브라우저가
   scrollY를 되밀면서 "위로 스크롤"로 읽혀 헤더가 다시 펼쳐진다 —
   그 즉시 문서가 길어져 또 접힌다. 화면이 떠는 것은 그 되먹임이다.
   transform은 배치를 건드리지 않으므로 고리가 생기지 않는다. */
.bf-header { transition: transform var(--bf-dur-2) var(--bf-ease); }

/* 앵커로 이동할 때 스티키 헤더가 제목을 가리지 않도록.
   값은 헤더 높이 그대로다 — 그보다 크면 섹션이 헤더 아래에
   떨어져 서고, 그 틈으로 앞 섹션의 끝자락이 보인다(2026-09-07,
   사용자: 메뉴가 섹션보다 조금 위로 간다). 88 은 24px 많았다. */
[id] { scroll-margin-top: var(--bf-headrow); }

/* --- 히어로 + 스카이라인 씬 --------------------------------
   배경은 평면 SVG 스카이라인 하나(partials/scene.php, 승인
   핸드오프 docs/export_hero_cta). 바닥 고정(xMidYMax slice)이라
   씬 SVG 하나가 히어로와 아래 소산 구간을 함께 덮는다. */
.bf-scene-host {
  position: relative; overflow: hidden; background: var(--bf-bg);
  --bf-scene-foot: 104px;   /* 히어로 아래 여백 — 그림은 여기까지 오지 않는다 */
  /* 첫 화면에서 히어로가 갖는 높이. 그림판도 같은 값을 쓰므로
     한 곳에서만 정한다. */
  --bf-hero-h: max(600px, calc(100vh - var(--bf-headrow)));
}
/* 그림판의 바닥은 히어로의 바닥이다 — 도시의 기단까지가 첫 화면
   안에 들어온다(2026-08-13). 치수는 둘 다 적어 준다: SVG는 고유
   비율을 가진 대체 요소라 오프셋만으로는 상자를 채우지 않는다.

   폭은 그림의 비율(1440:780)에 묶고 오른쪽에 붙인다(2026-08-13).
   폭을 화면에 맞추면 slice가 폭을 기준으로 확대해 첨탑이 위로
   잘려 나갔다 — 넓은 화면일수록 심했다. 이제 그림은 높이만큼만
   자라고, 왼쪽에 남는 자리는 스크림의 그라파이트가 덮는다(카피가
   서는 쪽이다). 2.8:1보다 넓은 화면에서는 66% 하한이 걸려 예전처럼
   폭을 채운다 — 그쪽이 빈자리를 드러내는 것보다 낫다. */
/* .bf-scene-host__plane 은 판(그림과 그 창 겹)을 담아 가라앉히는 상자다
   — 먼 판과 앞 판, 둘이다(아래 "판이 가라앉는다"). 판과 같은 자리·
   크기에 서야 하므로 같은 규칙을 받는다. 좁은 화면의 덮어쓰기도. */
.bf-scene-host__svg, .bf-scene-host__plane {
  position: absolute; right: 0; top: 0; z-index: 0;
  height: var(--bf-hero-h);
  width: clamp(66%, calc(var(--bf-hero-h) * 1440 / 780), 100%);
}
/* 무대 — 스크림과 바닥 페이드는 마스크다(2026-09-03). 두 판(먼 판·앞
   판)을 담은 상자에 mask-image 를 걸어 도시 자체를 옅게 한다. 전에는
   반투명한 바탕색을 도시 위에 덮었는데(스크림·페이드 두 겹), 바탕색
   위에 같은 바탕색을 반투명으로 얹으면 수학으로는 그대로여야 할 것이
   8비트 반올림 때문에 알파 단마다 10 과 11 사이를 오가 하늘에 1/255
   짜리 세로 띠가 생겼다 — 어두운 방에서 보인다(사용자, 2026-09-03).
   마스크는 그려진 것에만 닿는다: 하늘은 애초에 아무것도 없어 반올림할
   것이 없고, 파사드 위의 1/255 는 보이지 않는다.
   두 그라데이션은 예전 두 겹을 가시성(1 − 알파)으로 뒤집은 것이다.
   스크림 — 핸드오프대로 왼쪽 가중: 카피가 서는 왼쪽은 그라파이트로
   눌리고 오른쪽 3분의 1에서 도시가 온전히 드러난다. 기울기(96deg)와
   세 단(34·56·74%)은 핸드오프 그대로다. 다만 이 사이트의 카피는
   1200px 래퍼 안쪽에서 시작하므로 — 핸드오프는 화면 왼쪽 가장자리에서
   96px였다 — 어두운 단을 그 열까지 넓혔다.
   페이드 — 그림이 끝나는 자리에서 함께 끝난다: 히어로 바닥 위 180px
   에서 도시의 기단을 그라파이트로 녹여 페이지로 넘긴다. 자리는
   --bf-hero-h 로 잰다; 그 아래(spacer)는 아예 보이지 않는다.
   교집합(intersect)이므로 둘 다 통과한 곳만 보인다. -webkit- 짝은
   옛 사파리 몫이다. 좁은 화면은 변수 둘만 바꾼다. */
.bf-scene-host__stage {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  --bf-stage-scrim: linear-gradient(96deg, transparent 34%, rgb(0 0 0 / .26) 56%, #000 74%);
  --bf-stage-fade: linear-gradient(to bottom,
    #000 calc(var(--bf-hero-h) - 180px),
    rgb(0 0 0 / .3) calc(var(--bf-hero-h) - 97px),
    transparent calc(var(--bf-hero-h) - 25px));
  -webkit-mask-image: var(--bf-stage-scrim), var(--bf-stage-fade);
  -webkit-mask-composite: source-in;
  mask-image: var(--bf-stage-scrim), var(--bf-stage-fade);
  mask-composite: intersect;
}
/* 히어로와 첫 섹션 사이의 빈 띠 */
.bf-scene-host__spacer { height: var(--bf-scene-foot); }

/* --- 판이 가라앉는다(2026-09-03, 히어로만) -----------------------
   페이지가 올라갈 때 도시는 페이지보다 느리게 올라간다 — 곧 아래로
   가라앉는다. 판마다 속도가 다르다: 앞 판(가운데 탑·기단·그 창)은
   페이지 속도의 45%, 먼 판(능선·가장자리 탑·계단식 건물·그 창)은
   25% 만큼 뒤처진다 — 가까운 것이 더 뒤처져 판이 갈라진다(사용자,
   2026-09-03: 처음엔 먼 판을 세워 두었는데 모두 내려가는 쪽으로).
   비율은 partials/scene.php 의 data-lag 에 있고, 옮기는 것은 site.js
   다: 스크롤마다 두 판(<svg>)에 정수 픽셀의 transform 을 바로 쓴다. 소수점으로 옮기면
   1px 선이 떨린다 — 카메라 드리프트를 접은 까닭이다. 그래서 CSS 의
   scroll-timeline 은 쓰지 않는다: 거기서는 반올림할 수 없다.
   상자(.bf-scene-host__plane)는 제자리에 서서 overflow 로 안을 자르고,
   움직이는 것은 그 안의 판들이다: 상자 자체를 옮기면 자르는 틀도
   함께 내려가 내려간 판이 페이드 아래 빈 띠(spacer)에 드러난다 —
   능선을 옮기던 첫 판에서 그랬다. 한 상자의 두 판은 같은 프레임에
   같은 값을 받으므로 어긋날 수 없다.
   처음엔 상자에 상속 변수(--bf-plane-y) 하나를 주고 판이 var() 로
   받게 했다 — 깨끗해 보였지만, 상속되는 사용자 속성이 바뀌면 브라우저는
   그 아래 모든 요소의 스타일을 다시 계산한다: 도형 300여 개와 창 360여
   개, 그것도 스크롤 프레임마다. 휴대폰에서 도시가 깜빡였다(사용자,
   2026-09-04). 인라인 transform 은 그 요소 하나만 건드린다. */
.bf-scene-host__plane { overflow: hidden; }
.bf-scene-host__plane > .bf-scene-host__svg {
  right: 0; left: 0; top: 0; width: 100%; height: 100%;
  will-change: transform;   /* 값은 site.js 가 인라인으로 쓴다 */
}

/* --- 도시가 세워진다(2026-09-03, 히어로만) ---------------------
   열릴 때 한 번, 먼 데서 가까운 데로: 먼 능선(+가장자리 두 탑,
   .bf-sky__edge — 첫 단계가 허전해서, 2026-09-03) → 탑 → 기단. 아래
   섹션의 zoom-in-up 과 같은 곡선이되 길이는 1초로 늘렸고, 판 사이
   간격은 길이의 절반이다 — 처음엔 720ms 에 140ms 간격이었는데
   셋이 한꺼번에 나타나는 것으로 읽혔다(사용자, 2026-09-03). 절반
   간격이면 앞 판이 거의 다 섰을 때 다음 판이 오른다.
   마지막 화면의 사본은 그대로 선다: 선택자가 히어로의
   판(.bf-scene-host__svg)에만 닿는다.
   16px 는 SVG 안이라 사용자 단위다 — 그림과 함께 줄고 는다.
   JS 도 관찰자도 없다: CSS 애니메이션은 요소가 그려지는 순간
   시작하므로 섹션의 등장과 달리 숨은 채 남을 길이 없다. */
.bf-scene-host { --bf-sky-dur: 1000ms; --bf-sky-step: 500ms; }
@keyframes bfSkyRise { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.bf-scene-host__svg :is(.bf-sky__far, .bf-sky__edge, .bf-sky__towers, .bf-sky__podium) {
  animation: bfSkyRise var(--bf-sky-dur) var(--bf-reveal-ease) both;
}
.bf-scene-host__svg .bf-sky__towers { animation-delay: var(--bf-sky-step); }
.bf-scene-host__svg .bf-sky__podium { animation-delay: calc(2 * var(--bf-sky-step)); }

/* --- 창이 켜진다(2026-09-03, 히어로만) -------------------------
   밤의 여의도가 불을 켠다. 창은 그림에 없다 — lib/common.php 의
   bf_sky_lights() 가 층선×멀리언 격자에서 칸을 계산하고 고정 씨앗으로
   뽑아 차례를 섞는다. 겹은 별도 <svg> 다(까닭은 partials/scene.php
   끝에). will-change 로 제 겹을 갖게 해 다시 그려지는 것이 창뿐이게
   한다.
   파도다(사용자, 2026-09-03): 하나씩 켜져 다 켜지고, 하나씩 꺼져 다
   꺼진다. 한 바퀴 37초 = 켜기 15초(PHP BF_SKY_FILL) → 다 켜진 채 4초
   → 끄기 15초 → 캄캄한 채 3초. 창 하나는 제 시각에 켜져 19초(51.4%)
   뒤에 꺼지므로 켜진 차례가 곧 꺼지는 차례다. 켜짐·꺼짐은
   0.3초(0.8%) — 찰칵이면 깜빡임으로 읽힌다. 켜기 + 19초 ≤ 37초여야
   다음 바퀴와 겹치지 않는다. 켜기 10 → 15초는 사용자 지시(2026-09-04):
   창이 두 배로 늘어 간격이 너무 촘촘해졌다.
   도시가 다 선 뒤(2×간격+길이)에 제 차례를 기다린다 — 그 전엔 캄캄하다
   (fill-mode 없음: 지연 동안은 기본값 0 이다). 창이 먼저 떠 있고
   건물이 뒤에 오는 것은 이상하다(사용자, 2026-09-03).
   prefers-reduced-motion 은 보지 않는다(사용자 결정, 2026-09-03). */
.bf-scene-host { --bf-win-cycle: 37s; }
@keyframes bfWindow { 0% { fill-opacity: 0; } 0.8% { fill-opacity: .7; } 51.4% { fill-opacity: .7; } 52.2% { fill-opacity: 0; } 100% { fill-opacity: 0; } }
.bf-scene-host__svg--lights { will-change: transform; }
/* 스크롤 중에는 창과 항공등이 멈춘다(2026-09-04). fill-opacity 와
   opacity 는 합성기가 아니라 페인터의 일이라, 창 하나가 켜지는 매
   프레임 창 겹이 통째로 다시 그려진다 — 가만히 있을 때는 그것만이
   전부여서 괜찮지만, 스크롤 중에는 네 겹을 옮기는 일과 겹쳐 휴대폰
   GPU 가 밀리고 타일이 깜빡인다. 스크롤이 멎은 뒤 160ms 에 다시
   돈다(site.js 가 클래스를 붙였다 뗀다). 멈춘 동안 진행은 보존되므로
   물결은 멈춘 자리에서 이어진다. 스크롤하는 사람이 창 하나가 켜지는
   것을 보고 있지는 않다. */
.bf-scene-host__svg--lights.is-scrolling :is(polygon, circle) { animation-play-state: paused; }
.bf-scene-host__svg--lights polygon {
  fill-opacity: 0;
  animation: bfWindow var(--bf-win-cycle) linear infinite;
  animation-delay: calc(2 * var(--bf-sky-step) + var(--bf-sky-dur) + var(--bf-win-on));
}

/* --- 항공등(2026-09-03, 히어로만) -------------------------------
   첨탑 꼭대기의 흰 점이 2초에 한 번 켜진다 — 높은 건물의 장애등이다.
   둘은 0.7초 어긋나 함께 깜빡이지 않는다. 둘레의 무리는 같은 박자로
   숨 쉰다. 도시가 다 설 때까지는 보이지 않는다: 깜빡임은 opacity 를,
   문은 fill-opacity 를 쓴다(같은 속성에 둘을 걸면 뒤엣것만 남는다).
   가장 낮은 밝기는 0 이 아니다 — 꺼진 등도 등이다. */
@keyframes bfBeacon { 0%, 35%, 65%, 100% { opacity: .12; } 50% { opacity: 1; } }
@keyframes bfSkyOn { from { fill-opacity: 0; } to { fill-opacity: 1; } }
.bf-sky__beacons circle {
  fill-opacity: 0;
  animation: bfBeacon 2s ease-in-out infinite, bfSkyOn 600ms var(--bf-reveal-ease) both;
  animation-delay: var(--bf-beacon-phase), calc(2 * var(--bf-sky-step) + var(--bf-sky-dur));
}

/* 첫 화면은 머리띠와 히어로가 정확히 나눠 갖는다(2026-08-13):
   상한을 두지 않으므로 넓고 높은 화면에서도 도시가 화면 높이만큼
   자란다 — 그림판이 이 상자를 그대로 따른다. */
.bf-hero {
  position: relative; z-index: 2;
  height: var(--bf-hero-h);
  display: flex; flex-direction: column;
}
/* 카피는 왼쪽 열에 선다(2026-08-13, 핸드오프 구성): 도시는
   오른쪽에서 온전히 보이고 활자는 어두운 쪽에 앉는다. 열의 왼쪽
   모서리는 사이트의 1200px 래퍼와 같다 — 헤드라인이 머리띠의
   로고와, 아래 모든 섹션과 한 줄에 선다. */
.bf-hero__in {
  flex: 1; display: flex; flex-direction: column; align-items: flex-start; justify-content: center;
  text-align: left;
  width: 100%; max-width: 1200px; margin: 0 auto; padding: 24px 32px 72px;
}
/* --- 히어로가 왼쪽에서 들어온다(2026-09-04, 사용자) --------------
   태그라인부터 개최 정보까지, 히어로의 블록이 차례로 왼쪽에서
   미끄러져 들어온다. 아래 섹션의 등장(zoom-in-up)과는 다른 몸짓이다:
   저쪽은 스크롤을 따라 아래에서 떠오르고, 여기는 첫 화면이라 기다릴
   스크롤이 없다.
   차례는 DOM 순서 그대로다 — 자식 목록을 손으로 적지 않으므로 블록을
   넣고 빼도 어긋나지 않는다. 도시가 다 서기까지 2초, 글은 1.4초에
   끝난다 — 글이 먼저 자리를 잡고 도시가 뒤따라 선다.
   관찰자도 JS 도 없다: CSS 애니메이션은 요소가 그려지는 순간 시작하고
   both 로 끝 상태를 지키므로, 스크립트가 없어도 글이 숨지 않는다. */
.bf-hero__in { --bf-hero-step: 90ms; }
@keyframes bfHeroIn { from { opacity: 0; transform: translateX(-32px); } to { opacity: 1; transform: none; } }
/* 표제 상자는 통째로가 아니라 세 무리로 들어온다(2026-09-06, 사용자):
   표제 → 화살표 줄 → 결론. 그림(<svg>)과 글자(.bf-title__text) 어느
   쪽이 보이든 무리는 .bf-title__part 셋이다. 상자 자체는 움직이지
   않는다 — 움직이면 무리가 두 번 들어온다. 뒤따르는 형제(단추, 개최
   정보)는 그 세 걸음 뒤에서 잇는다. <g> 안의 -32px 는 사용자 단위라
   글자의 픽셀과 한 단위쯤 다르지만 눈으로는 같다. */
.bf-hero__in > * { animation: bfHeroIn 700ms var(--bf-reveal-ease) both; }
.bf-hero__in > .bf-title { animation: none; }
.bf-title__part { animation: bfHeroIn 700ms var(--bf-reveal-ease) both; }
.bf-title__part:nth-child(1) { animation-delay: 150ms; }
.bf-title__part:nth-child(2) { animation-delay: calc(150ms + 1 * var(--bf-hero-step)); }
.bf-title__part:nth-child(3) { animation-delay: calc(150ms + 2 * var(--bf-hero-step)); }
.bf-hero__in > :nth-child(2) { animation-delay: calc(150ms + 3 * var(--bf-hero-step)); }
.bf-hero__in > :nth-child(3) { animation-delay: calc(150ms + 4 * var(--bf-hero-step)); }
.bf-hero__in > :nth-child(n+4) { animation-delay: calc(150ms + 5 * var(--bf-hero-step)); }

/* --- 표제 상자(2026-09-06) --------------------------------------
   디자이너의 벡터(.bf-title__art)와 살아 있는 글자(.bf-title__text)가
   한 상자에 있다. 한국어판 넓은 화면(--art)에서는 그림이 서고 글자는
   화면 밖으로 밀린다 — 없애지 않는다: 그것이 <h1> 이고, 검색과 읽기
   도구는 그것을 읽는다(sr-only 꼴: 한 픽셀로 잘라 두되 문서에는 둔다).
   좁은 화면에서도 그림이다(2026-09-06, 사용자가 휴대폰에서 보고 판단하기로).
   그림은 열 폭을 따라 줄어들되 480px 아래로는 내려가지 않는다(사용자,
   2026-09-06; 처음엔 표제 글자 56px 에 해당하는 330 이었다) — 그
   아래에서는 열을 다 쓴다. 휴대폰에서 화살표 줄은 약 5px, 결론은 10px
   가 된다: 읽히지 않으면 그때 글자판(.bf-title__text)으로 돌아간다.
   영문판에는 --art 가 없어 늘 글자다 — 영문 아트보드가 아직 없다.
   그림의 폭은 지금 표제 크기에 맞춘 것이다(사용자: "지금 크기로"):
   1440px 에서 표제 글자가 약 100px 이고, 아트보드의 글자는 94 단위이므로
   그림 한 단위 ≈ 1px, 곧 623px(선 끝에서 선 끝까지). 표제 크기가
   7.1vw 로 크므로 그림도 같은 비율로 — 623/1440 ≈ 43.3vw — 따라가고,
   표제의 상한 104px 에 맞춰 647px 에서 멈춘다. */
.bf-title { width: 100%; }
/* 살아 있는 글자로 짠 같은 디자인(2026-09-06). 아트보드의 치수를 1440px
   에서의 픽셀로 옮긴 것이다(한 단위 ≈ 1px): 선 위 23·아래 28, 표제 다음
   19, 화살표 줄 다음 12; 화살표 줄 대문자 높이 10 → 14px, 결론 19 →
   20px; 선은 글 폭만큼(width: fit-content). 표제 크기는 한국어 규칙이
   이미 아트보드와 맞고, 영문 표제도 같은 비율로 내렸다(전에는 8.2vw).
   글자는 글자라 자간까지 벡터와 같을 수는 없다 — 그것이 벡터를 쓰는
   까닭이고, 이 규칙은 벡터가 없는 자리(영문판, 좁은 화면)를 메운다. */
.bf-title__text {
  width: fit-content; max-width: 100%;
  padding: 20px 0 24px;
  border-top: 1px solid var(--bf-hero-line); border-bottom: 1px solid var(--bf-hero-line);
}
.bf-title__art { display: block; width: min(100%, max(480px, 43.3vw), 647px); height: auto; }
.bf-title--art .bf-title__text {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
/* 그림의 색 — 아트보드 그대로(tokens.css). 선은 1 단위, 화살표 줄은 2. */
.bf-title__ink { fill: var(--bf-fg); }
.bf-title__accent { fill: var(--bf-cyan); }
.bf-title__sub { fill: var(--bf-hero-sub); }
.bf-title__rule { stroke: var(--bf-hero-line); stroke-width: 1; }
.bf-title__arrow { stroke: var(--bf-cyan); stroke-width: 2; }

/* 폭 제한은 도시로 넘어가지 않게 하는 것이다. 상한은 em 이다 —
   ch 로 두면 글꼴을 탄다(2026-09-04): 1ch 는 글자 폭이 아니라 숫자
   0 의 폭이고, Pretendard 에서는 0.70em 인데 대체 글꼴에서는 0.56em
   이라 12ch 가 986px 에서 789px 로 줄었다. 표제(≈7.8em)가 그 안에
   들어가지 못해, 글꼴이 오기 전에는 두 줄로 접혔다가 오면 한 줄로
   펴졌다 — 그 한 줄이 117px 이라 페이지가 통째로 뛰었다. 8.5em 은
   지금 Pretendard 가 서는 폭 그대로이고(986px), 대체 글꼴의 표제도
   여유 있게 담는다. 한글 표제가 ch 에서 데인 이야기는 아래에 있다. */
.bf-hero__h1--en {
  font-size: clamp(56px, 7.1vw, 104px); font-weight: 900;
  letter-spacing: var(--bf-track-display); line-height: 1.0;
  margin: 0; max-width: 8.5em;
}
/* 한글 표제는 두 줄이다(2026-09-04, 디자인 시안): 첫 줄이 '기관,',
   둘째 줄이 '온체인 위에 서다'. 줄바꿈은 bf_hero_title 이 넣으므로
   폭 상한은 두지 않는다 — 9ch 로 묶였던 시절에는 글자 아홉 자가
   아니라 숫자 0 아홉 개의 폭(≈5em)이어서 엉뚱한 자리에서 접혔다.
   둘째 줄은 104px에서 ≈880px, 1136px 열 안에 넉넉히 선다.
   행간은 1 — 시안의 조판이 그만큼 붙어 있다. */
.bf-hero__h1--ko {
  font-size: clamp(56px, 7.1vw, 104px); font-weight: 900;
  letter-spacing: 0; line-height: 1.05;
  margin: 0; max-width: none; word-break: keep-all;
}
/* 행간은 여기서 못 박는다 — 짧은 두어 줄짜리 표제구다. 언어별
   기본값(라틴 1.5 / 한글 1.7)에 맡기면 두 언어판의 같은 문장이
   서로 다른 간격으로 앉는다. */
/* 표제 안의 한 낱말 — 화면에서 시안이 나오는 두 자리 중 하나다.
   글자 굵기도 크기도 그대로다: 색만 바뀐다. */
.bf-hero__hl { color: var(--bf-cyan); }   /* 마지막 띠의 제목도 같은 낱말에 이 클래스를 쓴다(2026-09-06) */
/* 'FROM ENTRY —→ TO EXECUTION' — 라틴 대문자에 넓은 자간. 한글이
   들어올 자리가 아니므로 :lang(ko) 예외가 필요 없다. */
/* 크기와 간격은 아트보드의 비례다(2026-09-06, 사용자: 영문판을
   한글판 벡터에 맞춰 달라). 재는 기준은 표제다: 아트보드의
   표제는 한글 살 93.6 ≈ 130 단위이고, 그 안에서 화살표 줄은 14.15,
   결론 줄은 20.8 단위다. 우리 표제는 104px 이므로 0.8 을 곱해
   11.5 와 16.5 가 된다 — 예전에는 아트보드의 절대값(14·20)을 그대로
   썼고, 그리면 표제가 작은 만큼 아랫글이 커 보인다.
   행간은 1 로 못 박는다: 아트보드의 간격은 살과 살 사이이고,
   글자에는 살 밖에 글꼴의 여백이 붙어 오기 때문이다 — 그 여백만큼
   밀어낸 값이 아래의 margin 이다(표제 다음 17 → 2, 화살표 줄 다음
   12.3 → 5). */
.bf-hero__track {
  display: flex; align-items: center; gap: 6px;
  margin-top: 2px; line-height: 1;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--bf-fg);
}
/* 선 하나와 삼각형 하나. 길이는 디자인의 비례를 따른다(선 76 : 머리 8,
   표제 아래 작은 글자의 대문자 높이 기준). flex: none 이 없으면 좁은
   화면에서 선이 먼저 줄어 화살표가 뭉개진다. */
.bf-hero__arrow {
  flex: none; position: relative;
  width: 61px; height: 2px; background: var(--bf-cyan);
  /* 머리가 선 밖으로 7px 나오므로, 다음 낱말까지의 10px 는
     이 여백이 만든다(아트보드 12.5 × 0.8). */
  margin-right: 11px;
}
.bf-hero__arrow::after {
  content: ''; position: absolute; right: -7px; top: 50%;
  border: 3.5px solid transparent; border-left: 7px solid var(--bf-cyan);
  transform: translateY(-50%);
}
/* 결론 한 줄. 표제보다 어둡지만 본문보다 밝다 — 아트보드의 회색
   그대로다(2026-09-06, 전에는 전경색을 바탕 쪽으로 당긴 값). */
.bf-hero__claim {
  margin-top: 5px;
  font-size: 16.5px; font-weight: 400; line-height: 1.15;
  color: var(--bf-hero-sub);   /* 아트보드의 회색, tokens.css */
}
/* 표제 그림 아래 여백은 60 — 그림의 viewBox 가 아랫선 밑으로 10 을 더 갖고
   있어 눈에는 70 으로 읽힌다(2026-09-06, 사용자: 조금 더). */
.bf-hero__cta { display: flex; gap: 16px; margin-top: 60px; justify-content: flex-start; }
.bf-hero__venue { font-size: 17.5px; font-weight: 500; color: var(--bf-fg-muted); margin-top: 36px; font-variant-numeric: tabular-nums; }
/* 조각은 통째로 움직인다 — 줄바꿈은 조각과 조각 사이에서만 일어난다.
   히어로와 마지막 화면이 함께 쓰므로 이름에 자리를 넣지 않는다. */
.bf-metaPart { white-space: nowrap; color: var(--bf-fg); }

/* --- 섹션 심(seam) — 진입 시 1회 발광하는 헤어라인 --------- */
.bf-seam { position: relative; height: 1px; background: var(--bf-rule); }
.bf-seam svg { position: absolute; left: 0; top: -1px; width: 100%; height: 3px; overflow: visible; }

/* --- 콘텐츠 섹션 패턴: 고정 인덱스 --------------------------
   모든 콘텐츠 섹션은 2열 그리드다. 왼쪽 열이 번호·라벨·제목·리드를
   지고 화면에 붙어 있고, 오른쪽 열만 흐른다. 페이지를 관통하는
   연속 수직 레일은 없다 — 열 자체가 구조다. 레일이 남는 곳은
   프로그램의 시간 스파인 하나뿐이다(.bf-agenda).
   근거: docs/concept/new-content-design (패턴 6b). */
.bf-wrap { max-width: 1200px; margin: 0 auto; padding: 0 32px; }

/* 섹션과 섹션 사이에는 선을 긋지 않는다(2026-09-03). 가르는 일은
   위아래 여백이 한다 — 선까지 있으면 한 페이지가 아니라 쌓아 올린
   칸들로 읽힌다. 올해의 것은 선이 아니라 바탕 한 겹으로 가른다
   (.bf-section--accent). */
/* 올해의 것만 서는 띠 — 페이지에서 한 겹 떠 있다(2026-09-03). 새 색이
   아니라 아주르를 묽게 깐 것이고, 강조 카드가 쓰는 그 색이다.
   20%인 이유는 잰 값이다: 12%는 바탕과의 밝기 차이가 3.8 로 카드
   표면만큼도 보이지 않고, 32%는 설명 글이 5.81 까지 내려간다.
   20%에서 차이는 6.8, 설명 글은 6.53 이다.
   띠는 폭을 다 쓴다 — 안쪽만 칠하면 띠가 아니라 상자가 된다. */
.bf-section--accent { background: color-mix(in srgb, var(--bf-600) 20%, transparent); }
/* 아직 비어 있는 자리. 내용이 들어오면 이 줄을 지운다 — 그때는
   높이를 내용이 정한다. */
.bf-body--placeholder { min-height: 260px; }
.bf-section__inner {
  max-width: 1200px; margin: 0 auto; padding: 88px 32px 96px;
  display: grid; grid-template-columns: 300px 1fr; gap: 80px;
  align-items: start;   /* 필수: 늘어난 자식은 sticky가 되지 않는다 */
}
/* 그리드 자식의 자동 최소 크기는 내용의 min-content다. 넓은 표가
   그 안에 있으면 열이 컨테이너보다 넓게 벌어져 페이지가 가로로
   밀린다 — 0으로 눌러야 안에서 스크롤된다. */
.bf-section__inner > * { min-width: 0; }

/* 넓은 섹션 — 인덱스가 위로 올라가고 본문이 컨테이너 폭을 다 쓴다.
   비교표처럼 좁은 열에 들어갈 수 없는 것에만 쓴다. */
.bf-section--wide .bf-section__inner { grid-template-columns: 1fr; gap: 36px; }
.bf-section--wide .bf-index { position: static; }

.bf-index { position: sticky; top: 88px; }   /* 64px 헤더 + 24px */
.bf-index__meta { display: flex; align-items: baseline; gap: 14px; }
.bf-index__num {
  font-size: 44px; font-weight: 800; line-height: 1;
  color: var(--bf-700);            /* 물러난 색 — 내용이 아니라 구조다 */
  font-variant-numeric: tabular-nums;
}
.bf-index__label {
  font-size: var(--bf-size-body); font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase;       /* 라틴 전용 */
  color: var(--bf-fg-muted);
}
.bf-index__label:lang(ko) { letter-spacing: 0; text-transform: none; }
.bf-index__title {
  font-size: 36px; font-weight: 800; letter-spacing: var(--bf-track-display);
  line-height: 1.15; margin: 24px 0 0; word-break: keep-all;
}
:lang(ko) .bf-index__title { letter-spacing: 0; line-height: 1.3; }
.bf-index__lead {
  font-size: 15.5px; line-height: 1.6; color: var(--bf-fg-muted);
  margin: 18px 0 0; text-wrap: pretty; word-break: keep-all;
}
:lang(ko) .bf-index__lead { line-height: 1.7; }

/* --- 섹션 머리 (메인 페이지) --------------------------------
   2026-08-18: 번호가 사라지고 머리가 가운데로 섰다. 왼쪽에 붙어
   따라오던 인덱스(.bf-index)는 후원 페이지에만 남는다 — 그 페이지는
   손대지 않기로 했으므로 옛 규칙을 그대로 둔다.
   가운데 정렬은 머리까지다. 그 아래 본문은 컨테이너 폭을 다 쓴다. */
.bf-section--stack .bf-section__inner { grid-template-columns: 1fr; gap: 0; }
.bf-head { text-align: center; margin-bottom: 56px; }
/* 머리글만 읽는 폭으로 묶는다. 한 줄이 1136px 이면 눈이 되돌아올
   자리를 잃는다. */
.bf-head__title {
  font-size: 64px; font-weight: 800; letter-spacing: var(--bf-track-display);
  line-height: 1.15; margin: 0 auto; max-width: 820px; word-break: keep-all;
}
:lang(ko) .bf-head__title { letter-spacing: 0; line-height: 1.3; }
.bf-head__lead {
  font-size: 20px; line-height: 1.6; color: var(--bf-fg-muted);
  margin: 16px auto 0; max-width: 640px; text-wrap: pretty; word-break: keep-all;
}
:lang(ko) .bf-head__lead { line-height: 1.7; }
/* 본문은 폭을 다 쓴다 — 읽는 폭으로 묶어 두던 제한을 푼다. */
.bf-section--stack .bf-body .bf-lead { max-width: none; }
/* 다만 머리 바로 아래, 본문 맨 앞뒤에 홀로 선 리드 문단은 다시
   가운데로 묶는다(2026-09-04) — 가운데 선 .bf-head 를 그대로
   잇는다. 자식 결합자(>)로 좁혀 카드나 소제목 옆에 딸린 .bf-lead
   (변화의 지점, 장소 리드)는 건드리지 않는다 — 그것들은 왼쪽
   정렬된 이웃과 짝이라 혼자 가운데로 옮기면 어긋난다. */
.bf-section--stack .bf-body > .bf-lead { text-align: center; margin: 0 auto; max-width: 740px; }
/* 다만 신청 서식은 늘리지 않는다. 입력칸이 560px 을 넘으면 글자를
   따라 눈이 가로로 끌려다녀 오히려 쓰기 어렵다 — 대신 가운데로
   옮겨 가운데 선 머리와 축을 맞춘다. */
.bf-section--stack .bf-body .bf-form { margin-inline: auto; }

/* --- 섹션 공통 --------------------------------------------- */
.bf-h2 { font-size: 44px; font-weight: 800; letter-spacing: var(--bf-track-display); line-height: 1.12; margin: 0; word-break: keep-all; }
:lang(ko) .bf-h2 { letter-spacing: 0; }

/* --- 포지셔닝 ---------------------------------------------- */
.bf-pos__body { font-size: 17px; line-height: 1.6; color: var(--bf-fg-muted); margin: 20px 0 0; max-width: 620px; text-wrap: pretty; word-break: keep-all; }
.bf-pos__axis { width: 100%; height: auto; display: block; margin: 4px 0 20px; }
/* 참가 기관 유형 — 100% 막대. .bf-who 는 막대와 수치를 한 덩어리로
   묶어 함께 떠오르게 하는 상자다(등장 대상). 제 여백은 없다 — 위의
   소제목과의 사이는 막대가 제 margin 으로 잡는다. 예전 섹션의
   __head/__h3/__cap 은 쓰이지 않아 걷었다(2026-09-04). */
/* 막대와 그 아래 수치는 같은 폭 배분을 쓴다 — 두 줄의 flex 설정이
   똑같아야 구간과 수치가 어긋나지 않는다. 폭이 곧 값이므로 수치
   위에 장식 선은 없다. */
.bf-who__bar { display: flex; height: 22px; border-radius: var(--bf-radius-1); overflow: hidden; margin-top: 20px; gap: 2px; }
.bf-who__legend { display: flex; gap: 2px; margin-top: 16px; }
.bf-who__cell { width: var(--w); min-width: 0; padding-right: 14px; }
.bf-who__val { font-size: 26px; font-weight: 800; font-variant-numeric: tabular-nums; }
.bf-who__lbl { font-size: 16px; font-weight: 500; color: var(--bf-fg-muted); margin-top: 6px; text-wrap: pretty; word-break: keep-all; }

/* --- 프로그램 시간 스파인 -----------------------------------
   사이트에서 수직선이 남는 유일한 자리. 왼쪽 거터의 오른쪽
   테두리가 끊기지 않는 레일이 되고, 시각은 거터 안에, 점은
   레일 위에, 세션은 그 오른쪽에 온다. */
/* 거터는 시각 한 줄에 딱 맞는 너비다 — 날짜가 아니라 시각이 서므로
   150px는 왼쪽에 빈 자리를 남겼다 */
.bf-agenda__row { display: grid; grid-template-columns: 64px 1fr; }
/* 시각과 점과 설명이 한 높이에서 만난다 — 셋 다 줄의 세로 가운데다 */
.bf-agenda__rail {
  position: relative; border-right: 1px solid var(--bf-700);
  text-align: left; padding-right: 12px;
  display: flex; align-items: center;
}
/* 첫 줄 위에는 선을 긋지 않는다 — 제목이 이미 시작을 알린다 */
.bf-agenda__row:first-child .bf-row__body { border-top: 0; }

/* --- 프로그램(어젠다) 행 ----------------------------------- */
.bf-row__time { font-size: 14px; font-variant-numeric: tabular-nums; padding: 0; }
.bf-row__time--major { font-weight: 600; color: var(--bf-fg); }
.bf-row__time--minor { font-weight: 500; color: var(--bf-fg-muted); }  /* faint 금지 — 대비 미달 */
/* 두 점은 크기가 같고 색으로만 갈린다. 작은 점은 지름이 홀수 픽셀도
   되지 못해 레일 위에서 반 픽셀씩 어긋나 보였다 — 지름이 작을수록
   그 반 픽셀이 크게 보인다. 위계는 색과 글자 굵기가 이미 지고 있다.
   -5px = 지름의 절반(4.5) + 레일 두께의 절반(0.5). */
.bf-row__dot {
  position: absolute; border-radius: 50%;
  top: 50%; transform: translateY(-50%);
  width: 9px; height: 9px; right: -5px;
}
.bf-row__dot--major { background: var(--bf-100); }
.bf-row__dot--minor { background: var(--bf-600); }
.bf-row__body {
  border-top: var(--bf-border);
  padding: 18px 20px 18px 32px;
  display: grid; grid-template-columns: 1fr auto; gap: 20px; align-items: center;
  transition: background var(--bf-dur-1) var(--bf-ease);
}
.bf-row__body:hover { background: var(--bf-surface); }
.bf-row__title { font-size: 17px; line-height: 1.4; word-break: keep-all; }
.bf-row__title--major { font-weight: 600; color: var(--bf-fg); }
.bf-row__title--minor { font-weight: 500; color: var(--bf-fg-muted); }
.bf-row__note { font-size: 13.5px; line-height: 1.55; color: var(--bf-fg-muted); margin-top: 4px; max-width: 620px; text-wrap: pretty; word-break: keep-all; }
.bf-chip {
  font-size: 12.5px; font-weight: 500; color: var(--bf-fg-muted);
  background: var(--bf-surface); border: var(--bf-border); border-radius: var(--bf-radius-1);
  padding: 3px 9px; white-space: nowrap;
}

/* --- 연사 --------------------------------------------------
   2026-08-18: 카드가 사라졌다. 남는 것은 원과 그 아래 두 줄뿐이고,
   색 필터도 걷었다 — 얼굴은 실제 피부색으로 선다. 두 줄의 띠가
   왼쪽으로 흐르고, 가리키면 그 줄만 멈춘다. */
.bf-section--rails .bf-section__inner { padding-bottom: 36px; }
/* 띠는 사이트 폭 안에 머문다(2026-08-18) — 창 끝까지 늘리지 않는다.
   폭이 제목과 같은 자리에서 시작하고 끝나야 섹션이 한 덩어리로 읽힌다.
   양 끝의 녹아 사라짐은 .bf-rail 의 마스크가 맡는다. */
.bf-rails {
  --bf-rail-photo: 130px;
  --bf-rail-item: 168px;
  --bf-rail-gap: 28px;
  max-width: 1200px; margin-inline: auto; padding-inline: 32px;
  display: flex; flex-direction: column; gap: 26px; padding-bottom: 92px;
}
/* 양 끝은 마스크로 녹는다 — 반쯤 잘린 칸이 가장자리에서 갑자기
   끝나면 띠가 아니라 사고로 보인다.
   곧은 기울기는 밝은 것을 늦게 놓아 준다. 흰 판이 걸리면 로고가
   끝난 뒤의 빈 여백이 흰 띠로 남는다 — 앞을 가파르게 눌러 그것부터
   지운다. 폭은 담긴 것이 정한다(--bf-rail-fade): 배경이 비치는
   연사 원은 좁아도 되지만, 흰 판은 판 하나가 삼켜질 만큼 필요하다.
   세로 여백은 판 밖으로 나가는 것(연사 원의 테두리) 자리다 —
   비우지 않으면 첫 줄의 윗변이 잘린다. */
.bf-rail {
  --bf-rail-fade: 2.5%;
  position: relative; overflow: hidden; padding-block: var(--bf-rail-bleed, 4px);
  -webkit-mask-image: linear-gradient(to right,
    transparent 0,
    rgba(0, 0, 0, .45) calc(var(--bf-rail-fade) * .3),
    rgba(0, 0, 0, .85) calc(var(--bf-rail-fade) * .62),
    #000 var(--bf-rail-fade),
    #000 calc(100% - var(--bf-rail-fade)),
    rgba(0, 0, 0, .85) calc(100% - var(--bf-rail-fade) * .62),
    rgba(0, 0, 0, .45) calc(100% - var(--bf-rail-fade) * .3),
    transparent 100%);
  mask-image: linear-gradient(to right,
    transparent 0,
    rgba(0, 0, 0, .45) calc(var(--bf-rail-fade) * .3),
    rgba(0, 0, 0, .85) calc(var(--bf-rail-fade) * .62),
    #000 var(--bf-rail-fade),
    #000 calc(100% - var(--bf-rail-fade)),
    rgba(0, 0, 0, .85) calc(100% - var(--bf-rail-fade) * .62),
    rgba(0, 0, 0, .45) calc(100% - var(--bf-rail-fade) * .3),
    transparent 100%);
}
/* 흰 판은 판 하나가 통째로 삼켜져야 흰 띠가 남지 않는다. */
.bf-rails--logos .bf-rail { --bf-rail-fade: 8%; }
.bf-rail__track { display: flex; width: max-content; animation: bf-rail var(--bf-rail-dur, 80s) linear infinite; }
/* 2026-08-18: 한 덩이의 줄들은 한 판이다 — 함께 서고 함께 밀린다.
   미는 동안과 미끄러지는 동안은 클래스가 세운다 — 손가락에는 가리킴이
   없기 때문이다. */
.bf-rails.is-dragging .bf-rail__track {
  animation-play-state: paused;
  /* 끄는 동안 합성 층을 세워 둔다 — 빠른 손짓에서 층을 그때그때
     다시 세우면 떨린다. 늘 켜 두지는 않는다: 층은 GPU 메모리다. */
  will-change: translate;
}
/* 가리켜서 서는 것은 진짜 포인터가 있는 장치에게만 준다.
   터치스크린에서는 :hover 가 한 번 붙으면 다른 곳을 누를 때까지
   떨어지지 않는다 — 한 번 건드린 띠가 영영 멈춰 있게 된다.
   손가락과 마우스를 함께 쓰는 노트북은 이 질의에 '있다'고 답하므로
   그것만으로는 모자란다. 그래서 손가락이 한 번이라도 닿은 덩이에는
   스크립트가 .is-touch 를 붙이고, 그때부터 가리킴은 세우지 않는다. */
@media (hover: hover) and (pointer: fine) {
  .bf-rails:not(.is-touch):hover .bf-rail__track { animation-play-state: paused; }
}
/* 세로 스크롤은 페이지에 주고 가로만 가져온다 — 이 한 줄이 없으면
   손가락으로 띠를 밀 때 브라우저가 먼저 페이지를 움직여 버린다. */
.bf-rails { touch-action: pan-y; cursor: grab; }
.bf-rails.is-dragging { cursor: grabbing; }
/* 미는 동안 글자가 잡히면 끌기가 글 선택으로 새어 나간다 */
.bf-rails.is-dragging, .bf-rails.is-dragging * { user-select: none; }
/* 초상과 로고는 그 자체가 끌 손잡이다 — 브라우저의 그림 끌기를 끈다 */
.bf-rail img { -webkit-user-drag: none; user-select: none; }
.bf-rail__group { display: flex; }
/* 지그재그 — 어긋남이 줄마다 쌓인다: 0, 35%, 70% …
   줄들이 같은 속도로 함께 움직이므로 어긋나 있지 않으면 격자처럼
   뻣뻣해 보인다. 절반이 아니라 35%인 이유는 세 줄일 때다 — 절반씩
   주면 셋째 줄이 100%, 곧 제자리가 되어 첫 줄과 겹친다.
   왼쪽으로만 당긴다: 오른쪽으로 밀면 줄의 머리가 빈자리로 드러난다. */
.bf-rail__track {
  margin-left: calc((var(--bf-rail-item) + var(--bf-rail-gap)) * -0.35 * var(--bf-rail-i, 0));
}
/* 미는 거리는 딱 한 벌 — 트랙이 몇 벌이든 -100%/벌수 다. */
@keyframes bf-rail {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-100% / var(--bf-rail-copies, 2)), 0, 0); }
}

/* 칸 사이는 gap 이 아니라 각 칸의 오른쪽 여백이다. gap 이면 두
   묶음 사이만 간격이 하나 모자라 미는 거리가 맞지 않는다. */
.bf-rail__group > * { flex: 0 0 auto; margin-right: var(--bf-rail-gap); }
.bf-speaker { width: var(--bf-rail-item); text-align: center; }
/* 판의 색이 원 뒤에 남아 사진이 없을 때의 바닥이 된다. 테두리는
   사이트의 1px 구분선이다 — 어두운 배경의 초상이 페이지에 녹아
   없어지지 않게 하되, 아주르로 신호를 보내지는 않는다. */
.bf-speaker__photo {
  position: relative; width: var(--bf-rail-photo); height: var(--bf-rail-photo);
  margin: 0 auto; overflow: hidden; border-radius: 50%;
  background: color-mix(in srgb, var(--bf-600) 10%, var(--bf-surface-hi));
  border: var(--bf-border);
}
.bf-speaker__photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.bf-speaker__initials {   /* 사진 없는 연사의 폴백 */
  position: absolute; inset: 0; display: grid; place-content: center;
  font-size: 34px; font-weight: 800; color: var(--bf-fg-faint);
}
.bf-speaker__name { font-size: 15px; font-weight: 700; margin-top: 13px; word-break: keep-all; }
/* 가운뎃점은 직함과 같은 톤이다 — 구분자가 글보다 튀면 안 된다 */
.bf-speaker__meta { font-size: 12.5px; margin-top: 6px; line-height: 1.45; word-break: keep-all; color: var(--bf-fg-muted); }
.bf-speaker__role { color: var(--bf-fg-muted); }
.bf-speaker__org { font-weight: 600; color: var(--bf-200); }  /* 아주르 소속 — 기관 행사라는 신호 */

/* 로고 띠 — 뼈대는 연사와 같고 판만 로고의 것이다. 판 크기는
   그대로 176x78 이다: 남의 마크를 줄이면 읽히지 않는다. 판 밖으로
   나가는 것이 없으므로 세로 여백은 두지 않는다. */
.bf-rails--logos {
  --bf-rail-item: 176px;
  --bf-rail-gap: 16px;
  --bf-rail-bleed: 0px;
  gap: 16px; padding-bottom: 44px;
}
.bf-rails--logos:last-child { padding-bottom: 92px; }
/* 줄 수가 다른 두 벌이 함께 찍혀 있다 — 화면 폭이 하나를 고른다.
   서버는 창 폭을 모르고, 스크립트로 다시 나누면 스크립트 없는
   화면에서 띠가 무너지므로 CSS 가 고르게 한다. */
.bf-rails--narrow { display: none; }
/* 띠 안에서는 로고가 없는 칸도 같은 크기여야 한다 — 칸마다 폭이
   다르면 한 벌의 폭을 셀 수 없어 벌 수 계산이 어긋난다. */
.bf-rails .bf-rail__group > .bf-mark {
  width: var(--bf-rail-item); height: 78px;
  display: grid; place-items: center; text-align: center;
}
/* 묶음 이름도 섹션 머리와 같은 축에 선다 — 가운데다 */

/* 움직임을 끈 사람에게는 띠가 그냥 멈춘 줄이 된다 — 화면 밖 사람은
   영영 못 본다. 손으로 밀 수 있게 열어 주고 뒤 묶음은 치운다.
   애니메이션 자체는 위쪽 전역 규칙이 이미 끈다. */
@media (prefers-reduced-motion: reduce) {
  .bf-rail { overflow-x: auto; }
  .bf-rail__group--dup { display: none; }
}

/* --- 테마: 네 개의 축 --------------------------------------
   축은 카드가 아니라 위쪽 실선으로 구분한다 — 컨슈머 카드 UI를
   쓰지 않기 위해서다. */
.bf-pillars { display: grid; grid-template-columns: repeat(2, 1fr); gap: 40px 48px; margin-top: 48px; }
.bf-pillar { border-top: 2px solid var(--bf-700); padding-top: 18px; }
.bf-pillar__no { font-size: 12px; font-weight: 600; letter-spacing: var(--bf-track-eyebrow); color: var(--bf-fg-faint); font-variant-numeric: tabular-nums; }
.bf-pillar__title { font-size: 22px; font-weight: 600; margin: 10px 0 0; word-break: keep-all; }
.bf-pillar__body { font-size: 15px; line-height: 1.65; color: var(--bf-fg-muted); margin: 10px 0 0; text-wrap: pretty; word-break: keep-all; }

/* --- 기록: 숫자 ------------------------------------------- */
.bf-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2px; margin-top: 48px; }
.bf-stat { border-top: 2px solid var(--bf-400); padding-top: 14px; }
.bf-stat__value { font-size: 34px; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.bf-stat__unit { font-size: 14px; font-weight: 600; color: var(--bf-fg-muted); margin-left: 8px; letter-spacing: 0; }
.bf-stat__label { font-size: 13.5px; font-weight: 500; color: var(--bf-fg-muted); margin-top: 8px; text-wrap: pretty; word-break: keep-all; }

/* --- 지표 카드 ----------------------------------------------
   덱에서 면으로 구분되는 지표. 깊이는 표면 단계와 헤어라인으로만
   내고, 호버는 빛의 방향만 바꾼다 — 카드가 뜨지 않는다. */
.bf-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
/* 카드 안의 긴 낱말이 열을 벌리지 못하게 한다 */
.bf-cards > * { min-width: 0; }

/* 아이콘 — 카드 맨 위에 하나. 선 굵기와 색은 글자를 따라간다.
   내용이 이미 긴 카드에는 붙이지 않는다. */
.bf-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.bf-ico {
  display: block; width: 22px; height: 22px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.bf-card__ico { color: var(--bf-300); margin-bottom: 14px; }
.bf-card--accent .bf-card__ico { color: var(--bf-200); }
.bf-cards--2 { grid-template-columns: repeat(2, 1fr); gap: 20px; }
.bf-cards--3 { grid-template-columns: repeat(3, 1fr); }
/* 카드는 면도 테두리도 갖지 않는다(2026-09-04, 사용자 지시). 남는
   것은 안쪽 여백과 글자뿐이다 — 카드를 가르는 일은 격자의 간격이
   한다. 이전에는 표면 한 단(--bf-surface-hi)과 헤어라인, 그리고
   비스듬히 깔리는 빛(--bf-card-lit)이 있었고 강조 카드는 가리키면
   네 가지가 함께 밝아졌다 — 모두 걷었다. 되살리려면 git 을 볼 것.
   가리킴에 답하는 카드는 이제 하나도 없다: 전부 <article> 과 <div>
   이지 링크도 단추도 아니다. */
.bf-card { padding: 20px 22px 22px; }
.bf-card--panel { padding: 24px 26px; }
/* 강조 카드에 남은 것은 두 가지다: 안쪽이 가운데로 모이고, 아이콘이
   램프 한 단 위로 올라간다. 면이 없으니 이 둘이 유일한 차이다. */
.bf-card--accent { text-align: center; }
.bf-card--accent .bf-card__ico { margin-left: auto; margin-right: auto; }

/* 지표 카드의 안쪽 */
.bf-card__value {
  font-size: 30px; font-weight: 800; line-height: 1.1;
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
/* keep-all 은 낱말 안에서 끊지 않는다 — 칸보다 넓은 낱말 하나는 그대로
   넘친다. anywhere 를 덧대 그런 낱말만은 끊게 한다(2026-09-06): 보기
   좋지는 않지만 페이지를 밀지는 않는다. */
.bf-card__value { font-size: 30px; font-weight: 800; line-height: 1.1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; word-break: keep-all; overflow-wrap: anywhere; }
}
:lang(ko) .bf-card__value { letter-spacing: 0; }
.bf-card__label {
  font-size: 13.5px; font-weight: 500; color: var(--bf-fg-muted);
  margin-top: 10px; text-wrap: pretty; word-break: keep-all;
}
/* 넷씩 서는 지표 카드의 라벨은 12px다. 카드 안쪽 폭이 131px이고
   'Korea Blockchain Week'는 13.5px에서 143px이라 두 줄이 되었다 —
   12px에서 127px로 한 줄에 들어간다. */
.bf-cards .bf-card__label { font-size: 12px; }
/* 낱말이 값으로 오는 카드 — 숫자가 아니라 이름이므로 30px에서는
   카드 밖으로 나간다(Blockmedia 162px, Bipartisan 141px). 낱말을
   자르지 않기 위해 크기를 줄인다. */
/* 넓이와 상관없이 줄인다(2026-09-06). 901px 위에서만 줄이던 시절에는
   휴대폰의 'National Assembly'가 42px 그대로 서서 카드 밖으로 75px
   나갔고, 그만큼 페이지 전체가 오른쪽으로 밀렸다(사용자). */
.bf-card__value--word { font-size: 25px; }
/* 지표 카드의 라벨은 카드 바닥에 선다. 값이 한 줄이든 두 줄이든,
   글자가 25px이든 30px이든 라벨의 아랫줄이 한 줄에 놓인다 — 값의
   높이마다 따로 보정하지 않아도 무리가 가지런하다. */
.bf-cards .bf-card { display: flex; flex-direction: column; }
.bf-cards .bf-card__label { margin-top: auto; padding-top: 12px; }
/* BLOCKFESTA 섹션의 지표 카드만 한 단 크다(2026-09-04, 사용자 지시) —
   아이콘·숫자·라벨과 그 사이 간격을 손으로 잡은 값이다. 면과 테두리가
   사라진 뒤 이 넷은 섹션에서 유일하게 서 있는 형상이므로 본문과 같은
   크기로는 무게가 모자란다. 카드의 바깥 여백은 그대로다: 칸을 벌리는
   일은 격자의 간격이 한다.
   .bf-cards 의 두 라벨 규칙과 특정도가 같으므로 반드시 그 아래 적는다. */
.bf-cards--lg .bf-card__ico { width: 25px; height: 25px; margin-bottom: 16px; }
.bf-cards--lg .bf-card__value { font-size: 42px; }
.bf-cards--lg .bf-card__label { font-size: 16px; padding-top: 16px; }
.bf-cards--lg .bf-card__value--word { font-size: 30px; }
/* 901–1100px는 인덱스 열(300px)이 그대로 있는데 본문만 좁아지는
   구간이다 — 여기서 넷씩 세우면 카드 안쪽이 87px까지 줄어 어떤 값도
   들어가지 않는다. 둘씩 세운다. */
@media (min-width: 901px) and (max-width: 1100px) {
  .bf-cards { grid-template-columns: repeat(2, 1fr); }
}
/* 이름 앞의 표식 — inline-flex라야 카드의 text-align을 그대로 따른다.
   좁은 화면에서 카드가 가운데 정렬될 때 표식도 같이 가운데로 간다. */
.bf-card__labelIn { display: inline-flex; align-items: center; gap: 7px; }
.bf-card__labelIco { width: 15px; height: 15px; color: var(--bf-300); }

/* 글 카드의 안쪽 — 번호·제목·본문 */
.bf-card__no {
  font-size: 12px; font-weight: 600; letter-spacing: var(--bf-track-eyebrow);
  color: var(--bf-fg-faint); font-variant-numeric: tabular-nums;
}
.bf-card__title { font-size: 20px; font-weight: 600; margin: 10px 0 0; word-break: keep-all; }
.bf-card__title:first-child { margin-top: 0; }   /* 번호 없는 카드 */
.bf-card__body {
  font-size: 15px; line-height: 1.65; color: var(--bf-fg-muted);
  margin: 10px 0 0; text-wrap: pretty; word-break: keep-all;
}
:lang(ko) .bf-card__body { line-height: 1.7; }

/* --- 기록: 미디어 도달력 -----------------------------------
   막대는 비교를 위한 것이지 장식이 아니다. 블록미디어 행만
   아주르로 올린다. */
.bf-media { margin-top: 64px; }
.bf-media__rows { margin-top: 20px; display: flex; flex-direction: column; gap: 8px; }
.bf-media__row { display: grid; grid-template-columns: 150px 1fr 64px; gap: 16px; align-items: center; }
.bf-media__name { font-size: 14px; font-weight: 500; color: var(--bf-fg-muted); }
/* 트랙은 카드 면 위에 있으므로 표면을 한 단계 올려야 보인다 */
.bf-media__track { height: 10px; background: var(--bf-surface-hi); border-radius: var(--bf-radius-1); overflow: hidden; }
.bf-media__bar { height: 100%; background: var(--bf-800); }
.bf-media__val { font-size: 14px; font-variant-numeric: tabular-nums; color: var(--bf-fg-muted); text-align: right; }
.bf-media__row.is-self .bf-media__name { color: var(--bf-fg); font-weight: 700; }
.bf-media__row.is-self .bf-media__bar { background: var(--bf-400); }
.bf-media__row.is-self .bf-media__val { color: var(--bf-fg); font-weight: 600; }
/* 출처 — 그림 아래 캡션 */
.bf-media__source { font-size: 12.5px; color: var(--bf-fg-faint); margin: 16px 0 0; word-break: keep-all; }

/* 채널 도달 — 수치는 카드로, 근거와 결론은 본문 글로. 결론 한
   문장만 아주르로 올린다(크기는 본문 그대로 — 색만 다르다).
   .bf-lead가 파일 뒤쪽에 있으므로 여기서는 두 클래스를 함께 걸어
   특정도를 올린다. 그러지 않으면 색과 여백을 .bf-lead가 덮는다. */
.bf-lead.bf-reach__text { margin-top: 48px; border-top: 1px solid var(--bf-rule); padding-top: 32px; max-width: none; }
.bf-lead.bf-reach__strong { max-width: none; }

/* --- 기록: KBW 주간에서의 위치 ----------------------------- */
.bf-week { margin-top: 56px; }
.bf-week__list { list-style: none; margin: 20px 0 0; padding: 0; }
.bf-week__item {
  display: grid; grid-template-columns: 150px 1fr 1fr; gap: 16px;
  padding: 12px 0; border-top: var(--bf-border);
  font-size: 14.5px; color: var(--bf-fg-muted);
}
.bf-week__date { font-variant-numeric: tabular-nums; }
.bf-week__note { color: var(--bf-fg-faint); font-weight: 400; word-break: keep-all; }
.bf-week__item.is-featured { color: var(--bf-fg); font-weight: 600; }
.bf-week__item.is-featured .bf-week__event { color: var(--bf-100); }

/* --- 파트너 로고 스트립 ------------------------------------
   등급마다 크기가 실제로 달라야 한다 — 최상위가 Silver 크기로
   렌더링되면 계약 위반이다. 로고는 품질이 제각각이라 중립
   컨테이너에 넣고 광학 크기를 맞춘다. */
.bf-strip { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 40px; align-items: center; }
/* --- 2026 연사 카드 -------------------------------------------
   2026-09-06, 디자이너 시안(docs/spikers-img)을 그대로 옮겼다.
   카드가 가로로 눕는다: 왼쪽에 번호·이름·직함·소속을 곁줄 하나로
   묶고, 오른쪽에 누끼 초상이 카드 모서리까지 간다. 한 줄에 둘.
   비례는 시안에서 잰 값이다 — 카드 604×277(2.18:1), 왼쪽 여백 37,
   곁줄에서 글까지 25, 사진칸 47%. 모서리는 시안대로 각지다.
   높이는 비율이 정하되 글이 더 길면 카드가 자란다: 영문 이름은
   두 줄이 되는 일이 있다. */
/* 줄마다 높이를 같게 한다(grid-auto-rows: 1fr, 2026-09-06). 이름이
   두 줄이 되는 카드가 있으면 그 줄만 키가 커졌고, 곁줄은 카드
   높이의 66% 이므로 줄마다 길이가 달라졌다. 모두 가장 큰 줄에
   맞추면 카드도 곁줄도 한 길이다. */
.bf-lineup { display: grid; grid-template-columns: repeat(2, 1fr); grid-auto-rows: 1fr; gap: 12px; margin-top: 40px; }
.bf-lineup > * { min-width: 0; }
.bf-lineup__item {
  /* 자르지 않는다. overflow: hidden 은 계산된 최소 높이를 0 으로
     만들어(CSS 스펙의 automatic minimum size), 글이 비율보다 길면
     카드가 자라는 대신 아랫줄을 잘라 먹었다(2026-09-06, 사용자:
     몇몇 폭에서 소속이 반만 보인다). 사진은 제 상자가 따로
     자르므로 여기서 가릴 일이 없고, 모서리도 각진 채로 둔다. */
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) 47%;
  align-items: center; aspect-ratio: 604 / 277;
  /* 섹션의 아주르 띠보다 한 겹 밝다 — 시안에서도 카드는 바탕보다
     딱 그만큼만 밝다. 새 색이 아니라 램프에서 섞은 값이다. */
  background: color-mix(in srgb, var(--bf-700) 22%, var(--bf-surface));
  /* 글자 크기가 카드 폭을 따른다 — 끊는 자리를 여럿 두는 대신
     칸 질의 하나로 잇는다. 이름은 세 글자와 열세 글자가 같은 칸에
     들어가야 하므로 언어마다 기울기가 다르다. */
  container-type: inline-size;
  /* 누를 것이 없다 — 글자 위에서도 화살표를 지킨다(2026-08-19) */
  cursor: default;
}
/* 곁줄은 글 상자의 테두리가 아니라 카드의 것이다(2026-09-06,
   사용자: 줄 길이가 카드마다 다르다). 테두리였을 때는 길이가 글의
   양을 따라서, 이름이 두 줄인 카드에서 훌씩 길어졌다. 시안에서
   줄은 카드 높이의 66%를 가운데에서 차지한다(y 47..229 / 277). */
.bf-lineup__item { --bf-lineup-x: 34px; --bf-lineup-gap: 25px; }
.bf-lineup__item::before {
  content: ''; position: absolute; left: var(--bf-lineup-x); top: 17%;
  width: 2px; height: 66%; background: var(--bf-300);
}
.bf-lineup__text { margin-left: calc(var(--bf-lineup-x) + var(--bf-lineup-gap)); }
/* 이름이 카드의 무게다 — 시안에서 이름 하나가 카드 높이의 1/6을
   차지한다. 한글 세 글자와 영문 열세 글자를 같은 칸에 넣으려면
   기울기가 달라야 한다: 영문은 그래도 두 줄이 되는 일이 있다. */
.bf-lineup__name {
  font-size: clamp(24px, 11cqw, 52px); font-weight: 800; line-height: 1.05;
  letter-spacing: -.01em; word-break: keep-all; margin-bottom: 10px;
}
.bf-lineup__name:lang(en) { font-size: clamp(19px, 6.2cqw, 34px); }
/* 직함만 아주르다 — 이름과 소속은 흰 글자이므로 색 하나로 셋이 갈린다.
   --bf-300 은 링크의 색이지만 여기서는 밑줄도 손 모양도 없다. */
.bf-lineup__role { font-size: clamp(13px, 3.6cqw, 20px); line-height: 1.4; color: var(--bf-300); word-break: keep-all; }
.bf-lineup__org  { font-size: clamp(13px, 3.6cqw, 20px); line-height: 1.4; color: var(--bf-fg); word-break: keep-all; }
.bf-lineup__role:lang(en), .bf-lineup__org:lang(en) { font-size: clamp(12.5px, 3.1cqw, 17px); }
/* 덧말(전 직함) — 소속보다 한 단 물러선다: 색은 흐리게, 크기는 작게 */
.bf-lineup__note { font-size: clamp(12.5px, 2.7cqw, 15px); line-height: 1.4; margin-top: 4px; color: var(--bf-fg-muted); word-break: keep-all; }

/* 초상은 카드의 오른쪽 끝까지 간다 — 위아래 모서리도 자른다.
   원본은 배경 없는 누끼이고 세로로 길므로 폭에 맞춰 채우고
   아래를 자른다(object-position 위 맞춤): 머리는 늘 위에 선다. */
.bf-lineup__photo {
  position: relative; align-self: stretch; overflow: hidden;
  display: grid; place-items: center;
}
.bf-lineup__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 0;
}
/* 같은 그림이 두 겹이다: 아래는 제 색, 위는 남색 듀오톤(필터는
   speakers.php 안에 있다). 가리키면 위 겹만 사라진다.
   두 겹인 까닭은 filter: url() 이 none 으로 건너가지 못해서다 —
   오가는 것은 불투명도뿐이고, 그래서 부드럽다.
   500ms 는 카드 강조와 같은 값이다: 색이 '켜지는' 것이 아니라
   '돌아오는' 것으로 읽히려면 200ms 로는 짧다. */
.bf-lineup__img--duo { filter: url(#bf-duotone); transition: opacity 500ms var(--bf-ease); }
/* 가리킴은 마우스에게만 있다 — 손가락에서는 :hover 가 탭 뒤에 눌어붙어
   한 번 만진 카드만 영영 컬러로 남는다(띠에서 겪은 그것이다).
   카드는 여전히 링크도 단추도 아니다: 색이 돌아올 뿐 눌리지 않는다. */
@media (hover: hover) and (pointer: fine) {
  .bf-lineup__item:hover .bf-lineup__img--duo { opacity: 0; }
}
.bf-lineup__initials { font-size: 38px; font-weight: 800; color: var(--bf-fg-faint); }

/* 자리 카드 — 확정된 카드와 혼동되지 않게 한 걸음 물러나 있다:
   면을 비우고 테두리를 점선으로 둔다. 이름 아래 두 줄은 글자가
   아니라 자리 표시 막대다. 반짝이는 뼈대로 만들지 않는다 — 그것은
   '불러오는 중'이라는 뜻이고, 여기는 '아직 정해지지 않았다'는 뜻이다. */
.bf-lineup__item--tba { background: transparent; border: 1px dashed var(--bf-hairline); }
.bf-lineup__item--tba .bf-lineup__photo {
  background: color-mix(in srgb, var(--bf-800) 12%, var(--bf-surface));
}
/* 글리프는 작게 둔다. 크게 늘리면 선 굵기까지 함께 자라 스프라이트의
   다른 아이콘과 굵기가 어긋난다. */
.bf-lineup__glyph { width: 34px; height: 34px; color: var(--bf-fg-faint); opacity: .65; }
.bf-lineup__item--tba .bf-lineup__name { color: var(--bf-fg-faint); font-weight: 600; }
.bf-lineup__bar {
  height: 9px; margin-top: 8px; border-radius: var(--bf-radius-1);
  background: var(--bf-surface-hi); max-width: 78%;
}
.bf-lineup__bar--short { max-width: 52%; }

/* 2026 파트너 — 섹션 하나가 통째로 흰 면이다(2026-09-04, 주최 측
   요청). 위의 .bf-strip 은 스폰서십 페이지가 계속 쓰므로 그대로 둔다.
   흰 타일을 칸마다 깔던 방식도, 컨테이너 안에서 끝나는 흰 판도 거쳐
   여기까지 왔다: 모양이 제각각인 마크를 같은 크기 상자에 담으면 흰
   상자의 격자가 먼저 보였고, 판을 하나로 합쳐도 어두운 여백이 액자로
   남아 로고 벽이 상자 안에 갇혀 보였다.
   이 섹션만 밝다. 올해를 가르던 아주르 띠(bf-section--accent)는 여기서
   쓰지 않는다 — 흰 면이 그보다 훨씬 큰 구분이다. */
.bf-section--plate { background: var(--bf-plate); }
/* 밝은 면 위의 글자는 방향이 뒤집힌다. 제목은 바탕색 그대로(19:1),
   리드는 흰쪽으로 30% 당긴 값이다 — 흰 바탕에서 7.0:1. */
.bf-section--plate .bf-head__title { color: var(--bf-bg); }
.bf-section--plate .bf-head__lead {
  color: color-mix(in srgb, var(--bf-bg) 70%, var(--bf-plate));
}
.bf-plate { margin-top: 44px; }
/* 등급 사이의 칸막이는 없다(2026-09-04) — 선은 등급 이름의 높이에서
   좌우로 뻗는다. 이름이 선을 끊고 서므로 층이 갈리는 자리와 이름이
   같은 줄이다. */
.bf-plate__tier { padding: 34px 0; }
/* 등급 이름 — 브랜드 블루다. 램프에서 흰 바탕에 쓸 수 있는 가장 깊은
   단이 --bf-600 이고(6.62:1), 한 단 위인 --bf-500 은 4.97:1 로 본문
   기준을 겨우 넘는다. 18px 은 큰 글자 기준(24px 또는 굵은 18.66px)에
   못 미치므로 4.5:1 을 지켜야 한다.
   좌우로 뻗는 선은 flex 로 남는 자리를 다 먹는 두 조각이다. 선 색은
   헤어라인 토큰이 아니라 바탕색을 옅게 깐 것이다 — 어두운 면의 선을
   밝은 면에 그대로 쓰면 보이지 않는다. */
.bf-plate__label {
  display: flex; align-items: center; gap: 20px;
  margin-bottom: 26px;
  font-size: 18px; font-weight: 700; letter-spacing: 0;
  color: var(--bf-600);
}
.bf-plate__label::before, .bf-plate__label::after {
  content: ''; flex: 1 1 0; height: 1px;
  background: color-mix(in srgb, var(--bf-bg) 14%, transparent);
}
/* 로고는 줄에 눕고 가운데로 모인다. 칸에 폭을 주지 않는 것이 요점이다:
   칸의 폭은 로고가 제 비율대로 그 높이에 설 때의 폭이고, 상한만 둔다 —
   그래야 가로로 긴 워드마크와 정사각형 마크가 한 줄에서 광학적으로
   같은 무게로 보인다. 폭을 못박으면 정사각형 마크만 작아 보인다. */
.bf-plate__row {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: center;
  gap: 24px 44px;
}
.bf-plate__cell {
  display: flex; align-items: center; justify-content: center;
  color: var(--bf-bg); font-size: 24px; font-weight: 600; text-align: center;
}
/* 그림은 칸을 채운다 — max-width 만 두면 칸보다 작은 파일은 제 크기
   그대로 남는다(The Block 의 SVG 는 155×24 라 240 칸 안에서 155 로
   섰다). width·height 를 100%로 주고 object-fit 이 비율을 지키면
   모든 마크가 칸의 한쪽 변에 닿는다. */
.bf-plate__cell img { width: 100%; height: 100%; object-fit: contain; }
/* 칸은 등급과 상관없이 하나이고, 폭은 상한이 아니라 못박은 값이다
   (2026-09-04, 사용자 지시). 상한(max-width)이었을 때는 칸이 로고의
   비율만큼만 넓어져 칸마다 폭이 달랐다 — 마크의 비율이 155×24 에서
   238×120 까지 벌어져 있기 때문이다. 못박으면 줄이 격자로 읽히고
   로고는 그 안에서 object-fit 으로 앉는다.
   처음에는 등급마다 높이를 달리했다(76/56/44/36) — 계단이 보여야
   등급을 판 뜻이 산다고 보았다. 되돌리려면 그 네 줄이 git 에 있다. */
.bf-plate__cell { width: 240px; height: 60px; }

/* 전화기에서는 판의 여백과 칸의 높이를 함께 줄인다. 여백을 그대로 두면
   360px 화면에서 로고가 설 자리가 296px 밖에 남지 않는다. */
@media (max-width: 600px) {
  .bf-plate__tier { padding: 24px 0; }
  .bf-plate__label { font-size: 16px; gap: 14px; margin-bottom: 20px; }
  .bf-plate__row { gap: 18px 28px; }
  /* 두 칸이 한 줄에 서려면 360px 화면에서 칸이 146px 를 넘을 수 없다.
     이름만 서 있는 자리는 글자도 함께 줄인다 — 24px 에서 '알앤투
     테크놀로지' 아홉 자는 216px 라 칸을 넘어 두 줄이 되고, 못박은
     높이 밖으로 나간다. */
  .bf-plate__cell { width: 140px; height: 46px; font-size: 15px; }
}
/* 가리킴에 반응하지 않는다 — 로고 판과 같은 이유다: 남의 마크를 담는
   자리일 뿐 누를 것이 아니다. */

/* 어두운 면 위에서는 대부분의 브랜드 마크가 사라진다 — 워드마크는
   보통 검정이나 짙은 남색이라 대비가 1.6:1 밖에 나오지 않는다.
   밝은 판을 깔면 브랜드 색을 손대지 않고 그대로 살릴 수 있다.
   로고는 흰 단색이라 흑연 위에 그대로 선다(2026-09-03). 예전에는 흰
   판을 깔았다 — 덱에서 온 로고가 저마다 제 색이었고 어두운 벽에서는
   검은 워드마크가 사라졌기 때문이다. 이제 모두 흰색으로 바꿨으므로
   판이 필요 없고, 판을 걷으니 띠가 배경과 한 몸이 된다. */
/* 행을 1fr로 고정한다. 기본값(auto)이면 행 높이를 그림이 정하므로
   그림의 max-height:100%가 기댈 곳이 없어져 세로로 넘쳐 나간다.
   overflow는 마지막 안전장치다 — 판 밖으로는 무슨 일이 있어도 안 나간다. */
.bf-strip__item {
  display: grid; place-items: center; grid-template-rows: minmax(0, 1fr); overflow: hidden;
  border: 1px solid transparent; border-radius: var(--bf-radius-2);
  color: var(--bf-fg-muted); font-weight: 600;
}
.bf-strip__item img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* 칸의 너비를 내용이 정하게 두면 1000px짜리 SVG 하나가 띠를 무너뜨린다.
   로고가 든 칸은 등급이 정한 너비로 고정하고 안에서 맞춘다. */
.bf-strip__item:has(img) { width: var(--bf-strip-w); }
.bf-strip__item--coHost   { --bf-strip-w: 260px; min-width: 260px; height: 96px; padding: 20px 28px; font-size: 20px; }
.bf-strip__item--title    { --bf-strip-w: 220px; min-width: 220px; height: 84px; padding: 18px 24px; font-size: 18px; }
.bf-strip__item--platinum { --bf-strip-w: 170px; min-width: 170px; height: 66px; padding: 14px 20px; font-size: 15.5px; }
.bf-strip__item--gold     { --bf-strip-w: 140px; min-width: 140px; height: 54px; padding: 12px 16px; font-size: 14px; }
.bf-strip__item--silver   { --bf-strip-w: 112px; min-width: 112px; height: 44px; padding: 10px 14px; font-size: 13px; }

/* 이름만 있는 마크 목록 — 65개가 벽처럼 보이지 않게 */
/* 한 줄에 넷이 서야 벽이 짧게 끝난다. 본문 폭은 756px이고 판 넷과
   사이 셋이 그 안에 들어가야 한다 — 판을 176px로 4px 줄여 간격에
   보탰다. 딱 맞추면 반올림 한 번에 셋으로 접히므로 여유를 남긴다. */
.bf-marks { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 20px; align-items: center; }
.bf-mark {
  font-size: 13px; font-weight: 500; color: var(--bf-fg-muted);
  border: var(--bf-border); border-radius: var(--bf-radius-1); padding: 5px 10px;
}
/* 로고 마크 — 띠와 같은 이유로 밝은 판이다. 칸은 모두 같은 크기이며
   로고는 그 안에서 맞춰진다: 가로로 긴 마크와 정사각형 마크가 한 줄에
   서도 광학적으로 같은 무게로 보이게 하려는 것이다.
   칸 크기는 판을 걷은 뒤에도 그대로다 — 줄 간격과 띠 계산이 여기에
   기대고 있다. */
.bf-mark--logo {
  display: grid; place-items: center; grid-template-rows: minmax(0, 1fr); overflow: hidden;
  width: 176px; height: 78px; padding: 12px;
  border-color: transparent;
}
.bf-mark--logo img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* 로고에는 가리킴 반응이 없다(2026-08-18). 들림도 테두리도 걷었다 —
   판은 남의 마크를 담는 자리일 뿐 누를 것이 아니다. 띠에서는 가리킴이
   이미 다른 뜻을 가진다: 그 줄이 멈춘다. */
/* 참가 대상은 여섯 뿐이므로 보통 카드로 선다 — 면과 테두리는 카드
   그대로이고 글자는 본문 크기다. 아래쪽 파트너 65개는 작은 마크로
   남는다: 같은 옷을 입히면 이름의 벽이 된다.
   폭은 지표 카드와 같은 격자를 쓴다(2026-08-19) — 한 섹션에 두
   무리가 서므로 칸 나눔이 어긋나면 둘 다 흐트러져 보인다. 채움까지
   강조로 올리지는 않는다: 강조는 한 섹션에 한 무리뿐이고, 그 자리는
   위쪽 지표 카드가 이미 가졌다. */
/* 여섯 칸의 높이는 하나다. 이름이 한 줄인 것과 두 줄인 것이 섞이는데
   ('Financial institutions', '디지털자산 기업'), 칸마다 높이가 다르면
   한 무리로 보이지 않는다. grid-auto-rows: 1fr 은 모든 줄을 가장 높은
   줄에 맞추고, align-items 는 그 줄을 칸이 채우게 한다 —
   .bf-marks 가 물려준 center 를 여기서 되돌린다. 그것 때문에 칸이
   줄 안에서 가운데에 뜬 채 늘어나지 않았다. */
.bf-marks--cards {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px;
  grid-auto-rows: 1fr; align-items: stretch;
}
/* 지표 카드와 같은 구간에서 둘씩 선다. 이 규칙은 반드시 기본 규칙
   뒤에 있어야 한다 — 미디어 질의는 특정성을 올리지 않으므로 차례가
   전부다. 위쪽 묶음에 적어 두었더니 기본 규칙이 그보다 아래에 있어
   내내 지고 있었다(2026-08-19에 발견). .bf-cards 는 기본이 위에
   있어 같은 자리에서도 이긴다. */
@media (min-width: 901px) and (max-width: 1100px) {
  .bf-marks--cards { grid-template-columns: repeat(2, 1fr); }
}
.bf-marks--cards > * { min-width: 0; }
/* 아이콘은 이름 왼쪽에 선다(2026-08-19). 카드가 낮아지고 눈이 왼쪽
   한 줄만 훑으면 여섯을 다 읽는다. 두 줄로 접히는 이름이 섞이므로
   세로 가운데로 맞춘다 — 아이콘이 첫 줄에 붙으면 줄 수마다 높이가
   달라 보인다. */
.bf-marks--cards .bf-mark {
  display: flex; align-items: center; gap: 12px;
  border-radius: var(--bf-radius-2);
  padding: 14px 16px; font-size: var(--bf-size-body); font-weight: 400;
/* keep-all 은 낱말 안에서 끊지 않는다 — 칸보다 넓은 낱말 하나는 그대로
   넘친다. anywhere 를 덧대 그런 낱말만은 끊게 한다(2026-09-06): 보기
   좋지는 않지만 페이지를 밀지는 않는다. */
.bf-card__value { font-size: 30px; font-weight: 800; line-height: 1.1; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; word-break: keep-all; overflow-wrap: anywhere; } text-wrap: pretty;
}
.bf-mark__ico { color: var(--bf-300); }
/* 가장 좁은 화면에서 칸이 100px 안팎까지 줄고 'institutions' 같은
   긴 낱말은 그 안에 통째로 들어가지 않는다. 들어가지 않을 때만
   낱말을 자른다 — 평소 줄바꿈은 그대로다. */
.bf-mark__label { min-width: 0; overflow-wrap: break-word; }

/* --- 등급별 금액 (메인 페이지) -----------------------------
   등급 순위는 위 테두리 색으로 읽힌다. 상세 혜택은 파트너십
   페이지가 맡고, 여기서는 금액만 답한다. */
.bf-prices { margin-top: 56px; }
/* 열은 다섯이 아니라 '들어가는 만큼'이다. repeat(5, 1fr) 로 두면 트랙의
   최소 크기가 내용의 min-content라 카드가 116px 아래로 못 줄고, 좁아진
   폭에서 격자가 본문을 밀어 페이지 전체가 가로로 늘어난다(901px에서
   200px 넘침). 최소를 140px로 못 박으면 트랙이 내용과 무관해지고,
   auto-fit 이 다섯 → 넷 → 셋으로 접는다. */
.bf-prices__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-top: 20px; }
/* 등급 카드 — 순위는 2px 테두리 색으로 읽힌다. 가리키면 그 색이
   면 전체를 채우고 글자는 그라파이트로 뒤집힌다. 등급색은 모두
   밝은 색이므로 어두운 글자라야 읽힌다. */
.bf-price {
  background: var(--bf-surface); border: 2px solid var(--bf-hairline);
  border-radius: var(--bf-radius-2); padding: 18px 18px 20px;
  transition: background var(--bf-dur-1) var(--bf-ease), color var(--bf-dur-1) var(--bf-ease);
}
.bf-price--coHost   { border-color: var(--bf-100); }
.bf-price--title    { border-color: var(--bf-tier-title); }
.bf-price--platinum { border-color: var(--bf-tier-platinum); }
.bf-price--gold     { border-color: var(--bf-tier-gold); }
.bf-price--silver   { border-color: var(--bf-tier-silver); }

.bf-price:hover { color: var(--bf-cta-fg); }
.bf-price--coHost:hover   { background: var(--bf-100); }
.bf-price--title:hover    { background: var(--bf-tier-title); }
.bf-price--platinum:hover { background: var(--bf-tier-platinum); }
.bf-price--gold:hover     { background: var(--bf-tier-gold); }
.bf-price--silver:hover   { background: var(--bf-tier-silver); }
/* 안쪽 글자들은 자기 색을 버리고 카드의 색을 따른다 */
.bf-price:hover .bf-price__name,
.bf-price:hover .bf-price__value,
.bf-price:hover .bf-price__limit { color: inherit; }
/* 별이 이름 왼쪽에 붙는다 — 카드의 양 끝으로 벌려 놓으면 둘이 서로
   다른 것을 가리키는 두 신호처럼 읽힌다. 붙어 있어야 한 이름이다. */
.bf-price__name {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600; letter-spacing: var(--bf-track-eyebrow);
  color: var(--bf-fg-muted); text-transform: uppercase;
}
/* 별은 등급 테두리와 같은 색이다 — 두 신호가 같은 것을 말한다.
   여기서만 면을 채운다: 20px 윤곽선 별은 형태가 뭉개진다. */
.bf-price__ico, .bf-tier__ico {
  width: 20px; height: 20px; color: var(--bf-hairline);
  fill: currentColor; stroke-width: 1.5;
}
.bf-price--coHost   .bf-price__ico, .bf-tier--coHost   .bf-tier__ico { color: var(--bf-100); }
.bf-price--title    .bf-price__ico, .bf-tier--title    .bf-tier__ico { color: var(--bf-tier-title); }
.bf-price--platinum .bf-price__ico, .bf-tier--platinum .bf-tier__ico { color: var(--bf-tier-platinum); }
.bf-price--gold     .bf-price__ico, .bf-tier--gold     .bf-tier__ico { color: var(--bf-tier-gold); }
.bf-price--silver   .bf-price__ico, .bf-tier--silver   .bf-tier__ico { color: var(--bf-tier-silver); }
/* 카드가 채워지면 글자는 그라파이트가 되므로 메달도 함께 따라간다 */
.bf-price:hover .bf-price__ico { color: var(--bf-cta-fg); }
.bf-tier__name { display: flex; align-items: center; gap: 12px; }
.bf-tier__ico { width: 22px; height: 22px; }
/* 금액과 한정 문구가 한 줄에 선다. 기준선을 맞춰야 크기가 다른 두 글이
   같은 줄로 읽힌다. 칸이 좁아지면 접히고, 그때만 문구가 아래로 간다. */
.bf-price__row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 8px; margin-top: 8px; }
.bf-price__value { font-size: 21px; font-weight: 700; font-variant-numeric: tabular-nums; }
.bf-price__limit { font-size: 12.5px; color: var(--bf-fg-faint); word-break: keep-all; }

/* --- 실행 리본 -----------------------------------------------
   디자인 번들 '09_execution_ribbon_cinematic' 을 테마 섹션의 제목
   자리에 옮긴 것이다(2026-09-04). 그림은 partials/ribbon.php 의
   인라인 SVG, 글자와 화살표는 HTML(theme.php), 스타일은 전부 여기다 —
   인라인 SVG 의 <style> 은 문서 전체에 적용되므로 파일 안에 두면
   :root 규칙까지 페이지로 새어 나간다.

   색은 번들 그대로 둔다(사용자 결정, 2026-09-04). 서른두 색 가운데
   토큰과 같은 것은 다섯뿐이지만, 이 그림은 히어로의 도시 그림처럼
   통째로 받은 한 벌이므로 낱낱이 램프에 끼워 맞추지 않는다.

   길이는 3.5초다. 번들은 6.2초인데 그것은 첫 화면을 위한 길이이고,
   여기는 세 번째 섹션이라 다 서기 전에 지나쳐 버린다. 키프레임이
   백분율이므로 되돌리려면 이 한 값만 고치면 된다. */
.bf-rb {
  position: relative;
  container-type: inline-size;   /* cqw 의 기준 — 글자가 그림과 함께 자란다 */
  aspect-ratio: 10 / 3;          /* 잘라 낸 viewBox 와 같은 비율 */
  margin-bottom: 56px;           /* 걷어 낸 .bf-head 의 아래 여백 자리 */
  --bf-rb-dur: 3.5s;
  --bf-rb-ease: cubic-bezier(.16, 1, .3, 1);
}
.bf-rb__art { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.bf-rb__type { position: absolute; inset: 0; }
.bf-rb__h2 { margin: 0; font-weight: 800; }

/* 낱말은 저마다 제 상자에 앉는다. 상자는 번들의 아웃라인 SVG 에서
   글자의 실제 경계를 재어 백분율로 옮긴 값이고, 글자 크기와 자간은
   번들의 것 그대로다(92·124.41·76 을 1600 으로 나눈 cqw). */
.bf-rb__w {
  position: absolute; display: flex; align-items: center;
  white-space: nowrap; line-height: 1;
}
.bf-rb__w--a { left:  6.00%; top: 34.34%; width: 10.60%; height: 17.67%; font-size: 5.75cqw;  letter-spacing: -.04em; color: #0B0D12; }
.bf-rb__w--b { left: 40.36%; top: 60.02%; width: 19.52%; height: 23.33%; font-size: 7.776cqw; letter-spacing: 0;      color: #F3F6FA; }
.bf-rb__w--c { left: 72.79%; top: 62.48%; width: 16.98%; height: 14.25%; font-size: 4.75cqw;  letter-spacing: -.03em; color: #0B0D12; }

/* 영문판은 낱말이 둘이므로 리본의 두 끝에 하나씩 선다
   (2026-09-06, 사용자 지시): Onchain 은 왼쪽 파란 띄, Finance 는
   오른쪽 파란 띄다. 예전에는 둘 다 오른쪽 띄에 몰려 서 있었다.
   자리는 그림에서 재었다. 띄는 M0 273H438L594 401H1600V539H1159L1003 411H0Z —
   왼쪽 목은 y 273..411(상자 높이의 27.7..56.5%), x 0..438(0..27.4%),
   오른쪽 목은 y 401..539(54.4..83.1%), x 594..1600(37.1..100%) 이다.
   글자 크기는 띄 안에 들어가도록 줄였다: Onchain 은 5.8cqw 에서
   폭이 23% 남직이라 빗금(x 420)에 닿기 전에 끝난다.
   색은 밑에 깔린 것을 따른다(사용자 지시). 그라데이션은 왼쪽이
   #07589F, 오른쪽이 #78B7EE 이므로 왼쪽 낱말은 흰 글자(6.5:1),
   오른쪽 낱말은 그라파이트 글자(7:1)다 — 바꿔 놓으면 둘 다 2:1 이다. */
.bf-rb__h2:lang(en) .bf-rb__w--b { left:  2.4%;  top: 33.5%;  width: 24%; height: 17.67%; font-size: 5.8cqw; }
.bf-rb__h2:lang(en) .bf-rb__w--c { left: 72.79%; top: 62.48%; width: 18%; height: 14.25%; font-size: 4.8cqw; }

/* 영문 한 줄과 그 위의 선. 번들에서는 점선이 먼저 그려지고 문장이
   나중에 왔는데, 실선으로 바꾸고 둘을 같은 순간에 세웠다. */
.bf-rb__claim { position: absolute; left: .57%; top: 5.2%; width: 49.1%; margin: 0; }
.bf-rb__rail {
  display: block; position: relative; transform-origin: left center;
  height: 3px; background: #9AC7E9;
}
/* 머리는 히어로의 화살표와 같은 만듦새다 — 테두리 삼각형 하나 */
.bf-rb__rail::after {
  content: ''; position: absolute; right: -9px; top: 50%;
  border: 6px solid transparent; border-left: 9px solid #B5D1EE;
  transform: translateY(-50%);
}
.bf-rb__claimText {
  display: block; margin-top: 1.1cqw;
  font-size: 2.15cqw; font-weight: 500; line-height: 1.25;
}
.bf-rb__claimHead { color: #F3F6FA; }
.bf-rb__claimTail { color: var(--bf-200); }

/* --- 리본의 움직임 -------------------------------------------
   감추는 일은 html.bf-anim 아래에서만 한다 — 등장 애니메이션과 같은
   안전장치다. 스크립트가 없으면 그 클래스가 없고, 리본은 처음부터
   완성된 채로 선다. */
.bf-anim .bf-rb__half--l,
.bf-anim .bf-rb__half--r { transform: scaleX(0); }
.bf-anim .bf-rb__final   { opacity: 0; }
.bf-anim .bf-rb__trace   { stroke-dasharray: 980; stroke-dashoffset: 980; }
.bf-anim .bf-rb__bead    { opacity: 0; }
.bf-anim .bf-rb__flare   { opacity: 0; transform: scaleX(.04); }
.bf-anim .bf-rb__fold    { opacity: 0; }
.bf-anim .bf-rb__sweep   { opacity: 0; }
.bf-anim .bf-rb__node    { opacity: .22; transform: scale(.72); }
.bf-anim .bf-rb__settle  { opacity: 0; }
.bf-anim .bf-rb__w       { opacity: 0; }
.bf-anim .bf-rb__rail    { transform: scaleX(0); }
.bf-anim .bf-rb__rail::after,
.bf-anim .bf-rb__claimText { opacity: 0; }

/* SVG 안에서 transform 을 쓰려면 기준 상자를 정해 주어야 한다 */
.bf-rb__half--l, .bf-rb__half--r, .bf-rb__flare,
.bf-rb__fold, .bf-rb__sweep, .bf-rb__node, .bf-rb__settle, .bf-rb__bead {
  transform-box: fill-box;
}
.bf-rb__half--l { transform-origin: right center; }
.bf-rb__half--r { transform-origin: left center; }
.bf-rb__flare, .bf-rb__node, .bf-rb__settle { transform-origin: center; }

.bf-rb.is-playing .bf-rb__half--l,
.bf-rb.is-playing .bf-rb__half--r,
.bf-rb.is-playing .bf-rb__final,
.bf-rb.is-playing .bf-rb__trace,
.bf-rb.is-playing .bf-rb__bead,
.bf-rb.is-playing .bf-rb__flare,
.bf-rb.is-playing .bf-rb__fold,
.bf-rb.is-playing .bf-rb__sweep,
.bf-rb.is-playing .bf-rb__node,
.bf-rb.is-playing .bf-rb__settle,
.bf-rb.is-playing .bf-rb__w,
.bf-rb.is-playing .bf-rb__rail,
.bf-rb.is-playing .bf-rb__rail::after,
.bf-rb.is-playing .bf-rb__claimText {
  animation-duration: var(--bf-rb-dur);
  animation-timing-function: var(--bf-rb-ease);
  animation-fill-mode: both;
  animation-iteration-count: 1;
}

.bf-rb.is-playing .bf-rb__half--l  { animation-name: bfRbHalf; }
.bf-rb.is-playing .bf-rb__half--r  { animation-name: bfRbHalf; animation-delay: .045s; }
.bf-rb.is-playing .bf-rb__final    { animation-name: bfRbFinal; }
.bf-rb.is-playing .bf-rb__trace--l { animation-name: bfRbTrace; }
.bf-rb.is-playing .bf-rb__trace--r { animation-name: bfRbTrace; animation-delay: .034s; }
.bf-rb.is-playing .bf-rb__bead--l  { animation-name: bfRbBeadL; }
.bf-rb.is-playing .bf-rb__bead--r  { animation-name: bfRbBeadR; }
.bf-rb.is-playing .bf-rb__flare    { animation-name: bfRbFlare; }
.bf-rb.is-playing .bf-rb__fold--1  { animation-name: bfRbFold; }
.bf-rb.is-playing .bf-rb__fold--2  { animation-name: bfRbFold; animation-delay: .051s; }
.bf-rb.is-playing .bf-rb__w--a     { animation-name: bfRbCopyA; }
.bf-rb.is-playing .bf-rb__w--b     { animation-name: bfRbCopyB; animation-delay: .045s; }
.bf-rb.is-playing .bf-rb__w--c     { animation-name: bfRbCopyC; animation-delay: .09s; }
.bf-rb.is-playing .bf-rb__rail     { animation-name: bfRbRail; }
.bf-rb.is-playing .bf-rb__rail::after { animation-name: bfRbArrow; }
.bf-rb.is-playing .bf-rb__claimText   { animation-name: bfRbClaim; }
.bf-rb.is-playing .bf-rb__sweep--soft { animation-name: bfRbSweepSoft; }
.bf-rb.is-playing .bf-rb__sweep--core { animation-name: bfRbSweepCore; }
.bf-rb.is-playing .bf-rb__node--1  { animation-name: bfRbNode; }
.bf-rb.is-playing .bf-rb__node--2  { animation-name: bfRbNode; animation-delay: .068s; }
.bf-rb.is-playing .bf-rb__node--3  { animation-name: bfRbNode; animation-delay: .136s; }
.bf-rb.is-playing .bf-rb__node--4  { animation-name: bfRbNode; animation-delay: .203s; }
.bf-rb.is-playing .bf-rb__settle   { animation-name: bfRbSettle; }

@keyframes bfRbHalf  { 0%, 6% { transform: scaleX(0); } 28%, 100% { transform: scaleX(1); } }
@keyframes bfRbFinal { 0%, 23% { opacity: 0; } 30%, 100% { opacity: 1; } }
@keyframes bfRbTrace {
  0%, 4%    { stroke-dashoffset: 980; opacity: .15; }
  25%, 100% { stroke-dashoffset: 0;   opacity: .9; }
}
@keyframes bfRbBeadL {
  0%, 3%    { transform: translateX(-510px); opacity: 0; }
  6%        { opacity: .85; }
  18%       { transform: translateX(0); opacity: 1; }
  22%, 100% { transform: translateX(0); opacity: 0; }
}
@keyframes bfRbBeadR {
  0%, 3%    { transform: translateX(510px); opacity: 0; }
  6%        { opacity: .85; }
  18%       { transform: translateX(0); opacity: 1; }
  22%, 100% { transform: translateX(0); opacity: 0; }
}
@keyframes bfRbFlare {
  0%, 15%   { opacity: 0;   transform: scaleX(.04); }
  18%       { opacity: .95; transform: scaleX(1); }
  23%       { opacity: .25; transform: scaleX(.42); }
  30%, 100% { opacity: 0;   transform: scaleX(.2); }
}
@keyframes bfRbFold {
  0%, 20%   { opacity: 0;   transform: translateX(-10px); }
  29%, 100% { opacity: .98; transform: translateX(0); }
}
/* 글자 셋은 번들의 움직임 그대로다. 자간 변화만 뺐다 — 자간을
   애니메이션하면 매 프레임 줄을 다시 재게 되고, 그것은 이 사이트가
   피하기로 한 일이다(transform 과 opacity 만 움직인다). */
@keyframes bfRbCopyA {
  0%, 18%   { opacity: 0; transform: translateX(18px); }
  34%, 100% { opacity: 1; transform: translateX(0); }
}
@keyframes bfRbCopyB {
  0%, 20%   { opacity: 0; transform: translateY(12px); }
  35%, 100% { opacity: 1; transform: translateY(0); }
}
@keyframes bfRbCopyC {
  0%, 22%   { opacity: 0; transform: translateX(-18px); }
  36%, 100% { opacity: 1; transform: translateX(0); }
}
@keyframes bfRbRail {
  0%, 34%   { transform: scaleX(0); }
  49%, 100% { transform: scaleX(1); }
}
@keyframes bfRbArrow {
  0%, 44%   { opacity: 0; transform: translateY(-50%) scale(.86); }
  48%       { opacity: 1; transform: translateY(-50%) scale(1.03); }
  52%, 100% { opacity: 1; transform: translateY(-50%) scale(1); }
}
@keyframes bfRbClaim {
  0%, 36%   { opacity: 0; transform: translateY(8px); }
  50%, 100% { opacity: 1; transform: translateY(0); }
}
@keyframes bfRbSweepSoft {
  0%, 47%   { opacity: 0;   transform: translateX(-450px) skewX(-18deg); }
  50%       { opacity: .72; }
  65%       { opacity: .72; transform: translateX(1940px) skewX(-18deg); }
  69%, 100% { opacity: 0;   transform: translateX(1940px) skewX(-18deg); }
}
@keyframes bfRbSweepCore {
  0%, 49%   { opacity: 0;   transform: translateX(-500px) skewX(-18deg); }
  52%       { opacity: .92; }
  64%       { opacity: .92; transform: translateX(1950px) skewX(-18deg); }
  68%, 100% { opacity: 0;   transform: translateX(1950px) skewX(-18deg); }
}
@keyframes bfRbNode {
  0%, 51%   { opacity: .22; transform: scale(.72); }
  54%       { opacity: 1;   transform: scale(1.55); }
  59%, 100% { opacity: .55; transform: scale(1); }
}
@keyframes bfRbSettle {
  0%, 59%   { opacity: 0;   transform: scaleX(.1); }
  67%, 100% { opacity: .52; transform: scaleX(1); }
}

/* 좁은 화면 — 리본은 폭에 매인 그림이라 저절로 줄지만, 글자는 함께
   줄면 읽히지 않는다. 400px 화면에서 5.75cqw 는 23px 이다. 그래서
   여기서는 세 낱말을 한 줄씩 쌓고 그림은 뒤로 물린다. */
@media (max-width: 720px) {
  /* 좁은 화면에서도 구성은 넓은 화면과 같다(2026-09-06, 사용자
     지시): 낱말은 리본의 밝은 빗금 위에 그대로 서고, 크기만
     그림과 함께 줄어든다 — 자리도 크기도 cqw 로 적혔으므로
     줄일 것이 없다. 세 낱말을 세로로 쌓고 바탕판을 깔던 법(2026-09-04
     → 09-06)은 여기서 끝난다: 그림 위에 서면 판이 필요 없다.
     남는 것은 아래 줄 하나다 — 영문 한 줄은 그림 폭을 다 쓰고
     글자만 조금 큼직하다. 그대로 줄이면 7px 가 되어 읽힐 수 없다. */
  .bf-rb { margin-bottom: 40px; }
  /* 오른쪽 끝의 3%는 화살표 머리의 자리다 — 그것이 레일 밖으로
     9px 나와 있다.
     문장을 상자 위로 조금 들어 올린다(2026-09-07, 사용자: 문장 밑에
     숨 쉴 자리가 없다). 잰 값이다: 좁은 화면에서 문장의 밑선과 리본의
     윗변(상자 높이의 27.71%) 사이가 320px 에서 0.9px, 390px 에서 2px
     밖에 없었다 — 글자만 그림보다 덜 줄기 때문이다. 상자 밖으로
     나가도 되는 까닭은 위에 아무것도 없어서다: 리본이 곧 이 섹션의
     머리이고, 그 위는 섹션의 여백이다. */
  .bf-rb__claim { width: 96.5%; top: -1.6%; }
  .bf-rb__claimText { font-size: 3.1cqw; margin-top: 1.4cqw; }
}

/* --- 장소 -------------------------------------------------- */
/* 끼워 넣던 구글 지도는 걷었다(2026-09-04) — 그 자리에는 사진이 서고,
   지도는 아래 두 링크가 맡는다. 두 열이던 배치도 함께 걷혔다: 오른쪽
   열에 서 있던 것이 그 지도뿐이었다.
   덤으로 이 페이지는 다시 바깥 자원을 하나도 부르지 않는다 — 지도가
   심던 구글 쿠키도 없다. */
.bf-venue { display: block; }
/* 사진은 본문 폭을 다 쓴다. 비율을 못박고 잘라 맞춘다 — 파일마다
   높이가 다르면 섹션의 키가 사진에 따라 들쭉날쭉해진다. */
.bf-venue__photo {
  margin: 0 0 40px; border-radius: var(--bf-radius-2); overflow: hidden;
  background: var(--bf-surface);
}
.bf-venue__photo img {
  display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
}
.bf-venue__name { font-size: 24px; font-weight: 700; margin: 0; word-break: keep-all; }
/* 이 문장은 위 이름의 설명이다 — 이름에 붙여 둔다 */
.bf-lead.bf-venue__lead { margin-top: 8px; }
/* 주소는 카드가 아니라 글이다(2026-09-04, 사용자 지시). 면도 테두리도
   안쪽 여백도 걷었다 — 라벨과 두 줄의 배치만 남는다. */
.bf-venue__addr {
  display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 10px 12px;
  font-size: 17px; color: var(--bf-fg-muted); margin-top: 24px;
  font-variant-numeric: tabular-nums;
}
/* 두 줄로 고정한다: 윗줄에 라벨, 아랫줄에 주소.
   길이에 따라 배치가 달라지면 두 언어가 다른 카드로 보인다. */
.bf-venue__addrLabel { grid-area: 1 / 1; }
.bf-venue__addrText { grid-area: 2 / 1 / 3 / 3; }
/* 라벨은 물러나지 않는다 — 이 줄에서 가장 먼저 눈에 들어와야 한다 */
.bf-venue__addrLabel { display: inline-flex; align-items: center; gap: 7px; color: var(--bf-fg); font-weight: 600; }
.bf-venue__pin { width: 17px; height: 17px; color: var(--bf-300); }
.bf-venue__addrText { color: var(--bf-fg-muted); }
/* 마지막 낱말과 복사 단추는 함께 접힌다 — 단추만 홀로 떨어지지 않게 */
.bf-venue__addrTail { white-space: nowrap; }
/* 복사 단추 — 주소 줄 끝에 이어 붙는 조용한 동작. 누르면 아이콘과
   글자가 바뀌고 잠시 뒤 제자리로 돌아온다. 주소 글보다 작으므로
   기준선이 아니라 가운데로 맞춘다 — 기준선에 걸면 단추가 내려앉는다.
   앞 여백은 글자가 아니라 단추의 것이다: 줄이 접힐 때 따라 붙는다. */
.bf-copy {
  display: inline-flex; align-items: center; gap: 6px;
  vertical-align: middle; margin-left: 10px;
  font-family: var(--bf-font); font-size: 12px; font-weight: 600;
  color: var(--bf-cta-2-fg); background: var(--bf-cta-2-bg);
  border: 1px solid var(--bf-cta-2-border); border-radius: 2px;
  padding: 4px 10px; cursor: pointer;
  transition: background var(--bf-dur-1) var(--bf-ease);
}
.bf-copy:hover { background: var(--bf-cta-2-bg-hover); }
.bf-copy .bf-ico { width: 13px; height: 13px; }
.bf-copy__ico--done, .bf-copy.is-done .bf-copy__ico { display: none; }
.bf-copy.is-done .bf-copy__ico--done { display: block; }
/* 지도 링크 둘 — 나란히 서고, 좁으면 아래로 접힌다. 화살표는 이 사이트를
   떠난다는 표시이므로 글자를 따라 색이 바뀐다. */
.bf-venue__maps { display: flex; flex-wrap: wrap; gap: 10px 20px; margin-top: 20px; }
.bf-venue__map {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 14px; font-weight: 600;
}
.bf-venue__mapIco { width: 14px; height: 14px; transition: transform var(--bf-dur-1) var(--bf-ease); }
.bf-venue__map:hover .bf-venue__mapIco { transform: translate(2px, -2px); }

/* --- 파트너십 페이지 --------------------------------------- */
/* 등급은 가로로 놓인 카드다 — 순위는 2px 테두리 색으로 읽힌다 */
/* 카드는 본문 열을 다 쓰지 않는다. 폭을 다 쓰면 짧은 혜택 항목 사이가
   벌어져 한 줄을 읽고 다음 줄을 찾는 데 눈이 멀리 움직인다 — 읽는
   덩어리는 좁을수록 빠르다. */
.bf-tiers { display: flex; flex-direction: column; gap: 16px; margin-top: 0; max-width: 660px; }
.bf-tier {
  background: var(--bf-surface); border: 2px solid var(--bf-hairline);
  border-radius: var(--bf-radius-2); padding: 24px 26px 26px;
}
.bf-tier--coHost   { border-color: var(--bf-100); }
.bf-tier--title    { border-color: var(--bf-tier-title); }
.bf-tier--platinum { border-color: var(--bf-tier-platinum); }
.bf-tier--gold     { border-color: var(--bf-tier-gold); }
.bf-tier--silver   { border-color: var(--bf-tier-silver); }
.bf-tier__head { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; flex-wrap: wrap; }
.bf-tier__name { font-size: 26px; font-weight: 800; margin: 0; letter-spacing: -0.02em; }
.bf-tier__limit { font-size: 13px; color: var(--bf-fg-muted); margin-top: 4px; }
.bf-tier__price { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.bf-tier__benefits {
  list-style: none; margin: 18px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 20px;
  font-size: 14px; color: var(--bf-fg-muted);
}
.bf-tier__benefits li { padding-left: 14px; position: relative; text-wrap: pretty; word-break: keep-all; }
.bf-tier__benefits li::before { content: ""; position: absolute; left: 0; top: 9px; width: 5px; height: 5px; background: var(--bf-600); border-radius: 50%; }
.bf-tier__band { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
/* 카드 아래 주석 — 카드 무리의 일부이므로 본문 리듬(44px)이 아니라
   가까이 붙는다 */
.bf-tiers__note { font-size: 13.5px; color: var(--bf-fg-faint); margin: 10px 0 0; }

.bf-past { margin-top: 88px; border-top: 1px solid var(--bf-rule); padding-top: 48px; }
.bf-past__group { margin-top: 32px; }
.bf-past__label { font-size: 13px; font-weight: 600; letter-spacing: var(--bf-track-eyebrow); color: var(--bf-fg-faint); margin: 0; }

/* --- 기관별 가치 제안 ---------------------------------------
   기관 유형이 넷이고 유형마다 여섯 항목이라, 한 화면에 다 펼치면
   어느 것도 읽히지 않는다. 탭으로 한 번에 하나만 보여 준다.
   스크립트가 없으면 탭 목록이 숨은 채 네 패널이 모두 보인다. */
.bf-tabs__list {
  display: flex; flex-wrap: wrap; gap: 4px;
  border-bottom: 1px solid var(--bf-rule); margin-bottom: 32px;
}
/* 탭 이름은 소제목과 같은 크기다 — 패널의 제목 노릇을 한다 */
.bf-tab {
  font-family: var(--bf-font); font-size: 20px; font-weight: 600;
  color: var(--bf-fg-muted); background: none; border: 0;
  padding: 12px 18px; cursor: pointer; position: relative;
  border-radius: var(--bf-radius-2) var(--bf-radius-2) 0 0;
  transition: color var(--bf-dur-1) var(--bf-ease), background var(--bf-dur-1) var(--bf-ease);
}
.bf-tab:hover { color: var(--bf-100); background: var(--bf-surface); }
.bf-tab.is-active { color: var(--bf-fg); }
/* 활성 탭의 밑줄은 목록의 헤어라인을 덮는다 */
.bf-tab.is-active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--bf-300);
}

/* 겹화살표 표시 — 넓은 화면에는 없다(탭이 다 보인다). 좁은 화면의
   규칙은 아래 미디어 쿼리에 있다. */
.bf-tabs__scroller { position: relative; }
.bf-tabs__hint { display: none; }

/* 탭이 붙으면 패널 안의 유형 이름은 탭이 대신 말한다 */
.bf-tabs.is-tabbed .bf-inst[hidden] { display: none; }
.bf-tabs.is-tabbed .bf-inst__type { display: none; }
.bf-tabs:not(.is-tabbed) .bf-inst + .bf-inst { margin-top: 64px; }

.bf-inst__type { font-size: 13px; font-weight: 600; letter-spacing: var(--bf-track-eyebrow); color: var(--bf-200); }

/* 패널 안은 위에서 아래로 한 줄기다 — 슬라이드의 좌우 배치를
   그대로 옮기면 좁은 열에서 어느 쪽도 숨을 못 쉰다. */
/* 컨셉 한 줄과 프레임 칩. 칩은 언제나 오른쪽 끝에 있고, 왼쪽 글이
   길어지면 칩이 밀려 내려가는 대신 글이 여러 줄로 접힌다. */
.bf-inst__head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 24px; flex-wrap: nowrap; margin-top: 12px;
}
.bf-inst__head .bf-lead { flex: 1 1 auto; min-width: 0; }
.bf-inst__head .bf-frame__badge { flex: none; }
.bf-inst__value { margin-top: 40px; }
.bf-inst__frame { margin-top: 44px; }
.bf-inst .bf-cards { margin-top: 44px; }
/* .bf-lead가 파일 뒤쪽에 있으므로 두 클래스를 함께 걸어야 이긴다 */
.bf-lead.bf-inst__closing { margin-top: 56px; max-width: none; }

/* 프레임 이름은 스스로 서는 칩이다 */
.bf-frame__badge {
  display: inline-block; font-size: 15px; font-weight: 700; color: var(--bf-200);
  border: 1px solid var(--bf-600); border-radius: var(--bf-radius-2);
  padding: 7px 14px; word-break: keep-all; white-space: nowrap;
}
.bf-frame__steps {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px;
}
.bf-frame__steps li { display: flex; align-items: center; gap: 10px; font-size: 17px; color: var(--bf-fg-muted); word-break: keep-all; }
.bf-frame__steps li + li::before { content: "→"; color: var(--bf-fg-faint); }
.bf-frame__steps span {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--bf-800); color: var(--bf-100);
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
}

/* --- 파트너십: 상세 비교 표 --------------------------------
   좁은 화면에서는 표가 자기 안에서 가로로 스크롤된다 — 페이지가
   가로로 밀리면 안 된다. */
.bf-benefits { margin-top: 88px; border-top: 1px solid var(--bf-rule); padding-top: 48px; }
/* 표는 자기 안에서 가로로 스크롤된다 — 페이지가 가로로 밀리면
   안 된다. 값은 줄바꿈하지 않는다: 한 칸이 세 줄이 되면 등급 간
   비교가 불가능해진다. 대신 표를 넓게 두고 밀어서 본다. */
/* 데스크톱에서는 감싼 상자에 overflow를 주지 않는다. overflow가 있으면
   그 상자가 스크롤 컨테이너가 되고, 붙어 있는(sticky) 머리글이 페이지가
   아니라 그 상자를 기준으로 잡혀 아예 붙지 않는다. 표가 들어가지 않는
   폭에서만 아래 미디어 쿼리로 가로 스크롤을 켠다. */
.bf-table__wrap { margin-top: 28px; }
/* border-collapse는 separate여야 한다. collapse에서는 테두리가 칸이
   아니라 표에 속해서, 머리글이 붙어(sticky) 아래로 떠 있는 동안 그
   뒤에 있는 줄들의 세로 테두리가 머리글 위로 새어 나온다 — 선이
   표 밖까지 올라간 것처럼 보이던 원인이다. */
.bf-table { --bf-grp-w: 170px; width: 100%; border-collapse: separate; border-spacing: 0; font-size: 16px; min-width: 900px; }
.bf-table th, .bf-table td {
  padding: 13px 10px; text-align: center; border-bottom: var(--bf-border);
  white-space: nowrap;
}
/* 머리글 — 위에 표를 여는 선, 아래에 본문과 갈라 놓는 굵은 선.
   붙어 있는 동안에도 두 선이 함께 따라간다. */
.bf-table thead th {
  position: sticky; top: 64px; background: var(--bf-bg); z-index: 2;
  border-top: 1px solid var(--bf-hairline);
  border-bottom: 2px solid var(--bf-700);
}
/* 항목 이름은 왼쪽에 붙어 있는다 — 가로로 밀어도 무엇을 비교하는지
   보이지 않으면 표가 아니다. width:1%로 내용 폭까지 줄여 남는
   자리가 등급 열로 고르게 가게 한다 — 그러지 않으면 첫 열 뒤에만
   빈 자리가 몰린다. */
.bf-table th[scope="row"] {
  position: sticky; left: var(--bf-grp-w); z-index: 1; background: var(--bf-bg);
  text-align: left; color: var(--bf-fg-muted); font-weight: 500;
  width: 1%; padding-right: 28px;
}
.bf-table thead th:first-child { left: 0; z-index: 3; }
/* 아래 선택자들이 모두 .bf-table th / .bf-table td 를 포함하는 이유:
   기본 칸 규칙이 `.bf-table th, .bf-table td`라 특정도가 (0,1,1)이고,
   클래스 하나짜리 규칙 (0,1,0)은 파일 뒤에 있어도 그것을 이기지
   못한다. 테두리·정렬·배경이 조용히 무시되던 원인이다. */

/* 표 안의 두 머리글 — 열 이름과 묶음 이름. 둘 다 소제목 크기다.
   th[scope]가 이미 그 열·줄의 제목이므로 안에 h3을 또 넣지 않는다. */
.bf-table th.bf-table__itemhead { text-align: center; font-size: 20px; font-weight: 600; color: var(--bf-fg); }

/* 묶음 열 — 자기 줄들을 세로로 아우른다. 폭을 변수로 고정해야
   항목 열이 그 옆에 붙을 자리를 알 수 있다. */
.bf-table th.bf-table__grp {
  position: sticky; left: 0; z-index: 1; background: var(--bf-bg);
  width: var(--bf-grp-w); min-width: var(--bf-grp-w);
  text-align: left; vertical-align: middle;
  font-size: 20px; font-weight: 600; color: var(--bf-fg);
  border-right: 1px solid var(--bf-hairline);
  /* 이 칸은 묶음 전체를 아우르므로 그 아래 테두리가 곧 묶음의
     경계다. is-group-end는 마지막 줄에 붙지만 이 칸은 첫 줄에
     있어서 그 규칙이 닿지 않는다 — 여기서 따로 긋는다. */
  border-bottom: 1px solid var(--bf-700);
}
/* 묶음이 끝나는 줄은 아래 테두리를 진하게 — 묶음 사이의 경계다 */
.bf-table tr.is-group-end th, .bf-table tr.is-group-end td { border-bottom-color: var(--bf-700); }

/* 항목 열과 등급 열 사이의 경계. 선은 첫 등급 열의 왼쪽 테두리로
   긋는다 — 그래야 머리글부터 마지막 줄까지 표의 높이만큼만
   이어진다. */
.bf-table th.bf-table__col--0,
.bf-table td.bf-table__col--0 { border-left: 1px solid var(--bf-hairline); }

/* 등급 열의 얼룩말 무늬 — 한 열 건너 표면을 한 단계 올린다. 가로로
   긴 줄에서 눈이 열을 잃지 않게 하는 장치다. rowspan 때문에 줄마다
   칸 수가 달라지므로 nth-child로는 셀 수 없다 — 열 번호를 클래스로
   찍는다. */
.bf-table th.bf-table__col--0, .bf-table td.bf-table__col--0,
.bf-table th.bf-table__col--2, .bf-table td.bf-table__col--2 { background: var(--bf-surface); }
.bf-table__tier span { display: block; font-size: 17px; font-weight: 700; }
.bf-table__tier small { display: block; font-size: 13.5px; font-weight: 500; color: var(--bf-fg-muted); margin-top: 3px; font-variant-numeric: tabular-nums; }
.bf-table__tier--title    { border-bottom: 2px solid var(--bf-tier-title); }
.bf-table__tier--platinum { border-bottom: 2px solid var(--bf-tier-platinum); }
.bf-table__tier--gold     { border-bottom: 2px solid var(--bf-tier-gold); }
.bf-table__tier--silver   { border-bottom: 2px solid var(--bf-tier-silver); }
.bf-table td.is-none { color: var(--bf-fg-faint); }
/* '있음' 표시 — 글자 O가 아니라 그려진 동그라미다. 숫자 0으로
   읽히지 않게 하려는 것이 요점이다. */
.bf-table__yes {
  display: inline-block; width: 15px; height: 15px;
  border: 2px solid var(--bf-400); border-radius: 50%;
  vertical-align: -2px;
}

/* --- 부스 -------------------------------------------------- */
.bf-booths { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 28px; }
.bf-booth { background: var(--bf-surface); border: var(--bf-border); border-radius: var(--bf-radius-2); padding: 18px; }
.bf-booth__tier { font-size: 11.5px; font-weight: 600; letter-spacing: var(--bf-track-eyebrow); color: var(--bf-fg-faint); }
.bf-booth__name { font-size: 17px; font-weight: 600; margin-top: 8px; }
.bf-booth__desc { font-size: 13.5px; color: var(--bf-fg-muted); margin-top: 6px; word-break: keep-all; }
.bf-booth__size { font-size: 14px; font-weight: 600; margin-top: 12px; font-variant-numeric: tabular-nums; color: var(--bf-100); }

/* --- 등록 폼 -----------------------------------------------
   폼은 한 틀 안에 든다(2026-09-03) — 페이지에서 선을 모두 걷어 낸
   뒤라, 테두리를 두른 것이 이 하나뿐이므로 눈이 먼저 여기로 간다.
   테두리는 아주르(--bf-600)다: 카드의 강조 테두리와 같은 색이고,
   한 섹션에 강조 무리는 하나뿐인데 이 섹션에서는 그 자리가 비어
   있었다.
   면은 채우지 않는다. 밝게 채우면 입력칸 테두리가 판에 대해 3:1
   (WCAG 1.4.11)을 잃는다 — --bf-surface-hi 로 채웠을 때 2.85 로
   떨어지는 것을 재어 보았다. 대신 위쪽에서 옅은 빛만 얹는다:
   4%에서 입력칸 테두리가 3.15 로 남는다(5%면 3 아래로 내려간다).
   background-image 로 쓰는 것은 단축형이 다른 배경 속성을 지우기
   때문이다.
   안쪽 여백은 창 폭을 따라간다 — 좁은 화면에서 32px 은 입력칸의
   자리를 너무 빼앗는다. */
/* 액자도 면도 없다(2026-09-04, 사용자 지시). 폭 상한과 가운데 정렬만
   남는다 — 입력칸 자체의 테두리가 이미 서식의 모양을 그린다. 안쪽
   여백까지 두면 있지도 않은 액자의 안쪽이 되므로 함께 걷었다. */
.bf-form { margin-top: 40px; max-width: 560px; }
.bf-form__grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/* 한 줄을 다 쓰는 항목. 좁은 화면에서는 격자가 한 칸이 되므로
   이 규칙은 저절로 아무 일도 하지 않는다. */
.bf-field--wide { grid-column: 1 / -1; }
.bf-field { display: flex; flex-direction: column; gap: 6px; }
.bf-field label { font-size: 13.5px; font-weight: 500; color: var(--bf-fg-muted); }
/* 필수 항목 — 라벨 오른쪽 위에 아주르 별표 하나 */
.bf-field--req label::after {
  content: "*"; color: var(--bf-300);
  font-size: 0.85em; vertical-align: super; margin-left: 3px;
}
.bf-field input {
  height: 44px; padding: 0 14px; font-family: var(--bf-font); font-size: 15px;
  color: var(--bf-fg); background: var(--bf-surface); border: 1px solid var(--bf-field-line);
  border-radius: var(--bf-radius-1); transition: border-color var(--bf-dur-1) var(--bf-ease);
}
.bf-field input:focus { outline: none; border-color: var(--bf-400); }
/* 관심분야 셀렉트 — input과 같은 옷. appearance를 벗기므로 화살표는
   래퍼가 그린다. color-scheme dark: 이것이 없으면 펼친 목록이
   브라우저 기본 흰색으로 뜬다. */
.bf-field select {
  width: 100%; height: 44px; padding: 0 42px 0 14px; appearance: none;
  font-family: var(--bf-font); font-size: 15px; color: var(--bf-fg);
  background: var(--bf-surface); border: 1px solid var(--bf-field-line);
  border-radius: var(--bf-radius-1); cursor: pointer; color-scheme: dark;
  transition: border-color var(--bf-dur-1) var(--bf-ease);
}
.bf-field select:focus { outline: none; border-color: var(--bf-400); }
.bf-select { position: relative; display: block; }
.bf-select::after {
  content: ""; position: absolute; right: 17px; top: 50%; width: 7px; height: 7px;
  border-right: 2px solid var(--bf-fg-faint); border-bottom: 2px solid var(--bf-fg-faint);
  transform: translateY(-70%) rotate(45deg); pointer-events: none;
}
/* 허니팟 — 사람 눈에는 보이지 않는다 */
.bf-form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.bf-consent { display: flex; align-items: baseline; gap: 10px; margin-top: 18px; font-size: 13.5px; }
.bf-consent input[type="checkbox"] { accent-color: var(--bf-400); width: 15px; height: 15px; flex: none; transform: translateY(2px); }
/* 글과 단추는 한 덩이다 — 단추가 마지막 낱말을 따라 줄을 넘어간다 */
.bf-consent__text { line-height: 1.5; }
.bf-consent label { color: var(--bf-fg-muted); }
.bf-consent button {
  font-family: var(--bf-font); font-size: 12.5px; font-weight: 600; color: var(--bf-300);
  background: none; border: none; padding: 0; cursor: pointer; white-space: nowrap;
  /* 글줄에 얹히는 단추다 — 앞말과 한 칸 띄우고 같은 줄에 앉힌다 */
  margin-left: 8px; vertical-align: baseline;
}
.bf-consent button:hover { color: var(--bf-200); }
/* 단추는 가운데다(2026-09-04). 상태 문구는 그 아래 줄로 내려간다 —
   단추 옆에 두면 문구가 길어질 때 단추가 왼쪽으로 밀려 축이 흔들린다. */
.bf-form__actions {
  margin-top: 28px; display: flex; flex-direction: column;
  align-items: center; gap: 12px;
}
.bf-form__buttons {
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: center; gap: 16px;
}
.bf-form__msg { font-size: 13.5px; color: var(--bf-fg-muted); }
.bf-form__msg--error { color: var(--bf-100); }

/* --- 동의 모달 --------------------------------------------- */
.bf-dialog {
  background: var(--bf-surface); color: var(--bf-fg);
  border: var(--bf-border); border-radius: var(--bf-radius-2);
  padding: 28px; max-width: 640px; width: calc(100% - 40px);
  max-height: 84vh; overflow-y: auto;   /* 방침 전문이 들어간다 */
}
.bf-dialog__policyTitle {
  font-size: 17px; font-weight: 700; margin: 28px 0 0;
  padding-top: 24px; border-top: 1px solid var(--bf-rule); word-break: keep-all;
}

/* --- 방침 본문 (모달과 /privacy가 함께 쓴다) ----------------- */
.bf-policy { font-size: 14.5px; line-height: 1.7; color: var(--bf-fg-muted); }
.bf-policy__sec { margin-top: 26px; }
.bf-policy__h { font-size: 15.5px; font-weight: 700; color: var(--bf-fg); margin: 0 0 10px; word-break: keep-all; }
.bf-policy__p { margin: 10px 0 0; word-break: keep-all; text-wrap: pretty; }
.bf-policy__label { margin-top: 14px; font-size: 13px; font-weight: 600; color: var(--bf-fg); }
.bf-policy__list { margin: 8px 0 0; padding-left: 18px; }
.bf-policy__list li { margin-top: 4px; word-break: keep-all; }
.bf-policy__rows { margin: 10px 0 0; display: grid; grid-template-columns: 1fr; gap: 2px 16px; }
.bf-policy__rows dt { font-weight: 600; color: var(--bf-fg); word-break: keep-all; }
.bf-policy__rows dd { margin: 0 0 10px; word-break: keep-all; }
@media (min-width: 560px) {
  .bf-policy__rows { grid-template-columns: 1fr 1fr; }
  .bf-policy__rows dd { margin-bottom: 0; }
}
.bf-dialog form.bf-dialog__dismiss {
  /* `.bf-dialog form`의 margin이 폼 일반 규칙으로 묻는다 — absolute여도
     margin-top만큼 내려앉으므로 선택자를 높여 0으로 되돌린다.
     top은 첫 줄(아이브로우·제목)과 눈높이가 맞는 값이다. */
  position: absolute; top: 22px; right: 20px; margin: 0;
}
.bf-contact form.bf-dialog__dismiss { top: 24px; right: 24px; }
.bf-dialog__x {
  display: grid; place-items: center; width: 34px; height: 34px;
  background: none; border: 0; color: var(--bf-fg-faint); cursor: pointer;
}
.bf-dialog__x:hover { color: var(--bf-300); }
.bf-dialog__x .bf-ico { width: 18px; height: 18px; }
.bf-dialog {
  opacity: 0; transform: translateY(8px);
  transition: opacity .18s ease, transform .18s ease,
              overlay .18s ease allow-discrete, display .18s ease allow-discrete;
}
.bf-dialog[open] { opacity: 1; transform: none; }
@starting-style { .bf-dialog[open] { opacity: 0; transform: translateY(8px); } }
.bf-dialog::backdrop {
  background: color-mix(in srgb, var(--bf-bg) 78%, transparent);
  opacity: 0;
  transition: opacity .18s ease,
              overlay .18s ease allow-discrete, display .18s ease allow-discrete;
}
.bf-dialog[open]::backdrop { opacity: 1; }
@starting-style { .bf-dialog[open]::backdrop { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .bf-dialog, .bf-dialog::backdrop { transition: none; transform: none; }
}
.bf-dialog h3 { font-size: 17px; font-weight: 700; margin: 0; padding-right: 40px; word-break: keep-all; }
.bf-dialog pre {
  font-family: var(--bf-font); font-size: 14px; line-height: 1.7;
  color: var(--bf-fg-muted); white-space: pre-wrap; word-break: keep-all; margin: 16px 0 0;
}
.bf-dialog form { margin: 24px 0 0; text-align: right; }

/* --- 스폰서십 문의 창 ---------------------------------------
   동의 모달과 같은 판이되 읽을거리가 아니라 주소 두 줄이다:
   폭을 좁히고 여백을 늘려 카드처럼 선다. 파란 채움은 쓰지 않는다 —
   주소는 링크 색으로 충분하다. */
.bf-contact { max-width: 460px; padding: 32px; }
h3.bf-contact__title {
  font-size: 25px; font-weight: 700; line-height: 1.25;
  margin: 12px 0 0; color: var(--bf-fg); word-break: keep-all; text-wrap: balance;
  /* 닫기 단추가 앉는 자리는 비워 둔다 — 제목이 그 밑으로 들어가면
     글자와 단추가 겹쳐 읽힌다. */
  padding-right: 40px;
}
h3.bf-contact__title:lang(ko) { line-height: 1.45; }
.bf-contact__rows { margin: 26px 0 0; padding-top: 26px; border-top: 1px solid var(--bf-rule); }
.bf-contact__rows dt { font-size: 13px; font-weight: 600; color: var(--bf-fg-faint); }
.bf-contact__rows dd { margin: 4px 0 0; font-size: 17px; font-weight: 600; }
.bf-contact__rows dd + dt { margin-top: 20px; }
.bf-contact__rows a { color: var(--bf-fg); text-decoration: none; }
.bf-contact__rows a:hover { color: var(--bf-200); }

/* --- 마지막 CTA --------------------------------------------
   배경은 히어로와 같은 스카이라인이다(2026-08-13). 아주르로 물든
   면도, 위아래를 닫던 아주르 헤어라인도 걷어 냈다 — 이 띠는 앞
   섹션에서 그대로 흘러나와 푸터로 그대로 넘어간다. 자르는 선도,
   덮는 어둠도 두지 않는다. */
.bf-closing {
  position: relative; text-align: center; overflow: hidden;
  background: var(--bf-bg);
  /* 띠의 높이 — 그림의 비율을 따르되 화면의 4분의 3을 넘지 않는다
     (2026-08-13: 1/2 → 3/4). 320px는 제목·날짜·버튼이 서는 최소치다.
     aspect-ratio로 쓰면 안 된다 — 높이가 잘릴 때 브라우저가 폭까지
     같이 줄여 띠가 화면 절반짜리 섬이 된다. 높이를 직접 적는다.
     그림도 이 값을 알아야 하므로 변수로 둔다. */
  --bf-cta-h: max(320px, min(calc(100vw * 780 / 1440), 75vh));
  height: var(--bf-cta-h);
}
/* 그림은 세로로도 가로로도 잘리지 않는다 — 폭이 치수를 정하고
   높이는 비율이 따라온다. 폭의 상한은 사이트 본문 폭(1200px,
   .bf-wrap과 같은 값)이다(2026-08-13): 띠가 아무리 높아져도 도시가
   본문보다 넓게 퍼지지 않는다. 남는 높이는 그림 위의 하늘이 되므로
   바닥에 붙인다 — 가운데에 두면 기단이 허공에 뜬다. */
.bf-closing__svg {
  position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  width: min(1200px, calc(var(--bf-cta-h) * 1440 / 780));
  height: auto; aspect-ratio: 1440 / 780;
}
/* 이 띠에는 덮는 것이 없다 — 스크림도, 마스크도, 그림자도.
   활자를 지키는 것은 어둠이 아니라 대비다: 흰 제목과 채운 버튼. */
.bf-closing__in {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 0 32px;
}
.bf-closing .bf-h2 { font-size: 52px; }
.bf-closing__meta { font-size: 17px; font-weight: 500; color: var(--bf-fg-muted); margin-top: 18px; font-variant-numeric: tabular-nums; }
.bf-closing__cta { display: flex; gap: 14px; margin-top: 38px; justify-content: center; }

/* --- 푸터 --------------------------------------------------
   위 테두리는 없다 — 마지막 CTA 띠의 아래 테두리가 이미 그 선이다.
   둘을 두면 얇은 선과 굵은 선이 나란히 놓인다. */
.bf-footer { border-top: 0; }
.bf-footer__in {
  max-width: 1200px; margin: 0 auto; padding: 40px 32px;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.bf-footer__host { font-size: 13px; color: var(--bf-fg-muted); }
.bf-footer__legal { font-size: 13px; color: var(--bf-fg-faint); margin-left: auto; }
/* 지난 행사의 해 — 한 줄로 눕는다. 숫자는 표 숫자로 둔다: 폭이
   들쭉날쭉하면 여섯 개가 줄지어 설 때 간격이 떨린다. 라벨이
   없으면 푸터에 숫자만 여섯 개 남아 무엇인지 알 수 없다. */
.bf-footer__archive { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; font-size: 13px; }
/* 라벨이 밝고 해가 어둡다(2026-09-07, 사용자) — 처음에는 반대였다.
   눌리는 것이 여섯이고 이름표가 하나이므로, 밝은 쪽을 이름표에
   주면 줄이 무엇인지부터 읽힌다. 해는 가리킬 때 밝아진다. */
.bf-footer__archiveLbl { color: var(--bf-fg-muted); }
.bf-footer__archive a { color: var(--bf-fg-faint); font-variant-numeric: tabular-nums; }
.bf-footer__archive a:hover { color: var(--bf-fg-muted); }
/* 주최사 이름 링크 — 문장 안에 있으므로 글자 색을 따라가고, 밑줄은
   가리킬 때만 나온다. 파란 낱말 하나가 문장 가운데서 튀지 않는다. */
.bf-hostlink { color: inherit; text-decoration: underline; text-decoration-color: var(--bf-700); text-underline-offset: 3px; }
.bf-hostlink:hover { color: var(--bf-200); text-decoration-color: currentColor; }
.bf-footer__legal a { color: var(--bf-fg-faint); }
.bf-footer__legal a:hover { color: var(--bf-fg-muted); }

/* --- 404 --------------------------------------------------- */
.bf-404 { min-height: calc(100vh - 65px); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 40px; }
.bf-404__code { font-size: clamp(72px, 10vw, 140px); font-weight: 900; letter-spacing: var(--bf-track-display); line-height: 1; color: var(--bf-700); font-variant-numeric: tabular-nums; }
.bf-404__title { font-size: 28px; font-weight: 700; margin-top: 24px; word-break: keep-all; }
.bf-404__body { font-size: 15px; color: var(--bf-fg-muted); margin-top: 10px; word-break: keep-all; }
.bf-404__cta { margin-top: 36px; }

/* 901~1080px — 헤더가 한 줄에 못 들어가는 구간이다. 브랜드·내비·언어·
   등록이 나란히 서려면 영어에서 1044px, 한국어에서 938px이 필요한데
   좁은 화면 헤더는 900px 아래에서야 켜진다. 그 사이에서 버튼이 화면
   밖으로 밀려 페이지 전체가 가로로 늘어났다. 여백만 줄여 넣는다 —
   항목을 빼면 그 구간에서만 내비가 달라져 더 이상해진다. */
@media (min-width: 901px) and (max-width: 1080px) {
  .bf-header__in { gap: 14px; padding: 0 20px; }
  .bf-header__nav { gap: 0; }
  .bf-header__nav a { padding: 8px 7px; font-size: 14px; }
}

/* --- 반응형 ------------------------------------------------
   ~900px 아래: 2열이 1열로 접히고 인덱스는 더 이상 붙지 않는다.
   프로그램의 시간 거터도 접혀 시각이 제목 위로 올라간다.       */
@media (max-width: 900px) {
  .bf-wrap { padding: 0 20px; }
  .bf-section__inner { grid-template-columns: 1fr; gap: 36px; padding: 64px 20px 72px; }
  .bf-head { margin-bottom: 40px; }
  .bf-venue__photo { margin-bottom: 28px; }
  .bf-head__title { font-size: 30px; }
  .bf-section--rails .bf-section__inner { padding-bottom: 28px; }
  .bf-rails--logos:last-of-type { padding-bottom: 68px; }
  .bf-rails { --bf-rail-photo: 96px; --bf-rail-item: 128px; --bf-rail-gap: 20px; gap: 18px; padding-inline: 20px; padding-bottom: 68px; }
  .bf-rails--wide { display: none; }
  .bf-rails--narrow { display: flex; }
  /* 좁은 화면에서 띠는 창 밖으로 나간다 — 사이트 폭에 가두지 않는다.
     화면이 좁을수록 한 번에 보이는 칸이 적으므로, 양옆을 비우면 띠가
     아니라 토막으로 보인다. 가장자리를 녹이던 마스크도 걷는다:
     좁은 화면에서는 그 폭이 칸 하나를 통째로 삼킨다. */
  .bf-rails { max-width: none; padding-inline: 0; }
  .bf-rail { -webkit-mask-image: none; mask-image: none; }
  .bf-index { position: static; }
  .bf-index__num { font-size: 34px; }
  /* 번호줄과 제목은 한 덩어리다. 넓은 화면에서는 24px이 그 덩어리를
     묶어 주지만, 좁은 화면에서 글자가 작아지면 같은 24px이 둘을
     떼어 놓아 번호가 제목이 아니라 위 섹션에 붙어 보인다. */
  .bf-index__title { font-size: 28px; margin-top: 10px; }
  .bf-body > * + * { margin-top: 44px; }
  /* 좁은 화면에서는 시간 거터가 들어가지 않는다. 레일을 왼쪽
     가장자리로 옮기고 시각을 제목 위에 세운다 — 세로선은 그대로
     하나로 이어진다. */
  /* 레일은 행 자신이 그린다. 시각 칸과 본문이 각자 왼쪽 테두리를
     그리면 그 사이(행의 위 여백)와 행 경계에서 선이 끊긴다 — 화면에
     보이던 토막난 세로선이 그것이다. 행 하나가 한 조각을 그리고 행이
     맞붙으므로 선은 끊기지 않는다. */
  .bf-agenda__row {
    grid-template-columns: 1fr;
    border-left: 1px solid var(--bf-700);
    padding: 14px 0 0 18px;
  }
  /* 탭은 줄을 바꾸지 않고 가로로 밀린다 — 두 줄이 되면 어느 것이
     지금 켜진 탭인지 한눈에 들어오지 않는다. 켜진 탭은 스크립트가
     끌어온다(site.js). */
  .bf-tabs__list {
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .bf-tabs__list::-webkit-scrollbar { display: none; }
  .bf-tab { flex: none; font-size: 17px; padding: 12px 14px; }
  /* 남은 방향에만 켜진다. 뒤에 있는 글자가 비쳐 읽히지 않도록 바탕에서
     번지는 그라데이션을 깔고, 그 위에 겹화살표가 그쪽으로 살짝 기울었다
     돌아온다 — 움직임이 있어야 '더 있다'로 읽힌다. 모션 감소 설정에서는
     전역 규칙이 이 애니메이션을 끈다. */
  .bf-tabs__hint {
    display: flex; align-items: center; pointer-events: none;
    position: absolute; top: 0; bottom: 1px; width: 66px; padding-right: 4px;
    opacity: 0; transition: opacity var(--bf-dur-2) var(--bf-ease);
    color: var(--bf-fg-muted);
  }
  /* 반투명한 것은 화살표뿐이다. 표시 전체에 opacity를 걸면 그 아래
     그라데이션까지 비쳐 글자가 화살표를 뚫고 나온다. */
  .bf-tabs__hint .bf-ico {
    width: 18px; height: 18px; stroke-width: 2.5; opacity: .7;
    animation: bfNudge 2.6s var(--bf-ease) infinite;
  }
  .bf-tabs__hint--end {
    right: 0; justify-content: flex-end;
    background: linear-gradient(to right, transparent, var(--bf-bg) 42%, var(--bf-bg) 100%);
  }
  .bf-tabs__hint--start {
    left: 0; justify-content: flex-end; transform: scaleX(-1);
    background: linear-gradient(to right, transparent, var(--bf-bg) 42%, var(--bf-bg) 100%);
  }
  .bf-tabs__scroller.has-end .bf-tabs__hint--end,
  .bf-tabs__scroller.has-start .bf-tabs__hint--start { opacity: 1; }
  .bf-agenda__row + .bf-agenda__row { border-top: var(--bf-border); }
  .bf-agenda__rail {
    border-right: 0; border-left: 0;
    text-align: left; padding: 0; display: block;
  }
  .bf-row__time { padding: 0; font-size: 12.5px; }
  /* 점은 행의 테두리 위에 얹힌다. 23px = 행의 왼쪽 여백 18 + 지름의
     절반 4.5 + 테두리 두께의 절반 0.5. 세로 위치는 기본 규칙(50%)
     그대로 — 이때 레일의 높이는 시각 한 줄이므로 그 절반이 곧 줄의
     한가운데다. 상수로 박았더니 행간이 넓은 한글에서 1px 떠 보였다. */
  .bf-row__dot { left: -23px; right: auto; }
  .bf-row__body {
    border-top: 0; border-left: 0;
    padding: 6px 0 18px; grid-template-columns: 1fr; gap: 10px;
  }
  .bf-agenda__row:first-child .bf-row__body { border-top: 0; }
  .bf-chip { justify-self: start; }
  /* 좁은 화면에서는 막대가 세로로 선다. 가로 막대와 그 아래 수치로
     나누면 어느 색이 어느 숫자인지 알 수 없다 — 각 수치가 자기 색
     옆에 서고, 색 띠의 높이가 곧 값이다. */
  .bf-who__bar { display: none; }
  .bf-who__legend { flex-direction: column; gap: 0; height: 420px; margin-top: 20px; }
  .bf-who__cell {
    width: 100%; flex: var(--p) 1 0; min-height: 0;
    border-left: 8px solid var(--c); padding: 0 0 0 16px;
    display: flex; align-items: center; gap: 12px;
  }
  .bf-who__val { font-size: 24px; }
  .bf-who__lbl { margin-top: 0; }
  .bf-pillars { grid-template-columns: 1fr; gap: 28px; }
  .bf-stats { grid-template-columns: repeat(2, 1fr); gap: 20px 16px; }
  .bf-cards { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .bf-marks--cards { grid-template-columns: repeat(2, 1fr); }
  .bf-cards--2 { grid-template-columns: 1fr; gap: 12px; }
  .bf-cards--3 { grid-template-columns: repeat(2, 1fr); }
  .bf-media__row { grid-template-columns: 104px 1fr 52px; gap: 10px; }
  .bf-week__item { grid-template-columns: 1fr; gap: 4px; }
  .bf-tier__benefits { grid-template-columns: 1fr; }
  .bf-prices__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 12px; }

  .bf-tab { font-size: 17px; padding: 10px 13px; }
  /* 좁은 화면에서는 칩이 글 아래로 내려간다 — 나란히 설 폭이 없다 */
  .bf-inst__head { flex-wrap: wrap; gap: 14px; }

  /* 좁은 화면: 헤더는 위에 붙지 않고, 표는 작아지되 항목 이름은
     계속 왼쪽에 붙어 있다. 밀어서 보는 표라는 것을 알리려고
     감싼 상자에 안쪽 여백을 준다. */
  .bf-table { font-size: 14.5px; min-width: 700px; }
  .bf-table th, .bf-table td { padding: 11px 8px; }
  .bf-table thead th { position: static; }
  .bf-table th[scope="row"] { padding-right: 18px; }
    /* 상자를 화면 가장자리까지 넓히되 안쪽 여백은 두지 않는다. 여백이
     있으면 붙어 있는 항목 열이 left:0에서 그 여백만큼 안쪽에 서고,
     그 틈으로 스크롤된 값들이 비쳐 보인다. 대신 묶음 열이 자기
     왼쪽 여백을 가진다. */
  .bf-table__wrap { margin-left: -20px; margin-right: -20px; padding: 0; }
  .bf-table th.bf-table__grp { padding-left: 20px; }
  .bf-tier__head { gap: 8px; }
  .bf-who__cell { width: 100%; display: flex; align-items: baseline; gap: 12px; padding-right: 0; }
  .bf-form__grid { grid-template-columns: 1fr; }
  /* 헤더 — 390px에 브랜드·언어·등록이 다 들어가야 한다. 32px 좌우
     여백과 28px 간격만으로 457px가 되어 등록 버튼이 잘려 있었다. */
  .bf-header__nav { display: none; }   /* 자리는 섹션 띠가 이어받는다 */
  .bf-subnav {
    display: flex; gap: 18px; overflow-x: auto; overscroll-behavior-x: contain;
    padding: 0 16px 4px; scrollbar-width: none; -ms-overflow-style: none;
    /* 항목이 화면보다 좁으면 가운데, 넘치면 왼쪽부터 — safe가 없으면
       넘칠 때 첫 항목이 왼쪽 밖으로 밀려 손이 닿지 않는다. */
    justify-content: center;
    justify-content: safe center;
  }
  .bf-subnav::-webkit-scrollbar { display: none; }
  /* 접히는 것은 윗줄뿐이다. 헤더째 올려 버리면 섹션 띠도 함께 사라져
     현재 위치를 알 수 없게 된다 — 브랜드·언어·등록만 화면 위로
     밀려 나가고, 섹션 띠가 그 자리에 올라와 top:0에 선다. */
  .bf-header.is-hidden { transform: translateY(calc(var(--bf-headrow) * -1)); }
  /* 두 줄이 되었으므로 앵커가 그만큼 더 내려와야 한다:
     섹션 띄는 링크 8+6 여백과 2px 밑줄, 14.5px × 1.5 글줄, 그리고
     띄 자신의 아래 4px — 모두 42px 이다. 112 는 여기서도 6px 많았다
     (2026-09-07, 사용자). */
  :root { --bf-subnav-h: 42px; }
  /* 윗줄은 내리면 접힌다(site.js). 아래로 가는 앵커는 도착할 때
     띄 한 줄만 남으므로 스크립트가 누르는 순간 --bf-anchor-top 을
     띄 높이로 두고, 위로 가면 지운다 — 그러면 여기 두 줄 값이
     돌아온다(2026-09-07, 사용자). */
  [id] { scroll-margin-top: var(--bf-anchor-top, calc(var(--bf-headrow) + var(--bf-subnav-h))); }
  .bf-header__in { padding: 0 16px; gap: 12px; }
  .bf-header__year { display: none; }
  .bf-header__word { font-size: 15px; }
  .bf-lang { margin-left: auto; }      /* 내비가 없으니 여기서 민다 */
  :root { --bf-ctl-h: 38px; }   /* 손가락으로 누르므로 더 높다 */
  .bf-lang a { padding: 0 10px; }
  .bf-btn--sm { padding: 0 13px; }
  /* 손가락으로 누르는 것들 — 24px는 작다 */
  /* 좁은 화면에서는 네모와 글이 세로로 가운데에서 만난다. 넓은
     화면의 기준선 맞춤은 15px 네모에 맞춰 2px 내려 둔 것이라,
     19px 로 커지면 어긋나 보인다. */
  .bf-consent { align-items: center; }
  .bf-consent input[type="checkbox"] { width: 19px; height: 19px; transform: none; }
  .bf-consent button { padding: 6px 0; }
  .bf-venue__map { padding: 6px 0; }
  /* 좁은 화면에서는 그림이 높이를 정하지 못한다 — 폭에 맞추면
     200px짜리 띠가 되어 제목도 버튼도 들어가지 않는다. 내용이
     높이를 정하고, 그림은 제 비율대로 서서 좌우가 잘린다
     (히어로와 같은 방식). */
  .bf-closing { height: auto; padding: 96px 20px 104px; }
  /* 흐름으로 돌아와 섹션의 높이를 만든다. static이 아니라 relative다
     — 그림이 절대 배치라, 자리를 잡지 않은 내용은 그 아래로 깔린다. */
  .bf-closing__in { position: relative; inset: auto; padding: 0; }
  /* 좁은 화면에서는 폭이 아니라 높이가 기준이다 — 띠의 높이를 꽉
     채우고 좌우가 잘린다. 본문 폭 상한은 여기서 볼 일이 없다. */
  .bf-closing__svg { height: 100%; width: auto; min-width: 100%; }
  /* 히어로 아래 소산 구간 — 넓은 화면의 200px은 레일이 사라질 거리지만,
     좁은 화면에서는 개최 정보 다음에 오는 빈 화면 반쪽이 된다. 레일은
     그만큼 짧은 거리에서도 사라진다. 페이드도 함께 줄인다 — 구간보다
     긴 페이드는 히어로 글자 위로 올라온다. */
  .bf-scene-host__stage { --bf-stage-fade: linear-gradient(to bottom,
    #000 calc(var(--bf-hero-h) - 150px),
    rgb(0 0 0 / .3) calc(var(--bf-hero-h) - 81px),
    transparent calc(var(--bf-hero-h) - 21px)); }
  /* 좁은 화면에서는 svh다 — vh는 주소창이 접힐 때마다 튄다.
     여백도 88px로 줄인다: 넓은 화면의 104px은 개최 정보 다음에
     오는 빈 화면 반쪽이 된다. 그림판과 페이드가 이 값을 따르므로
     여백 높이는 여기 한 곳에서만 정한다. */
  .bf-scene-host {
    --bf-hero-h: max(600px, calc(100svh - var(--bf-headrow)));
    --bf-scene-foot: 88px;
  }
  /* 좁은 화면: 그림은 제 높이를 다 쓴다 — 히어로 높이만큼 서고
     잘리는 것은 좌우뿐이다(2026-08-13). 가로 위치는 마스트 타워
     (작품 왼쪽에서 947/1440 지점)가 화면 가운데 오도록 잡는다.
     아래로는 흘리지 않는다: 바닥이 히어로의 바닥이다. */
  .bf-scene-host__svg, .bf-scene-host__plane {
    right: auto; left: calc(50% - var(--bf-hero-h) * 947 / 780);
    width: calc(var(--bf-hero-h) * 1440 / 780);
  }
  /* 3C 스크림: 위 ~55%만 어두워지고 아래는 건드리지 않는다 —
     타워가 헤드라인을 뚫고 버튼 뒤까지 그대로 읽힌다. */
  .bf-scene-host__stage { --bf-stage-scrim: linear-gradient(to bottom,
    rgb(0 0 0 / .18) 0%, rgb(0 0 0 / .48) 34%, rgb(0 0 0 / .78) 54%, #000 70%); }
  /* 900~480px 에서는 넓은 화면처럼 왼쪽 정렬이다(2026-09-06, 사용자):
     단추와 개최 정보가 왼쪽에 서고, 표제 그림도 같은 왼쪽에 선다 —
     그림의 선이 단추와 같은 세로선에서 시작해야 하기 때문이다(같은 날의
     앞선 지시). 480px 아래에서만 가운데다(아래 블록). 예전(3C)에는
     900 아래가 모두 가운데였다: 왼쪽 열은 도시를 오른쪽에 비워 두려는
     것인데 여기서는 비울 오른쪽이 없다는 까닭에서였다. */
  .bf-hero__in { align-items: flex-start; text-align: left; padding: 24px 20px 48px; }
  .bf-hero__h1--en { max-width: none; }
  .bf-hero__cta { justify-content: flex-start; }
}
@media (max-width: 520px) {
  /* 손안에서는 사진칸을 한 점 줄이고 여백을 좁힌다 — 글자는
     칸 질의가 이미 줄이고 있다. */
  .bf-lineup__item { grid-template-columns: minmax(0, 1fr) 44%; }
  .bf-lineup__item { --bf-lineup-x: 20px; --bf-lineup-gap: 18px; }
  /* 연사 카드는 좁은 화면에서도 2열을 유지한다 — 1열로 두면
     역대 연사 20명이 화면 스무 개 길이의 벽이 된다. */
  /* 등급 카드는 한 줄에 둘씩 — 한 장이 화면 폭을 다 쓰면 값 하나에
     띠 하나가 되어 다섯 장이 화면 다섯 개 길이가 된다. 좁아진 카드
     안에서는 내용을 가운데로 모은다. */
  .bf-prices__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .bf-price { padding: 16px 12px 18px; text-align: center; }
  .bf-price__name { justify-content: center; gap: 6px; }
  .bf-price__row { justify-content: center; }
  /* 숫자 카드는 좁은 화면에서도 두 칸이다(2026-09-04, 사용자): 400px
     남짓한 화면에서 한 칸이면 카드가 화면만큼 넓어지고 네 장이 세로로
     길게 늘어선다. 파트너 로고 타일이 쓰던 것과 같은 자동 채움이다 —
     같은 화면에 있는 두 격자가 서로 다른 자리에서 접히면 안 된다.
     칸이 150px 아래로 내려가면 스스로 한 칸이 된다(≈350px 화면).
     min-width: 0(위 기본 규칙)이 있어야 카드 안의 긴 낱말이 칸을
     벌리지 못한다 — 그것이 예전에 여기서 1열을 고른 까닭이다.
     문단이 든 카드(--2, --3)는 그대로 1열이다: 좁은 칸에서 글이
     읽히지 않는다. 아래에 와야 이긴다 — 둘 다 홑클래스라 무게가 같고
     순서가 정한다. */
  .bf-cards { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .bf-cards--2, .bf-cards--3 { grid-template-columns: 1fr; }
  /* 1열이 되면 지표 카드는 화면만큼 넓어지고, 왼쪽에 붙은 두 줄이
     빈 오른쪽을 끌고 다닌다. 수치 카드만 가운데로 — 문단이 있는
     카드는 그대로 왼쪽이다. 가운데 정렬한 문단은 읽기 어렵다. */
  /* 카드가 둘씩 서면 안쪽이 118px(375px 화면)뿐이다 — 'Assembly'가
     30px에서 138px이라 넘친다. 한 단 더 줄인다(2026-09-06). */
  .bf-card__value--word, .bf-cards--lg .bf-card__value--word { font-size: 24px; }
  .bf-card:has(> .bf-card__value) { text-align: center; }
  .bf-card:has(> .bf-card__value) .bf-card__ico { margin-left: auto; margin-right: auto; }
  .bf-closing .bf-h2 { font-size: 34px; }
}

/* 히어로와 마지막 화면의 두 동작은 480px 아래에서만 폭을 다 쓴다
   (2026-08-13). 그보다 넓으면 나란히 서도 손가락에 넉넉하고, 화면
   폭을 가로지르는 버튼 두 장은 그 자리를 양식처럼 보이게 한다.
   두 곳이 같은 규칙을 쓴다: 같은 두 버튼이다. */
@media (max-width: 479.98px) {
  /* 연사 카드는 여기서야 한 칸이 된다(2026-09-06, 사용자 지시).
     그 위로는 카드가 220px 남짓이어도 두 칸을 지킨다 — 글자는 칸
     질의가 함께 줄여 준다. 한 칸이 되면 비율을 놀아 준다:
     가로가 넓어지면 2.18:1 은 눈에 띄게 낮아진다. */
  .bf-lineup { grid-template-columns: 1fr; }
  .bf-lineup__item { aspect-ratio: auto; min-height: 208px; }
  /* 휴대폰(480 아래)에서는 히어로가 가운데다(2026-09-06, 사용자: 그대로).
     900~480 은 왼쪽 정렬이므로 여기서 되돌린다 — 순서가 중요하다: 이
     블록은 900 블록보다 아래에 있어야 이긴다. 단추는 어차피 세로로
     쌓여 열을 다 쓰므로 정렬은 개최 정보와 표제 그림에만 보인다. */
  .bf-hero__in { align-items: center; text-align: center; }
  /* 화살표 줄은 flex 행이라 text-align 이 닿지 않는다 — 제 힘으로 가운데
     (2026-09-06, 사용자: 영문판 휴대폰에서 이 줄만 왼쪽에 붙어 있었다). */
  .bf-hero__track { justify-content: center; }
  /* 표제 그림은 열을 다 쓴다(2026-09-06, 사용자). 바닥 330px 은 여기서
     열보다 좁거나(479 에서 109px 남는다) 아슬아슬해(375 에서 5px) 의미가
     없다 — 휴대폰에서는 폭이 곧 열이다. */
  .bf-title--art .bf-title__art { width: 100%; }
  .bf-hero__cta, .bf-closing__cta { flex-direction: column; align-items: stretch; width: 100%; gap: 12px; }
  /* 화살표 줄은 320px에서 넘친다 — 대문자 열두 자에 넓은 자간이 붙고
     그 사이에 80px짜리 화살표가 있기 때문이다. 글자와 화살표를 함께
     줄인다: 화살표만 줄이면 두 낱말이 붙어 한 낱말로 읽힌다. */
  /* 표제가 바닥(56px)에 닿으므로 아랫글까지 비례대로 줄이면
     6px 가 된다 — 그래서 크기만 바닥값을 갖고, 간격은 기본
     규칙(2·5)을 그대로 따른다(2026-09-06, 사용자: 휴대폰에서도
     두·세 무리 사이가 원본보다 벌어져 있다). */
  .bf-hero__track { font-size: 11px; gap: 6px; }
  .bf-hero__arrow { width: 40px; margin-right: 9px; }
  .bf-hero__cta .bf-btn, .bf-closing__cta .bf-btn { width: 100%; }
  /* 로고 판은 두 칸으로 선다. 176px 고정 폭이면 한 줄에 하나가
     서고 오른쪽에 손가락만 한 자리가 버려진다. 폭은 여백과 간격을
     뺀 절반이다 — 판이 남는 자리 없이 화면을 채운다. */
  .bf-marks { gap: 12px; }
  .bf-mark--logo { width: calc((100% - 12px) / 2); }
}

/* 320px 아래 — 두 칸이면 판이 130px까지 줄어 로고를 알아볼 수 없다.
   한 칸으로 서고 여백을 뺀 폭을 다 쓴다. */
@media (max-width: 319.98px) {
  .bf-mark--logo { width: 100%; }
}

/* 320px — 헤더에 브랜드 글자까지 넣을 자리는 없다. 마크만 남긴다. */
@media (max-width: 380px) {
  .bf-header__in { padding: 0 12px; gap: 10px; }
  .bf-header__word { display: none; }
  .bf-lang a { padding: 8px 8px; }
  .bf-btn--sm { padding: 0 11px; font-size: 13px; }
}

/* 등급 설명이 산문일 때(영문 덱) */
.bf-tier__summary {
  font-size: 15px; line-height: 1.6; color: var(--bf-fg-muted);
  margin: 16px 0 0; max-width: 760px; text-wrap: pretty;
}

/* --- 왜 지금: 포지셔닝 축 ------------------------------------
   축 그래픽은 오른쪽 열 전체 폭을 쓴다. 근거 카드와 나란히 두면
   축의 글자가 읽히지 않는 크기까지 줄어든다. */
.bf-axis { background: var(--bf-surface); border: var(--bf-border); border-radius: var(--bf-radius-2); padding: 24px 26px; }
/* 좁은 화면용 축 — 기본은 숨어 있고 900px 아래에서 SVG와 자리를
   바꾼다. 1000단위 viewBox를 330px로 줄이면 글자가 7px가 된다. */
.bf-axis__compact { display: none; }
.bf-axis__compact li { display: flex; align-items: baseline; gap: 10px; font-size: 15px; color: var(--bf-fg-muted); word-break: keep-all; }
.bf-axis__compact b { font-weight: 700; color: var(--bf-fg-muted); }
.bf-axis__compact .is-self b, .bf-axis__compact li.is-self { color: var(--bf-100); }
.bf-axis__dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--bf-fg-faint); transform: translateY(-1px); }
.bf-axis__compact .is-self .bf-axis__dot { background: var(--bf-100); }
/* 이 미디어 쿼리는 바로 위 기본 규칙 뒤에 있어야 한다. 위쪽 900px
   블록에 넣었더니 여기의 display:none이 나중에 나와 그것을 덮어
   목록이 끝내 나타나지 않았다. */
@media (max-width: 900px) {
  .bf-pos__axis { display: none; }
  .bf-axis__compact { display: flex; flex-direction: column; gap: 12px; list-style: none; margin: 6px 0 20px; padding: 0; }
  /* 두 점을 잇는 선 — 넓은 화면의 가로축이 여기서는 세로로 선다.
     점을 기준선이 아니라 고정 위치에 세우는 이유는 선이 점에서
     정확히 시작하고 끝나야 하기 때문이다: 기준선 정렬은 글자 크기와
     행간에 따라 점의 높이가 흔들린다. 마지막 항목 아래로는 선이
     이어지지 않는다 — 축은 두 점 사이에만 있다.
     점은 옆 줄의 한가운데에 선다: (줄 높이 - 지름) / 2. 상수로 박으면
     언어마다 다른 행간에서 어긋난다. */
  .bf-axis__compact li { position: relative; padding-left: 19px; }
  .bf-axis__dot {
    position: absolute; left: 0; transform: none;
    top: 6px;                           /* lh 단위가 없는 브라우저용 */
    top: calc((1lh - 9px) / 2);
  }
  .bf-axis__compact li:not(:last-child)::before {
    content: ""; position: absolute; left: 4px; width: 1px;
    top: calc((1lh - 9px) / 2 + 9px);   /* 첫 점의 아래 끝 */
    bottom: calc(-12px - (1lh - 9px) / 2);   /* 12px 간격을 건너 다음 점의 위 끝 */
    background: var(--bf-600);
  }
}

/* 겹화살표의 손짓 — 그쪽으로 조금 밀렸다 돌아온다. 대부분의 시간은
   가만히 있고 한 번씩만 움직인다. */
@keyframes bfNudge {
  0%, 62%, 100% { transform: translateX(0); }
  74%           { transform: translateX(4px); }
  86%           { transform: translateX(0); }
}

/* 블록페스타 노드의 맥동 — 한 번에 하나, 아주 느리게. 모션 감소
   설정에서는 전역 규칙이 이 애니메이션을 끈다. */
.bf-axis__pulse {
  transform-box: fill-box; transform-origin: center;
  stroke-width: 2.5;
  animation: bfNodePulse 2s cubic-bezier(.25,.6,.25,1) infinite;
}
@keyframes bfNodePulse {
  0%   { transform: scale(.55); opacity: .95; }
  75%  { transform: scale(1.9); opacity: 0; }
  100% { transform: scale(1.9); opacity: 0; }
}

/* 덱에서 온 본문 산문 */
.bf-lead {
  font-size: 18px; line-height: 1.6; color: var(--bf-fg-muted);
  margin: 0; max-width: 660px; text-wrap: pretty; word-break: keep-all;
}
:lang(ko) .bf-lead { line-height: 1.7; }
/* 이어지는 문단 */
.bf-lead + .bf-lead { margin-top: 8px; }
/* 강조는 색으로만 한다 — 크기도 굵기도 본문 그대로다 */
.bf-lead.bf-lead--accent { color: var(--bf-200); }

/* 오른쪽 열 안의 소제목 */
.bf-subhead { font-size: 24px; font-weight: 600; margin: 0 0 10px; word-break: keep-all; }
.bf-subhead__cap { font-size: 14px; font-weight: 500; color: var(--bf-fg-muted); margin: -4px 0 16px; word-break: keep-all; }

/* 소제목의 표식 — 내비게이션 밑줄과 같은 옷이다: 높이 2px, 색은
   --bf-300, 모서리 1px. 같은 획이 이미 "여기가 어디인지"를 말하고
   있으므로 페이지에 새 말투를 들이지 않는다.
   길이는 32px 고정이다. 이름이 '스폰서' 셋에서 '미디어 및 리서치
   파트너' 열둘까지 벌어지므로 글자 폭을 따라가면 표식이 제목마다
   다른 무게로 읽힌다 — 다섯이 한 무리로 보이려면 같은 길이여야 한다. */
.bf-subhead::after {
  content: ''; display: block;
  width: 32px; height: 2px; margin-top: 8px;
  background: var(--bf-300); border-radius: 1px;
}

/* --- 상세비교 표: 넓은 화면이 아닐 때 -----------------------
   표가 자리에 들어가지 않는 폭에서만 가로 스크롤을 켠다. 그 순간
   감싼 상자가 스크롤 컨테이너가 되어 머리글이 붙지 못하므로 붙이기도
   함께 끈다 — 둘은 같이 켜지고 같이 꺼진다. */
@media (max-width: 1000px) {
  .bf-table__wrap { overflow-x: auto; }
  .bf-table thead th { position: static; }
  /* 왼쪽 두 열이 다 붙어 있으면 390px 화면을 라벨이 통째로 먹어
     값이 한 칸도 보이지 않는다. 묶음 열은 놓아 주고 항목 열만
     붙인다 — 밀면 항목이 묶음 위를 덮으며 따라온다. */
  .bf-table { --bf-grp-w: 104px; }
  .bf-table th.bf-table__grp { position: static; font-size: 15px; }
  /* 항목 이름만 줄바꿈을 허용한다 — 값은 그대로 한 줄이다. 긴
     항목 하나가 라벨 열을 200px까지 늘려 값이 밀려나 있었다. */
  /* 항목 열은 줄바꿈을 허용하되 너무 좁으면 세 줄로 쪼개진다 —
     바닥을 두고 천장을 둔다. */
  .bf-table th[scope="row"] {
    left: 0; z-index: 2; border-right: 1px solid var(--bf-hairline);
    white-space: normal; word-break: keep-all;
    min-width: 142px; max-width: 190px; padding-left: 14px;
  }
  .bf-table th.bf-table__grp { white-space: normal; word-break: keep-all; }
}

/* --- 오른쪽 열의 리듬 ---------------------------------------
   블록 간격은 패턴이 정한다. 각 컴포넌트가 스스로 위 여백을
   들고 오면 간격이 제각각이 되므로, 직계 자식의 위 여백은
   여기서 한 번에 덮어쓴다. 이 규칙은 파일 맨 끝에 있어야 한다 —
   같은 특정도의 컴포넌트 규칙을 뒤에서 덮어써야 하기 때문이다. */
.bf-body > * { margin-top: 0; }
.bf-body > * + * { margin-top: 56px; }

/* --- 스크롤에 따라 나타나기 ---------------------------------
   블록이 처음 화면에 들어올 때 한 번만 떠오른다(zoom-in-up).
   되돌아와도 다시 재생하지 않는다 — 페이지가 계속 들썩이지 않게.

   감추는 일은 html.bf-anim 아래에서만 한다. 스크립트가 없으면 그
   클래스가 없고, 따라서 아무것도 감춰지지 않는다.

   대상 목록은 site.js의 REVEAL_SEL과 한 쌍이다 — 한쪽만 고치면
   블록이 숨은 채로 남는다. 히어로, 연사·파트너 레일, 등록 폼은
   일부러 뺐다: 첫 화면은 기다림 없이 서야 하고, 레일은 이미
   움직이며, 폼 칸은 자동완성이 먼저 채우기 때문이다.

   옮기는 것은 opacity와 transform뿐이므로 레이아웃은 다시 계산되지
   않는다. 지연은 함께 들어온 블록끼리만 계단이 되며(site.js),
   여섯 칸에서 멈춘다. 속도는 2026-08-18에 한 번 늦췄다(500→720ms). */
:root { --bf-reveal-dur: 720ms; --bf-reveal-ease: cubic-bezier(.22, .61, .36, 1); }

/* ⚠ 이 목록에 :not()이나 다른 클래스를 겹쳐 쓰지 말 것. :is()의
   특정성은 인자 중 가장 무거운 것을 따르므로, 그 순간 감추는 쪽이
   보여 주는 쪽(.is-revealed)을 이겨 블록이 영영 투명해진다. */
.bf-anim [data-reveal] :is(
  .bf-head, .bf-lead, .bf-subhead,
  .bf-card, .bf-mark--card, .bf-lineup__item, .bf-plate__label, .bf-plate__cell, .bf-who,
  .bf-venue__photo, .bf-venue, .bf-venue__intro,
  .bf-h2, .bf-closing__meta, .bf-closing__cta
) {
  opacity: 0;
  transform: translateY(20px) scale(.96);
  transition: opacity var(--bf-reveal-dur) var(--bf-reveal-ease),
              transform var(--bf-reveal-dur) var(--bf-reveal-ease);
  transition-delay: calc(var(--bf-reveal-i, 0) * 90ms);
}
.bf-anim [data-reveal] .is-revealed { opacity: 1; transform: none; }

/* 이미 함께 떠오르는 블록 안의 대상은 두 번 감추지 않는다 — 부모가
   나타나도 자식이 제 차례를 기다리면 빈 자리가 보인다. site.js도
   같은 이유로 대상에서 뺀다. */
.bf-anim [data-reveal] :is(.bf-venue, .bf-venue__intro) :is(.bf-lead, .bf-subhead, .bf-mark--card, .bf-card) {
  opacity: 1; transform: none; transition: none;
}
