/* ---------------------------------------------------------------------------
   Phase 2 — Globe panel (slide-in)
   ---------------------------------------------------------------------------
   Panel is `position: absolute` inside `.globe-hero`. Closed state hides it
   off-screen via `transform: translateX(100%)` rather than `display:none`
   so the slide-in transition has something to animate from.
   When the hero is in `data-panel-state="open"`, the canvas narrows to
   leave room and the panel translates back to its rest position.
   --------------------------------------------------------------------------- */

/* Canvas resize is the layout change globe.js's ResizeObserver picks up
 * — globe.gl re-fits the WebGL viewport, so picking stays accurate
 * without us having to reach for a CSS transform (which would skew the
 * raycast input coordinates).
 *
 * Implementation note: `.globe-hero__canvas` is positioned absolute with
 * inset:0 (= top/left/right/bottom: 0). For absolute elements the
 * left+right pair determines the width, so a `width: 67%` would be
 * ignored as long as `right: 0` is set. We therefore drive the canvas
 * width by adjusting the `right` edge to 33% when the panel opens —
 * which matches the panel's own width and produces a clean butt-join
 * without any pixel gap. */
/* A1 (2026-06-19): the panel now OVERLAYS the full-width globe (calm
 * rise+fade) instead of narrowing the canvas to 67%. Removing the
 * canvas-narrow eliminates the ResizeObserver / raycast-realign churn
 * that drove a whole class of globe hotfixes. */

.globe-panel {
  /* Right-side floating card overlaying the globe (desktop). The
   * transition is the A1 rise+fade defined below. */
  position: absolute;
  /* D1: shared top grid line (topbar bottom + one gutter = 84px) + gutter edges */
  top: var(--globe-top);
  right: var(--globe-gutter);
  bottom: var(--globe-gutter);
  /* ~1/4 of the viewport each (left profile + right headlines) so the
   * globe keeps the middle half — 33% felt too full (2026-06-19). */
  width: 25%;
  min-width: 320px;
  /* (Glass Terminal W#3) tier-1 glass. The opaque fallback ships first; the
     @supports block below layers translucency + backdrop blur, so unsupported
     browsers AND the prefers-reduced-transparency gate keep the solid fill.
     Trio = hairline border + inset top highlight + tier-3 float shadow. The
     sheet is edge-anchored over the Cesium canvas, so the blur only recomputes
     on an actual globe drag (requestRenderMode is on). */
  background: var(--glass-1-fallback);
  border: 1px solid var(--glass-hairline);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-3), inset 0 1px 0 var(--glass-highlight);
  display: flex;
  flex-direction: column;
  z-index: var(--z-globe-3);
  /* A1 (2026-06-19) "quiet rise + fade": invisible + nudged down at
   * rest; .globe-hero[data-panel-state="open"] lifts + fades it in over
   * --dur-base. Visibility is pure CSS — no mesh, no JS failsafe — so it
   * can never get stuck invisible. (Mobile overrides to a bottom sheet
   * in the max-width:720px block.) */
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  overflow: hidden;
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.globe-hero[data-panel-state="open"] .globe-panel {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
/* (Glass Terminal W#3) tier-1 glass enhancement — translucent fill + backdrop
   blur where supported. Covers BOTH the right headlines sheet and the left
   .globe-panel--profile (same base class). Kept out of the base rule so
   unsupported browsers keep the opaque fallback. */
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .globe-panel {
    background: var(--glass-1-bg);
    -webkit-backdrop-filter: blur(var(--glass-1-blur)) saturate(var(--glass-sat));
    backdrop-filter: blur(var(--glass-1-blur)) saturate(var(--glass-sat));
  }
}
/* prefers-reduced-transparency: force the opaque fallback (no translucency, no
   blur) on the country sheets. The central gate at the end of 70-aux.css
   enumerates a fixed surface list that does NOT yet include .globe-panel; this
   local block covers it until the orchestrator folds .globe-panel into that
   central gate (see deviations). It sits later in THIS file than the @supports
   block above, so it wins at equal specificity without !important;
   backdrop-filter is never written inline by JS, so forcing it off is safe. */
@media (prefers-reduced-transparency: reduce) {
  .globe-panel {
    background: var(--glass-1-fallback);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
/* Swap: keep the single panel, briefly cross-fade its list so a
 * different-country click reads as a calm content change rather than
 * an instant text swap. Re-triggered per swap by globe-panel.js. */
.globe-panel.is-swapping .globe-panel__list {
  animation: gp-swap var(--dur-base) var(--ease-out);
}
@keyframes gp-swap { from { opacity: 0.35; } to { opacity: 1; } }

/* C4a — feed view switch (Headlines/Events/Saved): the newly-shown section
   fades + rises subtly. Applied by app.js on show only (no exit animation).
   Neutralised by the global reduced-motion block (animation:none). */
.view-in { animation: view-in var(--dur-base) var(--ease-out) both; }
@keyframes view-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* C4b — headline list load-in: each row rises + fades. app.js sets a per-row
   animationDelay (i*20ms, capped) on full rebuilds only (not stash-restores).
   Reduced-motion: the global block zeroes the animation. */
.article--rise { animation: item-rise var(--dur-base) var(--ease-out) both; }
@keyframes item-rise {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: none; }
}

/* Left "country profile" panel — mirrors .globe-panel but anchored to the
 * LEFT edge (B1b scaffold, 2026-06-19). Inherits the rise+fade + the
 * [data-panel-state="open"] reveal above; only the horizontal anchor and
 * the placeholder body differ. Detailed composition is TBD. */
.globe-panel--profile {
  right: auto;
  left: var(--globe-gutter);   /* D1: left grid line, mirrors the right panel */
}
.globe-panel__profile-body {
  padding: var(--sp-3) var(--sp-4) var(--sp-4);
  overflow-y: auto;
}
/* Mobile-only tab bar + in-sheet profile host (audit #41). Hidden on desktop —
 * the mobile @media(max-width:720px) block flips these back on. Base rules here
 * (rather than only in the media block) guarantee the elements, which
 * globe-panel.js always creates in the DOM, stay invisible on wide screens.
 * 2026-07-08 regression fix: the tab bar carries BOTH classes (.view-tabs
 * .globe-panel__mtabs) and the `.view-tabs { display:flex }` base rule sits
 * LATER in this file — equal specificity, later wins, so the single-class
 * hide leaked the tabs onto desktop (clicking Profile then relocated the
 * profile body into the hidden mobile host = "profile disappears"). The
 * compound selector outranks .view-tabs regardless of rule order. */
.view-tabs.globe-panel__mtabs,
.globe-panel__mtabs,
.globe-panel__mprofile { display: none; }
.globe-panel__profile-note {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--ink-dim);
}

/* Country-profile content blocks (B1c increment 1: badges + live coverage). */
.globe-profile__sec { padding-bottom: var(--sp-3); }
.globe-profile__sec + .globe-profile__sec {
  border-top: 1px solid var(--glass-hairline);
  padding-top: var(--sp-3);
}
.globe-profile__lab {
  font-size: var(--text-2xs);
  font-weight: 600;
  letter-spacing: 0.08em;   /* G4: eyebrow unify — standard 0.08em tracking (was 0.1em); w600 + --ink-dim already per recipe */
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: var(--sp-2);
}
.globe-profile__badges,
.globe-profile__tags { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.globe-profile__badge {
  font-size: var(--text-xs);
  color: var(--tag-sector);
  background: color-mix(in srgb, var(--tag-sector) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--tag-sector) 28%, transparent);
  border-radius: var(--r-sm);
  padding: 1px 6px;
}
.globe-profile__bigrow { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.globe-profile__big {
  font-family: var(--font-serif);
  font-size: var(--text-2xl);
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* H — coverage trend delta beside the lead figure. A mono tabular "chip" so the
   sign + percentage line up like a terminal readout. Colour keeps the existing
   COVERAGE semantic (accent = rising attention, muted = flat/down) rather than
   the market green/red — a coverage rise is not inherently "good". */
.globe-profile__delta {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  padding: 2px var(--sp-2);
  border-radius: var(--r-sm);
}
.globe-profile__delta--up { color: var(--accent); background: var(--accent-soft); }
.globe-profile__delta--down { color: var(--ink-muted); background: color-mix(in srgb, var(--ink-muted) 14%, transparent); }
.globe-profile__delta--flat { color: var(--ink-muted); background: color-mix(in srgb, var(--ink-muted) 14%, transparent); }
/* H — sentiment pill in the inspector (only shown when a headline is classified). */
.globe-panel__sentrow, .article__sentrow {
  margin-top: 8px;
  /* Multi-label: a story can carry more than one sentiment pill. */
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Multi-label match toggle (Any=OR / All=AND) — segmented control in the
   filter rail. Governs how multiple selected topic/sector/religion tags are
   combined. */
.match-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-elev-1);
}
.match-toggle__btn {
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--text-sm);
  padding: 5px 12px;
  line-height: 1.2;
  cursor: pointer;
  /* G2: segmented-control state transition (hover/active fill + text) */
  transition: color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.match-toggle__btn + .match-toggle__btn { border-left: 1px solid var(--border); }
.match-toggle__btn:hover { background: var(--accent-soft); }
.match-toggle__btn.is-active { background: var(--accent); color: #fff; }
.match-toggle__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ── View tabs (Headlines | Events | Saved) ─────────────────────────────
   Terminal grammar: uppercase tracked labels on a hairline rail; the active tab
   is marked by a 2px accent underline (no solid pill — density). `display:
   inline-flex` is PRESERVED so the `.view-tabs.globe-panel__mtabs` compound
   above keeps outranking this base rule on desktop (mobile-sheet contract). */
.view-tabs {
  display: inline-flex; gap: var(--sp-3); margin-bottom: var(--sp-3);
  border-bottom: 1px solid var(--glass-hairline);
}
.view-tabs__tab {
  appearance: none; -webkit-appearance: none; border: 0; background: transparent;
  color: var(--ink-dim); font: inherit; font-size: var(--text-2xs); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: var(--sp-2) 2px; line-height: 1.2; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.view-tabs__tab + .view-tabs__tab { border-left: 0; }
.view-tabs__tab:hover { color: var(--ink); }
.view-tabs__tab.is-active { color: var(--ink); border-bottom-color: var(--accent); }
.view-tabs__tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }
/* (Glass Terminal, 2026-07-12) Coarse-pointer tap height. The view tabs
   (Headlines | Events | Saved, and the mobile-sheet Headlines | Profile pair via
   .globe-panel__mtabs) are native <button>s WITHOUT the .btn class, so the
   central 70-aux @media(pointer:coarse) .btn{min-height:44px} rule never reaches
   them — this is the one gap in the coarse target set. A native button centres
   its label vertically, so min-height alone gives a 44px tap target while the
   2px underline + tracked caps read unchanged. Coarse-only → fine-pointer
   density is preserved. */
@media (pointer: coarse) {
  .view-tabs__tab { min-height: 44px; }
}

/* ── Event Feed view ────────────────────────────────────────────────── */
.event-view__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: var(--sp-2); margin-bottom: var(--sp-3);
}
.event-view__title { margin: 0; font-size: var(--text-lg, 1.1rem); color: var(--ink); }
.event-view__subtitle { display: block; font-size: var(--text-xs); color: var(--ink-dim); margin-top: 2px; }
.event-view__controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.event-view__window { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-xs); color: var(--ink-muted); }
/* G7: period/window select archetype — bg-elev-2 + 1px --border + --r-sm (window variant). */
.event-view__window select {
  font: inherit; font-size: var(--text-sm); padding: 4px 8px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--bg-elev-2); color: var(--ink);
}
.event-sort { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; background: var(--bg-elev-1); }
.event-sort__btn {
  appearance: none; -webkit-appearance: none; border: 0; background: transparent;
  color: var(--ink-muted); font: inherit; font-size: var(--text-xs); font-weight: 600;
  padding: 5px 11px; cursor: pointer;
  /* G2: segmented-control state transition (hover/active fill + text) */
  transition: color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.event-sort__btn + .event-sort__btn { border-left: 1px solid var(--border); }
.event-sort__btn:hover { background: var(--accent-soft); color: var(--ink); }
.event-sort__btn.is-active { background: var(--accent); color: #fff; }
.event-sort__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.event-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
/* Empty / loading / error placeholder. A quiet centred column: the single text
   node (empty + loading) reads exactly as before, and the error variant
   (app.js appends a message span + a .btn retry — spec §1.6 "에러 상태 재시도
   버튼 포함") now stacks the retry under the copy with a 4px-grid gap instead of
   trailing it inline. --ink-dim keeps the copy in the faint meta tier. */
.event-list__empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  color: var(--ink-dim);
  font-size: var(--text-sm);
  padding: 28px 8px;
  text-align: center;
}

/* ── Saved view (audit #40) ──────────────────────────────────────────────
   Reuses .article--compact rows, .globe-panel__statuspill status chips, and
   .watch-star for the unflag control; only the section headers, the grouped
   list, the note preview, and the empty/login/error states are new. */
.saved-list { display: flex; flex-direction: column; gap: var(--sp-4); }
.saved-list__empty {
  color: var(--ink-dim); font-size: var(--text-sm);
  padding: 28px 8px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-2);
}
.saved-list__empty-title { color: var(--ink); font-weight: 600; }
.saved-section { display: flex; flex-direction: column; gap: var(--sp-2); }
.saved-section__head {
  margin: 0; font-size: var(--text-xs); font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-dim);
}
.saved-list__group { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
/* Override the base .article grid: a flat flex row of [content | ★]. Rows are
   separated by hairline dividers with a hover tint (W#1-class local fix). The
   vertical padding replaces the former 8px group gap so row rhythm is
   unchanged (density-neutral). */
.saved-row {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  grid-template-columns: none; border-top: 0;
  padding: var(--sp-1) 0;
  transition: background var(--dur-fast) var(--ease-out);
}
.saved-row + .saved-row { border-top: 1px solid var(--glass-hairline); }
.saved-row:hover { background: var(--bg-elev-2); }
.saved-row__content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.saved-row__body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.saved-row__status { align-self: flex-start; cursor: default; }
.saved-row__note {
  font-size: var(--text-xs); color: var(--ink-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
.saved-row__unflag { flex: 0 0 auto; align-self: flex-start; }

.event {
  border: 1px solid var(--glass-hairline); border-radius: var(--r-md);
  background: var(--bg-elev-1); padding: var(--sp-3); cursor: pointer;
  box-shadow: inset 0 1px 0 var(--glass-highlight);
  transition: transform var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.event:hover {
  border-color: var(--warm);
  box-shadow: var(--shadow-2), inset 0 1px 0 var(--glass-highlight);
  transform: translateY(-1px);
}
.event:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.event__head { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
/* W#5/W#15 — the surge percentage is the money number of the Events view.
   Promoted to a mono tabular hero figure with a micro tracked label. app.js
   builds two spans (.event__badge-label + .event__badge-val — see
   html_js_requests); the base rule also styles the pre-split single text node
   ("Surge +NN%") as the amber figure so it degrades cleanly if the markup split
   has not landed. No pill — the figure stands on its own (density) and shares
   the amber surge tier with the spark bars so number + bars read as one
   instrument. --warm-text is the AA-safe amber text token in both themes. */
.event__badge {
  flex: none;
  display: inline-flex; align-items: baseline; gap: var(--sp-1);
  white-space: nowrap;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-lg); font-weight: 700; line-height: 1;
  letter-spacing: -0.01em; color: var(--warm-text);
}
.event__badge-label {
  font-family: var(--font-sans); font-size: var(--text-3xs); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-dim);
}
.event__badge-val {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--text-lg); font-weight: 700; line-height: 1;
  letter-spacing: -0.01em; color: var(--warm-text);
}
.event__label { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; min-width: 0; }
.event__chip {
  font-size: var(--text-xs); font-weight: 600; padding: 2px var(--sp-2); border-radius: 999px;
  border: 1px solid var(--glass-hairline); color: var(--ink); white-space: nowrap;
}
.event__chip--country { background: var(--bg-elev-2); }
/* W#15 — magnitude sparkline sized up so it reads as one instrument with the
   surge figure. viewBox is fixed 64×18 in app.js; scaling width+height in the
   same ratio lets preserveAspectRatio "meet" enlarge the bars uniformly, and
   the non-latest bars gain contrast (45% → 55%). */
.event__spark { flex: none; margin-left: auto; width: 78px; height: 22px; color: var(--warm); }
.event__spark-bar { fill: color-mix(in srgb, var(--warm) 55%, transparent); }
.event__spark-bar.is-last { fill: var(--warm); }
.event__time { flex: none; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-dim); white-space: nowrap; font-variant-numeric: tabular-nums; }
.event__sent { display: flex; height: 5px; border-radius: 999px; overflow: hidden; margin-top: var(--sp-2); background: var(--bg-elev-2); }
.event__sent-seg + .event__sent-seg { box-shadow: inset 1px 0 0 var(--glass-hairline); }
.event__sent-seg.is-pos { background: var(--positive); }
.event__sent-seg.is-neu { background: var(--ink-dim); }
.event__sent-seg.is-neg { background: var(--negative); }   /* G6: negative lean = market-red semantic, not brand --accent */
/* B7: sample links fold behind a click toggle; card sits ~90px collapsed. */
.event__samples-toggle {
  appearance: none; -webkit-appearance: none;
  display: inline-flex; align-items: center; gap: var(--sp-1);
  margin-top: var(--sp-2); padding: 0; border: 0; background: transparent;
  font: inherit; font-size: var(--text-xs); color: var(--ink-dim);
  cursor: pointer; letter-spacing: 0.02em;
}
.event__samples-toggle:hover { color: var(--ink-muted); }
.event__samples-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }
/* C2 — SVG chevron-right (injected by app.js); rotates 90° to point down when
   the sources fold is open. Replaces the former CSS border-triangle. */
.event__samples-caret {
  display: inline-flex; align-items: center; line-height: 0;
  transition: transform var(--dur-fast) var(--ease);
}
.event__samples-toggle[aria-expanded="true"] .event__samples-caret {
  transform: rotate(90deg);    /* points down (expanded) */
}
@media (prefers-reduced-motion: reduce) { .event__samples-caret { transition: none; } }
.event__samples { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
.event__samples[hidden] { display: none; }
.event__sample-link {
  display: block; font-size: var(--text-sm); color: var(--ink-muted); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.event__sample-link:hover { color: var(--accent); text-decoration: underline; }
.event__sample-link::before { content: "• "; color: var(--ink-dim); }

/* ── Trade panel section (globe profile) ────────────────────────────── */
.globe-profile__trade-head { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin: 0 0 var(--sp-2); }
.globe-profile__trade-dir { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-sm); overflow: hidden; }
.globe-profile__trade-dirbtn {
  appearance: none; -webkit-appearance: none; border: 0; background: transparent;
  color: var(--ink-muted); font: inherit; font-size: var(--text-xs); font-weight: 600;
  padding: 3px 9px; cursor: pointer;
  /* G2: segmented-control state transition (hover/active fill + text) */
  transition: color var(--dur-fast) var(--ease),
              background-color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.globe-profile__trade-dirbtn + .globe-profile__trade-dirbtn { border-left: 1px solid var(--border); }
.globe-profile__trade-dirbtn:hover { background: var(--accent-soft); }   /* G2: was missing a hover affordance */
.globe-profile__trade-dirbtn.is-active { background: var(--accent); color: #fff; }
.globe-profile__trade-period { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-dim); margin-left: auto; font-variant-numeric: tabular-nums; }
.globe-profile__trade-body { display: flex; flex-direction: column; gap: var(--sp-1); }
.globe-profile__trade-row { display: grid; grid-template-columns: minmax(64px, 1.1fr) 2fr auto; align-items: center; gap: var(--sp-2); }
.globe-profile__trade-name { font-size: var(--text-sm); color: var(--ink-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }   /* G5: label demoted to muted (markets-table convention) */
.globe-profile__trade-bar { height: 6px; border-radius: 999px; background: var(--bg-elev-2); overflow: hidden; }
/* JS writes `width` inline on the fill (never touched here). Rounded caps via
   the pill radius; colours mirror the globe trade arcs — hoisted to
   --trade-export / --trade-import tokens (see token_requests) with the current
   literals as var() fallbacks so an un-added token degrades to today's colour
   rather than erroring. */
.globe-profile__trade-fill { display: block; height: 100%; border-radius: 999px; }
.globe-profile__trade-fill.is-export { background: var(--trade-export, #0891b2); }   /* teal */
.globe-profile__trade-fill.is-import { background: var(--trade-import, #ea580c); }   /* orange */
.globe-profile__trade-val { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink); white-space: nowrap; font-variant-numeric: tabular-nums; }   /* G5: value promoted to --ink (data-first, markets-table convention) */
.globe-profile__trade-src { font-size: var(--text-xs); color: var(--ink-dim); margin-top: var(--sp-2); }

/* ── World-trade globe legend (global layer) ────────────────────────── */
.globe-legend__traderamp { display: flex; align-items: center; gap: 6px; margin-top: 4px; }
.globe-legend__rampbar {
  width: 40px; height: 7px; border-radius: 4px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--ink-dim) 45%, transparent), var(--ink-muted));
}
.globe-legend__ramplab { font-size: var(--text-xs); color: var(--ink-dim); }
.globe-legend__src { font-size: var(--text-xs); color: var(--ink-dim); margin-top: 4px; opacity: 0.85; }

/* Trade arc hover tooltip (globe). Floating, follows the cursor. */
.globe-trade-tip {
  position: absolute; z-index: var(--z-globe-4); pointer-events: none;
  background: color-mix(in srgb, var(--bg-elev-1) 92%, transparent);
  color: var(--ink); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: 4px 8px; font-size: var(--text-xs); font-weight: 600;
  white-space: nowrap; box-shadow: var(--shadow-1);
}

.sentiment-pill {
  display: inline-flex; align-items: center; font-size: var(--text-xs); font-weight: 600;
  padding: 2px 9px; border-radius: 999px;
}
.sentiment-pill--positive { color: var(--positive); background: color-mix(in srgb, var(--positive) 14%, transparent); }
.sentiment-pill--neutral  { color: var(--ink-muted); background: color-mix(in srgb, var(--ink-muted) 16%, transparent); }
.sentiment-pill--negative { color: var(--negative); background: color-mix(in srgb, var(--negative) 14%, transparent); }
/* Dark overrides are now redundant (var(--positive)/(--negative) already
   re-resolve under [data-theme="dark"]) but kept as explicit 1:1 no-ops. */
[data-theme="dark"] .sentiment-pill--positive { color: var(--positive); }
[data-theme="dark"] .sentiment-pill--negative { color: var(--negative); }
/* H — markets / 시세 (per-country index + commodities). Conventional finance
   colours: price up = green, down = red. */
.globe-profile__markets[hidden] { display: none; }
.globe-profile__markets-body { display: flex; flex-direction: column; gap: 4px; }
.globe-profile__market-row {
  display: grid; grid-template-columns: 1fr auto auto; align-items: baseline; gap: 8px;
  font-size: var(--text-sm);
}
/* Index rows carry a leading watch ★ (feature: index watchlist, 2026-07-08) —
   an extra auto column at the start; centre-align so the star sits on the row. */
.globe-profile__market-row--watch {
  grid-template-columns: auto 1fr auto auto; align-items: center;
}
.globe-profile__market-row--watch .watch-star { margin: -2px 0; }
.globe-profile__market-name { color: var(--ink-dim); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.globe-profile__market-val { font-family: var(--font-mono); color: var(--ink); font-variant-numeric: tabular-nums; }
.globe-profile__market-chg {
  font-family: var(--font-mono);
  font-size: var(--text-xs); font-weight: 600; font-variant-numeric: tabular-nums;
  min-width: 54px; text-align: right;
}
.globe-profile__market-chg--up { color: var(--positive); }
.globe-profile__market-chg--down { color: var(--negative); }
.globe-profile__market-chg--flat { color: var(--ink-muted); }
[data-theme="dark"] .globe-profile__market-chg--up { color: var(--positive); }
[data-theme="dark"] .globe-profile__market-chg--down { color: var(--negative); }

/* Collapsible commodity category (Energy / Precious Metals / …) — default collapsed. */
.globe-profile__mktgroup { border-top: 1px solid var(--border); }
.globe-profile__mktgroup:first-of-type { border-top: 0; }
.globe-profile__mktgroup-head {
  display: flex; align-items: center; gap: 6px; width: 100%;
  background: transparent; border: 0; padding: 5px 0; cursor: pointer;
  color: var(--ink); font: inherit; font-size: var(--text-sm); text-align: left;
}
.globe-profile__mktgroup-head:hover { color: var(--accent); }
.globe-profile__mktgroup-chev {
  display: inline-block; width: 10px; font-size: var(--text-3xs); color: var(--ink-muted);
  transition: transform var(--dur-fast) var(--ease-out);
}
.globe-profile__mktgroup:not(.is-collapsed) .globe-profile__mktgroup-chev { transform: rotate(90deg); }
.globe-profile__mktgroup-label { flex: 1; font-weight: 600; }
.globe-profile__mktgroup-count {
  font-size: var(--text-xs); color: var(--ink-muted); font-variant-numeric: tabular-nums;
}
.globe-profile__mktgroup-body {
  display: flex; flex-direction: column; gap: 4px; padding: 2px 0 6px 16px;
}
/* The display:flex above overrides the [hidden] attribute (class beats UA
   sheet), so collapse must be driven by the class, not bdy.hidden alone. */
.globe-profile__mktgroup.is-collapsed .globe-profile__mktgroup-body { display: none; }
.globe-profile__sub { font-size: var(--text-xs); color: var(--ink-muted); margin-top: 2px; }
.globe-profile__spark-wrap { position: relative; margin-top: var(--sp-2); }
.globe-profile__spark { display: block; width: 100%; height: 30px; color: var(--accent); cursor: crosshair; }
.globe-profile__spark-dot {
  position: absolute; width: 6px; height: 6px; margin: -3px 0 0 -3px;
  border-radius: 50%; background: var(--accent); pointer-events: none;
  box-shadow: 0 0 0 2px var(--bg-elev-1);
}
.globe-profile__spark-dot[hidden] { display: none; }
.globe-profile__tip {
  position: absolute; bottom: 100%; transform: translate(-50%, -4px);
  background: var(--ink); color: var(--bg-elev-1);
  font-size: var(--text-xs); line-height: 1.4; padding: 2px 7px;
  border-radius: var(--r-sm); white-space: nowrap; pointer-events: none;
  box-shadow: var(--shadow-2); z-index: var(--z-globe-2);
}
.globe-profile__tip[hidden] { display: none; }
.globe-profile__tag {
  font-size: var(--text-xs);
  color: var(--tag-topic);
  background: color-mix(in srgb, var(--tag-topic) 12%, transparent);
  border-radius: var(--r-sm);
  padding: 1px 6px;
}
/* Clickable topic chip (multi-select) — filters the right country-headlines list. */
.globe-profile__tag--toggle {
  border: 1px solid color-mix(in srgb, var(--tag-topic) 32%, transparent);   /* G1: kill sub-pixel border (0.5px -> 1px, same colour) */
  cursor: pointer;
  font-family: inherit;
  line-height: 1.5;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.globe-profile__tag--toggle:hover { background: color-mix(in srgb, var(--tag-topic) 22%, transparent); }
.globe-profile__tag--toggle[aria-pressed="true"] {
  background: var(--tag-topic);
  color: #fff;
  border-color: var(--tag-topic);
}
.globe-profile__outlets { list-style: none; margin: 0; padding: 0; }
.globe-profile__outlets li { font-size: var(--text-sm); color: var(--ink-muted); padding: 2px 0; }
/* JS writes `width` + `background` inline on each segment (never touched here);
   the pill radius gives rounded caps and the hairline inset separates adjacent
   leans without altering their JS-driven widths. */
.globe-profile__lean { display: flex; height: 8px; border-radius: 999px; overflow: hidden; }
.globe-profile__lean > span + span { box-shadow: inset 1px 0 0 var(--glass-hairline); }
.globe-profile__legend { font-size: var(--text-xs); color: var(--ink-dim); margin-top: 4px; }
.globe-profile__cov-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
/* G7: period/window select archetype REFERENCE — bg-elev-2 + 1px --border + --r-sm.
   This rule already matches the chosen recipe; the other three variants
   (.event-view__window select, .globe-data-pop__period, .globe-legend__period)
   were unified to it. background-color (not shorthand) is kept so the chevron
   background-image below survives. */
.globe-profile__period {
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  color: var(--ink-muted);
  background-color: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 2px 22px 2px 8px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none' stroke='%237a8694' stroke-width='1.5'><path d='M3 4.5l3 3 3-3'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 10px 10px;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease);
}
.globe-profile__period:hover { border-color: var(--border-strong); }
.globe-profile__period:focus { border-color: var(--link); } /* A1: keyboard ring from :focus-visible baseline (~226) */
.globe-profile__idrow { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.globe-profile__flag {
  display: block;
  height: 20px;
  width: auto;
  border-radius: var(--r-sm);   /* D3c — 4px, unified profile card/chip radius (was 2px) */
  box-shadow: 0 0 0 1px var(--border);
}
.globe-profile__offname { font-size: var(--text-xs); color: var(--ink-dim); }
.globe-profile__facts {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 var(--sp-3);
  margin: 0;
  font-size: var(--text-xs);
}
.globe-profile__facts dt { color: var(--ink-dim); white-space: nowrap; }
.globe-profile__facts dd { margin: 0; color: var(--ink); }
/* Fact rows separated by hairlines (terminal ledger). The row-gap is dropped to
   0 above; each row past the first pays a hairline + 4px top pad instead, so the
   net vertical rhythm shifts by ~2px (density-safe). The first row (lead figure)
   stays flush. */
.globe-profile__facts dt:not(:first-of-type),
.globe-profile__facts dd:not(:first-of-type) {
  border-top: 1px solid var(--glass-hairline);
  padding-top: var(--sp-1);
}
/* D3a — per-section headline number: the FIRST metric value of each facts grid
   gets the serif display promotion (same convention as .globe-profile__big, the
   coverage count). Editorial serif on the lead figure gives every section a clear
   focal point. The plain-dd sections (identity/governance/strategic) promote the
   dd itself; the economy section's dd is a flex row, so promote its first span
   (the value) and leave the year/delta chips at their UI size. */
.globe-profile__facts dd:first-of-type {
  font-family: var(--font-serif);
  font-size: var(--text-md);
  line-height: 1.15;
  font-variant-numeric: tabular-nums;   /* G3: lead figure aligns like a readout */
}
.globe-profile__facts dd.globe-profile__econ-dd:first-of-type { font-family: inherit; font-size: inherit; }
.globe-profile__facts dd.globe-profile__econ-dd:first-of-type > span:first-child {
  font-family: var(--font-serif);
  font-size: var(--text-md);
  line-height: 1.15;
  font-variant-numeric: tabular-nums;   /* G3: economy lead value aligns like a readout */
}
.globe-profile__leader { display: flex; align-items: center; gap: var(--sp-2); margin: var(--sp-2) 0; }
.globe-profile__leader-photo,
.globe-profile__leader-av {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: var(--r-sm);   /* D3c — 4px, unified profile card/chip radius (was 6px) */
  border: 1px solid var(--glass-hairline);   /* G1: kill sub-pixel border (0.5px -> 1px); neutral --border case on the glass panel -> --glass-hairline */
  background: var(--bg-elev-2);
}
.globe-profile__leader-photo { object-fit: cover; }
.globe-profile__leader-av {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-dim);
}
.globe-profile__leader-name { font-size: var(--text-sm); font-weight: 600; line-height: 1.2; }
.globe-profile__leader-title { font-size: var(--text-xs); color: var(--ink-dim); margin-top: 2px; }
.globe-profile__econ-dd {
  display: flex;
  gap: 6px;
  align-items: baseline;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.globe-profile__econ-yr { font-size: var(--text-xs); color: var(--ink-dim); }
.globe-profile__econ-chg { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-dim); font-weight: 600; font-variant-numeric: tabular-nums; }
/* D3b — YoY delta coloured by sign (matches the markets-row convention). No
   modifier (no-delta rows never render a chg span) → neutral --ink-dim above. */
.globe-profile__econ-chg--up { color: var(--positive); }
.globe-profile__econ-chg--down { color: var(--negative); }
.globe-profile__econ-chg--flat { color: var(--ink-muted); }
.globe-profile__substrong { font-size: var(--text-xs); color: var(--ink-dim); margin: 8px 0 5px; }
.globe-profile__substrong .globe-profile__econ-yr { margin-left: 6px; }
.globe-profile__chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.globe-profile__chip {
  font-family: inherit;
  font-size: var(--text-xs);
  padding: 2px 8px;
  border-radius: var(--r-sm);   /* D3c — 4px, unified with __badge/__tag (was 999px pill) */
  border: 1px solid var(--border-strong);   /* G1: kill sub-pixel border (0.5px -> 1px, same colour — interactive chip keeps --border-strong) */
  background: var(--bg-elev-2);
  color: var(--ink);
  cursor: pointer;
}
.globe-profile__chip:hover { border-color: var(--link); }
.globe-profile__chip-sh { font-family: var(--font-mono); font-size: var(--text-3xs); color: var(--ink-dim); margin-left: 4px; }
.globe-profile__nb { text-align: left; line-height: 1.5; }
.globe-profile__link {
  font: inherit;
  font-size: var(--text-xs);
  background: none;
  border: 0;
  padding: 0;
  color: var(--link);
  cursor: pointer;
}
.globe-profile__link:hover { text-decoration: underline; }
.globe-lightbox {
  position: fixed;
  inset: 0;
  /* collision (audit #71): shares 9999 with .theme-fade-overlay. Kept
     identical; the two are never open simultaneously so order is moot. */
  z-index: var(--z-overlay-top);
  background: var(--scrim-82);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 24px;
  cursor: zoom-out;
}
.globe-lightbox__img {
  max-width: 90vw;
  max-height: 82vh;
  border-radius: var(--r-md);
  box-shadow: 0 8px 40px var(--scrim-50);
  background: var(--bg-elev-2);
}
.globe-lightbox__cap {
  color: #fff;
  font-size: var(--text-sm);
  text-align: center;
  max-width: 90vw;
}

.globe-panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
  border-bottom: 1px solid var(--glass-hairline);
}
.globe-panel__title {
  font-family: var(--font-serif);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--ink);
  /* Long country names (e.g. "Bosnia and Herzegovina") still need to fit
   * — wrap rather than truncate so the user always sees the full name. */
  word-break: keep-all;
}
.globe-panel__close {
  appearance: none;
  width: 32px; height: 32px;
  border: 0;
  background: transparent;
  color: var(--ink-muted);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--r-sm);
  display: inline-grid;
  place-items: center;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.globe-panel__close:hover,
.globe-panel__close:focus-visible {
  background: var(--accent-soft);
  color: var(--accent);
  outline: none;
}
.globe-panel__close:focus-visible {
  box-shadow: var(--focus-ring);
}

.globe-panel__list {
  list-style: none;
  margin: 0;
  padding: 0 var(--sp-5);
  overflow-y: auto;
  flex: 1 1 auto;
  /* Smooth scroll feel; momentum on iOS. */
  -webkit-overflow-scrolling: touch;
  /* Hotfix#2 (2026-04-28): give the list a min-width:0 anchor so the
   * `.article--compact` flex children can actually shrink below their
   * intrinsic content width. Without this the .article__title's longest
   * unbreakable token (a long URL or a long ALL-CAPS proper noun) keeps
   * the row at its preferred width and the meta column gets squeezed. */
  min-width: 0;
}
.globe-panel__list > li.article--compact {
  /* Per-row min-width chain so the meta column inside actually shrinks. */
  min-width: 0;
}

.globe-panel__loading,
.globe-panel__error,
.globe-panel__empty {
  /* Quiet centred column, unified with .event-list__empty / .saved-list__empty
     so all four panel placeholders share one composition. A lone text node
     (today's loading/empty/error copy) renders exactly as the previous
     text-align:center did; the flex column also lets a future retry <button>
     (spec §1.6 error affordance — see html_js_requests) stack under the copy
     with a 4px-grid gap instead of trailing it inline. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-5) 0;
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  text-align: center;
  list-style: none;
}
.globe-panel__error { color: var(--warm-text); }   /* C6 — text on light */
/* (Glass Terminal, 2026-07-12) Drop the "no headlines" empty copy to the faint
   meta tier (--ink-dim), matching the country/event/saved empty states so all
   four empty placeholders share one voice. Loading stays --ink-muted (transient,
   slightly more present); error keeps --warm-text above. Later + equal
   specificity than the shared rule, so this wins without !important. */
.globe-panel__empty { color: var(--ink-dim); }

