/* =============================================================================
   Chaos Sphere Generator — standalone stylesheet
   -----------------------------------------------------------------------------
   Sections:
     1. Reset + body defaults
     2. Glass control panel + tabs (cp-* / ctrl-*)
     3. Form controls (cs-* sliders, toggles, selects, colors, gradients)
     4. Buttons (cp-btn)
     5. Keyboard shortcut rows
     6. Toast notifications
     7. Welcome modal (wm-*)
     8. Help button (cp-help-btn)
     9. Mobile / touch adjustments
    10. Sphere-specific UI (export grid, shader editor, texture grid, trip
        confirm overlay, charge-sigil editor)
   ========================================================================== */

/* ---- 1. Reset + body defaults ------------------------------------------- */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: #000;
  color: #eee;
  font-family: 'SF Mono', 'Fira Code', 'Menlo', 'Consolas', monospace;
  font-size: 12px;
  -webkit-text-size-adjust: 100%;
}

/* "Know more" link bottom-right */
#know-more-link {
  position: fixed;
  bottom: 12px;
  right: 16px;
  color: rgba(255, 255, 255, 0.35);
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 11px;
  text-decoration: none;
  z-index: 10000;
  transition: color 0.2s;
}
#know-more-link:hover { color: rgba(79, 195, 247, 0.8); }

/* ---- 2. Glass control panel + tabs -------------------------------------- */
.cp-panel {
  position: fixed;
  left: 16px;
  top: 16px;
  display: flex;
  flex-direction: column;
  /* Shared backing for the sticky tab bar + sticky Trip launcher. They must
     mask content scrolling under them, so they're a touch more opaque than the
     panel — driven from one var so the two stay in lockstep and track the
     per-breakpoint panel tone (a hardcoded 0.95 read as a mismatched black
     square on the more-translucent mobile panel). */
  --cp-sticky-bg: rgba(0, 0, 0, 0.95);
  background: rgba(0, 0, 0, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 12px;
  color: #eee;
  font-family: 'SF Mono', 'Fira Code', monospace;
  font-size: 12px;
  z-index: 10000;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5);
  user-select: none;
  min-width: 44px;
  transition: width 0.2s ease;
}

.cp-tab {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  cursor: pointer;
  border-bottom: 1px solid transparent;
  border-radius: 12px 12px 0 0;
}
.cp-tab:hover { background: rgba(255, 255, 255, 0.04); }
.cp-panel.collapsed .cp-tab { border-radius: 12px; border-bottom-color: transparent; }
.cp-panel:not(.collapsed) .cp-tab { border-bottom-color: rgba(255, 255, 255, 0.1); }

.cp-tab-icon  { font-size: 16px; color: #4fc3f7; }
.cp-tab-label { font-weight: bold; font-size: 14px; }
.cp-tab-status {
  margin-left: auto;
  font-size: 11px;
  color: #4fc3f7;
  transition: opacity 0.2s;
  opacity: 0.4;
}
.cp-tab-status.active { opacity: 1; animation: pulse 1.5s ease-in-out infinite; }
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}

.cp-body {
  padding: 10px 14px;
  width: 320px;
  max-height: calc(100vh - 80px);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}
.cp-panel.collapsed .cp-body { display: none; }
.cp-body::-webkit-scrollbar       { width: 5px; }
.cp-body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 3px; }

.ctrl-tabs {
  display: flex;
  gap: 2px;
  margin-bottom: 10px;
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--cp-sticky-bg);
  padding-bottom: 4px;
}
.ctrl-tab {
  flex: 1;
  /* min-width:0 lets the flex:1 tabs shrink to share the row instead of
     overflowing .ctrl-tabs and poking the last tab ("Actions") past the
     sticky background's right edge. Without it, flex items keep their
     default min-width:auto (content width) and the row overflows. */
  min-width: 0;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: #888;
  padding: 5px 4px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 10px;
  font-family: inherit;
  transition: all 0.15s;
}
.ctrl-tab:hover { background: rgba(255, 255, 255, 0.1); color: #ccc; }
.ctrl-tab.active {
  background: rgba(79, 195, 247, 0.12);
  color: #4fc3f7;
  border-color: rgba(79, 195, 247, 0.3);
}
.ctrl-tab-content         { display: none; }
.ctrl-tab-content.active  { display: block; }

/* ---- 3. Form controls (cs-*) -------------------------------------------- */
.cs-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 10px;
}
.cs-label { font-size: 10px; color: #aaa; letter-spacing: 0.5px; }
.cs-slider-wrap { display: flex; align-items: center; gap: 8px; }
.cs-slider {
  flex: 1;
  height: 4px;
  -webkit-appearance: none;
  appearance: none;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 2px;
  outline: none;
  cursor: pointer;
}
.cs-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px;
  background: #4fc3f7;
  border-radius: 50%;
  cursor: pointer;
  border: none;
}
.cs-slider::-moz-range-thumb {
  width: 12px; height: 12px;
  background: #4fc3f7;
  border-radius: 50%;
  cursor: pointer;
  border: none;
}
.cs-val {
  font-size: 10px;
  color: #4fc3f7;
  min-width: 36px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Toggle */
.cs-toggle-wrap { display: inline-flex; align-items: center; cursor: pointer; }
.cs-toggle      { display: none; }
.cs-toggle-indicator {
  width: 28px; height: 14px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 7px;
  position: relative;
  transition: background 0.2s;
  flex-shrink: 0;
}
.cs-toggle-indicator::after {
  content: '';
  position: absolute;
  top: 2px; left: 2px;
  width: 10px; height: 10px;
  background: #888;
  border-radius: 50%;
  transition: all 0.2s;
}
.cs-toggle:checked + .cs-toggle-indicator         { background: rgba(79, 195, 247, 0.3); }
.cs-toggle:checked + .cs-toggle-indicator::after  { left: 16px; background: #4fc3f7; }

/* Select dropdown */
.cs-select {
  flex: 1;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #ccc;
  padding: 5px 6px;
  border-radius: 4px;
  font-size: 10px;
  font-family: inherit;
  outline: none;
  text-transform: capitalize;
  cursor: pointer;
}
.cs-select:focus { border-color: rgba(79, 195, 247, 0.5); }

/* Color input */
.cs-color {
  -webkit-appearance: none;
  appearance: none;
  width: 36px; height: 22px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 4px;
  cursor: pointer;
  background: none;
  padding: 0;
  flex-shrink: 0;
}
.cs-color::-webkit-color-swatch-wrapper { padding: 2px; }
.cs-color::-webkit-color-swatch         { border: none; border-radius: 2px; }
.cs-color::-moz-color-swatch            { border: none; border-radius: 2px; }
.cs-color-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.cs-color-row .cs-label { margin-bottom: 0; flex: 1; }

/* Gradient editor (used in Lighting tab) */
.gradient-preview {
  height: 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 4px;
  margin: 6px 0;
}
.gradient-stops-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 160px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
}
.gradient-stop-row {
  display: grid;
  grid-template-columns: 30px 1fr 32px 18px;
  align-items: center;
  gap: 6px;
}
.gradient-stop-row .cs-color { width: 100%; height: 18px; }
.gradient-pos-slider {
  -webkit-appearance: none;
  appearance: none;
  height: 3px;
  background: rgba(255, 255, 255, 0.12);
  border-radius: 2px;
  outline: none;
  cursor: pointer;
  width: 100%;
}
.gradient-pos-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 10px; height: 10px;
  background: #4fc3f7;
  border-radius: 50%;
  cursor: pointer;
  border: none;
}
.gradient-pos-slider::-moz-range-thumb {
  width: 10px; height: 10px;
  background: #4fc3f7;
  border-radius: 50%;
  cursor: pointer;
  border: none;
}
.gradient-pos-label {
  font-size: 9.5px;
  color: #888;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.btn-remove {
  background: transparent;
  border: none;
  color: #666;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
  line-height: 1;
}
.btn-remove:hover:not(:disabled) { color: #ff5555; }
.btn-remove:disabled             { opacity: 0.25; cursor: default; }

.dg-add-stop {
  margin-top: 8px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: #aaa;
  font-family: inherit;
  font-size: 10px;
  padding: 5px 10px;
  border-radius: 4px;
  cursor: pointer;
  width: 100%;
  transition: all 0.15s;
}
.dg-add-stop:hover { background: rgba(255, 255, 255, 0.12); color: #ddd; }

/* ---- 4. Buttons (cp-btn) ------------------------------------------------ */
.cp-btn {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #ddd;
  padding: 8px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 11px;
  font-family: inherit;
  transition: all 0.15s;
  width: 100%;
  margin-bottom: 6px;
}
.cp-btn:hover { background: rgba(255, 255, 255, 0.15); border-color: rgba(255, 255, 255, 0.25); }

.cp-btn-start {
  background: rgba(79, 195, 247, 0.12);
  border-color: rgba(79, 195, 247, 0.3);
  color: #4fc3f7;
  font-weight: bold;
  padding: 10px 12px;
}
.cp-btn-start:hover { background: rgba(79, 195, 247, 0.22); }
.cp-btn-start.active {
  background: rgba(79, 195, 247, 0.25);
  color: #fff;
  border-color: #4fc3f7;
  animation: pulse 1.5s ease-in-out infinite;
}

/* ---- 5. Keyboard shortcut rows ----------------------------------------- */
.ctrl-keys {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  padding-top: 10px;
}
.ctrl-key-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
}
.ctrl-key-row kbd {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 3px;
  padding: 2px 6px;
  font-size: 10px;
  font-family: inherit;
  color: #4fc3f7;
  min-width: 50px;
  text-align: center;
}
.ctrl-key-row span { color: #aaa; }
.ctrl-key-row.clickable {
  cursor: pointer;
  padding: 4px 6px;
  margin: 0 -6px;
  border-radius: 4px;
  transition: background 0.15s;
  user-select: none;
}
.ctrl-key-row.clickable:hover         { background: rgba(79, 195, 247, 0.08); }
.ctrl-key-row.clickable:hover span    { color: #4fc3f7; }
.ctrl-key-row.clickable:active        { background: rgba(79, 195, 247, 0.18); }

/* Hide-controls toggle (H key) */
.controls-hidden #controls-panel,
.controls-hidden #know-more-link { display: none; }

/* ---- 6. Toast ---------------------------------------------------------- */
#toast {
  position: fixed;
  bottom: 32px;
  left: 50%;
  transform: translateX(-50%) translateY(80px);
  background: rgba(0, 0, 0, 0.85);
  color: #4fc3f7;
  border: 1px solid rgba(79, 195, 247, 0.3);
  padding: 10px 32px 10px 18px;
  border-radius: 8px;
  font-size: 11px;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 0;
  transition: transform 0.3s, opacity 0.3s;
  pointer-events: none;
  z-index: 1000;
  max-width: calc(100vw - 40px);
  cursor: pointer;
}
#toast.show {
  transform: translateX(-50%) translateY(0);
  opacity: 1;
  pointer-events: auto;
}
#toast.show::after {
  content: '×';
  position: absolute;
  top: 4px;
  right: 8px;
  font-size: 16px;
  color: #888;
  line-height: 1;
}
#toast:hover::after { color: #fff; }

/* ---- 7. Welcome modal -------------------------------------------------- */
#welcome-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
  z-index: 50000;
  opacity: 0;
  transition: opacity 0.4s ease;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
#welcome-modal.visible { opacity: 1; }

.wm-card {
  position: relative;
  background: rgba(10, 10, 15, 0.95);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 16px;
  padding: 32px 36px;
  max-width: 520px;
  width: calc(100vw - 40px);
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  color: #ddd;
  font-family: 'SF Mono', 'Fira Code', monospace;
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.1) transparent;
}
.wm-close {
  position: absolute;
  top: 12px;
  right: 16px;
  background: none;
  border: none;
  color: #666;
  font-size: 24px;
  cursor: pointer;
  padding: 4px 8px;
  line-height: 1;
  transition: color 0.15s;
}
.wm-close:hover { color: #eee; }

.wm-title {
  font-size: 22px;
  font-weight: bold;
  color: #fff;
  margin: 0 0 6px;
}

/* ---- Export print-size modal (STL / 3MF) ---- */
#export-size-modal {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.7);
  z-index: 50001;
  opacity: 0;
  transition: opacity 0.25s ease;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
#export-size-modal.visible { opacity: 1; }
.es-card { max-width: 460px; }
.es-title {
  font-size: 20px;
  font-weight: bold;
  color: #fff;
  margin: 0 0 14px;
}
.es-text {
  font-size: 13px;
  line-height: 1.55;
  color: #bbb;
  margin: 0 0 18px;
}
.es-text strong { color: #eee; }
.es-field {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 14px;
}
.es-field label {
  font-size: 13px;
  color: #ddd;
  white-space: nowrap;
}
.es-field input {
  flex: 1;
  min-width: 0;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 8px;
  color: #fff;
  font-family: inherit;
  font-size: 16px;
  padding: 10px 12px;
  text-align: right;
}
.es-field input:focus {
  outline: none;
  border-color: rgba(79, 195, 247, 0.6);
  background: rgba(79, 195, 247, 0.08);
}
.es-note {
  font-size: 11.5px;
  line-height: 1.5;
  color: #888;
  margin: 0 0 22px;
}
.es-note strong { color: #aaa; }
.es-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
.es-actions .cp-btn { min-width: 96px; }
.wm-subtitle {
  font-size: 12px;
  color: #888;
  margin: 0 0 20px;
  line-height: 1.5;
}

.wm-actions { display: flex; gap: 10px; margin-bottom: 20px; }
.wm-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 14px 8px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  color: #ddd;
  cursor: pointer;
  font-family: inherit;
  transition: all 0.2s;
}
.wm-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.25);
  transform: translateY(-2px);
}
.wm-btn-icon  { font-size: 24px; color: #4fc3f7; }
.wm-btn-label { font-size: 12px; font-weight: bold; color: #eee; }
.wm-btn-desc  { font-size: 9px; color: #666; text-align: center; }

.wm-btn-stream:hover { border-color: rgba(79, 195, 247, 0.4); }
.wm-btn-hand:hover   { border-color: rgba(129, 199, 132, 0.4); }
.wm-btn-random:hover { border-color: rgba(255, 183, 77, 0.4); }

.wm-divider { height: 1px; background: rgba(255, 255, 255, 0.08); margin: 0 0 16px; }

.wm-featured { display: flex; gap: 16px; margin-bottom: 16px; }
.wm-feat {
  flex: 1;
  background: rgba(79, 195, 247, 0.06);
  border: 1px solid rgba(79, 195, 247, 0.15);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 11px;
  color: #aaa;
  text-align: center;
}
.wm-feat kbd {
  background: rgba(79, 195, 247, 0.15);
  border: 1px solid rgba(79, 195, 247, 0.3);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 11px;
  font-family: inherit;
  color: #4fc3f7;
}

.wm-sections { display: flex; gap: 20px; margin-bottom: 16px; }
.wm-section  { flex: 1; }
.wm-section h3 {
  font-size: 11px;
  color: #888;
  margin: 0 0 8px;
  text-transform: uppercase;
  letter-spacing: 1px;
  font-weight: bold;
}
.wm-keys { display: flex; flex-direction: column; gap: 4px; }
.wm-key-row { display: flex; align-items: center; gap: 8px; font-size: 11px; }
.wm-key-row kbd {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 10px;
  font-family: inherit;
  color: #4fc3f7;
  min-width: 48px;
  text-align: center;
}
.wm-key-row span { color: #999; }

.wm-footer { font-size: 10px; color: #555; text-align: center; margin: 0 0 12px; }
.wm-links  { border-top: 1px solid rgba(255, 255, 255, 0.06); padding-top: 12px; }
.wm-links p {
  font-size: 10px;
  color: #666;
  margin: 0;
  text-align: center;
}
.wm-links a          { color: #4fc3f7; text-decoration: none; transition: color 0.15s; }
.wm-links a:hover    { color: #81d4fa; }

/* ---- 8. Help button on the panel header -------------------------------- */
.cp-help-btn {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: #aaa;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  font-size: 11px;
  cursor: pointer;
  font-family: inherit;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 6px;
  padding: 0;
  transition: all 0.15s;
}
.cp-help-btn:hover {
  background: rgba(79, 195, 247, 0.2);
  border-color: rgba(79, 195, 247, 0.4);
  color: #4fc3f7;
}

/* ---- 9. Mobile / touch ------------------------------------------------- */
@media (max-width: 700px) {
  .hiddenOnMobile { display: none; }

  .cp-panel {
    left: 8px;
    top: 8px;
    right: 8px;
    width: auto;
    max-width: calc(100vw - 16px);
    /* More opaque than the old 0.55: with the blur disabled below (perf), a
       see-through panel hurt text readability over busy universes AND made the
       sticky bars stand out as darker squares. Keep the sticky backing close in
       tone so the tab bar / Trip launcher blend instead of reading as boxes. */
    background: rgba(0, 0, 0, 0.82);
    --cp-sticky-bg: rgba(0, 0, 0, 0.9);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .cp-body {
    width: 100%;
    max-height: calc(100vh - 80px);
    max-height: calc(100dvh - 80px);
    padding: 12px 14px;
  }
  /* min-width:0 lets the flex:1 tabs shrink to share the row instead of
     overflowing the panel and pushing the last tab ("Actions") off the right
     edge on narrow phones. ellipsis covers any label too long to fit. This is
     what made the .ctrl-tabs background look like it "didn't fit the buttons". */
  .ctrl-tab {
    padding: 8px 4px;
    font-size: 11px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .cs-slider { height: 8px; border-radius: 4px; }
  .cs-slider::-webkit-slider-thumb { width: 20px; height: 20px; }
  .cs-slider::-moz-range-thumb     { width: 20px; height: 20px; }
  .gradient-pos-slider { height: 6px; }
  .gradient-pos-slider::-webkit-slider-thumb { width: 16px; height: 16px; }
  .gradient-pos-slider::-moz-range-thumb     { width: 16px; height: 16px; }
  .cs-toggle-indicator { width: 36px; height: 18px; border-radius: 9px; }
  .cs-toggle-indicator::after { width: 14px; height: 14px; }
  .cs-toggle:checked + .cs-toggle-indicator::after { left: 20px; }
  .cs-color { height: 28px; }
  .cp-btn   { padding: 10px 14px; font-size: 12px; }
  .cs-val   { font-size: 11px; }
  .cs-label { font-size: 11px; }

  .gradient-stops-list { max-height: 180px; }
  .gradient-stop-row   { grid-template-columns: 36px 1fr 36px 24px; gap: 8px; }

  #know-more-link { bottom: 8px; right: 10px; font-size: 10px; }

  .wm-card {
    padding: 20px 18px;
    border-radius: 12px;
    max-height: calc(100vh - 24px);
    max-height: calc(100dvh - 24px);
  }
  .wm-title    { font-size: 18px; }
  .wm-actions  { flex-direction: column; gap: 8px; }
  .wm-btn      { flex-direction: row; gap: 10px; padding: 12px 16px; align-items: center; }
  .wm-btn-icon { font-size: 22px; }
  .wm-btn-label { font-size: 14px; }
  .wm-btn-desc  { font-size: 11px; text-align: left; }
  .wm-sections  { flex-direction: column; gap: 8px; }
  .wm-featured  { flex-direction: column; gap: 6px; }
}

/* Prevent iOS-style page scroll bounce */
html, body { overscroll-behavior: none; touch-action: none; }
#controls-panel, #welcome-modal { touch-action: auto; }
.cs-slider, .gradient-pos-slider, .cs-color, .cs-select, input, button, select, label {
  touch-action: manipulation;
}

/* =============================================================================
   10. Sphere-specific UI
   ========================================================================== */

#sphereCanvas {
  position: fixed;
  inset: 0;
  width: 100vw;
  /* 100vh on iOS Safari refers to the LARGE viewport (including the
     hidden URL bar area), which is taller than window.innerHeight.
     If the drawing buffer is sized from innerHeight, the canvas CSS
     stretches the buffer vertically. 100dvh tracks the actual visible
     viewport so CSS + buffer stay 1:1. Falls back to 100vh on browsers
     without dvh support. */
  height: 100vh;
  height: 100dvh;
  display: block;
  background: #000;
  cursor: grab;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  touch-action: none;
}
#sphereCanvas:active { cursor: grabbing; }

/* The panel header / welcome modal / action button now use <img> for the
   Chaos Sphere icon instead of the ◉ character. Make them sit cleanly
   alongside the text and pick up a soft glow on hover. */
img.cp-tab-icon {
  display: inline-block;
  vertical-align: middle;
  margin-right: 2px;
  filter: drop-shadow(0 0 4px rgba(79, 195, 247, 0.35));
}
.wm-title {
  display: flex;
  align-items: center;
  gap: 10px;
  line-height: 1;            /* tight, so the icon sits visually centred */
}
img.wm-title-icon {
  display: block;
  width: 28px;               /* match the heading text height for clean alignment */
  height: 28px;
  flex: 0 0 28px;
  filter: drop-shadow(0 0 6px rgba(79, 195, 247, 0.35));
}
img.wm-btn-icon {
  display: inline-block;
  filter: drop-shadow(0 0 4px rgba(79, 195, 247, 0.30));
}

/* Export grid */
.export-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 10px;
}
.export-btn { width: 100%; }

/* Shader editor */
.shader-editor-wrap {
  position: relative;
  background: #050505;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 4px;
  margin-top: 8px;
}
.shader-editor {
  width: 100%;
  min-height: 220px;
  background: transparent;
  color: #d8e6f5;
  font-family: 'SF Mono', 'Fira Code', 'Menlo', monospace;
  font-size: 11px;
  line-height: 1.45;
  padding: 8px 8px 8px 36px;
  border: 0;
  resize: vertical;
  white-space: pre;
  outline: none;
  tab-size: 2;
}
.shader-line-numbers {
  position: absolute;
  top: 8px;
  left: 6px;
  width: 24px;
  color: rgba(255,255,255,0.25);
  font-family: 'SF Mono', 'Fira Code', 'Menlo', monospace;
  font-size: 11px;
  line-height: 1.45;
  text-align: right;
  pointer-events: none;
  user-select: none;
}
.shader-error {
  margin-top: 6px;
  padding: 6px 8px;
  background: rgba(220, 50, 60, 0.15);
  border-left: 2px solid #d33c3c;
  color: #ffb0b0;
  font-family: 'SF Mono', 'Fira Code', 'Menlo', monospace;
  font-size: 10px;
  white-space: pre-wrap;
  display: none;
}
.shader-error.visible { display: block; }

.shader-toolbar {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
}
.shader-toolbar select,
.shader-toolbar input {
  flex: 1;
  background: rgba(0,0,0,0.5);
  border: 1px solid rgba(255,255,255,0.1);
  color: #d8e6f5;
  padding: 4px 6px;
  border-radius: 3px;
  font-size: 11px;
  font-family: 'SF Mono', monospace;
}

/* Texture grid (mirrors 2D layout) */
.tex-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  margin-top: 8px;
  max-height: 220px;
  overflow-y: auto;
}
.tex-tile {
  aspect-ratio: 1;
  border-radius: 3px;
  cursor: pointer;
  background-size: cover;
  background-position: center;
  border: 2px solid transparent;
  transition: border-color 0.15s, filter 0.15s;
}
.tex-tile:hover    { filter: brightness(1.2); }
.tex-tile.selected { border-color: #4fc3f7; }

/* Actions tab section headers */
.actions-section {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.08);
}
.actions-section:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}
.actions-section-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: rgba(79, 195, 247, 0.7);
  margin-bottom: 8px;
}

/* Custom instant tooltip — native `title` has a ~1s browser delay we don't want. */
.tooltip-root {
  position: fixed;
  top: 0; left: 0;
  background: rgba(0, 0, 0, 0.92);
  border: 1px solid rgba(79, 195, 247, 0.35);
  color: #d8e6f5;
  padding: 10px 12px;
  border-radius: 6px;
  font-family: 'SF Mono', 'Fira Code', 'Menlo', monospace;
  font-size: 11px;
  line-height: 1.5;
  white-space: pre-wrap;
  max-width: 340px;
  pointer-events: none;
  z-index: 100000;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.55);
  opacity: 0;
  transform: translateY(2px);
  transition: opacity 0.08s ease-out, transform 0.08s ease-out;
}
.tooltip-root.visible {
  opacity: 1;
  transform: translateY(0);
}
[data-tooltip] { cursor: help; }

/* Texture-source slot cards (Custom image / Sigil). Each boxes its primary
   button with its Active / Stored-use / Download chips so the two slots read
   as distinct units instead of one entangled stack. */
.tex-slot {
  margin-top: 10px;
  /* Bottom margin so the following slider (Metalness) isn't glued to the
     Sigil card. Parent is display:block, so this collapses with the next
     card's top margin and doesn't bloat the gap between the two cards. */
  margin-bottom: 12px;
  padding: 9px 9px 10px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.tex-slot-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.5);
}

/* Lighting tab sub-section */
.light-subsection {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed rgba(255, 255, 255, 0.08);
}
.light-subsection-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.55);
  margin-bottom: 6px;
}

/* Larger dropdowns on mobile — the inline-styled <select>s in the Shader and
   Lighting tabs are uncomfortably small to tap at 11px. Bump font-size and
   padding under the same 700px breakpoint the rest of the panel uses.
   !important is needed because these elements set their own font-size inline. */
@media (max-width: 700px) {
  .cs-slider-wrap select,
  .shader-toolbar select {
    font-size: 15px !important;
    padding: 9px 10px !important;
    min-height: 38px;
    border-radius: 6px !important;
  }
}

/* Mode chooser pills */
.mode-pills {
  display: flex;
  gap: 4px;
  margin: 6px 0;
  background: rgba(0,0,0,0.4);
  padding: 3px;
  border-radius: 4px;
}
.mode-pill {
  flex: 1;
  background: transparent;
  border: 0;
  color: rgba(255,255,255,0.55);
  padding: 5px 8px;
  font-size: 11px;
  font-family: inherit;
  cursor: pointer;
  border-radius: 3px;
  transition: all 0.15s;
}
.mode-pill.active {
  background: rgba(79, 195, 247, 0.18);
  color: #4fc3f7;
}

/* --- Trip mode --- */
body.trip-active #controls-panel,
body.trip-active #know-more-link,
body.trip-active #cpTabHeader { display: none; }

/* After ~4s of no input the HUD/controls overlays fade out; hide the
   cursor too so nothing blocks the show. Any wake event (mousemove,
   touchstart, non-digit keydown) removes .trip-idle and the cursor
   reappears in sync with the overlays. */
body.trip-idle, body.trip-idle * { cursor: none !important; }

/* Tap / click on the visuals during a trip toggles all overlay chrome away
   for an unobstructed view (tap again to bring it back). !important so a stray
   mousemove "wake" can't fight the inline opacity the overlays set, and
   pointer-events:none so the invisible chrome can't catch taps meant to
   reveal it. */
body.trip-chrome-off #tripHud,
body.trip-chrome-off #tripControls { opacity: 0 !important; pointer-events: none !important; }
body.trip-chrome-off #tripHud *,
body.trip-chrome-off #tripControls * { pointer-events: none !important; }
body.trip-chrome-off, body.trip-chrome-off * { cursor: none !important; }

#trip-confirm-overlay {
  position: fixed; inset: 0; z-index: 100; display: flex;
  align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.85); color: #d8e6f5;
  font-family: inherit;
}
#trip-confirm-overlay .tco-card {
  text-align: center; padding: 28px 24px;
  border: 1px solid rgba(79,195,247,0.3); border-radius: 12px;
  background: linear-gradient(135deg, rgba(126,60,229,0.18), rgba(79,195,247,0.10));
  max-width: 90vw;
  display: flex; flex-direction: column; gap: 12px; align-items: stretch;
}
#trip-confirm-overlay .tco-btn   {
  background: linear-gradient(90deg,#7e3ce5,#4fc3f7); color: #fff;
  border: 0; padding: 14px 28px; border-radius: 8px;
  font-family: inherit; font-size: 15px; font-weight: 500; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
#trip-confirm-overlay .tco-icon  { font-size: 18px; line-height: 1; }
#trip-confirm-overlay .tco-btn-secondary {
  background: transparent; color: rgba(216,230,245,0.65);
  border: 1px solid rgba(255,255,255,0.12); border-radius: 6px;
  padding: 9px 18px;
  font-family: inherit; font-size: 12px; cursor: pointer;
}
#trip-confirm-overlay .tco-btn-secondary:hover {
  color: #d8e6f5; border-color: rgba(255,255,255,0.25);
}

/* --- Charge Sigil editor --- */
/* Hide the main control panel while the sigil modal is open so it can't
   peek through the backdrop blur or steal clicks. */
body.charge-sigil-open #controls-panel,
body.charge-sigil-open #know-more-link,
body.charge-sigil-open #cpTabHeader { display: none; }

#charge-sigil-overlay {
  position: fixed; inset: 0; z-index: 110; display: flex;
  align-items: center; justify-content: center;
  background: rgba(8, 12, 22, 0.72); color: #d8e6f5;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-family: inherit;
}
#charge-sigil-overlay .sigil-card {
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px;
  border: 1px solid rgba(79,195,247,0.3); border-radius: 12px;
  background: linear-gradient(135deg, rgba(126,60,229,0.10), rgba(79,195,247,0.06));
  max-width: 96vw; max-height: 96vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#charge-sigil-overlay .sigil-toolbar {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  padding: 4px 0;
}
#charge-sigil-overlay .sigil-toolbar > * { flex: 0 0 auto; }
#charge-sigil-overlay .sigil-tool {
  background: rgba(0,0,0,0.45); color: #d8e6f5;
  border: 1px solid rgba(255,255,255,0.12);
  padding: 5px 10px; border-radius: 12px;
  font-family: inherit; font-size: 11px; cursor: pointer;
  transition: background 150ms, color 150ms, border-color 150ms, opacity 150ms;
}
#charge-sigil-overlay .sigil-tool.active {
  background: rgba(126,60,229,0.45); color: #fff;
  border-color: rgba(160,120,255,0.7);
}
#charge-sigil-overlay .sigil-tool:disabled {
  opacity: 0.4; cursor: not-allowed;
}
#charge-sigil-overlay .sigil-tool-label {
  color: rgba(216,230,245,0.55); font-size: 10px;
  letter-spacing: 0.08em; text-transform: uppercase;
  padding: 0 4px 0 8px;
}
#charge-sigil-overlay input[type="color"] {
  background: transparent; border: 1px solid rgba(255,255,255,0.12);
  width: 28px; height: 22px; border-radius: 6px; padding: 0;
  cursor: pointer;
}
#charge-sigil-overlay input[type="range"] {
  accent-color: #a07cff; height: 14px;
}
#charge-sigil-overlay .sigil-canvas-wrap {
  position: relative; align-self: center;
  /* 2:1 ratio (1200×600 internal) — the correct equirectangular ratio so
     pixel-circles drawn on the canvas render as true circles on the
     sphere face. Width allowed up to 140vh so a wide viewport gets a
     bigger workspace; height capped at 70vh. */
  width: min(95vw, 1200px, calc(70vh * 2));
  aspect-ratio: 2 / 1;
  background: #000; border-radius: 6px; overflow: hidden;
  container-type: inline-size;
}
#charge-sigil-overlay .sigil-canvas-wrap canvas {
  display: block; width: 100% !important; height: 100% !important;
}
/* Fabric wraps both the lower + upper canvases in a `.canvas-container`
   div that it sizes inline to 1200×600. Without this override the
   container overflows our scaled-down wrap on small viewports, leaving
   only the LEFT 1/3 of the canvas visible (and the optimal-area
   center at canvas-coord 600 sitting off-screen). Forcing 100/100
   keeps the container in step with the wrap so the canvas's full
   1200×600 buffer maps neatly onto the visible rendered surface. */
#charge-sigil-overlay .sigil-canvas-wrap .canvas-container {
  width: 100% !important; height: 100% !important;
  position: relative !important;
}
#charge-sigil-overlay .sigil-area-hint {
  position: absolute; inset: 0; pointer-events: none;
  border-radius: 6px;
  /* Hairline white circle marking the "Optimal Sigil Area" — the central
     33% of the canvas width that lands on the sphere's front face after
     the UV shift. 33cqw = 33% of container width, so the diameter scales
     correctly as the canvas resizes. */
  --sigil-circle-d: 22cqw;
  background:
    radial-gradient(circle at 50% 50%,
      transparent 0,
      transparent calc(var(--sigil-circle-d) / 2 - 1px),
      rgba(255,255,255,0.85) calc(var(--sigil-circle-d) / 2 - 1px),
      rgba(255,255,255,0.85) calc(var(--sigil-circle-d) / 2 + 1px),
      transparent calc(var(--sigil-circle-d) / 2 + 1px));
  mix-blend-mode: difference;
}
#charge-sigil-overlay .sigil-area-hint::after {
  content: 'Optimal Sigil Area';
  position: absolute; left: 50%; bottom: 8%; transform: translateX(-50%);
  color: rgba(255,255,255,0.9); font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase;
  pointer-events: none;
  mix-blend-mode: difference;
}
#charge-sigil-overlay .sigil-actions {
  display: flex; gap: 8px; justify-content: flex-end; padding-top: 4px;
}
#charge-sigil-overlay .sigil-btn-primary {
  background: linear-gradient(90deg,#7e3ce5,#4fc3f7); color: #fff;
  border: 0; padding: 9px 22px; border-radius: 8px;
  font-family: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
}
#charge-sigil-overlay .sigil-btn-secondary {
  background: transparent; color: rgba(216,230,245,0.65);
  border: 1px solid rgba(255,255,255,0.12); border-radius: 6px;
  padding: 8px 16px;
  font-family: inherit; font-size: 12px; cursor: pointer;
}
#charge-sigil-overlay .sigil-btn-secondary:hover {
  color: #d8e6f5; border-color: rgba(255,255,255,0.25);
}

/* Crop button hover popover (Circle / Square). Show/hide is driven by JS
   (delayed close) so the cursor can travel from the button into the menu
   without the menu vanishing under it. */
#charge-sigil-overlay .sigil-crop-wrap {
  position: relative;
}
#charge-sigil-overlay .sigil-crop-pop {
  position: absolute; top: 100%; left: 0;
  /* No vertical gap — the button's bottom edge is the menu's top edge so
     the cursor can never "fall off" while moving down to a row. */
  margin-top: 0;
  display: none; flex-direction: column; gap: 4px;
  padding: 6px;
  background: rgba(10,14,24,0.96);
  border: 1px solid rgba(255,255,255,0.12); border-radius: 8px;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  z-index: 5;
}
#charge-sigil-overlay .sigil-crop-pop.open { display: flex; }
#charge-sigil-overlay .sigil-crop-pop .sigil-tool {
  min-width: 130px; text-align: left;
}

/* Right-click context menu on canvas objects. */
#charge-sigil-overlay .sigil-ctx-menu {
  position: fixed;
  min-width: 220px;
  background: rgba(10,14,24,0.96);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: 8px;
  padding: 4px;
  z-index: 120;
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: flex; flex-direction: column; gap: 2px;
}
#charge-sigil-overlay .sigil-ctx-item {
  display: flex; justify-content: space-between; align-items: center;
  gap: 24px;
  background: transparent; color: #d8e6f5;
  border: 0; padding: 7px 12px; border-radius: 6px;
  font-family: inherit; font-size: 12px; cursor: pointer;
  text-align: left;
}
#charge-sigil-overlay .sigil-ctx-item:hover {
  background: rgba(126,60,229,0.30);
}
#charge-sigil-overlay .sigil-ctx-shortcut {
  color: rgba(216,230,245,0.45); font-size: 11px;
}

/* --- Mobile / small-viewport adjustments -------------------------------- */
@media (max-width: 720px), (max-height: 600px) {
  #charge-sigil-overlay .sigil-card {
    /* Respect iOS notch / status bar / home indicator via safe-area
       insets (viewport-fit=cover is set in index.html). Split into
       longhand because Safari historically choked on `max(env(...))`
       nested inside the `padding` shorthand. On Android + desktop
       these envs evaluate to 0 so the modal still fills the screen
       edge-to-edge. */
    padding-top:    max(10px, env(safe-area-inset-top));
    padding-right:  max(10px, env(safe-area-inset-right));
    padding-bottom: max(10px, env(safe-area-inset-bottom));
    padding-left:   max(10px, env(safe-area-inset-left));
    max-width: 100vw; max-height: 100vh;
    border-radius: 0;
    width: 100vw; height: 100vh;
    /* Use dvh too — Safari's address bar pushes vh into negative-effective
       territory; dvh is the actual visible height which is what we want. */
    max-height: 100dvh;
    height: 100dvh;
    box-sizing: border-box;
  }
  /* Bigger tap targets so chips meet the ~44 px accessibility threshold. */
  #charge-sigil-overlay .sigil-tool {
    padding: 8px 12px; font-size: 12px; min-height: 36px;
  }
  /* Wider range slider for fingers. */
  #charge-sigil-overlay .sigil-toolbar input[type="range"] {
    width: 110px !important; height: 22px;
  }
  /* iOS Safari only renders color inputs as small swatches; bump size. */
  #charge-sigil-overlay input[type="color"] {
    width: 36px; height: 30px;
  }
  /* Optional canvas: take full width, scale by aspect ratio. */
  #charge-sigil-overlay .sigil-canvas-wrap {
    width: 100%; max-width: 100%;
  }
  /* Stack the Cancel/Apply pair full-width on the smallest screens. */
  #charge-sigil-overlay .sigil-actions {
    justify-content: stretch;
  }
  #charge-sigil-overlay .sigil-btn-primary,
  #charge-sigil-overlay .sigil-btn-secondary {
    flex: 1; padding: 12px 16px; font-size: 14px;
  }
  /* Context menu items get larger hit areas. */
  #charge-sigil-overlay .sigil-ctx-item {
    padding: 12px 14px; font-size: 13px;
  }
  /* Crop / Order hover-popovers: anchor below so they don't go off-screen
     on narrow viewports where the chip might sit on the right edge. */
  #charge-sigil-overlay .sigil-crop-pop {
    min-width: 160px;
  }
}
