/* =============================================================
   arXiv Design System — internal tools (tier 2)
   Admin Console, arXiv Check, the moderation queue.

   This file is NOT self-contained. Load the tier 1 stylesheet first, and
   put .ds-internal on <html> — that class is what makes the accent lime:

     <html lang="en" class="ds-internal">
     <link rel="stylesheet" href="design-system.css">
     <link rel="stylesheet" href="internal-tools.css">

   Tier 1 owns everything a second surface could use — the foundation,
   the alert, the tag, the field family, the close control. What lives
   here is what only internal tools have (tables, metadata panels,
   segmented controls, toggles, type badges, info cards, the internal
   icon-button variants), plus the tokens whose VALUES differ on this
   surface.

   The rule for this file: it may re-point a tier 1 token where this
   surface needs a different value. It must never introduce a token that
   reuses a tier 1 name for a different meaning.
   ============================================================= */


/* ─── Tokens that differ on this surface ────────────────────── */
/*
 * Only what disagrees with tier 1 is declared here. Everything else —
 * text, canvas, borders, links, focus ring, the four status families,
 * the spacing scale, the type stack — is inherited, because it is
 * identical on both surfaces and a second copy is only somewhere for
 * the two to drift apart.
 */
:root {

  /* Surfaces. Light matches tier 1; the dark values are a shade
     different because internal screens are dense with tables and want a
     little more separation between a row and its ground. */
  --ds-surface:               #ffffff;
  --ds-surface-muted:         var(--ds-grey-10);

  /* Internal-only surfaces: two hover washes, because a table row wants a
     wash you barely notice and a control wants one you do, and a
     pressed state below both. */
  --ds-surface-hover:         var(--ds-grey-5);
  --ds-surface-hover-strong:  var(--ds-grey-10);
  --ds-surface-active:        var(--ds-grey-25);

  /* Text one step above muted — column headers, a row's leading cell. */
  --ds-text-strong:           #4a433d;

}


/* ─── Icon button, internal variants ─────────────────────────
   Modifiers on tier 1's .ds-btn-icon, which is a shape composed with a
   Only what internal tools alone have is here: the pressed state of a
   toggle. The button itself is tier 1's, and so is the quiet destructive
   (.ds-btn-text.ds-btn-destructive). */

/* Compact — inline field actions and table rows. 29px tall, above the 24px floor. */

/* Constructive — edit, add, copy */

/* Pressed — a toggle that is on. aria-pressed carries the state; this only shows it. */
.ds-btn-icon[aria-pressed="true"] {
  background: var(--ds-surface-active);
  border-color: var(--ds-text-disabled);
  color: var(--ds-text-strong);
}
.ds-btn-icon[aria-pressed="true"]:hover:not(:disabled) {
  background: var(--ds-surface-hover-strong);
  border-color: var(--ds-text-disabled);
  color: var(--ds-text-strong);
}


/* The bulk bar's count: "2 selected", quieter than the actions beside it. */
.ds-bulk-count { font-size: 0.75rem; color: var(--ds-text-muted); }

/* ─── Table Row Selection ────────────────────────────────────
 * Selected rows carry the lime selection tint (
 * the tint aids scanability of the selection set). The row's checkbox
 * carries the state; the tint is never the only signal (WCAG 1.4.1).
 */
.ds-table tr.is-selected td { background: var(--ds-accent-wash); }


/* ─── Dark Mode Overrides ───────────────────────────────────── */
/*
 * Fires when: OS is set to dark  AND  the page has not locked to light mode.
 *
 * To lock a page to light mode, add data-theme="light" to <html>:
 *   <html lang="en" data-theme="light">
 * The :not([data-theme="light"]) guard prevents this block from applying.
 */

/* Dark mode. Only the tokens whose dark value differs from tier 1's; never
 * hand-pick a dark colour into a component rule. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* Only the tokens whose dark value differs from tier 1's. Everything
       else — text, canvas, borders, links, focus ring, all four status
       families — flips identically on both surfaces and is inherited. */

    /* Surfaces sit a shade apart from tier 1's: internal screens are dense
       with tables and want more separation between a row and its ground. */
    --ds-surface:               #252118;
    --ds-surface-muted:         #302c28;
    --ds-surface-hover:         #2a2520;
    --ds-surface-hover-strong:  #272420;
    --ds-surface-active:        #302c28;

    --ds-text-strong:           #d4cfc9;  /* 11.22:1 on dark ✓ */


  }

  /* Constructive icon — lime holds its light value, so the label is lime on dark */


}

/* ── The same values, keyed to the attribute ──────────────────────────────
   Generated from the @media block above; check-drift.py fails if the two
   disagree. The block above answers the OS; this one answers the reader,
   who can now say so on either surface. Until 2026-09-16 this file had no
   attribute rules at all, so an internal tool followed the machine and could
   not be switched — an asymmetry with tier 1 that was inherited, not chosen.
   Dropping the :root / html prefix also makes it scopable: a data-theme
   island anywhere in the DOM picks up the same values. */
[data-theme="dark"] {
  /* Only the tokens whose dark value differs from tier 1's. Everything
     else — text, canvas, borders, links, focus ring, all four status
     families — flips identically on both surfaces and is inherited. */

  /* Surfaces sit a shade apart from tier 1's: internal screens are dense
     with tables and want more separation between a row and its ground. */
  --ds-surface:               #252118;
  --ds-surface-muted:         #302c28;
  --ds-surface-hover:         #2a2520;
  --ds-surface-hover-strong:  #272420;
  --ds-surface-active:        #302c28;

  --ds-text-strong:           #d4cfc9;  /* 11.22:1 on dark ✓ */


}

/* Constructive icon — lime holds its light value, so the label is lime on dark */


/* ─── Data Table ───────────────────────────────────────────── */
/*
 * Base table styles for admin data tables. Warm-tinted header row,
 * subtle row dividers, hover highlight. Use .ds-table on <table>.
 *
 * Column widths: set via classes on <th> / <td> or inline widths.
 * The table defaults to auto layout; add table-layout: fixed to
 * the <table> element when fixed columns are needed.
 */

.ds-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: 6px;
  overflow: hidden;
}

.ds-table th {
  text-align: left;
  font-family: var(--ds-font-condensed);
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ds-text-muted);
  padding: 9px 14px;
  background: var(--ds-surface-muted);
  border-bottom: 1px solid var(--ds-border);
  white-space: nowrap;
}

.ds-table td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--ds-surface-muted);
  vertical-align: top;
  color: var(--ds-text);
}

.ds-table tbody tr:last-child td {
  border-bottom: none;
}

.ds-table tbody tr:hover td {
  background: var(--ds-surface-hover);
}

/* Filtered-out / hidden rows */
.ds-table tbody tr.hidden {
  display: none;
}

/* Table footer — row count, pagination, etc. */
.ds-table-footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 9px 14px;
  font-size: 0.75rem;
  color: var(--ds-text-muted);
  border-top: 1px solid var(--ds-border);
}


/* ─── Sortable Column Headers ──────────────────────────────── */
/*
 * Put <button class="sortable"> inside a <th> to make the column sortable from mouse and keyboard.
 * Add .sort-asc or .sort-desc to indicate current sort direction.
 * Place a <span class="sort-arrow"> inside the <th> for the indicator.
 *
 * Unsorted:  ⇅ (dimmed)
 * Ascending: ↑ (dark)
 * Descending:↓ (dark)
 */

.ds-table th .sortable {
  /* A button that looks like the header text it replaces: the keyboard stop is the point. */
  all: unset;
  display: inline;
  font: inherit;
  color: inherit;
  cursor: pointer;
  user-select: none;
  transition: color 0.1s;
}
.ds-table th .sortable:hover { color: var(--ds-text); }
.ds-table th .sortable:focus-visible {
  outline: 2px solid var(--ds-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

.sort-arrow {
  display: inline-block;
  margin-left: 3px;
  font-size: 0.5625rem;
  color: var(--ds-border-strong); /* 3.3:1 on the table header ground ✓ */
  vertical-align: middle;
}

.ds-table th.sort-asc .sort-arrow,
.ds-table th.sort-desc .sort-arrow {
  color: var(--ds-text);
}


/* ─── Filter Select ────────────────────────────────────────── */
/*
 * Minimal underline-only <select> for toolbar filters.
 * Used inline with a <label> in a .ds-filter wrapper.
 *
 * Usage:
 *   <div class="ds-filter">
 *     <label for="…">Show:</label>
 *     <select id="…">…</select>
 *   </div>
 */

.ds-filter {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.75rem;
  color: var(--ds-text-muted);
}

.ds-filter label {
  font-weight: 500;
  white-space: nowrap;
}

.ds-filter select {
  /* A filter is a control, so it carries the 24px floor even though its type
     is small — the padding grows the hit area without growing the text. */
  min-height: 24px;
  font-family: inherit;
  font-size: 0.75rem;
  color: var(--ds-text);
  background: none;
  border: none;
  border-bottom: 1px solid var(--ds-border-strong); /* 3.61:1 on white ✓ */
  border-radius: 0;
  padding: 1px 18px 1px 2px;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  /* Custom chevron */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%238b8680'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 2px center;
}

.ds-filter select:focus-visible {
  outline: 2px solid var(--ds-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}


/* ─── Form Validation ──────────────────────────────────────── */
/*
 * Invalid state: add .is-invalid to the input/textarea/select.
 * Error message: <p class="field-error"> below the field.
 * The field-error should have [hidden] by default, removed on validation failure.
 *
 * Usage:
 *   <label>Reason</label>
 *   <textarea class="is-invalid" required aria-required="true" aria-describedby="err-1">…</textarea>
 *   <p class="field-error" id="err-1">Please provide a reason.</p>
 */

/* ─── Form fields — internal-only additions ────────────────────── */
/*
 * The field family itself — .ds-field, .ds-label, .ds-input, .ds-hint,
 * .ds-check, the invalid state and the error message — lives in the tier 1
 * stylesheet, which this surface loads first. What is here is what only
 * internal tools need.
 *
 * The checkbox accent is the one genuine difference: a public checkbox
 * ticks Link Blue, a staff one ticks the accent, which is the same rule
 * every other control on this surface follows.
 *
 * Usage is unchanged:
 *   <div class="ds-field ds-field--md">
 *     <label class="ds-label" for="reason">Reason</label>
 *     <textarea class="ds-input is-invalid" id="reason"
 *               required aria-required="true" aria-describedby="reason-err"></textarea>
 *     <p class="field-error" id="reason-err">Say why this is being withdrawn.</p>
 *   </div>
 */

/* Field width follows the content: size a control to what it expects
   rather than stretching everything edge-to-edge. Internal screens are dense
   enough that this matters; public forms have not needed it yet. */
.ds-field--sm .ds-input { max-width: 240px; }
.ds-field--md .ds-input { max-width: 360px; }
.ds-field--lg .ds-input { max-width: 480px; }

/* The checkbox ticks this surface's accent, not Link Blue. */
.ds-check input { accent-color: var(--ds-accent-border); }

/* A row-selection checkbox has no label to borrow a target from, so it grows
   its own: 24px of cell, with the box left at its natural size. A dense table
   is exactly where this gets skipped, and exactly where mis-clicks cost most
   — the control beside it removes someone's access. */
.ds-table td:has(> input[type="checkbox"]),
.ds-table th:has(> input[type="checkbox"]) { min-width: 24px; }
.ds-table input[type="checkbox"] {
  accent-color: var(--ds-accent-border);
  width: 24px;
  height: 24px;
  margin: 0;
  cursor: pointer;
}

/* .is-invalid without .ds-input, for the staff controls that are not
   inputs — the segmented control and the category editor. */
.is-invalid {
  border-color: var(--ds-error-border);
  box-shadow: 0 0 0 3px rgba(198, 40, 40, 0.10);
}
.is-invalid:focus-visible {
  border-color: var(--ds-error-border);
  box-shadow: 0 0 0 3px rgba(198, 40, 40, 0.15);
}

/* Error slots render empty until validation fails. */
.field-error[hidden] { display: none; }

/* ─── Switch — staff colour only ────────────────────────────── */
/*
 * The component is .ds-switch in the tier 1 stylesheet. All this surface
 * changes is the on-track colour, and it changes it by re-pointing one
 * token — which is the whole point of the tier split.
 *
 * Not --ds-accent: Access Lime is a light fill built to carry dark text,
 * and a white thumb on it is 1.6:1. This is the darker end of the same
 * accent, which holds the knob at 4.8:1 and clears 3:1 against the page.
 */
:root { --ds-switch-on: var(--ds-accent-border-active); }

/* ─── Alert / Status Message ────────────────────────────────── */
/*
 * Nothing here. The whole component — .ds-alert and its four variants,
 * the icon, the title, the close control, and the forced-colors and
 * reduced-motion handling — lives in the tier 1 stylesheet, which this
 * surface loads first. The status palettes were already identical
 * between the two surfaces, so there was nothing left to override.
 */