/* ══════════ 위젯 판 — 판·달력·지하철 공통 규칙 ═══════════════════════════
   ⛔ 이 파일은 **자동 생성**이다. 손으로 고치지 말 것.
        만드는 법:  python automation/sync_board_css.py
        값의 주인:  portal_widget_board_v4.html  (판 규격본 · 디자이너)
      규격본을 고치고 위 명령을 다시 돌린다. 여기서 고치면 그 순간 갈라진다.
      배포 게이트(deploy_portal.gate_widget_board)가 두 파일을 대조해 갈라지면 배포를 막는다.

   담기는 것 = 판 자체(.wb · .w · .wp · .v1 · .mini · .sk · .wph · --wg-*) + 지하철(.sw-*)
   담기지 않는 것 = 날씨는 weather.css · 달력은 calendar.css 가 따로 떠 온다. 셸 기하(--stripw 등)는
              shell_tokens.css 단독 소유다 — 여기서 새로 선언하지 않는다.

   ⚠ 판 안의 글자에 opacity 를 쓰지 말 것(투명도는 곱해진다). 색은 --wg-ink-1/2/3 으로.
   ⚠ 한 칸은 정사각이다. 행 높이(--wg-cell)는 board.js 가 실제 열 폭을 재서 넣는다 —
     CSS 만으로는 자기 폭을 참조할 수 없다. JS 가 죽어도 폴백 208px 로 판은 선다.
   ══════════════════════════════════════════════════════════════════════════ */

.hub{--wg-gap:16px;--wg-min:196px;--wg-cell:208px;--wg-r:16px;--wg-pad:16px;--wg-max:1320px;--wg-ink-1:#FFFFFF;--wg-ink-2:#C8C8C8;--wg-ink-3:#B4B4B4}
.wbhead{display:flex;align-items:center;gap:10px;height:24px;margin-top:24px; max-width:var(--wg-max);font-size:11.5px;color:var(--wg-ink-2)}
.wbhead .sp{flex:1}
.wbhead .tip{text-shadow:0 1px 3px rgba(0,0,0,.55)}
.wbhead button{font:inherit;font-size:11.5px;padding:3px 9px;border-radius:6px;cursor:pointer; border:1px solid transparent;background:transparent;color:var(--wg-ink-2); text-shadow:0 1px 3px rgba(0,0,0,.55)}
.wbhead button:hover{background:rgba(255,255,255,.12);color:#fff}
.wbhead button.done{border-color:var(--hs-line);background:rgba(255,255,255,.14);color:#fff;font-weight:600}
.wbhead button:focus-visible{outline:2px solid #00A4EB;outline-offset:2px}
.wb{margin-top:10px;max-width:var(--wg-max); display:grid;gap:var(--wg-gap); grid-template-columns:repeat(auto-fill,minmax(var(--wg-min),1fr)); grid-auto-rows:var(--wg-cell); align-content:start}
.w[data-size="s"]{grid-column:span 1;grid-row:span 1}
.w[data-size="m"]{grid-column:span 2;grid-row:span 1}
.w[data-size="l"]{grid-column:span 2;grid-row:span 2}
.wb[data-cols="1"] .w{grid-column:span 1}
.w{position:relative;border-radius:var(--wg-r);overflow:hidden; background:rgba(8,11,16,.78);border:1px solid var(--hs-line); box-shadow:0 10px 30px rgba(0,0,0,.32); display:flex;flex-direction:column;color:var(--wg-ink-1); text-align:left;font:inherit;padding:0;cursor:pointer}
.w:hover{border-color:rgba(255,255,255,.42)}
.w:focus-visible{outline:2px solid #00A4EB;outline-offset:2px}
.w-h{flex:none;display:flex;align-items:center;gap:7px;min-height:20px; padding:var(--wg-pad) var(--wg-pad) 0; font-size:11.5px;font-weight:600;color:var(--wg-ink-2);white-space:nowrap}
.w-h > span:nth-of-type(1){overflow:hidden;text-overflow:ellipsis}
.w-h .sp{flex:1}
.w-h .st{font-size:10.5px;font-weight:400;color:var(--wg-ink-3);flex:none; font-variant-numeric:tabular-nums}
.w-h .dot{width:6px;height:6px;border-radius:50%;background:#4CC38A;flex:none}
.w-h .dot.stale{background:#E0A227}
.w-h .dot.err{background:#E05C4A}
.w-b{flex:1;min-height:0;padding:10px var(--wg-pad) var(--wg-pad); display:flex;flex-direction:column;overflow:hidden}
.w[data-size="s"] .w-b{justify-content:center}
.w-x{position:absolute;right:8px;bottom:8px;z-index:5;font-size:9.5px;letter-spacing:.06em; color:#FFCE73;background:rgba(0,0,0,.5);border:1px solid rgba(255,206,115,.5); padding:1px 5px;border-radius:4px;pointer-events:none}
.wsep{height:1px;background:rgba(255,255,255,.16);margin:10px calc(var(--wg-pad) * -1)}
.v1{min-height:44px;display:flex;align-items:flex-end;gap:3px;overflow:hidden;white-space:nowrap; flex:none}
.v1 .num{font-size:40px;line-height:1;font-weight:600;letter-spacing:-.035em; font-variant-numeric:tabular-nums}
.v1 .word{font-size:26px;line-height:1.15;font-weight:600;letter-spacing:-.03em}
.v1 .unit{font-size:14px;font-weight:600;color:var(--wg-ink-2);padding-bottom:4px}
.v1 sup{font-size:.34em;font-weight:400;vertical-align:top;top:.35em;position:relative; color:var(--wg-ink-2)}
.v1.soon .num,.v1.soon .word{color:#FFB020}
.v2l{font-size:12px;color:var(--wg-ink-2);margin-top:8px;line-height:1.45;min-height:17px; overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.v2l .del{font-weight:600;font-variant-numeric:tabular-nums}
.del.up{color:#4CC38A}
.del.dn{color:#E05C4A}
.mini{display:flex;flex-direction:column;font-size:12.5px}
.mini div{padding:5px 0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.mini div + div{border-top:1px solid rgba(255,255,255,.10)}
.mini em{font-style:normal;color:var(--wg-ink-2);font-size:11.5px;margin-right:7px; font-variant-numeric:tabular-nums}
.w-msg{flex:1;display:flex;flex-direction:column;align-items:flex-start;justify-content:center; gap:7px;font-size:12.5px;line-height:1.5;color:var(--wg-ink-2)}
.w-msg b{font-size:13px;font-weight:600;color:#fff}
.w-msg button{font:inherit;font-size:12px;padding:4px 10px;border-radius:7px;cursor:pointer; border:1px solid var(--hs-line);background:rgba(255,255,255,.06);color:#fff}
.sk{background:rgba(255,255,255,.13);border-radius:5px;height:11px}
.sk.big{height:30px;width:58%}
.sk.w7{width:70%}
.sk.w5{width:46%}
.w-sk{flex:1;display:flex;flex-direction:column;gap:9px;justify-content:center}
.sw-row{display:flex;align-items:center;gap:9px;padding:6px 0;min-height:36px}
.sw-row + .sw-row{border-top:1px solid rgba(255,255,255,.10)}
.sw-line{width:8px;height:8px;border-radius:50%;flex:none}
.sw-dir{font-size:12.5px;color:var(--wg-ink-2);flex:1;min-width:0; overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sw-t{font-size:17px;font-weight:700;letter-spacing:-.02em;flex:none}
.sw-t .num{font-variant-numeric:tabular-nums}
.sw-t .word{font-size:14px}
.sw-t .unit{font-size:11px;font-weight:600;color:var(--wg-ink-2);margin-left:2px}
.sw-t.soon{color:#FFB020}
.sw-next{font-size:11.5px;color:var(--wg-ink-2);white-space:nowrap;flex:none}
.sw-dest{font-size:11.5px;color:var(--wg-ink-3);flex:none; overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:28%}
.sw-more{font-size:11.5px;color:var(--wg-ink-3);padding-top:7px}
.sw-chips{display:flex;gap:5px;flex-wrap:wrap;margin:2px 0 10px}
.sw-chips button{font:inherit;font-size:11.5px;padding:3px 9px;border-radius:999px;cursor:pointer; border:1px solid var(--hs-line);background:transparent;color:var(--wg-ink-2)}
.sw-chips button[aria-pressed="true"]{background:rgba(255,255,255,.16);color:#fff;font-weight:600; border-color:rgba(255,255,255,.5)}
.wp-bd{position:absolute;inset:0;z-index:20;background:rgba(0,0,0,.48); opacity:0;pointer-events:none;transition:opacity .22s ease}
.hub.panel .wp-bd{opacity:1;pointer-events:auto}
.wp{position:absolute;z-index:21;left:50%;top:50%;transform:translate(-50%,-50%) scale(.96); width:560px;max-width:calc(100% - 64px);max-height:78%; display:flex;flex-direction:column;overflow:hidden; border-radius:18px;border:1px solid var(--hs-line); background:#0E1319;box-shadow:0 30px 80px rgba(0,0,0,.55);color:#fff; opacity:0;pointer-events:none;transition:opacity .2s ease, transform .2s ease}
.hub.panel .wp{opacity:1;pointer-events:auto;transform:translate(-50%,-50%) scale(1)}
.wp-h{flex:none;display:flex;align-items:center;gap:10px;padding:16px 18px 12px; border-bottom:1px solid rgba(255,255,255,.12)}
.wp-h h3{margin:0;font-size:15px;font-weight:600}
.wp-h .sp{flex:1}
.wp-h .st{font-size:11px;color:var(--wg-ink-3)}
.wp-h button{font:inherit;width:28px;height:28px;border-radius:7px;cursor:pointer; border:1px solid var(--hs-line);background:rgba(255,255,255,.07);color:#fff;line-height:1}
.wp-b{flex:1;min-height:0;overflow-y:auto;padding:16px 18px 18px}
.wp-src{padding:0 18px 14px;font-size:10.5px;color:var(--wg-ink-3);text-align:center}
.wp .grab{display:none}
.wp .wsep{margin:12px -18px}
.wp-act{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
.wp-act button{font:inherit;font-size:12.5px;padding:7px 12px;border-radius:8px;cursor:pointer; border:1px solid var(--hs-line);background:rgba(255,255,255,.07);color:#fff}
.wp-gr{display:grid;grid-template-columns:repeat(4,1fr);border-top:1px solid rgba(255,255,255,.16); margin:12px -18px 0}
.wp-g{padding:11px 10px 13px;text-align:center}
.wp-g + .wp-g{border-left:1px solid rgba(255,255,255,.12)}
.wp-g dt{font-size:10.5px;color:var(--wx-ink-2);margin:0 0 4px}
.wp-g dd{margin:0;font-size:15px;font-weight:600;font-variant-numeric:tabular-nums}
.hub.edit .w{cursor:grab;border-style:dashed;border-color:rgba(255,255,255,.45)}
.hub.edit .w:active{cursor:grabbing}
.w-grip,.w-off,.w-size{display:none}
.hub.edit .w-grip{display:grid;place-items:center;position:absolute;left:6px;top:6px;z-index:6; width:26px;height:26px;border-radius:7px;color:var(--wg-ink-2); background:rgba(0,0,0,.55);font-size:13px;letter-spacing:-2px;pointer-events:none}
.hub.edit .w-off{display:grid;place-items:center;position:absolute;right:6px;top:6px;z-index:6; width:26px;height:26px;border-radius:50%;cursor:pointer; border:1px solid var(--hs-line);background:rgba(0,0,0,.7);color:#fff;font-size:13px;line-height:1}
.hub.edit .w-off:hover{background:#E05C4A;border-color:#E05C4A}
.hub.edit .w-size{display:flex;position:absolute;left:50%;bottom:8px;transform:translateX(-50%); z-index:6;gap:3px;padding:3px;border-radius:999px;background:rgba(0,0,0,.72); border:1px solid var(--hs-line)}
.w-size button{font:inherit;display:grid;place-items:center;width:26px;height:22px; border:0;border-radius:999px;background:transparent;cursor:pointer;color:var(--wg-ink-2)}
.w-size button:hover{background:rgba(255,255,255,.16);color:#fff}
.w-size button[aria-pressed="true"]{background:#fff;color:#0E1319}
.w-size i{display:block;border:1.6px solid currentColor;border-radius:2px}
.w-size i.s{width:9px;height:9px}
.w-size i.m{width:15px;height:8px}
.w-size i.l{width:14px;height:14px}
.w.dragging{position:fixed;z-index:30;pointer-events:none;opacity:.95; box-shadow:0 26px 60px rgba(0,0,0,.6);border-style:solid;border-color:#00A4EB}
.wph{border:1.5px dashed rgba(255,255,255,.55);border-radius:var(--wg-r); background:rgba(255,255,255,.06)}
.wboff{max-width:var(--wg-max);margin-top:16px;padding:12px 14px;border-radius:12px; border:1px dashed rgba(255,255,255,.30);background:rgba(8,11,16,.62); display:none;align-items:center;gap:9px;flex-wrap:wrap}
.hub.edit .wboff{display:flex}
.wboff > b{font-size:11.5px;font-weight:600;color:var(--wg-ink-2);margin-right:3px}
.wboff .none{font-size:12px;color:var(--wg-ink-3)}
.wboff button{font:inherit;font-size:12px;padding:5px 11px;border-radius:999px;cursor:pointer; border:1px solid var(--hs-line);background:rgba(255,255,255,.08);color:#fff}
.wboff button:hover{background:rgba(0,164,235,.28);border-color:#00A4EB}
@media (prefers-reduced-transparency:reduce){
  .w{background:#0B0E13}
}
@media (prefers-reduced-motion:reduce){
  .wp,.wp-bd{transition:none}
}
@media (max-width:900px){
  .hub{--wg-gap:12px;--wg-min:132px;--wg-pad:14px}
  .wb{overflow-y:auto;min-height:0}
  .wbhead{margin-top:14px}
  .v1{min-height:38px}
  .v1 .num{font-size:32px}
  .v1 .word{font-size:21px}
  .wp{left:0;right:0;bottom:0;top:auto;width:auto;max-width:none;max-height:86%; transform:translateY(101%);border-radius:22px 22px 0 0;border-bottom:0}
  .hub.panel .wp{transform:translateY(0)}
  .wp .grab{display:block;position:absolute;left:50%;top:8px;transform:translateX(-50%); width:36px;height:4px;border-radius:2px;background:rgba(255,255,255,.42);z-index:4}
  .wp-h{padding-top:20px}
}

/* ══ 포털 결선 — 규격본에 없고 허브에만 필요한 것 ═══════════════════════════
   ⛔ 이 블록도 자동 생성이다(automation/sync_board_css.py 의 TAIL).
   ⚠ `body.hubboard` 는 board.js 가 판을 실제로 세웠을 때만 붙인다 —
     판이 없는 상태(권한 없음·스크립트 실패)에서 허브 배치가 바뀌면 안 된다. */
/* DOM 을 직접 그리는 위젯(지하철)이 들어가는 속칸. 판이 붙인 손잡이·숨김·크기 알약은
   이 칸의 **형제**로 남는다 → 위젯이 제 속을 다시 그려도 그 장치들이 지워지지 않는다. */
.w > .w-sub{flex:1;min-height:0;display:flex;flex-direction:column}
/* 인사줄 → 판 → (남는 공간) → 문의 줄. 문의 줄을 **화면 바닥으로** 내린다
   (사용자 결정 2026-08-17: 위젯 판이 그 위에 들어간다).
   ⚠ 선택자를 셸 v2 규칙과 **같은 특이도**로 맞춘다 —
     `:root[data-shell="v2"] body.hubon .hubwrap` 이 폭·여백을 이미 정하고 있어서
     낮은 선택자로 쓰면 조용히 무시된다. 뒤에 오는 파일이라 같은 특이도면 이쪽이 이긴다.
   ⚠ 폭은 건드리지 않는다 — 판의 폭은 `.wb{max-width:var(--wg-max)}` 가 잡는다. */
:root[data-shell="v2"] body.hubon.hubboard .hubwrap,
body.hubboard .hubwrap{display:flex;flex-direction:column;min-height:100vh}
/* ⚠ 인사줄(.hubhello)은 2026-08-18 에 마크업째 삭제됐다 → 순서 선언도 함께 걷었다.
   순서는 이제 카드(2) → 판(3) → 문의(4) 뿐이다. */
body.hubboard .hubsec,body.hubboard .hubcards{order:2}
body.hubboard .wbwrap{order:3;min-height:0;display:flex;flex-direction:column}
body.hubboard .hubutil{order:4;margin-top:auto;padding-top:16px}
/* 펼침 판은 화면 기준이다. `.hub` 는 스크롤되는 상자라 absolute 로 두면
   아래로 스크롤했을 때 판이 화면 밖에 선다(실제로 겪기 전에 막는다). */
body.hubboard .wp-bd,body.hubboard .wp{position:fixed}
@media (max-width:900px){
  body.hubboard .hubwrap{min-height:0}
  /* 폰 = **2열**(사용자 결정). 정사각 한 칸이라 1열이면 294px 짜리 거대한 타일이 된다 */
  body.hubboard .wb{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* ★ 판을 **위로 당긴다** (2026-08-18 사용자 지시: "모바일에서 위젯편집과 위젯을 좀 더
     상단에 붙여도 되지 않아?"). 폰에서는 헤더 아래 여백이 데스크톱 기준으로 잡혀 있어
     첫 타일이 한참 내려와 있었다.
     ⚠ 헤더(사용자 칩)와 겹치면 안 된다 — 어제 고친 결함이 그 자리다. 그래서 0 으로
       붙이지 않고 한 줄 간격(8px)만 남긴다.
     ⛔⛔ 2026-08-28 재발 발견(390px 실측) — 위 처방이 **한 번도 적용된 적이 없었다.**
       `body.hubboard .hubwrap`(0,2,0)은 login.css `:root[data-shell="v2"] body.hubon
       .hubwrap`(0,3,0, 같은 ≤900 블록 안에 있다)에 특이도로 **항상 진다** → 실제
       padding-top 은 8 이 아니라 login.css 의 `--hs-block`(20)이었다(실측: wbEdit
       top = hubwrap top(54, 첫 아이콘과 일치) + 20 + wbhead margin-top 8 = **82**,
       기대값은 54+8+8=70 — 12px 차이). 바로 위 `min-height:0` 규칙은 이미 겪은 같은
       함정을 login.css 쪽에서 `#hub` id 로 특이도를 올려 고쳐 뒀는데(2026-08-18,
       login.css 1561행 주석 참고), 이 padding-top 규칙만 그 처방이 안 들어갔다.
     → 여기서도 **같은 처방**을 쓴다: `body.hubon.hubboard` 로 특이도를 (0,4,0)까지
       올려 login.css 의 (0,3,0)을 이긴다. */
  :root[data-shell="v2"] body.hubon.hubboard .hubwrap,
  body.hubboard .hubwrap{padding-top:8px}
  .wbhead{margin-top:8px}
}
/* ══ 달력은 폰에서 **두 칸 높이**로 세운다 (사용자 신고 2026-08-18: "캘린더도 짤려있고")
   달력은 그 달 전체를 보는 화면이다 → 6주 격자가 통째로 보여야 한다. 그런데 폰 2열에서
   한 칸은 정사각(칸 높이 = 열 폭)이라 자리가 모자란다 — 390px 실측:
       필요 = 머리 1줄 + 6주 × 20.6px ≈ 146px  /  자리 = 141 - 34(머리줄) - 24(여백) = 83px
   줄 높이를 1.0 까지 눌러도 87px 이라 **글자를 줄여서 넣는 길이 없다**(계산으로 확인).
   → 잘림을 남기지 않는 유일한 답은 타일을 그만큼 높이는 것이다.
   ⚠ 임계는 폭이 아니라 **칸 높이**다: 두 열에서 칸 높이 = (뷰포트 - 108)/2 이므로
     146+58 = 204px 를 넘기려면 뷰포트가 516px 이상이어야 한다(실측 390→141 · 430→161 로
     이 식이 맞는 것을 확인). 그래서 560px 아래에서만 건다 — 768px 태블릿에서 달력이
     672px 짜리로 부푸는 것을 막는다.
   ⚠ 크기 알약으로 `작게`·`크게` 를 고른 사람은 건드리지 않는다(중간 = 기본값만). */
@media (max-width:560px){
  body.hubboard .wb .w[data-k^="cal"][data-size="m"]{grid-row:span 2}
}
