world-map.scss 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // ─────────────────────────────────────────────────────────────
  2. // 메인 세계지도 (WorldMarketMap) — 주요국 증시지수 핀
  3. // 색은 토큰/반투명 리터럴만 사용(라이트·다크 양립). 등락색은 --price-up/down/flat(상승 적/하락 청)
  4. // ─────────────────────────────────────────────────────────────
  5. .world-map {
  6. // 지도 전용 반투명 톤 — 패널 배경 위에 얹혀 양 테마에서 자연스럽게 블렌딩
  7. --az-map-ocean-1: rgba(46, 110, 190, 0.20);
  8. --az-map-ocean-2: rgba(46, 110, 190, 0.04);
  9. --az-map-land: rgba(140, 158, 180, 0.32);
  10. --az-map-land-edge: rgba(150, 168, 190, 0.55);
  11. --az-map-grid: rgba(130, 145, 170, 0.16);
  12. margin-bottom: var(--sp-6);
  13. padding: var(--sp-4);
  14. background: var(--bg-elevated);
  15. border: 1px solid var(--border-default);
  16. border-radius: var(--radius);
  17. &__head {
  18. display: flex;
  19. align-items: center;
  20. justify-content: space-between;
  21. flex-wrap: wrap;
  22. gap: var(--sp-3);
  23. margin-bottom: var(--sp-3);
  24. }
  25. &__title {
  26. font-size: var(--fs-lg);
  27. font-weight: 700;
  28. color: var(--text-primary);
  29. }
  30. &__meta {
  31. display: flex;
  32. align-items: center;
  33. gap: var(--sp-4);
  34. font-size: var(--fs-xs);
  35. color: var(--text-muted);
  36. }
  37. &__legend {
  38. display: inline-flex;
  39. align-items: center;
  40. gap: var(--sp-2);
  41. }
  42. &__dot {
  43. display: inline-block;
  44. width: 8px;
  45. height: 8px;
  46. border-radius: 50%;
  47. &--up {
  48. background: var(--price-up);
  49. margin-left: var(--sp-2);
  50. }
  51. &--down {
  52. background: var(--price-down);
  53. margin-left: var(--sp-3);
  54. }
  55. }
  56. &__asof {
  57. font-variant-numeric: tabular-nums;
  58. }
  59. // 무대 — 2:1 등거리 비율 고정, 툴팁 기준 컨테이너
  60. &__stage {
  61. position: relative;
  62. width: 100%;
  63. aspect-ratio: 1000 / 500;
  64. }
  65. &__svg {
  66. width: 100%;
  67. height: 100%;
  68. display: block;
  69. }
  70. &__empty {
  71. display: flex;
  72. align-items: center;
  73. justify-content: center;
  74. width: 100%;
  75. height: 100%;
  76. font-size: var(--fs-sm);
  77. color: var(--text-muted);
  78. }
  79. // 격자
  80. &__grid line {
  81. stroke: var(--az-map-grid);
  82. stroke-width: 1;
  83. }
  84. // 대륙
  85. &__land polygon {
  86. fill: var(--az-map-land);
  87. stroke: var(--az-map-land-edge);
  88. stroke-width: 1;
  89. stroke-linejoin: round;
  90. }
  91. // 핀 — 그룹 color 로 방향색을 상속, dot/pulse 는 currentColor
  92. &__pin {
  93. cursor: pointer;
  94. outline: none;
  95. &--up {
  96. color: var(--price-up);
  97. }
  98. &--down {
  99. color: var(--price-down);
  100. }
  101. &--flat {
  102. color: var(--price-flat);
  103. }
  104. }
  105. &__pin-dot {
  106. fill: currentColor;
  107. filter: drop-shadow(0 0 3px currentColor);
  108. transition: r 0.15s ease;
  109. }
  110. &__pin-core {
  111. fill: rgba(255, 255, 255, 0.92);
  112. pointer-events: none;
  113. }
  114. // 확산 링 (상승/하락 핀) — 중심 기준 확대·소멸 반복
  115. &__pulse {
  116. fill: currentColor;
  117. opacity: 0.5;
  118. transform-box: fill-box;
  119. transform-origin: center;
  120. animation: wm-pulse 2.4s ease-out infinite;
  121. pointer-events: none;
  122. }
  123. // 활성(hover/focus) 핀 강조 링
  124. &__pin.is-active &__pin-dot {
  125. stroke: rgba(255, 255, 255, 0.9);
  126. stroke-width: 1.5;
  127. }
  128. // 툴팁 — 활성 핀 위에 부유
  129. &__tip {
  130. position: absolute;
  131. transform: translate(-50%, -128%);
  132. min-width: 132px;
  133. padding: var(--sp-3) var(--sp-4);
  134. background: var(--bg-page);
  135. border: 1px solid var(--border-strong);
  136. border-radius: var(--radius);
  137. box-shadow: 0 var(--sp-2) var(--sp-4) var(--shadow-color);
  138. pointer-events: none;
  139. z-index: 2;
  140. }
  141. &__tip-head {
  142. display: flex;
  143. align-items: baseline;
  144. gap: var(--sp-2);
  145. margin-bottom: var(--sp-2);
  146. }
  147. &__tip-country {
  148. font-size: var(--fs-xs);
  149. font-weight: 700;
  150. color: var(--text-primary);
  151. }
  152. &__tip-name {
  153. font-size: var(--fs-2xs);
  154. color: var(--text-muted);
  155. white-space: nowrap;
  156. }
  157. &__tip-close {
  158. font-size: var(--fs-lg);
  159. font-weight: 700;
  160. font-variant-numeric: tabular-nums;
  161. color: var(--text-primary);
  162. }
  163. &__tip-change {
  164. display: flex;
  165. align-items: baseline;
  166. justify-content: space-between;
  167. gap: var(--sp-3);
  168. margin-top: var(--sp-1);
  169. font-size: var(--fs-sm);
  170. font-weight: 600;
  171. font-variant-numeric: tabular-nums;
  172. &--up {
  173. color: var(--price-up);
  174. }
  175. &--down {
  176. color: var(--price-down);
  177. }
  178. &--flat {
  179. color: var(--price-flat);
  180. }
  181. }
  182. &__tip-exch {
  183. font-size: var(--fs-2xs);
  184. font-weight: 400;
  185. color: var(--text-muted);
  186. }
  187. }
  188. @keyframes wm-pulse {
  189. 0% {
  190. transform: scale(1);
  191. opacity: 0.5;
  192. }
  193. 100% {
  194. transform: scale(2.6);
  195. opacity: 0;
  196. }
  197. }
  198. @media (prefers-reduced-motion: reduce) {
  199. .world-map__pulse {
  200. animation: none;
  201. opacity: 0;
  202. }
  203. }