/* Yagit design system -- hand-written, no framework dependency.
   Sidebar-console shell (.app-shell/.app-sidebar/.app-main) for
   authenticated pages, a centered .guest-shell for /login. Forms,
   typography, and plain content still style bare elements directly
   (classless-authoring convention); named hook classes cover structural
   and composite UI: .status, .notice, .impersonation-banner. */

:root {
  --sidebar-bg: #14161f;
  --sidebar-text: #c9cbd8;
  --sidebar-text-active: #ffffff;
  --sidebar-item-hover-bg: #1e2130;
  --sidebar-item-active-bg: #23263a;

  --bg: #f5f6fa;
  --surface: #ffffff;
  --border: #e7e8ee;
  --text: #181a24;
  --text-muted: #6b6f80;
  --text-subtle: #9497a6;

  --accent: #5b5bf5;
  --accent-hover: #4747d1;
  --accent-ink: #ffffff;
  --accent-soft: #edecff;

  --success: #12876b;
  --success-hover: #0d6c55;
  --success-soft: #e3f7f0;
  --danger: #c8412d;
  --danger-hover: #a83322;
  --danger-soft: #fdecec;
  --warn: #a15a00;
  --warn-soft: #fdefdb;

  --role-admin: #7c3aed;
  --role-admin-soft: #f1e9fe;
  --role-teacher: #2563eb;
  --role-teacher-soft: #e9f0fe;
  --role-observer: #6d5bd0;
  --role-observer-soft: #f0edff;
  --role-student: #475569;
  --role-student-soft: #eef1f5;
  --role-sa: #b45309;
  --role-sa-soft: #fef3e0;

  --diagram-commit-red: #d6453f;
  --diagram-commit-orange: #dd7a1a;
  --diagram-commit-yellow: #b89412;
  --diagram-commit-green: #2f9e52;
  --diagram-commit-blue: #1f7fbf;
  --diagram-commit-violet: #a83fc0;
  --diagram-commit-magenta: #e60c92;
  --diagram-commit-red-soft: #fcf0f0;
  --diagram-commit-orange-soft: #fcf4ed;
  --diagram-commit-yellow-soft: #f9f6ec;
  --diagram-commit-green-soft: #eef7f1;
  --diagram-commit-blue-soft: #edf5fa;
  --diagram-commit-violet-soft: #f8f0fa;
  --diagram-commit-magenta-soft: #fdecf6;

  /* Shared timing for every animated-diagram transition (frame-to-frame
     morphs, duplicate-and-fly) -- plain ease-in-out per spec, "no
     overshoot, no bounce, no spring/damping". */
  --diagram-transition: 0.55s ease-in-out;
  --diagram-transition-fast: 0.2s ease-in-out;
  /* The duplicate-and-fly guide line's own fade in/out -- spans the full
     one-second hold before the duplicate departs, so every dotted arrow
     across every diagram gradually appears rather than snapping in. */
  --diagram-guide-fade: 1s ease-in-out;

  --radius-lg: 14px;
  --radius-md: 10px;
  --radius-sm: 7px;
  --shadow: 0 1px 2px rgba(20, 22, 35, .04), 0 8px 24px -12px rgba(20, 22, 35, .10);

  --font-size-base: 14px;
  --space-sm: 0.5rem;
  --space-md: 0.85rem;
  --space-lg: 1.5rem;

  --impersonation-bar-height: 3rem;
}

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

body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Noto Sans, Helvetica, Arial, sans-serif;
  font-size: var(--font-size-base);
  line-height: 1.55;
}

code,
pre {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

pre {
  padding: var(--space-sm) var(--space-md);
  background: var(--bg);
  border-radius: var(--radius-sm);
  overflow-x: auto;
}

pre code {
  padding: 0;
  background: none;
}

.app-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.app-sidebar {
  flex-shrink: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-md);
  background: var(--sidebar-bg);
  color: var(--sidebar-text);
  padding: var(--space-sm) var(--space-md);
  overflow-x: auto;
}

.sidebar-brand {
  flex-shrink: 0;
  padding: 0;
  color: var(--sidebar-text-active);
  font-weight: 700;
}

.side-nav {
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.25rem;
  overflow-x: auto;
}

.nav-item {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 0.4rem;
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-sm);
  color: var(--sidebar-text);
  white-space: nowrap;
}

.nav-item:hover {
  background: var(--sidebar-item-hover-bg);
  color: var(--sidebar-text-active);
}

.nav-item.active {
  background: var(--sidebar-item-active-bg);
  color: var(--sidebar-text-active);
}

.nav-item-icon {
  display: flex;
}

.nav-item-label {
  display: none;
}

.sidebar-footer {
  display: flex;
  flex-direction: row;
  flex-shrink: 0;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0;
  padding: 0;
  border-top: none;
}

.sidebar-footer-name,
.sidebar-footer-role {
  display: none;
}

.sidebar-footer a {
  color: var(--sidebar-text);
}

.sidebar-footer a:hover {
  color: var(--sidebar-text-active);
}

.app-main {
  flex: 1;
  min-width: 0;
  padding: var(--space-lg);
}

.page-topbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-bottom: var(--space-lg);
}

.page-topbar h1 {
  margin: 0;
}

.guest-shell {
  max-width: 26rem;
  margin: 3rem auto;
  padding: 0 var(--space-lg);
}

.guest-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-lg);
  font-weight: 700;
}

h1,
h2,
h3 {
  line-height: 1.25;
  margin-top: 0;
}

h1 {
  font-size: 1.6rem;
}

h2 {
  font-size: 1.3rem;
}

h3 {
  font-size: 1.1rem;
}

a {
  color: var(--accent);
}

a:hover {
  color: var(--accent-hover);
}

label {
  display: block;
  font-weight: 600;
  margin-top: var(--space-md);
  margin-bottom: 0.25rem;
}

input,
select,
textarea {
  display: block;
  width: 100%;
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font: inherit;
}

input[type="checkbox"],
input[type="radio"] {
  display: inline-block;
  width: auto;
  padding: 0;
  border: none;
  background: none;
  vertical-align: middle;
  margin-right: 0.4rem;
}

input:focus,
select:focus,
textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px transparent;
}

button,
input[type="submit"],
input[type="button"] {
  display: inline-block;
  width: 100%;
  margin-top: var(--space-md);
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

button:hover,
input[type="submit"]:hover,
input[type="button"]:hover {
  background: var(--border);
  border-color: var(--border);
}

.btn-primary,
button.btn-primary,
input.btn-primary[type="submit"],
input.btn-primary[type="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  margin-top: 0;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--accent);
  border-radius: var(--radius-md);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.btn-primary:hover,
button.btn-primary:hover,
input.btn-primary[type="submit"]:hover,
input.btn-primary[type="button"]:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.btn-success,
button.btn-success,
input.btn-success[type="submit"],
input.btn-success[type="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  margin-top: 0;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--success);
  border-radius: var(--radius-md);
  background: var(--success);
  color: var(--accent-ink);
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.btn-success:hover,
button.btn-success:hover,
input.btn-success[type="submit"]:hover,
input.btn-success[type="button"]:hover {
  background: var(--success-hover);
  border-color: var(--success-hover);
}

.btn-danger,
button.btn-danger,
input.btn-danger[type="submit"],
input.btn-danger[type="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  margin-top: 0;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--danger);
  border-radius: var(--radius-md);
  background: var(--danger);
  color: var(--accent-ink);
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.btn-danger:hover,
button.btn-danger:hover,
input.btn-danger[type="submit"]:hover,
input.btn-danger[type="button"]:hover {
  background: var(--danger-hover);
  border-color: var(--danger-hover);
}

.btn-danger:disabled,
button.btn-danger:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-secondary,
button.btn-secondary,
input.btn-secondary[type="submit"],
input.btn-secondary[type="button"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  margin-top: 0;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.btn-secondary:hover,
button.btn-secondary:hover,
input.btn-secondary[type="submit"]:hover,
input.btn-secondary[type="button"]:hover {
  background: var(--bg);
  border-color: var(--text-subtle);
}

.btn-google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  margin-top: var(--space-md);
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
}

.btn-google:hover {
  background: var(--bg);
}

.btn-copy,
button.btn-copy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 11rem;
  margin-top: 0;
  padding: 0.45rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font-weight: 600;
  cursor: pointer;
}

.btn-copy:hover,
button.btn-copy:hover {
  background: var(--bg);
}

.btn-copy.btn-success,
button.btn-copy.btn-success {
  background: #86efac;
  border-color: #86efac;
  color: #000000;
}

.btn-copy.btn-success:hover,
button.btn-copy.btn-success:hover {
  background: #4ade80;
  border-color: #4ade80;
  color: #000000;
}

button.tutorial-copy-clone-command {
  display: flex;
  width: fit-content;
  margin: 1rem 0;
}

table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  margin-top: var(--space-md);
  background: var(--surface);
}

th,
td {
  padding: 0.55rem 0.65rem;
  border-bottom: 1px solid var(--border);
  text-align: left;
}

th {
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.9em;
}

tr:hover td {
  background: var(--bg);
}

.row--late td {
  background: var(--danger-soft);
}

.notice {
  padding: 0.6rem 1rem;
  margin-bottom: 1rem;
  border-radius: var(--radius-md);
}

.notice--warn {
  background: var(--warn-soft);
  color: var(--warn);
}

.notice--ok {
  background: var(--success-soft);
  color: var(--success);
}

.notice--observer {
  border: 1px solid var(--role-observer);
  background: var(--role-observer-soft);
  color: var(--role-observer);
}

/* Observer-disabled controls remain legible through explicit color, border,
   and surface changes. The full opacity keeps the dashed treatment—not
   dimming—as the state signal. */
.observer-disabled,
button.observer-disabled,
input.observer-disabled,
select.observer-disabled,
textarea.observer-disabled {
  border: 1px dashed var(--role-observer);
  background: var(--role-observer-soft);
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 1;
}

.observer-disabled:hover,
.observer-disabled:active,
.observer-disabled:focus,
.observer-disabled:focus-visible,
button.observer-disabled:hover,
button.observer-disabled:active,
button.observer-disabled:focus,
button.observer-disabled:focus-visible,
input.observer-disabled:hover,
input.observer-disabled:active,
input.observer-disabled:focus,
input.observer-disabled:focus-visible,
select.observer-disabled:hover,
select.observer-disabled:active,
select.observer-disabled:focus,
select.observer-disabled:focus-visible,
textarea.observer-disabled:hover,
textarea.observer-disabled:active,
textarea.observer-disabled:focus,
textarea.observer-disabled:focus-visible {
  border-color: var(--role-observer);
  background: var(--role-observer-soft);
  color: var(--text-muted);
  box-shadow: none;
  transform: none;
}

label:has(.observer-disabled) {
  color: var(--text-muted);
}

input[type="checkbox"].observer-disabled,
input[type="radio"].observer-disabled {
  accent-color: var(--role-observer);
}

.stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-md);
  margin-bottom: var(--space-lg);
}

.stat-card {
  flex: 1 1 140px;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: var(--space-md);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.stat-card-value {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text);
}

.stat-card-label {
  color: var(--text-muted);
  font-size: 0.85em;
}

.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: var(--space-lg);
  margin-bottom: var(--space-lg);
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.panel-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.panel-header-actions label {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.panel-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-md);
}

.panel-toolbar input,
.panel-toolbar select {
  width: auto;
  flex: 1 1 200px;
  margin-top: 0;
}

.panel-toolbar--split {
  justify-content: space-between;
}

#roster-import-button {
  margin-top: var(--space-sm);
}

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 999px;
  font-size: 0.78em;
  font-weight: 700;
  color: var(--sidebar-text-active);
}

.avatar--admin {
  background: var(--role-admin);
}

.avatar--teacher {
  background: var(--role-teacher);
}

.avatar--student {
  background: var(--role-student);
}

.avatar--sa,
.avatar--assistant {
  background: var(--role-sa);
}

.badge {
  display: inline-block;
  padding: 0.12rem 0.55rem;
  border-radius: 999px;
  font-size: 0.78em;
  font-weight: 600;
  text-transform: capitalize;
  text-decoration: none;
}

.badge-course {
  background: var(--success-soft);
  color: var(--success);
  text-transform: none;
}

.badge-course:hover {
  background: var(--success-soft);
  color: var(--success-hover);
}

.badge-admin {
  background: var(--role-admin-soft);
  color: var(--role-admin);
}

.badge-teacher {
  background: var(--role-teacher-soft);
  color: var(--role-teacher);
}

.badge-student {
  background: var(--role-student-soft);
  color: var(--role-student);
}

.badge-sa,
.badge-assistant {
  background: var(--role-sa-soft);
  color: var(--role-sa);
}

.badge-student-assistant {
  background: var(--role-sa-soft);
  color: var(--role-sa);
  text-transform: none;
}

.user-role-badges,
.user-courses {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.35rem;
}

.badge-individual {
  background: var(--role-teacher-soft);
  color: var(--role-teacher);
}

.badge-group {
  background: var(--role-admin-soft);
  color: var(--role-admin);
}

.badge-owner {
  background: var(--role-admin-soft);
  color: var(--role-admin);
}

.badge-template-status--uploaded {
  background: var(--success-soft);
  color: var(--success);
}

.badge-template-status--not_uploaded {
  background: var(--warn-soft);
  color: var(--warn);
}

.uname {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.9em;
  color: var(--text-muted);
}

.tutorial-dashboard-parts {
  font-size: 0.85em;
  color: var(--text-muted);
  letter-spacing: 0.03em;
}

.tutorial-dashboard-tick {
  color: var(--success);
  font-weight: 700;
}

.member-email {
  font-size: 0.85em;
  color: var(--text-muted);
}

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.9em;
  font-weight: 600;
}

.status::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: currentColor;
}

.status--on,
.status--ontime {
  color: var(--success);
}

.status--off,
.status--not-accepted {
  color: var(--text-subtle);
}

.status--warning {
  color: var(--warn);
}

.status--late {
  color: var(--danger);
}

.status--missing {
  color: var(--warn);
}

.status--submitted {
  color: var(--success);
}

button.status {
  width: auto;
  margin-top: 0;
  padding: 0.15rem 0.6rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  background: none;
}

button.status--on:hover {
  background: var(--success-soft);
}

button.status--off:hover {
  background: var(--border);
}

.link-action {
  display: inline-block;
  width: auto;
  margin-top: 0;
  padding: 0.12rem 0.65rem;
  border: none;
  border-radius: 999px;
  background: var(--accent-soft);
  font-size: 0.85em;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}

.link-action:hover {
  color: var(--accent-hover);
}

.link-action-form {
  display: inline;
  margin: 0;
}

.link-action--attention {
  background: var(--warn-soft);
  color: var(--warn);
}

.link-action--attention:hover {
  color: var(--warn);
}

.link-action--danger {
  background: var(--danger-soft);
  color: var(--danger);
}

.link-action--danger:hover {
  color: var(--danger);
}

.context-menu {
  position: relative;
  display: inline-block;
}

.context-menu-panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.25rem);
  right: 0;
  min-width: 8rem;
  padding: 0.35rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--shadow);
}

.context-menu-item {
  display: block;
  width: 100%;
  margin-top: 0;
  padding: 0.35rem 0.5rem;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--text);
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.context-menu-item:hover {
  background: var(--bg);
}

.context-menu-item--danger {
  color: var(--danger);
}

.context-menu-item--danger:hover {
  background: var(--danger-soft);
}

dialog {
  width: 26rem;
  max-width: calc(100vw - 2rem);
  padding: var(--space-lg);
  border: none;
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow);
}

dialog::backdrop {
  background: rgba(20, 22, 35, .5);
}

dialog p {
  margin-top: 0;
  margin-bottom: var(--space-lg);
}

.dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-sm);
}

.dialog-actions form {
  margin: 0;
}

.dialog-actions button {
  width: auto;
  margin-top: 0;
}

.commit-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.9em;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.commit-list li {
  display: flex;
  gap: 0.75rem;
  padding: 0.4rem 0.65rem;
}

.commit-list li:not(:last-child) {
  border-bottom: 1px solid var(--border);
}

.commit-list--lapsed {
  background: var(--danger-soft);
  border-color: var(--danger);
}

.commit-table {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.commit-table--lapsed {
  background: var(--danger-soft);
  border-color: var(--danger);
}

.commit-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-md);
  margin-top: var(--space-md);
}

.commit-pager-label {
  color: var(--text-muted);
  font-size: 0.9em;
}

.commit-toggle {
  display: inline-block;
  width: auto;
  margin-top: 0;
  padding: 0.12rem 0.65rem;
  border: none;
  border-radius: 999px;
  background: var(--accent-soft);
  font-size: 0.85em;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}

.commit-toggle:hover {
  color: var(--accent-hover);
}

.file-browser {
  display: grid;
  grid-template-columns: minmax(180px, 260px) 1fr;
  gap: var(--space-lg);
  align-items: start;
  margin-top: var(--space-lg);
}

.file-browser-branch-select {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

.file-browser-branch-select label {
  margin: 0;
}

.file-browser-branch-select select {
  width: auto;
  margin-top: 0;
}

.browser-content-file-path {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.9em;
  color: var(--text-muted);
  margin-bottom: var(--space-sm);
}

.file-tree {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow-y: auto;
  max-height: 420px;
}

.file-tree-row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: 0.4rem 0.65rem;
  color: var(--text);
  cursor: pointer;
}

.file-tree-row:not(:last-child) {
  border-bottom: 1px solid var(--border);
}

.file-tree-row:hover {
  background: var(--accent-soft);
  color: var(--accent);
}

.file-tree-row--parent {
  color: var(--text-muted);
  font-weight: 600;
}

.browser-content {
  min-height: 120px;
}

.file-content {
  margin: 0;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  background: var(--bg);
  overflow-x: auto;
  font-size: 0.9em;
  white-space: pre;
}

@media (max-width: 599px) {
  .file-browser {
    grid-template-columns: minmax(0, 1fr);
  }
}

.group-member-list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  font-size: 0.9em;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.group-member-list li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.65rem;
}

.group-member-list li:not(:last-child) {
  border-bottom: 1px solid var(--border);
}

.activity-summary {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.6rem 1.5rem;
}

.activity-summary-label {
  align-self: baseline;
  color: var(--text-muted);
  font-size: 0.85em;
  font-weight: 600;
}

.activity-summary-value {
  align-self: baseline;
  color: var(--text);
}

.activity-summary:has(> .activity-summary-divider) {
  row-gap: var(--space-md);
}

.activity-summary-divider {
  grid-column: 1 / -1;
  border-top: 1px solid var(--border);
}

.activity-summary-action-boundary {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--border);
}

.teachers-table {
  width: auto;
}

.teacher-identity {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
}

@media (max-width: 599px) {
  .activity-summary:has(> .activity-summary-divider) {
    grid-template-columns: minmax(0, 1fr);
  }

  .activity-summary:has(> .activity-summary-divider) .activity-summary-value {
    min-width: 0;
  }
}

.deadline {
  font-weight: 600;
}

.deadline--lapsed {
  color: var(--danger);
}

.deadline--none {
  color: var(--text-subtle);
  font-weight: 400;
}

.description-content {
  position: relative;
  white-space: pre-wrap;
}

.description-panel {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.description-content--collapsed {
  max-height: 9rem;
  overflow: hidden;
}

.description-content--collapsed::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2.5rem;
  background: linear-gradient(to bottom, transparent, var(--surface));
  pointer-events: none;
}

.markdown-body {
  white-space: normal;
}

.markdown-body > *:first-child {
  margin-top: 0;
}

.markdown-body > *:last-child {
  margin-bottom: 0;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4 {
  margin-top: var(--space-md);
  margin-bottom: 0.35rem;
}

.markdown-body h1 {
  font-size: 1.25rem;
}

.markdown-body h2 {
  font-size: 1.1rem;
}

.markdown-body h3,
.markdown-body h4 {
  font-size: 1rem;
}

.markdown-body p {
  margin: 0 0 var(--space-sm);
}

.markdown-body ul,
.markdown-body ol {
  margin: 0 0 var(--space-sm);
  padding-left: 1.4rem;
}

.markdown-body li {
  margin-bottom: 0.2rem;
}

.markdown-body code {
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  font-size: 0.9em;
}

.markdown-body pre {
  margin: 0 0 var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  background: var(--bg);
  overflow-x: auto;
}

.markdown-body pre code {
  padding: 0;
  background: none;
}

.markdown-body blockquote {
  margin: 0 0 var(--space-sm);
  padding-left: var(--space-md);
  border-left: 3px solid var(--border);
  color: var(--text-muted);
}

.description-textarea {
  width: 100%;
  min-height: 10rem;
}

.description-textarea[hidden] {
  display: none;
}

.description-textarea--markdown {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

.description-preview-toggle[hidden] {
  display: inline-flex;
  visibility: hidden;
}

.description-panel-toolbar {
  margin-bottom: var(--space-md);
}

.description-panel-toolbar h2 {
  margin: 0 0 var(--space-sm);
}

.description-panel-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: flex-start;
  gap: var(--space-sm) var(--space-md);
}

.description-panel-controls > label {
  display: inline-flex;
  align-items: baseline;
}

.description-preview-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  width: auto;
  margin: 0;
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  cursor: pointer;
}

.description-preview-toggle:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.description-form {
  max-width: none;
}

.description-form .description-textarea {
  max-width: none;
}

.description-live-preview {
  min-height: 10rem;
  max-height: 22rem;
  overflow-y: auto;
}

.impersonation-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--impersonation-bar-height);
  padding: 0.6rem 1rem;
  background: var(--warn-soft);
  color: var(--warn);
  border-bottom: 1px solid var(--warn);
}

body.has-impersonation-banner .app-shell,
body.has-impersonation-banner .guest-shell {
  margin-top: var(--impersonation-bar-height);
}

.impersonation-banner p {
  margin: 0;
}

.impersonation-banner form {
  margin: 0;
}

.impersonation-banner button {
  width: auto;
  margin-top: 0;
  background: var(--surface);
  color: var(--warn);
  border-color: var(--warn);
}

.dt-picker {
  position: relative;
  margin-top: var(--space-md);
}

.dt-picker-trigger {
  display: flex;
  align-items: center;
  width: 100%;
  margin-top: 0;
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.dt-picker-trigger:hover {
  border-color: var(--accent);
}

.dt-picker-panel {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.35rem);
  left: 0;
  width: 17rem;
  padding: var(--space-md);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow);
}

.dt-picker-calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
  font-weight: 600;
}

.dt-picker-nav {
  width: auto;
  margin-top: 0;
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
}

.dt-picker-nav:hover {
  background: var(--bg);
}

.dt-picker-weekdays,
.dt-picker-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.15rem;
  text-align: center;
}

.dt-picker-weekdays {
  color: var(--text-muted);
  font-size: 0.78em;
  font-weight: 600;
  margin-bottom: 0.25rem;
}

.dt-picker-day {
  width: auto;
  margin-top: 0;
  padding: 0.3rem 0;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  font: inherit;
  font-size: 0.85em;
  cursor: pointer;
}

.dt-picker-day:hover {
  background: var(--bg);
}

.dt-picker-day--empty {
  cursor: default;
}

.dt-picker-day--empty:hover {
  background: transparent;
}

.dt-picker-day--selected {
  background: var(--accent);
  color: var(--accent-ink);
}

.dt-picker-day--disabled {
  color: var(--text-muted);
  cursor: not-allowed;
  opacity: 0.4;
}

.dt-picker-day--disabled:hover {
  background: transparent;
}

.dt-picker-time {
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--border);
}

.dt-picker-time-label {
  margin-top: 0;
  margin-bottom: 0.25rem;
  font-size: 0.85em;
}

.dt-picker-time-fields {
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.dt-picker-time-fields input {
  width: 3.4rem;
  margin-top: 0;
  padding: 0.3rem 0.4rem;
  text-align: center;
}

.dt-picker-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: var(--space-sm);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--border);
}

@media (min-width: 900px) {
  .course-membership-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
    gap: var(--space-lg);
    margin-bottom: var(--space-lg);
  }

  #course-membership-panels {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--space-lg);
  }

  .course-membership-layout .panel {
    margin-bottom: 0;
  }

  .app-shell {
    flex-direction: row;
  }

  .app-sidebar {
    width: 236px;
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-md) 0;
    overflow-x: visible;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
  }

  .sidebar-brand {
    padding: 0 var(--space-md) var(--space-lg);
  }

  .side-nav {
    flex-direction: column;
    align-items: stretch;
    overflow-x: visible;
  }

  .nav-item-label {
    display: inline;
  }

  .sidebar-footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.2rem;
    margin-top: auto;
    padding: var(--space-md);
    border-top: 1px solid var(--sidebar-item-active-bg);
  }

  .sidebar-footer-name,
  .sidebar-footer-role {
    display: block;
  }

  .sidebar-footer-name {
    color: var(--sidebar-text-active);
    font-weight: 600;
  }

  .sidebar-footer-role {
    color: var(--sidebar-text);
    font-size: 0.85em;
    text-transform: capitalize;
  }

  .app-main {
    height: 100vh;
    overflow-y: auto;
  }

  body.has-impersonation-banner .app-sidebar {
    top: var(--impersonation-bar-height);
    height: calc(100vh - var(--impersonation-bar-height));
  }

  body.has-impersonation-banner .app-main {
    height: calc(100vh - var(--impersonation-bar-height));
  }
}

.activity-code-field {
  display: flex;
  align-items: stretch;
  gap: 0;
}

.activity-code-prefix {
  display: flex;
  align-items: center;
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--border);
  border-right: none;
  border-radius: var(--radius-md) 0 0 var(--radius-md);
  background: var(--bg);
  color: var(--text-muted);
  white-space: nowrap;
}

.activity-code-field input {
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}

.code-check {
  font-size: 0.85em;
  font-weight: 600;
}

.code-check--available {
  color: var(--success);
}

.code-check--taken {
  color: var(--danger);
}

.code-check-status {
  display: block;
  min-height: 1.3rem;
  line-height: 1.3rem;
  margin-top: 0.35rem;
}

.tutorial-part {
  margin: 1.25rem 0 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border);
}

.tutorial-part:first-child {
  margin-top: 0.75rem;
  padding-top: 0;
  border-top: none;
}

.tutorial-part-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-sm);
}

.tutorial-part-title {
  margin-bottom: 0.2rem;
}

.tutorial-part-description {
  margin: 0;
  font-size: 0.85em;
  color: var(--text-muted);
}

.tutorial-congrats {
  margin: 1rem 0 0;
  padding-top: 0.85rem;
  border-top: 1px solid var(--border);
  font-weight: 600;
  color: var(--success);
}

.tutorial-steps {
  list-style: none;
  margin: 0.75rem 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.tutorial-step {
  display: flex;
  flex-direction: column;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.tutorial-step[hidden],
.tutorial-part[hidden],
.tutorial-substep-proceed[hidden],
#tutorial-restart-button[hidden] {
  display: none;
}

.tutorial-step-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-sm);
}

.tutorial-step-title {
  font-weight: 600;
}

.tutorial-step-summary {
  font-size: 0.85em;
  color: var(--text-muted);
}

.tutorial-step-autotrack {
  display: block;
  margin-top: 0.35rem;
  font-size: 0.8em;
  font-style: italic;
  color: var(--text-subtle);
}

.tutorial-step--current {
  border-color: var(--role-teacher);
}

.tutorial-step--complete .tutorial-step-title::before {
  content: "✅ ";
}

.tutorial-step-action {
  margin: 0.85rem 0 0;
}

.tutorial-proceed-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}

.tutorial-proceed-spinner {
  display: none;
  width: 0.9em;
  height: 0.9em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: tutorial-proceed-spin 0.6s linear infinite;
}

.tutorial-proceed-btn--loading .tutorial-proceed-spinner {
  display: inline-block;
}

@keyframes tutorial-proceed-spin {
  to {
    transform: rotate(360deg);
  }
}

.tutorial-proceed-error {
  margin: 0.4rem 0 0;
  color: var(--danger);
  font-weight: 600;
  font-size: 0.85em;
}

.tutorial-proceed-error[hidden] {
  display: none;
}

.btn-toggle-details {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  width: auto;
  margin: 1.5rem 0 0;
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--success);
  border-radius: var(--radius-md);
  background: var(--success-soft);
  color: var(--success);
  font-weight: 600;
  font-size: 0.9em;
  cursor: pointer;
}

.btn-toggle-details:hover {
  background: var(--success);
  color: var(--accent-ink);
}

.tutorial-step-commands {
  margin: 0.5rem 0 0;
  padding-left: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.tutorial-substeps {
  margin: 1rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.tutorial-step-substep + .tutorial-step-substep {
  margin-top: 1.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
}

.tutorial-substep-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  border-bottom: 1px solid var(--border);
}

.tutorial-substep-tab {
  padding: 0.35rem 0.75rem;
  border: none;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--text-muted);
  font-size: 0.85em;
  font-weight: 600;
  cursor: pointer;
}

.tutorial-substep-tab:hover {
  color: var(--text);
}

.tutorial-substep-tab--active {
  border-bottom-color: var(--accent);
  color: var(--accent);
}

.tutorial-substep .tutorial-step-commands {
  margin-top: 0.35rem;
}

.tutorial-step-commands li > code {
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--accent);
  font-size: 0.9em;
}

.tutorial-command-placeholder {
  display: inline-block;
  padding: 0.05rem 0.35rem;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-hover);
  font: inherit;
  font-weight: 600;
  line-height: 1.35;
  user-select: none;
}

.tutorial-command-placeholder::before {
  content: attr(data-placeholder);
}

/* Cycled per placeholder within a single command so that lines with
   multiple arguments (eg. "git push <remote> <branch>") read each
   argument as visually distinct from the others and from plain text. */
.tutorial-command-placeholder--0 {
  background: var(--diagram-commit-red-soft);
  color: var(--diagram-commit-red);
}

.tutorial-command-placeholder--1 {
  background: var(--diagram-commit-orange-soft);
  color: var(--diagram-commit-orange);
}

.tutorial-command-placeholder--2 {
  background: var(--diagram-commit-green-soft);
  color: var(--diagram-commit-green);
}

.tutorial-command-placeholder--3 {
  background: var(--diagram-commit-blue-soft);
  color: var(--diagram-commit-blue);
}

.tutorial-step-commands li > p {
  margin: 0.35rem 0 0;
}

.tutorial-step-summary code {
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--accent);
  font-size: 0.9em;
}

.tutorial-step-commands li > p code {
  padding: 0.1rem 0.35rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--accent);
  font-size: 0.9em;
}

.tutorial-command-syntax {
  margin-top: 0.75rem;
}

.tutorial-glossary {
  margin: 1rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.tutorial-glossary dt {
  font-weight: 600;
}

.tutorial-glossary dd {
  margin: 0.2rem 0 0;
}

.tutorial-diagram-frame-item {
  list-style: none;
  counter-increment: list-item 0;
}

.tutorial-diagram-frame {
  margin: 0.5rem 0 0;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}

.tutorial-diagram-note {
  margin: 0 0 0.5rem;
  font-size: 0.85em;
  font-style: italic;
  color: var(--text-subtle);
}

.tutorial-diagram-svg {
  display: block;
  width: 100%;
  height: auto;
}

.tutorial-diagram-half-label {
  font-size: 9px;
  font-weight: 600;
  fill: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.tutorial-diagram-half-box {
  fill: none;
  stroke: var(--border);
  stroke-width: 1;
}

.tutorial-diagram-node {
  stroke-width: 1.5;
  /* cx/cy are standard CSS-animatable SVG geometry properties (SVG2, all
     evergreen browsers) -- transitioning them directly on the plain
     attribute values the template already emits, rather than requiring
     the animation JS to compute an offsetting transform instead. */
  transition: cx var(--diagram-transition), cy var(--diagram-transition),
    fill var(--diagram-transition), stroke var(--diagram-transition),
    opacity var(--diagram-transition);
}

.tutorial-diagram-edge {
  stroke: var(--text-subtle);
  stroke-width: 1.5;
  transition: x1 var(--diagram-transition), y1 var(--diagram-transition),
    x2 var(--diagram-transition), y2 var(--diagram-transition),
    opacity var(--diagram-transition);
}

.tutorial-diagram-arrowhead {
  fill: var(--text-subtle);
}

.tutorial-diagram-branch-tip-badge {
  fill: #fff !important;
  stroke: var(--success);
  stroke-width: 1;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    opacity var(--diagram-transition);
}

.tutorial-diagram-branch-tip {
  font-size: 9px;
  font-weight: 600;
  fill: var(--success);
  dominant-baseline: central;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    opacity var(--diagram-transition);
}

/* HEAD is deliberately neutral: green remains reserved for named branches.
   Step 14 keeps this marker in all three frames so it moves between the
   branch tip and detached commit through the standard keyed SVG morph. */
.tutorial-diagram-head-badge {
  fill: var(--surface);
  stroke: var(--text-subtle);
  stroke-width: 1;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    opacity var(--diagram-transition);
}

.tutorial-diagram-head {
  font-size: 9px;
  font-weight: 600;
  fill: var(--text-subtle);
  dominant-baseline: central;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    opacity var(--diagram-transition);
}

/* A branch created locally, or an untracked file created only on the local
   disk, has no Remote source to animate from. Its visible parts fade, grow,
   and settle together to make the local-only change perceptible. */
.tutorial-diagram-branch-tip-badge--created,
.tutorial-diagram-branch-tip-badge--popped,
.tutorial-diagram-branch-tip--popped,
.tutorial-diagram-file-appearance--local-untracked {
  transform-box: fill-box;
  transform-origin: center;
  animation: tutorial-diagram-branch-created 0.52s ease-out;
}

@keyframes tutorial-diagram-branch-created {
  0% { opacity: 0; transform: scale(0.65); }
  35% { opacity: 1; transform: scale(1.2); }
  100% { opacity: 1; transform: scale(1); }
}

/* A branch is still visible before `git branch -d` takes effect. Shrink it,
   rebound once, then remove it so the deletion reads as a deliberate local
   change rather than an unexplained fade. */
.tutorial-diagram-branch-tip-badge--deleted,
.tutorial-diagram-branch-tip--deleted {
  transform-box: fill-box;
  transform-origin: center;
  animation: tutorial-diagram-branch-deleted 0.52s ease-in-out both;
}

@keyframes tutorial-diagram-branch-deleted {
  0%, 20% { opacity: 1; transform: scale(1); }
  55% { opacity: 1; transform: scale(0.65); }
  80% { opacity: 1; transform: scale(1.2); }
  100% { opacity: 0; transform: scale(1); }
}

.tutorial-diagram-tracking-ref {
  font-size: 9px;
  font-weight: 600;
  font-style: italic;
  fill: #fff !important;
  stroke: var(--text-subtle);
  stroke-width: 0.5;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    opacity var(--diagram-transition);
}

.tutorial-diagram-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.4rem 0 0;
  /* The SVG's viewBox has a small visual tail below its panels. Lift the
     controls without reflowing the legend so both visible gaps match. */
  transform: translateY(-0.8rem);
}

.tutorial-diagram-playpause {
  flex: 0 0 3rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  min-width: 3rem;
  height: 3rem;
  min-height: 3rem;
  aspect-ratio: 1;
  padding: 0;
  margin: 0;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--surface);
  color: var(--text-muted);
  font-size: 1.1rem;
  line-height: 1;
}

.tutorial-diagram-playpause:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.tutorial-diagram-progress {
  flex: 1 1 auto;
  width: 100%;
  min-width: 0;
  height: 3rem;
  margin: 0;
  cursor: pointer;
  appearance: none;
  background: transparent;
}

.tutorial-diagram-progress::-webkit-slider-runnable-track {
  height: 0.25rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
}

.tutorial-diagram-progress::-webkit-slider-thumb {
  width: 1rem;
  height: 1rem;
  margin-top: -0.375rem;
  border: 2px solid var(--surface);
  border-radius: 50%;
  appearance: none;
  background: var(--accent);
}

.tutorial-diagram-progress::-moz-range-track {
  height: 0.25rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
}

.tutorial-diagram-progress::-moz-range-thumb {
  width: 0.75rem;
  height: 0.75rem;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background: var(--accent);
}

.tutorial-diagram-progress:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.tutorial-diagram-legend {
  list-style: none;
  margin: 0.25rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  font-size: 0.8em;
  color: var(--text-muted);
}

.tutorial-diagram-legend-item {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}

/* A commit that lands mid-loop (eg. step 4's `git commit`) gets its own
   legend row appended live by tutorial-diagram.js -- reuses the same
   grow-and-settle bounce as a locally created branch tip badge so a new
   commit reads as a new thing everywhere it shows up, not just in the
   graph. */
.tutorial-diagram-legend-item--created {
  transform-origin: center left;
  animation: tutorial-diagram-branch-created 0.52s ease-out;
}

.tutorial-diagram-legend-dot {
  flex: none;
  width: 0.6em;
  height: 0.6em;
  border-radius: 50%;
  align-self: center;
}

.tutorial-diagram-legend code {
  padding: 0.05rem 0.3rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--accent);
  font-size: 0.9em;
}

.tutorial-diagram-annotation {
  font-style: italic;
  color: var(--text-subtle);
}

.tutorial-diagram-files-box {
  fill: var(--surface);
  stroke: var(--border);
  stroke-width: 1;
  transition: opacity var(--diagram-transition);
}

.tutorial-diagram-files-box-label {
  font-size: 7px;
  font-weight: 600;
  fill: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  transition: opacity var(--diagram-transition);
}

/* The branch name in "Working directory (<branch>)" -- kept visually
   secondary to the box's own uppercase label, and left lowercase/unstyled
   so a branch name doesn't get shouted in caps like the label itself. */
.tutorial-diagram-files-box-label-branch {
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}

/* A branch switch changes only this label, so give it a temporary pill and
   flash rather than making the otherwise-identical Working directory box look
   like it changed wholesale. */
.tutorial-diagram-files-box-label-branch-highlight {
  fill: var(--accent-soft);
  stroke: var(--accent);
  stroke-width: 0.5;
  transform-box: fill-box;
  transform-origin: center;
  pointer-events: none;
  animation: tutorial-diagram-branch-highlight 1.1s ease-out;
}

.tutorial-diagram-files-box-label-branch--changed {
  animation: tutorial-diagram-branch-switch 1.1s ease-out;
}

@keyframes tutorial-diagram-branch-highlight {
  0% { opacity: 0; transform: scale(0.88); }
  18% { opacity: 1; transform: scale(1.08); }
  45%, 100% { transform: scale(1); }
  100% { opacity: 0; }
}

@keyframes tutorial-diagram-branch-switch {
  0% { fill: var(--text-subtle); opacity: 0.35; }
  18%, 45% { fill: var(--accent); opacity: 1; }
  100% { fill: var(--text-subtle); opacity: 1; }
}

.tutorial-diagram-file-badge {
  fill: var(--surface);
  stroke: var(--border);
  stroke-width: 1;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    width var(--diagram-transition), height var(--diagram-transition),
    rx var(--diagram-transition), ry var(--diagram-transition),
    fill var(--diagram-transition), stroke var(--diagram-transition),
    opacity var(--diagram-transition);
}

/* Border/text color (which commit a file's current content belongs to) is
   set inline per-frame from that node's color_token. This class's own fill
   is a fallback only -- the template overrides it inline with a soft tint
   of that same current commit's color, so the highlight that flags
   unstaged edits reads as "this commit's content, lightly flagged" rather
   than an unrelated color. */
.tutorial-diagram-file-badge--dirty {
  fill: var(--danger-soft);
}

/* Same idea as --dirty above, but for a file that's been staged (git add)
   and not yet committed. Fallback fill only -- the template overrides it
   inline with a soft tint of the *next* commit's color (the same preview
   color the Staging area badge uses), so the highlight ties visually to
   the commit that file is about to become part of. */
.tutorial-diagram-file-badge--staged {
  fill: var(--accent-soft);
}

.tutorial-diagram-file-badge-text {
  font-size: 7px;
  fill: var(--text-muted);
  dominant-baseline: central;
  transition: x var(--diagram-transition), y var(--diagram-transition),
    fill var(--diagram-transition), opacity var(--diagram-transition);
}

.tutorial-diagram-file-badge-text--dirty,
.tutorial-diagram-file-badge-text--staged {
  font-weight: 600;
}

.tutorial-diagram-file-entry--empty {
  font-size: 7.5px;
  font-style: italic;
  fill: var(--text-subtle);
}

/* Fallback fill only -- both the --dirty and --staged notes get their real
   color inline per-frame (current commit's color for --dirty, next
   commit's for --staged; see the badge fill comments above). */
.tutorial-diagram-file-note {
  font-size: 6.5px;
  font-style: italic;
  fill: var(--danger);
  transition: x var(--diagram-transition), y var(--diagram-transition),
    fill var(--diagram-transition), opacity var(--diagram-transition);
}

.tutorial-diagram-file-note--staged {
  fill: var(--accent);
}

/* Terminal-styled typing caption (JS-created, Task 5) rendered above a
   playing frame's SVG -- dramatizes "you just ran this command", separate
   from the SVG's accessible name and the step's own plain-text command
   list. No template currently emits this markup; the class names here are
   the contract Task 5's JS builds its DOM against. */
.tutorial-diagram-caption {
  display: flex;
  align-items: center;
  gap: 0.3em;
  margin: 0 0 0.35rem;
  padding: 0.15rem 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--bg);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.78em;
  color: var(--text-muted);
  transition: background var(--diagram-transition-fast);
}

.tutorial-diagram-caption-prompt {
  flex: none;
  color: var(--accent);
}

.tutorial-diagram-caption-cursor {
  display: inline-block;
  width: 0.5em;
  margin-left: 0.05em;
  border-left: 1px solid currentColor;
  animation: tutorial-diagram-cursor-blink 1s step-end infinite;
}

@keyframes tutorial-diagram-cursor-blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

/* JS toggles this modifier when the frame being typed carries
   data-caption-is-command="false" (see DiagramFrame.is_command) -- a
   prose instruction like step 6's "In main.py, replace..." reusing this
   same typed-caption element rather than a real command. Overrides the
   terminal look with plain instructional text: no prompt glyph, no
   blinking cursor, no monospace font, and no Enter-flash highlight (the
   --typing/--typing-done overrides below), since there's no command here
   that was actually "entered". */
.tutorial-diagram-caption--instruction {
  font-family: inherit;
  font-style: italic;
}

.tutorial-diagram-caption--instruction .tutorial-diagram-caption-prompt,
.tutorial-diagram-caption--instruction .tutorial-diagram-caption-cursor {
  display: none;
}

.tutorial-diagram-caption--instruction.tutorial-diagram-caption--typing,
.tutorial-diagram-caption--instruction.tutorial-diagram-caption--typing-done {
  animation: none;
  background: var(--bg);
}

/* JS adds this class the moment a command starts typing and removes it
   once typing finishes (see --typing-done below for the hand-off) --
   holds the highlight for the full duration of the typing animation,
   not just a one-shot cue at the end. `forwards` keeps the fade's
   settled end state (warn background) until that hand-off, since
   TYPE_MS runs well past this animation's own short duration. */
.tutorial-diagram-caption--typing {
  animation: tutorial-diagram-caption-fade-in 0.25s ease-out forwards;
}

/* One-shot cue: JS swaps --typing for this class the instant typing
   finishes, then removes it once the fade-out animation completes. */
.tutorial-diagram-caption--typing-done {
  animation: tutorial-diagram-caption-fade-out 0.35s ease-in forwards;
}

@keyframes tutorial-diagram-caption-fade-in {
  0% { background: var(--bg); }
  100% { background: var(--warn-soft); }
}

@keyframes tutorial-diagram-caption-fade-out {
  0% { background: var(--warn-soft); }
  100% { background: var(--bg); }
}

/* Duplicate-and-fly boundary-crossing treatment (JS-created/positioned,
   Task 6) -- the source element never moves; a temporary duplicate flies
   from source to destination along a JS-computed quadratic arc, dashed
   guide line first. Position/path is driven per-frame by JS (a curved
   path isn't a single CSS-transitionable value), so only the color morph
   and the guide line's draw/fade are CSS transitions here. */
.tutorial-diagram-guide-line {
  fill: none;
  stroke: var(--text-subtle);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  marker-end: url(#tutorial-diagram-arrowhead);
  opacity: 0;
  transition: opacity var(--diagram-guide-fade);
}

.tutorial-diagram-guide-line--visible {
  opacity: 1;
}

.tutorial-diagram-duplicate {
  pointer-events: none;
  transition: fill var(--diagram-transition), stroke var(--diagram-transition);
}

/* Plain-cut override (Task 5's JS, the last-frame-back-to-first-frame wrap
   in a card's loop): applied for one frame just while attributes are
   rewritten, so that specific jump doesn't animate like every other
   frame-to-frame transition does -- "no real git command undoes a push". */
.tutorial-diagram-svg--cut,
.tutorial-diagram-svg--cut * {
  transition: none !important;
}

/* Reduced-motion baseline: every card sits at its own settled target frame
   with no in-progress transition (belt-and-suspenders alongside Task 5's
   JS, which must also skip starting any card's loop under
   prefers-reduced-motion rather than relying on this alone). */
@media (prefers-reduced-motion: reduce) {
  .tutorial-diagram-node,
  .tutorial-diagram-edge,
  .tutorial-diagram-branch-tip-badge,
  .tutorial-diagram-branch-tip,
  .tutorial-diagram-head-badge,
  .tutorial-diagram-head,
  .tutorial-diagram-tracking-ref,
  .tutorial-diagram-file-badge,
  .tutorial-diagram-file-badge-text,
  .tutorial-diagram-file-note,
  .tutorial-diagram-files-box,
  .tutorial-diagram-files-box-label,
  .tutorial-diagram-caption,
  .tutorial-diagram-guide-line,
  .tutorial-diagram-duplicate {
    transition: none;
  }

  .tutorial-diagram-caption-cursor,
  .tutorial-diagram-caption--typing,
  .tutorial-diagram-caption--typing-done,
  .tutorial-diagram-files-box-label-branch-highlight,
  .tutorial-diagram-files-box-label-branch--changed {
    animation: none;
  }
}

.validator-outcomes {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0;
}

.validator-outcome {
  font-size: 0.85em;
  font-weight: 600;
}

.validator-outcome--passed {
  color: var(--success);
}

.validator-outcome--failed {
  color: var(--danger);
}

.validator-outcome--not-tested {
  color: var(--text-muted);
}

.validator-outcome--warning {
  color: var(--warn);
}

.validator-outcome--optional {
  color: var(--success);
}

.validator-error-detail {
  margin: 0 0 0.35rem;
  color: var(--danger);
  font-size: 0.85em;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.validator-excerpt,
.validator-error-detail--expanded {
  max-width: 100%;
  max-height: 12rem;
  margin: 0.3rem 0 0;
  padding: 0.5rem;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-family: monospace;
  font-size: 0.8em;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  box-sizing: border-box;
}

.validator-output-details {
  margin: 0.3rem 0 0;
  max-width: 100%;
}

.validator-output-details > summary {
  cursor: pointer;
  font-size: 0.85em;
  color: var(--text-muted);
}

.validator-output-details[open] > summary {
  margin-bottom: 0.2rem;
}

button:disabled,
input[type="submit"]:disabled,
input[type="button"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Keep Observer-disabled controls at full opacity even though the generic
   disabled rule above dims ordinary unavailable controls. */
button.observer-disabled:disabled,
input.observer-disabled:disabled,
select.observer-disabled:disabled,
textarea.observer-disabled:disabled {
  opacity: 1;
}

.field-hint {
  margin-top: 0.2rem;
  margin-bottom: 0;
  color: var(--text-muted);
  font-size: 0.82em;
}

.field-hint--error {
  color: var(--danger);
  font-weight: 600;
}

.group-size-fields {
  margin-top: var(--space-md);
  padding: var(--space-md);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg);
}

.group-size-fields input.input-invalid {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.group-size-fields input.input-invalid:focus {
  outline-color: var(--danger);
  border-color: var(--danger);
}

.group-size-inline {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.group-size-inline input[type="number"] {
  width: 4.5rem;
}

.group-size-inline input.input-invalid {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.group-size-inline input.input-invalid:focus {
  outline-color: var(--danger);
  border-color: var(--danger);
}

.dropzone {
  margin-top: var(--space-md);
  padding: var(--space-lg);
  text-align: center;
  border: 2px dashed var(--border);
  transition: border-color .1s ease, background .1s ease;
}

.dropzone--active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.dropzone input[type="file"] {
  max-width: 24rem;
  margin: 0 auto;
}

.dropzone-hint {
  margin-top: var(--space-sm);
  margin-bottom: 0;
  color: var(--text-muted);
  font-size: 0.85em;
}

.dropzone-filename {
  margin-top: var(--space-sm);
  margin-bottom: 0;
  font-weight: 600;
}

@media (min-width: 768px) {
  :root {
    --font-size-base: 14px;
    --space-md: 0.7rem;
  }

  main form {
    max-width: 32rem;
  }

  main form.activity-create-form {
    max-width: none;
  }

  main table form {
    max-width: none;
  }

  main input:not([type="checkbox"]):not([type="radio"]):not([type="file"]),
  main select,
  main textarea {
    max-width: 28rem;
  }

  main button[type="submit"],
  main button[type="button"],
  main input[type="submit"],
  main input[type="button"] {
    width: auto;
  }
}

/* Git command cheatsheet: a vertical tab fixed to the right edge of the
   viewport that peeks out further on hover/focus, opening a right-anchored
   <dialog> listing every git command CURRICULUM has revealed so far. */
.tutorial-cheatsheet-tab {
  position: fixed;
  top: 25%;
  right: 0;
  z-index: 30;
  transform: translateY(-50%) translateX(6px);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.9rem 0.5rem;
  border: 1px solid var(--accent);
  border-right: none;
  border-radius: var(--radius-md) 0 0 var(--radius-md);
  background: var(--accent);
  color: var(--accent-ink);
  box-shadow: var(--shadow);
  cursor: pointer;
  transition: transform 0.15s ease;
  width: max-content;
}

.tutorial-cheatsheet-tab:hover,
.tutorial-cheatsheet-tab:focus-visible {
  transform: translateY(-50%) translateX(0);
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.tutorial-cheatsheet-tab span {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0.03em;
}

.tutorial-cheatsheet-dialog {
  position: fixed;
  inset: 0 0 0 auto;
  margin: 0;
  width: min(28rem, 92vw);
  max-width: none;
  height: 100vh;
  max-height: 100vh;
  border-radius: 0;
  overflow-y: auto;
}

.tutorial-cheatsheet-dialog::backdrop {
  background: rgba(20, 22, 35, .5);
}

.tutorial-cheatsheet-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-bottom: var(--space-sm);
}

.tutorial-cheatsheet-header h2 {
  margin: 0;
}

.tutorial-cheatsheet-close {
  width: auto;
  margin: 0;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 1.2rem;
  line-height: 1.4;
  cursor: pointer;
}

.tutorial-cheatsheet-close:hover {
  border-color: var(--text-subtle);
  color: var(--text);
}

.tutorial-cheatsheet-intro {
  color: var(--text-muted);
  font-size: 0.9em;
}

.tutorial-cheatsheet-empty {
  color: var(--text-muted);
}

.tutorial-cheatsheet-group {
  margin-top: var(--space-lg);
}

.tutorial-cheatsheet-group h3 {
  margin: 0 0 var(--space-sm);
  padding-bottom: 0.25rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.95rem;
  color: var(--accent);
}

.tutorial-cheatsheet-command {
  margin-bottom: var(--space-md);
}

.tutorial-cheatsheet-command + .tutorial-cheatsheet-command {
  padding-top: var(--space-md);
  border-top: 1px dashed var(--border);
}

.tutorial-cheatsheet-root {
  display: inline-block;
  margin-bottom: 0.3rem;
  font-weight: 600;
}

.tutorial-cheatsheet-syntax {
  margin: 0 0 0.3rem;
  padding-left: 1.1rem;
  color: var(--text-muted);
  font-size: 0.85em;
}

.tutorial-cheatsheet-explanation {
  margin: 0 0 0.3rem;
  font-size: 0.9em;
}

.tutorial-cheatsheet-examples {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.85em;
}

.tutorial-cheatsheet-examples code {
  word-break: break-word;
}
