/* 물밑의 시각 세계 — 페이지에 무관한 층 (2026-09-04)
 *
 * `segment.css`에서 뽑아냈다. 홈에서 증명된 것 중 **어느 화면에나 붙는 것**만
 * 여기 산다 — 토큰 재정의, 셸, 상태 블록, 브라우저가 그리는 자리, 모션 한 줄.
 * 홈에만 있는 것(상단 시각 표시, `#board`, `.tile` 계열의 유령 셀)은
 * `segment.css`에 남았다.
 *
 * **이 파일이 세계를 입히는 방법은 클래스가 아니라 토큰이다.** 앞에 실리는
 * `monitor.css`·`console.css`가 이 토큰들을 700곳 넘게 쓴다(--line 136 ·
 * --accent 114 · --ink-3 103 · --ink 99 …). 그래서 표·도넛·달력·히트맵처럼
 * 우리가 이름을 모르는 부품까지 값만 바꿔 따라온다. 클래스를 열거했다면
 * 화면마다 다시 써야 했다 — 실제로 홈에서 그렇게 했다가 같은 페이지의
 * `.kro-card`를 놓쳤다.
 *
 * 쓰는 법: `<body class="world">`. 이관한 화면만 켠다.
 *
 * 규칙과 근거는 `docs/DESIGN.md`. 여기서는 값만 정한다.
 */

.world {
  /* --- 면: 수면 아래로 내려가는 물 ------------------------------------ */
  --bg: #070b12;
  --bg-deep: #04070c;
  --panel: #0d1420;
  --panel-2: #121b2a;
  --panel-3: #16202e;

  /* --- 선 ------------------------------------------------------------- */
  --line: #1d2a3a;
  --line-strong: #2a3a4e;
  --line-2: #2a3a4e;

  /* --- 잉크: 값은 색을 입지 않는다 (판 위 15.83 / 8.31 / 5.37) --------- */
  --ink: #e9eef5;
  --ink-2: #9db0c6;
  --muted: #9db0c6;
  /* 범례 잉크는 **틴트면을 견뎌야 한다.** 신호색 12% 틴트(`--up`/`--down`을
     `--panel-2`에 섞은 면, `/us` 지수 표가 쓴다) 위에서 `#7a8ca4`는 3.95·4.27로
     AA에 못 미쳤다 — 판 위에서는 5.37로 멀쩡한데도. 이게 DESIGN.md의
     Tinted-Surface Rule이 말하는 바로 그 함정이라, 셀렉터를 좇는 대신 토큰이
     견디게 만든다. #8b9db4는 판 위 6.66 · 상승틴트 4.89 · 하락틴트 5.30이고
     `--ink-2`(8.31)보다는 여전히 조용하다. */
  --ink-3: #8b9db4;
  --faint: #8b9db4;

  /* --- 동작: 파랑은 누를 수 있는 것과 지금 켜진 것에만 ----------------
   * 파랑 면 위의 글자는 어두운 잉크다. 흰 글자는 3.71로 AA에 못 미치고
   * 어두운 잉크는 4.97로 통과한다(실측). 옛 세계가 지켜 온 규칙과 같다. */
  --accent: #3182f6;
  --accent-ink: #0d1420;
  --accent-soft: rgba(49, 130, 246, .16);
  --chart: #3182f6;
  --chart-fill: rgba(49, 130, 246, .10);

  /* --- 모서리는 재정의하지 않는다 (운영자 결정 2026-09-05) -------------
   *
   * 2px 하나로 내렸다가 되돌렸다. 새 세계와 옛 세계를 나란히 놓고 보고 내린
   * 판정이다("전에가 더 낫다").
   *
   * 되돌리는 근거도 이 세계 안에 있다: 계기판으로 읽히게 만드는 것은 모서리가
   * 아니라 자리가 고정된 `tabular-nums`, 꺼진 셀 격자, 세그먼트 눈금이다.
   * 그것들은 **뜻이 있다**(자릿수가 안 흔들린다 · 칸은 있는데 안 켜졌다).
   * 158px짜리 판의 2px 모서리에는 그런 뜻이 없었다 — 값을 더 정직하게 만들지
   * 않고 엄해 보이게만 했다. 이 화면에 오는 사람은 증권사 앱을 쓰다 넘어온다.
   *
   * 그래서 여기서 아무것도 덮지 않는다. `tokens.css`의 6·10·14·999가 그대로
   * 온다 — 값을 두 곳에 적어 두면 다음에 한쪽만 바뀐다. */

  /* --- 계기판은 뜨지 않는다 ------------------------------------------- */
  --shadow: none;

  /* --- 이 세계만의 것 ------------------------------------------------- */
  --seg-ghost: #16202e;       /* 꺼진 셀 */
  --seg-ghost-2: #111926;     /* 아직 수집 안 된 자리 */
  --seg-live: #5ac8fa;        /* 지금 켜졌다 */
  --seg-cell: 1ch;

  background: var(--bg);
}
body.world { background: var(--bg); }

/* ======================================================================
 * 셸 — 모든 화면이 같은 머리와 발을 쓴다
 * ====================================================================== */
/* 계기판은 유리가 아니다. 고정 띠 셋이 전부 블러를 쓰고 있었는데, 세계에서는
   불투명면으로 간다 — 모바일 GPU에서 가장 비싼 효과이고 1순위 사용자의 기기가
   거기다. 마스트헤드만 껐던 것을 나머지 둘로 넓힌다. */
.world .masthead { background: var(--bg); backdrop-filter: none; }
.world .jump-nav { background: var(--bg); backdrop-filter: none; }
.world .section-rail { background: var(--bg); backdrop-filter: none; }
.world .tape { background: var(--bg-deep); }
/* 밑줄은 **넓은 화면에만** 있다. 폰의 탭 바는 가장자리에서 띄운 알약이라
   밑줄을 걸 모서리가 없고, 활성은 잉크와 점이 말한다(monitor.css).
   이 줄은 한때 폰까지 덮어 `inset 0 -2px`를 바 맨 아래에 그리고 있었다 —
   순서상 뒤에 와서 monitor.css가 고쳐 둔 것을 조용히 되돌린 회귀였다.
   이제 폰 규칙을 여기서 **명시적으로 끈다**. 한쪽만 두면 같은 일이 반복된다. */
.world .view-tab.active { box-shadow: inset 0 -2px var(--accent); }
@media (max-width: 760px) {
  .world .view-tab.active { box-shadow: none; }
}
.world .skip-link { background: var(--panel); color: var(--ink); border: 1px solid var(--accent); }

/* 브라우저가 그리는 자리도 이 세계의 것이다. */
.world ::selection { background: var(--accent); color: var(--accent-ink); }
.world :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 검색칸만 예외다 — **보이는 것은 알약이고 초점을 받는 것은 그 안의 글자
   상자**라, 위 규칙이 알약 안쪽에 네모난 파란 상자를 하나 더 그렸다(운영자
   제보 2026-09-07: "클릭하면 이상한 푸른 박스가 같이 나와"). 옛 판에서는
   입력칸 자체가 보이는 칸이라 링이 그 모서리를 그대로 감쌌다.

   링을 지우는 것이 아니라 **옮긴다.** 알약이 받으면 모양도 맞고 초점도
   그대로 보인다. 예외를 여기 적는 이유는 링의 주인이 이 파일이기 때문이다 —
   `monitor.css`에 적으면 뒤에 실리는 이 줄에 진다(같은 실수를 밑줄에서
   한 번 했다). */
.world .site-search-input:focus-visible { outline: none; }
.world .site-search-field:has(.site-search-input:focus-visible) {
  outline: 2px solid var(--accent); outline-offset: 2px;
}

/* ======================================================================
 * 비어 있음 — 값이 없는 이유 다섯은 어느 화면에서나 같은 꼴로 말한다
 *
 * 색은 여전히 둘뿐이다. 꺼짐에 호박을 다시 부르지 않는다 — 잉크를 내리고
 * 점등을 주지 않는 것으로 말한다. 오류만 신호색을 쓴다.
 * ====================================================================== */
.world .state-block {
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background:
    linear-gradient(90deg, var(--seg-ghost-2) 0 calc(var(--seg-cell) * .72),
                    transparent calc(var(--seg-cell) * .72) var(--seg-cell))
    repeat-x var(--panel);
  background-size: var(--seg-cell) 100%;
  color: var(--ink-3);
  /* 깜빡임의 위상. 축이 둘이라 더해야 한다 — 아래 참조. */
  --seg-phase-section: 0s;
  --seg-phase-box: 0s;
}
.world .state-block[data-state="off"] { color: var(--ink-3); border-color: var(--line-strong); }
/* `deferred` — 아직 화면에 안 들어와서 부르지도 않은 자리. 넷을 세던 시절에는
   이름이 없어 `data-state`가 비어 있었고, 그래서 **연결이 끊긴 판과 똑같이
   보였다**(실측 8곳). 일부러 쉬는 꼴 그대로 둔다 — 아무 일도 안 일어나고 있는
   것이 사실이므로 깜빡이면 거짓말이 된다. 이름만 준다. */
.world .state-block[data-state="deferred"] { color: var(--ink-3); }
.world .state-block[data-state="failed"] { color: var(--red); border-color: color-mix(in srgb, var(--red) 35%, var(--line)); }

@keyframes seg-unset { 50% { opacity: .5; } }
.world .state-block[data-state="waiting"],
.world .state-block[data-state="collecting"] {
  /* **밑값을 되돌려 놓아야 한다.** `monitor.css:348`이 `.state-block`에
     `opacity: 0`을 두고 `state-block-in`으로 1까지 올린다. 아래 `animation`
     단축이 그 진입 애니메이션을 갈아치우는데, `seg-unset`은 `50%` 키프레임
     하나뿐이라 0%와 100%가 밑값 0을 그대로 쓴다 — 판이 0과 .5 사이만 오가며
     **한 번도 온전히 보이지 않았다.** 타이밍이 아니라 CSS 의미론이라 어느
     기기에서나 그랬다. 밑값을 1로 올려 깜빡임을 '보임 ↔ 반쯤'으로 만든다. */
  opacity: 1;
  animation: seg-unset 1.8s steps(2, end) infinite;
  /* 지연은 **단축 다음 줄에** 와야 한다. `animation` 단축은 적지 않은 하위
     속성을 초깃값으로 되돌리므로, 지연을 다른 규칙에 두면 여기서 0으로
     지워진다 — 실제로 그렇게 해서 위상이 도로 하나로 뭉쳤다(실측). */
  animation-delay: calc(var(--seg-phase-section) + var(--seg-phase-box));
}

/* **위상을 흩는다.** 자리표시자가 처음부터 `waiting`을 달고 출발하면서 한
   화면의 판이 전부 같은 시각에 깜빡이기 시작했다(실측 2026-09-04: `/crypto`
   11개 · `/bio` 7 · `/semi` 4가 전부 지연 0s에 위상 0). 계기 열한 개가 한
   박자로 깜빡이는 것은 계기가 아니라 **고장 난 화면 하나**로 읽힌다 — 방향
   계약이 말한 "설정 안 된 시계"는 각자 제 박자로 깜빡인다.

   구역 차례로 1.8초 주기를 넷으로 나눈다. `steps(2, end)`라 켜짐과 꺼짐이
   반씩이므로, 넷이면 이웃한 판이 서로 반대 위상에 선다.

   축이 둘인 이유: `nth-of-type`은 **형제 안에서만** 센다. 구역이 통에 감싸이면
   번호가 통마다 1로 되돌아가서, `/bio`는 일곱 중 다섯이 전부 `#1`이라 한 위상에
   몰렸다. 구역 차례와 통 차례를 따로 받아 `calc()`로 합친다 — CSS는 지연을
   겹쳐 더하지 못하지만 값은 더한다.

   결과(실측 390px): `/crypto` 11 → 최대 동위상 4 · `/bio` 7 → 3 ·
   `/semi` 4 → 1. */
.world .console-section:nth-of-type(4n + 2) .state-block { --seg-phase-section: .45s; }
.world .console-section:nth-of-type(4n + 3) .state-block { --seg-phase-section: .9s; }
.world .console-section:nth-of-type(4n)     .state-block { --seg-phase-section: 1.35s; }
.world .bio-zone:nth-of-type(2n) .state-block,
.world details.disclose:nth-of-type(2n) .state-block { --seg-phase-box: .225s; }
@media (prefers-reduced-motion: reduce) {
  .world .state-block[data-state="waiting"],
  .world .state-block[data-state="collecting"] { animation: none; opacity: .75; }
}

/* ======================================================================
 * 칩 — 누를 수 없는 것은 동작색을 입지 않는다
 *
 * `.ev-by-mark`(공시 요약의 "무엇이 만들었나" 라벨)는 액센트 글자를 자기
 * 액센트 16% 워시 위에 얹고 그 위에 글로우까지 달고 있었다. 세 가지가 어긋난다 —
 * 새 액센트가 더 어두워 **4.10:1로 AA 미달**(프로덕션 실데이터 32곳 실측),
 * 누를 수 없는 라벨이 동작색을 쓰고, 바깥 글로우가 No-Shadow를 어긴다.
 *
 * 조용한 칩으로 내린다. 이 라벨이 말하는 것은 출처이지 행동이 아니다.
 *
 * --- 2026-09-07: 너무 조용해졌다 (운영자) ---
 *
 * 회색 칩이 되고 나니 옆의 공시종류 칩(`.ev-kind`)과 구분이 안 됐다. 한 줄에
 * 둘이 나란히 서는데 둘 다 회색이면 **누가 썼는지가 분류표처럼 읽힌다.**
 * 자동 생성 문장은 그 사실이 눈에 띄어야 한다 — 숨길 것이 아니라 밝힐 것이다.
 *
 * 살리되 옛 잘못은 되풀이하지 않는다:
 *   글자는 `--ink`다.  액센트 글자를 액센트 워시에 얹어 4.10:1이 됐던 것이
 *                      원래 문제였다. 지금은 14:1이고 이웃 회색 칩보다 밝다.
 *   색은 **점만** 든다.  6px 점은 글자가 아니라 표식이라 대비 기준이 다르고
 *                      (WCAG 1.4.11의 3:1), 누를 수 있다고 오해될 크기도 아니다.
 *   글로우는 여전히 없다. 아래 맥박은 **퍼졌다 사라지는 고리**이고 남는 그림자가
 *                      아니다 — `.presence-badge`가 이미 쓰는 이 세계의 어휘다.
 * ====================================================================== */
.world .ev-by-mark {
  background: var(--panel-2);
  color: var(--ink);
  border-color: var(--line);
  box-shadow: none;
}
.world .ev-by-mark::before { background: var(--accent); opacity: 1; box-shadow: none; }

/* 섹션 머리의 배지 **하나만** 숨을 쉰다.
 *
 * 실측(2026-09-07, 1280px): `/kr`에 이 배지가 26개 — 25개는 줄마다 붙고 1개가
 * 섹션 머리다. 26개가 다 맥박치면 화면이 떨린다. 그래서 움직임은 **한 화면에
 * 하나**뿐이고, 줄에 붙는 것들은 색 점만 갖는다.
 *
 * 고리는 퍼졌다 **사라진다** — 남는 그림자가 아니라 지나가는 신호다. 값이
 * 없을 때 도는 스피너와 다르다: 이건 "지금 읽고 있다"가 아니라 "이 글은
 * 사람이 아니라 모델이 썼다"를 계속 말하는 표식이고, 그래서 느리다(3.2초). */
.world .ev-model .ev-by-mark {
  background: color-mix(in srgb, var(--accent) 12%, var(--panel-2));
  border-color: color-mix(in srgb, var(--accent) 26%, var(--line));
}
.world .ev-model .ev-by-mark::before {
  animation: byline-pulse 3.2s ease-out infinite;
}
@keyframes byline-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}
/* 움직임을 원치 않는 사람에게는 색 점만 남는다 — 뜻은 그대로다. */
@media (prefers-reduced-motion: reduce) {
  .world .ev-model .ev-by-mark::before { animation: none; }
}

/* `.digest-tag`도 같은 무늬다 — `--accent-soft` 워시 위의 `--accent` 글자로
   4.10:1(실측 2곳). 출처를 말하는 라벨이므로 같은 처방을 쓴다. */
.world .digest-tag {
  background: var(--panel-2);
  color: var(--ink-2);
}

/* 같은 함정, 세 번째 — 이제 셀렉터가 아니라 **무늬**로 다룬다.
 *
 * `color: var(--accent)` + `background: var(--accent-soft)`는 이 저장소에
 * 여섯 번 나타나고 전부 4.10:1이다(실측: `/us` 9곳 · `/kr` 13곳). 액센트가
 * 자기를 틴트한 면 위에 서면 대비가 무너진다.
 *
 * 위의 둘(`.ev-by-mark`·`.digest-tag`)과 처방이 다른 이유: 저 둘은 **출처를
 * 말하는 라벨**이라 동작색을 쓸 이유가 애초에 없어 통째로 조용히 내렸다.
 * 아래 넷은 **상태를 말하는 칩**이다 — "새로 왔다"·"알림"은 액센트가 지고
 * 있는 뜻이라 글자는 남기고 워시만 걷는다. 판 위 액센트는 4.65로 통과한다.
 *
 * 새 칩을 만들 때: 액센트 글자를 액센트 워시 위에 얹지 마라. */
.world .status-badge.info,
.world .score-new,
.world .issue-move-new,
.world .pulse-side .issue-kind {
  background: var(--panel-2);
  color: var(--accent);
}

/* ======================================================================
 * 모션 — 값은 굴러서 도착한다 (2026-09-06 판정으로 뒤집음)
 *
 * 여기 `.world .odo-strip { transition: none; }`이 있었다. 세그먼트 세계를
 * 지키려는 규칙이었다 — "자리는 움직이지 않고 어느 칸이 켜지는지만 바뀐다."
 * 대가가 컸다: `console.js`의 계기판이 자리마다 띠를 세우고 굴릴 준비를 다
 * 해 놓고도 **한 프레임에 끝났다.** 화면에는 깜빡임만 남았고, 운영자가 세 번
 * "룰렛이 안 보인다"고 말한 것이 그 소리였다(2026-09-06).
 *
 * 판정이 바뀌었다: 값이 바뀌는 순간은 이 제품의 사건이고, 그 사건은 **굴러서
 * 도착하는 것**으로 말한다. 규칙을 지우는 것이 곧 그 결정이므로 자리를 비워
 * 두지 않고 무엇이 있었는지 적어 둔다 — 세그먼트 세계를 다시 세우려는 사람이
 * 같은 줄을 되살리기 전에 이 사연을 읽게.
 * ====================================================================== */

/* 검색 드롭다운이 `0 18px 40px` 바깥 그림자를 들고 있었다. 닫혀 있어 눈에
   안 띄었을 뿐 열리면 뜬다 — The No-Shadow Rule 위반이고, 이 세계에서 판이
   떠 있음을 말하는 방법은 그림자가 아니라 **한 단 위 면과 선**이다. */
.world .site-search-panel {
  box-shadow: none;
  background: var(--panel-2);
  border-color: var(--line-strong);
}

/* ======================================================================
 * 텍스트를 200%로 키워도 가로로 새지 않는다 (WCAG 1.4.4)
 *
 * 실측 2026-09-04: 루트 글꼴 16 → 32px에서 홈 문서 폭이 375 → 478로 벌어졌다.
 * 세 자리가 원인이었고 전부 **줄바꿈을 막아 둔 것**이었다.
 *
 * 확대는 폭이 좁아지는 것과 다르다 — 미디어 쿼리가 안 걸린다. 그래서 이
 * 규칙들은 폭 조건 없이 건다. 보통 크기에서는 어차피 한 줄에 들어가므로
 * 화면이 바뀌지 않고, 키웠을 때만 접힌다.
 * ====================================================================== */
.world .session-badge { white-space: normal; }
/* 긴 도메인·URL 토큰은 어디서든 끊는다. 안 그러면 한 단어가 상자를 밀어낸다
   (실측: `newyorktelegraph…`가 103px 밖으로). */
.world .feed-domain,
.world .ev-src,
.world .attribution a { overflow-wrap: anywhere; }
.world .seg-readout { flex-wrap: wrap; }

/* 재생 원반의 원형 예외를 걷었다(2026-09-05).
 *
 * `--r-pill`을 2px로 내렸을 때만 필요했던 것이다 — 42×42 원반이 각진 사각형이
 * 됐다는 운영자 지적(2026-09-04)에 대한 답이었다. 모서리를 옛 값으로 되돌리면서
 * `monitor.css`의 밑값(`--r-pill`)이 그대로 원을 만든다. 없어도 되는 예외는
 * 남기지 않는다 — 남겨 두면 다음 사람이 "왜 여기만 특별한가"를 묻게 된다.
 * ====================================================================== */

/* ======================================================================
 * 잘리는데 스크롤 신호가 없던 자리
 *
 * 이 세계에는 그림자가 없어서 통상의 scroll-shadow 기법을 못 쓴다. 그래서
 * 신호를 더하는 대신 **잘림 자체를 없앤다.**
 *
 * `.pulse-chips`는 값을 품은 칩이라 가장 아팠다 — 390px에서 464px가 필요해
 * 세 번째 칩이 "엔비디아 +1.9"에서 끊겼고, **잘린 숫자는 틀린 숫자처럼
 * 읽힌다**(critique 2026-09-04). 접으면 끝난다. 세로로 몇 px 더 쓰는 값은
 * 숫자를 틀리게 보여 주는 것보다 싸다.
 *
 * 표(`.table-scroll`)는 그대로 스크롤한다 — 표는 원래 넓고, 접으면 열이
 * 무너져 비교가 안 된다.
 * ====================================================================== */
@media (max-width: 560px) {
  .world .pulse-chips { flex-wrap: wrap; overflow-x: visible; }
}
/* 고정 하단 내비는 접으면 두 줄이 되어 폰 화면을 더 먹는다. 대신 여섯 칸이
   들어가게 조인다(실측 390px: 459 필요 → 375 가용, 84px 초과). */
@media (max-width: 420px) {
  .world .section-rail { gap: 0; padding-inline: var(--sp-1); }
  .world .section-rail > * { padding-inline: var(--sp-1h); }
}

/* ======================================================================
 * 판 — 들리지 않는다
 * ====================================================================== */
.world .tile:hover,
.world .zone-link-card:hover,
.world .kro-card:hover {
  border-color: var(--accent);
  transform: none;
}

/* ======================================================================
 * 폰 밀도 — 토스 결 (2026-09-07, 운영자: "2번도 토스처럼")
 *
 * 토스가 넓어 보이는 이유는 넷이다: 큰 모서리, 블록 **사이**의 세로 여백,
 * 손가락에 맞춘 행, 그리고 카드 안쪽의 넉넉한 여백. 우리는 앞의 셋만
 * 가져온다 — 넷째는 이 저장소에서 이미 막혀 있다.
 *
 * **안쪽 여백은 못 늘린다.** 타일은 폰에서 `--sp-4`(16) → `--sp-3`(12)로
 * 이미 **줄여** 놓았고, 그 줄임이 360px 넘침(−4.2px)을 고친 결과다. 값
 * 크기도 마찬가지로 358px에서 원화 7자리(1,739,718)가 잘려 clamp로 묶여
 * 있다. 이 둘을 토스처럼 키우면 고쳐 놓은 것이 그대로 되돌아간다.
 *
 * **테두리도 못 걷는다.** 토스 카드는 선 없이 면만으로 서는데, 이 세계의
 * 지면과 판은 대비가 1.08:1이라(#070b12 대 #0d1420) 선을 걷으면 카드가
 * 사라진다. 판을 밝히면 서지만 그건 팔레트 변경이고, 판 위 잉크 대비를
 * 전부 다시 재야 하는 별도 판정이다.
 * ====================================================================== */
@media (max-width: 760px) {
  /* 모서리 — 가장 크게 도는 신호이고 자리를 한 픽셀도 안 먹는다. */
  .world {
    --r-sm: 10px;
    --r-md: 16px;
    --r-lg: 20px;
  }
  /* 구역 사이. 가로가 아니라 **세로**로 숨을 틔운다 — 넘칠 축이 아니다. */
  .world .console-section { margin-top: var(--sp-6); }
  .world .console-section > header { margin-bottom: var(--sp-4); }
  /* 표 행을 손가락에 맞춘다. 24px는 **바닥이지 목표가 아니다**(WCAG 2.2 AA
     2.5.8). 한 화면의 행이 줄어드는 대가는 운영자가 알고 고른 것이다. */
  .world .panel .accessible-table :is(th, td) { padding-block: var(--sp-3); }
}

/* ======================================================================
 * V2 · 부품의 상태 계약 (2026-09-09, 밤샘 개편)
 *
 * 이 층이 하는 일은 하나다 — **누를 수 있는 것이 여섯 상태를 전부 갖게
 * 한다**: 쉼 · 마우스 · 초점 · 눌림 · 비활성 · 바쁨.
 *
 * 왜 지금인가. 실측(2026-09-09, 7,600줄 CSS 전수): `:active` 규칙 12개 ·
 * `:focus-visible` 9개다. 그중 눌림은 열 개 남짓한 컨트롤만 덮고 있었다.
 * 화면이 "웹 같다"고 느껴지는 이유가 폰트나 여백이 아니라 여기다 — 손가락을
 * 대는 동안 아무 일도 일어나지 않으면 그건 종이지 앱이 아니다.
 *
 * 셀렉터를 하나씩 세지 않는다. 그 방식으로는 다음에 또 놓친다 — 이 저장소가
 * `word-break`에서 이미 겪었다("선택자를 하나씩 세는 방식으로는 다시 놓친다",
 * tokens.css). 여기서는 **역할로 묶는다.**
 *
 * 역할 셋:
 *   컨트롤 — 눌러서 무언가를 바꾸는 작은 것. 눌리면 **줄어든다**.
 *   면     — 눌러서 어딘가로 가는 큰 것(카드·행·요약줄). 눌리면 **면이 오른다**.
 *            큰 상자가 줄어드는 것은 눌림이 아니라 오류처럼 읽힌다
 *            (console.css의 2026-08-31 판정, 그대로 따른다).
 *   글     — 문장 안을 흐르는 링크. 아무것도 하지 않는다. 밑줄이 이미 말한다.
 * ====================================================================== */

/* 이 세계에서 "컨트롤"과 "면"이 무엇인지 한 곳에서 정한다. 아래 규칙들이
   전부 이 두 목록을 읽는다 — 새 부품이 생기면 여기 한 줄만 더한다. */

/* --- 1. hover는 마우스에만 있다 --------------------------------------
 *
 * 폰에는 hover가 없다. 있는 것은 **탭한 뒤에 남는 hover 잔상**이다 —
 * 안드로이드 크롬은 탭한 요소를 다른 곳을 누를 때까지 `:hover`로 둔다.
 * 그래서 카드 하나를 눌러 다녀오면 그 카드만 테두리가 파란 채로 남는다.
 * 사용자가 고른 것도 아니고 지금 상태도 아닌데 화면이 그렇게 말한다.
 *
 * `@media (hover: hover)`로 감싸는 것이 정석이지만, 그러려면 세 파일에
 * 흩어진 hover 규칙 백여 개를 전부 손봐야 한다. 대신 **손가락 기기에서만
 * 쉼 상태를 다시 못 박는다.** 값을 두 곳에 적는 대가를 치르지만, 되돌리는
 * 자리가 이 블록 하나로 모인다.
 * ==================================================================== */
@media (hover: none) {
  .world :is(a.tile, .zone-link-card, .kro-card, .cliq-card):hover {
    border-color: var(--line);
    background: var(--panel);
    transform: none;
  }
  .world :is(.view-tab, .nav-chip):not(.active):hover {
    color: var(--ink-3);
    background: transparent;
  }
  .world :is(.icon-button, .refresh-button):hover {
    color: var(--muted);
    border-color: var(--line);
    background: transparent;
  }
  /* 문장 속 링크는 눌린 뒤 파랗게 남을 이유가 없다. */
  .world .disclose-body a:hover,
  .world .panel-footer a:hover { color: inherit; }
}

/* --- 2. 눌림 — 손가락에 붙는다 ---------------------------------------
 *
 * 120ms. 전환을 **걸지 않는다** — 들어갈 때는 즉시고 놓을 때만 돌아온다.
 * 즉각적인 상태 변화라 `prefers-reduced-motion`과 무관하다(이미 이 저장소가
 * 그렇게 판정했다). 다만 돌아오는 전환은 모션이라 그쪽만 끈다.
 * ==================================================================== */
.world :is(
  button, [role="button"], .view-tab, .nav-chip, .section-rail a,
  .sec-link, .my-board-edit, .pin-toggle, .resume-chip, .cal-step, .cal-jump
):not(:disabled):not([aria-disabled="true"]) {
  transition:
    transform var(--mo-press) var(--mo-ease),
    background-color var(--mo-press) var(--mo-ease),
    border-color var(--mo-press) var(--mo-ease),
    color var(--mo-press) var(--mo-ease);
}
.world :is(
  button, [role="button"], .view-tab, .nav-chip, .section-rail a,
  .sec-link, .my-board-edit, .pin-toggle, .resume-chip, .cal-step, .cal-jump
):not(:disabled):not([aria-disabled="true"]):active {
  transform: scale(.96);
  transition: none;
}
/* 밑줄 컨트롤은 빠진다 — 4% 줄이면 밑줄이 칸보다 짧아져 "선택된 칸"의 폭이
   흔들린다(console.css의 판정). 글자가 잉크로 올라오는 것으로 말한다. */
.world .segmented button:active { transform: none; color: var(--ink); }

/* 면 — 줄어들지 않고 한 단 오른다. */
.world :is(
  a.tile, .zone-link-card, .kro-card, .cliq-card, .metric-card,
  .disclose > summary, .disclosure-brief, .weekend-details > summary
):active {
  background: var(--panel-2);
  border-color: var(--line-strong);
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .world :is(button, [role="button"], .view-tab, .nav-chip, .section-rail a,
             .sec-link, .my-board-edit, .pin-toggle, .resume-chip):active {
    transform: none;
  }
}

/* --- 3. 초점 — 키보드에게도 같은 층이 있다 ----------------------------
 *
 * 링은 이미 이 파일 위쪽에서 준다(`.world :focus-visible`). 빠져 있던 것은
 * **초점이 간 것이 어디인지**가 링 말고는 아무것도 말하지 않는다는 점이다.
 * 마우스가 hover로 받는 것을 키보드도 받아야 한다.
 * ==================================================================== */
.world :is(a.tile, .zone-link-card, .kro-card, .cliq-card):focus-visible {
  border-color: var(--accent);
  background: var(--panel-2);
}
.world :is(.view-tab, .nav-chip, .icon-button, .refresh-button):focus-visible {
  color: var(--ink);
}

/* --- 4. 비활성과 바쁨 --------------------------------------------------
 *
 * 없던 두 상태다. 비활성 버튼이 쉼 상태와 똑같이 생겨서, 눌리지 않는 이유가
 * 화면에 없었다. 색만으로 말하지 않도록 커서도 함께 바꾼다(PRODUCT.md —
 * "색으로만 말하는 상태는 만들지 않는다").
 * ==================================================================== */
.world :is(button, [role="button"], input, select, textarea):disabled,
.world [aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
}
.world :is(button, [role="button"]):disabled:active,
.world [aria-disabled="true"]:active { transform: none; }
.world [aria-busy="true"] { cursor: progress; }

/* --- 5. 주 동작은 엄지에 맞춘다 (폰) ----------------------------------
 *
 * 토스의 컨트롤 램프는 32/38/48/56이고 기본이 **56**이다. 이 화면에서 그
 * 자리에 서는 것은 셋뿐이다 — 종목 고정 · 종목 고정 해제 · 새로 고침.
 * 나머지는 필터·토글·표 안 링크라 각자의 단이 맞다.
 *
 * **24px 바닥을 대체하지 않는다.** 그건 표 안 인라인 링크의 바닥이고
 * (WCAG 2.2 AA 2.5.8), 이건 주 동작의 크기다 — 다른 것을 재는 자다.
 * ==================================================================== */
@media (max-width: 760px) {
  .world .pin-toggle {
    min-height: var(--tap-primary);
    padding-inline: var(--ctl-pad-x);
    border-radius: var(--r-xl);
    font-size: var(--fs-lg);
    font-weight: var(--ctl-fw);
  }
}
/* **홈의 `종목 고정`은 뺐다.** 처음엔 같이 올렸는데, `PRODUCT.md`가 그 단추를
   "24시간 시장 제목 옆의 **작은** 종목 고정 버튼"이라고 못 박아 두었다
   (2026-09-05 확정). `segment.css`도 운영자가 그 자리를 두 번 옮겼다 되돌린
   기록을 들고 있다. 지시서의 "주 동작 56px"은 일반 규칙이고, 이건 화면을 보고
   내린 개별 판정이다 — 개별 판정이 이긴다.

   실측으로도 그 규칙은 안 먹고 있었다: `.page-landing .my-board-edit`(0,2,0)와
   `.world :is(.my-board-edit, …)`(0,2,0)이 특정도가 같아 뒤에 실리는
   `segment.css`가 이겼다. 억지로 이기게 만드는 대신 뺀다.

   `/stock/{코드}`·`/asset/{id}`·`/crypto/{심벌}`의 `.pin-toggle`은 그 화면의
   유일한 동작이라 56에 선다(실측 `/stock/005930` 폰: 56×59). */

/* --- 6. 제목 램프 — 데스크톱은 다른 구성이다 --------------------------
 *
 * 지금 데스크톱이 나쁜 이유는 폰 화면을 늘려 놓았기 때문이다. 1288px 칸에서
 * 섹션 제목이 22px로 서면 그 화면에는 위계가 없다 — 열두 구역이 같은 무게로
 * 선다는 말이 이 뜻이다.
 *
 * `--t-*`는 `clamp`라 **폰에서는 지금 값 그대로**고 넓어질수록 토스 값에
 * 닿는다(도달: h1 36 @692px · h2 30 @883px). 그래서 이 규칙은 폰 화면을
 * 한 픽셀도 바꾸지 않는다.
 * ==================================================================== */
.world .console-head h1 {
  font-size: var(--t-h1);
  line-height: var(--t-lh-heading);
  font-weight: var(--t-w-h1);
}
.world .console-section > header :is(h1, h2),
.world .weekend-details > summary h2 {
  font-size: var(--t-h2);
  line-height: var(--t-lh-heading);
  font-weight: var(--t-w-h);
  letter-spacing: -.02em;
}
/* 제목이 커지면 옆에 선 설명 줄도 한 단 올라야 짝으로 읽힌다. 값·라벨의
   램프(12·13)는 건드리지 않는다 — 이건 문장이다. */
@media (min-width: 1080px) {
  .world .console-section > header .sec-note,
  .world .console-head .console-sub { font-size: var(--t-body); }
}

/* 구역과 구역 **사이**. 폰에서는 `world.css` 위쪽이 이미 32px을 준다.
   넓은 화면에서는 제목이 커진 만큼 사이도 벌어져야 같은 리듬이 된다. */
@media (min-width: 1080px) {
  .world .console-section { margin-top: 72px; }
  .world .console-section > header { margin-bottom: var(--sp-5); }
  .world main > .console-section:first-child { margin-top: 0; }
}

/* --- 7. 읽는 줄은 묶는다 ----------------------------------------------
 *
 * `--measure`(68ch)가 토큰으로 서 있는데 네 곳에서만 쓰였다. 1288px 칸에서
 * 12~15px 문장이 끝까지 늘어나면 한 줄이 200자를 넘고, 눈이 다음 줄의 첫
 * 글자를 못 찾는다. 계약상 필수인 저작자 표기가 그 상태였다.
 *
 * 표·차트·값에는 걸지 않는다 — 넓은 칸을 실제로 써야 하는 것들이다.
 * ==================================================================== */
.world :is(
  .console-head .console-sub, .section-copy, .intro-copy,
  .interpretation-note, .stress-method, .stress-disclaimer, .sentiment-note,
  .disclose-body p, .disclose-body li, .metric-description
) { max-width: var(--measure); }

/* --- 8. 화면이 바뀌는 방식 --------------------------------------------
 *
 * 목록 → 상세가 **페이지 점프**라 화면이 한 번 하얗게 끊긴다. 이 사이트에
 * 라우터가 없어서(빌드 단계도 없다) 시트를 흉내 내려면 SPA를 새로 세워야
 * 하는데, 그건 하룻밤에 안전하게 할 수 있는 크기가 아니다.
 *
 * 대신 브라우저가 이미 갖고 있는 것을 쓴다 — 문서 간 View Transition은
 * CSS 한 줄이고, 지원하지 않는 브라우저는 지금처럼 그냥 이동한다(점진적
 * 향상이라 되돌릴 위험이 없다). 1순위 사용자가 오는 곳이 안드로이드 크롬과
 * 그것을 감싼 TWA다.
 *
 * 모션을 원치 않는 사람에게는 끈다 — 그때는 전환이 아예 없다.
 * ==================================================================== */
/* **껐다 (운영자 제보 2026-09-10).**
 *
 * 카카오톡 인앱 브라우저에서 링크로 들어온 뒤 하단 내비로 다른 탭을 누르면
 * **검은 화면에서 멈췄다.** 정적 마스트헤드까지 안 보였는데, 그 마스트헤드는
 * 서버가 보내는 HTML에 있다 — JS 예외로는 그렇게 안 된다. 문서가 안 그려진
 * 것이고, 문서 간 전환이 남긴 빈 스냅샷과 정확히 맞는다.
 *
 * 위 주석은 "지원하지 않는 브라우저는 그냥 이동한다(되돌릴 위험이 없다)"고
 * 적었다. **그 가정이 틀렸다.** 위험은 "지원 안 함"이 아니라 "반쯤 지원하고
 * 버그가 있음"이었고, 하필 그게 우리 유입이 실제로 지나가는 창구다(등록부의
 * 유입 실측: `kakaotalk-scrap`·UA의 ` wv)`).
 *
 * 최신 크롬에서도 이 전환은 `Transition was skipped`를 예외로 던진다(실측
 * 2026-09-10, 카카오톡 UA로 `/` → `/kr`). 거기서는 그냥 넘어가지만, 얻는 것이
 * 크로스페이드 하나인데 잃을 수 있는 것이 **들어온 사람이 못 움직이는 것**이다.
 *
 * 다시 켜려면 카카오톡 인앱 브라우저 실기기에서 왕복을 확인한 뒤에 켠다.
 * 규칙은 그대로 두되 주석으로 남긴다 — 지우면 다음 사람이 같은 이유로 다시
 * 넣는다.
 *
 *   @view-transition { navigation: auto; }
 *   ::view-transition-old(root),
 *   ::view-transition-new(root) {
 *     animation-duration: var(--mo-settle);
 *     animation-timing-function: var(--mo-ease);
 *   }
 */

/* --- 9. `.is-pressed` — `:active`가 못 놓는 손 --------------------------
 *
 * `motion.js`가 붙이는 클래스다. `:active`와 **같은 꼴**을 주되, 푸는 쪽을
 * 자바스크립트가 맡는다 — 크롬은 누른 채 요소 밖으로 끌고 나가면 `:active`를
 * 유지하고, 그 상황이 정확히 "손가락으로 스크롤을 시작할 때"다. 목록을
 * 넘기는 동안 카드 하나가 눌린 채 따라오는 것이 그 소리였다.
 *
 * 두 곳에 같은 목록이 적히는 대가를 치른다. 그래도 이름이 같아서 한쪽만
 * 고치기 어렵고, 여기 없는 부품은 `:active`만으로도 눌린다 — 잃는 것은
 * 잔상을 푸는 손뿐이다.
 * ==================================================================== */
.world :is(
  button, [role="button"], .view-tab, .nav-chip, .section-rail a,
  .sec-link, .my-board-edit, .pin-toggle, .resume-chip, .cal-step, .cal-jump
).is-pressed:not(:disabled):not([aria-disabled="true"]) {
  transform: scale(.96);
  transition: none;
}
.world .segmented button.is-pressed { transform: none; color: var(--ink); }
.world :is(
  a.tile, .zone-link-card, .kro-card, .cliq-card, .metric-card,
  .disclose > summary, .disclosure-brief, .weekend-details > summary
).is-pressed {
  background: var(--panel-2);
  border-color: var(--line-strong);
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .world .is-pressed { transform: none; }
}

/* --- 10. 같은 줄, 같은 높이 — `/kr` 카드가 자로 짚힌 자리 ---------------
 *
 * 기준선에서 자가 짚은 결함은 사이트 전체에 이것 하나였다(두 뷰포트 모두):
 *
 *     ALIGN  #kro-grid > .kro-card > .kro-vs — 같은 자리[2]의 y가 18.8px 어긋남
 *
 * 원인을 재서 찾았다. `console.css`가 카드의 일곱 자리를 부모 격자의 줄에
 * 못 박아 두었는데(`grid-row: span 7`), `#kro-grid`의 카드는 그중 **셋에서
 * 다섯만** 쓴다 — 머리 · 값 · [종가 대비] · [프리미엄] · [배지].
 * `monitor.js`의 `renderKro`가 만드는 자식이 그게 전부다.
 *
 * 어긋남: 종가 대비(`.kro-vs-ref`)는 3번 줄, 프리미엄(`.kro-vs`)은 4번 줄에
 * 박혀 있다. 한 줄에 두 종류가 섞이면 한쪽 카드의 세 번째 줄만 한 트랙
 * 아래에서 시작한다. 실측(1440): 트랙3 6.84 + 줄간격 12 = **18.84px**.
 * 자가 말한 값과 같다.
 *
 * 처방은 **자리를 옮기는 것이 아니라 조건을 다는 것**이다. 둘 다 가진 카드는
 * 지금 순서가 맞다(종가 대비가 위, 프리미엄이 아래). 하나만 가진 카드에서만
 * 그것이 첫 자리에 선다. `:has()`가 그 조건을 그대로 쓴다.
 *
 * 남는 트랙도 함께 걷는다. 일곱 중 다섯만 쓰므로 두 트랙과 그 줄간격이
 * 카드 바닥에 빈칸으로 남아 있었다(실측: 카드 168px 중 **59px이 꼬리**).
 * 운영자가 "아래 공백이 저렇게 많이 남는다"고 한 것이 이 모양이다.
 *
 * `span`을 줄이는 것은 **자식이 그 span을 안 넘을 때만** 안전하다 — 넘는
 * 자식은 암묵 트랙을 얻고 그 트랙은 아래 줄 카드 위로 자란다(2026-09-08
 * 실측: span 7 → 2에서 /kr 97 → 82). 여기서는 다섯이 최대이므로 다섯이 맞다.
 * ==================================================================== */
@supports (grid-template-rows: subgrid) {
  /* 여섯이다 — 머리 · 값 · 종가 대비 · 프리미엄 · 추이선 · 배지.
     `console.css`가 이미 그 여섯을 1~6번 줄에 박아 두었으므로 `span`만 맞춘다.
     일곱 중 마지막(`.kro-meta`)은 김프 격자에만 있고 여기엔 없다.

     **2026-09-09 밤에 다섯으로 잡았다가 여섯으로 고쳤다.** 그 사이 main에
     `#418`이 들어와 이 카드에 30일 추이선(`.tile-spark`)이 붙었다 — 다섯으로
     두면 추이선이 span을 넘어 **암묵 트랙**을 얻고, 그 트랙은 아래 줄 카드
     위로 자란다(2026-09-08 실측: span을 넘긴 자식 때문에 /kr이 97 → 82).
     `span`을 줄이는 처방은 **자식 수가 바뀌면 다시 세야 한다.** */
  .world #kro-grid > .kro-card { grid-row: span 6; }
  /* 종가 대비 줄이 없는 카드에서는 프리미엄 줄이 그 자리에 선다. */
  .world #kro-grid > .kro-card:not(:has(> .kro-vs-ref)) > .kro-vs { grid-row: 3; }
}

/* ======================================================================
 * V3 · 모바일 — 손가락이 만지는 층 (2026-09-09)
 *
 * 지시서 §5-1의 다섯 중 셋은 이 저장소가 이미 하고 있었다(자리가 안 움직이는
 * `.booting` 예약, 안전영역, 하단 탭). 안 하고 있던 것은 **손가락이 화면에
 * 닿는 순간 브라우저가 끼어드는 자리들**이다 — 회색 상자가 번쩍이고, 길게
 * 누르면 글자가 잡히고, 표 끝에 닿으면 페이지가 같이 흔들린다.
 *
 * 이것들은 크기나 색이 아니라 **웹 브라우저의 기본값**이고, 앱에는 없다.
 * ====================================================================== */

/* --- 1. 브라우저의 회색 상자를 우리 눌림으로 갈아 끼운다 ---------------
 *
 * `monitor.css`가 `button, a, select`에는 이미 껐다. 빠진 것은 **`summary`와
 * `[role=button]`**이다 — 고지 접기 줄과 JS가 만든 컨트롤이 그쪽이다.
 * 안드로이드는 거기에 반투명 회색 사각형을 그리는데, 사각형이라 둥근 판
 * 모서리 밖으로 삐죽 나온다(이 저장소가 `POKE`라고 부르는 그 모양이다).
 *
 * 끄기만 하면 안 된다 — 끄고 나면 아무 반응이 없어야 하는데, 그 자리는 §2의
 * 눌림이 이미 채우고 있다. 브라우저 것을 우리 것으로 **바꾸는** 것이지
 * 없애는 것이 아니다.
 * ==================================================================== */
.world :is(summary, [role="button"], label) {
  -webkit-tap-highlight-color: transparent;
}

/* --- 2. 길게 눌러도 글자가 잡히지 않는다 ------------------------------
 *
 * 컨트롤을 길게 누르면 안드로이드가 글자를 선택하고 확대경과 메뉴를 띄운다.
 * 눌림 애니메이션이 그 위에서 도는 꼴이라 "잘못 눌렀다"처럼 읽힌다.
 *
 * **값과 표에는 걸지 않는다.** 이 화면에 오는 사람은 숫자를 복사한다 —
 * 종목코드, 가격, 공시 제목. 그걸 못 집게 만드는 것은 앱 흉내가 아니라 손해다.
 * 컨트롤(버튼·탭·내비)에만 건다.
 * ==================================================================== */
@media (hover: none) {
  .world :is(
    button, [role="button"], .view-tab, .nav-chip, .section-rail a,
    .segmented button, .cal-step, .cal-jump, .my-board-edit, .pin-toggle
  ) { user-select: none; -webkit-user-select: none; }
}

/* --- 3. 표 끝에서 페이지가 같이 흔들리지 않는다 ------------------------
 *
 * 가로로 흐르는 상자를 끝까지 밀면 그 스크롤이 **부모로 새어** 페이지가
 * 통째로 흔들린다. 히트맵에서 같은 종류를 이미 한 번 고쳤다(#407 —
 * "히트맵을 끌면 페이지가 같이 스크롤됐다"). 그때는 `touch-action`이었고
 * 여기는 연쇄를 끊는 쪽이다.
 * ==================================================================== */
.world :is(.table-scroll, .tape, .pulse-chips, .chart-toolbar, .feed-filter) {
  overscroll-behavior-x: contain;
}

/* --- 4. 브라우저가 글자를 제멋대로 키우지 않는다 -----------------------
 *
 * 안드로이드 크롬의 폰트 부스팅은 좁은 칸의 글자를 자기 판단으로 키운다.
 * 여기서는 밀도가 제품의 성격이고 크기 램프가 계약이라, 그 판단을 브라우저에
 * 맡기면 잰 값이 실기기에서 달라진다.
 * ==================================================================== */
.world { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* ======================================================================
 * V4 · PC — 폰을 늘려 놓은 자리를 되돌린다 (2026-09-09)
 *
 * 폰에서 통한 처방을 그대로 옮기지 않는다 — 이 저장소는 lane에서 그 실수를
 * 이미 겪었다("처방을 lane 사이에 그대로 옮기지 마라"). 여기 적힌 것은
 * 전부 `min-width` 안에 있고, 폰 화면은 한 픽셀도 안 바뀐다.
 * ====================================================================== */

/* --- 1. 상단 내비 — 마우스가 겨냥하는 크기 ----------------------------
 *
 * `.view-tab`이 13px/600에 좌우 12px이다. 폰 하단 알약에서는 맞는 크기지만,
 * 1288px 칸 맨 위에 서는 **이 제품의 1차 내비**로는 각주만 하다.
 * 토스의 제품 내비는 15/600 근처다.
 *
 * 마우스에는 44px 같은 손가락 바닥이 없다 — 겨냥은 정확하다. 그래서 크기가
 * 아니라 **읽히는 무게**를 위해 올린다.
 * ==================================================================== */
@media (min-width: 1080px) {
  .world .view-tab { font-size: var(--fs-md); padding-inline: var(--sp-4); }
  .world .nav-chip { font-size: var(--t-body-sm); }
}

/* --- 2. 값은 넓은 칸을 실제로 쓴다 -------------------------------------
 *
 * 카드가 3열로 서는 폭에서 카드 하나가 421px인데 그 안의 값 줄은 220px쯤에서
 * 끝난다. 남는 200px은 **글자를 키워서** 쓰는 것이 아니라(값 램프는 계약이다)
 * 카드가 덜 비어 보이게 세로를 줄여서 쓴다 — 이미 `#kro-grid`의 남는 트랙을
 * 걷어 168 → 144px가 됐다(§10).
 *
 * 열 수는 **바꾸지 않았다.** 4열이 칸을 더 쓰지만 `/kr`의 카드 여섯이
 * 4 + 2로 갈려 3 + 3보다 나쁘게 앉는다. 운영자가 이 격자를 여러 번 손봤으므로
 * 밤에 혼자 뒤집을 자리가 아니다 — `.impeccable/NIGHT_QUESTIONS.md`에 적었다.
 * ==================================================================== */

/* --- 3. 초점 이동이 보인다 --------------------------------------------
 *
 * 데스크톱에는 키보드로 움직이는 사람이 있다. `Tab`으로 넘어갈 때 링만 뜨고
 * 그 줄이 어디인지 안 보이면 긴 표에서 자리를 잃는다. 마우스가 hover로 받는
 * 것을 키보드도 받게 한다 — §3에서 카드에 준 것과 같은 처방을 표 줄에도.
 * ==================================================================== */
@media (hover: hover) {
  .world :is(.accessible-table, .kridx-table) tbody tr:focus-within {
    background: color-mix(in srgb, var(--ink) 5%, transparent);
  }
}

/* --- 4. 판 꼬리말에는 `--measure`를 걸지 않는다 (2026-09-09 되돌림) ------
 *
 * 여기 `.panel-footer p · .kro-footer p · .attribution p · .attribution li`에
 * `max-width: var(--measure)`가 있었다. 1288px에서 12~13px 한 줄이 238자가
 * 되는 것을 묶으려던 것이다. **운영자가 아침에 깨진 것을 짚었다.**
 *
 * `#attribution`은 문장과 그 약관 링크가 **짝으로** 읽혀야 하는 블록인데,
 * 문장이 오른쪽 끝으로 밀려 링크는 왼쪽 열, 문장은 오른쪽 열처럼 갈렸다.
 * 실측 1440px `/us`:
 *
 *     main    .attribution p   x=17   w=1254  ml=0
 *     이 규칙 .attribution p   x=785  w=486   ml=767.9   ← 오른쪽 끝
 *     main    .panel-footer p  x=0    w=1254
 *     이 규칙 .panel-footer p  x=471  w=527               ← 가운데로
 *     블록 높이 735 → 995px
 *
 * 원인은 **남의 `margin-left: auto`가 후손까지 걸려 있던 것**이다.
 * `monitor.css`의 `.site-footer p { margin-left: auto }`는 꼬리말의 제 문단
 * 하나를 오른쪽으로 밀려고 둔 규칙인데(2026-09-05 판정) 선택자가 후손을 잡는다.
 * 그동안은 문단이 100% 폭이라 `auto`가 밀 자리가 없어 보이지 않았고,
 * `max-width`를 씌우는 순간 밀 자리가 생겼다.
 *
 * **자는 못 봤다**(`/us` pc1440 = 100.0). `GAP`은 블록 부모의 블록 형제만 보고
 * `ALIGN`은 같은 줄 카드의 같은 자리만 본다 — 짝이 깨진 것을 재는 규칙은 없다.
 *
 * 다시 하려면 폭을 씌우기 전에 **그 자리의 `margin`부터 확인할 것.** 그리고
 * 긴 줄은 제보된 결함이 아니었다 — 계약상 필수인 표기 블록을 읽기 어렵게
 * 만드는 대가를 치를 값이 아니다.
 * ==================================================================== */

/* ======================================================================
 * V5 · 표 — 값은 안 끊고 글은 끊는다 (2026-09-09)
 *
 * 자에 규칙을 하나 더하고 나서 보인 것이다(`WIDE`). 실측 390px:
 *
 *     /score   표 1,414px · 보이는 칸 364px → **3.9배**
 *     /us      1,127 / 330 → 3.4배
 *     /bio     980 / 330 → 3.0배 (여섯 곳)
 *     /crypto  936 / 330 → 2.8배
 *     /kr      928 / 330 → 2.8배 (여섯 곳)
 *
 * `/score`는 이 제품의 본선(L1 공시 스코어보드)인데, 폰에서 한 화면에 서는
 * 것이 종목 이름과 배지뿐이고 **점수가 하나도 안 보인다.** 값이 없는 것과
 * 같다 — "읽히지 않으면 없는 것이다"(PRODUCT.md 원칙 5).
 *
 * 원인은 선언 하나다:
 *
 *     .accessible-table th, .accessible-table td { … white-space: nowrap; }
 *
 * 숫자에는 맞다. `43,000원`이 두 줄로 끊기면 그건 다른 값처럼 읽힌다. 그런데
 * 같은 선언이 **회사 이름·보고자·공시 제목**에도 걸려 있었다. 글은 끊겨도
 * 같은 글이고, 안 끊기면 표가 화면의 네 배가 된다.
 *
 * 그래서 역할로 가른다 — `.num`은 그대로 두고 나머지만 접는다. 셀렉터를
 * 하나씩 세지 않는 이유는 앞과 같다: 표가 열몇 개고 클래스가 제각각인데,
 * `.num`은 **이미 이 저장소가 "이 칸은 숫자다"라고 적어 둔 표시**다.
 *
 * `max-width`는 접히는 폭을 정한다. 없으면 긴 이름 하나가 칸을 통째로 먹어
 * 접어도 안 좁아진다(실측: 종목 237px → 114px). 표 레이아웃이 `auto`라
 * 명세상 `max-width`는 힌트지만, 크롬은 그것을 선호폭 계산에 쓴다.
 *
 * **가로 스크롤을 없애는 것이 목표가 아니다.** 표는 원래 넓고, 접으면 열이
 * 무너져 비교가 안 된다(이 파일이 이미 그렇게 판정했다). 목표는 **정도**다 —
 * 스크롤이 탐색이 되게, 미로가 되지 않게.
 * ====================================================================== */
.world :is(.accessible-table, .kridx-table, .score-table, .bio-table, .crypto-table)
  :is(th, td):not(.num):not(.range) {
  white-space: normal;
}
/* **캡은 폰에만.** 처음엔 전 폭에 걸었다가 되돌렸다 — 데스크톱에서 `/score`
   표가 1,288px 판 안에서 876px이 되어 오른쪽에 400px이 비었다(채움 0.68).
   이 저장소가 2026-09-06에 "좁은 표가 넓은 상자 안에 떠 있다"로 이미 한 번
   겪은 모양이고, 그때도 자는 아무 말이 없었다.

   좁히는 일은 **폰의 문제**였다. 데스크톱에는 애초에 폭 문제가 없었고
   (`/score`만 1.13배로 살짝 흘렀다), 거기서 칸을 조이면 얻는 것 없이
   빈자리만 생긴다. */
/* 표 머리는 원래 접히라고 만든 자리다 — `monitor.css`가 그 이유로 줄높이를
   1.35로 두었는데("표 머리는 줄바꿈이 일어나는 자리다"), 같은 규칙의
   `white-space: nowrap`이 그것을 막고 있었다. 글로 쓴 의도와 실제 배선이
   갈린 자리다. */
.world :is(.accessible-table, .kridx-table) thead th { white-space: normal; }

@media (max-width: 760px) {
  .world :is(.accessible-table, .kridx-table, .score-table, .bio-table, .crypto-table)
    :is(th, td):not(.num):not(.range) {
    max-width: 9.5em;
  }
}

/* --- V5-2. 값 아래 붙는 작은 줄은 **아래**에 붙는다 ---------------------
 *
 * `.weekend-table`은 이미 그렇게 하고 있었다(`td small { display: block }`).
 * 나머지 표는 안 해서 `43,000원2026-06-05`이 한 줄로 서고, 그 한 줄이 열의
 * 폭을 정했다 — `/score`의 기준가 열이 **190px**이었다.
 *
 * 값이 주고 작은 줄이 근거다. 근거는 값 아래에 선다 — 옆에 서면 둘이 같은
 * 값의 두 부분처럼 읽히고, 실제로 `43,000원2026-06-05`은 그렇게 읽혔다.
 *
 * `tbody`로 좁힌다. 머리의 `현재 <small>참고</small>`는 라벨 옆에 붙는 단서라
 * 아래로 내리면 머리가 두 줄이 된다.
 * ==================================================================== */
.world :is(.accessible-table, .kridx-table, .score-table, .crypto-table)
  tbody :is(td, th).num small { display: block; }

/* --- V5-3. 폰에서는 어디서든 끊는다 ------------------------------------
 *
 * `tokens.css`가 사이트 전체에 `word-break: keep-all`을 건다 — 한글을 음절
 * 사이에서 끊지 않기 위해서고, 문장에는 그게 맞다. 그런데 표 안에는 **띄어쓰기가
 * 없는 한 낱말**이 온다: `휴달비정80밀리그램(아질사르탄메독소밀칼륨)`.
 * `keep-all`에게 그건 한 단어라 어디서도 안 끊기고, 자동 배치 표에서는 그
 * 낱말 하나가 열의 폭을 정한다.
 *
 * `overflow-wrap: anywhere`는 `break-word`와 달리 **최소 폭 계산에도** 들어간다.
 * 그래서 표가 실제로 좁아진다. 폰에서만 건다 — 넓은 화면에서는 끊을 이유가 없다.
 * ==================================================================== */
/* **접는 규칙은 좁히는 규칙과 같은 폭에 걸어야 한다.**
 *
 * 처음엔 접는 쪽만 폰에 걸고 캡은 전 폭에 걸었다. 그 틈에서 데스크톱 칸이
 * 좁아진 채로 내용이 접히지 못해 **밖으로 샜다** — 자가 `SPILL` 90건으로
 * 잡았다(`/score` 84 · `/bio` 6, 768·1024·1440 전부). 지금은 캡도 폰에만
 * 있으니 둘이 같은 조건에 선다.
 *
 * 접는 쪽은 전 폭에 남긴다. 데스크톱에서는 칸이 넓어 접힐 일이 없고, 있다면
 * 그건 정말 긴 낱말이라 접히는 편이 맞다(`.bio-table`은 `table-layout: fixed`
 * 라 폭이 못 박혀 있어 실제로 그 경우다 — 실측 1440px에서 두 칸이 샜다). */
.world :is(.accessible-table, .kridx-table, .score-table, .bio-table, .crypto-table)
  :is(th, td):not(.num):not(.range) {
  word-break: normal;
  overflow-wrap: anywhere;
  /* **바닥이 없으면 열이 사라진다.** `anywhere`는 최소 폭을 글자 하나까지
     내리므로, 자동 배치 표가 그 열을 48px까지 조인다. 그러면 이름이
     한 줄에 두 글자씩 일곱 줄로 서서 행 높이가 159px이 됐다(실측).
     6em을 깔면 폭은 2.05 → 2.12배로 조금 늘고 **행 높이는 159 → 102**다.
     옆으로 조금 더 미는 대신 세로로 훨씬 덜 민다.

     캡과 짝이라 이것도 폰에만 있다 — 아래 미디어 블록. */
}
@media (max-width: 760px) {
  .world :is(.accessible-table, .kridx-table, .score-table, .bio-table, .crypto-table)
    :is(th, td):not(.num):not(.range) { min-width: 6em; }
  /* `.bio-table`만 `table-layout: fixed` + `min-width: 980px`이라 위 규칙이
     폭을 못 바꾼다 — 이미 못 박아 두었기 때문이다. 폰에서 그 못을 낮춘다.
     실측 390px: 2.97배 → **2.00배**, 그러면서 넘치는 셀은 3 → **0**이다
     (좁혔는데 잘림이 줄었다 — 끊을 수 있게 되었기 때문이다).
     데스크톱에서는 980px이 칸 안에 들어가므로 그대로 둔다. */
  .world .bio-table { min-width: 660px; }
}

/* --- V5-4. 판 꼬리말의 출처 링크가 카드마다 다른 높이에 섰다 -------------
 *
 * 자가 768·1024에서만 짚었다(`/us`):
 *
 *     ALIGN  .metric-grid > .metric-card > footer > a — 같은 자리[6][0]이
 *            4.9 · 13.8 · 23.5px 어긋남
 *
 * 카드 바깥은 격자가 맞춰 놓았다(실측: 같은 줄 두 장 다 554px, 꼬리말도 둘 다
 * y=450). 어긋난 것은 **꼬리말 안**이다 — `flex-wrap: wrap` + `align-items:
 * center`라, 출처 문장의 길이에 따라 줄이 몇 개로 접히느냐가 달라지고 그러면
 * 가운데 정렬의 기준선이 달라진다. "카드는 밖에서 맞는데 그 안의 목록이 다시
 * 어긋난다"는 이 저장소의 함정 그대로다.
 *
 * `flex-start`로 세우면 첫 줄의 위가 모든 카드에서 같은 자리다.
 * 실측 41장: 11 · 16 · 25 · 35이 섞여 있던 것이 전부 11로 모였다.
 * ==================================================================== */
.world .metric-card > footer { align-items: flex-start; }

/* --- V5-5. 눌림은 즉시 도착한다 ----------------------------------------
 *
 * §2가 컨트롤에는 `transition: none`을 줬는데 **면에는 안 줬다.** 그래서
 * 카드를 누르면 `.tile`이 원래 갖고 있던 `transition: background .15s`를 타고
 * 150ms 뒤에야 눌린 색이 도착한다(실측: 0ms 시점 `--panel`, 400ms `--panel-2`).
 * 손가락에 붙어야 하는 반응이 한 박자 늦으면 그건 반응이 아니라 잔상이다.
 *
 * 들어갈 때만 끈다 — 놓을 때는 원래 전환을 타고 돌아온다.
 * ==================================================================== */
.world :is(
  a.tile, .zone-link-card, .kro-card, .cliq-card, .metric-card,
  .disclose > summary, .disclosure-brief, .weekend-details > summary
):is(:active, .is-pressed) { transition: none; }

/* --- V5-6. 360px — 가장 좁은 폰에서 한 단 더 조인다 --------------------
 *
 * 운영자 지시의 세 폭 중 가장 좁은 것이 360이다. 거기서는 `--sp-3`(12) 좌우
 * 여백과 6em 바닥이 함께 서면 표가 다시 2.5배를 넘는다(실측: `/kr` 2.59 ·
 * `/score` 2.71).
 *
 * 둘을 같이 내린다 — 바닥을 5em으로, 셀 여백을 8px로. **따로 하면 나빠진다**:
 * 바닥만 내리면 열이 좁아진 만큼 글이 더 접혀 행 높이가 107 → 127px로 늘고
 * (`/kr`), 4em까지 내리면 188px이 된다. 여백까지 함께 내리면 폭은 줄고 행
 * 높이는 그대로다.
 *
 *     /kr    2.59 → 2.37배 · 행 107 그대로
 *     /score 2.71 → 2.49배 · 행 102 그대로
 *
 * 8px은 이 저장소의 눈금 위의 값이다(`--sp-2`). 밀도가 이 제품의 성격이라는
 * 규칙과 같은 방향이고, 여기서만 한 칸 더 간다.
 * ==================================================================== */
@media (max-width: 400px) {
  .world :is(.accessible-table, .kridx-table, .score-table, .crypto-table)
    :is(th, td):not(.num):not(.range) { min-width: 5em; }
  .world :is(.accessible-table, .kridx-table) :is(th, td) {
    padding-inline: var(--sp-2);
  }
}

/* --- V5-7. 좁힌 칸 밖으로 샌 알약 -------------------------------------
 *
 * 표를 좁힌 처방이 만든 결함이다. `결과 도달 2026-09-04` 알약은
 * `white-space: nowrap`이라 149px인데, 종목 칸을 113px로 조이자 **칸 밖으로
 * 나가 옆 칸의 보고자 이름을 덮었다** — 실측 390px `/score`에서 스물넷.
 * 자에 `SPILL`을 더해서 잡았고(잘린 것보다 나쁘다: 두 칸의 글자가 겹쳐 둘 다
 * 못 읽는다), 그 자리에서 함께 고친다.
 *
 * **날짜를 떼지 않는다.** 그 날짜가 "왜 이 줄의 값이 더 안 움직이나"에 답하는
 * 정보다 — 좁은 화면에서 정보를 줄이는 쪽으로는 안 간다. 대신 알약이 접힌다.
 * 두 줄짜리 알약은 예쁘지 않지만, 옆 칸을 덮는 것보다 낫다.
 * ==================================================================== */
/* 접히되 **어절 단위로**. `white-space: normal`만 주면 위 규칙이 건
   `overflow-wrap: anywhere`를 물려받아 글자 하나씩 끊긴다 — 실측: 알약이
   35×166px이 되고 행 높이가 92 → **223px**이 됐다. **자 점수는 100 그대로였다.**
   자가 짚지 못하는 종류의 악화라, 눈으로 보고 되돌린 자리다.

   폰 전용이 아니다 — 데스크톱에서도 칸이 `max-width`로 좁혀져 있어서 알약이
   9px씩 밖으로 샜다(실측 768·1024·1440에서 28칸씩). */
.world :is(.score-landed, .score-arriving) {
  display: block; width: max-content; max-width: 100%;
  margin: 3px 0 0;
  white-space: normal; overflow-wrap: normal; word-break: keep-all;
}
.world :is(.score-new, .score-halted) {
  white-space: normal; overflow-wrap: normal; word-break: keep-all;
}
/* 실측(360 · 390 · 412px): 알약 93×40 · 행 높이 92 · 칸 밖으로 샌 것 0.
   표 폭은 1.79 → 1.94배로 조금 늘었다 — 옆으로 조금 더 미는 대신 세로로
   131px을 덜 민다. 같은 저울을 §V5-6에서도 썼다. */

/* --- V5-8. 이미 판을 거의 채우는 표는 마저 채운다 (데스크톱) -------------
 *
 * `.table-scroll`은 `max-width: max-content`라 상자가 표를 감싼다 — 좁은 표가
 * 넓은 상자 안에 떠서 오른쪽 스크롤 표시만 멀리 서던 것을 2026-09-06에 그렇게
 * 고쳤다. 그 판정은 그대로 맞다.
 *
 * 다만 `/score`의 표는 **원래 판보다 넓었다**(1,421px 대 1,256px, 1.13배로 살짝
 * 흘렀다). 폰용으로 좁히고 나니 데스크톱에서 982px이 되어 판 안에 306px이
 * 남았다. 그 표는 늘려서 채우는 것이 맞다 — 9열짜리 데이터 표이고, 늘리면
 * 열마다 143px씩 갖는다.
 *
 * **판의 3분의 2도 안 쓰는 표는 늘리지 않는다.** `/crypto`의 공포·탐욕 표는
 * 195px이고 `/stock`의 재무 표는 463px이다. 그걸 1,288px로 펴면 열이 흩어져
 * 오히려 못 읽는다 — 2026-09-06 판정이 지키려던 것이 그것이다. 그래서 규칙이
 * 아니라 **이름**으로 적는다.
 *
 * 실측 1440px: 판 1,288 · 표 876 → **1,286**. 행 높이 84 → 66. 샌 칸 0.
 * ==================================================================== */
@media (min-width: 1080px) {
  .world .score-page .table-scroll { max-width: none; }
  .world .score-table { width: 100%; }
}

/* --- V3-5. 하단 내비는 아래로 읽는 동안 비켜 준다 (#427 ①) --------------
 *
 * 테스터 제보(2026-09-09): 폰 하단 내비가 거슬린다. 되물어 보니 **늘 떠 있는
 * 것**과 **면이 단단한 것**이었고, 크기는 아니었다 — 그래서 62px은 그대로 두고
 * 떠 있는 시간만 줄인다.
 *
 * **자리는 안 움직인다.** 본문 아래 여백(`--pagebar-h`를 읽는 86px)은 그대로다.
 * 바는 `transform`으로만 나가므로 리플로우가 없고, 돌아올 자리도 그대로 있다.
 * 여백을 같이 줄이면 스크롤하는 내내 내용이 위아래로 튄다 — 이 저장소가 세 번
 * 고친 자리다.
 *
 * 반투명은 하지 않았다. 실측(#427): 블러 없이 면만 낮추면 바 아래 글자가 라벨
 * 위에 겹치고, 블러는 CPU 4배 조임부터 프레임의 8%가 33ms를 넘는다(6배에서
 * 최악 249.9ms). 숨으면 면이 안 보이므로 이것이 그쪽 불만도 함께 던다.
 * ==================================================================== */
@media (max-width: 760px) {
  .world .view-switch {
    transition: transform var(--mo-settle) var(--mo-ease);
    will-change: transform;
  }
  /* 나가는 거리는 바 높이 + 가장자리 여백 + 안전영역. 넉넉히 밀어야 모서리가
     화면에 걸리지 않는다. */
  .world .view-switch.is-tucked {
    transform: translateY(calc(var(--pagebar-h) + var(--pagebar-inset) * 2
                               + env(safe-area-inset-bottom, 0px)));
  }
}
/* 모션을 원치 않는 사람에게는 **없음**이다 — 짧게가 아니다. */
@media (prefers-reduced-motion: reduce) {
  .world .view-switch { transition: none; }
  .world .view-switch.is-tucked { transform: none; }
}
