/* ==========================================================================
   Precision Instrument — ripmanager theme
   --------------------------------------------------------------------------
   Dark mode first. Apple-inspired minimalism. Premium and understated.
   Deep observatory blue dominates; brass appears only on important actions
   and highlights. No gradients, no glow, no startup candy.

   Visual reference: vintage audio equipment, watch movements, astronomy,
   precision manufacturing.

   LAYER 1 (tokens) and LAYER 2 (primitives) are copied verbatim from
   riptidal's static/theme.css — the shared house style. Keep them in sync
   across ripqueue, riptidal and ripmanager. LAYER 3 is ripmanager's own
   and is still empty; the project has no statuses yet.
   ========================================================================== */

/* ==========================================================================
   LAYER 1 — Tokens
   ========================================================================== */

:root {
  /* Brand ------------------------------------------------------------- */
  --primary:          #213A5A;   /* deep observatory blue — dominant */
  --primary-hover:    #2D4E77;
  --accent:           #B08D57;   /* brass — important actions only */
  --accent-hover:     #C09A60;

  /* Surfaces ---------------------------------------------------------- */
  --bg:               #0E1218;
  --surface:          #171D25;
  --surface-elevated: #202833;
  --border:           #304050;

  /* Text -------------------------------------------------------------- */
  --text:             #E8EDF3;
  --text-secondary:   #AAB5C3;
  --text-muted:       #758293;

  /* Semantic ---------------------------------------------------------- */
  --success:          #4F8A63;
  --warning:          #C69243;
  --error:            #B45454;
  --info:             #4C78A8;

  /* Semantic, low-emphasis. Tints of the above for outline treatments.
     Kept as explicit values rather than opacity so they composite
     identically over --surface and --surface-elevated. */
  --success-dim:      #7FB894;
  --success-line:     #3D6B4D;
  --success-wash:     rgba(79, 138, 99, 0.12);
  --warning-dim:      #DBB477;
  --warning-line:     #6E5427;
  --warning-wash:     rgba(198, 146, 67, 0.12);
  --error-dim:        #D08A8A;
  --error-line:       #6E3535;
  --error-wash:       rgba(180, 84, 84, 0.12);
  --info-dim:         #7FA5CC;
  --info-line:        #3A5A7C;
  --info-wash:        rgba(76, 120, 168, 0.10);
  --accent-wash:      rgba(176, 141, 87, 0.12);

  /* Typography -------------------------------------------------------- */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
          system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SF Mono", ui-monospace, SFMono-Regular, "JetBrains Mono",
          Menlo, Consolas, monospace;

  --fs-xs:   11px;
  --fs-sm:   12.5px;
  --fs-base: 14px;
  --fs-md:   15px;
  --fs-lg:   18px;
  --fs-xl:   24px;
  --fs-2xl:  32px;

  --lh-tight: 1.25;
  --lh-base:  1.55;

  /* Section eyebrows: uppercase, tracked out, muted. Used for every
     section label in the app so scanning feels instrument-like. */
  --eyebrow-size: 10.5px;
  --eyebrow-track: 0.09em;

  /* Geometry ---------------------------------------------------------- */
  --r-sm: 5px;
  --r-md: 7px;
  --r-lg: 10px;
  --r-xl: 14px;

  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 22px;
  --sp-6: 32px;
  --sp-7: 48px;

  /* Elevation. Shadows are deep and soft, never colored — the eye should
     read depth, not decoration. */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 4px 14px rgba(0, 0, 0, 0.40);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.55);

  --focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--info);

  --transition: 120ms cubic-bezier(0.32, 0.72, 0, 1);
}

/* This app is dark-mode first and does not ship a light palette. Declaring
   the scheme keeps form controls, scrollbars and the UA caret dark. */
:root { color-scheme: dark; }


/* ==========================================================================
   LAYER 2 — Primitives
   ========================================================================== */

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Numbers must never shift width — queue positions, years, runtimes,
   timestamps and counts all sit in columns. */
.tnum, table, input[type="number"], time, .pos, .count {
  font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4 {
  margin: 0 0 var(--sp-3);
  line-height: var(--lh-tight);
  letter-spacing: -0.011em;
  font-weight: 600;
}
h1 { font-size: var(--fs-2xl); letter-spacing: -0.021em; }
h2 { font-size: var(--fs-xl);  letter-spacing: -0.017em; }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

p { margin: 0 0 var(--sp-3); }

a {
  color: var(--info-dim);
  text-decoration: none;
  transition: color var(--transition);
}
a:hover { color: var(--text); }

code, kbd, pre { font-family: var(--font-mono); font-size: 0.92em; }

hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--sp-5) 0;
}

:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--r-sm);
}

::selection { background: var(--primary-hover); color: var(--text); }

/* Screen-reader only ------------------------------------------------- */
.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;
}

/* Layout -------------------------------------------------------------- */
.container { width: 100%; max-width: 1120px; margin: 0 auto; padding: 0 var(--sp-4); }
.container--narrow { max-width: 720px; }
.container--content { max-width: 940px; }

.stack > * + * { margin-top: var(--sp-3); }
.stack-lg > * + * { margin-top: var(--sp-5); }

.row { display: flex; align-items: center; gap: var(--sp-2); }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.spacer { flex: 1 1 auto; }

/* Eyebrow / section label --------------------------------------------- */
.eyebrow {
  font-size: var(--eyebrow-size);
  letter-spacing: var(--eyebrow-track);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-muted);
  margin: 0 0 var(--sp-3);
}

.muted { color: var(--text-muted); }
.secondary { color: var(--text-secondary); }
.small { font-size: var(--fs-sm); }

/* Navigation ---------------------------------------------------------- */
.nav {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 40;
}
.nav-inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  height: 54px;
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 var(--sp-4);
}
.nav-brand {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.012em;
}
/* The one brass mark in the chrome: a hairline under the wordmark. */
.nav-brand::after {
  content: "";
  display: block;
  height: 1.5px;
  width: 20px;
  margin-top: 3px;
  background: var(--accent);
  border-radius: 1px;
}
.nav-links { display: flex; align-items: center; gap: var(--sp-1); }
.nav-link {
  color: var(--text-secondary);
  font-size: var(--fs-sm);
  font-weight: 500;
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--r-sm);
  transition: background var(--transition), color var(--transition);
}
.nav-link:hover { background: var(--surface-elevated); color: var(--text); }
.nav-link[aria-current="page"] { background: var(--primary); color: var(--text); }

/* Cards and panels ---------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
}
.card--elevated { background: var(--surface-elevated); box-shadow: var(--shadow-md); }
.card--flush { padding: 0; overflow: hidden; }

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.card-body { padding: var(--sp-5); }
.card-footer {
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border);
  background: var(--bg);
}

/* Buttons -------------------------------------------------------------
   Brass is the single primary action per view. Everything else is quiet. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 550;
  line-height: 1;
  padding: 9px var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface-elevated);
  color: var(--text);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition), border-color var(--transition),
              color var(--transition), opacity var(--transition);
}
.btn:hover { background: var(--border); }

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
  font-weight: 600;
}
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

.btn-secondary { background: var(--primary); border-color: var(--primary); color: var(--text); }
.btn-secondary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }

.btn-ghost { background: transparent; border-color: var(--border); color: var(--text-secondary); }
.btn-ghost:hover { background: var(--surface-elevated); color: var(--text); }

.btn-danger { background: transparent; border-color: var(--error-line); color: var(--error-dim); }
.btn-danger:hover { background: var(--error-wash); border-color: var(--error); color: var(--text); }

.btn-sm { font-size: var(--fs-xs); padding: 6px var(--sp-3); border-radius: var(--r-sm); }
.btn-lg { font-size: var(--fs-base); padding: 12px var(--sp-5); }

.btn:disabled, .btn[aria-disabled="true"] {
  opacity: 0.42;
  cursor: not-allowed;
  pointer-events: none;
}

/* Icon-only button — used for the queue reorder arrows. */
.btn-icon {
  width: 30px; height: 30px;
  padding: 0;
  border-radius: var(--r-sm);
  color: var(--text-muted);
  background: transparent;
}
.btn-icon:hover { background: var(--surface-elevated); color: var(--accent); }

/* Forms ---------------------------------------------------------------- */
.field { display: block; margin-bottom: var(--sp-4); }
.label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.hint { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 5px; }

.input, .select, .textarea {
  width: 100%;
  font-family: inherit;
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 9px var(--sp-3);
  transition: border-color var(--transition), background var(--transition);
}
.input::placeholder, .textarea::placeholder { color: var(--text-muted); }
.input:hover, .select:hover, .textarea:hover { border-color: #3B4E62; }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--info);
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--info-wash);
}
.textarea { min-height: 92px; resize: vertical; line-height: var(--lh-base); }

.select {
  appearance: none;
  padding-right: var(--sp-6);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%23758293' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-3) center;
}

.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--error); }
.field-error { font-size: var(--fs-xs); color: var(--error-dim); margin-top: 5px; }

/* Search field — the wizard's centrepiece. */
.search {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 0 var(--sp-3);
}
.search:focus-within { border-color: var(--info); box-shadow: 0 0 0 3px var(--info-wash); }
.search input {
  flex: 1;
  border: 0; background: transparent; color: var(--text);
  font-family: inherit; font-size: var(--fs-md);
  padding: 11px 0;
}
.search input:focus { outline: none; }
/* The wrapper already indicates focus via :focus-within. Without this the
   global :focus-visible rule draws a second ring around the input itself,
   which reads as a box inside a box. */
.search input:focus-visible { box-shadow: none; }

/* Tables --------------------------------------------------------------- */

/* Wide tables scroll inside their own box rather than stretching the page.
   This lived only in the mobile media query, which is backwards: a narrow
   screen is not where a wide table causes trouble. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Columns size to their content and give the rest to the widest one, so a
   table does not spread its few columns across the full width with acres
   between them. */
.table { width: 100%; table-layout: auto; border-collapse: collapse; font-size: var(--fs-sm); }
.table td:not(:last-child), .table th:not(:last-child) { white-space: nowrap; }
.table td:first-child, .table th:first-child { width: 40%; }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.table th {
  text-align: left;
  font-size: var(--eyebrow-size);
  letter-spacing: var(--eyebrow-track);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-muted);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--surface-elevated);
  color: var(--text-secondary);
  vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover td { background: var(--surface-elevated); }
.table td.title { color: var(--text); font-weight: 500; }
.table td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* Queue position marker — brass, because it is the thing the admin
   manipulates and the thing the requester waits on. */
.pos {
  display: inline-block;
  min-width: 2.1em;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* Dialogs -------------------------------------------------------------- */
dialog, .modal {
  background: var(--surface-elevated);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  padding: 0;
  width: min(560px, calc(100vw - 2 * var(--sp-4)));
}
dialog::backdrop { background: rgba(4, 7, 11, 0.68); }
.modal-header {
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
  border-bottom: 1px solid var(--border);
}
.modal-title { font-size: var(--fs-lg); font-weight: 600; margin: 0; }
.modal-body { padding: var(--sp-5); }
.modal-footer {
  display: flex; justify-content: flex-end; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border);
  background: var(--bg);
  border-radius: 0 0 var(--r-xl) var(--r-xl);
}

/* Banners -------------------------------------------------------------- */
.banner {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface-elevated);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}
.banner-info    { border-color: var(--info-line);    background: var(--info-wash); }
.banner-success { border-color: var(--success-line); background: var(--success-wash); }
.banner-warning { border-color: var(--warning-line); background: var(--warning-wash); }
.banner-error   { border-color: var(--error-line);   background: var(--error-wash); }

/* Wizard stepper ------------------------------------------------------- */
.stepper { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-5); }
.step { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); color: var(--text-muted); }
.step-mark {
  width: 22px; height: 22px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  font-size: var(--fs-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.step[aria-current="step"] { color: var(--text); }
.step[aria-current="step"] .step-mark { border-color: var(--accent); color: var(--accent); }
.step[data-complete] { color: var(--text-secondary); }
.step[data-complete] .step-mark { border-color: var(--success-line); color: var(--success-dim); background: var(--success-wash); }
.step-sep { width: 22px; height: 1px; background: var(--border); }

/* Charts ---------------------------------------------------------------
   Ordered categorical ramp. Brass sits first because in this app the
   highlighted series is the one the viewer came for. */
:root {
  --chart-1: #B08D57;
  --chart-2: #4C78A8;
  --chart-3: #4F8A63;
  --chart-4: #7FA5CC;
  --chart-5: #C69243;
  --chart-6: #6E8299;
  --chart-grid: #202833;
  --chart-axis: #758293;
}

/* Empty state ----------------------------------------------------------- */
.empty {
  text-align: center;
  padding: var(--sp-7) var(--sp-5);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}


/* ==========================================================================
   LAYER 3 — ripmanager  (project-specific)
   --------------------------------------------------------------------------
   Two systems so far: connection-check results, and configuration state.
   The discrepancy chips arrive with build step 8.

   Four outcomes, three colors. A check that did not run is deliberately not
   given a color of its own — it is muted, like an absent value, because
   nothing was learned and a red mark would claim a failure that was never
   observed.

     pass     success  solid     ran, succeeded
     fail     error    solid     ran, failed
     warn     warning  outline   ran, succeeded, worth a second look
     skip     muted              did not run; an earlier check failed
   ========================================================================== */

.chip {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-xs);
  font-weight: 550;
  letter-spacing: 0.01em;
  line-height: 1;
  padding: 4px 11px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  white-space: nowrap;
}

.chip--pass { color: var(--bg);          border-color: var(--success);   background: var(--success); }
.chip--fail { color: var(--bg);          border-color: var(--error);     background: var(--error); }
.chip--warn { color: var(--warning-dim); border-color: var(--warning-line); background: var(--warning-wash); }
.chip--skip { color: var(--text-secondary); border-color: var(--border);  background: var(--surface); }

/* One check in a results list. The mark is fixed-width so a column of them
   lines up regardless of how long each label runs. */
.check {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: var(--sp-3);
  align-items: start;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--border);
}
.check:last-child { border-bottom: none; }
.check-mark { font-size: var(--fs-md); line-height: 1.3; }
.check-mark--pass { color: var(--success-dim); }
.check-mark--fail { color: var(--error-dim); }
.check-mark--skip { color: var(--text-muted); }
.check-label { font-weight: 550; }
.check-detail {
  margin-top: 2px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}
/* A remedy is a command or an instruction. It gets the brass rule because it
   is the one line in a failed check the reader is looking for. */
.check-remedy {
  margin-top: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-left: 2px solid var(--accent);
  background: var(--accent-wash);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}
.check-remedy code { font-family: var(--font-mono); font-size: var(--fs-xs); }

/* A storage backend and the servers on it. The count is the load-bearing
   number — it is what says whether a comparison has three sides or four —
   so it is set larger than the name beside it. */
.backend { display: flex; align-items: baseline; gap: var(--sp-3); }
.backend-count {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--text);
}
.backend-shared {
  font-size: var(--fs-xs);
  letter-spacing: var(--eyebrow-track);
  text-transform: uppercase;
  color: var(--accent);
}

/* Storage comparison. Three outcomes and they are not shades of one thing:
   a backend that has it, one that does not, and one that could not look.
   The third gets its own treatment because copying to it would overwrite
   content that is already there. */
.chip--have { color: var(--success-dim);  border-color: var(--success-line); background: var(--success-wash); }
.chip--need { color: var(--bg);           border-color: var(--error);        background: var(--error); }
.chip--perm { color: var(--warning-dim);  border-color: var(--warning-line); background: var(--warning-wash); }

/* The replication master. Brass, because it is the one designation on the
   page that changes what every remedy says. */
.chip--master {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-wash);
  letter-spacing: var(--eyebrow-track);
  text-transform: uppercase;
  font-size: 10px;
}

/* A group of findings under one title. The title is what the operator
   recognizes; the paths beneath it are how they act. */
.title-group { border-bottom: 1px solid var(--border); padding: var(--sp-3) 0; }
.title-group:last-child { border-bottom: none; }
.title-name { font-weight: 600; }
.title-rows { margin-top: var(--sp-2); }
.finding {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-3);
  align-items: baseline;
  padding: 3px 0 3px var(--sp-4);
}
.finding-path {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  overflow-wrap: anywhere;
}

/* A running job. Flat and quiet: a transfer can run for hours and a bar that
   demands attention for that long is a bar you stop seeing. */
.progress {
  height: 4px;
  border-radius: 2px;
  background: var(--surface-elevated);
  overflow: hidden;
}
.progress-bar {
  height: 100%;
  background: var(--info);
  transition: width var(--transition);
}

/* Mirror freshness. Shown everywhere a comparison result is, so that reading
   a stale answer is a deliberate act rather than an accident. */
.freshness { font-size: var(--fs-xs); color: var(--text-muted); }
.freshness--stale { color: var(--warning-dim); }
.freshness--never { color: var(--error-dim); }
