/* ---------- settings / keys ---------- */

/* The user Settings area (settings-sidebar pass, 2026-08-09): Keys /
   Access tokens / Petnames are sections of one /settings area —
   sidebar nav on the left, section content beside it. Active paint
   mirrors .subtabs a.active. At the site's 720px breakpoint the nav
   wraps into a horizontal row above the content and the group
   headings hide. */
.settings-page { display: flex; align-items: flex-start; gap: 2.5rem; max-width: 60rem; }
.settings-nav {
  flex: 0 0 10.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  position: sticky;
  top: 1rem;
}
.settings-nav a { padding: 0.3rem 0.6rem; border-radius: var(--radius-ctl); color: var(--fg); font-size: 0.95rem; }
.settings-nav a:hover { background: var(--bg-inset); text-decoration: none; }
.settings-nav a.active { background: var(--accent-wash); color: var(--accent-emph); font-weight: 600; }
.settings-nav-group {
  margin: 1rem 0 0.35rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fg-muted);
}
.settings-nav-group:first-child { margin-top: 0; }
.settings-content { flex: 1; min-width: 0; }
.settings-content h1 { margin-top: 0; }
@media (max-width: 720px) {
  .settings-page { flex-direction: column; gap: 1.25rem; }
  /* flex: none — the desktop 10.5rem flex-basis would become HEIGHT
     once .settings-page turns into a column. */
  .settings-nav { position: static; flex: none; flex-direction: row; flex-wrap: wrap; gap: 0.25rem; width: 100%; }
  .settings-nav-group { display: none; }
}

.settings-slot, .settings { margin-top: 1.5rem; }
/* Repo Settings sections (repo-settings-sidebar pass, 2026-08-09):
   the tab reuses the account-settings sidebar layout; inside
   .repo-body the page-level top margin comes from the wrapper, not
   the .settings content box. */
.repo-body .settings-page { margin-top: 1.5rem; }
.repo-body .settings-page .settings { margin-top: 0; }
/* .settings is a flex item, so a first child's own margin-top doesn't
   collapse into it — it becomes visible internal space that differs
   per section (dl/form/h3/h2 all carry different UA/rule margins),
   making the content column jump as you click through the sidebar
   (finding 2, repo-settings-sidebar final review). Zero it on both
   the plaintext template's direct children and the E2EE client's
   per-section [data-section] wrapper divs. */
.repo-body .settings-page .settings > :first-child,
.repo-body .settings-page .settings > [data-section] > :first-child { margin-top: 0; }
.settings-facts { display: grid; grid-template-columns: auto 1fr; gap: 0.4rem 1.5rem; margin: 1.25rem 0 0.5rem; max-width: 40rem; }
.settings-facts dt { color: var(--fg-muted); font-size: 0.9rem; }
.settings-facts dd { margin: 0; }
.settings-facts .badge { margin-left: 0; }
.settings ul.members { list-style: none; padding: 0; }
.settings pre, .key-status pre {
  background: var(--code-bg);
  border: 1px solid var(--border);
  padding: 0.75rem;
  border-radius: var(--radius-ctl);
  overflow-x: auto;
  font-size: 0.85rem;
}
.muted { color: var(--fg-muted); font-size: 0.9rem; }

.explainer {
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.5rem;
  max-width: 40rem;
  color: var(--fg-muted);
}
/* The E2EE repo's locked state is the only thing on an otherwise wide
   page (the unlocked browse grid needs the full width, so the page
   can't be .narrow) — center the card so the emptiness reads as
   sealed-on-purpose, not as a stranded column. */
#app .explainer { margin: 3rem auto; }

.key-status dl { display: grid; grid-template-columns: auto 1fr; gap: 0.25rem 1rem; }
.key-status dt { color: var(--fg-muted); }
.key-status dd { margin: 0; word-break: break-all; font-family: var(--mono); font-size: 0.85rem; }
.key-import form { display: flex; flex-direction: column; gap: 0.5rem; max-width: 40rem; margin-top: 1.5rem; }
.key-import textarea { font-family: var(--mono); font-size: 0.85rem; }
.message { min-height: 1.2em; }

/* ---------- states ---------- */

/* Hidden for the first 500ms: on a fast load the page must paint
   nothing where the decrypted content will land — the instant
   "Loading…" line read as a flash of an error page. The 0s-duration
   delayed animation flips visibility on only when a load is actually
   slow; the pulse waits out the same delay. */
.loading {
  color: var(--fg-muted);
  visibility: hidden;
  animation: loading-appear 0s 0.5s forwards, loading-pulse 1.2s 0.5s ease-in-out infinite alternate;
}
@keyframes loading-appear { to { visibility: visible; } }
@keyframes loading-pulse { from { opacity: 1; } to { opacity: 0.45; } }

/* ---------- error page ---------- */

.error-page { max-width: 44rem; padding-top: 4rem; }
.error-page .status {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(3rem, 10vw, 5rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--accent);
  margin: 0 0 0.75rem;
}
.error-page p { font-size: 1.05rem; }

