@font-face {
  font-family: BerkeleyMono;
  src: url("/assets/BerkeleyMono-Regular-849d6d29.woff2") format("woff2"),
       url("/assets/BerkeleyMono-Regular-506ee6a7.woff") format("woff");
}

:root {
  --theme-color: 220;
  --accent-color: 180;

  --bg-color: hsl(var(--theme-color), 20%, 10%);
  --text-color: hsl(var(--theme-color), 70%, 85%);
  --dim-color: hsl(var(--theme-color), 20%, 60%);
  --map-color: hsl(var(--theme-color), 15%, 40%);

  --link-color: hsl(var(--accent-color), 70%, 80%);
  --link-underline-color: hsla(var(--accent-color), 70%, 80%, 0.5);
  --basemap-fill: hsl(var(--theme-color), 15%, 35%); /* countries */

  --ok-color: hsl(140, 70%, 55%);
  --warn-color: hsl(40, 90%, 60%);
  --down-color: hsl(0, 80%, 62%);

  --panel-bg: hsla(var(--theme-color), 30%, 9%, 0.72);
  --panel-border: hsla(var(--theme-color), 40%, 45%, 0.35);
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
}

html {
  background-color: var(--bg-color);
  color: var(--text-color);
  font-size: clamp(14px, 1vw + 5px, 16px);
}

body {
  margin: 0;
  overflow: hidden;
  font-family: BerkeleyMono, 'IBM Plex Mono', 'Share Tech Mono', 'Nimbus Mono PS', 'Courier New', monospace;
}

a {
  color: var(--link-color);
  text-underline-offset: 0.25em;
  text-decoration-color: var(--link-underline-color);
}

@keyframes blink-caret { from, to { opacity: 0 } 50% { opacity: 1; } }
blink { animation: blink-caret 1s 4 step-end; }

/* --- Header ------------------------------------------------------------- */
.site-header {
  position: absolute;
  top: 0.4em;
  left: 0.8em;
  z-index: 10;
  pointer-events: none;
}
.site-header h1 {
  margin: 0;
  font-weight: normal;
  font-size: 1.5rem;
  text-shadow: 3px 0 hsl(var(--theme-color), 60%, 25%);
}

/* --- Map ---------------------------------------------------------------- */
figure.map {
  position: relative;
  margin: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The world map is north-heavy: nudge the whole layer stack down so the
     dense northern landmass clears the top panel row, at the expense of the
     (empty) southern ocean sliding behind the bottom row. Zeroed on mobile,
     where the panels aren't overlaid. */
  --map-shift: 2vw;
}

figure.map > svg, #live > svg {
  width: 100%;
  height: auto;
  max-height: 100vh;
  stroke-width: 0.5;
}
figure.map > svg.grid {
  fill: var(--basemap-fill);
  transform: translateY(var(--map-shift));
}

/* Stack every layer on top of the first (which sets the size). */
figure.map > svg:not(.grid), #live > svg {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(calc(-50% + var(--map-shift)));
  fill: var(--basemap-fill);
}

svg[baseprofile="tiny"] path { fill: var(--map-color); }
svg[baseprofile="tiny"] path:hover { filter: brightness(1.4); }

/* Too small to see otherwise (base map quirks) */
.PF { stroke: var(--basemap-fill); }

/* Infrastructure dots */
svg.infra { pointer-events: none; }
.landing-stations circle { fill: hsla(var(--accent-color), 60%, 55%, 0.35); stroke: none; }
.ixps circle { fill: hsla(var(--accent-color), 80%, 70%, 0.55); stroke: none; }

/* Submarine cable routes */
svg.cables-layer { pointer-events: none; }
.cables polyline {
  fill: none;
  stroke: hsla(var(--accent-color), 70%, 65%, 0.28);
  stroke-width: 0.6;
}

/* Global check-failure heatmap (updown.io) — blurred via the shared
   #heatmap-blur filter, so overlapping dots blend into hotspots. */
svg.heatmap { pointer-events: none; }
.heat-down { fill: var(--down-color); }
.heat-legend { color: var(--down-color); filter: blur(2px) }

/* Smoothly animate the fill when IODA flags/clears a country outage. */
figure.map path { transition: fill 0.2s ease; }

/* --- Status banner ------------------------------------------------------ */
.status-banner {
  position: absolute;
  top: 0.6em;
  right: 0.8em;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.4em 1em;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  backdrop-filter: blur(4px);
  white-space: nowrap;
}
.dot { width: 0.5em; height: 0.5em; border-radius: 50%; }
.status-ok .dot      { background: var(--ok-color);   box-shadow: 0 0 6px var(--ok-color); }
.status-warn .dot    { background: var(--warn-color); box-shadow: 0 0 6px var(--warn-color); }
.status-down .dot    { background: var(--down-color); box-shadow: 0 0 6px var(--down-color); }
.status-unknown .dot { background: var(--dim-color); }
.status-banner .clock { color: var(--dim-color); }

.panels {
  position: absolute;
  inset: 3.2em 0.8em 2em;
  z-index: 5;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  pointer-events: none;
}
.panel-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(21em, 100%), 1fr));
  align-items: stretch;
  gap: 0.8em;
}
.panel {
  min-width: 0;
  overflow: auto;
  display: flex;
  flex-direction: column;
  padding: 0.6em 0.8em;
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 4px;
  backdrop-filter: blur(4px);
  font-size: 0.8em;
  pointer-events: auto;
}
.panel h2 {
  margin: 0 0 0.5em;
  font-size: 1em;
  font-weight: normal;
  letter-spacing: 0.05vw;
  text-transform: uppercase;
  color: var(--dim-color);
  display: flex;
  justify-content: space-between;
}
.panel h2 .count { color: var(--text-color); }
.panel .loading { color: var(--dim-color); margin: 0.2em 0; font-style: italic; }
.panel .source { margin: 0.5em 0 0; margin-top: auto; padding-top: 0.5em; color: var(--dim-color); font-size: 0.85em; }

/* Status dot + list rows */
.dot.ok      { background: var(--ok-color); }
.dot.warn    { background: var(--warn-color); }
.dot.down    { background: var(--down-color); }
.dot.unknown { background: var(--dim-color); }

.status-list { list-style: none; margin: 0; padding: 0; }
.status-list li {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.15em 0;
  line-height: 1.4;
}
.status-list li .dot { width: 0.5em; height: 0.5em; border-radius: 50%; flex: none; }
.status-list li a { text-decoration: none; }
.status-list li a:hover { text-decoration: underline; }

.detail {
  margin-left: auto;
  color: var(--dim-color);
  font-size: 0.9em;
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The "name" cell in these lists absorbs all leftover row width (ellipsis if
   it doesn't fit), pushing the trailing sparkline/detail to a consistent
   position instead of drifting with how long the name happens to be. */
.tld-list li a,
.status-list.anomalies li a,
.status-list.resolvers li a,
.status-list.updown .cname {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.status-list.outages a:hover { text-decoration: underline; }
/* Country names are short; cap + ellipsis the rare long one so it can't shove
   the reason text out of the row. */
.status-list.outages .cname {
  min-width: 0;
  max-width: 14em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-decoration: none;
  color: var(--text-color);
}

.tld-list .detail,
.status-list.resolvers .detail,
.status-list.updown .detail,
.root-list .detail {
  min-width: 8em;
}
.status-list.anomalies .detail { min-width: 8em; }
.status-list.updown .detail { min-width: 4em; }

/* Root servers: one status-coloured letter + latency sparkline per root.
   A responsive grid, not the old fixed 2-column multicol — multicol's
   column count didn't respond to the *panel's* own width (only the page's,
   via the mobile breakpoint below), so a panel narrow enough from the
   panel-row's own reflow, but still short of that breakpoint, forced a
   second column too narrow for its content and overlapping the first. */
.root-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(152px, 1fr));
  gap: 0 1em;
  list-style: none;
  margin: 0;
  padding: 0;
}
.root-list a {
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.12em 0;
  text-decoration: none;
}
.root-list a:hover { background: hsla(var(--theme-color), 40%, 40%, 0.15); }
.root-list .rletter { font-weight: bold; flex: 1 1 1em; text-align: left; }
.root-list li.ok   .rletter { color: var(--ok-color); }
.root-list li.warn .rletter { color: var(--warn-color); }
.root-list li.down .rletter { color: var(--down-color); }

/* Sparkline width increases a bit on large screen */
.spark { width: clamp(46px, 4vw, 92px); height: 14px; }
.spark polyline { stroke: var(--link-color); stroke-width: 1; vector-effect: non-scaling-stroke; }
li.warn .spark polyline { stroke: var(--warn-color); }
li.down .spark polyline { stroke: var(--down-color); }
.spark-empty { display: inline-block; width: 46px; }

/* --- Footer ------------------------------------------------------------- */
figcaption {
  position: absolute;
  bottom: 1em;
  right: 1em;
  z-index: 5;
  color: var(--dim-color);
  text-align: right;
  font-size: 0.7rem;
  text-wrap: balance;
}

figcaption .dot {
  display: inline-block;
  filter: blur(2px);
}

/* --- Mobile: stack panels below a shorter, centered map ----------------- */
@media (max-width: 870px) {
  html, body { height: auto; min-height: 100%; }
  body { overflow-y: auto; overflow-x: hidden; }

  figure.map { height: 65vw; }

  .status-banner {
    top: 2.6em;
    left: 0.8em;
    right: 0.8em;
    justify-content: center;
  }

  .panels {
    top: 100%;
    right: 0.6em;
    bottom: auto;
    left: 0.6em;
    gap: 0.6em;
    padding-bottom: 1em;
  }
}
