/* ═══════════════════════════════════════════════════════════
   globe.css — Irides Globe (public page + admin placement tool)
   Built entirely from the existing design tokens in style.css
   (--bg, --text, --border, --font-display, --radius, etc.)
   so it inherits the site's theme switching for free.
═══════════════════════════════════════════════════════════ */

/* ─── PUBLIC PAGE LAYOUT ─────────────────────────────────── */
.globe-main {
  display: flex;
  flex-direction: column;
  min-height: calc(100dvh - var(--header-h, 88px));
  position: relative;
}

.globe-intro {
  padding: 40px clamp(20px, 5vw, 64px) 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.globe-intro-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.globe-timelines-btn {
  flex-shrink: 0;
  margin-top: 6px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--text-mid);
  background: var(--bg);
  border: 1px solid var(--border-light);
  border-radius: 999px;
  padding: 8px 16px;
  box-shadow: var(--shadow-sm);
  transition: all var(--transition);
  white-space: nowrap;
}
.globe-timelines-btn:hover { border-color: var(--accent); color: var(--accent); }
.globe-timelines-btn svg { flex-shrink: 0; }

.globe-eyebrow {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.globe-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 4vw, 42px);
  color: var(--text);
  letter-spacing: 0.01em;
}

.globe-stage-wrap {
  flex: 1;
  position: relative;
  margin: 12px clamp(12px, 4vw, 48px) 28px;
  min-height: 420px;
  /* Ensure the canvas can actually grow into available space */
  align-self: stretch;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-light);
  background: radial-gradient(circle at 50% 42%, var(--bg-2) 0%, var(--bg) 72%);
  overflow: hidden;
}

.globe-stage {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* The Three.js renderer sets inline width/height on the canvas element.
   Override with CSS so the canvas always fills the stage regardless of
   what pixel size the renderer calculated at init time (which can be
   wrong on mobile portrait if layout hadn't settled yet). The renderer's
   internal pixel buffer stays correct; this just makes the display layer
   stretch to fill the container at all times. */
.globe-canvas {
  touch-action: none;
  cursor: grab;
  display: block;
  width: 100% !important;
  height: 100% !important;
}
.globe-canvas:active { cursor: grabbing; }

.globe-hint {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  background: var(--bg);
  border: 1px solid var(--border-light);
  border-radius: 999px;
  padding: 7px 16px;
  pointer-events: none;
  opacity: 1;
  transition: opacity 600ms ease 2400ms;
}
.globe-stage-wrap.interacted .globe-hint { opacity: 0; }

.globe-empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 10px;
  color: var(--text-faint);
  font-size: 13px;
  text-align: center;
  padding: 24px;
}

/* ─── STAGE CONTROLS: territory jump-to select + fullscreen toggle ──── */
.globe-stage-controls {
  position: absolute;
  top: 14px;
  right: 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  z-index: 5;
}

.globe-territory-select {
  font-family: var(--font-body);
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border-light);
  border-radius: 999px;
  padding: 7px 14px;
  max-width: 50vw;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

.globe-fullscreen-btn {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid var(--border-light);
  color: var(--text-mid);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: all var(--transition);
}
.globe-fullscreen-btn:hover { border-color: var(--accent); color: var(--accent); }

/* While the browser's real Fullscreen API is engaged on .globe-stage-wrap,
   let it fill the entire screen and square off the corners. */
.globe-stage-wrap:fullscreen,
.globe-stage-wrap:-webkit-full-screen {
  margin: 0;
  border-radius: 0;
  border: none;
  height: 100dvh;
  min-height: 100dvh;
  max-height: 100dvh;
  background: var(--bg);
}
.globe-stage-wrap:fullscreen .globe-stage-controls,
.globe-stage-wrap:-webkit-full-screen .globe-stage-controls {
  top: max(14px, env(safe-area-inset-top));
  right: max(14px, env(safe-area-inset-right));
}

/* iOS Safari fallback (no element.requestFullscreen support): pin the
   stage over the full viewport with CSS and lock page scroll behind it. */
.globe-stage-wrap.ios-fullscreen-fallback {
  position: fixed;
  inset: 0;
  z-index: 999;
  margin: 0;
  border-radius: 0;
  border: none;
  min-height: 100dvh;
}
body.globe-ios-fullscreen-active { overflow: hidden; }

.globe-index {
  padding: 0 clamp(20px, 5vw, 64px) 48px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.globe-index-zone-heading {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 14px 2px 2px;
  border-bottom: 1px solid var(--border-light);
}
.globe-index-zone-heading:first-child { padding-top: 0; }

.globe-index-zone-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 10px 0 4px;
}

.globe-index-chip {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-mid);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 7px 14px;
  transition: all var(--transition);
}
.globe-index-chip:hover { border-color: var(--text-mid); color: var(--text); }

/* ─── PIN OVERLAY (shared by viewer + admin) ────────────────── */
.globe-pin-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The pin's JS-driven transform (see globe-core.js _updatePins) does
   translate(x, y) translate(-50%, -50%) scale(...) — i.e. it centers
   THIS box exactly on the projected 3D point and scales around that
   same center. So .globe-pin itself must be sized/positioned so its
   own center is the dot's center, with the label hanging below it
   *without* shifting that center — hence the dot wrapper below instead
   of relying on flex gap + content height (which made the box's visual
   center drift depending on label height, the original bug). */
.globe-pin {
  position: absolute;
  top: 0;
  left: 0;
  width: 10px;
  height: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  pointer-events: auto;
  will-change: transform, opacity;
  transform-origin: 50% 50%;
}

.globe-pin-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--pin-color, var(--accent));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pin-color, var(--accent)) 20%, transparent);
  position: relative;
}
.globe-pin-dot::before {
  content: '';
  position: absolute;
  inset: -6px;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--pin-color, var(--accent)) 50%, transparent);
  animation: globePinPulse 2.6s ease-out infinite;
}
@keyframes globePinPulse {
  0%   { transform: scale(0.6); opacity: 0.9; }
  100% { transform: scale(2.1); opacity: 0; }
}

.globe-pin-label {
  position: absolute;
  top: 100%;
  left: 50%;
  margin-top: 6px;
  transform: translate(-50%, 2px);
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-light);
  border-radius: 999px;
  padding: 4px 10px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--transition), transform var(--transition);
  box-shadow: var(--shadow-sm);
}
.globe-pin:hover .globe-pin-label,
.globe-pin:focus-visible .globe-pin-label { opacity: 1; transform: translate(-50%, 0); }

/* Dim-until-active mode (public globe page): pins sit at reduced opacity
   (combined with the per-frame facing fade in globe-core.js) until they're
   hovered or clicked. Transition is on the dot/label only — the wrapper's
   own opacity is driven every frame from JS, so it can't carry a CSS
   transition without fighting that per-frame update. */
.globe-pin-dimmable .globe-pin-dot,
.globe-pin-dimmable .globe-pin-dot::before { transition: filter var(--transition); }
.globe-pin-dimmable.globe-pin-hovered .globe-pin-dot,
.globe-pin-dimmable.globe-pin-active .globe-pin-dot {
  filter: drop-shadow(0 0 4px color-mix(in srgb, var(--pin-color, var(--accent)) 60%, transparent));
}

.globe-pin-preview { cursor: default; pointer-events: none; }
.globe-pin-preview .globe-pin-dot { background: var(--text-mid); }
.globe-pin-preview .globe-pin-dot::before { border-color: var(--text-mid); }

/* ─── TERRITORY DETAIL DRAWER (slides in from the right) ─────── */
#territoryDetailOverlay { align-items: stretch; justify-content: flex-end; }
.territory-detail-modal {
  width: min(420px, 92vw);
  height: 100%;
  max-height: 100%;
  margin: 0;
  border-radius: 0;
  display: flex;
  flex-direction: column;
  animation: territoryDrawerIn 280ms ease;
}
@keyframes territoryDrawerIn {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
.territory-detail-body { padding: 0; overflow-y: auto; flex: 1; }
.territory-detail-images {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  scrollbar-width: thin;
  scroll-snap-type: x mandatory;
}
.territory-detail-images img {
  width: 100%;
  max-height: 220px;
  object-fit: cover;
  flex: 1 0 100%;
  scroll-snap-align: start;
}
.territory-detail-text { padding: 20px; display: flex; flex-direction: column; gap: 16px; }
.territory-detail-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--text);
}
.territory-detail-icon-img {
  width: 26px;
  height: 26px;
  padding: 3px;
  border-radius: 6px;
  object-fit: contain;
  box-sizing: border-box;
  flex-shrink: 0;
}
.territory-detail-zonerow { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.territory-detail-section { display: flex; flex-direction: column; gap: 8px; }
.territory-detail-section-label {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.territory-detail-history {
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-mid);
  font-weight: 300;
  white-space: pre-wrap;
}
.territory-detail-coords {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* Characters Associated list (public) */
.detail-character-list { display: flex; flex-direction: column; gap: 4px; }
.detail-character-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  background: var(--bg-2);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--transition);
}
.detail-character-row:hover { border-color: var(--text-mid); }
.detail-character-thumb {
  width: 28px; height: 28px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--border-light);
  flex-shrink: 0;
}
.detail-character-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.detail-character-name { font-size: 12.5px; color: var(--text); }

/* Places of Interest list (public) */
.detail-poi-list { display: flex; flex-direction: column; gap: 4px; }
.detail-poi-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  background: var(--bg-2);
  cursor: pointer;
  text-align: left;
  width: 100%;
  transition: border-color var(--transition);
}
.detail-poi-row:hover { border-color: var(--text-mid); }
.detail-poi-thumb {
  width: 28px; height: 28px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--border-light);
  flex-shrink: 0;
}
.detail-poi-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.detail-poi-name { font-size: 12.5px; color: var(--text); }

/* Location Images grid (public) */
.detail-image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 6px;
}
.detail-image-cell {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border-light);
  cursor: pointer;
  display: block;
}
.detail-image-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }

.view-in-gallery-btn {
  font-family: var(--font-body);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  color: var(--text-mid);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 13px;
  align-self: flex-start;
  transition: all var(--transition);
}
.view-in-gallery-btn:hover { border-color: var(--accent); color: var(--accent); }

/* Character detail sub-panel (slides over the territory drawer) */
.character-detail-modal { width: min(380px, 92vw); height: 100%; margin: 0; border-radius: 0; display: flex; flex-direction: column; animation: territoryDrawerIn 220ms ease; }
.character-detail-body { padding: 20px; display: flex; flex-direction: column; gap: 14px; overflow-y: auto; flex: 1; }
.character-detail-name { font-family: var(--font-display); font-size: 20px; color: var(--text); }
.character-detail-image-card { display: flex; flex-direction: column; gap: 8px; }
.character-detail-image-card img {
  width: 100%;
  border-radius: var(--radius-md);
  object-fit: cover;
  max-height: 260px;
}

/* Hierarchy rank chip shown under a character's name in the detail panel */
.character-detail-rank-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: -6px; }
.character-detail-rank-chip { color: var(--accent); border-color: var(--accent); }

/* Character description (territory characters + faction characters + roster) */
.character-detail-desc {
  font-size: 13px;
  line-height: 1.7;
  color: var(--text-mid);
  font-weight: 300;
  white-space: pre-wrap;
}

/* Small abbreviation badge appended to a character row chip, e.g. "ZA" */
.detail-character-rank-badge {
  font-family: var(--font-body);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  color: var(--text-mid);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 8px;
  margin-left: auto;
  flex-shrink: 0;
}
.detail-character-row:hover .detail-character-rank-badge { border-color: var(--accent); color: var(--accent); }

/* Expandable "Hierarchy Details" panel inside the character drawer */
.character-hierarchy-details {
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  background: var(--bg-2);
  padding: 0;
  overflow: hidden;
}
.character-hierarchy-details summary {
  cursor: pointer;
  list-style: none;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-mid);
  padding: 10px 12px;
  transition: color var(--transition);
}
.character-hierarchy-details summary::-webkit-details-marker { display: none; }
.character-hierarchy-details summary::before {
  content: '+';
  display: inline-block;
  width: 12px;
  font-weight: 600;
}
.character-hierarchy-details[open] summary::before { content: '–'; }
.character-hierarchy-details:hover summary { color: var(--accent); }
.character-hierarchy-details-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0 12px 12px;
}
.hierarchy-detail-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12.5px;
  color: var(--text);
  line-height: 1.6;
}
.hierarchy-detail-label {
  font-size: 9.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* ─── FACTIONS (public) ───────────────────────────────────────── */
.globe-faction-btn {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 14px auto 0;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--text-mid);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 18px;
  transition: all var(--transition);
}
.globe-faction-btn:hover { border-color: var(--accent); color: var(--accent); }

.faction-list-modal { width: min(460px, 94vw); }
.faction-grid-list { display: flex; flex-direction: column; gap: 6px; padding: 4px 0; }
.faction-list-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border: 1px solid var(--border-light);
  border-radius: var(--radius);
  background: var(--bg-2);
  cursor: pointer;
  text-align: left;
  transition: border-color var(--transition);
}
.faction-list-row:hover { border-color: var(--text-mid); }
.faction-list-icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--border-light);
  flex-shrink: 0;
}
.faction-list-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }
.faction-list-name { font-size: 13px; color: var(--text); }

.faction-detail-modal { width: min(460px, 94vw); }
.faction-detail-header { display: flex; align-items: center; gap: 14px; padding: 4px 0 16px; }
.faction-detail-icon {
  width: 52px; height: 52px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--border-light);
  flex-shrink: 0;
}
.faction-detail-icon img { width: 100%; height: 100%; object-fit: cover; display: block; }
.faction-detail-name { font-family: var(--font-display); font-size: 20px; color: var(--text); }
.faction-detail-desc { font-size: 13px; line-height: 1.7; color: var(--text-mid); font-weight: 300; white-space: pre-wrap; margin-bottom: 16px; }

/* ─── ADMIN: GLOBE EDITOR SCREEN ─────────────────────────────── */
.globe-editor-body { padding: 16px; overflow-y: auto; flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 18px; }

.globe-asset-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.globe-asset-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.globe-asset-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.globe-asset-label { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-faint); }
.globe-asset-name { font-size: 12px; color: var(--text-mid); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.globe-asset-name.set { color: var(--text); }

.globe-admin-stage-wrap {
  position: relative;
  flex: none;
  width: 100%;
  aspect-ratio: 1 / 1;
  max-height: min(60vh, 420px);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-light);
  background: radial-gradient(circle at 50% 42%, var(--bg-2) 0%, var(--bg) 72%);
  overflow: hidden;
  transition: none;
}
.globe-admin-stage {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.globe-admin-stage .globe-canvas {
  width: 100% !important;
  height: 100% !important;
}
.globe-admin-hint {
  font-size: 11px;
  color: var(--text-faint);
  text-align: center;
}

.globe-admin-expand-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--text-mid);
  background: var(--bg);
  border: 1px solid var(--border-light);
  border-radius: 999px;
  padding: 6px 12px;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: all var(--transition);
}
.globe-admin-expand-btn:hover { border-color: var(--accent); color: var(--accent); }

/* Expanded mode: the preview pops out of the admin panel's normal flow
   and fills the viewport, so aiming pins isn't squeezed into a tiny
   280px-tall box. Toggled by JS adding .expanded to the stage wrap; the
   rest of the editor body stays exactly where it is underneath. */
.globe-admin-stage-wrap.expanded {
  position: fixed;
  inset: 0;
  z-index: 1000;
  width: auto;
  height: 100dvh;
  max-height: none;
  aspect-ratio: auto;
  border-radius: 0;
  border: none;
}
.globe-admin-stage-wrap.expanded .globe-admin-expand-btn {
  top: max(14px, env(safe-area-inset-top));
  right: max(14px, env(safe-area-inset-right));
}
body.globe-admin-expanded-active { overflow: hidden; }

.globe-territory-list { display: flex; flex-direction: column; gap: 6px; }
.globe-territory-zone-header {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 8px 2px 2px;
  border-bottom: 1px solid var(--border-light);
  margin-top: 4px;
}
.globe-territory-zone-header:first-child { margin-top: 0; }
.globe-territory-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-2);
}
.globe-territory-item-swatch {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}
.globe-territory-item-name {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.globe-territory-item-coords { font-size: 10px; color: var(--text-faint); flex-shrink: 0; }
.globe-territory-empty { font-size: 12px; color: var(--text-faint); text-align: center; padding: 14px; }

/* ─── ADMIN: Places of Interest list (inside Territory form) ──── */
.poi-list { display: flex; flex-direction: column; gap: 6px; }
.poi-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-2);
  cursor: pointer;
}
.poi-item-thumb {
  width: 26px; height: 26px;
  flex-shrink: 0;
  border-radius: 5px;
  overflow: hidden;
  background: var(--bg);
}
.poi-item-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.poi-item-name {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.poi-item-remove {
  width: 18px; height: 18px;
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--text-faint);
  background: none;
  border: none;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.poi-item-remove:hover { color: var(--danger); background: var(--border-light); }
.poi-form-modal { width: min(480px, 96vw); }

/* ─── ADMIN: Places of Interest (sub-list within Territory form) ── */
.poi-list { display: flex; flex-direction: column; gap: 6px; }
.poi-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-2);
  cursor: pointer;
}
.poi-item-thumb {
  width: 26px; height: 26px;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg);
  flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.poi-item-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.poi-item-name {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.poi-item-remove {
  width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--text-faint);
  background: none;
  border: none;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.poi-item-remove:hover { color: var(--danger); background: var(--border-light); }
.poi-form-modal { width: min(480px, 94vw); }

/* Hierarchy editor: rank-group headings + abbreviation tag (admin) */
.hierarchy-rank-heading {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 8px 2px 2px;
  border-bottom: 1px solid var(--border-light);
  margin-top: 4px;
}
.hierarchy-rank-heading:first-child { margin-top: 0; }
.hierarchy-abbrv-tag {
  font-size: 10px;
  letter-spacing: 0.05em;
  color: var(--text-mid);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 1px 7px;
  margin-left: 4px;
}

/* ─── ADMIN: TERRITORY FORM MODAL ────────────────────────────── */
.territory-form-modal { width: min(460px, 96vw); }
.territory-form-coords-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.territory-form-coords {
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: 0.04em;
}
.territory-pin-color-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.territory-pin-color-input {
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: none;
  cursor: pointer;
  flex-shrink: 0;
}
.territory-pin-color-value {
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-mid);
  font-family: monospace;
}

.territory-img-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 6px;
  max-height: 180px;
  overflow-y: auto;
  padding: 2px;
}
.territory-img-cell {
  position: relative;
  aspect-ratio: 1;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1.5px solid var(--border);
  cursor: pointer;
}
.territory-img-cell img { width: 100%; height: 100%; object-fit: cover; display: block; }
.territory-img-cell.selected { border-color: var(--accent); }
.territory-img-cell.selected::after {
  content: '✓';
  position: absolute;
  top: 3px;
  right: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg);
  font-size: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ─── ADMIN: CARD-TERRITORY / ZONE / ENERGY (territory form) ──── */
.territory-zone-energy-row { display: flex; flex-wrap: wrap; gap: 6px; margin: -4px 0 4px; }
.zone-energy-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  letter-spacing: 0.03em;
  color: var(--text-mid);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 10px;
}
.zone-energy-chip.zone-chip { color: var(--accent); border-color: var(--accent); }
.zone-energy-chip .chip-icon { width: 14px; height: 14px; padding: 2px; box-sizing: border-box; border-radius: 3px; object-fit: contain; flex-shrink: 0; }
.zone-energy-chip .energy-color-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1px solid rgba(0,0,0,0.18);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.35) inset;
}
.chip-icon-upload-btn {
  width: 14px; height: 14px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: none;
  border: 1px dashed var(--text-faint);
  color: var(--text-faint);
  font-size: 10px;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.chip-icon-upload-btn:hover { border-color: var(--accent); color: var(--accent); }

/* Territory icon, next to the Name field */
.territory-name-icon-row { display: flex; align-items: center; gap: 8px; }
.territory-name-icon-row input.panel-input { flex: 1; }
.territory-icon-control { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.territory-icon-preview {
  width: 32px; height: 32px;
  padding: 4px;
  box-sizing: border-box;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-2);
  border: 1px solid var(--border);
  flex-shrink: 0;
}
.territory-icon-preview img { width: 100%; height: 100%; object-fit: contain; display: block; }
.territory-icon-upload-btn {
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text-mid);
  cursor: pointer;
  flex-shrink: 0;
}
.territory-icon-upload-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.territory-icon-upload-btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ─── ADMIN: field-label-row + chip-list (characters associated) ── */
.field-label-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.chip-list { display: flex; flex-wrap: wrap; gap: 6px; min-height: 28px; }
.char-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--text);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 6px 5px 11px;
}
.char-chip-remove {
  width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--text-faint);
  background: none;
  border: none;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.char-chip-remove:hover { color: var(--danger); background: var(--border-light); }

/* ─── ADMIN: removable image cells (Location/Character Images) ── */
.img-cell-remove {
  position: absolute;
  top: 3px; right: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: none;
  font-size: 13px;
  line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.img-cell-missing {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-size: 9px;
  color: var(--text-faint);
  background: var(--bg-2);
  text-align: center;
  padding: 4px;
}

/* ─── ADMIN: fullscreen image lightbox ───────────────────────── */
.image-lightbox-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: rgba(0,0,0,0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(16px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) max(16px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
}
.image-lightbox-img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: var(--radius);
}
.image-lightbox-close {
  position: absolute;
  top: max(14px, env(safe-area-inset-top));
  right: max(14px, env(safe-area-inset-right));
  width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: rgba(0,0,0,0.55);
  border: 1px solid rgba(255,255,255,0.25);
  color: #fff;
  cursor: pointer;
}
.image-lightbox-close:hover { border-color: var(--accent); color: var(--accent); }

/* Expand button shown on any pickable/picked image cell to preview fullscreen */
.img-cell-expand {
  position: absolute;
  bottom: 3px; left: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: rgba(0,0,0,0.55);
  color: #fff;
  border: none;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.img-cell-expand:hover { background: var(--accent); }
.img-cell-expand svg { width: 10px; height: 10px; display: block; }

/* ─── ADMIN: artwork picker modal (reusable) ─────────────────── */
.artwork-picker-modal { width: min(620px, 96vw); }
.artwork-picker-list { display: flex; flex-direction: column; gap: 18px; max-height: 60vh; overflow-y: auto; }
.artwork-picker-group-title {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 8px;
}

/* ─── ADMIN: character picker modal ──────────────────────────── */
.character-picker-modal { width: min(420px, 94vw); }
.character-picker-list { display: flex; flex-direction: column; gap: 4px; max-height: 50vh; overflow-y: auto; }
.character-picker-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: var(--radius);
  cursor: pointer;
}
.character-picker-row:hover { background: var(--bg-2); }
.character-picker-row input[type="checkbox"] { flex-shrink: 0; }
.character-picker-thumb {
  width: 26px; height: 26px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--border-light);
  flex-shrink: 0;
}
.character-picker-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.character-picker-name { font-size: 12.5px; color: var(--text); }

/* ─── ADMIN: faction icon uploader ───────────────────────────── */
.faction-icon-row { display: flex; align-items: center; gap: 12px; margin-top: 4px; }
.faction-icon-preview {
  width: 48px; height: 48px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-2);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.faction-icon-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.faction-icon-placeholder { font-size: 9px; color: var(--text-faint); text-align: center; }

/* ═══════════════════════════════════════════════════════════
   TIMELINE PANEL — full-screen slide-out drawer (js/timeline.js)
   A vertical rail with era-grouped colour accents. Three field
   clusters per entry: Year/Event (always visible), Era Background
   /Event Details (always visible, slightly muted), and the
   Influence/Remedy/Documentation/Characters/Zones cluster, which
   is collapsed behind a "Details" toggle to keep the rail scannable.
═══════════════════════════════════════════════════════════ */
.timeline-overlay {
  position: fixed;
  inset: 0;
  z-index: 1200;
  background: rgba(0,0,0,0.45);
  backdrop-filter: blur(5px);
  display: flex;
  justify-content: flex-end;
  animation: fadeIn 0.18s ease;
}

.timeline-panel {
  width: min(720px, 100vw);
  height: 100%;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  display: flex;
  flex-direction: column;
  animation: slideInRight 0.26s cubic-bezier(0.4,0,0.2,1);
  min-width: 0;
}

.timeline-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 22px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.timeline-panel-heading {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.timeline-panel-eyebrow {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.timeline-panel-title {
  font-family: var(--font-display);
  font-size: 19px;
  font-style: italic;
  color: var(--text);
}

.timeline-panel-body {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 28px clamp(18px, 4vw, 36px) 60px;
}

/* ─── The rail ───────────────────────────────────────────── */
.timeline-rail {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0;
}

/* The vertical line running through all entries */
.timeline-rail::before {
  content: '';
  position: absolute;
  top: 6px;
  bottom: 6px;
  left: 7px;
  width: 1.5px;
  background: var(--border);
}

.timeline-entry {
  position: relative;
  padding: 0 0 30px 32px;
}
.timeline-entry:last-child { padding-bottom: 4px; }

.timeline-entry-dot {
  position: absolute;
  top: 5px;
  left: 0;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--era-color, var(--accent));
  z-index: 1;
}
.timeline-entry-dot::after {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--era-color, var(--accent));
}

/* ── Cluster 1: Year (Era) + Event — always the most prominent ── */
.timeline-entry-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px 12px;
  margin-bottom: 6px;
}

.timeline-entry-year {
  font-family: var(--font-display);
  font-size: clamp(19px, 2.4vw, 23px);
  font-weight: 500;
  color: var(--text);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.timeline-entry-era-tag {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.05em;
  color: var(--era-color, var(--text-mid));
  background: color-mix(in srgb, var(--era-color, var(--text-mid)) 12%, transparent);
  border-radius: 999px;
  padding: 3px 10px;
  white-space: nowrap;
}

.timeline-entry-event {
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 500;
  color: var(--text);
  letter-spacing: 0.01em;
  margin-bottom: 10px;
}

/* ── Cluster 2: Era Background + Event Details ── */
.timeline-entry-narrative {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-bottom: 12px;
}

.timeline-entry-field {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.timeline-entry-field-label {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.timeline-entry-field-text {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 300;
  line-height: 1.6;
  color: var(--text-mid);
}

/* ── Cluster 3: collapsible Influence/Remedy/Docs/Characters/Zones ── */
.timeline-entry-toggle {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--text-mid);
  background: none;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 12px 5px 10px;
  transition: all var(--transition);
}
.timeline-entry-toggle:hover { border-color: var(--era-color, var(--text-mid)); color: var(--text); }
.timeline-entry-toggle svg { flex-shrink: 0; transition: transform var(--transition); }
.timeline-entry.expanded .timeline-entry-toggle svg { transform: rotate(180deg); }
.timeline-entry.expanded .timeline-entry-toggle { border-color: var(--era-color, var(--text-mid)); color: var(--text); }

.timeline-entry-details {
  display: grid;
  grid-template-rows: 0fr;
  overflow: hidden;
  transition: grid-template-rows 280ms cubic-bezier(0.4,0,0.2,1);
}
.timeline-entry.expanded .timeline-entry-details {
  grid-template-rows: 1fr;
}
.timeline-entry-details-inner {
  min-height: 0;
  overflow: hidden;
}

.timeline-entry-detail-grid {
  margin-top: 12px;
  padding: 14px 16px;
  background: var(--bg-2);
  border-radius: var(--radius-md);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.timeline-entry-detail-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.timeline-entry-detail-row .timeline-entry-field-label { color: var(--era-color, var(--text-faint)); }
.timeline-entry-detail-row .timeline-entry-field-text { color: var(--text); }

.timeline-entry-tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
}
.timeline-entry-tag {
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 11px;
}
.timeline-entry-tag.zone-tag {
  color: var(--era-color, var(--text));
  border-color: var(--era-color, var(--border));
}

/* ── Filter chips at the top of the panel body ── */
.timeline-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 26px;
}
.timeline-filter-chip {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.03em;
  color: var(--text-mid);
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 6px 13px;
  transition: all var(--transition);
}
.timeline-filter-chip:hover { border-color: var(--text-mid); color: var(--text); }
.timeline-filter-chip.active {
  color: var(--surface);
  background: var(--accent);
  border-color: var(--accent);
}

/* ─── RESPONSIVE ─────────────────────────────────────────────── */
@media (max-width: 640px) {
  .globe-stage-wrap {
    /* Fill all remaining vertical space after the intro text */
    flex: 1;
    min-height: 0;          /* override the 340px floor — let flex drive height instead */
    margin: 10px 12px 20px;
    /* Prevent the box from collapsing if content is sparse */
    height: 0;              /* flex-basis trick: with flex:1 this makes it stretch fully */
  }
  .globe-title { font-size: 26px; }
  .globe-stage-controls { top: 10px; right: 10px; left: 10px; justify-content: flex-end; }
  .globe-territory-select { max-width: 60vw; font-size: 11px; padding: 6px 10px; }

  .globe-intro { flex-wrap: wrap; }
  .globe-timelines-btn { font-size: 11px; padding: 7px 13px; margin-top: 2px; }

  .timeline-overlay { justify-content: stretch; }
  .timeline-panel { width: 100%; }
  .timeline-panel-header { padding: 14px 16px; }
  .timeline-panel-title { font-size: 17px; }
  .timeline-panel-body { padding: 20px 16px 48px; }
  .timeline-rail::before { left: 6px; }
  .timeline-entry { padding-left: 26px; padding-bottom: 26px; }
  .timeline-entry-dot { width: 13px; height: 13px; }
  .timeline-entry-year { font-size: 18px; }
  .timeline-entry-event { font-size: 13.5px; }
}

/* Portrait-specific: when the device is taller than it is wide, maximise
   the globe area so zooming doesn't crop the bottom */
@media (max-width: 640px) and (orientation: portrait) {
  .globe-main {
    /* Clamp the intro section so the globe gets the lion's share */
    display: flex;
    flex-direction: column;
  }
  .globe-intro {
    flex-shrink: 0;
  }
  .globe-stage-wrap {
    flex: 1 1 auto;
    min-height: 0;
    /* At minimum use 55% of the dynamic viewport height so it never shrinks
       to nothing on very short phones, but will grow taller on tall ones */
    height: max(55dvh, 320px);
  }
  /* Push faction btn + index below without stealing globe height */
  .globe-faction-btn,
  .globe-index {
    flex-shrink: 0;
  }
}
