/* ---------------------------------------------------------------------------
   base.css — reset, type, focus, utilities. MAIN-THREAD OWNED.
   Component files own their own selectors. Nothing here targets a component.
--------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-fg);
  font-family: var(--f-sans);
  font-size: var(--t-base);
  line-height: var(--lh-body);
  -webkit-text-size-adjust: 100%;
  /* The workspace panes scroll internally. The page body must never scroll
     sideways, at any width, for any content. */
  overflow-x: hidden;
}

h1, h2, h3, h4 { margin: 0; font-weight: var(--fw-semi); line-height: var(--lh-tight); }
p { margin: 0 0 var(--s-3); }
p:last-child { margin-bottom: 0; }

a { color: var(--c-primary); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--c-primary-hover); }

img { max-width: 100%; height: auto; display: block; }

button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
button:disabled { cursor: not-allowed; }

code, kbd, samp, pre, .mono { font-family: var(--f-mono); font-size: 0.95em; }

/* Focus. Never removed, only restyled. Keyboard operators exist and this is a
   console they may drive for half an hour. */
:focus-visible {
  outline: 2px solid var(--c-primary);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
:focus:not(:focus-visible) { outline: none; }

::selection { background: var(--c-primary-soft); }

/* Scrollbars inside the panes, so a 30 minute run does not look like a wall. */
.pane, .log-panel__body, .dropped-list, .lead-stream {
  scrollbar-width: thin;
  scrollbar-color: var(--c-border-strong) transparent;
}
.pane::-webkit-scrollbar,
.log-panel__body::-webkit-scrollbar,
.dropped-list::-webkit-scrollbar,
.lead-stream::-webkit-scrollbar { width: 10px; height: 10px; }
.pane::-webkit-scrollbar-thumb,
.log-panel__body::-webkit-scrollbar-thumb,
.dropped-list::-webkit-scrollbar-thumb,
.lead-stream::-webkit-scrollbar-thumb {
  background: var(--c-border-strong); border-radius: var(--r-pill);
  border: 3px solid transparent; background-clip: content-box;
}

/* ---- utilities ---------------------------------------------------------- */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sr-only--focusable:focus {
  position: fixed; top: var(--s-2); left: var(--s-2);
  width: auto; height: auto; margin: 0; clip: auto; white-space: normal;
  padding: var(--s-2) var(--s-3); background: var(--c-surface);
  border: 1px solid var(--c-border-strong); border-radius: var(--r-md);
  z-index: var(--z-modal); box-shadow: var(--sh-2);
}

.muted  { color: var(--c-fg-muted); }
.faint  { color: var(--c-fg-faint); }
.nowrap { white-space: nowrap; }
.tnum   { font-variant-numeric: tabular-nums; }
/* Counters and timers update every second. Without tabular numerals the whole
   row reflows on each tick and the eye reads it as flicker. */

.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A scraped URL or slug has no spaces and will otherwise push a card wider
   than the viewport. */
.breakable { overflow-wrap: anywhere; word-break: break-word; }

/* Any wide child (a table, a payload dump, a diff) scrolls inside itself. */
.scroll-x { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }

.stack   { display: flex; flex-direction: column; gap: var(--s-3); }
.row     { display: flex; align-items: center; gap: var(--s-2); }
.row--wrap { flex-wrap: wrap; }
.spacer  { flex: 1 1 auto; }

.empty-state {
  padding: var(--s-6) var(--s-4);
  text-align: center;
  color: var(--c-fg-muted);
  background: var(--c-surface);
  border: 1px dashed var(--c-border-strong);
  border-radius: var(--r-lg);
}

.card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
}

/* ---- shared chip -------------------------------------------------------- */
.chip {
  display: inline-flex; align-items: center; gap: var(--s-1);
  padding: 2px var(--s-2);
  font-size: var(--t-xs); font-weight: var(--fw-medium);
  line-height: 1.6; white-space: nowrap;
  border-radius: var(--r-pill);
  background: var(--c-idle-soft); color: var(--c-idle-ink);
}
.chip--ok     { background: var(--c-ok-soft);     color: var(--c-ok-ink); }
.chip--warn   { background: var(--c-warn-soft);   color: var(--c-warn-ink); }
.chip--danger { background: var(--c-danger-soft); color: var(--c-danger-ink); }
.chip--info   { background: var(--c-info-soft);   color: var(--c-info-ink); }
.chip--drop   { background: var(--c-drop-soft);   color: var(--c-drop); }
.chip--mono   { font-family: var(--f-mono); font-size: var(--t-xs); }

/* A status dot is never the ONLY signal — every one of these sits beside a
   text label, so the screen survives a colour-blind operator and a bad monitor. */
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--c-idle); flex: none; }
.dot--ok { background: var(--c-ok); }
.dot--warn { background: var(--c-warn); }
.dot--danger { background: var(--c-danger); }
.dot--live { background: var(--c-ok); animation: pulse 2s var(--m-ease) infinite; }

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(21, 128, 61, .45); }
  50%      { box-shadow: 0 0 0 5px rgba(21, 128, 61, 0); }
}

/* Skeleton shimmer. A website scrape runs 6-10 minutes; a pane that shows
   nothing during it reads as a hung app. */
.sk {
  position: relative; overflow: hidden;
  background: var(--c-muted, #eef1ef); border-radius: var(--r-md);
}
.sk::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.75), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.6s infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }

@media (prefers-reduced-motion: reduce) {
  .sk::after, .dot--live { animation: none; }
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
