/*
 * K110 shell layout authority.
 *
 * The legacy facade owns visual styling. This file owns only page-shell
 * geometry so the brand header can evolve without editing generated CSS.
 * Adjust the semantic tokens below when the final header design is decided.
 */
:root {
  /*
   * 두 브랜드 마크의 **잉크**(실제 그려진 영역) 높이. 브랜드 헤더 크기의 단일 기준이다.
   *
   * 이 토큰이 필요한 이유: 슬롯 높이만으로는 마크가 얼마나 커 보이는지 정할 수 없었다.
   * 산돌구름 에셋은 잉크 66x45 를 120x64 캔버스에 담고 있었고 K110 SVG 는 여백이 사실상
   * 0 이어서, 슬롯을 맞추면 잉크 높이비가 1.41 로 벌어졌다.
   *
   * 45px 인 이유: 산돌구름 에셋 잉크의 원본 높이다. 이 값에서 확대하면 래스터가 뭉갠다
   * (에셋 내부가 120x64 PNG). 여백 0 벡터로 교체하면 자유롭게 올릴 수 있다.
   *
   * 기준을 잉크 바운딩 높이로 잡은 이유: 두 마크의 구조가 달라 다른 기준은 성립하지
   * 않는다. 산돌구름의 `산돌구름` 워드마크는 심볼에 종속된 부속(잉크의 41%)이고 K110 의
   * `K110` 글자는 마크 자체(99%)라 워드마크끼리 맞추면 산돌구름 잉크가 154px 이 된다.
   * 잉크 면적을 맞추는 안도 렌더해 보고 기각했다 — 면적비 3.71 은 크기 차이가 아니라
   * 굵기 차이라 크기로 갚으면 과보정되어 K110 이 종속 요소로 읽힌다.
   *
   * 마크별 파생값은 facade CSS 가 이 토큰에서 계산한다. 두 마크의 보정 계수가 다른 이유는
   * 그쪽 주석에 있다.
   */
  --k110-brand-ink-h: 45px;
  /*
   * 브랜드 락업 슬롯 높이. **잉크 높이와 같다.**
   *
   * 64px 상수였다. 그때는 산돌구름 에셋에 구운 여백이 있어 슬롯이 곧 마크 크기였지만,
   * 에셋을 잘라 잉크 기준으로 정렬한 뒤로는 슬롯 64 안에 잉크 45 가 들어가 위아래로 각
   * 9.5px 를 비웠다. 그 죽은 공간이 `--k110-brand-header-top-space` 위에 얹혀서, 선언된
   * 상단 여백(21.6px)과 실제로 보이는 여백(31.1px)이 갈렸다. 토큰이 제 값을 뜻하지 않는
   * 상태였다.
   *
   * 상수 대신 잉크 토큰을 참조하는 이유: 두 마크의 크기가 이미 그 토큰에서 파생되므로
   * 슬롯까지 같은 출처를 쓰면 값이 갈릴 자리가 없어진다. 잉크를 키우면 슬롯이 따라온다.
   *
   * 여유 공간을 두지 않아도 되는 이유: 락업은 `align-items: center` 이고 두 마크 모두
   * `overflow: visible` 이라, 잉크가 슬롯보다 커져도 잘리지 않고 넘쳐 그려진다.
   *
   * 아래 `--k110-brand-header-h` 가 이 값을 `max(--k110-header-h, ...)` 로 받는다. 그래서
   * 헤더가 실제로 줄어드는 폭은 뷰포트마다 다르다 — `--k110-header-h` 가 더 큰 화면
   * (1600x1100 에서 66px)에서는 그쪽이 바닥값이라 헤더 높이가 그대로다. 그 바닥값을 걷는
   * 것은 패널 top 오프셋·스크롤 마진 등 12곳이 같은 토큰을 직접 읽고 있어 별도 결정이다.
   */
  --k110-brand-lockup-h: var(--k110-brand-ink-h);
  --k110-brand-header-top-space: var(--k110-edge-y);
  --k110-brand-header-bottom-space: clamp(18px, 2.8svh, 32px);
  --k110-brand-header-h: calc(
    var(--k110-brand-header-top-space) +
    max(var(--k110-header-h), var(--k110-brand-lockup-h)) +
    var(--k110-brand-header-bottom-space)
  );
  --k110-hero-flow-gap: clamp(10px, 1.8svh, 20px);
  /* Some fallback glyphs paint above their line box; reserve visual ink space. */
  --k110-hero-glyph-top-guard: clamp(72px, 10svh, 96px);
  --k110-hero-mobile-lead-space: max(
    0px,
    calc(
      clamp(210px, 32svh, 305px) -
      var(--k110-brand-header-h)
    )
  );
  --k110-layout-header-bottom: var(--k110-brand-header-h);
}

/*
 * 발견하기 "다른 외계어 보기"·"등록" 버튼의 눌림 표현: 누르는 동안만 노란 채움, 떼면 기본 모양.
 *
 * 파사드는 노란 채움을 :hover 에 걸어 두었다(6898행, 그리고 id 선택자 + !important 인 14692행).
 * 그러면 (1) 터치 기기는 탭 뒤 :hover 를 다른 곳을 건드리기 전까지 유지하므로 손을 떼도 채움이 남아
 * "선택된 것처럼" 보이고, (2) 데스크톱은 마우스가 올라가 있기만 해도 눌린 모양이 된다. 의도는 두 환경
 * 모두 "누르면 채움, 떼면 복귀" 이므로 채움을 :active 로 옮긴다. hover 에는 채움 대신 은은한 글로우만
 * 남겨 마우스 사용자에게 올라갔다는 신호는 준다. 파사드가 !important 를 쓰므로 같은 세기로 덮는다.
 * 기본 모양 값은 파사드 14638행 블록의 --btn-* 토큰과 6862행 ::after 배경을 그대로 쓴다.
 * 탭 순간의 번쩍임 연출(.is-command-burst)은 별도 애니메이션이라 그대로다.
 */
#discoverPanel .k110-discover-next:hover,
#discoverPanel .k110-discover-bottom.has-register .k110-discover-register:hover {
  background: var(--btn-bg) !important;
  border-color: var(--btn-border) !important;
  color: var(--btn-fg) !important;
  text-shadow: 0 0 8px color-mix(in srgb, #FFEE00 26%, transparent) !important;
  box-shadow: none !important;
  filter: drop-shadow(0 0 12px color-mix(in srgb, #FFEE00 36%, transparent)) !important;
}
#discoverPanel .k110-discover-next:hover::after,
#discoverPanel .k110-discover-bottom.has-register .k110-discover-register:hover::after {
  background:
    linear-gradient(0deg, var(--k110-command-glow-soft) 0%, rgba(0, 0, 0, 0) 64%),
    rgba(0, 0, 0, 0.86) !important;
  box-shadow: none !important;
}
#discoverPanel .k110-discover-next:active,
#discoverPanel .k110-discover-bottom.has-register .k110-discover-register:active {
  background: #FFEE00 !important;
  border-color: #FFEE00 !important;
  color: #000 !important;
  text-shadow: none !important;
  box-shadow: 0 0 18px color-mix(in srgb, #FFEE00 42%, transparent) !important;
  filter: none !important;
}
#discoverPanel .k110-discover-next:active::after,
#discoverPanel .k110-discover-bottom.has-register .k110-discover-register:active::after {
  background: #FFEE00 !important;
  box-shadow: inset 0 0 18px rgba(255, 255, 255, 0.16) !important;
}
/* 터치 기기: 탭 뒤 남는 :hover 흉내에는 글로우조차 남기지 않는다. */
@media (hover: none) {
  #discoverPanel .k110-discover-next:hover,
  #discoverPanel .k110-discover-bottom.has-register .k110-discover-register:hover {
    filter: none !important;
  }
}

/* Borderless, non-sticky brand header in normal document flow. */
.k110-root > .k110-header {
  position: relative !important;
  inset: auto !important;
  width: calc(
    100% -
    (var(--k110-layout-gutter, var(--k110-edge-x)) * 2)
  ) !important;
  height: var(--k110-brand-header-h) !important;
  margin: 0 auto !important;
  padding: var(--k110-brand-header-top-space) 0 0 !important;
  border: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  box-sizing: border-box !important;
  align-items: flex-start !important;
}

.k110-root > .k110-header .k110-brand-lockup,
.k110-root > .k110-header .k110-brand-item {
  height: var(--k110-brand-lockup-h) !important;
}

/* Header and hero are direct siblings; keep both in the same flow. */
.k110-root > .k110-hero {
  position: relative !important;
  inset: auto !important;
  transform: none !important;
  box-sizing: border-box !important;
}

body.k110-layout-landscape .k110-root > .k110-hero {
  width: var(--k110-hero-w) !important;
  max-width: var(--k110-hero-w) !important;
  min-height: max(
    0px,
    calc(var(--k110-screen-h) - var(--k110-brand-header-h))
  ) !important;
  margin: 0 auto 0 var(--k110-layout-gutter) !important;
  padding:
    calc(var(--k110-hero-flow-gap) + var(--k110-hero-glyph-top-guard))
    0
    var(--k110-hero-flow-gap) !important;
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
}

body.k110-layout-portrait .k110-root > .k110-header {
  width: var(--k110-panel-w) !important;
}

body.k110-layout-portrait .k110-root > .k110-hero {
  min-height: max(
    0px,
    calc(var(--k110-screen-h) - var(--k110-brand-header-h))
  ) !important;
  margin-left: auto !important;
  margin-right: auto !important;
  padding-top: var(--k110-hero-flow-gap) !important;
  padding-bottom: var(--k110-hero-flow-gap) !important;
}

/*
 * 히어로 안내의 긴 팝업(PBGSPQA-1207): 타이틀·표본 카운터가 숨고 팝업이 헤더 바로 아래에서 시작한다.
 *
 * 위 규칙들은 가로 화면에서 히어로를 세로 가운데 정렬하고(타이틀 위 글리프 가드 여백 포함),
 * 좁은 세로 화면에서는 선두 여백(`--k110-hero-mobile-lead-space`)을 둔다. 긴 팝업은 화면에 남은
 * 높이만큼 본문을 늘리므로, 그 여백을 걷어야 `useK110HeroGuide` 가 잰 본문 위치와 최대 높이가
 * 실제 배치와 맞는다. 레퍼런스(studiok110.com)의 "헤더 아래 20px 에서 시작" 과 같은 뜻이다.
 * 특이도 (0,4,1) 이라 아래 좁은 세로 화면 규칙(0,3,1)보다도 이긴다.
 */
body.k110-layout-landscape .k110-root > .k110-hero.is-guide-long,
body.k110-layout-portrait .k110-root > .k110-hero.is-guide-long {
  justify-content: flex-start !important;
  padding-top: var(--k110-hero-flow-gap) !important;
}

@media (max-width: 767px) and (orientation: portrait) {
  :root {
    /*
     * `--k110-brand-lockup-h` 오버라이드를 걷었다. 루트가 잉크 토큰을 참조하므로 좁은
     * 화면에서도 슬롯이 잉크와 같다. 종전에는 여기 64px 상수가 남아 모바일만 슬롯 안에
     * 19px 죽은 공간이 생겼다(슬롯 64 - 잉크 45).
     */
    --k110-hero-flow-gap: clamp(8px, 1.6svh, 14px);
  }

  body.k110-layout-portrait .k110-root > .k110-hero {
    min-height: max(
      0px,
      calc(var(--k110-visible-h) - var(--k110-brand-header-h))
    ) !important;
    padding-top: var(--k110-hero-mobile-lead-space) !important;
    padding-bottom: 0 !important;
    justify-content: flex-start !important;
  }

  /*
   * 섹션 스냅을 브라우저에 맡긴다.
   *
   * 종전에는 useK110Mobile 이 touchmove 를 preventDefault 로 가로채 드래그 거리(화면의 28%/40%)로
   * hero↔ui 전환을 직접 판정하고, 벗어난 스크롤은 되당겼다. 그 장치가 관성 스크롤·주소창·
   * 소프트 키보드와 충돌해 화면 떨림, 짧은 플릭 무효, 바닥 도달 불가를 만들었다. CSS scroll-snap 은
   * 같은 "한 화면씩" 연출을 브라우저의 관성·속도 판정으로 제공한다.
   *
   * 스냅 지점은 둘 — 문서 최상단(헤더가 0 에서 시작)과 ui 상단. hero 는 헤더 아래(약 77px)라 지점으로
   * 두지 않는다. 종전 JS 도 hero 로 갈 때 scrollTo(0) 이었다.
   *
   * `mandatory` 인 이유: 지점이 둘뿐이고 ui 가 정확히 한 화면이라 "두 페이지" 라는 원본 의도 그대로다.
   * `proximity` 는 Chromium 에서 지점과 뷰포트 높이의 약 1/4 이내일 때만 붙어(400px 뷰포트에서
   * 120px 거리도 붙지 않았다) 대부분의 플릭이 어중간한 위치에 멈춘다. ui 가 뷰포트보다 커지는
   * 경우(소프트 키보드로 보이는 높이가 줄 때)는 스냅 영역이 스냅포트를 덮는 모든 위치가 유효하므로
   * mandatory 라도 바닥까지 자유롭게 스크롤된다. 키보드 락 중에는 스냅을 끈다 — 락이 스크롤을
   * 앵커에 고정하는 것과 서로 당긴다.
   */
  html {
    scroll-snap-type: y mandatory;
  }
  html.is-mobile-keyboard-lock {
    scroll-snap-type: none;
  }
  /*
   * 파사드가 세로 모드에서 `body { overflow-y: auto !important }` 를 걸어 두어 body 가 스크롤
   * 컨테이너가 된다(높이가 auto 라 실제로 스크롤되지는 않지만 컨테이너인 것은 같다). 그러면
   * 헤더·ui 의 scroll-snap-align 은 가장 가까운 스크롤 컨테이너인 body 에 붙고, 뷰포트(html)의
   * scroll-snap-type 은 붙일 영역이 없어 아무 일도 하지 않는다 — 에뮬레이터에서 스냅이 전혀
   * 걸리지 않던 원인이다. body 를 스크롤 컨테이너에서 빼려면 두 축 모두 visible 또는 clip 이어야
   * 한다(한 축만 hidden/auto 면 다른 축의 visible 이 auto 로 승격된다). `overflow-x: clip` 은
   * 가로 넘침을 종전 hidden 과 같게 잘라 주면서 스크롤 컨테이너를 만들지 않는다.
   */
  body.k110-layout-portrait {
    overflow-x: clip !important;
    overflow-y: visible !important;
  }
  body.k110-layout-portrait .k110-root > .k110-header,
  body.k110-layout-portrait .k110-root > .k110-ui {
    scroll-snap-align: start;
  }
  /*
   * hero 가 한 화면보다 길면 그 안에서도 멈출 수 있게 한다.
   *
   * 위 두 지점만 두면 hero 가 한 화면보다 길 때(좁은 폰에서 안내 카드가 길어질 때) 두 지점 사이의
   * hero 아래쪽은 손을 떼는 순간 어느 한쪽 지점으로 끌려가 멈춰서 볼 수 없다. 실측 `390x844`:
   * 스냅 지점 0 / 1253.5, 첫 화면 0~844 라 안내 설명서 아래쪽·폰트 섹션·버튼(985~1023)이 어느
   * 지점에서도 보이지 않았다. 종전 JS 스냅은 안내 카드(`.k110-hero-info`)에서 시작한 터치를
   * 스냅하지 않아 카드 위를 끌면 읽을 수 있었는데, 1439d21 이 CSS 스냅으로 바꾸면서 그 예외가
   * 사라졌다.
   *
   * hero 를 스냅 영역으로 두고 위 여백을 헤더 높이만큼 줘서 영역이 문서 맨 위(0)에서 시작하게 한다.
   * 스냅 영역이 스냅포트보다 크면 그 영역이 화면을 덮는 모든 위치가 유효한 스냅 위치다(CSS Scroll
   * Snap 1 의 "snap area larger than the snapport"). 그래서 0 ~ (hero 바닥 − 화면 높이) 사이에서는
   * 멈춘 자리에 머물고, 그보다 더 내리면 ui 지점으로 붙는다. hero 가 한 화면에 들어가는 화면에서는
   * 영역이 한 화면이라 지점이 0 하나뿐이고 헤더 지점과 겹쳐 동작이 바뀌지 않는다.
   */
  body.k110-layout-portrait .k110-root > .k110-hero {
    scroll-snap-align: start;
    scroll-margin-top: var(--k110-brand-header-h);
  }
}

/*
 * Contribution celebration: let the facade's shell hide actually win.
 *
 * The facade hides the shell during the celebration at the top level (all viewports):
 * `body.is-contribution-warping .k110-hero { display: none !important }`, specificity
 * (0,2,1). The landscape hero rule above is (0,3,1) and re-asserts
 * `display: flex !important` purely for layout geometry, so it also beat the hide and the
 * hero stayed on screen behind the flight stage. Both declarations are `!important`, so
 * specificity alone decided it. This only misfired on landscape layouts; the portrait rule
 * does not set `display`, so the hide worked there. The portrait selector is listed below
 * anyway so a later edit adding `display` to it cannot silently reopen the same hole.
 *
 * Only specificity is corrected here. The hide itself, the header exit animation, and the
 * `k110HeaderExitTop` keyframes all already exist at the top level of the generated
 * facade, so none of that is restated.
 */
body.is-contribution-warping.k110-layout-landscape .k110-root > .k110-hero,
body.is-contribution-warping.k110-layout-portrait .k110-root > .k110-hero {
  display: none !important;
}

/*
 * Contribution celebration: centre the single continue button.
 *
 * The facade lays this row out as `grid-template-columns: 1fr 1fr` because the legacy
 * screen had two buttons here (`계속 디자인하기` and `등록한 기록보기`). The history button
 * was removed for anonymous participation, so the one remaining button occupied only the
 * left column of a 720px container and read as left-aligned against the centred text
 * above it.
 *
 * Collapse the row to a single centred column and cap it near the old half-column width,
 * so the button keeps its legacy size and only its position changes. The facade's
 * per-breakpoint `width` and `gap` on this container still apply; only the column
 * definition is overridden here.
 *
 * This lives here rather than in the facade because the facade still describes the
 * legacy two-button row and this override belongs to the anonymous-participation
 * change layered on top of it. The facade has no counterpart rule for this selector,
 * so there is nothing there to edit.
 *
 * Correction: an earlier commit message for this rule claimed the facade is generated
 * from `public/k110/index.html` and would lose direct edits. That is not true in this
 * repository. Neither the source HTML nor `scripts/k110-extract-facade-css.js` was
 * ported (see `docs/k110_integration_plan.md`), so the facade is hand-maintained here
 * and is edited directly when a rule already lives in it.
 */
.k110-contribution-success-actions {
  grid-template-columns: min(100%, 348px);
  justify-content: center;
}
