/* OpenMarketIL -- brutalist Swiss grid. System rules, don't break them
   ad hoc elsewhere in this file:
   1. White page background; black is a component color, never on <body>.
   2. Green marks exactly one "this matters" element -- never decoration.
   3. Sharp corners everywhere. No border-radius, no box-shadow depth.
   4. Two voices: --font (Helvetica) for everything dense; --font-display
      (Monocraft) only for the topbar and the two section titles.
   5. Job Board and Market Stats are permanent, side by side above the
      mobile breakpoint (where they stack) -- never a drawer or toggle.
   6. Light/dark is a straight token swap: every rule reads
      var(--white)/var(--black), never a literal hex, so the swap stays
      total under [data-theme="dark"]. */

@font-face {
  font-family: "Monocraft";
  src: url("fonts/Monocraft-Black.ttf") format("truetype");
  font-weight: 800;
  font-display: swap;
}

:root {
  --white: #ffffff;
  --black: #0a0a0a;
  --green: #1c7c3f;
  --green-bright: #2fae60;
  --grey: #6b6b6b;
  --grey-line: #d4d4d4;
  --red: #b8362c;
  --hover-bg: #f4f4f4;

  --font: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-display: "Monocraft", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Side padding for .workspace/.container -- scales with viewport
     (20px floor, 64px ceiling) instead of a fixed max-width box. */
  --gutter: clamp(20px, 4vw, 64px);
  --rule: 2px;

  /* Forces native chrome (input caret, scrollbars) to follow OUR toggle
     instead of the OS's own dark-mode setting, which would otherwise
     paint them dark against our light surfaces. */
  color-scheme: light;
}

:root[data-theme="dark"] {
  --white: #0a0a0a;
  --black: #ffffff;
  --green: #2fae60;
  --green-bright: #4ee585;
  --grey: #9a9a9a;
  --grey-line: #333333;
  --hover-bg: #1a1a1a;
  color-scheme: dark;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--white);
  color: var(--black);
}

body {
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--black); color: var(--white); }

/* Custom scrollbars, theme-tokened like the rest of the page. The thumb's
   border uses the track color -- the standard trick for an inset look. */
html { scrollbar-width: thin; scrollbar-color: var(--black) var(--white); }
*::-webkit-scrollbar { width: 12px; height: 12px; }
*::-webkit-scrollbar-track { background: var(--white); }
*::-webkit-scrollbar-thumb {
  background: var(--black);
  border: 3px solid var(--white);
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--green); }
*::-webkit-scrollbar-corner { background: var(--white); }

a { color: inherit; }
a.link { color: var(--green); text-decoration: none; border-bottom: 1px solid var(--green); }
a.link:hover { background: var(--green); color: var(--white); }

button, input, select {
  font-family: var(--font);
  font-size: 13px;
  color: var(--black);
  caret-color: var(--black); /* belt-and-suspenders on top of color-scheme: light above */
}

.container {
  padding: 0 var(--gutter);
}

.section {
  border-bottom: var(--rule) solid var(--black);
  padding: 40px 0;
}

.section-title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 24px;
}

/* ---------------------------------------------------------------------- */
/* Topbar */
/* ---------------------------------------------------------------------- */

.topbar {
  font-family: var(--font-display);
  border-bottom: var(--rule) solid var(--black);
  position: sticky;
  top: 0;
  background: var(--white);
  z-index: 10;
}

.topbar .container {
  display: flex;
  align-items: center;
  gap: 16px;
  /* nowrap, deliberately -- .ticker has min-width:0 + overflow:hidden so
     it shrinks to fit instead. flex-wrap here wrapped the whole topbar
     onto 3 lines at any width short of "everything fits." */
  flex-wrap: nowrap;
  min-height: 56px;
  padding-top: 10px;
  padding-bottom: 10px;
}
.topbar .container > * { min-width: 0; } /* same min-width:auto issue as everywhere else in this file */
.wordmark, .topnav { flex: 0 0 auto; } /* natural width -- the ticker is the one flexible element between them */

/* ---------------------------------------------------------------------- */
/* Topbar ticker -- seamless CSS-loop marquee. The item list is duplicated
   once in the track, animated exactly -50% so the loop has no visible seam. */
/* ---------------------------------------------------------------------- */

.ticker-rule { flex: 0 0 auto; width: var(--rule); height: 22px; background: var(--black); }

.ticker {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  height: 20px;
  display: flex;
  align-items: center; /* .ticker-track's height comes from its own text content, not this 20px window -- without this it just sits at the top of the clipped box instead of centered in it */
}

.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker-scroll 40s linear infinite;
}
.ticker:hover .ticker-track { animation-play-state: paused; } /* let a visitor actually read/click one without it sliding away */

@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

.ticker-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 20px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--black);
  text-decoration: none;
  white-space: nowrap;
  border-right: 1px solid var(--grey-line);
}
.ticker-item:hover { color: var(--green); }
.ticker-item .bullet { color: var(--green); }
.ticker-item .ticker-company { color: var(--grey); }
.ticker-item:hover .ticker-company { color: var(--green); }

.wordmark {
  font-weight: 800;
  font-size: 15px;
  letter-spacing: 0.02em;
  text-decoration: none;
}
.wordmark .accent { color: var(--green); }

.topnav {
  display: flex;
  align-items: center;
  gap: 28px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.theme-toggle {
  background: none;
  border: none;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  color: inherit;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 0;
  cursor: pointer;
  border-bottom: 1px solid transparent;
}
.theme-toggle:hover { color: var(--green); border-color: var(--green); }

/* A square block, not a circle, per the sharp-corners rule. Flickers in
   irregular jump-cut steps like a torch, not a smooth pulse. OFFLINE
   kills the animation outright -- the torch went out, not still pulsing. */
.status-dot {
  width: 8px;
  height: 8px;
  background: var(--green);
  display: inline-block;
  margin-right: 6px;
  animation: torch-flicker 1.6s steps(1) infinite;
}
.status-dot.stale { background: var(--red); animation: none; }
@keyframes torch-flicker {
  0%, 100% { opacity: 1; }
  6% { opacity: 0.8; }
  11% { opacity: 1; }
  19% { opacity: 0.55; }
  27% { opacity: 1; }
  33% { opacity: 0.85; }
  41% { opacity: 1; }
  52% { opacity: 0.7; }
  58% { opacity: 1; }
  69% { opacity: 0.9; }
  74% { opacity: 1; }
  83% { opacity: 0.6; }
  89% { opacity: 1; }
}

/* ---------------------------------------------------------------------- */
/* Workspace -- Job Board (main) + Market Stats (a permanent right-hand
   board, not a drawer/overlay). Stacks vertically under the responsive
   breakpoint at the end of this file. */
/* ---------------------------------------------------------------------- */

.workspace {
  display: grid;
  grid-template-columns: 1fr clamp(360px, 28vw, 460px);
  align-items: start;
  padding: 0 var(--gutter);
}

/* min-width:0 -- without it a grid item can't shrink below its content's
   natural width, so one long unbreakable value (a table row, a bar-list
   name) forces the whole page wider instead of wrapping locally. */
.workspace > #board,
.workspace > .stats-board {
  min-width: 0;
}

.workspace > #board {
  border-right: var(--rule) solid var(--black);
  padding-right: var(--gutter);
}
.workspace > #board .container { padding: 0; }

.stats-board {
  position: sticky;
  top: 57px; /* topbar height + its 2px bottom rule */
  max-height: calc(100vh - 57px);
  overflow-y: auto;
  /* Right padding is half the left gutter, not zero -- without it the
     scrollbar (inside this box's own right edge) sits flush against the
     panel content with no breathing room. */
  padding: 40px calc(var(--gutter) / 2) 40px var(--gutter);
}

.stats-board .metrics-grid { grid-template-columns: repeat(2, 1fr); }
.stats-board .panel-grid { grid-template-columns: 1fr; }

/* ---------------------------------------------------------------------- */
/* Metrics grid */
/* ---------------------------------------------------------------------- */

/* Same shape as .panel-grid/.panel below: the black background is just
   the hairline showing through the gaps -- the cells are the light
   surface, matching the (correctly white) panels beside them. */
.metrics-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: var(--rule);
  background: var(--black);
  border: var(--rule) solid var(--black);
}

.metric-card {
  background: var(--white);
  color: var(--black);
  padding: 18px 16px;
  min-height: 116px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.metric-card .label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--grey);
}

.metric-card .value {
  font-size: 30px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  margin-top: 10px;
  color: var(--black);
}

.metric-card.highlight .value { color: var(--green); }
.metric-card .sub {
  font-size: 10.5px;
  color: var(--grey);
  margin-top: 4px;
}

/* Market-insight panels -- who's hiring, what for, where. No ATS-vendor
   breakdown here -- that's plumbing, not a market signal. */

.panel-grid {
  margin-top: var(--rule);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--rule);
  background: var(--black);
  border: var(--rule) solid var(--black);
}

.panel {
  background: var(--white);
  padding: 18px 20px 20px;
}

.panel-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--grey);
  margin-bottom: 12px;
  font-weight: 700;
}

.bar-row {
  display: grid;
  grid-template-columns: 1fr 100px 44px;
  align-items: center;
  gap: 12px;
  font-size: 12.5px;
  padding: 6px 0;
}
.bar-row .name {
  min-width: 0; /* the ellipsis below can't engage without this */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bar-row .bar-track { background: var(--grey-line); height: 9px; position: relative; }
.bar-row .bar-fill { background: var(--black); height: 100%; }
.bar-row:first-child .bar-fill { background: var(--green); }
.bar-row .n { text-align: right; font-variant-numeric: tabular-nums; }
.bar-row.clickable { cursor: pointer; }
.bar-row.clickable .name:hover { color: var(--green); text-decoration: underline; }

.trend-chart { width: 100%; height: 64px; display: block; overflow: visible; }
.trend-bar { fill: var(--grey-line); }
.trend-bar.latest { fill: var(--green); }

/* Shared by the closed-jobs overlay line and the open-jobs-over-time
   line: black line/dots, green only on the most-recent point. */
.trend-line { fill: none; stroke: var(--black); stroke-width: 1.5; }
.trend-dot { fill: var(--black); }
.trend-dot.latest { fill: var(--green); }

.trend-legend {
  display: flex;
  gap: 14px;
  font-size: 9.5px;
  color: var(--grey);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 6px;
}
.trend-legend .dot { display: inline-block; width: 7px; height: 7px; margin-right: 4px; }
.trend-legend .dot.new { background: var(--grey-line); }
.trend-legend .dot.closed { background: var(--black); }

.trend-axis {
  display: flex;
  justify-content: space-between;
  font-size: 9.5px;
  color: var(--grey);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 4px;
}

/* One big headline number -- for a panel whose whole point is a single
   stat (the stale-listing rate), not a list of several. */
.ghost-pct {
  font-size: 34px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.ghost-sub { font-size: 11.5px; color: var(--grey); margin-top: 8px; }

@media (max-width: 720px) {
  .panel-grid { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------- */
/* Job board */
/* ---------------------------------------------------------------------- */

/* The list and its detail panel, side by side -- same fixed-width-sidebar
   idiom as .workspace (board/stats). .job-detail starts [hidden] in
   index.html; app.js clears that on first selection. Never a drawer or
   modal -- laid out in-flow like everything else in this system. */
.board-split {
  display: flex;
  align-items: flex-start;
  gap: var(--gutter);
}
.board-list { flex: 1 1 0; min-width: 0; }

.job-detail {
  flex: 0 0 clamp(320px, 34%, 420px);
  min-width: 0;
  position: sticky;
  top: 77px; /* topbar (56px content + 2px rule) + a little breathing room, so it doesn't sit flush under the sticky header */
  max-height: calc(100vh - 97px);
  overflow-y: auto;
  border: var(--rule) solid var(--black);
  padding: 20px;
}
.job-detail[hidden] { display: none; }

.job-detail-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.job-detail-close {
  flex: 0 0 auto;
  border: var(--rule) solid var(--black);
  background: var(--white);
  color: var(--black);
  width: 28px;
  height: 28px;
  font-size: 13px;
  cursor: pointer;
}
.job-detail-close:hover { background: var(--black); color: var(--white); }

.job-detail-title {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  margin: 2px 0 0;
  overflow-wrap: anywhere;
}
.job-detail-company {
  color: var(--grey);
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: 4px;
  overflow-wrap: anywhere;
}
.job-detail-badges { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px; }

.job-detail-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin: 16px 0;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--black);
}
.job-detail-apply {
  display: inline-flex;
  align-items: center;
  height: 38px;
  padding: 0 16px;
  background: var(--green);
  color: var(--white);
  border: var(--rule) solid var(--green);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-decoration: none;
  white-space: nowrap;
}
.job-detail-apply:hover { background: var(--black); border-color: var(--black); }
.job-detail-star {
  border: var(--rule) solid var(--black);
  background: var(--white);
  height: 38px;
  padding: 0 14px;
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
}
.job-detail-star.on { color: var(--green); border-color: var(--green); }
.job-detail-star:hover { border-color: var(--green); color: var(--green); }

.job-detail-meta { display: flex; flex-direction: column; gap: 10px; margin-bottom: 20px; }
.job-detail-meta-row { display: flex; gap: 10px; font-size: 12.5px; }
.job-detail-meta-row .label {
  flex: 0 0 92px;
  color: var(--grey);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 10.5px;
  padding-top: 1px;
}
.job-detail-meta-row .value { overflow-wrap: anywhere; }

.job-detail-description-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--grey);
  font-weight: 700;
  margin-bottom: 10px;
}
.job-detail-description {
  font-size: 12.5px;
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.job-detail-description.empty { color: var(--grey); font-style: normal; }
.job-detail-desc-heading {
  display: block;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--grey);
  margin-top: 12px;
}

table.jobs tbody tr.selected { background: var(--hover-bg); }
table.jobs tbody tr[data-id] { cursor: pointer; }

@media (max-width: 1300px) {
  .board-split { flex-direction: column; }
  .job-detail {
    flex-basis: auto;
    width: 100%;
    position: static;
    max-height: none;
  }
}

/* Flex-wrap, not a fixed-column grid -- drops filters onto a second row
   once they stop fitting, at any width, not just hand-picked breakpoints. */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 20px;
}
.filters > * { min-width: 0; } /* form controls have a real intrinsic width too */
#f-q, #f-keywords { flex: 1 1 200px; }
.filters .ms { flex: 1 1 130px; }
.filters label.toggle,
.filters #f-reset { flex: 0 0 auto; }

.filters input[type="text"],
.filters select {
  border: var(--rule) solid var(--black);
  background: var(--white);
  padding: 9px 10px;
  height: 38px;
  width: 100%;
}
.filters input[type="text"]:focus,
.filters select:focus { outline: 2px solid var(--green); outline-offset: -2px; }

/* Multi-select filter -- a native <select multiple> needs ctrl/cmd-click
   to pick more than one, not discoverable, so this is a checkbox-dropdown. */
.ms { position: relative; }
.ms-toggle {
  width: 100%;
  height: 38px;
  padding: 9px 10px;
  border: var(--rule) solid var(--black);
  background: var(--white);
  color: var(--black);
  font-family: var(--font);
  font-size: 13px;
  text-align: left;
  cursor: pointer;
  /* A long label otherwise wraps and spills past this fixed-height box --
     truncate with an ellipsis instead, same reasoning as .bar-row .name. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ms-toggle.active { border-color: var(--green); color: var(--green); font-weight: 700; }
.ms-toggle:focus { outline: 2px solid var(--green); outline-offset: -2px; }

.ms-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  width: max(100%, 220px);
  max-height: 320px;
  overflow-y: auto;
  background: var(--white);
  border: var(--rule) solid var(--black);
  z-index: 40;
  padding: 8px;
}

.ms-search {
  width: 100%;
  height: 32px;
  padding: 6px 8px;
  margin-bottom: 6px;
  border: 1px solid var(--grey-line);
  background: var(--white);
  color: var(--black);
  font-family: var(--font);
  font-size: 12px;
}

.ms-options { display: flex; flex-direction: column; }
.ms-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  font-size: 12.5px;
  cursor: pointer;
}
.ms-option:hover { background: var(--hover-bg); }
.ms-option input { accent-color: var(--green); flex-shrink: 0; }
.ms-empty { padding: 10px 4px; color: var(--grey); font-size: 12px; }

.ms-clear {
  width: 100%;
  margin-top: 6px;
  padding: 6px;
  border: 1px solid var(--grey-line);
  background: none;
  color: var(--grey);
  font-family: var(--font);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
}
.ms-clear:hover { border-color: var(--black); color: var(--black); }

.filters label.toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  border: var(--rule) solid var(--black);
  padding: 0 10px;
  height: 38px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  cursor: pointer;
}
.filters label.toggle input { accent-color: var(--green); }

.btn {
  border: var(--rule) solid var(--black);
  background: var(--black);
  color: var(--white);
  height: 38px;
  padding: 0 16px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  cursor: pointer;
}
.btn:hover { background: var(--green); border-color: var(--green); }
.btn.ghost { background: var(--white); color: var(--black); }
.btn.ghost:hover { background: var(--black); color: var(--white); border-color: var(--black); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--green);
  color: var(--white);
  border: var(--rule) solid var(--green);
  font-family: var(--font);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 6px 10px;
  margin-bottom: 12px;
  cursor: pointer;
}
.chip:hover { background: var(--black); border-color: var(--black); }

.result-count {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--grey);
  margin-bottom: 12px;
}
.result-count b { color: var(--black); }

/* #board's content padding leaves a gutter-wide gap between the table's
   own right edge and the divider. Widen by --gutter and pull back with a
   matching negative margin to bleed the table out to the true box edge;
   the last column gets that width back as padding to keep its own inset. */
table.jobs {
  width: calc(100% + var(--gutter));
  margin-right: calc(-1 * var(--gutter));
  border-collapse: collapse;
  font-size: 13px;
}
table.jobs thead th {
  text-align: left;
  text-transform: uppercase;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  color: var(--grey);
  border-bottom: var(--rule) solid var(--black);
  padding: 0 10px 10px;
  user-select: none;
  white-space: nowrap;
}
table.jobs thead th:last-child,
table.jobs tbody td:last-child {
  padding-right: calc(10px + var(--gutter));
}
/* Only sortable columns get the pointer cursor. */
table.jobs thead th[data-sort] { cursor: pointer; }
table.jobs thead th[data-sort]:hover { color: var(--black); }
table.jobs thead th.active { color: var(--black); }
table.jobs thead th.active::after { content: attr(data-dir); margin-left: 4px; color: var(--green); }

table.jobs tbody tr { border-bottom: 1px solid var(--black); }
table.jobs tbody tr:hover { background: var(--hover-bg); }
table.jobs tbody td { padding: 12px 10px; vertical-align: top; }

/* overflow-wrap:anywhere -- a company domain has no spaces to break at,
   and some job titles arrive as one long hyphenated/slashed word too. */
table.jobs .title-cell a {
  font-weight: 600;
  text-decoration: none;
  color: var(--black);
  overflow-wrap: anywhere;
}
table.jobs .title-cell a:hover { color: var(--green); }
table.jobs .company { color: var(--grey); font-size: 11.5px; text-transform: uppercase; margin-top: 2px; overflow-wrap: anywhere; }

.job-links {
  display: flex;
  align-items: center;
  flex-wrap: wrap; /* individual links can drop to a new row if truly out of width -- their own text never should (see white-space: nowrap below) */
  gap: 12px;
  margin-top: 8px;
}

/* The one action this row exists for -- green per rule 2 above. Filled,
   not just colored text, so it reads as the row's one button, not a
   same-weight sibling to Save link. Hover inverts to ink, like .chip/.btn. */
.job-links a.apply-link {
  display: inline-flex;
  align-items: center;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--white);
  background: var(--green);
  border: var(--rule) solid var(--green);
  padding: 4px 10px;
  text-decoration: none;
  white-space: nowrap;
}
.job-links a.apply-link:hover { background: var(--black); border-color: var(--black); }

.copy-link-btn {
  font-size: 10.5px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--grey);
  text-decoration: none;
  border: none;
  border-bottom: 1px solid var(--grey-line);
  background: none;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
}
.copy-link-btn:hover { color: var(--black); border-color: var(--black); }
.copy-link-btn.copied { color: var(--green); font-weight: 700; border-color: var(--green); }

.badge {
  display: inline-block;
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border: 1px solid var(--black);
  padding: 2px 6px;
  font-weight: 700;
}
.badge.best-effort { border-color: var(--grey); color: var(--grey); }
.title-cell .badge { margin-left: 6px; vertical-align: middle; }

.age-cell { font-variant-numeric: tabular-nums; white-space: nowrap; }
.age-cell.fresh { color: var(--green); font-weight: 700; }

.star-btn {
  border: none;
  background: none;
  cursor: pointer;
  font-size: 15px;
  color: var(--black);
  padding: 0;
  line-height: 1;
}
.star-btn.on { color: var(--green); }
.star-btn:hover { color: var(--green); }

.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap; /* page buttons + result-count text won't both fit one row on a phone */
  gap: 10px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--grey-line);
  font-size: 12px;
}
.pagination .pages { display: flex; gap: 6px; }
.pagination .pages button {
  border: 1px solid var(--black);
  background: var(--white);
  width: 32px;
  height: 32px;
  cursor: pointer;
}
.pagination .pages button.active { background: var(--black); color: var(--white); }
.pagination .pages button:disabled { opacity: 0.3; cursor: default; }

.empty-state, .error-state, .loading-state {
  border: var(--rule) dashed var(--grey-line);
  padding: 40px;
  text-align: center;
  color: var(--grey);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.error-state { border-color: var(--red); color: var(--red); }

/* ---------------------------------------------------------------------- */
/* Footer */
/* ---------------------------------------------------------------------- */

footer {
  padding: 40px 0 60px;
}
footer .footer-note {
  font-size: 12px;
  color: var(--grey);
  margin: 0 0 28px;
  max-width: 640px;
}
footer h3 {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin: 0 0 16px;
}
/* min-width:0 -- a curl command or long param row is an unbreakable-width
   child that would otherwise force the whole footer wider than the
   viewport instead of scrolling locally. */
.api-endpoint {
  min-width: 0;
  padding: 16px 0;
  border-top: 1px solid var(--grey-line);
}
.api-endpoint:first-of-type { border-top: none; padding-top: 0; }
.api-endpoint-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.api-method {
  flex: 0 0 auto;
  background: var(--black);
  color: var(--white);
  font-size: 10px;
  font-weight: bold;
  letter-spacing: 0.06em;
  padding: 2px 6px;
}
.api-path {
  font-family: "Courier New", monospace;
  font-size: 13px;
  font-weight: bold;
}
.api-endpoint > p {
  font-size: 12px;
  color: var(--grey);
  margin: 0 0 10px;
  max-width: 720px;
}
.api-params {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 10px;
  font-size: 12px;
}
.api-params td {
  padding: 4px 12px 4px 0;
  vertical-align: top;
  color: var(--grey);
}
.api-params td:first-child { white-space: nowrap; width: 1%; }
.api-params .param {
  font-family: "Courier New", monospace;
  font-size: 11.5px;
  font-weight: bold;
  color: var(--black);
}
/* Deliberately fixed, not var(--black)/var(--white) -- a terminal/code
   block stays dark regardless of the page's own light/dark state. */
footer code {
  display: block;
  background: #0a0a0a;
  color: #2fae60;
  text-shadow: 0 0 1px var(--white);
  padding: 10px 12px;
  font-size: 11.5px;
  margin-bottom: 8px;
  overflow-x: auto;
  white-space: pre;
}
footer p { color: var(--grey); margin: 0 0 8px; }

/* ---------------------------------------------------------------------- */
/* Responsive */
/* ---------------------------------------------------------------------- */

@media (max-width: 960px) {
  .workspace { grid-template-columns: 1fr; }
  .workspace > #board { border-right: none; padding-right: 0; }
  .stats-board {
    position: static;
    max-height: none;
    padding: 24px 0;
    border-top: var(--rule) solid var(--black);
    overflow-y: visible;
  }
  table.jobs thead { display: none; }
  /* Reset the desktop bleed (width:100%+gutter, negative margin) back to
     plain 100% -- meaningless once every cell stacks as its own block. */
  table.jobs, table.jobs tbody, table.jobs tr, table.jobs td { display: block; width: 100%; margin-right: 0; }
  table.jobs tr { padding: 10px 0; }
  /* Stacked cells need a label to tell them apart -- app.js's data-label
     attribute stands in for the table header that display:none removed. */
  table.jobs td[data-label] { padding: 4px 10px; }
  /* The desktop last-column padding (clears the divider) is meaningless
     stacked full-width -- just an oversized gap under one value. */
  table.jobs tbody td:last-child { padding-right: 10px; }
  table.jobs td[data-label]::before {
    content: attr(data-label) ": ";
    color: var(--grey);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }
}

@media (max-width: 640px) {
  /* On an actual phone the filter flex-basis values above still fit two
     or three per row -- full width reads better and gives bigger touch
     targets. */
  .filters > * { flex-basis: 100%; }
  /* Wordmark + 4 nav items don't fit a 360-390px phone in Monocraft --
     tighten rather than let the topbar force wider than the viewport. */
  .topnav { gap: 14px; font-size: 10.5px; }
  .wordmark { font-size: 13px; }
  .ticker-rule, .ticker { display: none; } /* topbar is already tight without a marquee too */
  .topbar .container { flex-wrap: wrap; row-gap: 8px; }
}
