html, body {
  height: 100%;
  width: 100%;
  background: #faf8f3;
  overscroll-behavior: none;
}

body {
  display: flex;
  flex-direction: column;
}

#links-canvas,
#offscreen-indicators {
  display: none !important;
}

/* Search input + results are part of the universe shell DOM and surface in
   mobile only when the user taps the search button (body.mobile-searching). */
#search-input,
#search-results {
  display: none;
}

#mobile-bar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
  background: rgba(250, 248, 243, 0.95);
  font: 13px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  z-index: 5;
}

/* 16px specifically: prevents iOS Safari from auto-zooming the viewport on
   focus (it triggers when the focused control's font-size resolves <16px).
   Touch target lands ~40px tall with the padding. */
#mobile-bar select {
  font: 16px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  padding: 8px 28px 8px 12px;
  min-height: 40px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  background-color: #fff;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M1 1l4 4 4-4' fill='none' stroke='%23666' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  appearance: none;
  -webkit-appearance: none;
}

#mobile-bar .spacer {
  flex: 1 1 auto;
}

#mobile-bar button.random-button {
  flex: 0 0 auto;
  width: 40px;
  min-height: 40px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  background: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
}

/* Era-stopped timeline. Each segment between ticks gets equal visual width,
   so 4M years of prehistory don't compress the recent millennia to nothing.
   The .inner wrapper has horizontal margin so 0%/100% land slightly inside
   the screen edges — keeps boundary tick labels from clipping. */
#mobile-timeline {
  flex: 0 0 auto;
  position: relative;
  height: 60px;
  background: rgba(250, 248, 243, 0.95);
  font: 10px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  color: #6b6b6b;
  z-index: 4;
  /* Inner is the touch surface for the scrubber; this rule + touch-action: none
     on .inner (set in JS) prevents the page from interpreting drags as scrolls. */
  cursor: grab;
}

#mobile-timeline .inner {
  cursor: grab;
}

body.mobile-scrubbing #mobile-timeline,
body.mobile-scrubbing #mobile-timeline .inner {
  cursor: grabbing;
}

#mobile-timeline .inner {
  position: relative;
  height: 100%;
  margin: 0 24px;
}

#mobile-timeline .track {
  position: absolute;
  left: 0;
  right: 0;
  top: 28px;
  height: 1px;
  background: rgba(0, 0, 0, 0.2);
}

#mobile-timeline .tick {
  position: absolute;
  top: 24px;
  width: 1px;
  height: 8px;
  background: rgba(0, 0, 0, 0.4);
  /* left is set inline; nudge by half a px so the tick centers on its position. */
  margin-left: -0.5px;
}

#mobile-timeline .tick-label {
  position: absolute;
  top: 11px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: #6b6b6b;
}

/* First and last tick anchor their labels to the inner edge of the timeline
   so they can't clip past the screen even with longer year text. */
#mobile-timeline .tick:first-of-type .tick-label {
  left: 0;
  transform: translateX(-2px);
}

#mobile-timeline .tick:last-of-type .tick-label {
  left: auto;
  right: 0;
  transform: translateX(2px);
}

#mobile-timeline-marker {
  position: absolute;
  top: 24px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #c66a2a;
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  /* left is set inline 0..100%; pull back half the box width so the dot is
     centered on its mathematical position. */
  margin-left: -6.5px;
  transition: left 220ms ease-out;
  pointer-events: none;
}

/* Mid-scrub the dot must track the finger 1:1 — the easing transition would
   otherwise lag behind the pointer and feel rubbery. */
body.mobile-scrubbing #mobile-timeline-marker {
  transition: none;
}

#mobile-timeline-marker .marker-label {
  position: absolute;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  padding: 2px 6px;
  background: #222;
  color: #fff;
  border-radius: 4px;
  font: 11px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

#mobile-timeline-marker .marker-label::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid #222;
}

#container {
  flex: 1 1 auto;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px 48px;
  min-height: 0;
  overflow: hidden;
}

/* The deck wraps three slots and reserves space for the card plus the
   stacked-card peek-out at the bottom. Width is the visible card width;
   height is the card height plus the deepest depth's vertical offset so
   the back cards don't get clipped at the bottom of #container. */
#deck {
  position: relative;
  width: min(100vw - 32px, 360px);
  /* aspect-ratio is set inline by mobile.js from card.js's cardWidth /
     fullCardHeight so the deck box tracks card geometry changes. */
  /* Reserve a little extra height so the deepest depth's translateY peek
     isn't clipped at the bottom of #container. */
  margin-bottom: 56px;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.slot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transform-origin: 50% 100%;
  transition:
    transform 320ms cubic-bezier(0.22, 0.85, 0.32, 1),
    opacity 320ms cubic-bezier(0.22, 0.85, 0.32, 1),
    filter 320ms cubic-bezier(0.22, 0.85, 0.32, 1);
  will-change: transform, opacity;
  pointer-events: none;
  touch-action: none;
}

.slot svg.mobile-card {
  width: 100%;
  height: 100%;
  display: block;
  cursor: default;
}

/* Depth tiers: 0 = top (interactive), 1 = peek beneath, 2 = far back.
   Each tier offsets down + scales down + dims, with progressively
   softer drop shadows so the stack feels physical. */
.slot[data-depth="0"] {
  z-index: 4;
  transform: translateY(0) scale(1);
  opacity: 1;
  filter: drop-shadow(0 10px 22px rgba(0, 0, 0, 0.22));
  pointer-events: auto;
  cursor: grab;
}

.slot[data-depth="0"]:active {
  cursor: grabbing;
}

.slot[data-depth="1"] {
  z-index: 3;
  transform: translateY(14px) scale(0.955);
  opacity: 0.96;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.14));
}

.slot[data-depth="2"] {
  z-index: 2;
  transform: translateY(28px) scale(0.91);
  opacity: 0.88;
  filter: drop-shadow(0 4px 9px rgba(0, 0, 0, 0.10));
}

.slot[data-depth="3"] {
  z-index: 1;
  transform: translateY(42px) scale(0.865);
  opacity: 0.78;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.08));
}

/* While dragging the top card we drive transform inline with no transition
   so it tracks the finger 1:1. */
.slot.dragging {
  transition: none;
  cursor: grabbing;
}

/* New far card animating in below the deck on forward commit. Initial
   state is offset further down + smaller + invisible; removing this
   class lets the slot transition to its data-depth="2" rest pose.
   Specificity must match `.slot[data-depth]` and live later in the
   stylesheet so it overrides the depth transform. */
.slot.entering-bottom {
  transform: translateY(80px) scale(0.8);
  opacity: 0;
}

/* New top card sliding in from off-screen on backward commit. Starts
   tilted off the side of the viewport and transitions to depth-0. */
.slot.enter-from-left {
  transform: translate(-130%, -8px) rotate(-14deg) scale(0.94);
  opacity: 0;
  z-index: 5;
}

.slot.enter-from-right {
  transform: translate(130%, -8px) rotate(14deg) scale(0.94);
  opacity: 0;
  z-index: 5;
}

/* The card that gets pushed out of the visible deck on backward commit
   (it was at depth-2 and the stack is sinking by one). Fade + push
   further down. */
.slot.exit-bottom {
  transform: translateY(86px) scale(0.78);
  opacity: 0;
}

/* Search button sits in the bar next to the dropdown. Same touch target size
   as the select. SVG magnifier inside is centered. */
#mobile-bar button.search-toggle {
  flex: 0 0 auto;
  width: 40px;
  min-height: 40px;
  border-radius: 8px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  background: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
}

/* Search overlay: when active, the input docks under the bar and the results
   scroll beneath it, covering the deck. Tapping a result jumps to that card
   and closes the overlay. */
body.mobile-searching #search-input {
  display: block;
  position: fixed;
  top: 56px; /* below the bar; matches bar's vertical footprint */
  left: 12px;
  right: 12px;
  padding: 10px 14px;
  font: 16px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 10px;
  background: #fff;
  z-index: 20;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
}

body.mobile-searching #search-results {
  display: block;
  position: fixed;
  top: 110px; /* under the docked input */
  left: 12px;
  right: 12px;
  bottom: 12px;
  background: rgba(250, 248, 243, 0.98);
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 10px;
  overflow-y: auto;
  z-index: 19;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
  -webkit-overflow-scrolling: touch;
}

#search-results .mobile-result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 14px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  cursor: pointer;
  font: 14px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
}

#search-results .mobile-result:last-child {
  border-bottom: none;
}

#search-results .mobile-result .title {
  font-weight: 600;
  color: #222;
}

#search-results .mobile-result .meta {
  color: #6b6b6b;
  font-size: 12px;
}

#search-results .mobile-result.empty {
  color: #6b6b6b;
  font-style: italic;
  cursor: default;
}

/* Dim the deck when search is active so the focus is on the result list. */
body.mobile-searching #deck {
  filter: blur(2px);
  opacity: 0.4;
  pointer-events: none;
}
