/* Shared components. Linked after tokens.css and before any page sheet, so a
 * page can still override a component but never has to redefine one.
 *
 * A selector defined here is defined nowhere else -- that is the rule
 * tests/test_stylesheet.py enforces, and it is the permanent replacement for
 * "keep these in sync by hand" comments.
 */

/* Full-screen modal backdrop.
 *
 * Had five definitions. Three were identical (import_instances, rescue_images,
 * workers/workspace), dirty_harry carried a stripped-down base under its own
 * .dirty-harry-overlay modifier, and the source-cloud auth partial disagreed:
 * centered rather than top-anchored, a darker backdrop, and z-index 80.
 * import.html and workers/workspace.html include both families, so which one
 * rendered was decided by include order -- undocumented and load-bearing.
 *
 * The page variant wins. It is the majority, it is already what operators see
 * on import and workers, flex-start plus overflow:auto handles a form taller
 * than the viewport, and z-55 slots into the existing scale (wizard 40,
 * picker 50, log and form 55, help 58-61). The partial's z-80 wrongly stacked
 * its modal above the help overlay system.
 */
.form-overlay {
  position: fixed;
  inset: 0;
  background: rgba(14, 11, 12, 0.38);
  display: none;
  align-items: flex-start;
  justify-content: center;
  overflow: auto;
  padding: 40px 24px;
  z-index: 55;
}

/* Both activation classes, deliberately. The import and workers scripts toggle
 * .open; the source-cloud auth partial toggles .active. Honouring only one
 * would silently break every modal in the other family, which is the most
 * likely functional break in this phase -- so no classList call anywhere has
 * to change.
 */
.form-overlay.open,
.form-overlay.active {
  display: flex;
}

/* Buttons.
 *
 * .btn is worn by both <button> and <a> elements. base.css styles the bare
 * `button` element, which is why login, the migration cards and the migrate
 * toolbar each grew their own .btn -- an anchor gets nothing from a `button`
 * rule. Geometry here is base's, so a <button class="btn"> looks the same
 * either way.
 *
 * The focus ring is the point. A `button:focus-visible` rule cannot match
 * <a class="btn">, so every anchor-styled button on the site was keyboard-
 * invisible: you could tab to it with no indication of where you were. That
 * is the accessibility bug the plan describes, though not quite where it
 * looked -- operator_app.css and run.css do have their own button
 * :focus-visible rules, so the gap is anchors, not those pages.
 *
 * The two scoped variants (.migration-actions .btn, .workspace-toolbar .btn)
 * are deliberately different geometry and outrank this on specificity; they
 * keep their looks and gain the ring, because they set no focus properties of
 * their own.
 */
.btn {
  display: inline-block;
  appearance: none;
  cursor: pointer;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--body);
  padding: 7px 14px;
  font-family:
    Inter,
    system-ui,
    -apple-system,
    sans-serif;
  font-size: 12.5px;
  font-weight: 500;
  text-decoration: none;
  transition: background 100ms ease;
}

.btn:hover {
  background: var(--surface-2);
}

.btn.primary {
  background: var(--red);
  border-color: var(--red);
  color: #fff;
}

.btn.primary:hover {
  background: var(--red-dark);
}

.btn:disabled {
  cursor: not-allowed;
  opacity: 0.52;
}

.btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px rgba(207, 21, 66, 0.35);
}

/* Status chip.
 *
 * Conservative on purpose: only the byte-identical pair (the conversion
 * workspace and the migrations board) merges here, with its token-named
 * modifiers. The three other geometries -- rescue_images, import and
 * object_migrate, which are smaller, uppercase and letter-spaced -- stay on
 * their pages and win on load order, because unifying them would be a visual
 * change dressed as a refactor. They migrate opportunistically, when someone
 * is in that file anyway.
 *
 * Modifiers are named for tokens (.green/.amber/.red/.blue), not for meanings
 * (.chip-warn), so a chip's colour and the token it comes from cannot drift
 * apart.
 */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 500;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--gray-soft);
  color: var(--dim);
  white-space: nowrap;
}

.chip.green {
  background: var(--green-soft);
  color: var(--green);
}

.chip.amber {
  background: var(--amber-soft);
  color: var(--amber);
}

.chip.red {
  background: var(--red-soft);
  color: var(--red-dark);
}

.chip.blue {
  background: var(--blue-soft);
  color: var(--blue);
}

/* Dense table header.
 *
 * Three copies (the conversion workspace, the migrations board and
 * migration plans) become one, opted into by class. The plan expected to add a .table-dense
 * class to three tables' markup; no markup change is needed, because all three
 * already share .tbl -- so this is a pure deletion and DOM classes are
 * untouched.
 *
 * The selector is .table-dense, not .tbl, and that matters. Consolidating on
 * .tbl leaked the dense header into migration_plans' modal tables, which wear
 * .tbl but were never meant to be dense -- the page had scoped its copy to
 * .migration-content precisely to avoid that. The visual baseline caught it.
 * An explicit opt-in class cannot leak.
 *
 * base.css's `th` stays canonical for everything else; this differs from it
 * only in padding (9px vs 10px) and nowrap. The JetBrains Mono headers on the
 * run console and the migrate inline table are deliberately their own and are
 * left alone.
 */
.table-dense th {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--dim);
  text-align: left;
  padding: 9px 16px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

/* Site chrome: the black bar every page wears.
 *
 * Lived in base.css and was hand-copied into the two help pages, and the run
 * console reinvented it under .app-header/.logo at a different height with a
 * different border. It is a component, so it lives here and every page --
 * including Family B, which never linked base.css -- gets the same one.
 */

.topbar {
  height: 48px;
  background: var(--ink);
  color: #fff;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 0 24px;
  border-bottom: 3px solid var(--red);
  font-size: 12px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.brand .mark {
  width: 7px;
  height: 20px;
  background: var(--red);
  border-radius: 1px;
}

.brand .name {
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.brand .sub {
  font-size: 11px;
  color: #9b938e;
  padding-left: 12px;
  border-left: 1px solid #3a3335;
}

.topbar .context {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 18px;
  font-size: 12px;
  color: #c9c2bd;
}

.topbar .context a {
  color: #c9c2bd;
  text-decoration: none;
}

.topbar .context a:hover {
  color: #fff;
}

.topbar .context b {
  color: #fff;
  font-weight: 600;
}

.topbar .context .sep {
  color: #4a4346;
}

.topbar .context button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid #4a4346;
  border-radius: var(--radius-sm);
  color: #c9c2bd;
  font-family:
    Inter,
    system-ui,
    -apple-system,
    sans-serif;
  padding: 5px 12px;
  font-size: 12px;
  cursor: pointer;
}

.topbar .context button:hover {
  color: #fff;
  border-color: #9b938e;
  background: transparent;
}
