/* Threads Autobot — SEED 파생 대시보드 레이어
   SEED 에 없는 데스크톱 컴포넌트만 정의한다. 색·간격·라디우스는 전부 토큰. */

/* ---------- 폰트 : Wanted Sans + Pretendard 폴백 ----------

   **두 폰트를 겹쳐 쓴다.** 한 폰트로는 안 됐다 - 후보를 파일로 열어 재본 결과
   (`docs/research/2026-08-20-font-audit.md`):

   | 폰트 | 한글 음절 | 가나 | `tnum` |
   |---|---:|---:|:---:|
   | Wanted Sans | 11172/11172 | **0** | 있다 |
   | Pretendard | 11172/11172 | 174자 | 있다 |
   | SUIT | **2668** (23.9%) | 0 | 있다 |
   | S-Core Dream | 11172/11172 | 169자 | **없다** |

   Wanted Sans 를 앞에 세운다(사람 결정 - 더 개성 있는 인상). 다만 Pretendard 가
   덮는 **2,345 코드포인트를 덮지 못한다**: 히라가나 84 · 가타카나 94 · 전각기호
   96 · 그리스 · 키릴 등. 코퍼스에 일본어 인기글이 있어서(`draft 33`) 이걸 비우면
   한 문장 안에서 서체가 갈린다.

   **`unicode-range` 로 자르지 않는다.** 폴백 체인에 그냥 두면 브라우저가 글리프
   단위로 넘긴다 - 범위를 손으로 적으면 2,345자 중 적지 않은 것을 빠뜨린다.
   파일도 필요할 때만 받는다: 한국어만 있는 화면에서 Pretendard 는 `unloaded` 로
   남는다(실측). 가나가 한 자라도 나타나는 순간에만 내려온다.

   섞여도 축이 맞는다 - 둘 다 `upm 2048` · **`cap-height 1448` 로 같다.**
   (x-height 는 1032 vs 1086 으로 다르다 - 가나는 본문 안에서만 나오므로 감수한다.)

   `url()` 을 **상대 경로**로 둔다. 두 경로가 다 살아야 한다:
     · SPA  — Vite 가 `ui/app.css` 기준으로 해석해 `dist/assets/` 로 emit 한다
     · SSR  — Caddy 가 `/srv/autobot-ui` 를 `file_server` 로 내보내 `/fonts/…` 가 된다

   **무게는 400/500/700 세 종이다.** SEED v2 가 `--seed-font-weight-medium`(500)을
   recipe 60개·135곳에서 쓴다(실측). 500 을 안 실으면 CSS 폰트 매칭이 400 으로
   내려가서 SEED 컴포넌트의 위계가 통째로 사라진다 - v1(400/700 두 단계)에서
   올라오며 생긴 차이다.

   둘 다 SIL Open Font License 1.1 - self-host 가 허용된다.

   `font-display: swap` — 폰트를 기다리며 글자를 숨기지 않는다. */
@font-face{ font-family:'Wanted Sans'; font-weight:400; font-style:normal;
  font-display:swap; src:url('fonts/WantedSans-Regular.woff2') format('woff2'); }
@font-face{ font-family:'Wanted Sans'; font-weight:500; font-style:normal;
  font-display:swap; src:url('fonts/WantedSans-Medium.woff2') format('woff2'); }
@font-face{ font-family:'Wanted Sans'; font-weight:700; font-style:normal;
  font-display:swap; src:url('fonts/WantedSans-Bold.woff2') format('woff2'); }
@font-face{ font-family:'Pretendard'; font-weight:400; font-style:normal;
  font-display:swap; src:url('fonts/Pretendard-Regular.woff2') format('woff2'); }
@font-face{ font-family:'Pretendard'; font-weight:500; font-style:normal;
  font-display:swap; src:url('fonts/Pretendard-Medium.woff2') format('woff2'); }
@font-face{ font-family:'Pretendard'; font-weight:700; font-style:normal;
  font-display:swap; src:url('fonts/Pretendard-Bold.woff2') format('woff2'); }

:root{
  --gutter: 16px;
  /* SEED v2 는 `font-family` 토큰을 정의하지 않는다 — recipe 는 `inherit` 을 쓴다.
     즉 서체는 **우리 소유**다. 그래서 `--ui-` 접두사로 못박는다: v2 가 나중에
     같은 이름을 들고 오면 어느 쪽이 이기는지 알 수 없어진다.

     순서가 곧 폴백 규칙이다. Wanted Sans 가 없는 글자(가나·전각·그리스 2,345자)를
     Pretendard 가 받고, 둘 다 없는 것(한자 등)은 시스템 폰트가 받는다. */
  --ui-font-family: 'Wanted Sans', 'Pretendard', -apple-system, BlinkMacSystemFont, sans-serif;

  /* ---- 잉크 단계 : v2 가 우리 손땜을 공식화했다 ----

     v1 은 잉크가 2단계뿐이라(16.06:1 / 3.42:1) AA 를 넘는 중간이 없었고, 그래서
     `--ui-ink-2`(gray-700)를 손으로 만들어 39곳에 발랐다. **v2 는 5단계를 준다:**

       fg-neutral          #1a1c20  17.06:1   본문
       fg-neutral-muted    #555d6d   6.62:1   **보조 텍스트 - 우리 --ui-ink-2 의 후계**
       fg-neutral-subtle   #868b94   3.42:1   미달 - 쓰지 않는다
       fg-placeholder      #b0b3ba   2.10:1   플레이스홀더 전용
       fg-disabled         #d1d3d8   1.50:1   비활성 전용

     **이름에 속으면 안 된다** - `subtle` 이 의미상 "보조" 로 읽히지만 3.42:1 로
     v1 의 결함값과 같은 색(#868b94)이다. 보조 텍스트는 반드시 `muted` 다.
     `subtle`·`placeholder`·`disabled` 는 WCAG 가 대비를 면제하는 자리에만 쓴다.

     그래서 이 블록에 잉크 토큰 정의가 없다 - 공식 토큰을 직접 참조한다. */

  /* ---- 컨트롤 높이 래더 ----

     **우리가 만든 토큰이다.** v2 는 컴포넌트가 자기 높이를 갖고 오므로 이 래더는
     SEED 에 대응이 없는 것(표·시간대 격자·툴바 정렬)에만 쓴다.

     이 다섯 값 밖의 높이를 쓰지 않는다. 한 줄에 두 높이가 섞이면 밑변이 어긋나고,
     그게 2026-08-20 에 사용자가 지적한 "틀어지는 게 많다" 의 원인이었다. */
  --seed-control-height-xsmall: 32px;
  --seed-control-height-small: 36px;
  --seed-control-height-medium: 40px;
  --seed-control-height-large: 48px;
  --seed-control-height-xlarge: 52px;
}
@media (min-width: 1024px){ :root{ --gutter: 24px; } }

*{ box-sizing: border-box; }
html,body{ margin:0; padding:0; }
body{
  font-family: var(--ui-font-family);
  background: var(--seed-color-bg-layer-basement, #f7f8fa);
  color: var(--seed-color-fg-neutral);
  -webkit-font-smoothing: antialiased;
}
a{ color: inherit; text-decoration: none; }
button{ font-family: inherit; }

/* ---------- 2026-08-21 죽은 규칙 정리 (81벌) ----------

   SEED 컴포넌트로 옮긴 뒤 **마크업이 사라졌는데 규칙만 남아 있던 것**을 지웠다.
   판정은 눈이 아니라 대조다: `ui/app.css` 의 규칙 251벌에서 클래스를 뽑고,
   `web/src/**`·`web/seed-design/**`·SSR 템플릿·`ui/*.html`·`web/*.py` 의 문자열
   전부와 맞춰 **한 번도 나오지 않는 것만** 지웠다. 동적 조립(`hcell hcell--${st}`,
   `navClass()` 의 반환 문자열)까지 세었다 — `className=` 속성만 보면 그것들을
   죽었다고 오판한다.

   지운 묶음: 드롭존 `.drop`(8) · 토글 `.switch`(7) · 도움말 `.hb`(13) ·
   계정 탭 `.acctab`(6) · 설정 행 `.row`(6) · 더보기 `.mlist`(5) · 계정 건전성 표
   `.tbl--health`(10) · 모바일 CTA·초안 네비(4) · 스파크라인 `.spark`(4) ·
   타임라인 모바일 요약(5) · 낱개 유틸리티(`.ic-16` `.warn` `.progress`
   `.progress__bar` `.metarow` `.datenav__d` `.pick__x` `.copybox`
   `.meta--foot` `.cellhide`).

   `.mobonly` 는 **되살렸다** — 모바일 메뉴 버튼이 그 자리를 다시 쓴다.

   **되살리지 말고 컴포넌트를 써라.** 지운 자리마다 대응 컴포넌트를 주석에 적었다. */

/* ---------- 아이콘 ---------- */
.ic{ width:20px; height:20px; display:inline-block; flex:0 0 auto;
     background-color: currentColor; -webkit-mask-size: contain; mask-size: contain;
     -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
     -webkit-mask-position:center; mask-position:center; }
.ic-24{ width:24px; height:24px; }

/* ---------- 셸 ----------

   사이드바는 SEED `SideNavigation` 이 그린다(`web/src/components/Shell.tsx`).
   여기 있던 `.sidebar`·`.navgroup__label`·`.navitem`(+hover/on) 6벌을 지웠다.
   **접힘이 CSS 트릭에서 상태로 바뀐 것이 핵심이다** — 전에는 `@media` 가 라벨을
   `display:none` 으로 숨겼고, 그래서 넓은 화면에서 사람이 접을 수 없었고 접힌
   상태에서 무슨 메뉴인지 알 수 없었다. SEED 는 240px/56px 두 폭과 `data-` 상태를
   갖고 오고, 접혔을 때 라벨을 툴팁으로 되돌린다.

   **스크롤 주인이 바뀌었다.** 전에는 창이 스크롤하고 사이드바가 `sticky` 였다.
   지금은 셸이 뷰포트 높이에 고정되고 `SideNavigationInset`(본문)이 스크롤한다 —
   recipe 가 `overflow-y:auto` 를 갖고 있어서 그렇게 두지 않으면 높이 제약이 없는
   스크롤 컨테이너가 되고, 그 안의 `sticky` 상단바가 **영원히 붙지 않는다**
   (스크롤이 창에서 일어나므로 Inset 의 스크롤포트는 움직이지 않는다). */
.shell{ display:flex; height:100vh; overflow:hidden; }

/* 브랜드 줄은 `SideNavigationHeader`(min-height 64px, padding 8px) 안에 산다.
   접히면 이름을 빼고 마크만 남긴다 — 56px 안에서 이름은 잘린다. */
.brand{ display:flex; align-items:center; gap:8px; padding:0 4px; height:100%; }
.brand__mark{ width:22px; height:22px; flex:0 0 auto; border-radius:var(--seed-radius-r2);
  background: var(--seed-color-bg-brand-solid); }
/* 트래킹을 손으로 주지 않는다. SEED 는 38개 시맨틱 스타일 **전부**
   `letter-spacing: 0` 이다(`ui/seed.css` 실측 - narrow 토큰은 정의만 있고 어떤
   스타일도 쓰지 않는다). Pretendard 는 0 에서 맞게 설계된 폰트라 음수 트래킹을
   주면 오히려 자모가 붙는다. 이 화면들의 -0.01~-0.03em 은 전 폰트(에스코어드림)
   시절의 습관이었다. */
.brand__name{ font-weight:700; font-size:15px; white-space:nowrap; }
/* 접기 버튼은 펼친 상태에서 오른쪽 끝, **접힌 상태에서는 유일하게 남는 것**이다.
   처음엔 접히면 감췄는데 그러면 1280px 아래에서 사람이 펼칠 방법이 없다 — SEED 가
   그 폭에서 자동으로 접기 때문에 영구히 접힌 상태가 된다(실측: 1100px 에서 버튼
   `display:none`). 56px 안에 마크와 버튼을 나란히 두면 둘 다 잘리므로, 접히면
   브랜드 마크를 내리고 버튼만 가운데 남긴다. */
.brand__fold{ margin-left:auto; }
.seed-side-navigation__root[data-side-navigation-state=collapsed] .brand__name,
.seed-side-navigation__root[data-side-navigation-state=collapsed] .brand__mark{ display:none; }
.seed-side-navigation__root[data-side-navigation-state=collapsed] .brand__fold{ margin:0 auto; }
.topbar{
  height:56px; display:flex; align-items:center; gap:12px;
  padding: 0 var(--gutter);
  background: var(--seed-color-bg-layer-default);
  border-bottom: 1px solid var(--seed-color-stroke-neutral-weak);
  position:sticky; top:0; z-index:5;
}
.topbar__title{ font-size:16px; font-weight:700; }
.topbar__sub{ font-size:13px; color: var(--seed-color-fg-neutral-muted); }
.topbar__right{ margin-left:auto; display:flex; align-items:center; gap:8px; }
.page{ padding: var(--gutter); max-width: 1180px; }

/* ---------- 카드 : 틴트 또는 테두리, 둘 다 금지. 그림자 없음 ---------- */
.card{
  background: var(--seed-color-bg-layer-default);
  border: 1px solid var(--seed-color-stroke-neutral-weak);
  border-radius: var(--seed-radius-r3);
  padding: 16px;
}
.card--tint{ background: var(--seed-color-palette-gray-200); border: none; }
.card__head{ display:flex; align-items:baseline; gap:8px; margin-bottom:12px; }
.card__title{ font-size:13px; font-weight:700; color: var(--seed-color-fg-neutral-muted); }
.card__more{ margin-left:auto; font-size:12px; color: var(--seed-color-palette-carrot-800); font-weight:700; }

/* 12칸 격자는 **SEED `Grid` 로 안 간다** (2026-08-21 판정).

   `Grid` 는 컨테이너 축만 반응형이다: `columns` 는 `ResponsiveValue` 지만
   `GridItem` 의 `colSpan` 은 아니다 — 구현이 `gridColumn` 을 단일 CSS 변수
   (`--seed-box-grid-column`)로 내리고, `base.css` 에 그 변수의 브레이크포인트
   4단(`-sm`/`-md`/`-lg`/`-xl`)이 **없다**(실측). 즉 `span 8 -> span 12` 같은
   항목별 반응형 폭을 표현할 방법이 없고, 그게 이 격자가 존재하는 이유다.
   `columns={{base:1, md:12}}` 로 우회하면 모바일에서 `colSpan=8` 이 암시적 열
   7개를 만들어 레이아웃이 깨진다.

   그래서 3줄을 남긴다. DatePicker 와 같은 종류의 판정이다 — SEED 에 대응이
   없어서 남기는 것이고, 트리거가 생기면 그때 간다. */
.grid{ display:grid; gap:12px; grid-template-columns: repeat(12, 1fr); }
.col-3{ grid-column: span 3; } .col-4{ grid-column: span 4; }
.col-6{ grid-column: span 6; } .col-8{ grid-column: span 8; } .col-12{ grid-column: span 12; }

/* ---------- 수치 ---------- */
.stat{ display:flex; flex-direction:column; gap:2px; }
/* `font-variant-numeric` 선언은 이 파일에 원래부터 11곳 있었다. **에스코어드림에는
   `tnum` 이 없어서 전부 무효였다** - Pretendard 로 바꾼 지금 처음 동작한다. */
.stat__v{ font-size:26px; font-weight:700; line-height:1.2;
  font-variant-numeric: tabular-nums; }
.stat__u{ font-size:13px; font-weight:400; color: var(--seed-color-fg-neutral-muted); }
.stat__l{ font-size:12px; color: var(--seed-color-fg-neutral-muted); }
.num{ font-variant-numeric: tabular-nums; }

/* 배지는 SEED `Badge` 가 그린다 (`@seed-design/react`).
   여기 있던 `.badge` + 변형 5종(13줄)을 지웠다 — 대비를 팔레트에서 손으로 골라
   맞추던 자리다.

   교체 대응:
     `.badge--a`(BEST)  -> `tone="brand"`
     `.badge--b`(발행)   -> `tone="informative"`
     `.badge--c`         -> `tone="neutral"`
     `.badge--d`(흐림)   -> `tone="neutral" variant="outline"`
     `.badge--acct`      -> `tone="neutral"`

   **`.bad` 로 글자만 빨갛게 칠하던 손땜이 사라졌다.** SEED 는 색을 안쪽
   `.seed-badge__label` 에 주므로 root 에 붙는 클래스가 닿지 않는다. 실패는
   `tone="critical"` 로 올렸다(`format.ts::statusTone`). */

/* 콜아웃은 SEED `Callout` 이 그린다 (`seed-design/ui/callout.tsx`).
   여기 있던 `.callout` 3종 + `__t`/`__d`(12줄)을 지웠다 — 대비를 손으로 맞추던
   자리이고, `tone="neutral|informative|positive|warning|critical|magic"` 이
   그 판단을 공식 팔레트로 대신한다. `description` 이 **필수 prop** 이라 제목만
   띄우는 콜아웃을 만들 수 없다. */

/* ---------- 표 ---------- */
.tbl{ width:100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.tbl th{ text-align:left; font-size:12px; font-weight:700;
  color: var(--seed-color-fg-neutral-muted); padding:8px 10px;
  border-bottom:1px solid var(--seed-color-stroke-neutral-weak); white-space:nowrap; }
.tbl td{ font-size:13px; padding:10px; border-bottom:1px solid var(--seed-color-stroke-neutral-subtle); }
.tbl tr:hover td{ background: var(--seed-color-bg-neutral-weak-alpha); }
/* 오른쪽 정렬 칸은 **줄바꿈하지 않는다.** 헤더(`th`)에는 `nowrap` 이 있었는데
   본문에는 없어서, 열이 좁아지면 값이 글자 중간에서 접혔다 — 운영 화면 실측에서
   `21시간` 이 `21시` / `간` 으로 갈렸다(2026-08-21, `/app/timeline` 1024px).
   숫자·기간은 한 덩어리로 읽어야 하는 값이다. 넘치면 `.tblwrap` 이 가로로 민다. */
.tbl .r{ text-align:right; white-space:nowrap; }

/* 값 하나를 경고색으로. **`.r` 과 다른 축이다** — `.r` 은 표 안 우측 정렬이고
   이건 색이다. 2026-08-14 신설: 회전 소진(8회전)·하드 탈락 축·상한 초과처럼
   "이 숫자가 문제다" 를 한 글자도 안 읽고 알아채게 하는 자리에만 쓴다.
   전부 칠하면 아무것도 눈에 안 띈다. */
.bad{ color: var(--seed-color-fg-critical); }
.tbl__hook{ max-width:1px; width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* 버튼은 SEED `ActionButton` 이 그린다 (`seed-design/ui/action-button.tsx`).
   여기 있던 `.btn` + 변형 6종 + hover/press/disabled(40줄)을 지웠다.

   교체 대응:
     `.btn--primary`   -> `variant="brandSolid"`
     `.btn--secondary` -> `variant="neutralWeak"`
     `.btn--ghost`     -> `variant="ghost"`
     `.btn--sm`(32)    -> `size="xsmall"`
     `.btn`(36)        -> `size="small"` (기본은 `medium`=40)
     `.btn--full`(48)  -> `size="large"`(52) + `Box width="100%"`

   공짜로 얻은 것 — `loading` prop 이 스피너를 붙인다(전에는 레이블만 '…중' 으로
   바꿔서 누른 게 먹었는지 안 보였다), `asChild` 가 `<a>` 를 감싸므로
   `a:hover` 가 버튼 색을 덮는 사고(주황 배경에 주황 글자)가 구조적으로 없다,
   그리고 `@media (hover:hover)`·press 지연·`:disabled` 재도색을 우리가 안 짠다. */

.kbd{ display:inline-flex; align-items:center; height:18px; padding:0 5px;
  border-radius: var(--seed-radius-r1); background: var(--seed-color-palette-gray-300);
  font-size:11px; color: var(--seed-color-palette-gray-800); font-weight:700; }

/* ---------- 목록 행 ---------- */
.lrow{ padding:12px 14px; border-bottom:1px solid var(--seed-color-stroke-neutral-subtle); cursor:pointer; }
.lrow:hover{ background: var(--seed-color-bg-neutral-weak-alpha); }
.lrow--on{ background: var(--seed-color-palette-carrot-100); box-shadow: inset 3px 0 0 var(--seed-color-bg-brand-solid); }
.lrow__top{ display:flex; align-items:center; gap:6px; margin-bottom:4px; }
.lrow__hook{ font-size:13px; line-height:1.45; overflow:hidden; display:-webkit-box;
  -webkit-line-clamp:2; -webkit-box-orient:vertical; }

.post{ white-space:pre-wrap; font-size:15px; line-height:1.62;
  padding:16px; border-radius: var(--seed-radius-r3);
  background: var(--seed-color-palette-gray-200); }
.post--src{ background: transparent; border:1px solid var(--seed-color-stroke-neutral-weak); }
.meta{ font-size:12px; color: var(--seed-color-fg-neutral-muted); }
.meta b{ color: var(--seed-color-fg-neutral); font-size:13px; }

/* SEED `Divider` 는 **지금 들일 자리가 없다** (2026-08-21 판정). 남은 구분선은
   전부 `border` 다 — 표 셀(`.tbl td`) · 목록 행(`.lrow`) · 카드 경계 · 접이식 위의
   실선(아래 `details.fold`). 그건 요소가 아니라 **경계**라서 `<hr>` 로 바꾸면 DOM
   노드만 늘고 색은 SEED 의 `stroke.neutralMuted` 로 미묘하게 달라진다(우리는
   `stroke-neutral-weak`). 독립 구분선을 실제로 그리는 자리가 생기면 그때 쓴다 —
   `/app/settings`(자동발행 Phase 0) 의 구역 나누기가 첫 후보다. */
details.fold{ border-top:1px solid var(--seed-color-stroke-neutral-weak); padding-top:12px; margin-top:12px; }
details.fold > summary{ cursor:pointer; font-size:13px; font-weight:700;
  color: var(--seed-color-fg-neutral-muted); list-style:none; display:flex; align-items:center; gap:6px; }
details.fold > summary::-webkit-details-marker{ display:none; }

/* ---------- 날짜 네비 ---------- */
.datenav{ display:flex; align-items:center; gap:10px; }
/* 아이콘 버튼도 래더를 따른다. **리터럴 px 을 쓰지 않는다** — 툴바에서 32 로
   남아 있어 40px 필드와 밑변이 어긋났다. 기본은 `small`(36)이고 툴바처럼 필드와
   나란히 서는 자리는 `medium`(40)으로 올린다. */
.iconbtn{ width: var(--seed-control-height-small); height: var(--seed-control-height-small);
  border-radius:var(--seed-radius-r2); border:none;
  background:transparent; color: var(--seed-color-fg-neutral-muted);
  display:flex; align-items:center; justify-content:center; cursor:pointer; }
.iconbtn:hover{ background: var(--seed-color-bg-neutral-weak-alpha); }

/* 칩은 SEED `Chip`(선택 가능한 필터)과 `Badge`(누를 수 없는 라벨)로 갈렸다 —
   여기 있던 `.chips`/`.chip`/`.chip--on`(10줄)을 지웠다.

   **하나였던 것을 둘로 나눈 게 핵심이다.** 전에는 `<button className="chip">`(인기글
   필터)과 `<span className="chip">`(분석 욕구 라벨)이 같은 클래스를 썼다. 생김새가
   같으니 라벨도 눌러 보게 만든다. SEED 는 컨트롤(`Chip` = button)과 표기(`Badge`
   = span)를 다른 컴포넌트로 갈라 놓아서 그 거짓말이 구조적으로 불가능하다. */

/* 스파크라인(`.spark` + `.floor`/`.ceil`)을 지웠다 — `<svg>` 폴리라인 2벌을 쓰는
   화면이 없어졌다. 지금 막대 차트는 `.bars`(아래 발행 모니터링)가 그린다. */

/* ---------- 모바일 ---------- */
.mobilebar{ display:none; }
/* 모바일에서만 보이는 것(`.desktoponly` 의 반대). 지금 쓰는 곳은 상단바의 메뉴
   버튼 하나다 — 데스크톱에서는 사이드바가 같은 링크를 이미 갖고 있다. */
.mobonly{ display:none; }

/* 좁은 화면(<1024px)의 접기는 **CSS 가 아니라 상태**다 — `Shell.tsx` 의
   `useNarrowCollapse` 가 `matchMedia` 로 경계를 듣고 `collapsed` 를 넘긴다.
   여기서 라벨을 숨기던 규칙 4벌을 지웠다: CSS 로 숨기면 사람이 펼칠 수 없고
   툴팁도 붙지 않는다. */

@media (max-width: 767px){
  /* 사이드바 자체를 내린다. 56px 접힌 사이드바를 함께 두면 240px 드로우어와
     둘이 같은 일을 한다. 이 폭의 길잡이는 **둘**이다:
       · 하단 탭바(`.mobilebar`) — 자주 가는 4개, 엄지 자리
       · 상단 메뉴 버튼 → SEED `SidePanel` 드로우어 — 전체 6개
     탭바만 두면 시간대·동기화가 **모바일에서 닿을 수 없다**(2026-08-21 지적).

     `.shell >` 로 두 가지를 동시에 해결한다:
       1. **특이도** — recipe 가 `app.css` 뒤에 실려서 클래스 1개로는 `display:flex`
          를 못 덮는다(첫 시도에서 375px 에 56px 사이드바가 그대로 남아 있었다).
       2. **범위** — 드로우어 안의 `SideNavigation` 은 `.shell` 밖(포털)에 있어야
          살아남는다. 자식 선택자가 그 경계를 그대로 표현한다. */
  .shell > .seed-side-navigation__root{ display:none; }
  .mobonly{ display:flex; }
  .page{ padding: 12px 16px 84px; }
  .col-4,.col-6,.col-8{ grid-column: span 12; }
  .col-3{ grid-column: span 6; }            /* 요약 지표는 2 x 2 */
  .grid{ gap:8px; }
  .topbar{ height:52px; }
  .desktoponly{ display:none !important; }

  .mobilebar{
    display:flex; position:fixed; left:0; right:0; bottom:0; z-index:20;
    height:56px; padding-bottom: env(safe-area-inset-bottom);
    background: var(--seed-color-bg-layer-default);
    border-top:1px solid var(--seed-color-stroke-neutral-weak);
  }
  .mtab{ flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
    color: var(--seed-color-fg-neutral-muted); font-size:10px; position:relative; }
  .mtab--on{ color: var(--seed-color-palette-carrot-800); font-weight:700; }

  /* 아래 3벌을 지웠다 — 쓰는 화면이 사라졌다: 하단 고정 CTA(`.stickycta`/`.page--cta`) ·
     모바일 초안 네비(`.mnav`) · 계정 건전성 표를 카드로 바꾸던 규칙 9벌(`.tbl--health`).
     계정 건전성 화면 자체가 없다. */

  /* 타임라인을 카드 리스트로. **375px 실측이 근거다**: 표를 그대로 세우면 라벨 없는
     칸 10개가 쌓여 한 행이 186px 이고, `thead` 를 숨기므로 뒤 4칸(`–`)이 무슨 값인지
     알 수 없었다. 그래서 모바일에서는 표를 세우는 대신 **무엇을 보여줄지 고른다**:
     시각·상태·계정 / 훅 / 지표 3줄(`Timeline.tsx`). 나머지 칸은 내린다. */
  .tbl--timeline thead{ display:none; }
  .tbl--timeline, .tbl--timeline tbody, .tbl--timeline tr, .tbl--timeline td{ display:block; width:100%; }
  .tbl--timeline tr{ border:1px solid var(--seed-color-stroke-neutral-weak);
    border-radius: var(--seed-radius-r3); padding:12px; margin-bottom:8px; }
  .tbl--timeline td{ border:none; padding:0; }
  /* 가로 스크롤을 끈다 — 카드 리스트는 폭을 넘지 않는다. `.tblwrap` 의 620px
     하한이 남아 있으면 카드가 화면 밖으로 나가 스와이프가 생긴다(실측 620 vs 375). */
  .tblwrap:has(.tbl--timeline) .tbl{ min-width:0; }
  .tbl--timeline .m-top{ display:flex; align-items:center; gap:6px; flex-wrap:wrap;
    margin-bottom:6px; font-size:12px; color: var(--seed-color-fg-neutral-muted); }
  .tbl--timeline .m-hook{ font-size:14px; line-height:1.5; margin-bottom:8px; }
  .tbl--timeline .m-bottom{ display:flex; align-items:center; gap:14px; flex-wrap:wrap;
    font-size:12px; color: var(--seed-color-fg-neutral-muted); }
  .tbl--timeline .m-bottom b{ color: var(--seed-color-fg-neutral); }
  .tbl--timeline .cellhide{ display:none; }
}

/* 데스크톱에서는 모바일 요약 3줄을 내린다. 같은 `<tr>` 안에 두 벌이 있으므로
   한쪽은 항상 `display:none` 이어야 한다 — 숨긴 칸은 접근성 트리에서도 빠지므로
   헤더 10칸과 보이는 칸 10칸의 대응이 어긋나지 않는다. */
@media (min-width: 768px){
  .tbl--timeline .m-top, .tbl--timeline .m-hook, .tbl--timeline .m-bottom{ display:none; }
}

/* 계정 탭(`.acctabs`/`.acctab`/`.acctab--on` 4벌 + 모바일 `small` 숨김)을 지웠다 —
   계정 고르기는 SEED `Select` 가 한다(발행 모니터링·예약·인기글 툴바 3곳). 세그먼트
   트랙(42px)은 옆 필드(40px)와 같은 무게로 읽혀 필터의 보조 위계를 깨뜨렸다. */

/* 모달은 SEED `Dialog`(ContentDialog) 가 그린다 (`seed-design/ui/dialog.tsx`).
   여기 있던 `.scrim`/`.modal` + `__head`/`__t`/`__body`/`__foot` + 애니메이션
   2벌(14줄)을 지웠다.

   손땜이던 이유 — `<dialog open>` 은 정적 속성이라 `showModal()` 이 아니고,
   그래서 **포커스 트랩이 없었다.** `Esc` 처리·바깥 클릭 닫기·모바일 바텀시트
   전환을 우리가 하나씩 짰다. SEED 는 그 셋을 다 갖고 온다(포커스가 실제로 안으로
   들어가는 것을 실측했다).

   `.kv`(4칸 수치 격자)는 SEED 에 대응이 없어 남긴다. */

.kv{ display:grid; grid-template-columns: repeat(4,1fr); gap:10px; margin:14px 0; }
.kv > div{ background: var(--seed-color-palette-gray-200); border-radius: var(--seed-radius-r2); padding:10px 12px; }
.kv .k{ font-size:11px; color: var(--seed-color-fg-neutral-muted); }
.kv .v{ font-size:16px; font-weight:700; font-variant-numeric: tabular-nums; margin-top:2px; }

.tbl--timeline tr{ cursor:pointer; }

@media (max-width:767px){
  .kv{ grid-template-columns: repeat(2,1fr); }
}

/* 도움말 말풍선(`.hb` 계열 11벌 + `::after` 화살표 2벌)을 지웠다 — 손으로 만든
   툴팁이었고 쓰는 자리가 없어졌다(설명은 `Callout` 과 `TextField` 의 `description`
   으로 옮겨졌다). 다시 필요하면 `web/seed-design/ui/help-bubble-tooltip.tsx` 가
   있다 — 포커스·포지셔닝·모바일 전환을 컴포넌트가 갖고 온다. */

/* ---------- 미디어 ---------- */
.mediastrip{ display:flex; gap:6px; overflow-x:auto; padding-bottom:4px; margin:10px 0 0; }
.mediastrip img{ height:120px; width:auto; border-radius: var(--seed-radius-r2);
  object-fit:cover; flex:0 0 auto; background: var(--seed-color-palette-gray-200); }
.mediastrip--lg img{ height:190px; }
.medialabel{ display:flex; align-items:center; gap:6px; font-size:12px;
  color: var(--seed-color-fg-neutral-muted); margin-top:10px; }
.medialabel .seed-badge__root{ margin-right:2px; }
/* ---------- 원문 읽기 보조 (2026-08-14) ---------- */
/* 지표 줄. 본문이 주인공이라 지표는 아래에 작게 눕힌다. */
.facts{ display:flex; flex-wrap:wrap; gap:4px 12px; margin-top:12px; font-size:12px;
  color: var(--seed-color-fg-neutral-muted); font-variant-numeric: tabular-nums; }
.facts b{ color: var(--seed-color-fg-neutral); font-weight:700; }
/* 원문에 딸린 짧은 글 한 칸(타래·초안). 본문 바로 아래 붙여 나란히 읽게 한다. */
.rework{ margin-top:12px; padding:12px 14px; border-radius: var(--seed-radius-r2);
  background: var(--seed-color-palette-gray-200); }
.rework__top{ display:flex; align-items:center; gap:6px; margin-bottom:6px; }
.rework__body{ white-space:pre-wrap; font-size:13px; line-height:1.62; }

/* ---------- 사진 업로드 (2026-08-14) ---------- */
/* 드롭존(`.drop` 계열 8벌)을 지웠다 — SEED `AttachmentField` 가 드래그 앤 드롭·
   파일 대화상자·검증·진행률을 갖고 온다(`web/src/components/PhotoField.tsx`).

   여기 남은 것은 **SEED 에 대응이 없는 두 가지**다: 고른 사진의 비율 경고(거부가
   아니라 "피드에서 잘릴 수 있다" 는 도메인 판정)와 최근 업로드 재사용 스트립
   (서버에 이미 있는 사진이라 `File` 객체가 없다). */

/* 고른 사진. 썸네일 + 정보 + 제거 버튼을 한 줄에. */
.pick{ display:flex; align-items:center; gap:12px; text-align:left; }
.pick img{ width:72px; height:90px; border-radius: var(--seed-radius-r2); object-fit:cover;
  flex:0 0 auto; background: var(--seed-color-palette-gray-200); }
.pick__body{ min-width:0; flex:1; }
.pick__n{ font-size:13px; font-weight:700; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }
.pick__m{ font-size:12px; color: var(--seed-color-fg-neutral-muted); margin-top:2px; }
/* 비율이 권장(4:5)에서 멀면 알린다. 잘려 나가는 것은 발행 후에 보인다. */
.pick__m .bad{ font-weight:700; }

/* 최근 업로드에서 고르기. 다시 올리지 않아도 되게 한다. */
/* `margin-top` 을 뺐다 — 부모 `.field` 의 `gap:6px` 과 겹쳐 이 자리만 14px 이었다. */
.reuse{ display:flex; gap:6px; overflow-x:auto; padding:2px 0 6px; }
.reuse button{ flex:0 0 auto; padding:0; border:2px solid transparent; background:none;
  border-radius: var(--seed-radius-r2); cursor:pointer; line-height:0; }
.reuse button:hover{ border-color: var(--seed-color-stroke-neutral-weak); }
.reuse button[aria-pressed=true]{ border-color: var(--seed-color-bg-brand-solid); }
.reuse img{ width:52px; height:65px; border-radius: var(--seed-radius-r2); object-fit:cover;
  background: var(--seed-color-palette-gray-200); }

.lrow__thumb{ width:38px; height:38px; border-radius: var(--seed-radius-r2); object-fit:cover;
  flex:0 0 auto; background: var(--seed-color-palette-gray-200); }
.lrow__body{ display:flex; gap:8px; }
.lrow__body > div{ min-width:0; flex:1; }
@media (max-width:767px){ .mediastrip--lg img{ height:150px; } }

/* ---------- 툴바 · 필터 ---------- */
.toolbar{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; margin-bottom:12px; }
.toolbar__sp{ margin-left:auto; }
.frow{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
/* 라벨+입력이 섞인 줄은 **위로 정렬한다.**

   `align-items:center` 는 각 필드를 **자기 높이 기준으로** 가운데 놓는다. 설명이
   붙은 필드(109px)와 없는 필드(82px)를 한 줄에 두면 라벨이 14px 어긋난다
   (2026-08-21 설정 화면 실측: 라벨 top 138 vs 124). 사람이 "틀어졌다" 고 말한
   그것이다.

   가운데 정렬이 맞는 자리도 있다 — 배지 줄, 그리고 예약 화면의 댓글 줄(높은
   textarea 옆의 삭제 버튼)이다. 그래서 `.frow` 를 바꾸지 않고 변형을 만든다.
   `gap` 도 키운다: 필드끼리는 6px 이 너무 좁아 라벨이 옆 입력에 붙어 읽힌다. */
.frow--top{ align-items: flex-start; gap: 10px 14px; }

/* ---------- 넓은 표는 가로 스크롤 ---------- */
.tblwrap{ overflow-x:auto; }
@media (max-width:767px){ .tblwrap .tbl{ min-width:620px; } }

/* ---------- 폼 ----------

   **여기 남은 것은 SEED 에 대응이 없거나 아직 옮기지 못한 자리뿐이다.**
   `.textarea`·`.input--sm`·`.input--n` 은 SEED `TextField` 로 갔다(삭제).

   `.field`/`.field__l`/`.field__h` 는 아직 산다 — 발행 시각·사진·타래 껍데기와
   파일 입력 라벨이 쓴다. `TextField` 로 옮길 수 있는 자리가 남았다는 뜻이다.

   `.input` 도 아직 산다 — 날짜·시각·파일 입력 3종이다. 날짜·시각은 **일부러
   남겼다**: SEED `DatePicker` 는 늘 펼쳐진 달력 그리드이고 `TimePicker` 는
   12시간제 휠이라, 168px+128px 두 칸을 그걸로 바꾸면 폼 절반이 덮이고 OS 피커와
   키보드 타이핑이 사라진다. 트리거+팝오버 형태가 들어오면 그때 간다.
   파일 입력은 `AttachmentInput` 이 사진 전제(썸네일·배지 슬롯)라 CSV/MD 에 맞지 않다. */
.field{ display:flex; flex-direction:column; gap:6px; margin-bottom:14px; }
.field__l{ font-size:12px; font-weight:700; color: var(--seed-color-fg-neutral-muted); }
.field__h{ font-size:12px; color: var(--seed-color-fg-neutral-muted); }
.input{ width:100%; height: var(--seed-control-height-medium);
  padding:0 12px; font-family:inherit; font-size:14px;
  color: var(--seed-color-fg-neutral);
  background-color: var(--seed-color-bg-layer-default);
  border:1px solid var(--seed-color-stroke-neutral-weak); border-radius: var(--seed-radius-r2); }
.input:focus-visible{ outline:2px solid var(--seed-color-stroke-focus-ring);
  outline-offset:0; border-color:transparent; }

/* 여기 있던 `.select` 손땜(`appearance:none` + SEED 경로를 구운 data URI 셰브런
   2벌, 26줄)을 **지웠다.** SEED `Select` 컴포넌트가 대신한다
   (`seed-design/ui/select.tsx`) — 진짜 드롭다운이라 키보드 이동·그룹·다중 선택·
   플로팅 위치까지 따라온다. `<select>` 는 그중 아무것도 못 한다.

   남은 `.select` 참조는 없다. 마크업 3곳(`Timeline`·`Trend`·`Reserve`)이 전부
   `SelectRoot` 로 갔다. */

/* ---------- 날짜 입력의 네이티브 아이콘 ----------

   `<input type="date">` 의 달력 버튼도 UA 가 그린다 — 셀렉트와 **나란히 서는 줄**
   에서 하나는 SEED 셰브런, 하나는 네이티브 사각형이면 그게 눈에 걸린다.

   달력 버튼 자체는 대체할 수 없다(네이티브 피커를 여는 유일한 손잡이다). 대신
   크기·여백을 셀렉트와 맞추고 색을 `--seed-color-fg-neutral-muted` 로 끌어온다. `filter` 를 쓰는
   이유는 이 가짜 요소의 글리프에 `color` 가 닿지 않기 때문이다 -
   검정 글리프를 회색으로 낮춘다(#4d5159 는 검정의 약 30% 밝기다). */
.input[type="date"]{ padding-right:8px; }
.input[type="date"]::-webkit-calendar-picker-indicator{
  width:16px; height:16px; padding:0; margin:0 4px 0 0; cursor:pointer;
  opacity:1; filter: invert(28%) sepia(8%) saturate(560%) hue-rotate(178deg) brightness(96%);
}
.input[type="date"]::-webkit-calendar-picker-indicator:hover{
  filter: invert(10%) sepia(6%) saturate(700%) hue-rotate(185deg) brightness(95%);
}
/* 비활성 잉크. WCAG 는 비활성 컨트롤의 대비를 면제하고, 여기서는 흐린 것이
   **의미**다("지금 만질 수 없다"). */
.input:disabled{ background-color: var(--seed-color-palette-gray-200);
  color: var(--seed-color-fg-placeholder); }

/* 설정 행(`.row` 계열 6벌)을 지웠다 — 쓰는 화면이 없다. `/app/settings` 를 만들 때는
   SEED `Switch` + `Callout` 로 짠다(`.switch` 손땜 7벌도 같이 지웠다). */

/* ---------- 이름 · 값 두 칸 행 ---------- */
.srow{ display:grid; grid-template-columns:92px 1fr; gap:12px; padding:9px 0;
  border-bottom:1px solid var(--seed-color-stroke-neutral-subtle); }
.srow:last-child{ border-bottom:none; }
.srow__k{ font-size:11px; color: var(--seed-color-fg-neutral-muted); padding-top:3px; }
.srow__v{ font-size:13px; line-height:1.55; }

/* 복사 박스(`.copybox` 2벌)와 모바일 더보기 메뉴(`.mlist` 5벌)를 지웠다 —
   둘 다 쓰는 화면이 사라졌다. */

/* ---------- 빈 상태 ---------- */
.empty{ padding:40px 16px; text-align:center; font-size:13px;
  color: var(--seed-color-fg-neutral-muted); }

/* ---------- 인기글 코퍼스 (2026-08-19) ---------- */
/* **표가 아니라 카드다.** 이 화면은 남이 터뜨린 글을 눈으로 훑는 자리라, 무엇이
   먼저 보여야 하는지가 표와 다르다 — 사진과 본문 리듬이 먼저고 숫자는 나중이다.
   표로 두면 본문이 한 줄로 잘려 리듬(줄바꿈)이 사라진다. 그 줄바꿈을 복원하려고
   permalink 를 다시 받는 기능이므로, 목록이 그걸 못 보여주면 앞단이 무의미하다. */
.tgrid{ display:grid; gap:12px; grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
  /* **카드 높이를 행마다 같게 못박는다.** 본문 줄 수·배지 줄바꿈에 따라 카드가
     들쭉날쭉하면 사진 격자로 안 읽힌다 — 그리드가 아니라 목록처럼 보인다. */
  grid-auto-rows: 1fr; }

.tcard{ position:relative; display:flex; flex-direction:column; height:100%;
  border:1px solid var(--seed-color-stroke-neutral-weak); border-radius: var(--seed-radius-r3);
  background: var(--seed-color-bg-layer-default); overflow:hidden;
  /* `<a>` 라 링크 색을 물려받는다. 카드 안 글자는 본문 색이어야 읽힌다 —
     물려받은 색으로 두면 호버 오버레이의 원문이 흐린 주황으로 떠서 안 읽혔다(실측). */
  color: var(--seed-color-fg-neutral); text-decoration:none; }
/* `seed.css:869` 의 `a:hover{ color: primary-hover }` 가 카드 전체 글자를 주황으로
   바꾼다 — 카드는 링크지만 **본문을 보여주는 면**이라 그 색이면 원문이 안 읽힌다.
   `.tcard:hover`(0,2,0)가 `a:hover`(0,1,1)를 이긴다. */
.tcard:hover{ border-color: var(--seed-color-palette-gray-500);
  color: var(--seed-color-fg-neutral); }
.tcard:focus-visible{ outline:2px solid var(--seed-color-stroke-focus-ring, #0a5cff); outline-offset:1px; }

/* 4:5 는 Threads 세로 사진의 실제 비율이다(실측 1080x1440). 비율을 고정해야
   카드 높이가 사진마다 들쭉날쭉하지 않는다. */
/* 4:5 는 Threads 세로 사진의 실제 비율이다(실측 1080x1440). 비율을 **고정**해야
   카드마다 사진 칸이 같은 크기가 된다 — `flex:0 0 auto` 로 본문이 늘어나도 이 칸은
   줄지 않게 못박는다. */
.tcard__thumb{ position:relative; flex:0 0 auto; aspect-ratio: 4 / 5;
  background: var(--seed-color-palette-gray-200); overflow:hidden; }
/* `cover` + 위쪽 정렬. Threads 사진은 위에 얼굴·제목이 오는 경우가 많아 가운데를
   기준으로 자르면 정작 봐야 할 부분이 잘린다. */
.tcard__thumb img{ width:100%; height:100%; object-fit:cover; object-position: center top;
  display:block; }

/* 사진이 없는 글(TEXT 타입)과 아직 못 받은 글이 **같은 자리**를 차지해야 한다.
   빈 칸으로 두면 그리드가 어긋나고, 무엇이 비었는지도 알 수 없다. */
.tcard__ph{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  color: var(--seed-color-fg-neutral-muted); font-size:12px;
  background: var(--seed-color-palette-gray-200); }
/* 사선 무늬를 넣어 봤더니 카드 100장이 깔릴 때 그리드 전체가 시끄러웠다(실측).
   빈 자리는 **조용히** 비어 있어야 사진 있는 카드가 눈에 띈다 — 얇은 점선만 둔다. */
.tcard__ph::before{ content:''; position:absolute; inset:10px;
  border:1px dashed var(--seed-color-stroke-neutral-weak); border-radius: var(--seed-radius-r2); }

/* 마우스를 **잠시** 올려둔 사람에게만 뜬다(0.35초). 스치는 동작마다 뜨면
   그리드를 훑는 것 자체가 산만해진다. */
/* 순위 배지(`z-index:1`) 위로 올린다 — 원문 첫 줄이 배지에 가리면 읽는 순서가 끊긴다.
   순위는 카드를 훑을 때 필요한 값이고, 원문을 읽는 동안에는 가려도 된다. */
.tcard__over{ position:absolute; inset:0; z-index:2; overflow:auto; padding:12px 13px;
  background: var(--seed-color-bg-layer-default);
  opacity:0; visibility:hidden; transition: opacity 140ms ease, visibility 140ms; }
.tcard:hover .tcard__over, .tcard:focus-visible .tcard__over,
.tcard:focus-within .tcard__over{ opacity:1; visibility:visible; transition-delay:350ms; }
/* **원문 그대로다.** 줄바꿈·빈 줄이 사라지면 이 화면의 존재 이유가 사라진다. */
.tcard__full{ white-space:pre-wrap; word-break:break-word; font-size:13px; line-height:1.6;
  margin:0; color: var(--seed-color-fg-neutral); }
.tcard__note{ font-size:11px; color: var(--seed-color-fg-neutral-muted); margin:8px 0 0; }

/* 본문 칸이 남은 높이를 먹는다. 배지 줄은 아래에 붙여 카드끼리 눈금이 맞는다. */
.tcard__body{ padding:10px 11px 11px; display:flex; flex-direction:column; gap:6px;
  flex:1 1 auto; min-height:0; }
.tcard__who{ display:flex; align-items:center; gap:6px; font-size:12px;
  color: var(--seed-color-fg-neutral-muted); }
.tcard__who .num{ margin-left:auto; }
/* 두 줄까지. 세 줄이면 카드 높이가 사진보다 커져 그리드가 사진 목록으로 안 읽힌다. */
.tcard__hook{ font-size:13px; line-height:1.45; overflow:hidden; display:-webkit-box;
  -webkit-line-clamp:2; -webkit-box-orient:vertical;
  /* 두 줄 자리를 미리 잡는다. 한 줄 글과 두 줄 글이 섞이면 배지 줄이 어긋난다. */
  min-height: calc(2 * 1.45em); }
/* 배지 줄은 **날짜 줄과 함께** 카드 맨 아래에 붙는다 — 카드끼리 눈금이 맞아야
   격자로 읽힌다. 바닥에 붙이는 축(`margin-top:auto`)은 배지 줄이 갖고 날짜는
   그 아래에 따라온다.

   날짜에서 `margin-left:auto` 를 뺐다 — `flex-wrap:wrap` 안에서 그 값은 줄이
   넘칠 때 마지막 항목만 오른쪽 끝으로 던진다(`TrendCard.tsx` 주석 참고). */
.tcard__tags{ display:flex; align-items:center; gap:4px; flex-wrap:wrap; margin-top:auto; }
.tcard__body > .meta{ font-size:11px; }

/* 날짜 + 검수 버튼이 한 줄에 앉는다 (2026-08-21). 전에는 날짜만 있어 그 줄
   오른쪽이 비어 있었다 — 사람이 그 자리를 지목했다. */
.tcard__foot{ display:flex; align-items:center; gap:8px; }
.tcard__foot .meta{ font-size:11px; }

/* 검수 버튼. **`ActionButton` 을 안 쓴다** — 카드 안에 40px 컨트롤이 들어가면
   사진 아래 칸이 그만큼 두꺼워져 그리드가 사진 목록으로 안 읽힌다. 24px 로 둔다.
   탭 면적은 좌우 `padding` 이 벌린다. */
.tbtn{ margin-left:auto; height:24px; padding:0 9px; border-radius: var(--seed-radius-full);
  border:1px solid var(--seed-color-stroke-neutral-muted);
  background: var(--seed-color-bg-layer-default);
  font-size:11px; font-weight:700; cursor:pointer; white-space:nowrap;
  color: var(--seed-color-fg-neutral-muted); }
.tbtn:hover{ color: var(--seed-color-fg-critical);
  border-color: var(--seed-color-stroke-critical-weak); }
.tbtn:disabled{ cursor:default; opacity:0.5; }
.tbtn:focus-visible{ outline:2px solid var(--seed-color-stroke-focus-ring); outline-offset:1px; }
/* 되돌리기는 파괴적이지 않다 — 빨강을 쓰면 무엇이 위험한지 신호가 뒤섞인다. */
.tbtn--back:hover{ color: var(--seed-color-fg-neutral);
  border-color: var(--seed-color-stroke-neutral-weak); }

/* 제외한 카드. **지우지 않고 흐리게 둔다** — "제외한 글" 보기에서 무엇을 뺐는지
   보이고 되돌릴 수 있어야 한다. 사진만 흐리게 하고 글자는 남긴다: 전체를 흐리면
   되돌릴 카드를 고를 수 없다. */
.tcard--out .tcard__thumb{ opacity:0.4; }
.tcard--out{ border-color: var(--seed-color-stroke-neutral-muted); }
.tcard__rank{ position:absolute; top:8px; left:8px; z-index:1;
  height:22px; padding:0 8px; border-radius: var(--seed-radius-full);
  display:inline-flex; align-items:center; font-size:12px; font-weight:700;
  font-variant-numeric: tabular-nums;
  background: color-mix(in srgb, var(--seed-color-palette-gray-1000) 78%, transparent);
  color: var(--seed-color-palette-static-white, #fff); }

/* 상세. **읽는 화면이라 본문 폭을 재운다** — 1180px 를 다 쓰면 한 줄이 길어져
   원문 줄바꿈이 주는 리듬을 눈이 못 잡는다. 사진·표는 폭을 다 쓴다. */
.tdetail{ display:grid; gap:16px; }
.tdetail__read{ max-width: 760px; }
.tdetail .post{ font-size:16px; line-height:1.7; padding:18px 20px; }
.tdetail__head{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-bottom:12px; }
.tdetail__head .card__more{ margin-left:auto; }

@media (max-width: 767px){
  .tgrid{ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap:8px; }
  /* 손가락에는 hover 가 없다. 카드를 눌러 상세로 가면 되므로 오버레이를 끈다. */
  .tcard__over{ display:none; }
  .tdetail{ gap:12px; }
}

@media (prefers-reduced-motion: reduce){
  .tcard__over{ transition:none; }
}

/* 카드 그리드는 폭이 곧 정보량이다. 1180px 로 재우면 한 줄에 4장뿐이라
   58건을 훑는 데 스크롤이 두 배가 된다. 읽는 화면은 그대로 1180px 를 쓴다. */
.page--wide{ max-width: 1440px; }

/* 영상 표시. 포스터는 사진과 똑같이 생겨서 이 배지가 없으면 영상글을 사진글로 읽는다.
   순위 배지와 같은 모양·반대쪽에 둔다 — 둘이 겹치지 않고 눈이 한 줄에서 훑는다. */
.tcard__vid{ position:absolute; top:8px; right:8px; z-index:1;
  height:22px; padding:0 8px; border-radius: var(--seed-radius-full);
  display:inline-flex; align-items:center; gap:3px; font-size:11px; font-weight:700;
  background: color-mix(in srgb, var(--seed-color-palette-gray-1000) 78%, transparent);
  color: var(--seed-color-palette-static-white, #fff); }

/* ---------- 발행 모니터링 (2026-08-20) ---------- */
/* 24칸 그리드. **색은 상태만 나른다** — 조회수는 칸 안 숫자다. 시간대당 0~1건에서
   색 농도로 수량을 칠하면 그 색이 시간대 속성처럼 보이지만 실제로는 글 하나의
   속성이다 (`docs/plans/publish-timeline/context.md` §2).

   그래서 새 색 스케일을 만들지 않는다. 상태 3~4값에 기존 semantic 토큰만 쓴다. */
.hgrid{ display:grid; grid-template-columns: repeat(12, 1fr); gap:8px; }

.hcell{ position:relative; display:flex; flex-direction:column; align-items:center;
  gap:2px; padding:8px 4px 7px; border-radius: var(--seed-radius-r2);
  border:1px solid var(--seed-color-stroke-neutral-weak); background:transparent;
  font: inherit; cursor:pointer; text-align:center; }
.hcell__h{ font-size:11px; color: var(--seed-color-fg-neutral-muted); }
.hcell__v{ font-size:15px; font-weight:700; font-variant-numeric: tabular-nums; }
.hcell__n{ font-size:10px; color: var(--seed-color-fg-neutral-muted); }

/* 발행완료. **파랑이다** — 이 저장소는 `PUBLISHED → badge--b` 이고 초록을 쓰면
   여기만 예외가 된다 (`web/src/format.ts` statusClass). */
.hcell--done{ background: var(--seed-color-bg-informative-weak, #e3f0ff);
  border-color: transparent; }
/* 배지와 같은 이유로 한 단계 어둡게 - blue-700 on blue-100 은 4.03 으로 미달이다. */
.hcell--done .hcell__v{ color: var(--seed-color-fg-informative-contrast); }

/* 예정. 문제가 아니므로 회색이고, **테두리를 점선으로** 둔다 — 색만으로 구분하면
   색각 이상에서 발행완료와 같아 보인다(WCAG 1.4.1). */
.hcell--todo{ background: transparent; border-style:dashed; }
.hcell--todo .hcell__v{ font-size:12px; font-weight:400;
  color: var(--seed-color-fg-neutral-muted); }
.hcell--sending{ background: var(--seed-color-palette-gray-200);
  border-style:dashed; }
.hcell--sending .hcell__v{ font-size:12px; font-weight:400; }
.hcell--skip .hcell__v{ font-size:12px; font-weight:400;
  color: var(--seed-color-fg-neutral-muted); }

/* 실패만 색을 준다 — 손댈 곳이다. */
.hcell--bad{ border-color: var(--seed-color-fg-critical); }
.hcell--bad .hcell__v{ font-size:12px; color: var(--seed-color-fg-critical); }

/* 빈 시간. **누를 수 없다** — 24칸 중 14칸이 죽은 클릭 대상이 되면 키보드 이동이
   무의미해진다. 자리는 지킨다(칸이 사라지면 시간축이 흔들린다).

   **`opacity` 로 흐리지 않는다.** 전에는 `opacity:0.45` 였고, 그러면 시각 라벨의
   실효 대비가 7.18 -> 2.1 로 떨어진다(합성 실측). 시각 라벨은 **정보다** - 어느
   시간이 비었는지 읽으려면 시간을 읽을 수 있어야 한다. 24칸이 흐린 잡음처럼
   보였던 것도 이 때문이다.

   "비어 있음"은 **점선 테두리와 값의 부재**로 말한다. 채워진 칸은 파란 배경과
   굵은 숫자를 가지므로 여전히 먼저 눈에 든다. */
.hcell--empty{ border-style:dotted; cursor:default; min-height:52px;
  justify-content:center; }

.hcell--on{ outline:2px solid var(--seed-color-bg-brand-solid); outline-offset:1px; }
.hcell:focus-visible{ outline:2px solid var(--seed-color-bg-brand-solid);
  outline-offset:1px; }

/* BEST. 순위를 색 단계로 만들지 않고 배지로 붙인다 — 순위를 시각화하면
   "1등이 2등의 두 배" 로 읽힌다. */
.hcell__best{ position:absolute; top:-6px; right:-4px;
  height:16px; padding:0 5px; border-radius: var(--seed-radius-full);
  font-size:9px; font-weight:700; line-height:16px;
  background: var(--seed-color-bg-brand-solid);
  color: var(--seed-color-fg-neutral-inverted, #fff); }

.tbl--timeline tr.on{ background: var(--seed-color-bg-brand-weak); }
.tbl--timeline .head .seed-badge__root{ margin-left:6px; }

@media (max-width:1023px){
  /* 12칸이 좁아지면 숫자가 줄바꿈된다. 6칸 4줄이 읽힌다. */
  .hgrid{ grid-template-columns: repeat(6, 1fr); }
}

/* `<dialog>` UA 리셋도 사라졌다 — SEED `Dialog` 는 `<dialog>` 를 쓰지 않고
   포지셔너 `<div>` 를 쓴다. 그래서 UA 스타일시트(`border:2px inset` ·
   `background:canvas` · `padding:1em`)와 싸울 자리가 없다. */

/* 큰 숫자 요약 한 줄. `.kv` 는 작은 회색 칸 4개라 위계가 없다 — 요약은 한눈에
   읽혀야 하므로 `.stat`(26px) 을 쓴다. */
.statrow{ display:grid; grid-template-columns: repeat(3, 1fr); gap:16px;
  padding-bottom:4px; }
.statrow .stat__v small{ font-size:14px; font-weight:400;
  color: var(--seed-color-fg-neutral-muted); }

/* 툴바 한 줄은 **한 높이만** 쓴다. 전에는 `.iconbtn`(32)·`.btn`(36)·네이티브
   `.select`(40)이 섞여 밑변이 어긋났다(사용자 지적, 2026-08-20). 40px 로 맞춘다 —
   필드가 40 이고 필드는 줄일 수 없다.

   SEED 컴포넌트는 자기 높이를 갖고 오므로 여기서 다루지 않는다. 대신 툴바에
   넣을 때 `size="medium"` 을 준다(기본 `large` 는 52px 다 — 실측). */
.toolbar .iconbtn{ width: var(--seed-control-height-medium);
  height: var(--seed-control-height-medium); }
/* SEED 버튼은 `size="medium"` 을 주면 40px 이다 — CSS 로 덮지 않는다. */
.toolbar .input{ height: var(--seed-control-height-medium); }

/* 링크형 버튼의 hover 색 문제(`a:hover` 가 `.btn--primary` 를 덮어 주황 배경에
   주황 글자가 됐던 사고)는 **사라졌다.** SEED `ActionButton asChild` 가
   자기 스타일을 자식 `<a>` 에 위임하므로 `a:hover` 와 겹칠 자리가 없다. */

/* 요약 수치 3개의 리듬. 라벨 → 숫자 → 분모 순서로 **왼쪽 정렬 축을 하나**만 쓴다.
   숫자는 `tabular-nums` 라 자릿수가 늘어도 축이 흔들리지 않는다.
   `.stat__u` 에 `min-height` 를 주는 이유: 분모 줄이 없는 칸이 있어도 세 칸의
   밑변이 같아야 한다. */
.statrow .stat{ gap:4px; align-content:start; }
.statrow .stat__l{ font-size:12px; line-height:1.2; }
.statrow .stat__v{ font-variant-numeric: tabular-nums; line-height:1.15; }
.statrow .stat__u{ font-size:12px; line-height:1.3; min-height:16px; }

/* 7일 막대. **선이 아니라 막대 + 숫자다** — 축 없는 스파크라인은 "무엇이 얼마"
   를 못 읽힌다. 칸이 7개뿐이라 숫자를 그대로 적는 비용이 없다. */
.bars{ display:grid; grid-template-columns: repeat(7, 1fr); gap:6px;
  align-items:end; min-height:96px; }
.bars__c{ display:flex; flex-direction:column; align-items:center; gap:4px; }
.bars__n{ font-size:10px; font-variant-numeric: tabular-nums;
  color: var(--seed-color-fg-neutral-muted); }
.bars__b{ width:100%; max-width:26px; border-radius: var(--seed-radius-r1);
  background: var(--seed-color-palette-blue-300, #bcd9ff); }
/* 오늘은 구간이 안 끝났다. 채우지 않고 테두리만 둔다 — 어제와 같은 축에 놓고
   비교하면 거짓 결론이 나온다. */
.bars__b--part{ background: transparent;
  border:1px dashed var(--seed-color-palette-blue-500, #6aa8ff); }
.bars__d{ font-size:10px; color: var(--seed-color-fg-neutral-muted); }
.bars__c--on .bars__d{ font-weight:700; color: var(--seed-color-fg-neutral); }

@media (max-width:767px){ .statrow{ grid-template-columns: repeat(2, 1fr); } }

/* 같은 줄의 카드 높이를 맞춘다. `.grid` 는 그리드지만 **`.card` 가 셀을 채우지
   않는다** — 높이를 안 주면 요약 카드가 내용만큼만 자라고 옆 카드와 밑변이
   어긋난다.

   늘어난 카드의 내용은 **세로 중앙**에 둔다. 위에 붙여 두면 아래에 죽은 여백이
   남아 "위에 붙어 있다" 로 읽힌다(사용자 지적, 2026-08-20). 바닥에 붙일 것이
   있으면 그것만 `.meta--foot` 으로 밀어 붙인다. */
.card--eq{ height:100%; display:flex; flex-direction:column;
  justify-content:center; }
.card--eq > .card__head{ margin-bottom:12px; }
.card--eq:has(.card__head){ justify-content:flex-start; }

/* SEED `ActionButton` 은 `asChild` 로 `<a>` 를 감싸도 `inline-flex` 를 유지한다 —
   `<a class="btn">` 시절 필요했던 정렬 보정이 사라졌다. */

/* ---------- SEED 이탈 : `fg-neutral-subtle` 을 쓰는 슬롯의 대비 ----------

   SEED 의 보조 텍스트 슬롯 몇 개가 `fg-neutral-subtle`(#868b94)을 쓴다.
   흰 배경에서 **3.42:1** 이고 WCAG AA 기준 4.5:1 에 미달한다(실측).

   직전 회차에 우리 화면의 보조 텍스트 39곳이 정확히 이 색이었고, 그게 "흐릿해서
   안 고급스럽다" 의 실체였다(`docs/research/2026-08-20-font-audit.md` §3).
   `fg-neutral-muted`(6.62:1)로 올려 고쳤는데, SEED 컴포넌트를 들이면서 같은 색이
   그 슬롯들로 되돌아왔다.

   **한 단계만 올린다.** 색조·크기·배치는 SEED 그대로 두고 잉크만 바꾼다 —
   `muted` 는 SEED 가 정의한 공식 토큰이므로 팔레트를 벗어나지 않는다.

   `placeholder` 는 덮지 않는다. `fg-placeholder`(2.10:1)는 "아직 값이 없다" 를
   말하는 자리고, 올리면 빈 칸이 채워진 것처럼 보인다. WCAG 도 플레이스홀더를
   본문 대비 요구에서 사실상 제외한다.

   **특이도를 한 단계 올린다.** recipe 셀렉터가 클래스 1개이고 Vite 플러그인이
   컴포넌트 CSS 를 `app.css` **뒤에** 넣으므로 같은 특이도로는 순서에서 밀린다
   (실측 - 3.42 그대로였다). `__root` 를 앞에 붙여 (0,2,0) 으로 이긴다.
   `!important` 는 쓰지 않는다 - 다음 사람이 이 값을 덮을 길을 막는다.

   **새 컴포넌트를 들일 때마다 대비 감사를 다시 돌려라.** 이 목록은 그렇게
   하나씩 늘어났다 (`field__description` -> `indicatorText` -> `dropzoneLabel`). */
.seed-field__root .seed-field__description,
.seed-field__root .seed-field-label__indicatorText,
.seed-attachment-input__root .seed-attachment-input__dropzoneLabel{
  color: var(--seed-color-fg-neutral-muted);
  --seed-prefix-icon-color: var(--seed-color-fg-neutral-muted);
}

/* ---------- SEED 이탈 : 스켈레톤 반짝임과 `prefers-reduced-motion` ----------

   `.seed-skeleton::after` 는 `slide-x` 를 **무한 반복**한다(1.5s). SEED 는 이 애니메이션을
   `prefers-reduced-motion` 으로 끄지 않는다 (`recipes/skeleton.css` 실측 — 그 파일에
   미디어 쿼리는 폭·높이 브레이크포인트뿐이다. base.css 의 reduce 블록은 `--seed-scale-*`
   3개만 되돌린다).

   멀미·전정기관 장애가 있는 사용자에게 무한 반복 애니메이션은 접근성 문제다. 자리는
   그대로 두고 **움직임만** 멈춘다 — 배경은 남으므로 "아직 오지 않았다" 는 신호는 유지된다. */
@media (prefers-reduced-motion: reduce){
  .seed-skeleton::after{ animation: none; }
}

/* ---------- 모바일 드로우어 안의 사이드바 ----------

   드로우어(`SidePanel`)는 자기 폭(272px)을 갖는다. `SideNavigation` recipe 의
   `width:240px; height:100%` 는 그 안에서 오른쪽에 32px 빈 띠를 남기고, 항목이
   드로우어 폭을 다 쓰지 못해 탭 영역이 좁아진다. 폭만 부모에 맞춘다 — 색·간격·
   항목 스타일은 recipe 그대로다.

   **특이도를 한 단계 올린다.** recipe 셀렉터가 클래스 1개이고 Vite 플러그인이
   컴포넌트 CSS 를 `app.css` 뒤에 넣으므로 같은 특이도로는 밀린다 (2026-08-20 §9-34). */
.seed-side-panel__content .seed-side-navigation__root.drawernav{
  width:100%; height:auto; border:none; background:transparent;
}

/* ---------- 로그인 (2026-08-21) ----------

   셸이 없는 유일한 화면이다. `.shell` 이 뷰포트를 고정하고 `Inset` 이 스크롤하는
   구조 밖에 있으므로 자기 높이를 직접 잡는다.

   **`min-height: 100dvh` 다.** 모바일 브라우저의 주소창이 접히면 `100vh` 가
   화면보다 커져 로그인 상자가 위로 밀리고 스크롤이 생긴다. `dvh` 는 그 변화를
   따라간다(iOS Safari 15.4+, Chrome 108+ — 그 밑에서는 `vh` 폴백이 먹는다). */
.login{
  min-height:100vh; min-height:100dvh;
  display:flex; align-items:center; justify-content:center;
  padding: 24px 20px;
  background: var(--seed-color-bg-layer-basement, #f7f8fa);
}
/* 너비 상한을 두는 이유: 입력 한 칸이 1200px 로 늘어나면 어디를 눌러야 하는지
   시선이 흩어진다. 360px 은 375px 화면에서 좌우 여백이 남는 값이다. */
.login__box{
  width:100%; max-width:360px;
  background: var(--seed-color-bg-layer-default);
  border:1px solid var(--seed-color-stroke-neutral-weak);
  border-radius: var(--seed-radius-r4);
  padding:28px 24px;
}
.login__brand{ display:flex; align-items:center; gap:8px; }
.login__sub{ margin:6px 0 20px; font-size:13px; color: var(--seed-color-fg-neutral-muted); }
/* 버튼은 풀폭이다. `ActionButton` 은 자기 폭을 내용에 맞추므로 감싸서 늘린다 —
   모바일에서 엄지가 닿는 유일한 목표라 좁힐 이유가 없다. */
.login__box .seed-action-button{ width:100%; }

/* 설정 화면의 구역 제목. 값이 20개 넘게 한 카드에 있으면 사람이 어디를 보는지
   잃는다 — "글이 나가는 시간 · 사람 확인 · 쇼핑글 링크 댓글" 처럼 묶어 준다.
   `.card__title` 보다 작고 본문보다 굵다: 카드 제목과 경쟁하지 않아야 한다. */
.setgroup{ font-size:12px; font-weight:700; margin: 0 0 8px;
  color: var(--seed-color-fg-neutral-muted); }

/* 도움말 아이콘이 붙는 변형. `.setgroup` 자체를 flex 로 만들지 않는 이유는
   도움말 없는 구역이 대부분이고, 그쪽에 flex 를 얹으면 얻는 것 없이 줄바꿈
   거동만 바뀐다. */
.setgroup--help{ display:flex; align-items:center; gap:4px; }

/* 도움말 버튼. **44px 목표를 쓰지 않는다** — 구역 제목 옆 12px 글자에 붙는
   장식이라 그만큼 키우면 제목 줄이 두꺼워진다. 대신 `padding` 으로 실제 탭
   면적을 24px 까지 벌리고 아이콘만 14px 로 둔다. */
.helpbtn{ display:inline-flex; align-items:center; justify-content:center;
  padding:5px; margin:-5px 0 -5px -1px; border:0; background:none; cursor:pointer;
  border-radius:999px; color: var(--seed-color-fg-neutral-subtle); }
.helpbtn:hover{ color: var(--seed-color-fg-neutral); background: var(--seed-color-bg-neutral-weak); }
.helpbtn:focus-visible{ outline:2px solid var(--seed-color-stroke-focus-ring); outline-offset:1px; }

/* 레퍼런스 계정 칩 줄 (2026-08-21).
   계정이 많으면 한 줄을 넘는다 — 실측에서 57개가 옆으로 밀려 화면 밖으로 나갔다.
   실제 계정 CSV 는 1~2개일 테지만, 순위 CSV 를 실수로 올리면 이 상태가 된다.
   `flex-wrap` 으로 접고 높이를 제한해 목록이 화면을 다 먹지 않게 한다. */
.chiprow{ display:flex; flex-wrap:wrap; gap:6px; max-height:96px; overflow-y:auto; }

/* 계정 한 줄 (2026-08-21). 누르면 설정 모달이 열린다.
   `button` 이라 키보드로도 열린다 — `div` + `onClick` 은 탭 순서에 안 들어간다. */
.acctrow{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; width:100%;
  padding:12px 12px; border:1px solid var(--seed-color-stroke-neutral-muted);
  border-radius: var(--seed-radius-r3, 10px); background: var(--seed-color-bg-layer-default);
  cursor:pointer; text-align:left; font-size:14px;
  color: var(--seed-color-fg-neutral); }
.acctrow + .acctrow{ margin-top:8px; }
.acctrow:hover{ border-color: var(--seed-color-stroke-neutral-weak);
  background: var(--seed-color-bg-neutral-weak); }
.acctrow:focus-visible{ outline:2px solid var(--seed-color-stroke-focus-ring); outline-offset:1px; }
/* "설정" 은 오른쪽 끝. 행이 눌리는 것이라는 신호다. */
.acctrow__go{ margin-left:auto; font-size:12px; font-weight:700;
  color: var(--seed-color-fg-neutral-subtle); }
.acctrow:hover .acctrow__go{ color: var(--seed-color-fg-brand); }

/* 페이지 바 (2026-08-21). 무한 스크롤과 함께 쓴다 — 번호는 "나중에 바로 찾아가는"
   수단이다. `sticky` 로 붙이지 않는다: 그리드 4열이 화면을 다 쓰는데 바가 고정되면
   카드 한 줄이 늘 가려진다. */
.pagebar{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin-top:16px; padding-top:12px;
  border-top:1px solid var(--seed-color-stroke-neutral-muted);
}
.pagebar__count{ font-size:12px; color:var(--seed-color-fg-neutral-muted); }
.pagebar__nums{ display:flex; align-items:center; gap:4px; flex-wrap:wrap; margin-left:auto; }
.pagebar__gap{ font-size:12px; color:var(--seed-color-fg-neutral-muted); padding:0 2px; }
/* 번호는 `button` 이다 — 키보드로 넘길 수 있어야 한다. */
.pagenum{
  min-width:30px; height:30px; padding:0 6px;
  border:1px solid var(--seed-color-stroke-neutral-muted);
  border-radius:var(--seed-radius-r2);
  background:var(--seed-color-bg-layer-default);
  color:var(--seed-color-fg-neutral); font-size:12px; font-weight:600;
  cursor:pointer;
}
.pagenum:hover{ background:var(--seed-color-bg-neutral-weak-pressed); }
.pagenum--on{
  background:var(--seed-color-bg-brand-solid);
  border-color:var(--seed-color-bg-brand-solid);
  color:var(--seed-color-palette-static-white);
}
/* 무한 스크롤 감지 칸. **높이 0 이면 안 된다** — `IntersectionObserver` 가
   교차를 잡지 못한다(2026-08-21 실측). 1px 이면 눈에 안 보이고 감지는 된다. */
.endmark{ height:1px; }
