/* ===========================================================================
   BeeTopia 공통 모바일 레이어
   ---------------------------------------------------------------------------
   설계 원칙 (2026-09-02)

   1. HTML 을 고치지 않아도 적용되는 것만 여기 넣는다.
      37페이지를 각각 손대지 않는 게 이 파일의 존재 이유다.
   2. 데스크톱 화면은 건드리지 않는다. 폭 제한이 필요한 규칙은 모두
      @media (max-width: 640px) 안에 둔다.
   3. 기존 Tailwind 클래스를 이기지 않는다.
      특히 차트 높이(h-[260px] 등)는 페이지가 실측으로 맞춰둔 값이라
      여기서 덮으면 조용히 레이아웃이 바뀐다. 그래서 .chart-box 에는
      height 를 넣지 않는다 — 새 페이지용 .chart-h 를 따로 둔다.
   4. 요소 크기를 키워 가로 스크롤을 만들지 않는다. 터치 영역을 넓히는
      것은 opt-in(.tap)으로 한다. 전역으로 버튼을 44px 로 키우면 좁은
      줄에 놓인 아이콘 버튼들이 화면을 넘긴다.

   문서: docs/MOBILE_COMPATIBILITY.md
   =========================================================================== */

/* --- 전 폭 공통 ---------------------------------------------------------- */

/* iOS 가 가로 모드에서 본문 글자를 임의로 키우는 것을 막는다. */
html {
    -webkit-text-size-adjust: 100%;
}

/* 스크롤이 끝에 닿았을 때 당기면 새로고침되거나 부모로 전파되는 것을 막는다.
   대시보드는 안쪽 컨테이너가 스크롤하는 구조라 이게 없으면 끝에서 당길 때
   페이지 전체가 튕긴다.
   브라우저 기본 「당겨서 새로고침」도 이것 때문에 안 된다 — 그 동작 자체는
   폰에서 당연한 것이라 `shared/pullRefresh.js` 로 우리가 통제해 다시 넣었다
   (발동 지점을 본문 맨 위로 한정하고, 리로드 대신 데이터만 다시 읽는다). */
html,
body {
    overscroll-behavior-y: contain;
}

/* --- 당겨서 갱신 표시기 (shared/pullRefresh.js) ---------------------------
   JS 가 top(본문 스크롤러의 화면상 위치)과 transform(당긴 거리)을 넣는다.
   음수 margin 으로 처음에는 본문 위쪽 바깥에 숨어 있다. */
.ptr-ind {
    position: fixed;
    left: 50%;
    top: 0;
    z-index: 60;
    width: 36px;
    height: 36px;
    margin-top: -46px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: #fff;
    color: #f59e0b;
    box-shadow: 0 4px 14px rgba(15, 23, 42, .18);
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 0);
}

.dark .ptr-ind {
    background: #1e293b;
    color: #fbbf24;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .5);
}

/* 손가락을 따라오는 동안에는 트랜지션이 없어야 한다(JS 가 클래스를 뺀다).
   놓은 뒤 되돌아갈 때만 붙인다. */
.ptr-ind.ptr-anim {
    transition: transform .25s ease, opacity .25s ease;
}

/* 발동 지점을 넘겼다 — 놓으면 갱신된다는 신호 */
.ptr-ind.ptr-ready {
    color: #16a34a;
}

.ptr-ind > i {
    font-size: 14px;
    transition: transform .12s linear;
}

.ptr-ind.ptr-spin > i {
    animation: ptr-rot .8s linear infinite;
}

@keyframes ptr-rot {
    to { transform: rotate(360deg); }
}

/* 탭할 때 파란 사각형이 번지는 것 완화. 눌린 느낌은 각 요소의 active: 로 준다. */
* {
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0.06);
}

/* 이미지·표가 부모를 넘겨 가로 스크롤을 만드는 가장 흔한 원인 차단. */
img,
video,
canvas {
    max-width: 100%;
}

/* --- 유틸리티 (페이지가 클래스를 붙여 쓰는 것) --------------------------- */

/* 표 가로 스크롤. 오른쪽 끝에 그라데이션을 깔아 "더 있다"는 걸 보이게 한다.
   스크롤을 끝까지 밀면 배경이 붙어 그라데이션이 사라진다(background-attachment). */
.tbl-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.tbl-scroll > table {
    min-width: 100%;
}

@media (max-width: 640px) {
    .tbl-scroll {
        background-image: linear-gradient(to left, rgba(15, 23, 42, 0.10), rgba(15, 23, 42, 0));
        background-repeat: no-repeat;
        background-position: right center;
        background-size: 24px 100%;
        background-attachment: local, scroll;
    }
}

/* 차트 컨테이너.
   touch-action: pan-y 가 핵심이다. 줌·팬 플러그인을 붙이면 차트가 세로
   스와이프까지 먹어서 페이지 스크롤이 죽는다. 세로는 페이지에 양보하고
   가로 제스처만 차트가 받는다. */
.chart-box {
    position: relative;
    touch-action: pan-y;
}

/* 새로 만드는 페이지에서 쓸 반응형 높이. 기존 페이지에는 붙이지 않는다. */
.chart-h {
    height: clamp(180px, 45vw, 320px);
}

/* --- 가로 모드 -----------------------------------------------------------
   폰을 옆으로 눕히면 세로가 390px 밖에 안 남는다. 헤더 64px 를 빼면 본문은
   326px 인데, 차트 컨테이너는 h-[200px]~h-[320px] 로 고정돼 있어서 차트 하나가
   본문의 61~98% 를 차지했다. 그래프를 크게 보려고 눕혔더니 그래프 하나만
   보이고 나머지는 스크롤해야 나오는 상태다.

   더 나쁜 건 Tailwind 의 sm: 이 **폭** 기준이라는 것이다. 가로 모드는 폭이
   844px 이므로 sm: 이 켜지고, 세로용보다 **더 큰** 높이가 걸린다.

   그래서 높이가 짧을 때만 dvh 로 다시 계산한다. 세로 모드는 이 블록에
   들어오지 않으므로 지금 값이 그대로 유지된다 — 페이지가 실측으로 맞춰둔
   높이를 건드리지 않는다는 이 파일의 원칙과 어긋나지 않는다.

   :has() 로 캔버스의 부모를 직접 잡아서 HTML 을 한 줄도 고치지 않는다.
   (Chrome 105+ / Safari 15.4+ / Firefox 121+)

   height 가 아니라 **max-height** 로 거는 것이 중요하다. height 로 덮으면
   temp_array 의 배터리 추이(h-[90px])처럼 원래 작은 차트가 오히려 커진다.
   상한만 씌우면 작은 것은 그대로 있고 큰 것만 접힌다.
   Tailwind CDN 이 이 파일보다 뒤에 스타일을 넣으므로 !important 가 필요하다. */
@media (orientation: landscape) and (max-height: 560px) {
    main div:has(> canvas),
    .chart-box,
    .chart-h {
        max-height: max(150px, 52dvh) !important;
    }

    /* 관리자 계정 선택기는 세로 모드에서 `hidden sm:flex` 로 숨는다. 그런데 가로
       모드는 **폭이 844px** 이라 sm: 이 켜져 다시 나타나고, 동시에 md: 로 사이드바가
       256px 을 차지해 본문은 588px 밖에 안 된다. 그래서 세로보다 오히려 여유가 적은데
       데스크톱용 헤더가 그려졌고, 왼쪽 그룹(제목 + 이 선택기)이 더 줄어들 수 없어
       오른쪽 도구를 밀어내 **로그아웃 버튼이 화면 밖으로 나갔다** (loadcell/dashboard
       +24px, analysis +14px, temp_array/analysis +5px).

       폭 기준 breakpoint 가 눕힌 폰을 데스크톱으로 오인하는 것이 근본 원인이고, R2
       (계정 선택기가 인라인 style 로 클래스를 무력화)와 같은 자리에서 같은 증상이 났다.
       폰에서는 세로든 가로든 계정 전환을 못 하는 것이 일관된 동작이라 숨긴다. */
    #adminAccountSelectContainer {
        display: none !important;
    }

    /* 같은 오인이 헤더 도구에서도 난다. 세로 390px 에서는 `hidden sm:inline` 이
       꺼져 아이콘만 나오는데, 가로에서는 sm: 이 켜져 「엑셀 저장」·「전역 기본값」
       같은 글자 라벨과 정렬 select 까지 펼쳐진다. feeder/dashboard 의 오른쪽 묶음은
       그렇게 596px 을 요구했고 본문은 588px 이라 로그아웃이 36px 밀려났다.

       그래서 **눕힌 폰의 헤더는 세운 폰의 헤더와 같게** 만든다. 세로 390px 이
       통과한다는 것이 이미 검증돼 있으므로, 더 넓은 가로에서 같은 구성이면
       반드시 들어간다. 범위를 header 안으로 묶어 본문 레이아웃은 건드리지 않는다. */
    main > header .hidden.sm\:inline,
    main > header .hidden.sm\:flex,
    main > header .hidden.sm\:block {
        display: none !important;
    }
}

/* 폰: 관리자 계정 선택은 shell.js 가 헤더 밑 줄(#mobileAcctBar)로 옮긴다.
   헤더가 아니라 로그아웃을 밀어내지 않으므로 세로·가로 모두 보인다.
   관리자가 아니면 페이지가 인라인 display:none 을 그대로 두므로 줄째 숨긴다. */
#mobileAcctBar > #adminAccountSelectContainer {
    display: flex !important;
    width: 100%;
}
#mobileAcctBar > #adminAccountSelectContainer select {
    flex: 1;
    width: auto;
    max-width: none;
    font-size: 15px;
}
#mobileAcctBar:has(> #adminAccountSelectContainer[style*="none"]) {
    display: none;
}

/* 터치 영역만 넓힌다. 보이는 크기는 그대로. opt-in. */
@media (hover: none) {
    .tap {
        position: relative;
    }

    .tap::after {
        content: '';
        position: absolute;
        inset: -10px;
    }
}

/* 넓은 위젯(온도 허니컴, bee_map 격자)을 담는 칸.
   축소 배율은 페이지가 JS 로 계산해 --pinch-scale 에 넣는다. */
.pinch-pad {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-x pan-y;
}

.pinch-pad > .pinch-inner {
    transform: scale(var(--pinch-scale, 1));
    transform-origin: left top;
    transition: transform 0.15s ease-out;
}

.safe-b {
    padding-bottom: env(safe-area-inset-bottom);
}

/* --- 모바일 전용 --------------------------------------------------------- */

@media (max-width: 640px) {
    /* iOS 는 글자가 16px 미만인 입력칸을 누르면 화면을 확대한다. 확대된 화면은
       사용자가 손으로 되돌려야 하고, 그동안 레이아웃이 넘쳐 보인다.
       Tailwind 의 text-xs / text-[12px] 를 이겨야 하므로 !important 가 필요하다.
       체크박스·라디오·슬라이더는 글자가 없으니 제외한다. */
    input:not([type='checkbox']):not([type='radio']):not([type='range']):not([type='color']),
    select,
    textarea {
        font-size: 16px !important;
    }

    /* 옵션 글자가 길어진 select 가 flex 부모를 밀어내지 않게 줄어들 수 있게 한다.
       입력칸 전체에 걸면 안 된다 — 아래 date 류는 반대로 줄어들면 값이 잘리고,
       :not() 이 4개 붙은 위 선택자가 특이도로 date 규칙을 이겨버린다. */
    select {
        min-width: 0;
    }

    /* 날짜·시각 입력은 값이 길고 피커 아이콘까지 들어가서, 글자를 16px 로 올리면
       w-32 같은 고정 폭 안에서 뒷자리가 잘린다 (2026-09-02 → "2026-09-0").
       min-width 는 Tailwind 의 width 유틸리티가 건드리지 않으므로 !important 없이
       고정 폭을 이긴다. w-full 인 경우엔 하한만 올리므로 그대로 full 이다. */
    input[type='date'],
    input[type='month'],
    input[type='time'],
    input[type='datetime-local'] {
        min-width: fit-content;
    }

    /* 긴 MAC·URL·기기명이 줄바꿈 없이 화면을 넘기는 것을 막는다. */
    .break-anywhere {
        overflow-wrap: anywhere;
        word-break: break-word;
    }
}
