@import url("https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500&family=Noto+Sans+TC:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap");

:root {
  /* ---- Brand ---- */
  --color-primary: #ff9960;
  --color-primaryDark: #f3915a; /* primary-button hover only */
  --color-primaryMedium: #ffcdae;
  --color-primaryLight: #ffe0cd;
  --color-primaryWash: #eef3f8; /* soft info banner — cool tint (canon: warm wash clashes with cool neutrals) */
  --color-primaryText: #b05723; /* orange as text/link on light — AA 4.6; button orange stays --color-primary */

  /* ---- Neutrals (cool-blue tinted) ---- */
  --color-black: #1a222c; /* cool ink — primary text, never #000 in light mode */
  --color-greyDark: #3f4a57; /* secondary text */
  --color-greyMedium: #647082; /* tertiary text, captions, placeholders */
  --color-greyLightMedium: #c4cdd6; /* disabled, arrows, faint dividers */
  --color-greyLight: #d5dde4; /* hairline borders, switch/tab tracks */
  --color-white: #eef1f4; /* cool-blue off-white app background (body) — light end of the cool dark base */

  /* ---- Surfaces ---- */
  --color-pureWhite: #ffffff; /* inputs, text on filled buttons — stays pure white after cooling */
  --color-surface: #f8fafb; /* card / panel surface on the body — faint cool tint */
  --color-cream: #e3e9ef; /* signature feature blocks — cool-blue tint (use unchanged, hue only) */
  --color-featureTint: #fdf3ec; /* highest-emphasis signature card only (orange ~7% tint over cool neutral) — light-only, max 1 per viewport, never dark/Terminal */

  /* ---- Trading colors (unified — pastel fills, text, chart lines, PnL) ---- */
  /* green/red are the single source of truth; *Data aliases are deprecated
     (same light-mode value) and will be removed once code references are migrated. */
  --color-green: #26a69a;      /* TradingView — 3.1:1 on surface */
  --color-greenLight: #d2f0ec; /* badge bg — intentionally low contrast */
  --color-greenDark: #1d8075;  /* flash_green_dark keyframe only */
  --color-greenBlack: #1a5c56; /* deep text on greenLight bg */
  --color-red: #ef5350;        /* TradingView — 3.8:1 on surface */
  --color-redLight: #fdd9d8;   /* badge bg */
  --color-redDark: #c23f3d;    /* flash_red_dark keyframe only */
  --color-redBlack: #6b1d1c;   /* deep text on redLight bg */
  --color-badgeNeutralBg: #cecece;   /* neutral badge background */
  --color-badgeNeutralText: #2d2d2d; /* neutral badge text */
  --color-greenData: #26a69a;  /* deprecated alias → --color-green */
  --color-redData: #ef5350;    /* deprecated alias → --color-red */

  /* ---- Categorical data (多序列, non-trading-semantic) — canon › Color › Categorical data ---- */
  --color-data-1: #ff9960; /* = --color-primary, 主序列 */
  --color-data-2: #5b7a9e; /* 暖鋼藍 */
  --color-data-3: #c79a3e; /* 暖赭金 */
  --color-data-4: #9a6f8e; /* 暖梅紫 */

  /* ---- Dark mode (cool graphite) ---- */
  --color-darkBody: #14161a; /* body background — cool graphite black, never pure #000 */
  --color-darkCard: #1f2329; /* card / panel surface */
  --color-darkBorder: #2e343d; /* hairline, dividers, on-card controls & hover fills */
  --color-darkText: #eef1f4; /* primary foreground — faint cool white */

  /* ---- Scrollbar ---- */
  --scrollbar-color-thumb: var(--color-greyMedium);
  --scrollbar-color-track: transparent;
  --scrollbar-width: 6px;

  /* ---- Radii (see design-system canon › Radii — use these, don't invent in-betweens) ---- */
  --radius-micro: 4px; /* Terminal only — skeleton blocks, mini chips ≤24px */
  --radius-xs: 6px; /* Terminal only — dense controls ≤30px */
  --radius-sm: 8px; /* dense buttons, signup pill, tags */
  --radius-md: 10px; /* default button + input + sidebar pill */
  --radius-lg: 12px; /* modal, mid card, Terminal card/panel max */
  --radius-xl: 16px; /* primary card, feature step */
  --radius-2xl: 24px; /* hero / video container */
  --radius-pill: 999px; /* capsules, avatars, circular icons, switch track */

  /* ---- Elevation (see design-system canon › Elevation — sparingly, no inner/stacked) ---- */
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.12); /* selected tab pill */
  --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08); /* card resting surface */
  --shadow-brand: 0 4px 16px rgba(255, 153, 96, 0.12); /* focal-card emphasis */

  /* ---- Spacing (4px base — see design-system canon › Spacing; named by px value) ---- */
  --space-4: 4px;
  --space-8: 8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-24: 24px;
  --space-32: 32px;
  --space-48: 48px;
  --space-64: 64px;

  /* ---- Motion (see design-system canon › Motion; names existing durations, no new feel) ---- */
  --motion-fast: 0.15s; /* hover/focus micro-feedback */
  --motion-base: 0.4s; /* switch, small UI state change */
  --motion-enter: 0.8s; /* scroll/entrance reveal (GSAP power3.out baseline) */
  --motion-flash: 1.5s; /* data-update cell flash */
  --ease-standard: ease; /* default CSS transition curve */
}

button {
  box-shadow: none !important;
}

/* Font (English) */

h1:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 48px;
  line-height: 115%;
  letter-spacing: -0.02em;
  margin: 0px;
}

h2:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 40px;
  line-height: 118%;
  letter-spacing: -0.02em;
  margin: 0px;
}

h3:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 30px;
  line-height: 120%;
  letter-spacing: -0.01em;
  margin: 0px;
}

h4:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 700;
  font-size: 24px;
  line-height: 140%;
  margin: 0px;
}

h5:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 20px;
  line-height: 140%;
  margin: 0px;
}

h6:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
  font-size: 16px;
  line-height: 140%;
  margin: 0px;
}

p:lang(en),
a:lang(en),
li:lang(en),
label:lang(en),
input:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  margin: 0px;
}

button:lang(en) {
  font-family: "Plus Jakarta Sans", sans-serif;
  font-weight: 600;
}

/* Font (Chinese) */

h1:lang(zh),
h1:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  letter-spacing: -0.01em;
  font-weight: 700;
  font-size: 48px;
  line-height: 118%;
  margin: 0px;
}

h2:lang(zh),
h2:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  letter-spacing: -0.01em;
  font-weight: 700;
  font-size: 40px;
  line-height: 120%;
  margin: 0px;
}

h3:lang(zh),
h3:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  letter-spacing: -0.01em;
  font-weight: 700;
  font-size: 30px;
  line-height: 122%;
  margin: 0px;
}

h4:lang(zh),
h4:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  font-weight: 600;
  font-size: 24px;
  line-height: 140%;
  margin: 0px;
}

h5:lang(zh),
h5:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  font-weight: 600;
  font-size: 20px;
  line-height: 140%;
  margin: 0px;
}

h6:lang(zh),
h6:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  font-weight: 600;
  font-size: 16px;
  line-height: 140%;
  margin: 0px;
}

p:lang(zh),
p:lang(cn),
a:lang(zh),
a:lang(cn),
li:lang(zh),
li:lang(cn),
label:lang(zh),
label:lang(cn),
input:lang(zh),
input:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  font-weight: 400;
  margin: 0px;
}

button:lang(zh),
button:lang(cn) {
  font-family: "Noto Sans TC", sans-serif;
  font-weight: 500;
}

/* Numeric utility — Roboto Mono (plain zero, no dot/slash) for stat numerals;
   tabular figures keep digits aligned and jitter-free on live update. Text
   labels & eyebrows use the sans, NOT this. Code blocks use a system-mono
   stack in their own page CSS. Lang-agnostic. */
.mono {
  font-family: "Roboto Mono", "SF Mono", "SFMono-Regular", Consolas,
    "Liberation Mono", Menlo, monospace;
  font-variant-numeric: tabular-nums;
}

/* CJK eyebrow variant — Chinese has no uppercase, so .eyebrow's
   text-transform:uppercase no-ops and reads under-styled on Han. This drops
   uppercase and widens tracking to .16em to carry the professional weight
   instead. Use for descriptive CJK eyebrows ("籌碼縱深"); structural /
   English-term eyebrows (§01, D01, L1) stay on the mono .eyebrow. Explicit
   class, NOT :lang() — the EN/ZH split is semantic, not language-driven.
   See design-system canon › Type › utility class. */
.eyebrow-cjk {
  font-family: "Noto Sans TC", sans-serif;
  text-transform: none;
  letter-spacing: 0.16em;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-greyMedium);
}

/* Responsive type scale — the single sanctioned heading re-size.
   Pages must NOT shrink headings individually; this scale applies site-wide.
   (Selectors mirror the :lang() rules above to win on specificity.) */
@media (max-width: 768px) {
  h1:lang(en), h1:lang(zh), h1:lang(cn) {
    font-size: 36px;
  }
  h2:lang(en), h2:lang(zh), h2:lang(cn) {
    font-size: 30px;
  }
  h3:lang(en), h3:lang(zh), h3:lang(cn) {
    font-size: 26px;
  }
  h4:lang(en), h4:lang(zh), h4:lang(cn) {
    font-size: 22px;
  }
  h5:lang(en), h5:lang(zh), h5:lang(cn) {
    font-size: 18px;
  }
}

/* Items */

body {
  background-color: var(--color-white);
}

.container {
  max-width: 1200px;
  padding: 0px;
}

button {
  display: flex;
  justify-content: center;
  align-items: center;
}

button.primary_btn {
  height: 50px;
  padding: 0px 20px;
  background-color: var(--color-primary);
  border: 0px;
  border-radius: var(--radius-md);
  color: var(--color-pureWhite);
  margin: 0px;
}

button.primary_btn:hover {
  background-color: var(--color-primaryDark);
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
input[type="number"] {
  -moz-appearance: textfield;
}

/* Focus indicators (see design-system canon › States). Two treatments by element type.

   Form fields — no outer ring; focus highlights the border in the brand color
   so the indicator sits ON the field edge, not floating outside it. !important
   beats component resting/focus borders (often ID-scoped) for one site-wide
   look. (Borderless fields have nothing to tint — give them their own focus
   style.) box-shadow:none kills the Bootstrap default glow. */
input:active,
input:focus,
select:active,
select:focus,
textarea:active,
textarea:focus {
  outline: none !important;
  box-shadow: none !important;
}
input:focus,
select:focus,
textarea:focus {
  border-color: var(--color-primary) !important;
}

/* Buttons, links, and other focusables — branded keyboard ring via
   :focus-visible (pointer focus stays clean). */
button:focus-visible,
a:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-primary) !important;
  outline-offset: 2px;
}

/* RWD */

.rwd_100,
.rwd_110,
.rwd_101,
.rwd_111 {
  display: block;
}

.rwd_000,
.rwd_010,
.rwd_001,
.rwd_011 {
  display: none;
}

@media (max-width: 1300px) {
  .rwd_010,
  .rwd_110,
  .rwd_011,
  .rwd_111 {
    display: block;
  }
  .rwd_000,
  .rwd_100,
  .rwd_001,
  .rwd_101 {
    display: none;
  }
}
@media (max-width: 768px) {
  .rwd_001,
  .rwd_101,
  .rwd_011,
  .rwd_111 {
    display: block;
  }
  .rwd_000,
  .rwd_100,
  .rwd_010,
  .rwd_110 {
    display: none;
  }
}

/* Modal */
.modal {
  display: none;
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.4);
}

.modal .box_header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.modal .box_header .close {
  cursor: pointer;
}

.modal .box_header .close img {
  height: 15px;
}

.modal .modal-content {
  background-color: var(--color-surface);
  margin: 40px auto;
  padding: 25px 32px;
  border: 0px;
  border-radius: var(--radius-lg);
}

.modal .box_footer {
  position: absolute;
  bottom: 32px;
  left: 0px;
  width: 100%;
  display: flex;
  justify-content: space-between;
  padding-left: 32px;
  padding-right: 32px;
}

.modal .box_footer button {
  width: 47%;
  height: 40px;
  border: 0px;
  border-radius: var(--radius-md);
}

/* Loading */
.loader {
  border: 3px solid var(--color-white);
  border-radius: 50%;
  border-top: 3px solid transparent;
  width: 20px;
  height: 20px;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

/* Overlay */
.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色 */
  z-index: 998; /* 確保在導航欄下方 */
  display: none; /* 初始不顯示 */
}

.overlay_blur {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px); /* 濾鏡效果，可以調整模糊程度 */
  z-index: 997; /* 確保在導航欄下方 */
  display: none; /* 初始不顯示 */
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* dark mode */
body.dark-mode {
  /* Light-mode ink ramp is deepened in :root; dark mode re-ups these vars on
     dark surfaces, where the deep ramp would lose contrast. Cooled 2026-06-23
     to share the cool graphite hue of the dark base (canon › Neutrals note). */
  --color-black: #222a33;
  --color-greyDark: #545d68;
  --color-greyMedium: #818b97;
  /* Trading colors: TradingView — *Light/*Black inverted on dark */
  --color-greenLight: #0d2e2c; /* badge bg on dark */
  --color-greenDark: #1d8075;  /* flash_green_dark keyframe */
  --color-greenBlack: #8dd5ce; /* text on dark greenLight */
  --color-redLight: #2e1010;   /* badge bg on dark */
  --color-redDark: #c23f3d;    /* flash_red_dark keyframe */
  --color-redBlack: #f5a09e;   /* text on dark redLight */
  --color-badgeNeutralBg: #404856;   /* neutral badge background on dark */
  --color-badgeNeutralText: #c4cdd6; /* neutral badge text on dark */
  background-color: var(--color-darkBody);
  color: var(--color-darkText);
}

body.dark-mode .modal .modal-content {
  color: var(--color-black);
}

body.dark-mode .loader {
  border: 3px solid var(--color-darkBody);
  border-top: 3px solid var(--color-darkText);
}

/* btn feedback */
#box_feedback {
  display: flex;
  justify-content: flex-end;
}

#btn_feedback {
  position: fixed;
  bottom: 60px;
  z-index: 999;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background-color: var(--color-greyMedium);
  border: 3px var(--color-surface) solid;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--shadow-md);
}

#btn_feedback:hover {
  background-color: var(--color-greyDark);
}

#btn_feedback img {
  width: 22px;
}

/* Switch */
.switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 24px;
}

.switch input {
  opacity: 0;
  width: 0;
  height: 0;
}

.switch .slider {
  position: absolute;
  cursor: pointer;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: var(--color-greyLight);
  transition: var(--motion-base);
}

.switch .slider:before {
  position: absolute;
  content: "";
  height: 16px;
  width: 16px;
  left: 4px;
  bottom: 4px;
  background-color: var(--color-white);
  transition: 0.3s;
}

.switch input:checked + .slider {
  background-color: var(--color-primary);
}

.switch input:checked + .slider:before {
  transform: translateX(16px);
}

.switch .slider.round {
  border-radius: var(--radius-pill);
}

.switch .slider.round:before {
  border-radius: 50%;
}

/* Loading Box */
.loading-box {
  width: 100%;
  height: 75%;
  background-color: rgba(204, 204, 204, 0.2);
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-pill);
}

.loading-shine {
  content: "";
  position: absolute;
  top: 0;
  left: -100%;
  height: 100%;
  width: 100%;
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(255, 255, 255, 0.6) 20%,
    rgba(255, 255, 255, 0.6) 80%,
    transparent 100%
  );
  animation: shine 2s infinite;
}

body.dark-mode .loading-box {
  background-color: rgba(255, 255, 255, 0.05);
  border-radius: var(--radius-pill);
}

body.dark-mode .loading-shine {
  background: linear-gradient(
    to right,
    transparent 0%,
    rgba(255, 255, 255, 0.08) 20%,
    rgba(255, 255, 255, 0.08) 80%,
    transparent 100%
  );
}

@keyframes shine {
  0% {
    left: -100%;
  }
  100% {
    left: 100%;
  }
}

/* value 更新閃爍 */
@keyframes flash {
  0% {
    background-color: var(--color-greyLight);
  }
  100% {
    background-color: transparent;
  }
}

@keyframes flash-green {
  0% {
    background-color: var(--color-greenLight);
  }
  100% {
    background-color: transparent;
  }
}

@keyframes flash-red {
  0% {
    background-color: var(--color-redLight);
  }
  100% {
    background-color: transparent;
  }
}
@keyframes flash-dark {
  0% {
    background-color: var(--color-greyDark);
  }
  100% {
    background-color: transparent;
  }
}

@keyframes flash-green-dark {
  0% {
    background-color: var(--color-greenDark);
  }
  100% {
    background-color: transparent;
  }
}

@keyframes flash-red-dark {
  0% {
    background-color: var(--color-redDark);
  }
  100% {
    background-color: transparent;
  }
}

.flash {
  animation: flash var(--motion-flash) ease-in-out;
}

.flash_green {
  animation: flash-green var(--motion-flash) ease-in-out;
}

.flash_red {
  animation: flash-red var(--motion-flash) ease-in-out;
}

body.dark-mode .flash {
  animation: flash-dark var(--motion-flash) ease-in-out;
}

body.dark-mode .flash_green {
  animation: flash-green-dark var(--motion-flash) ease-in-out;
}

body.dark-mode .flash_red {
  animation: flash-red-dark var(--motion-flash) ease-in-out;
}

/* scrollbar */
/* Modern browsers with `scrollbar-*` support */
@supports (scrollbar-width: auto) {
  * {
    scrollbar-color: var(--scrollbar-color-thumb) var(--scrollbar-color-track);
    scrollbar-width: var(--scrollbar-width);
  }
}

/* Legacy browsers with `::-webkit-scrollbar-*` support */
@supports selector(::-webkit-scrollbar) {
  *::-webkit-scrollbar-thumb {
    background: var(--scrollbar-color-thumb);
    border-radius: var(--radius-sm);
  }
  *::-webkit-scrollbar-track {
    background: var(--scrollbar-color-track);
    border-radius: var(--radius-sm);
  }
  *::-webkit-scrollbar-button {
    display: none;
  }
}

/* Dark Mode */
body.dark-mode .light-mode {
  display: none;
}
body:not(.dark-mode) .dark-mode {
  display: none;
}

/* Language modal */
#modal_lang .modal-content {
  width: 280px;
}
#modal_lang .modal-header {
  padding: 0px;
  border: 0px;
  margin-bottom: 32px;
}
#modal_lang .modal-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0px;
}
#modal_lang .btn_lang {
  width: 100%;
  height: 54px;
  border: 0px;
  border-radius: var(--radius-md);
  background: transparent;
  font-size: 16px;
  cursor: pointer;
  text-align: left;
  color: var(--color-greyMedium);
}
#modal_lang .btn_lang:hover,
#modal_lang .btn_lang.active {
  background-color: var(--color-greyLight);
  color: var(--color-black);
}

/* ── Tooltip (canon › Components › Tooltip; Bootstrap override → Blave floating-panel) ── */
.has-tip {
  border-bottom: 1px dotted var(--color-greyLightMedium);
  cursor: help;
}
.has-tip,
[data-bs-toggle="tooltip"] {
  cursor: help;
}
.tooltip {
  font-family: "Plus Jakarta Sans", "Noto Sans TC", sans-serif;
}
.tooltip.show {
  opacity: 1;
}
.tooltip .tooltip-arrow {
  display: none;
}
.tooltip .tooltip-inner {
  max-width: 260px;
  padding: 6px 10px;
  text-align: left;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  color: var(--color-greyDark);
  background: var(--color-surface);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
}
body.dark-mode .has-tip {
  border-bottom-color: var(--color-darkBorder);
}
body.dark-mode .tooltip .tooltip-inner {
  color: var(--color-greyLightMedium);
  /* dark overlays separate by a lighter tone, not by deeper shadow */
  background: var(--color-darkBorder);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
@media (prefers-reduced-motion: reduce) {
  .tooltip.fade {
    transition: none;
  }
}

/* ── SEO explain block — server-rendered, always visible for crawlers ── */
.seo-explain {
  margin-top: var(--space-16);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-16);
}
.seo-explain h2 {
  font-size: 13px; font-weight: 600; color: var(--color-black);
  margin: 0 0 var(--space-8) 0;
  padding-bottom: var(--space-8);
  border-bottom: 1px solid var(--color-greyLight);
}
.seo-explain p { font-size: 13px; color: var(--color-greyMedium); line-height: 1.7; margin: 0; }
body.dark-mode .seo-explain { background: var(--color-darkCard); box-shadow: none; }
body.dark-mode .seo-explain h2 { color: var(--color-darkText); border-bottom-color: var(--color-darkBorder); }

/* ── Sortable table header (canon › Components › Sortable table header) ──
   The single site-wide sort indicator: every sortable column shows a faint
   resting hint (a stacked triangle pair) so users know it's sortable; the
   active column swaps to one solid up/down triangle. Arrows are
   decorative-only CSS ::after drawn with clip-path geometry — never a DOM
   text node, so they can't be scraped into search-result snippets, and the
   geometry doesn't depend on font rendering; screen readers get the real
   state from the aria-sort attribute JS sets/removes (JS never builds arrow
   DOM). Resting and active states share one 8×10px box, so state switches
   cause zero layout shift. `data-sort` marks a column as sortable (its
   value = the sort key). Covers twstock `table.tbl` <th> headers and Studio
   flex-div headers (`.box_header` cells with role="columnheader"). Don't
   re-declare arrow CSS in page files. */
table.tbl thead th[data-sort],
.box_header [data-sort] {
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
table.tbl thead th[data-sort]::after,
.box_header [data-sort]::after {
  content: "";
  display: inline-block;
  width: 8px;
  height: 10px;
  margin-left: 5px;
  /* 0px (= box bottom sits on the text baseline) optically centers the box
     on the header text for both sizes (12px twstock th / 14px Studio
     .box_header): measured ≤0.5px off either way, vs ~1.3–1.8px too low
     with `middle`. A single shared value can't beat ±0.5px because the
     ideal offset flips sign between the two font sizes. */
  vertical-align: 0px;
  /* resting: a pair of 4px-tall triangles, 2px apart */
  background-color: var(--color-greyLightMedium);
  clip-path: path("M4 0 L8 4 L0 4 Z M0 6 L8 6 L4 10 Z");
}
table.tbl thead th[aria-sort="ascending"]::after,
.box_header [aria-sort="ascending"]::after {
  /* single 6px-tall triangle, centered in the box */
  clip-path: path("M4 2 L8 8 L0 8 Z");
}
table.tbl thead th[aria-sort="descending"]::after,
.box_header [aria-sort="descending"]::after {
  clip-path: path("M0 2 L8 2 L4 8 Z");
}
table.tbl thead th[aria-sort]::after,
.box_header [aria-sort]::after {
  /* active column — must come after the resting rule (equal specificity) */
  background-color: var(--color-primaryText);
}
