/* Galaxy Sandbox Styles */

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0;
  background: #000;
  overflow: hidden;
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  color: #fff;
}

#gpu-canvas {
  display: block;
  width: 100vw;
  height: 100vh;
  cursor: grab;
}

#gpu-canvas:active {
  cursor: grabbing;
}

/* Loading Screen */
.loading {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  text-align: center;
  z-index: 1000;
}

.loader {
  width: 40px;
  height: 40px;
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top: 3px solid #fff;
  border-radius: 50%;
  margin: 20px auto;
  animation: spin 1s linear infinite;
}

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

  100% {
    transform: rotate(360deg);
  }
}

/* Error Display */
.error {
  color: #ff4444;
  background: rgba(0, 0, 0, 0.9);
  padding: 20px;
  border-radius: 8px;
  max-width: 600px;
  border: 1px solid #ff4444;
}

.error ul {
  text-align: left;
  margin: 15px 0;
}

.error li {
  margin: 5px 0;
}

.error code {
  background: rgba(255, 255, 255, 0.1);
  padding: 2px 6px;
  border-radius: 3px;
  font-family: monospace;
}

#runtime-notice {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom));
  z-index: 1001;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 12px;
  width: min(520px, calc(100vw - 28px));
  transform: translateX(-50%);
  padding: 12px 14px;
  border: 1px solid rgba(122, 162, 247, 0.5);
  border-radius: 8px;
  background: rgba(5, 8, 18, 0.92);
  box-shadow: 0 10px 32px rgba(0, 0, 0, 0.42);
  color: #dbeafe;
  font-size: 13px;
  line-height: 1.35;
}

#runtime-notice[hidden] {
  display: none;
}

#runtime-notice-title {
  color: #fff;
}

#runtime-notice-message {
  grid-column: 1;
}

#runtime-notice-dismiss {
  appearance: none;
  -webkit-appearance: none;
  grid-row: 1 / span 2;
  grid-column: 2;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid rgba(219, 234, 254, 0.24);
  border-radius: 50%;
  background: transparent;
  color: #dbeafe;
  cursor: pointer;
}

#runtime-notice-dismiss:hover,
#runtime-notice-dismiss:focus-visible {
  border-color: #7aa2f7;
  color: #fff;
  outline: none;
}

/* On-screen controls — a fixed cog button at the top-left that the panel hangs
   off. The chrome lives on the body (not the container), so the cog holds its exact
   place whether the panel is open or closed; it stays put when dragged too. */
#controls {
  position: fixed;
  /* Offset by the safe-area insets so the cog clears the iPhone status bar/notch
     (we render under it via viewport-fit=cover). env() is 0 on desktop. */
  top: calc(14px + env(safe-area-inset-top));
  left: calc(14px + env(safe-area-inset-left));
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  user-select: none;
  z-index: 100;
  transition: opacity 0.9s ease;
}

/* After ~20 s without interaction the whole panel fades away for a clean,
   movie-like view; any pointer move, key, or scroll brings it straight back
   (see setupIdleHide in index.html). */
#controls.idle-hidden {
  opacity: 0;
  pointer-events: none;
}

/* The cog: always the same discreet circular handle (and the drag grip), so it
   never moves or changes when the panel opens or closes. */
#controls-toggle {
  appearance: none;
  -webkit-appearance: none;
  width: 40px;
  height: 40px;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(10, 14, 28, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #c7d2fe;
  font: inherit;
  opacity: 0.85;
  cursor: grab; /* the panel drags by this handle */
  touch-action: none; /* let pointer-drag work on touch */
  user-select: none;
  transition: opacity 0.15s ease;
}

#controls-toggle:hover {
  opacity: 1;
}

#controls-toggle:active {
  cursor: grabbing;
}

/* Redundant next to the cog — kept in the DOM for assistive tech only. */
#controls-label {
  display: none;
}

#controls-icon {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The cog is an inline SVG (not a font glyph) so it centres by geometry, with no
   baseline/line-height offset — dead-centre in the circle. */
#controls-icon svg {
  display: block;
}

/* The panel body carries the glass chrome and sits below the cog when open. */
#controls-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 18px;
  max-height: calc(100vh - 78px - env(safe-area-inset-top) - env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(10, 14, 28, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 16px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 13px;
  letter-spacing: 0.02em;
  color: #c7d2fe;
}

#controls.collapsed #controls-body {
  display: none;
}

.control {
  display: flex;
  align-items: center;
  gap: 12px;
}

.control label {
  width: 72px;
  text-transform: uppercase;
  font-size: 11px;
  opacity: 0.8;
}

.control input[type="range"] {
  width: 200px;
  accent-color: #7aa2f7;
  cursor: pointer;
}

/* The autopilot row packs a toggle and a speed slider on one line — let the slider
   flex to fill whatever's left beside the switch (the fixed 200px would overflow). */
#autopilot-speed {
  width: auto;
  flex: 1;
  min-width: 56px;
}

/* Two compact toggles (halo Show + rotation Curve) share one row to save
   vertical space. Each half keeps its label + "?" + switch grouped together
   (labels shrink to content width), so each toggle stays right next to its own
   label and the pair still fits two-up even on a ~320px phone. */
.control-pair {
  display: flex;
  gap: 18px;
}

.control-pair .control {
  flex: 0 1 auto;
  min-width: 0;
}

.control-pair .control label {
  width: auto;
}

/* A small "?" after each control label that reveals a description on click. Sits
   in its own column right after the (fixed-width) label, so they line up. */
.info {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 50%;
  background: transparent;
  color: #c7d2fe;
  font: 700 10px/1 inherit;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.4;
  transition: opacity 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.info:hover,
.info:focus-visible,
.info[aria-expanded="true"] {
  opacity: 1;
  border-color: #7aa2f7;
  color: #fff;
  outline: none;
}

/* Shared description popover (one element, repositioned under the clicked icon). */
#info-popover {
  position: fixed;
  z-index: 30;
  max-width: 240px;
  padding: 9px 11px;
  background: rgba(10, 14, 28, 0.92);
  border: 1px solid rgba(122, 162, 247, 0.5);
  border-radius: 10px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 12px;
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: #e6ebff;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}

#info-popover[hidden] {
  display: none;
}

.control select {
  width: 200px;
  padding: 4px 8px;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 8px;
  font: inherit;
  cursor: pointer;
}

.control select option {
  background: #0a0e1c;
  color: #fff;
}

.control span {
  min-width: 4ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: #fff;
}

/* A labelled group of related controls (e.g. the dark-matter halo), bracketed by
   hairlines so its rows still line up with the rest of the panel. */
.control-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 2px 0;
  padding: 9px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.group-label {
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: #b3c2ff;
  opacity: 0.85;
}

/* Toggle switch (a styled checkbox) — used for the halo visibility toggle. */
.switch {
  appearance: none;
  -webkit-appearance: none;
  position: relative;
  flex: none;
  width: 38px;
  height: 20px;
  margin: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.18);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #c7d2fe;
  transition: transform 0.15s ease, background 0.15s ease;
}

.switch:checked {
  background: rgba(122, 162, 247, 0.55);
  border-color: rgba(122, 162, 247, 0.8);
}

.switch:checked::after {
  transform: translateX(18px);
  background: #fff;
}

.switch:focus-visible {
  outline: 1px solid #7aa2f7;
  outline-offset: 2px;
}

/* Mute toggle — a compact icon button sitting in the volume row */
.mute {
  appearance: none;
  -webkit-appearance: none;
  width: 4ch;
  padding: 2px;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  font-size: 16px;
  line-height: 1;
  text-align: right;
  cursor: pointer;
  opacity: 0.85;
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.mute:hover {
  opacity: 1;
  transform: translateY(-1px);
}

.mute[aria-pressed="true"] {
  opacity: 0.6;
}

/* Restart — a compact icon button beside the scenario dropdown (re-seeds). */
.restart-icon {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 30px;
  height: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: rgba(122, 162, 247, 0.18);
  color: #c7d2fe;
  border: 1px solid rgba(122, 162, 247, 0.5);
  border-radius: 8px;
  font: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.15s ease;
}

.restart-icon:hover {
  background: rgba(122, 162, 247, 0.32);
  transform: translateY(-1px);
}

/* Footer — feedback + support share one centred row (wrapping only if forced). */
/* Two stacked rows: the doc links above, the Feedback / Support actions below. */
.panel-footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
}

.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
}

/* Feedback button — a quiet footer action that opens the Sentry feedback form.
   Hidden until sentry.js wires it up. The doc links share the same quiet pill. */
.feedback,
.doclink {
  appearance: none;
  -webkit-appearance: none;
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 14px;
  background: none;
  color: rgba(199, 210, 254, 0.68);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px;
  font: inherit;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-decoration: none;
  cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.feedback[hidden] {
  display: none;
}

.feedback:hover,
.feedback:focus-visible,
.doclink:hover,
.doclink:focus-visible {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.32);
  background: rgba(255, 255, 255, 0.06);
  outline: none;
}

/* Sentry feedback widget — themed to match the app. These custom properties are
   set on the widget's host element and inherit into its shadow DOM, overriding the
   integration's defaults (deep-space dark + the galacto blue accent + panel font). */
#sentry-feedback {
  --font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  --foreground: #e6ecff;
  --background: #0b0f22;
  --accent-foreground: #0a0e1c;
  --accent-background: #7aa2f7;
  --border: 1px solid rgba(255, 255, 255, 0.14);
  --border-radius: 14px;
  --box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5);
  --outline: 1px auto #7aa2f7;
  --success-color: #6ee7b7;
  --error-color: #ff8a8a;

  /* Dialog shell */
  --dialog-background: #0b0f22;
  --dialog-color: #e6ecff;
  --dialog-border: 1px solid rgba(255, 255, 255, 0.14);
  --dialog-border-radius: 16px;
  --dialog-box-shadow: 0 16px 50px rgba(0, 0, 0, 0.55);

  /* Inputs */
  --input-color: #ffffff;
  --input-border: 1px solid rgba(255, 255, 255, 0.18);
  --input-border-radius: 8px;
  --input-placeholder-color: rgba(199, 210, 254, 0.5);
  --input-focus-outline: 1px solid #7aa2f7;

  /* Submit (primary) button — the galacto blue */
  --button-primary-background: #7aa2f7;
  --button-primary-hover-background: #93b4ff;
  --button-primary-color: #0a0e1c;
  --button-primary-hover-color: #0a0e1c;
  --button-primary-border: 1px solid rgba(122, 162, 247, 0.6);
  --button-primary-border-radius: 8px;

  /* Cancel / secondary button */
  --button-background: rgba(255, 255, 255, 0.06);
  --button-hover-background: rgba(255, 255, 255, 0.12);
  --button-color: #c7d2fe;
  --button-border: 1px solid rgba(255, 255, 255, 0.16);
  --button-border-radius: 8px;
}

/* Self-styled Ko-fi link — sits in the panel footer beside the feedback button */
#kofi {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 6px 13px;
  border: 1px solid rgba(116, 189, 255, 0.28);
  border-radius: 999px;
  color: rgba(214, 230, 255, 0.72);
  background: rgba(116, 189, 255, 0.06);
  font-size: 13px;
  font-weight: 650;
  text-decoration: none;
  transition:
    color 0.16s ease,
    border-color 0.16s ease,
    background 0.16s ease,
    transform 0.16s ease;
}

#kofi:hover,
#kofi:focus-visible {
  color: #fff;
  border-color: rgba(116, 189, 255, 0.58);
  background: rgba(116, 189, 255, 0.13);
  transform: translateY(-1px);
  outline: none;
}

/* The ♥ glyph renders optically high beside the text; pin its box height and
   nudge it down a hair so it sits on the label's centre line. */
#kofi span {
  line-height: 1;
  transform: translateY(1px);
}

/* "Update available" toast — top-centre so it never collides with the controls
   (which live at the bottom). Slides in when the service worker has a new version
   waiting; the Reload button takes it live. */
#update-toast {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top));
  left: 50%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px 9px 16px;
  background: rgba(10, 14, 28, 0.72);
  border: 1px solid rgba(122, 162, 247, 0.45);
  border-radius: 14px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #e6ecff;
  font-size: 13px;
  letter-spacing: 0.02em;
  z-index: 200;
  opacity: 0;
  transform: translate(-50%, -160%);
  transition: transform 0.32s ease, opacity 0.32s ease;
}

/* Keep the `hidden` attribute authoritative despite the id-level display above. */
#update-toast[hidden] {
  display: none;
}

#update-toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

#update-toast .update-text {
  white-space: nowrap;
}

#update-reload {
  appearance: none;
  -webkit-appearance: none;
  padding: 6px 14px;
  background: rgba(122, 162, 247, 0.22);
  color: #dbe4ff;
  border: 1px solid rgba(122, 162, 247, 0.6);
  border-radius: 8px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: background 0.15s ease;
}

#update-reload:hover {
  background: rgba(122, 162, 247, 0.36);
}

#update-reload:disabled {
  opacity: 0.6;
  cursor: default;
}

#update-dismiss {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: none;
  color: inherit;
  opacity: 0.6;
  font-size: 14px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
}

#update-dismiss:hover {
  opacity: 1;
}

#update-toast.deferred {
  left: auto;
  right: calc(16px + env(safe-area-inset-right));
  top: auto;
  bottom: calc(16px + env(safe-area-inset-bottom));
  padding: 0;
  transform: none;
}

#update-toast.deferred .update-text,
#update-toast.deferred #update-reload {
  display: none;
}

#update-toast.deferred #update-dismiss {
  padding: 9px 14px;
  opacity: 1;
  color: #dbe4ff;
  font-size: 12px;
  font-weight: 600;
}

/* Rotation-curve overlay — a small physics chart, bottom-right, in the glass style.
   Toggled from the Dark matter halo group; off by default to keep the view clean. */
#rotcurve {
  position: fixed;
  right: calc(16px + env(safe-area-inset-right));
  bottom: calc(16px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  background: rgba(10, 14, 28, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: #c7d2fe;
  z-index: 150;
  user-select: none;
}

#rotcurve[hidden] {
  display: none;
}

.rc-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.rc-title {
  opacity: 0.8;
}

.rc-time {
  color: #fff;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-transform: none;
}

#rc-canvas {
  display: block;
}

.rc-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  font-size: 10px;
  letter-spacing: 0.02em;
}

.rc-k {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.rc-k::before {
  content: "";
  width: 12px;
  border-top: 2px solid currentColor;
}

.rc-total {
  color: #ffffff;
}
.rc-disk {
  color: #7aa2f7;
}
.rc-bulge {
  color: #ffd479;
}
.rc-halo {
  color: #b18cff;
}

/* --- Mobile / narrow viewports ---------------------------------------------
   The control rows use a fixed 72px label + 200px slider + readout, which is
   ~430px wide — wider than a phone. On narrow screens, cap the panel to the
   viewport (minus the 14px inset margins, accounting for the notch safe areas)
   and let the sliders and dropdowns flex to fill instead of holding 200px, so
   the readouts stay on-screen. Cap the height too, with internal scroll, so a
   short or landscape screen can still reach every control. */
@media (max-width: 480px) {
  #controls-body {
    width: calc(
      100vw - 28px - env(safe-area-inset-left) - env(safe-area-inset-right)
    );
    padding: 12px 14px;
  }

  .control {
    gap: 10px;
  }

  .control label {
    width: 58px;
  }

  .control input[type="range"],
  .control select {
    width: auto;
    flex: 1 1 0;
    min-width: 0;
  }
}
