/* ============================================================================
   CourseForge – component styles.
   ========================================================================== */

/* -- buttons --------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--t-sm);
  font-weight: 530;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--speed) var(--ease), border-color var(--speed) var(--ease),
              color var(--speed) var(--ease), transform var(--speed) var(--ease);
}
.btn:hover:not(:disabled) { background: var(--surface-hover); border-color: var(--border-strong); }
.btn:active:not(:disabled) { transform: translateY(1px); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

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

.btn--success {
  background: var(--success);
  border-color: var(--success);
  color: var(--success-ink);
  font-weight: 600;
}
.btn--success:hover:not(:disabled) { filter: brightness(1.07); }

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

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

.btn--sm { padding: 4px 9px; font-size: var(--t-xs); gap: 5px; }
.btn--icon { padding: 6px; }
.btn--icon.btn--sm { padding: 4px; }
.btn--block { width: 100%; }
.btn--pill { border-radius: var(--r-pill); }

.btn-group { display: inline-flex; border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden; }
.btn-group > button {
  padding: 5px 11px;
  border: 0;
  border-left: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--t-xs);
  font-weight: 530;
  cursor: pointer;
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
}
.btn-group > button:first-child { border-left: 0; }
.btn-group > button:hover { background: var(--surface-hover); color: var(--text); }
.btn-group > button.is-active { background: var(--accent); color: var(--accent-ink); }

/* -- cards ----------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
}
.card--flat { background: var(--surface-2); }
.card--pad { padding: var(--s-5); }
.card__head {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  border-bottom: 1px solid var(--border-soft);
}
.card__title { font-size: var(--t-md); font-weight: 600; }
.card__body { padding: var(--s-5); }
.card__foot { padding: var(--s-4) var(--s-5); border-top: 1px solid var(--border-soft); }

.card--action {
  cursor: pointer;
  text-align: left;
  width: 100%;
  transition: border-color var(--speed) var(--ease), background var(--speed) var(--ease), transform var(--speed) var(--ease);
}
.card--action:hover { border-color: var(--accent-line); background: var(--surface-2); }

/* -- section header inside panes ------------------------------------------- */
.section {
  border-bottom: 1px solid var(--border-soft);
}
.section:last-child { border-bottom: 0; }
.section__head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 100%;
  padding: var(--s-3) var(--s-4);
  border: 0;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.section__head:hover { background: var(--surface-hover); }
.section__body { padding: 0 var(--s-4) var(--s-4); }
.section__chevron { color: var(--text-faint); transition: transform var(--speed) var(--ease); }
.section.is-open .section__chevron { transform: rotate(90deg); }

/* -- form field groups ----------------------------------------------------- */
.form-row { display: flex; flex-direction: column; gap: 5px; }
.form-row > label,
.label {
  font-size: var(--t-xs);
  font-weight: 560;
  color: var(--text-muted);
}
.hint { font-size: var(--t-xs); color: var(--text-dim); line-height: 1.5; }
.check { display: flex; align-items: flex-start; gap: var(--s-2); font-size: var(--t-sm); cursor: pointer; }
.check input { margin-top: 2px; }

/* -- badges and chips ------------------------------------------------------ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  color: var(--text-muted);
  font-size: var(--t-2xs);
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.badge--accent  { background: var(--accent-soft);  color: var(--accent); }
.badge--success { background: var(--success-soft); color: var(--success); }
.badge--warning { background: var(--warning-soft); color: var(--warning); }
.badge--danger  { background: var(--danger-soft);  color: var(--danger); }
.badge--magic   { background: var(--magic-soft);   color: var(--magic); }
.badge--outline { background: transparent; border: 1px dashed var(--border-strong); color: var(--text-dim); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  padding: 3px 5px 3px 9px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--t-xs);
  line-height: 1.35;
}
.chip--magic { background: var(--magic-soft); color: var(--magic); }

/* A row of chips used as a picker rather than as labels: quiet until chosen,
   so the row reads as one control with one answer. Padding is even, because
   nothing follows the text - the label chips leave room for a button. */
button.chip {
  padding-inline: 9px;
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--text-dim);
  cursor: pointer;
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
}
button.chip:hover { color: var(--text); }
button.chip.chip--on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
button.chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chip--off { background: var(--neutral-soft); color: var(--text-faint); text-decoration: line-through; }
.chip--inherited { background: transparent; border: 1px dashed var(--border-strong); color: var(--text-dim); padding-right: 9px; }
.chip__value { opacity: 0.72; }
.chip__btn {
  display: grid;
  place-items: center;
  padding: 2px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: inherit;
  opacity: 0.6;
  cursor: pointer;
  transition: opacity var(--speed) var(--ease), background var(--speed) var(--ease);
}
.chip__btn:hover { opacity: 1; background: rgb(255 255 255 / 12%); }
.chip__btn:disabled { opacity: 0.3; cursor: not-allowed; }
.chip__btn--danger:hover { color: var(--danger); }

/* -- status dot ------------------------------------------------------------ */
.dot {
  width: 8px;
  height: 8px;
  flex: none;
  border-radius: var(--r-pill);
  background: var(--text-faint);
}
.dot--pending    { background: var(--border-strong); }
.dot--generating { background: var(--warning); animation: cf-pulse 1.1s ease-in-out infinite; }
/* Queued in a provider batch: waiting, but not this minute - so it breathes
   far more slowly than a page being written right now. */
.dot--queued     { background: var(--magic); animation: cf-pulse 3.2s ease-in-out infinite; }
.dot--generated  { background: var(--accent); }
.dot--dirty      { background: var(--warning); }
.dot--pushed     { background: var(--success); }
.dot--error      { background: var(--danger); }

/* -- progress -------------------------------------------------------------- */
.bar {
  height: 5px;
  width: 100%;
  overflow: hidden;
  border-radius: var(--r-pill);
  background: var(--surface-3);
}
.bar__fill {
  height: 100%;
  border-radius: var(--r-pill);
  background: var(--accent);
  transition: width 220ms var(--ease);
}
.bar__fill--success { background: var(--success); }

/* -- tri-state toggle ------------------------------------------------------ */
.tri {
  display: inline-grid;
  grid-template-columns: repeat(3, 1fr);
  flex: none;
  width: 124px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.tri__opt {
  padding: 3px 4px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-dim);
  font-size: var(--t-2xs);
  font-weight: 620;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
}
.tri__opt:hover:not(:disabled) { color: var(--text); }
.tri__opt:disabled { cursor: not-allowed; opacity: 0.5; }
.tri__opt.is-on  { background: var(--success); color: var(--success-ink); }
.tri__opt.is-off { background: var(--danger); color: var(--danger-ink); }
.tri__opt.is-inherit { background: var(--surface-hover); color: var(--text); }

/* -- detail rows ----------------------------------------------------------- */
.detail-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: 9px var(--s-3);
  border-radius: var(--r-md);
  transition: background var(--speed) var(--ease);
}
.detail-row:hover { background: var(--surface-2); }
.detail-row__icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: none;
  border-radius: var(--r-sm);
  background: var(--surface-3);
  color: var(--text-dim);
}
.detail-row.is-on .detail-row__icon { background: var(--success-soft); color: var(--success); }
.detail-row.is-off .detail-row__icon { background: var(--neutral-soft); color: var(--text-faint); }
.detail-row__text { min-width: 0; flex: 1 1 auto; }
.detail-row__label { font-size: var(--t-sm); font-weight: 520; line-height: 1.3; }
.detail-row__note { font-size: var(--t-2xs); color: var(--text-dim); line-height: 1.4; }

.param-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 156px;
  align-items: center;
  gap: var(--s-3);
  padding: 8px var(--s-3);
  border-radius: var(--r-md);
}
.param-row:hover { background: var(--surface-2); }

/* The two lists of a detail editor - elements, values - side by side where
   there is room for both to keep their labels whole, and one under the other
   where there is not: a profile's pane and a phone are both narrower than the
   Details tab of a course. `min(100%, 380px)` is what stops the minimum from
   forcing a horizontal scroll on a screen narrower than the minimum itself. */
.detail-grid {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));
}
.detail-grid--one { grid-template-columns: minmax(0, 1fr); }

/* A value row that carries the same tile as an element row, so the two lists
   line up and a value can be told from the next by its glyph. */
.param-row--iconed { grid-template-columns: 28px minmax(0, 1fr) 156px; }
.param-row.is-changed .detail-row__icon,
.detail-row.is-changed .detail-row__icon { background: var(--accent-soft); color: var(--accent); }

/* The two levels of a detail row that has decided something: a rule down the
   left that the Settings screen draws for a changed setting, borrowed here so
   a level that stores an override is marked the same way everywhere. */
.detail-row.is-own, .param-row.is-own { box-shadow: inset 2px 0 0 var(--accent); }
.param-input { position: relative; display: flex; align-items: center; gap: 4px; }
.param-input input { min-width: 0; text-align: right; padding-inline: 6px; }
.param-input__unit { font-size: var(--t-2xs); color: var(--text-faint); width: 42px; flex: none; }

/* -- outline tree ---------------------------------------------------------- */
.tree { padding: var(--s-2); }
.tree__chapter { margin-bottom: var(--s-2); }
.tree__chapter-head {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 5px 7px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  text-align: left;
}
.tree__chapter-head:hover { background: var(--surface-hover); color: var(--text); }
.tree__chapter-head.is-active { background: var(--accent-soft); color: var(--accent); }
.tree__chapter-title {
  font-size: var(--t-2xs);
  font-weight: 680;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tree__page {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  padding: 5px 8px 5px 10px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--t-sm);
  cursor: pointer;
  text-align: left;
}
.tree__page:hover { background: var(--surface-hover); color: var(--text); }
.tree__page.is-active { background: var(--accent-soft); color: var(--accent); font-weight: 550; }
.tree__page-idx { font-size: var(--t-2xs); color: var(--text-faint); width: 18px; flex: none; text-align: right; font-variant-numeric: tabular-nums; }

/* -- tables ---------------------------------------------------------------- */
.table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.table th {
  padding: 9px var(--s-4);
  text-align: left;
  font-size: var(--t-2xs);
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-dim);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.table td { padding: 8px var(--s-4); border-bottom: 1px solid var(--border-soft); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr:hover { background: var(--surface-2); }
.table__num { text-align: right; font-variant-numeric: tabular-nums; }

/* -- popover / combo box --------------------------------------------------- */
.popover {
  position: absolute;
  z-index: var(--z-popover);
  top: calc(100% + 4px);
  left: 0;
  width: 100%;
  max-height: 260px;
  overflow-y: auto;
  padding: 4px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  animation: cf-rise 110ms var(--ease);
}
.popover__item {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 100%;
  padding: 6px 9px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--t-sm);
  cursor: pointer;
  text-align: left;
}
.popover__item:hover, .popover__item.is-active { background: var(--accent-soft); color: var(--accent); }
.popover__empty { padding: var(--s-3); font-size: var(--t-xs); color: var(--text-faint); text-align: center; }

/* -- modal ----------------------------------------------------------------- */
.modal-scrim {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--s-4);
  background: var(--overlay);
  backdrop-filter: blur(3px);
  animation: cf-fade 120ms var(--ease);
}
.modal {
  width: 100%;
  max-width: 440px;
  max-height: 90vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  animation: cf-rise 140ms var(--ease);
}
.modal--wide { max-width: 720px; }
.modal__head { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-5) var(--s-5) 0; }
.modal__body { padding: var(--s-4) var(--s-5); }
.modal__foot { display: flex; justify-content: flex-end; gap: var(--s-2); padding: 0 var(--s-5) var(--s-5); }

/* -- toasts ---------------------------------------------------------------- */
.toasts {
  position: fixed;
  right: var(--s-5);
  bottom: var(--s-5);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  width: min(380px, calc(100vw - var(--s-8)));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  font-size: var(--t-sm);
  pointer-events: auto;
  animation: cf-rise 160ms var(--ease);
}
.toast--success { border-color: var(--success-line); }
.toast--error   { border-color: var(--danger-line); }
.toast--info    { border-color: var(--accent-line); }
.toast__icon { flex: none; margin-top: 1px; }
.toast--success .toast__icon { color: var(--success); }
.toast--error   .toast__icon { color: var(--danger); }
.toast--info    .toast__icon { color: var(--accent); }
.toast__text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }

/* -- misc ------------------------------------------------------------------ */
.empty {
  display: grid;
  place-items: center;
  gap: var(--s-3);
  padding: var(--s-12) var(--s-6);
  text-align: center;
  color: var(--text-dim);
}
.empty__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--r-lg);
  background: var(--surface-2);
  color: var(--text-faint);
}
.empty__title { font-size: var(--t-md); font-weight: 600; color: var(--text-muted); }

.stat {
  padding: var(--s-3);
  border-radius: var(--r-md);
  background: var(--surface-2);
  text-align: center;
}
.stat__value { font-size: var(--t-xl); font-weight: 650; font-variant-numeric: tabular-nums; line-height: 1.2; }
.stat__label { font-size: var(--t-2xs); color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.06em; }

.log {
  max-height: 460px;
  overflow-y: auto;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  background: var(--bg);
  border: 1px solid var(--border-soft);
  font-family: var(--mono);
  font-size: var(--t-xs);
  line-height: 1.8;
  color: var(--text-muted);
}
.log__line { overflow-wrap: anywhere; }
.log__line--new { color: var(--success); }
.log__line--warn { color: var(--warning); }
.log__line--error { color: var(--danger); }

/* -- one BookStack destination on the Publish tab ----------------------------
   A card per wiki, with its facts, its outcome and its own buttons. A wiki
   that is switched off fades, so a course with four destinations and one on
   reads at a glance. */
.destination { transition: opacity var(--speed) var(--ease), border-color var(--speed) var(--ease); }
.destination.is-off { opacity: 0.6; }
.destination.is-off .card__body { display: none; }
.destination .card__title { min-width: 0; }

/* -- the publish log ---------------------------------------------------------
   One entry per task: a head with its state and the wikis it covers, and the
   lines it said underneath. The left rule takes the task's colour, so a
   failed push can be found in a column of successes. */
.task-log { max-height: 70vh; overflow-y: auto; overscroll-behavior: contain; padding-right: 2px; }
.task-entry {
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.task-entry--running, .task-entry--queued { border-left-color: var(--accent); }
.task-entry--done { border-left-color: var(--success); }
.task-entry--failed { border-left-color: var(--danger); }
.task-entry--canceled { border-left-color: var(--warning); }
.task-entry__head {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-3) var(--s-2);
}
.task-entry__icon { margin-top: 3px; flex: none; color: var(--text-dim); }
.task-entry--running .task-entry__icon { color: var(--accent); }
.task-entry--done .task-entry__icon { color: var(--success); }
.task-entry--failed .task-entry__icon { color: var(--danger); }
.task-entry__lines { max-height: 320px; border-radius: 0 0 var(--r-md) 0; border-width: 1px 0 0 0; }
.log__wiki {
  display: inline-block;
  margin-right: 6px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  color: var(--text-dim);
  font-size: var(--t-2xs);
  font-family: var(--font);
  vertical-align: 1px;
}
.log__line--done { color: var(--success); font-weight: 600; }
.log__line--links { color: var(--accent); }

/* -- a field that holds a secret, while secrets are locked -------------------
   The box is greyed out and framed in red, and the mark beside it is the
   button that explains why. `position: relative` on the field so the mark
   sits inside the box's right edge whatever the field is. */
.secret-field { position: relative; }
.secret-field.is-locked > input {
  padding-right: 34px;
  border-color: var(--danger-line);
  background: var(--danger-soft);
  opacity: 0.7;
}
.secret-lock {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--danger);
  cursor: pointer;
  animation: cf-pulse 2.4s ease-in-out infinite;
}
.secret-lock:hover { background: var(--danger-soft); animation: none; }
.row > .secret-lock { position: static; transform: none; }

/* The banner at the top of every screen while secrets are locked. */
.security-banner {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex: none;
  padding: var(--s-3) var(--s-5);
  background: var(--danger-soft);
  border-bottom: 1px solid var(--danger-line);
  color: var(--text);
  font-size: var(--t-sm);
}
.security-banner > .icon { color: var(--danger); }
@media (max-width: 640px) { .security-banner { padding-inline: var(--s-3); font-size: var(--t-xs); } }

.kbd {
  padding: 1px 5px;
  border: 1px solid var(--border-strong);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  background: var(--surface-2);
  font-family: var(--mono);
  font-size: var(--t-2xs);
  color: var(--text-muted);
}

.divider { height: 1px; background: var(--border-soft); }

.spin { animation: cf-spin 0.8s linear infinite; }

.placeholder-token {
  padding: 1px 6px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--t-2xs);
  cursor: pointer;
}
.placeholder-token:hover { background: var(--accent-line); }

/* -- icon tiles --------------------------------------------------------------
   A glyph on a soft square, so a section, a setting or a navigation entry can
   be told apart at a glance before its label is read. The tone says what kind
   of thing it is - accent for the ordinary, success for the healthy, warning
   for the thing to look at, danger for the destructive, magic for the AI. */
.tile {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: var(--r-md);
  background: var(--surface-3);
  color: var(--text-muted);
}
.tile--sm { width: 26px; height: 26px; border-radius: var(--r-sm); }
.tile--lg { width: 42px; height: 42px; border-radius: var(--r-lg); }
.tile--accent  { background: var(--accent-soft);  color: var(--accent); }
.tile--success { background: var(--success-soft); color: var(--success); }
.tile--warning { background: var(--warning-soft); color: var(--warning); }
.tile--danger  { background: var(--danger-soft);  color: var(--danger); }
.tile--magic   { background: var(--magic-soft);   color: var(--magic); }
.tile--brand {
  background: linear-gradient(140deg, var(--accent), var(--accent-strong));
  color: var(--accent-ink);
}

/* A card head that opens with a tile: the title and, under it, one line on
   what the card is for, so the card explains itself before it is read. */
.card__heading { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.card__desc { font-size: var(--t-xs); color: var(--text-dim); line-height: 1.45; }

/* -- switch ----------------------------------------------------------------
   A two-state control that reads as one: on is filled, off is hollow, and the
   knob moves. `role="switch"` with `aria-checked` is what a screen reader
   announces it as, and the state is carried on that attribute rather than on a
   class so the two can never disagree. */
.switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: none;
  width: 38px;
  height: 22px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--surface-3);
  cursor: pointer;
  transition: background var(--speed) var(--ease), border-color var(--speed) var(--ease);
}
.switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: var(--r-pill);
  background: var(--text-muted);
  transition: transform var(--speed) var(--ease), background var(--speed) var(--ease);
}
.switch:hover:not(:disabled) { border-color: var(--accent); }
.switch[aria-checked="true"] { background: var(--accent); border-color: var(--accent); }
.switch[aria-checked="true"]::after { transform: translateX(16px); background: var(--accent-ink); }
.switch--success[aria-checked="true"] { background: var(--success); border-color: var(--success); }
.switch--success[aria-checked="true"]::after { background: var(--success-ink); }
.switch:disabled { opacity: 0.5; cursor: not-allowed; }

/* A switch with its words: the label to the left, the control to the right,
   the whole row clickable. */
.switch-row {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  width: 100%;
  padding: 9px var(--s-3);
  border: 0;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  transition: background var(--speed) var(--ease);
}
.switch-row:hover { background: var(--surface-2); }

/* -- a text field with a glyph in it ---------------------------------------
   Search boxes, mostly. The glyph says what the box is for without a label
   taking a line of its own. */
.input-icon { position: relative; min-width: 0; }
.input-icon > .icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-faint);
  pointer-events: none;
}
/* The same deny-list base.css selects text fields by, so this outranks the
   padding it sets there - a plain `.input-icon > input` would lose to it. */
.input-icon > input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="color"]) {
  padding-left: 32px;
}

/* -- the legend under a control ---------------------------------------------
   Three states of the tri-toggle, or the four colours of a tag chip, named in
   words next to a swatch of what they look like. */
.legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); font-size: var(--t-xs); color: var(--text-dim); }
.legend__item { display: inline-flex; align-items: center; gap: 6px; }
.legend__swatch {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: var(--r-xs);
  font-size: var(--t-2xs);
  font-weight: 700;
}
.legend__swatch--on { background: var(--success); color: var(--success-ink); }
.legend__swatch--off { background: var(--danger); color: var(--danger-ink); }
.legend__swatch--inherit { background: var(--surface-hover); color: var(--text); border: 1px solid var(--border-strong); }

/* -- facts -------------------------------------------------------------------
   A row of labelled numbers or words, each with its glyph: what a course is
   made of, when it was created, where it publishes. */
.facts { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--s-2); }
.fact {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.fact__text { min-width: 0; }
.fact__label { font-size: var(--t-2xs); color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.06em; }
.fact__value { font-size: var(--t-sm); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* -- the steps a thing is done in --------------------------------------------
   Numbered, each with a glyph, read left to right. On the empty course list it
   is the whole story of the application in one strip. */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: var(--s-3); }
.step {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-4);
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--surface-2);
  text-align: left;
}
.step__num { font-size: var(--t-2xs); font-weight: 700; letter-spacing: 0.08em; color: var(--text-faint); }
.step__title { font-size: var(--t-sm); font-weight: 600; }
.step__text { font-size: var(--t-xs); color: var(--text-dim); line-height: 1.5; }

/* -- a strip that tells you which layer you are on --------------------------
   The same shape the prompt screens use, generalised: an accent wash under a
   sentence that frames everything below it. */
.note-strip {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-md);
  background: var(--accent-soft);
  color: var(--text-muted);
  font-size: var(--t-xs);
  line-height: 1.55;
}
.note-strip--warning { border-color: var(--warning-line); background: var(--warning-soft); }
.note-strip--success { border-color: var(--success-line); background: var(--success-soft); }
.note-strip--danger { border-color: var(--danger-line); background: var(--danger-soft); }
.note-strip > .icon { flex: none; margin-top: 1px; }

/* -- avatar ------------------------------------------------------------------
   Initials on a disc, for the account entry in the sidebar and the header of
   the account dialog. */
.avatar {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.avatar--lg { width: 42px; height: 42px; font-size: var(--t-md); }

/* -- the tri-toggle's inherit glyph ---------------------------------------- */
.tri__opt { display: inline-flex; align-items: center; justify-content: center; gap: 3px; }

/* -- tabs and navigation carry their glyphs a step quieter than the words --- */
.tab > .icon { color: var(--text-faint); transition: color var(--speed) var(--ease); }
.tab:hover > .icon, .tab.is-active > .icon { color: currentColor; }
.tab[aria-selected="true"] { color: var(--accent); }
.tab[aria-selected="true"]::after { background: var(--accent); }

/* A tab count, drawn as a pill so it never looks like part of the label. */
.tab__count {
  padding: 1px 7px;
  border-radius: var(--r-pill);
  background: var(--neutral-soft);
  color: var(--text-dim);
  font-size: var(--t-2xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tab.is-active .tab__count, .tab[aria-selected="true"] .tab__count { background: var(--accent-soft); color: var(--accent); }

/* -- a button group that is a set of tabs inside a pane -------------------- */
.btn-group > button { display: inline-flex; align-items: center; justify-content: center; gap: 5px; }
.btn-group > button > .icon { color: var(--text-faint); }
.btn-group > button.is-active > .icon { color: currentColor; }

/* -- feature cards (BookStackDev) --------------------------------------------
   One card per feature of a look: a tile, a title, one line on what it does,
   and the switch that turns it on - with its options underneath only while it
   is on, so a look with three features off is three quiet rows. */
.look-grid {
  display: grid;
  gap: var(--s-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
  align-items: start;
}
.look-card { transition: border-color var(--speed) var(--ease); }
.look-card.is-on { border-color: var(--accent-line); }
.look-card .card__head .switch { margin-left: auto; }
.look-field {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 220px);
  gap: var(--s-2) var(--s-4);
  align-items: start;
  padding: var(--s-2) 0;
  border-top: 1px solid var(--border-soft);
}
.look-field:first-of-type { border-top: 0; }
.look-field--switch { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
.look-field__text { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.look-field__label { font-size: var(--t-sm); font-weight: 550; }
.look-field__desc { font-size: var(--t-xs); color: var(--text-dim); line-height: 1.45; }
.look-field__control { min-width: 0; }
@media (max-width: 640px) {
  .look-field { grid-template-columns: minmax(0, 1fr); }
}

/* -- one line of key: value inside a card body ------------------------------ */
.kv { display: flex; align-items: center; gap: var(--s-3); padding: 7px 0; border-bottom: 1px solid var(--border-soft); font-size: var(--t-sm); }
.kv:last-child { border-bottom: 0; }
.kv__key { display: inline-flex; align-items: center; gap: 8px; color: var(--text-dim); min-width: 0; }
.kv__value { margin-left: auto; font-variant-numeric: tabular-nums; text-align: right; }
