/* Rutineer 사용자앱 스타일 — 2026-08-07 rutineer.html 인라인 <style> 2블록에서 분리.
   문서 안에 있으면 브라우저가 캐시하지 못해 방문마다 다시 받는다(문서 200KB 의 일부였다).
   두 블록은 원본 문서 순서(head 블록 → body 블록) 그대로 이어 붙였다 — 캐스케이드 우선순위가 바뀌지 않는다.
   ※ 갱신 시 rutineer.html 의 ?v= 값을 함께 올릴 것(캐시 무효화). */

  :root{ --bg:#f4f6fb; --card:#fff; --line:#e5e8f0; --ink:#1a1c22; --sub:#6b7280;
         --brand:#2f6bff; --brand2:#ff5a3c; --ok:#16a34a; --warn:#f59e0b; --danger:#dc2626; --nav:#3b6ef6; --r:14px; }
  *{ box-sizing:border-box; } html,body{ margin:0; padding:0; }
  /* 스크롤바 유무로 인한 좌우 밀림 방지 — 스크롤바 공간 항상 예약 */
  html{ scrollbar-gutter:stable; overflow-y:scroll; }
  body{ font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Malgun Gothic",sans-serif;
        background:var(--bg); color:var(--ink); line-height:1.45; -webkit-text-size-adjust:100%; }
  a{ color:inherit; text-decoration:none; }
  header{ position:sticky; top:0; z-index:30; background:var(--nav); color:#fff; box-shadow:0 2px 10px rgba(30,60,140,.12); }
  .hd{ max-width:1180px; margin:0 auto; padding:0 14px; display:flex; align-items:center; gap:6px; height:56px; position:relative; }
  .hamburger{ display:none; background:transparent; border:0; color:#fff; font-size:22px; line-height:1; cursor:pointer; padding:0 6px 0 0; }/* 햄버거 — 모바일 @media에서만 노출(신청/정보/수다 등 내비) */
  /* 로고가 좌측 LNB 컬럼(200px)을 차지 → 상단 탭이 콘텐츠 라인부터 시작(메인이 LNB 영역 침범 안 함) */
  .logo{ font-weight:800; font-size:19px; width:200px; flex:none; margin-right:18px; white-space:nowrap; cursor:pointer; text-align:center; }
  .topnav{ display:flex; gap:2px; overflow-x:auto; flex:1; scrollbar-width:none; }
  @media (max-width:820px){ .logo{ width:auto; margin-right:12px; } }
  /* 우측 프로필 아바타 + 드롭다운 (정의서 상단바 형식) */
  .hprofile{ width:32px; height:32px; border-radius:50%; background:rgba(255,255,255,.22); color:#fff; display:flex; align-items:center; justify-content:center; font-weight:800; font-size:14px; cursor:pointer; }
  .pmenu{ position:absolute; right:0; top:calc(100% + 10px); background:#fff; color:var(--ink); border:1px solid var(--line); border-radius:12px; box-shadow:0 8px 24px rgba(20,30,60,.16); min-width:170px; padding:6px; display:none; z-index:40; }
  .pmenu.on{ display:block; }
  .pmenu .pmi{ padding:9px 12px; border-radius:8px; font-size:14px; font-weight:600; cursor:pointer; display:block; color:var(--ink); text-decoration:none; }
  .pmenu .pmi:hover{ background:#f2f5ff; }
  .pmenu .pmsep{ height:1px; background:var(--line); margin:4px 6px; }
  .topnav::-webkit-scrollbar{ display:none; }
  .topnav button{ border:0; background:transparent; color:#dbe6ff; font-weight:700; font-size:15px; padding:8px 14px; border-radius:9px; cursor:pointer; white-space:nowrap; }
  .topnav button.on{ background:rgba(255,255,255,.18); color:#fff; }
  .htools{ display:flex; align-items:center; gap:8px; }
  .ic{ font-size:17px; cursor:pointer; opacity:.95; position:relative; }
  /* 비밀번호 보기 토글 — 눈 이모지(👁) 대신 SVG 눈 아이콘. .on(=보기 상태)이면 눈-off 아이콘 */
  .pweye{ width:20px; height:20px; display:inline-block; background:center/20px no-repeat;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'/%3E%3Ccircle cx='12' cy='12' r='3'/%3E%3C/svg%3E"); }
  .pweye.on{ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23555' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24'/%3E%3Cline x1='1' y1='1' x2='23' y2='23'/%3E%3C/svg%3E"); }
  .lnk{ font-size:12px; color:#e5edff; border:1px solid rgba(255,255,255,.35); border-radius:8px; padding:5px 8px; white-space:nowrap; }
  .who{ font-size:12.5px; color:#eaf1ff; white-space:nowrap; max-width:110px; overflow:hidden; text-overflow:ellipsis; }
  .authbtn{ background:#fff; color:var(--nav); border:0; border-radius:8px; padding:6px 12px; font-weight:700; font-size:13px; cursor:pointer; }
  .body{ max-width:1180px; margin:0 auto; display:flex; gap:18px; padding:18px 14px 90px; align-items:flex-start; }
  /* 정의서: LNB는 회색 패널 / 콘텐츠는 흰색 · 선택 항목은 왼쪽 '바'만(박스 채움 없음) */
  .lnb{ width:200px; flex:none; background:#eef1f7; border:1px solid var(--line); border-radius:0; padding:8px 0; position:sticky; top:74px; }
  .side{ width:280px; flex:none; position:sticky; top:74px; }
  .side:empty{ display:none; }
  .lnb .grp{ font-size:12px; color:var(--sub); font-weight:800; padding:8px 14px 6px; }
  .lnb button{ display:block; width:100%; text-align:left; border:0; background:transparent; color:var(--ink); padding:11px 14px; border-radius:0; font-size:14px; font-weight:600; cursor:pointer; border-left:3px solid transparent; }
  .lnb button:hover{ background:rgba(255,255,255,.55); color:var(--brand); }
  /* 선택: 섹션 전체 폭을 채우는 흰색 밴드 + 왼쪽 바(별도 박스 아님) */
  .lnb button.on{ background:#fff; color:var(--brand); border-left:3px solid var(--brand); font-weight:800; }
  main{ flex:1; min-width:0; }
  .btmtab{ display:none; }/* 데스크톱: 하단 탭 숨김(모바일 @media에서만 노출) */
  .mobonly{ display:none; }/* 모바일 전용 요소(프로필 메뉴의 게시판 진입 등) — 데스크톱 숨김 */
  .backbar{ display:none; }/* 앱 서브화면 뒤로가기 바 — 모바일 @media·서브화면(.on)에서만 노출(정의서 앱 상단 ←) */
  @media (max-width:820px){
    .body{ flex-direction:column; gap:10px; padding-top:10px; align-items:stretch; }/* column 전환 시 교차축(가로) stretch로 main을 컨테이너 폭에 맞춤 — flex-start 유지 시 main이 max-content(제안하기 헤더 등)로 커져 가로 넘침(AP-01) */
    .lnb{ width:100%; position:static; display:flex; gap:6px; overflow-x:auto; padding:8px; }
    .side{ width:100%; position:static; order:-1; }
    .lnb .grp{ display:none; }
    .lnb button{ width:auto; white-space:nowrap; padding:8px 12px; border-radius:20px; }
    .lnb button.on{ border-left:0; background:var(--brand); color:#fff; }
    /* 앱(PWA) 하단 탭 내비 — 정의서 PART5(모바일 로그인 사용자) : 🏠피드 ➕인증 🏆챌린지 👤마이 */
    .btmtab{ display:flex; position:fixed; left:0; right:0; bottom:0; z-index:60; background:#fff; border-top:1px solid var(--line); box-shadow:0 -2px 10px rgba(20,30,60,.07); padding-bottom:env(safe-area-inset-bottom); }
    .btmtab button{ flex:1; border:0; background:transparent; display:flex; flex-direction:column; align-items:center; gap:2px; padding:7px 0 6px; font-size:11px; color:var(--sub); font-weight:700; cursor:pointer; }
    .btmtab button .ic{ font-size:20px; line-height:1.1; }
    .btmtab button.on{ color:var(--brand); }
    body{ padding-bottom:60px; overflow-x:hidden; }/* 모바일 가로 오버플로우 차단 — 뷰포트 폭 고정, 내부 flex를 390 기준 재배치(AP-01 등 shrink-to-fit 확장 방지) */
    /* 앱(모바일) 정의서 정렬(PART4/5): 상단 대메뉴·검색·좌측 LNB·사이드(내현황/랭킹)·'메인' 섹션제목 숨김
       → 상단은 로고+알림+프로필, 내비는 하단탭+화면내탭으로 단순화(정의서 앱 화면 구조와 일치) */
    #topnav{ display:none; }
    /* [모바일] 상단 통합검색 아이콘(🔍)은 노출 — 검색은 우측상단 아이콘으로 진입(햄버거 내 검색은 제거) */
    .lnb{ display:none !important; }
    .side{ display:none !important; }
    .secttl{ display:none !important; }/* .h1{display:flex}가 뒤에 와서 덮으므로 우선순위 강제 */
    .pmi.mobonly{ display:block; }
    /* 서브화면(상세·작성·랭킹·알림 등) 상단 뒤로가기 바 — 정의서 앱의 '←' 반영 */
    /* ★2026-08-12 메인·마이페이지에도 '← 뒤로' 가 떠 있던 것 — 이 미디어 구간의
       `button:not(.btmtab button), .btn{ display:inline-flex }` 가 위쪽의 `.backbar{ display:none }`
       보다 우선순위가 높아(:not 안의 `.btmtab button` 때문) 숨김이 덮였다.
       서브화면이 아닐 때(.on 없음)는 확실히 숨기도록 클래스 둘로 우선순위를 올린다. */
    .backbar:not(.on){ display:none; }
    .backbar.on{ display:block; width:100%; text-align:left; border:0; border-bottom:1px solid var(--line); background:#fff; padding:11px 14px; font-size:15px; font-weight:700; color:var(--ink); cursor:pointer; position:sticky; top:0; z-index:40; }
    .hamburger{ display:inline-flex; align-items:center; }/* 모바일 햄버거 노출 */
    .hammenu{ left:6px; right:auto; }/* 햄버거 드롭다운은 좌측 정렬 */
    /* ★2026-08-11 야간 — 터치영역 40px 미달 (iPhone 14·Galaxy S20 실측 24건 FAIL의 실체)
       실측치: 필터·주제 칩 31px · 작은 버튼 33×31px · 섹션헤더 글자링크 19~20px · 주 버튼 37px.
       손가락 접촉면은 통상 40~48px 로 잡는다(Apple 44 · Android 48). 31px 칩이 6px 간격으로 붙어 있으면
       옆 칩이 눌린다 — 실제로 모바일에서 필터가 엉뚱하게 바뀐다는 지적이 재검에 있었다.
       ★글자 크기·색·간격은 건드리지 않는다 — 보이는 모양을 바꾸면 정의서와 어긋난다.
         높이만 40px 로 확보하고 글자를 세로 중앙에 둔다(padding 은 유지, 부족분만 min-height 로 채움).
       ★배지(.chip)는 제외한다 — 상태 표시이지 누르는 것이 아니다(예: "🟡 모집중" 23px).
       ★재측정 후 범위 확대 — .btn 계열만 잡았더니 button 인데 .btn 이 아닌 것들이 남았다:
         응원 버튼(.react 33px) · 햄버거(.hamburger 22x26px) · 중복확인 등. 버튼은 전부 잡는다.
         하단탭(.btmtab button)만 제외한다 — 자체 규격(세로 아이콘+글자)이 이미 48px 이상이다. */
    button:not(.btmtab button), .btn{
      min-height:40px; display:inline-flex; align-items:center; justify-content:center;
    }
    .hamburger{ min-width:40px; min-height:40px; justify-content:flex-start; }
    .btn.sm{ min-width:40px; }               /* ✕·목록 같은 짧은 버튼은 폭도 모자랐다(33px) */
    .h1 a.muted, .h1 a[onclick],             /* "⚙️ 설정" · "✏️ 글쓰기" 같은 헤더 글자링크 */
    .secln a{                                /* "전체 보기 ›" 같은 섹션줄 링크(19px 였다) */
      display:inline-flex; align-items:center; min-height:40px; padding:0 4px;
    }
    /* 본문 속 인라인 링크(해시태그 등)는 <글 흐름 안>에 있다 — 40px 블록으로 만들면 문장이 깨진다.
       실측: <a onclick="tagSearch(...)">#태그</a> 가 .content 안에서 21px.
       그래서 보이는 크기는 그대로 두고 투명 영역만 세로로 넓힌다 — 글자는 제자리, 손가락은 40px. */
    #main .content a[onclick]{ position:relative; }
    #main .content a[onclick]::after{
      content:""; position:absolute; left:0; right:0; top:50%; transform:translateY(-50%);
      height:40px;
    }
  }
  .btn{ appearance:none; border:1px solid var(--line); background:#fff; color:var(--ink); border-radius:10px; padding:8px 14px; font-size:14px; font-weight:600; cursor:pointer; }
  .btn:hover{ border-color:#c9cede; }
  .btn.pri{ background:var(--brand); border-color:var(--brand); color:#fff; }
  .btn.ok{ background:var(--ok); border-color:var(--ok); color:#fff; }
  .btn.sm{ padding:6px 10px; font-size:13px; border-radius:8px; }
  .btn.ghost{ background:transparent; }
  /* ★2026-08-11 가입 동의 영역 — 전체 동의 + 항목별.
     형제 서비스(TRA)와 구조는 같게 가되 <색은 우리 브랜드 톤>으로 맞춘다.
     회색 박스로 묶어 입력칸들과 시각적으로 분리한다 — 동의는 '읽고 고르는' 영역이라 폼과 성격이 다르다. */
  .terms-box{ background:#f6f7fb; border:1px solid var(--line); border-radius:12px;
              padding:12px 14px; margin-bottom:14px; }
  .terms-all{ display:flex; align-items:center; gap:8px; cursor:pointer; font-size:14px;
              padding-bottom:10px; border-bottom:1px solid var(--line); }
  .terms-all input{ width:auto; }
  .terms-list{ display:flex; flex-direction:column; gap:2px; padding-top:8px; }
  .terms-item{ display:flex; align-items:center; gap:8px; cursor:pointer; font-size:13px;
               color:var(--sub); min-height:32px; }
  .terms-item input{ width:auto; flex:none; }
  .terms-item a{ color:var(--ink); text-decoration:underline; text-underline-offset:2px; }
  .terms-item a:hover{ color:var(--brand); }
  .terms-item .tag-req{ color:var(--brand); font-weight:700; }
  .terms-item .tag-opt{ color:var(--sub); font-weight:700; }
  .card{ background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:16px; margin-bottom:14px; }
  .h1{ font-size:20px; font-weight:800; margin:2px 0 14px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
  .h1 .sp{ flex:1; }
  .row{ display:flex; align-items:center; gap:10px; }
  .avatar{ width:40px; height:40px; border-radius:50%; background:linear-gradient(135deg,#8ab4ff,#2f6bff); color:#fff; display:flex; align-items:center; justify-content:center; font-weight:700; flex:none; position:relative; overflow:hidden; }
  .avatar.sm{ width:30px; height:30px; font-size:13px; }
  /* 프로필 이미지는 어디에 꽂히든 컨테이너를 넘지 않게 한다.
     종전엔 `.avatar .avimg` 라 .avatar 자식만 잡혔는데, 헤더 프로필은 avInner() 가
     span#hpInit(=.avatar 아님) 안에 넣는다. 그래서 원본 크기로 렌더돼 상단이 통째로
     깨졌다(2026-08-06 실측: 마이 화면에서 헤더를 덮음). 클래스 단독으로 제약한다. */
  .avimg{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:1; }
  .avatar .avimg{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:1; }
  /* span#hpInit 은 position:static 이라 위 absolute 의 기준이 안 된다 — 기준을 만들어 준다. */
  #hpInit{ position:relative; display:block; width:100%; height:100%; border-radius:50%; overflow:hidden;
           display:flex; align-items:center; justify-content:center; }
  .nick{ font-weight:700; } .meta{ font-size:12px; color:var(--sub); }
  .streak{ color:var(--brand2); font-weight:700; }
  .photo{ margin:12px 0; height:200px; border-radius:12px; background:#fdf3e6; display:flex; align-items:center; justify-content:center; font-size:46px; color:#e2a24a; }
  /* 공통 사진 업로드 박스(대시 테두리·클릭 업로드) — 인증/게시글/신고 공용 */
  .uploadbox{ display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; min-height:150px; border:1.5px dashed var(--line); border-radius:12px; background:#fafbfe; color:var(--sub); font-size:15px; cursor:pointer; padding:16px; text-align:center; }
  .uploadbox:hover{ border-color:var(--brand); color:var(--brand); }
  /* ★2026-08-12 야간(모바일 전수) 무공백 긴 글이 <뷰포트를 뚫었다>.
     실측 — 무공백 140자 댓글에서 댓글 행 폭 1445px, 뷰포트 초과 +1148px(iPhone 14)/+1178px(S20).
     글자수 상한(maxlength=140) 안이라 <사용자가 그냥 만들 수 있는 값>이었고, 넘침은 무공백
     30자(S20)/33자(iPhone 14)부터 시작했다. 즉 방어선이 입력 글자수 제한뿐이었다.
     white-space:pre-wrap 은 <공백·개행>은 살리지만 공백이 없으면 끊을 자리를 못 찾는다 —
     끊을 자리를 강제하는 규칙을 함께 준다(anywhere 는 break-all 과 달리 공백 우선으로 끊는다). */
  .content{ margin:6px 0 10px; white-space:pre-wrap; overflow-wrap:anywhere; word-break:break-word; }
  .title{ font-weight:800; font-size:16px; overflow-wrap:anywhere; }
  .acts{ display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
  .react{ border:1px solid var(--line); background:#fff; border-radius:20px; padding:6px 14px; font-weight:700; cursor:pointer; font-size:14px; }
  .react.on{ background:#fff0ec; border-color:#ffd3c8; color:var(--brand2); }
  .chip{ display:inline-block; font-size:12px; color:var(--brand); background:#eef3ff; border-radius:20px; padding:3px 10px; font-weight:700; }
  .chip.g{ color:var(--ok); background:#e9f7ef; } .chip.w{ color:var(--warn); background:#fff6e6; }
  .bar{ height:8px; background:#eef1f8; border-radius:6px; overflow:hidden; margin:8px 0; }
  .bar > i{ display:block; height:100%; background:linear-gradient(90deg,#12b886,#38d9a9); }
  .empty{ text-align:center; color:var(--sub); padding:40px 10px; }
  /* ── 공통 프리로더(브랜드 톤) ──
     종전에는 '불러오는 중…' 이라는 맨 글자만 깔아 두어서, 응답이 조금만 늦어도
     화면이 멈춘 것처럼 보였다. 회전 스피너(짧은 대기)와 스켈레톤(목록 자리맡기)을
     한 곳에서 만들어 쓴다. 아래 pre()/preSkel()/btnBusy() 가 이 클래스들을 쓴다. */
  .pre{ display:flex; flex-direction:column; align-items:center; gap:10px; padding:34px 10px; color:var(--sub); font-size:13px; }
  .pre i{ width:26px; height:26px; border-radius:50%; border:2.5px solid #e6e9f2; border-top-color:var(--brand); animation:prespin .7s linear infinite; }
  @keyframes prespin{ to{ transform:rotate(360deg); } }
  /* 스켈레톤 — 회색 블록이 좌→우로 훑고 지나간다(내용이 곧 온다는 신호) */
  .skel{ background:linear-gradient(90deg,#eef1f6 25%,#f6f8fb 37%,#eef1f6 63%); background-size:400% 100%;
         animation:skelmv 1.2s ease-in-out infinite; border-radius:8px; }
  @keyframes skelmv{ 0%{ background-position:100% 50%; } 100%{ background-position:0 50%; } }
  .skcard{ background:#fff; border:1px solid var(--line); border-radius:14px; padding:14px; margin-bottom:10px; }
  .skrow{ display:flex; gap:10px; align-items:center; }
  /* 버튼 자체 진행 표시 — 저장 등 처리 중 중복 클릭을 막고 진행 중임을 알린다 */
  .btn.busy{ position:relative; color:transparent !important; pointer-events:none; }
  .btn.busy::after{ content:""; position:absolute; left:50%; top:50%; width:15px; height:15px; margin:-7.5px 0 0 -7.5px;
    border-radius:50%; border:2px solid rgba(255,255,255,.45); border-top-color:#fff; animation:prespin .7s linear infinite; }
  .btn.ghost.busy::after, .btn.sm.busy::after{ border-color:rgba(0,0,0,.18); border-top-color:var(--brand); }
  .secln{ display:flex; align-items:center; gap:10px; color:var(--sub); font-weight:700; font-size:13px; margin:16px 2px 10px; }
  .secln::before,.secln::after{ content:""; flex:1; height:1px; background:var(--line); }
  /* 섹션 헤더 우측에 액션(전체 보기)이 붙는 경우 — 액션을 <b>오른쪽 끝</b>으로 보낸다.
     종전에는 링크가 라벨 바로 뒤(구분선 사이)에 끼어 가운데에 떠 보였다.
     ::after(구분선)보다 뒤 order 를 줘서 선 → 액션 순서로 배치한다. */
  .secln.act-end::after{ order:2; }
  .secln.act-end > a{ order:3; margin-left:10px; }
  .statc{ flex:1; text-align:center; padding:16px 10px; } .statc .n{ font-size:26px; font-weight:800; } .statc .n.fire{ color:var(--brand2); } .statc .meta{ margin-top:2px; }
  .muted{ color:var(--sub); font-size:13px; }
  input,textarea,select{ width:100%; border:1px solid var(--line); border-radius:10px; padding:10px; font-size:14px; font-family:inherit; background:#fff; }
  textarea{ resize:vertical; min-height:80px; } .field{ margin:10px 0; } .field label{ font-size:12px; color:var(--sub); font-weight:700; display:block; margin-bottom:5px; }
  .stats{ display:flex; gap:18px; } .stats .n{ font-size:22px; font-weight:800; } .stats .n.fire{ color:var(--brand2); }
  .listrow{ display:flex; gap:10px; align-items:center; padding:12px 4px; border-bottom:1px solid var(--line); cursor:pointer; }
  .listrow:hover{ background:#fafbff; } .listrow .tt{ flex:1; min-width:0; } .listrow .tt b{ display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .tabs2{ display:flex; gap:6px; margin-bottom:10px; flex-wrap:wrap; }
  .tabs2 button{ border:1px solid var(--line); background:#fff; border-radius:20px; padding:6px 12px; font-size:13px; font-weight:700; color:var(--sub); cursor:pointer; }
  .tabs2 button.on{ background:var(--brand); color:#fff; border-color:var(--brand); }
  .rankrow{ display:flex; align-items:center; gap:8px; padding:8px 0; border-bottom:1px dashed var(--line); font-size:14px; }
  .rankrow:last-child{ border-bottom:0; } .rankno{ width:28px; text-align:center; font-weight:800; color:var(--sub); }
  /* 하이라이트 줄: 배경만 좌우로 살짝 넘치게(음수마진), 콘텐츠는 다른 줄과 동일 정렬 — 쪼그라듦/잘림 방지 */
  .rankrow.me{ background:#eef3ff; border-radius:8px; margin:0 -8px; padding:8px; }
  /* ★2026-08-12 야간 — 댓글도 같은 이유로 끊을 자리를 준다. Rutineer 앱 댓글은 공통 cmu.css 의
     .cmt .body(break-word 있음) 를 쓰지 않아 그 방어가 닿지 않았다(모바일 전수 실측). */
  .cmt{ padding:10px 0; border-top:1px solid var(--line); overflow-wrap:anywhere; word-break:break-word; }
  .cmt.reply{ margin-left:38px; }
  .cmtbar{ display:flex; gap:8px; margin-top:8px; flex-wrap:wrap; } .cmtbar input{ flex:1; min-width:0; }/* 모바일 좁은 폭에서 검색바 오버플로우 방지(input 축소 허용) */
  /* CM-08 태그 자동완성 드롭다운 — 검색 입력 바로 아래에 겹쳐 뜬다(부모 .cmtbar 가 position:relative) */
  .gs-suggest{ position:absolute; left:0; right:0; top:calc(100% + 4px); z-index:50; background:#fff;
    border:1px solid var(--line); border-radius:10px; box-shadow:0 8px 24px rgba(20,30,60,.12); overflow:hidden; max-height:280px; overflow-y:auto; }
  .gs-sg-item{ padding:10px 14px; font-size:14px; font-weight:600; color:var(--ink); cursor:pointer; }
  .gs-sg-item:hover{ background:#eef3ff; color:var(--brand); }
  /* 모달/시트 */
  .modal{ position:fixed; inset:0; background:rgba(15,20,35,.5); display:none; align-items:center; justify-content:center; z-index:50; padding:16px; }
  .modal.on{ display:flex; }
  /* [오류#2 → 스크롤락 방식 변경] 종전엔 html/body{overflow:hidden}으로 잠갔는데, 실제 스크롤 컨테이너가
     html(overflow-y:scroll)이라 overflow:hidden 이 걸리는 순간 스크롤이 top 으로 리셋돼 모달을 열고 닫으면
     화면이 맨 위로 점프했다. 이제 JS(syncScrollLock)가 position:fixed + 스크롤 오프셋 보존 방식으로 잠근다.
     body.scroll-locked 는 그 JS가 붙인다(현재 스크롤 위치를 top 오프셋으로 유지). */
  body.scroll-locked{ position:fixed; left:0; right:0; width:100%; overflow:hidden; }
  /* 모바일 하단탭(z-60)이 모달·바텀시트(z-50/55)보다 위라 오버레이 하단(닫기 버튼 등)을 가려 클릭이 막히던 문제 →
     모달/메뉴가 열려있는 동안 하단탭 숨김(오버레이 하단 버튼 클릭 가능). 데스크톱 하단탭은 원래 숨김이라 영향 없음 */
  body:has(.modal.on) .btmtab, body:has(.menu.on) .btmtab{ display:none; }
  table th{ text-align:center; } /* 0722 공통5: 리스트 헤더 중앙정렬 */
  .sheet{ background:#fff; border-radius:16px; width:100%; max-width:460px; padding:20px; max-height:88vh; overflow:auto; }
  .sheet.wide{ max-width:600px; }
  /* 상세(인증·챌린지·게시글) 팝업 전용 모달 — 다른 모달(로그인·신고·genModal)보다 아래(z-index 45)에 두어,
     상세 위에서 신고/로그인 등이 뜰 때 그것들이 상세 위에 겹치도록 함. 정의서 상세=✕ 딤 팝업 */
  #detailModal{ z-index:45; }
  #detailSheet{ max-width:600px; }
  /* 더보기(⋯) 메뉴 — 데스크톱은 화면 중앙 정렬 다이얼로그(앵커), 모바일은 하단 바텀시트(아래 @media에서 flex-end 분기). 기존엔 flex-end가 전역 적용돼 데스크톱에서도 하단에 붙어 위치가 깨졌음(CP-02) */
  .menu{ position:fixed; inset:0; background:rgba(15,20,35,.4); display:none; align-items:center; justify-content:center; z-index:55; padding:16px; }
  .menu.on{ display:flex; }
  .menu .inner{ background:#fff; border-radius:16px; width:100%; max-width:460px; padding:10px 0 18px; box-shadow:0 12px 40px rgba(20,30,60,.22); }
  .menu .mi{ padding:14px 20px; font-size:15px; cursor:pointer; display:flex; gap:10px; align-items:center; }
  .menu .mi:hover{ background:#f4f6fb; } .menu .mi.dz{ color:var(--danger); }
  /* 모바일: 더보기(⋯) 메뉴를 하단 바텀시트로(정의서 앱 형식). ★ 반드시 위 .menu 기본규칙 '다음'에 와야 소스순서상 재정의가 적용됨(데스크톱 중앙정렬 → 모바일 하단부착) */
  @media (max-width:820px){
    .menu{ align-items:flex-end; padding:0; }
    .menu .inner{ border-radius:16px 16px 0 0; box-shadow:0 -2px 10px rgba(20,30,60,.12); }
  }
  .demolist{ display:flex; flex-direction:column; gap:6px; max-height:52vh; overflow:auto; }
  .demoacc{ display:flex; align-items:center; gap:10px; border:1px solid var(--line); border-radius:12px; padding:9px 12px; cursor:pointer; }
  .demoacc:hover{ background:#f4f6fb; border-color:#c9cede; } .demoacc .pz{ font-size:12px; color:var(--sub); }
  /* pointer-events:none — 투명(미표시) 상태에서도 항상 DOM에 떠 있어 z-index 70으로 하단 버튼(더보기 '닫기' 등) 클릭을 가로채던 문제 수정. 토스트는 클릭 불필요하므로 항상 통과시킴(CP-02 닫기 미동작 해결) */
  /* 토스트 — 종전 bottom:26px 는 모바일 하단탭(≈56px)에 가려지고 웹(큰 화면)에선 시야 밖 맨 아래라 불편했다.
     하단탭을 확실히 넘기고 시야에 들어오게 올린다(모바일). 웹(하단탭 없음)에선 화면이 커서 하단 중앙보다
     상단 중앙이 눈에 잘 들어와 top 로 띄운다(헤더 아래). */
  .toast{ position:fixed; left:50%; bottom:calc(72px + env(safe-area-inset-bottom, 0px)); transform:translateX(-50%); background:#1a1c22; color:#fff; padding:11px 18px; border-radius:20px; font-size:14px; box-shadow:0 6px 20px rgba(15,20,35,.28); opacity:0; transition:opacity .2s, transform .2s; z-index:70; pointer-events:none; max-width:calc(100vw - 32px); text-align:center; }
  .toast.on{ opacity:1; }
  @media(min-width:900px){ .toast{ bottom:auto; top:76px; } }  /* 웹: 상단 중앙(헤더 아래) — 큰 화면에서 하단 맨 끝은 놓치기 쉬움 */
  .badge{ position:absolute; top:-6px; right:-8px; background:var(--brand2); color:#fff; font-size:10px; font-weight:800; border-radius:10px; padding:1px 5px; }

/* 중복확인 결과 문구 — 입력칸 바로 아래. 자리를 미리 잡아둬(min-height) 문구가 뜰 때 레이아웃이 밀리지 않게 한다. */
.dupmsg{font-size:12px;margin-top:4px;min-height:16px;line-height:16px}
.dupmsg.okmsg{color:#0a7d3c}
.dupmsg.ngmsg{color:#dc2626}
/* [UI] 필드 아래 인라인 검증 에러 — 토스트 대신 그 항목 밑에 붉게(가입·프로필·관리자 회원생성 공통). 내용 있을 때만 자리 차지. */
.ferr{ color:#dc2626; font-size:12px; margin-top:5px; line-height:1.45; font-weight:600; }
.ferr:empty{ display:none; }


  .site-footer{ margin-top:36px; }
  /* 웹(데스크톱)에서만 sticky footer — 콘텐츠 짧아도 푸터가 화면 최하단에 붙게. 모바일(하단탭)은 제외. */
  @media(min-width:641px){
    body{ min-height:100vh; display:flex; flex-direction:column; }
    header, .body{ flex:0 0 auto; }
    /* width:100% 필수 — body 가 flex 컬럼이 되면 .body 의 가로 auto margin(margin:0 auto)이
       교차축 stretch 를 무력화해서 폭이 콘텐츠 크기(max-content)로 쪼그라든다. 콘텐츠가 짧은
       화면(설정·알림 등)에서 레이아웃이 좁게 뭉쳐 가운데로 몰리는 증상(1440px 에서 1180→452px).
       폭을 100% 로 확정하고, 가운데 정렬은 기존 max-width:1180 + margin:0 auto 가 그대로 담당한다. */
    .body{ flex:1 0 auto; width:100%; }
    .site-footer{ margin-top:auto; }
  }
  .site-footer .ft-nav{ background:linear-gradient(135deg,#2f6bff 0%,#1e3a8a 100%); padding:15px 20px; display:flex; flex-wrap:wrap; gap:10px 28px; justify-content:center; }
  .site-footer .ft-nav a{ color:#dbe6ff; font-size:14px; font-weight:600; cursor:pointer; text-decoration:none; }
  .site-footer .ft-nav a:hover{ color:#fff; }
  .site-footer .ft-btm{ padding:18px 20px 24px; text-align:center; background:#f8fafc; border-top:1px solid var(--line); }
  .site-footer .ft-legal a{ color:var(--sub); font-size:13px; cursor:pointer; text-decoration:none; }
  .site-footer .ft-legal a:hover{ text-decoration:underline; color:var(--brand); }
  /* ★2026-08-12 개인정보처리방침만 파랗게 튀어 옆 링크들과 따로 놀았다 — 색은 나머지와 같은 회색으로 맞춘다.
     굵기는 남긴다. 개인정보처리방침은 다른 약관과 <구분되게> 표시하는 것이 관행이라, 색 대신 굵기로만 구분한다. */
  .site-footer .ft-legal a.strong{ color:var(--sub); font-weight:700; }
  .site-footer .ft-legal .sep{ color:#c9d3e6; margin:0 7px; }
  /* ★2026-08-11 사업자·책임자 정보 줄 — 법적 고지라 눈에 띄되 본문보다 조용해야 한다.
     약관 링크(13px)와 저작권(12px) 사이 크기로 두고, 좁은 화면에서 두 줄로 접히게 line-height 를 넉넉히 준다. */
  .site-footer .ft-biz{ margin-top:10px; font-size:12px; color:#94a3b8; line-height:1.7; }
  .site-footer .ft-biz a{ color:#94a3b8; text-decoration:none; }
  .site-footer .ft-biz a:hover{ color:var(--brand); text-decoration:underline; }
  .site-footer .ft-biz .sep{ color:#c9d3e6; margin:0 6px; }
  .site-footer .ft-copy{ margin-top:9px; font-size:12px; color:#94a3b8; }
  @media(max-width:640px){ .site-footer{ display:none; } } /* 앱(모바일)에선 푸터 숨김 — 웹(데스크톱)에서만 노출 */
