/* ==========================================================================
   Update Server — dashboard design system
   --------------------------------------------------------------------------
   Constraints this file is written under, all from the app's CSP
   (`style-src 'self'`, `script-src 'self'`, no `font-src`):

   - No inline `style="..."` attributes anywhere in the views. Anything that
     changes at runtime (the upload progress bar) is set through the CSSOM
     from an external script, which CSP does not police.
   - No webfonts. The stack below is what the OS already has, which is also
     why headings lean on weight and letter-spacing rather than a display
     face to carry hierarchy.
   - Icons are inline SVG in the markup, so there is nothing to fetch.
   ========================================================================== */

/* --- Tokens ------------------------------------------------------------- */

:root {
  color-scheme: dark;

  /* Surfaces, darkest to lightest. Elevation is a step up this ladder plus a
     shadow, never a one-off colour. */
  --bg: #0a0b0f;
  --bg-grad: radial-gradient(1200px 600px at 50% -200px, #171a26 0%, #0a0b0f 70%);
  --surface: #13151c;
  --surface-2: #191c25;
  --surface-3: #21242f;
  --border: #23262f;
  --border-strong: #333846;

  /* Text, most to least prominent. Three levels is enough; a fourth always
     ends up indistinguishable from the third. */
  --text: #f2f4f8;
  --text-2: #a4acbd;
  --text-3: #6f7789;

  --primary: #6366f1;
  --primary-hover: #7b7df3;
  --primary-press: #5457e0;
  --primary-soft: rgba(99, 102, 241, 0.14);
  --primary-ring: rgba(99, 102, 241, 0.35);
  --on-primary: #fff;

  --green: #34d399;
  --green-text: #6ee7b7;
  --green-soft: rgba(52, 211, 153, 0.13);
  --green-line: rgba(52, 211, 153, 0.32);

  --red: #f87171;
  --red-text: #fca5a5;
  --red-soft: rgba(248, 113, 113, 0.13);
  --red-line: rgba(248, 113, 113, 0.32);

  --amber: #fbbf24;
  --amber-text: #fcd34d;
  --amber-soft: rgba(251, 191, 36, 0.13);
  --amber-line: rgba(251, 191, 36, 0.32);

  --radius-lg: 16px;
  --radius: 12px;
  --radius-sm: 9px;
  --radius-xs: 7px;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
  --shadow: 0 4px 16px -4px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 24px 60px -20px rgba(0, 0, 0, 0.7);

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Light theme. Only the tokens change — every rule below is written against
   them, so the two themes cannot drift apart. */
@media (prefers-color-scheme: light) {
  :root {
    color-scheme: light;

    --bg: #f6f7f9;
    --bg-grad: radial-gradient(1200px 600px at 50% -240px, #e8ebf3 0%, #f6f7f9 70%);
    --surface: #ffffff;
    --surface-2: #f4f5f8;
    --surface-3: #e9ebf0;
    --border: #e3e6ec;
    --border-strong: #cdd2dc;

    --text: #10131a;
    --text-2: #545c6b;
    --text-3: #838b9a;

    --primary: #4f46e5;
    --primary-hover: #4338ca;
    --primary-press: #3730a3;
    --primary-soft: rgba(79, 70, 229, 0.09);
    --primary-ring: rgba(79, 70, 229, 0.25);

    --green: #059669;
    --green-text: #047857;
    --green-soft: rgba(5, 150, 105, 0.1);
    --green-line: rgba(5, 150, 105, 0.28);

    --red: #dc2626;
    --red-text: #b91c1c;
    --red-soft: rgba(220, 38, 38, 0.09);
    --red-line: rgba(220, 38, 38, 0.26);

    --amber: #d97706;
    --amber-text: #b45309;
    --amber-soft: rgba(217, 119, 6, 0.11);
    --amber-line: rgba(217, 119, 6, 0.3);

    --shadow-sm: 0 1px 2px rgba(16, 19, 26, 0.06);
    --shadow: 0 4px 16px -4px rgba(16, 19, 26, 0.1);
    --shadow-lg: 0 24px 60px -20px rgba(16, 19, 26, 0.22);
  }
}

/* --- Base --------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  color: var(--text);
  background-color: var(--bg);
  background-image: var(--bg-grad);
  background-repeat: no-repeat;
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -0.017em; line-height: 1.25; }
h1 { font-size: 1.55rem; }
h2 { font-size: 1.02rem; }
h3 { font-size: 0.92rem; }
p { margin: 0; }

a { color: var(--primary); text-decoration: none; }
a:hover { text-decoration: underline; }

code {
  font-family: var(--mono);
  font-size: 0.86em;
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: 0.1em 0.42em;
  border-radius: var(--radius-xs);
}

.muted { color: var(--text-2); }
.dim { color: var(--text-3); }
.small { font-size: 0.83rem; }
.mono { font-family: var(--mono); font-size: 0.86em; }
.nums { font-variant-numeric: tabular-nums; }
.center-text { text-align: center; }

/* One visible focus treatment for everything, and only for keyboard users. */
:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Layout ------------------------------------------------------------- */

.container { width: 100%; max-width: 1140px; margin: 0 auto; padding: 32px 24px 88px; }
.container.narrow { max-width: 720px; }
.centered { min-height: 100vh; display: grid; place-items: center; padding: 24px; }

.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
.page-head .titles { min-width: 0; }
.page-head .titles > p { margin-top: 6px; }

/* --- Top bar ------------------------------------------------------------ */

.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 28px;
  height: 58px;
  padding: 0 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .topbar {
    background: color-mix(in srgb, var(--surface) 78%, transparent);
    backdrop-filter: saturate(170%) blur(12px);
    -webkit-backdrop-filter: saturate(170%) blur(12px);
  }
}

/* The brand is a link home, but it must not read as one — the generic anchor
   colour would make the wordmark compete with the primary action. */
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-weight: 650;
  letter-spacing: -0.015em;
}
.brand:hover { text-decoration: none; }
.brand .logo {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  color: #fff;
  background: linear-gradient(140deg, var(--primary-hover), var(--primary-press));
  box-shadow: var(--shadow-sm);
  flex: none;
}
.brand .logo svg { width: 15px; height: 15px; display: block; }
.brand-lg { font-size: 1.16rem; }
.brand-lg .logo { width: 34px; height: 34px; border-radius: 10px; }
.brand-lg .logo svg { width: 18px; height: 18px; }

.nav { display: flex; gap: 3px; }
.nav a {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  font-size: 0.9rem;
  font-weight: 550;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.nav a:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
.nav a.active { background: var(--primary-soft); color: var(--primary); }
.nav svg { width: 15px; height: 15px; flex: none; }

.user { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.avatar {
  display: grid;
  place-items: center;
  width: 27px;
  height: 27px;
  border-radius: 50%;
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  color: var(--text-2);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  flex: none;
}
.user .who { color: var(--text-2); font-size: 0.87rem; }

/* --- Cards -------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 26px;
  box-shadow: var(--shadow-sm);
}

.auth-card {
  width: 100%;
  max-width: 392px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 34px 32px;
  box-shadow: var(--shadow-lg);
}
.auth-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-bottom: 24px;
  text-align: center;
}
.auth-card .stack { text-align: left; }

/* --- Status cards ------------------------------------------------------- */
/* The two delivery gates. They share a shape so the eye reads them as one
   control surface, and each carries its state colour on the top edge — the
   "off" states have to be obvious, because either one silently stops every
   device from updating. */

.status-grid {
  display: grid;
  /* min() matters: an auto-fit track will not shrink below its own floor, so a
     bare minmax(330px, 1fr) is wider than a phone viewport and gives the whole
     page a horizontal scroll. */
  grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.status {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.status::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--border-strong);
}
.status-ok::before { background: linear-gradient(90deg, var(--green), transparent 88%); }
.status-bad::before { background: linear-gradient(90deg, var(--red), transparent 88%); }
.status-warn::before { background: linear-gradient(90deg, var(--amber), transparent 88%); }

.status-top { display: flex; align-items: center; gap: 11px; min-width: 0; }
.status-top > div { min-width: 0; }
.status-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-2);
  flex: none;
}
.status-icon svg { width: 17px; height: 17px; }
.status-ok .status-icon { background: var(--green-soft); border-color: var(--green-line); color: var(--green); }
.status-bad .status-icon { background: var(--red-soft); border-color: var(--red-line); color: var(--red); }
.status-warn .status-icon { background: var(--amber-soft); border-color: var(--amber-line); color: var(--amber); }

.status-label {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-3);
}
.status-value {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 2px;
  font-size: 1.02rem;
  font-weight: 650;
  letter-spacing: -0.015em;
}
.status p { font-size: 0.87rem; color: var(--text-2); min-width: 0; overflow-wrap: anywhere; }
.status-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: auto;
}
.status-foot .stamp { font-size: 0.78rem; color: var(--text-3); }

/* A dot that reads as "currently serving" at a glance. */
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--text-3); }
.dot-ok { background: var(--green); animation: pulse 2.6s var(--ease) infinite; }
.dot-bad { background: var(--red); box-shadow: 0 0 0 4px var(--red-soft); }
.dot-warn { background: var(--amber); box-shadow: 0 0 0 4px var(--amber-soft); }
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--green-soft); }
  50% { box-shadow: 0 0 0 7px transparent; }
}

/* --- Switch ------------------------------------------------------------- */
/* A submit button, not a checkbox: flipping it is a server state change, so it
   has to post. It is styled as a switch because that is what it means, and
   carries aria-pressed so assistive tech is told the same thing. */

.switch {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 5px 12px 5px 6px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  color: var(--text-2);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.switch:hover { background: var(--surface-3); color: var(--text); }
.switch .track {
  position: relative;
  width: 34px;
  height: 20px;
  border-radius: 999px;
  background: var(--border-strong);
  transition: background 0.2s var(--ease);
  flex: none;
}
.switch .track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: transform 0.2s var(--ease);
}
.switch[aria-pressed="true"] { color: var(--text); }
.switch[aria-pressed="true"] .track { background: var(--green); }
.switch[aria-pressed="true"] .track::after { transform: translateX(14px); background: #fff; }

/* --- Buttons ------------------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 15px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  font-size: 0.89rem;
  font-weight: 600;
  line-height: 1.3;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease),
              color 0.15s var(--ease), transform 0.08s var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(0.5px); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.btn svg { width: 15px; height: 15px; flex: none; }

.btn-primary { background: var(--primary); color: var(--on-primary); box-shadow: var(--shadow-sm); }
.btn-primary:hover:not(:disabled) { background: var(--primary-hover); }
.btn-primary:active:not(:disabled) { background: var(--primary-press); }

.btn-ghost { background: var(--surface-2); border-color: var(--border-strong); color: var(--text); }
.btn-ghost:hover:not(:disabled) { background: var(--surface-3); border-color: var(--text-3); }

.btn-quiet { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-quiet:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

.btn-danger { background: transparent; border-color: var(--red-line); color: var(--red-text); }
.btn-danger:hover:not(:disabled) { background: var(--red-soft); border-color: var(--red); }

.btn-sm { padding: 6px 11px; font-size: 0.83rem; border-radius: var(--radius-xs); }
.btn-sm svg { width: 13px; height: 13px; }
.btn-block { width: 100%; }
.inline { display: inline-flex; }

/* --- Badges & chips ----------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
  vertical-align: middle;
}
.badge-green { background: var(--green-soft); border-color: var(--green-line); color: var(--green-text); }
.badge-red { background: var(--red-soft); border-color: var(--red-line); color: var(--red-text); }
.badge-amber { background: var(--amber-soft); border-color: var(--amber-line); color: var(--amber-text); }
/* "newest" states a fact about ordering, not a status. It sits beside the live
   badge and must not compete with it — that one says what actually ships. */
.badge-muted { background: var(--surface-2); border-color: var(--border); color: var(--text-3); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text-2);
}
.chip svg { width: 12px; height: 12px; opacity: 0.75; flex: none; }

/* --- Flash -------------------------------------------------------------- */

.flash {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 13px 15px;
  margin-bottom: 20px;
  border: 1px solid;
  border-radius: var(--radius);
  font-size: 0.9rem;
}
.flash > svg { width: 17px; height: 17px; flex: none; margin-top: 1px; }
.flash-body { flex: 1; min-width: 0; }
.flash-success { background: var(--green-soft); border-color: var(--green-line); color: var(--green-text); }
.flash-error { background: var(--red-soft); border-color: var(--red-line); color: var(--red-text); }
.flash-warn { background: var(--amber-soft); border-color: var(--amber-line); color: var(--amber-text); }
.flash .close {
  flex: none;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--radius-xs);
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
}
.flash .close:hover { opacity: 1; background: rgba(127, 127, 127, 0.18); }
.flash .close svg { width: 13px; height: 13px; margin: 0; }

/* --- Forms -------------------------------------------------------------- */

.stack { display: flex; flex-direction: column; gap: 20px; }
label > span { display: block; font-size: 0.83rem; font-weight: 600; margin-bottom: 7px; color: var(--text); }

input[type=text],
input[type=password],
input[type=number],
textarea,
select {
  width: 100%;
  padding: 10px 13px;
  font: inherit;
  font-size: 0.92rem;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease), background 0.15s var(--ease);
}
input::placeholder, textarea::placeholder { color: var(--text-3); }
input:hover:not(:disabled), textarea:hover, select:hover { border-color: var(--text-3); }
input:focus, textarea:focus, select:focus {
  outline: none;
  background: var(--surface);
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-ring);
}
input:disabled {
  color: var(--text-3);
  background: var(--surface);
  border-style: dashed;
  cursor: not-allowed;
}
textarea { resize: vertical; min-height: 96px; font-family: var(--font); line-height: 1.6; }
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 34px;
  /* Chevron drawn with two gradients — nothing to fetch, and no inline style
     attribute, both of which the CSP would block. */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-3) 50%),
    linear-gradient(135deg, var(--text-3) 50%, transparent 50%);
  background-position: right 16px center, right 11px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

small, .hint { display: block; margin-top: 6px; font-size: 0.79rem; color: var(--text-3); line-height: 1.5; }

.row { display: flex; gap: 16px; }
.grow { flex: 1; min-width: 0; }

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 13px 15px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color 0.15s var(--ease);
}
.checkbox:hover { border-color: var(--border-strong); }
.checkbox input { width: 17px; height: 17px; margin: 2px 0 0; accent-color: var(--primary); flex: none; cursor: pointer; }
.checkbox > div { min-width: 0; }
.checkbox span { display: block; margin: 0; font-size: 0.89rem; font-weight: 600; }
.checkbox .hint { margin-top: 3px; font-weight: 400; }

.actions { display: flex; justify-content: flex-end; gap: 10px; }
.divider { height: 1px; background: var(--border); border: 0; margin: 2px 0; }

/* File input styled as a drop target. `::file-selector-button` restyles the
   native control in place, so it stays a real <input type=file> — keeping
   keyboard access and the `required` validation the form relies on. */
.file-field input[type=file] {
  width: 100%;
  padding: 18px;
  font-size: 0.88rem;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1.5px dashed var(--border-strong);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.file-field input[type=file]:hover { border-color: var(--primary); background: var(--primary-soft); }
.file-field input[type=file]::file-selector-button {
  margin-right: 13px;
  padding: 7px 13px;
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  cursor: pointer;
}
.file-field input[type=file]::file-selector-button:hover { background: var(--border-strong); }

/* --- Toolbar (app switcher) --------------------------------------------- */

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 16px;
  margin-bottom: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.toolbar-label { display: flex; align-items: center; gap: 7px; font-size: 0.83rem; font-weight: 600; color: var(--text-2); }
.toolbar-label svg { width: 14px; height: 14px; }
.toolbar select { width: auto; min-width: 240px; padding-top: 7px; padding-bottom: 7px; font-size: 0.87rem; }

/* --- Table -------------------------------------------------------------- */

.table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.table-scroll { overflow-x: auto; }
.table { width: 100%; min-width: 760px; border-collapse: collapse; font-size: 0.88rem; }
.table th, .table td { padding: 13px 16px; text-align: left; vertical-align: top; }
.table th {
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  color: var(--text-3);
  font-size: 0.71rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.table tbody tr { border-bottom: 1px solid var(--border); transition: background 0.12s var(--ease); }
.table tbody tr:last-child { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-2); }
.table td.right, .table th.right { text-align: right; }
.table .ver { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; font-weight: 650; letter-spacing: -0.01em; }
.table .nowrap { white-space: nowrap; }

/* The build number is the value the app actually compares, so it is set at full
   size in tabular figures rather than shrunk the way `.mono` shrinks inline
   code — the version string beside it is the decorative half of the pair. */
.table .build {
  font-family: var(--mono);
  font-size: 0.92em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* The served build gets a left accent rail plus a wash. It is rarely the first
   row once builds are staged ahead of release, so it has to be findable
   without reading the Live column. */
.table tbody tr.row-live { background: var(--green-soft); }
.table tbody tr.row-live:hover { background: var(--green-soft); }
.table tbody tr.row-live td:first-child { box-shadow: inset 3px 0 0 var(--green); }

.notes { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; max-width: 320px; }
.notes li { position: relative; padding-left: 13px; color: var(--text-2); font-size: 0.84rem; }
.notes li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.58em;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--text-3);
}
.row-actions { display: flex; gap: 6px; justify-content: flex-end; align-items: center; }
.table-note { margin-top: 12px; text-align: center; }

/* --- Definition list (edit form metadata) ------------------------------- */

.meta { margin: 0; display: grid; gap: 10px; }
.meta > div { display: flex; gap: 14px; font-size: 0.85rem; }
.meta dt { flex: 0 0 96px; color: var(--text-3); }
.meta dd { margin: 0; min-width: 0; color: var(--text-2); overflow-wrap: anywhere; }

/* --- Empty state -------------------------------------------------------- */

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 72px 24px;
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}
.empty-icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  margin-bottom: 18px;
  border-radius: var(--radius);
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-3);
}
.empty-icon svg { width: 24px; height: 24px; }
.empty h2 { margin-bottom: 6px; }
.empty p { color: var(--text-2); max-width: 46ch; margin-bottom: 20px; }

/* --- Progress ----------------------------------------------------------- */

.progress { height: 6px; background: var(--surface-3); border-radius: 999px; overflow: hidden; }
.progress-bar {
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--primary), var(--primary-hover));
  transition: width 0.2s var(--ease);
}

/* --- Error page --------------------------------------------------------- */

.error-code {
  font-size: 3.4rem;
  font-weight: 750;
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: 10px;
  color: var(--primary);
}

/* --- Responsive --------------------------------------------------------- */

/* The top bar sheds detail on its own schedule: the wordmark and the button
   labels only get in the way once there is genuinely no room, which is well
   below the width at which the table has to become cards. */
@media (max-width: 620px) {
  .topbar { gap: 12px; padding: 0 14px; }
  .brand span:last-child { display: none; }
  .nav { min-width: 0; }
  .nav a { padding: 7px 9px; }
  .nav a span, .user .who, .user form span { display: none; }
  .user .btn { padding: 7px; }
}

@media (max-width: 900px) {
  .container { padding: 24px 16px 64px; }
  .row { flex-direction: column; }
  .actions { flex-direction: column-reverse; }
  .actions .btn { width: 100%; }
  .toolbar select { width: 100%; min-width: 0; }

  /* The release history stops being a table and becomes a stack of cards.
     Nine columns cannot be scrolled usefully on a phone, and the header row is
     what carries the meaning — so each cell reprints its own label. */
  .table-wrap { background: transparent; border: 0; box-shadow: none; }
  .table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .table, .table tbody, .table tr, .table td { display: block; width: 100%; }
  .table { min-width: 0; }
  .table tbody tr {
    margin-bottom: 12px;
    padding: 6px 0;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
  }
  .table tbody tr.row-live { border-color: var(--green-line); }
  .table tbody tr.row-live td:first-child { box-shadow: none; }
  .table td {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    min-width: 0;
    padding: 7px 15px;
    text-align: right;
    overflow-wrap: anywhere;
  }
  .table td::before {
    content: attr(data-label);
    flex: none;
    padding-top: 2px;
    color: var(--text-3);
    font-size: 0.71rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
  }
  .table .ver { justify-content: flex-end; }
  .notes { align-items: flex-end; max-width: none; }
  .notes li { padding-left: 0; padding-right: 13px; text-align: right; }
  .notes li::before { left: auto; right: 0; }
  .row-actions { flex: 1; }
}
