/* ============================================================
   AUTOMATA — Shell, motion & polish layer
   Loaded AFTER app.css. Presentation only; no DOM contracts.
   Created by Kevin Valentine
   ============================================================ */

:root {
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur-fast: 160ms;
  --dur: 280ms;
  --dur-slow: 460ms;
}

body { overflow: hidden; }

/* ---------- Scrollbars ---------- */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: #cbd5e1;
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover { background: #94a3b8; background-clip: content-box; }

/* ============================================================
   1 · OPENING SCREEN
   ============================================================ */
.splash {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Matches the assemble MP4 studio gray so the clip does not sit in a white box. */
  background: #e8e8e8;
  color: var(--navy);
  overflow: hidden;
  pointer-events: none !important;
  transition: opacity 620ms var(--ease-in-out), transform 620ms var(--ease-in-out);
}
.splash * { pointer-events: none !important; }
/* Compositor-driven safety net. The renderer's main thread can stall during a
   heavy first data load, which freezes JS timers AND any main-thread animation.
   Only opacity/transform animate on the compositor, so this keyframe touches
   opacity alone -- adding visibility or pointer-events here would push it back
   onto the stalled thread and defeat the purpose. The splash is pointer-events:
   none at all times, so even a stuck one never blocks input. */
/* Assemble video 4s; company fade 700ms after that. Welcome audio is
   6.008s and starts at 1s, so it ends ~7008ms — dismiss with the track
   (Kevin 2026-09-19: opening was ~2s too long; no silence after audio). */
.splash { animation: splashAutoOut 700ms var(--ease-in-out) 7000ms forwards; }
@keyframes splashAutoOut {
  from { opacity: 1; }
  to   { opacity: 0; }
}
.splash.is-leaving {
  animation: none;
  opacity: 0;
  transform: scale(1.045);
  pointer-events: none !important;
  visibility: hidden;
}
.splash.is-gone { display: none !important; pointer-events: none !important; }

.splash-aurora,
.splash-grid { display: none; }

.splash-inner {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 32px;
  /* Wordmark under the A: sit the lockup higher so the name is not below center. */
  margin-top: -8vh;
}

/* --- assemble mark ---
   Clip is 546px (420 + 30%). The MP4 has extra gray under the A, so the
   mark crops that pad and leaves 12px to AUTOMATA — optical lockup. */
.splash-mark {
  position: relative;
  width: 546px;
  overflow: hidden;
  line-height: 0;
  margin: 0 0 12px;
}
.splash-logo-video,
.splash-logo-fallback {
  display: block;
  width: 546px;
  height: auto;
  background: #e8e8e8;
  /* Source bottom pad 156px vs top 64px → extra 92px × (546/720) ≈ 70px. */
  margin: 0 0 -70px;
}
.splash-logo-fallback { display: none; }
.splash.is-static .splash-logo-video { display: none; }
.splash.is-static .splash-logo-fallback { display: block; }
/* Kevin, 2026-09-19: the video stays invisible until its first frame has
   painted, so nothing of the finished logo shows ahead of the animation. */
.splash:not(.is-static):not(.is-playing) .splash-logo-video { opacity: 0; }
.splash.is-playing .splash-logo-video { opacity: 1; transition: opacity 140ms ease-out; }

.mark-ring {
  stroke-dasharray: 327;
  stroke-dashoffset: 327;
  transform-origin: 60px 60px;
  transform: rotate(-90deg);
  animation: drawRing 1500ms var(--ease-out) 240ms forwards,
             ringPulse 4s ease-in-out 2s infinite;
  opacity: 0.55;
}
@keyframes drawRing { to { stroke-dashoffset: 0; } }
@keyframes ringPulse { 0%,100% { opacity: 0.4; } 50% { opacity: 0.85; } }

.mark-page, .mark-fold {
  stroke-dasharray: 220;
  stroke-dashoffset: 220;
  animation: drawPage 1100ms var(--ease-out) 420ms forwards;
}
.mark-fold { animation-delay: 900ms; stroke-dasharray: 40; stroke-dashoffset: 40; }
@keyframes drawPage { to { stroke-dashoffset: 0; } }

.mark-line {
  stroke-dasharray: 30;
  stroke-dashoffset: 30;
  opacity: 0.9;
  animation: drawLine 520ms var(--ease-out) forwards;
}
.mark-line-1 { animation-delay: 1080ms; }
.mark-line-2 { animation-delay: 1220ms; }
.mark-line-3 { animation-delay: 1360ms; }
@keyframes drawLine { to { stroke-dashoffset: 0; } }

/* --- wordmark --- */
.splash-word {
  display: flex;
  gap: 0.12em;
  margin: 0;
  font-size: 48px;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-indent: 0.12em;
  color: #fff;
  text-shadow: 0 6px 40px rgba(99, 179, 237, 0.35);
}
.splash-word span {
  display: inline-block;
  opacity: 0;
  transform: translateY(26px) rotate(4deg);
  animation: letterIn 760ms var(--ease-spring) forwards;
}
.splash-word span:nth-child(1) { animation-delay: 560ms; }
.splash-word span:nth-child(2) { animation-delay: 640ms; }
.splash-word span:nth-child(3) { animation-delay: 720ms; }
.splash-word span:nth-child(4) { animation-delay: 800ms; }
.splash-word span:nth-child(5) { animation-delay: 880ms; }
.splash-word span:nth-child(6) { animation-delay: 960ms; }
.splash-word span:nth-child(7) { animation-delay: 1040ms; }
.splash-word span:nth-child(8) { animation-delay: 1120ms; }
@keyframes letterIn {
  to { opacity: 1; transform: none; }
}

.splash-name {
  margin: 0 0 10px;
  font-size: 42px;
  font-weight: 800;
  letter-spacing: 0.28em;
  text-indent: 0.28em;
  text-transform: uppercase;
  color: var(--navy);
  line-height: 1;
  opacity: 0;
  /* Kevin, 2026-09-07: the name fades in slowly — 2.2s, landing as the A finishes assembling. */
  animation: fadeUp 2200ms var(--ease-out) 1800ms forwards;
}

.splash-tagline {
  margin: 0;
  font-size: 24px; /* 18.75 + 28% — still sits under the 546px A */
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0;
  animation: fadeUp 1200ms var(--ease-out) 2900ms forwards;
}

.splash-rule {
  width: 0;
  height: 1px;
  margin: 22px 0 18px;
  background: linear-gradient(90deg, transparent, rgba(227, 66, 52, 0.55), transparent);
  animation: ruleGrow 900ms var(--ease-out) 2560ms forwards;
}
@keyframes ruleGrow { to { width: 420px; } }

.splash-byline {
  margin: 0;
  font-size: 16.2px; /* 13.5px + 20% */
  font-weight: 600;
  letter-spacing: 0.05em;
  color: var(--navy);
  opacity: 0;
  animation: fadeUp 760ms var(--ease-out) 2700ms forwards;
}

.splash-credential {
  margin: 6px 0 0;
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--muted);
  opacity: 0;
  animation: fadeUp 760ms var(--ease-out) 2840ms forwards;
}

.splash-loader {
  width: 190px;
  height: 3px;
  margin: 38px 0 14px;
  border-radius: 99px;
  background: var(--line);
  overflow: hidden;
  opacity: 0;
  animation: fadeUp 500ms var(--ease-out) 3000ms forwards;
}
.splash-loader-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 99px;
  background: linear-gradient(90deg, #d6452a, #e34234);
  /* Tracks welcome-sound.mp3 (starts 1000ms, ~6008ms long). Full at audio end. */
  animation: loaderFill 6000ms var(--ease-in-out) 1000ms forwards;
}
@keyframes loaderFill { to { width: 100%; } }

.splash-hint {
  margin: 0;
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(226, 238, 251, 0.55);
  opacity: 0;
  animation: hintPulse 2.6s ease-in-out 2300ms infinite;
}
@keyframes hintPulse { 0%,100% { opacity: 0.3; } 50% { opacity: 0.75; } }

.splash-foot {
  position: absolute;
  bottom: 26px;
  margin: 0;
  z-index: 2;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  opacity: 0;
  animation: fadeUp 700ms var(--ease-out) 4700ms forwards;
}
.splash-company {
  position: absolute;
  left: 28px;
  bottom: 22px;
  z-index: 2;
  width: 185px; /* 148px + 25% */
  height: auto;
  opacity: 0;
  /* Starts when the 4s assemble video finishes. */
  animation: fadeUp 700ms var(--ease-out) 4000ms forwards;
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   2 · VIEW TRANSITIONS
   ============================================================ */
.view-veil {
  position: fixed;
  inset: 0;
  z-index: 900;
  background: var(--bg);
  opacity: 0;
  pointer-events: none;
}
.view-veil.is-active {
  animation: veilSweep 520ms var(--ease-in-out) forwards;
}
@keyframes veilSweep {
  0%   { opacity: 0; }
  38%  { opacity: 1; }
  100% { opacity: 0; }
}

.app-shell, .writer { animation: none; }
.app-shell.view-enter { animation: viewEnter 520ms var(--ease-out) both; }
.writer.view-enter    { animation: viewEnter 520ms var(--ease-out) both; }
@keyframes viewEnter {
  from { opacity: 0; transform: translateY(10px) scale(0.994); }
  to   { opacity: 1; transform: none; }
}

/* boot-in of the app behind the splash */
.app-shell.boot-in > * { animation: paneIn 620ms var(--ease-out) both; }
.app-shell.boot-in > .app-banner { animation-delay: 0ms; }
.app-shell.boot-in > .picker     { animation-delay: 60ms; }
.app-shell.boot-in > .board      { animation-delay: 140ms; }
.app-shell.boot-in > .ready-pane { animation-delay: 220ms; }
.app-shell.boot-in > .app-footer { animation-delay: 280ms; }
@keyframes paneIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* ============================================================
   3 · SHELL POLISH
   ============================================================ */
.picker {
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%);
  box-shadow: inset -1px 0 0 var(--line);
}
.brand {
  position: relative;
  padding-bottom: 16px;
}
.brand::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(90deg, var(--blue), transparent);
  opacity: 0.35;
}

.count-chip { transition: transform var(--dur) var(--ease-spring), background var(--dur) var(--ease); }
.count-chip.bump { animation: chipBump 460ms var(--ease-spring); }
@keyframes chipBump {
  0% { transform: scale(1); }
  40% { transform: scale(1.28); }
  100% { transform: scale(1); }
}

/* --- student cards --- */
.student-card {
  transition: transform var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease),
              background var(--dur) var(--ease);
  animation: cardIn 460ms var(--ease-out) both;
}
.student-card:hover { transform: translateX(3px); box-shadow: var(--shadow-sm); }
.student-card:active { transform: translateX(3px) scale(0.988); }
.student-card.active {
  box-shadow: 0 2px 12px rgba(43, 108, 176, 0.16);
  transform: translateX(3px);
}
.student-card::before { transition: background var(--dur) var(--ease), width var(--dur) var(--ease); }
.student-card .mini-fill {
  transition: width 900ms var(--ease-out), background 400ms var(--ease);
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.student-list .student-card:nth-child(1) { animation-delay: 20ms; }
.student-list .student-card:nth-child(2) { animation-delay: 55ms; }
.student-list .student-card:nth-child(3) { animation-delay: 90ms; }
.student-list .student-card:nth-child(4) { animation-delay: 125ms; }
.student-list .student-card:nth-child(5) { animation-delay: 160ms; }
.student-list .student-card:nth-child(6) { animation-delay: 195ms; }
.student-list .student-card:nth-child(n+7) { animation-delay: 230ms; }

/* --- buttons --- */
button {
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
button:hover:not(:disabled) { cursor: pointer; }
button:active:not(:disabled) {
  transform: translateY(1px) scale(0.97);
}
.primary-btn, .merge-btn {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--blue-bright), var(--blue));
  box-shadow: 0 2px 10px rgba(43, 108, 176, 0.26);
}
.primary-btn:hover:not(:disabled), .merge-btn:hover:not(:disabled) {
  cursor: pointer;
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(43, 108, 176, 0.34);
}
.primary-btn:active:not(:disabled), .merge-btn:active:not(:disabled) {
  transform: translateY(0) scale(0.96);
}

.survey-panel button,
.uploads-panel button {
  cursor: pointer;
  border: 1px solid #c9d3e0;
  background: linear-gradient(180deg, #ffffff 0%, #eef2f7 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    0 3px 0 #c5ced8,
    0 5px 10px rgba(16, 32, 61, 0.12);
  transform: translateY(-1px);
}
.survey-panel button:hover:not(:disabled),
.uploads-panel button:hover:not(:disabled) {
  cursor: pointer;
  background: linear-gradient(180deg, #e8eef6 0%, #d5deea 100%);
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 3px 0 #b7c2d0,
    0 6px 10px rgba(16, 32, 61, 0.12);
}
.survey-panel button:active:not(:disabled),
.uploads-panel button:active:not(:disabled) {
  transform: translateY(2px) scale(0.98);
  box-shadow:
    inset 0 2px 3px rgba(16, 32, 61, 0.16),
    0 0 0 #c5ced8;
}
.survey-panel button.is-awaiting,
.uploads-panel button.is-awaiting,
#notifyTeamBtn.is-awaiting,
#transitionSendBtn.is-awaiting {
  background: linear-gradient(180deg, #ffe9b8 0%, #f0c56a 100%);
  border-color: #e0a53a;
  color: #7a4b08;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.55),
    0 3px 0 #c48a22,
    0 5px 10px rgba(180, 83, 9, 0.18);
}
.survey-panel button.is-awaiting:hover:not(:disabled),
.uploads-panel button.is-awaiting:hover:not(:disabled),
#notifyTeamBtn.is-awaiting:hover:not(:disabled),
#transitionSendBtn.is-awaiting:hover:not(:disabled) {
  background: linear-gradient(180deg, #f6d48a 0%, #e0a84a 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    0 3px 0 #b57c1c,
    0 6px 10px rgba(180, 83, 9, 0.18);
}
.survey-panel button.is-received,
.uploads-panel button.is-received,
.extractor-btn.is-received,
#notifyTeamBtn.is-received,
#transitionSendBtn.is-received {
  background: linear-gradient(180deg, #e8f6ee 0%, #cdead8 100%);
  border-color: #8fceab;
  color: var(--ok);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 3px 0 #7bb894,
    0 5px 10px rgba(31, 122, 77, 0.16);
}
@media (prefers-reduced-motion: reduce) {
  .survey-panel button,
  .uploads-panel button {
    transform: none;
    box-shadow: var(--shadow-sm);
  }
  .survey-panel button:hover:not(:disabled),
  .uploads-panel button:hover:not(:disabled),
  .survey-panel button:active:not(:disabled),
  .uploads-panel button:active:not(:disabled) {
    transform: none;
  }
}

.merge-btn.is-ready:not(:disabled) {
  overflow: visible;
  background: linear-gradient(180deg, #3cb87a 0%, #1f7a4d 100%);
  border-color: #17643e;
  color: #fff;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.42),
    0 6px 0 #145534,
    0 12px 18px rgba(31, 122, 77, 0.32);
  transform: translateY(-3px);
  animation: mergeReadyPop 420ms var(--ease-spring) 1;
}
.merge-btn.is-ready:hover:not(:disabled) {
  background: linear-gradient(180deg, #48c488 0%, #218a57 100%);
  transform: translateY(-4px);
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.5),
    0 7px 0 #145534,
    0 16px 22px rgba(31, 122, 77, 0.36);
}
.merge-btn.is-ready:active:not(:disabled) {
  transform: translateY(2px) scale(0.98);
  box-shadow:
    inset 0 2px 3px rgba(16, 32, 61, 0.18),
    0 0 0 #145534;
  animation: none;
}
@keyframes mergeReadyPop {
  0% {
    transform: translateY(0) scale(0.98);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 0.2),
      0 1px 0 #145534,
      0 2px 6px rgba(31, 122, 77, 0.12);
  }
  62% {
    transform: translateY(-5px) scale(1.03);
    box-shadow:
      inset 0 2px 0 rgba(255, 255, 255, 0.5),
      0 8px 0 #145534,
      0 18px 24px rgba(31, 122, 77, 0.38);
  }
  100% {
    transform: translateY(-3px) scale(1);
    box-shadow:
      inset 0 2px 0 rgba(255, 255, 255, 0.42),
      0 6px 0 #145534,
      0 12px 18px rgba(31, 122, 77, 0.32);
  }
}
@media (prefers-reduced-motion: reduce) {
  .merge-btn.is-ready { animation: none; }
}

/* ripple */
.ripple {
  position: absolute;
  border-radius: 50%;
  transform: scale(0);
  background: rgba(22, 48, 90, 0.18);
  pointer-events: none;
  animation: rippleOut 620ms var(--ease-out) forwards;
}
.primary-btn .ripple, .merge-btn .ripple, .danger-btn .ripple {
  background: rgba(255, 255, 255, 0.45);
}
@keyframes rippleOut { to { transform: scale(2.6); opacity: 0; } }

/* --- panels --- */
.panel {
  transition: box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}
.panel.reveal { animation: paneIn 520ms var(--ease-out) both; animation-delay: 80ms; }
.board-header { animation: paneIn 480ms var(--ease-out) both; }

.dropzone { transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform var(--dur) var(--ease-out); }
.dropzone.is-empty:hover { transform: translateY(-1px); }
.dropzone.drag-over {
  border-color: var(--blue) !important;
  background: var(--blue-soft) !important;
  transform: scale(1.005);
}
.file-card { animation: cardIn 420ms var(--ease-out) both; }
.file-card:nth-child(2) { animation-delay: 40ms; }
.file-card:nth-child(3) { animation-delay: 80ms; }
.file-card:nth-child(4) { animation-delay: 120ms; }
.file-card:nth-child(n+5) { animation-delay: 160ms; }

/* ============================================================
   4 · COMPLETION DIAL
   ============================================================ */
.dial-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 2px 0 18px;
  animation: paneIn 520ms var(--ease-out) both;
}
.dial {
  position: relative;
  width: 150px;
  height: 150px;
}
.dial svg {
  width: 100%; height: 100%;
  transform: rotate(-90deg);
  overflow: visible;
}
.dial-track { stroke: var(--line-soft); }
.dial-fill {
  stroke: url(#dialGrad);
  stroke-dasharray: 326.7;
  stroke-dashoffset: 326.7;
  transition: stroke-dashoffset 1100ms var(--ease-out), stroke 500ms var(--ease);
  filter: drop-shadow(0 2px 6px rgba(43, 108, 176, 0.28));
}
.dial.complete .dial-fill {
  stroke: url(#dialGradOk);
  filter: drop-shadow(0 2px 10px rgba(31, 122, 77, 0.4));
}
.dial.complete { animation: dialPop 620ms var(--ease-spring); }
@keyframes dialPop {
  0% { transform: scale(1); }
  45% { transform: scale(1.055); }
  100% { transform: scale(1); }
}
.dial-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
}
.dial-num {
  font-size: 34px;
  font-weight: 800;
  color: var(--navy);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.dial-num i { font-style: normal; font-size: 17px; font-weight: 700; color: var(--muted); margin-left: 1px; }
.dial.complete .dial-num { color: var(--ok); }
.dial-sub {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--faint);
}
.dial-caption {
  margin: 12px 0 0;
  /* Kevin, 2026-09-07: PROGRESS reads as a heading, not a footnote. */
  font-size: 17px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: center;
}
.dial-caption.is-ready { color: var(--ok); }

/* ============================================================
   5 · CHECKLIST + PROGRESS
   ============================================================ */
.progress-track { overflow: hidden; position: relative; }
.progress-fill {
  transition: width 900ms var(--ease-out), background 500ms var(--ease);
  position: relative;
  overflow: hidden;
}
.progress-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.55), transparent);
  transform: translateX(-100%);
  animation: shimmer 2.4s var(--ease-in-out) infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }
.progress-value { transition: color var(--dur) var(--ease); }

.ready-item {
  border-radius: var(--r-sm);
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease-out);
  animation: rowIn 380ms var(--ease-out) both;
}
.ready-item:hover { transform: translateX(2px); }
@keyframes rowIn {
  from { opacity: 0; transform: translateX(-6px); }
  to   { opacity: 1; transform: none; }
}
.ready-bar .ready-item:nth-child(1) { animation-delay: 20ms; }
.ready-bar .ready-item:nth-child(2) { animation-delay: 45ms; }
.ready-bar .ready-item:nth-child(3) { animation-delay: 70ms; }
.ready-bar .ready-item:nth-child(4) { animation-delay: 95ms; }
.ready-bar .ready-item:nth-child(5) { animation-delay: 120ms; }
.ready-bar .ready-item:nth-child(6) { animation-delay: 145ms; }
.ready-bar .ready-item:nth-child(n+7) { animation-delay: 170ms; }

.tick {
  transition: background var(--dur) var(--ease-spring),
              border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease-spring);
}
.tick.done { animation: tickPop 480ms var(--ease-spring); }
.tick.sent { animation: tickPop 480ms var(--ease-spring); }
@keyframes tickPop {
  0%   { transform: scale(0.4); }
  55%  { transform: scale(1.22); }
  100% { transform: scale(1); }
}
.tick.done::after { animation: tickDraw 300ms var(--ease-out) 90ms both; }
.required-tags-panel .ready-item.is-done {
  animation: tagDoneIn 420ms var(--ease-out);
}
@keyframes tagDoneIn {
  from { transform: scale(0.94); }
  to   { transform: none; }
}
@keyframes tickDraw {
  from { opacity: 0; transform: rotate(45deg) scale(0.4); }
  to   { opacity: 1; }
}

.ready-count { transition: color var(--dur) var(--ease); }
.full-checklist {
  animation: sectionIn 420ms var(--ease-out) both;
}
@keyframes sectionIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.check-row, .tests-given-row {
  border-radius: var(--r-sm);
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease-out);
}
.check-row:hover, .tests-given-row:hover { transform: translateX(2px); }

/* section progress meter injected by ui-shell.js */
.section-meter {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 2px 0 8px;
}
.section-meter-track {
  flex: 1;
  height: 4px;
  border-radius: 99px;
  background: var(--line-soft);
  overflow: hidden;
}
.section-meter-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 99px;
  background: linear-gradient(90deg, var(--blue-bright), var(--blue));
  transition: width 800ms var(--ease-out), background 400ms var(--ease);
}
.section-meter-fill.complete { background: linear-gradient(90deg, #2f9e69, var(--ok)); }
.section-meter-val {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  min-width: 34px;
  text-align: right;
}

/* overall checklist summary */
.checklist-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  margin-bottom: 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--sunken);
}
.checklist-summary .cs-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}
.checklist-summary .cs-val {
  font-size: 13px;
  font-weight: 800;
  color: var(--navy);
  font-variant-numeric: tabular-nums;
}

/* ---------- ready pane empty state ---------- */
.ready-pane { display: flex; flex-direction: column; }
.ready-pane > #readyPanel { flex: 0 0 auto; }
/* flex-shrink 0: with a student selected the checklist is taller than the pane
   and this details (overflow: hidden) otherwise shrinks to a 2px line, hiding
   Data Sources & Template entirely. */
.ready-pane > .setup-group { margin-top: auto; flex: 0 0 auto; }

.pane-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 190px;
  text-align: center;
  padding: 26px 18px;
}
.pane-empty-mark { width: 46px; height: 46px; color: var(--faint); }
.pane-empty-mark svg { width: 100%; height: 100%; animation: spinSlow 14s linear infinite; }
@keyframes spinSlow { to { transform: rotate(360deg); } }

.empty-board .empty-mark { animation: floaty 4.5s ease-in-out infinite; }
@keyframes floaty {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-7px); }
}
.empty-board { animation: paneIn 520ms var(--ease-out) both; }

/* ============================================================
   6 · WRITER
   ============================================================ */
.writer-bar {
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  box-shadow: 0 1px 0 var(--line), 0 4px 16px rgba(16, 32, 61, 0.05);
  position: sticky;
  top: 0;
  z-index: 10;
}
.writer-bar-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.25;
}
.writer-bar-sub {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--faint);
}
.writer-progress {
  height: 3px;
  background: var(--line-soft);
  position: sticky;
  top: 0;
  z-index: 9;
}
.writer-progress span {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--blue-bright), var(--blue));
  transition: width 700ms var(--ease-out), background 400ms var(--ease);
}
.writer-progress span.complete { background: linear-gradient(90deg, #2f9e69, var(--ok)); }

.container { animation: paneIn 520ms var(--ease-out) both; }
.section {
  animation: paneIn 480ms var(--ease-out) both;
}
.container .section:nth-of-type(1) { animation-delay: 40ms; }
.container .section:nth-of-type(2) { animation-delay: 80ms; }
.container .section:nth-of-type(3) { animation-delay: 120ms; }
.container .section:nth-of-type(4) { animation-delay: 160ms; }
.container .section:nth-of-type(5) { animation-delay: 200ms; }
.container .section:nth-of-type(n+6) { animation-delay: 240ms; }

textarea, input {
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.section.is-filled > label { color: var(--ok); }
.section.is-filled > label::after {
  content: " ✓";
  font-weight: 800;
}

.writer-foot {
  margin: 34px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--line-soft);
  text-align: center;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
}

/* ============================================================
   7 · TOAST
   ============================================================ */
.toast-stack {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 950;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 15px;
  border-radius: var(--r-md);
  background: var(--navy-deep);
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  box-shadow: var(--shadow-lg);
  animation: toastIn 420ms var(--ease-spring) both;
}
.toast.out { animation: toastOut 320ms var(--ease-in-out) both; }
.toast.ok::before   { content: "✓"; color: #7ee2ac; font-weight: 800; }
.toast.err::before  { content: "!"; color: #ffb4b4; font-weight: 800; }
@keyframes toastIn  { from { opacity: 0; transform: translateY(14px) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes toastOut { to { opacity: 0; transform: translateY(8px) scale(0.97); } }

/* ============================================================
   8 · STATUS LINES
   ============================================================ */
.status-line:not(:empty) { animation: rowIn 320ms var(--ease-out) both; }

/* ============================================================
   9 · REDUCED MOTION
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .splash { animation: splashAutoOut 1ms linear 4000ms forwards; }
  .splash-rule { width: 325px; }
  .splash-loader-fill { width: 100%; }
  .splash-logo-video { display: none !important; }
  .splash-logo-fallback { display: block !important; }
}

/* ============================================================
   10 · SAVING OVERLAY + BOOT ERROR
   ============================================================ */
.saving-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(6px);
}
.saving-overlay.hidden { display: none; }
.saving-card #savingOverlayWarn {
  max-width: 28rem;
  text-align: center;
  font-weight: 500;
  letter-spacing: 0;
  font-size: 14px;
}
.saving-card #savingOverlayActions { margin-top: 4px; }
.saving-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 28px 36px;
  border-radius: var(--r-md);
  background: #fff;
  box-shadow: var(--shadow-lg);
  color: var(--navy);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.saving-card p { margin: 0; }
.saving-spinner {
  width: 28px;
  height: 28px;
  border: 3px solid var(--line);
  border-top-color: var(--navy);
  border-radius: 50%;
  animation: savingSpin 700ms linear infinite;
}
@keyframes savingSpin { to { transform: rotate(360deg); } }

.boot-error {
  position: fixed;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%) translateY(14px);
  z-index: 1100;
  max-width: 76vw;
  padding: 10px 16px;
  border-radius: var(--r-md);
  background: #7f1d1d;
  color: #fff;
  font-size: 12.5px;
  font-weight: 600;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease-out);
}
.boot-error.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* Kevin 2026-09-19 home: caseload-first, house buttons, 10s toast */
#home-view[data-home-stage="caseload"] .board,
#home-view[data-home-stage="caseload"] .ready-pane,
#home-view[data-home-stage="template"] .board,
#home-view[data-home-stage="template"] .ready-pane {
  pointer-events: none;
  opacity: 0.38;
  filter: grayscale(0.15);
}
#home-view[data-home-stage="caseload"] .home-stage-template,
#home-view[data-home-stage="caseload"] .home-stage-uploads { display: none; }
#home-view[data-home-stage="template"] .home-stage-uploads { display: none; }
#home-view[data-home-stage="ready"] .board,
#home-view[data-home-stage="ready"] .ready-pane {
  pointer-events: auto;
  opacity: 1;
  filter: none;
}
.caseload-title-row { justify-content: center; text-align: center; }
.caseload-title-row h3 { width: 100%; text-align: center; }
.student-select-option::after,
.student-select-tools button::after { content: none !important; }
.report-built-label {
  margin: 0 0 8px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--ok, #1f7a4d);
}
#homeDetagBtn.is-built,
button.house-btn.is-built,
.primary-btn.is-built,
.merge-btn.is-built {
  background: var(--al-done, #2F62B5) !important;
  border-color: var(--al-done, #2F62B5) !important;
  color: #fff !important;
}
.house-btn,
.primary-btn.house-btn,
.merge-btn.house-btn,
.compose-btn.house-btn,
#pickCaseloadBtn,
#pickTemplateBtn,
#useCaseloadDriveBtn,
#useTemplateDriveBtn,
#uploadTemplateBtn,
#homeDetagBtn,
#mergeBtn,
#reportSaveBtn,
#composeNarrativesBtn {
  min-height: 44px;
  height: 44px;
  width: 100%;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 700;
}
.home-merge-dock {
  margin-top: auto;
  padding: 16px 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Kevin 2026-09-19: bottom-right is MERGE only — no Word/Save-as, no Doc link bar.
   display:none !important so house-btn / inline-flex rules cannot paint them. */
#homeMergeDock #reportExportRow,
#homeMergeDock #reportExportStatus,
#homeMergeDock #reportSaveBtn,
#homeMergeDock #reportExportFormat,
#homeMergeDock > *:not(#mergeBtn),
#mergeDocBar,
#mergeDocEmpty,
#mergeDocLink,
#copyMergeDocBtn,
#microsoftBox,
#microsoftCodeRow,
#microsoftSignInBtn,
#microsoftSignOutBtn,
#saveMicrosoftAppIdBtn,
#microsoftAppId,
#microsoftStatus,
#microsoftCode,
#microsoftCodeLink,
#setupGroup,
#checklistHover,
#checklistToggle,
#readyEmpty {
  display: none !important;
  visibility: hidden !important;
}
.ready-pane {
  display: flex;
  flex-direction: column;
}
.house-save-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.house-save-row .report-export-type {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  margin: 0;
}
.house-save-row #reportExportFormat,
.house-save-row #reportSaveBtn {
  height: 44px;
  min-height: 44px;
  width: 100%;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 700;
  box-sizing: border-box;
}
.house-save-row #reportExportFormat {
  appearance: none;
  -webkit-appearance: none;
  padding: 0 12px;
  line-height: 44px;
}
.house-save-row #reportSaveBtn { flex: 0 0 38%; }
#homeComposePanel .muted,
#homeComposePanel .obs-home-preview,
#homeComposePanel .status-line,
#homeDiscussionPanel .muted,
#homeDiscussionPanel .obs-home-preview,
#homeDiscussionPanel .status-line,
#homeGraphPanel .muted,
#homeGraphPanel .obs-home-preview,
#homeGraphPanel .status-line,
#homeSummaryPanel .muted,
#homeSummaryPanel .obs-home-preview,
#homeSummaryPanel .status-line,
#homePolishPanel .muted,
#homePolishPanel .obs-home-preview,
#homePolishPanel .status-line,
#homeSignPanel .muted,
#homeSignPanel .obs-home-preview,
#homeSignPanel .status-line,
#homeInsertImagesPanel .muted,
#homeInsertImagesPanel .status-line,
#homeFinishPanel > p.muted,
#finishPipelinePanel .muted,
#homeMergeDock .status-line,
#composeGateList {
  display: none !important;
}
.home-toast {
  position: fixed;
  left: 50%;
  bottom: 72px;
  transform: translateX(-50%);
  z-index: 1200;
  max-width: 72vw;
  padding: 10px 16px;
  border-radius: 8px;
  background: #7f1d1d;
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  box-shadow: var(--shadow-lg);
}
.home-toast.hidden { display: none !important; }
.file-card .file-icon {
  width: 42px;
  height: 48px;
  margin: 8px auto;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.04em;
}
.file-card .file-icon.is-pdf { background: #fdeeee; color: #9d2235; }
.file-card .file-icon.is-image { background: #e8f6ee; color: #1f7a4d; }
.file-card .file-kind.house-name { font-weight: 700; }

/* Kevin, 2026-10-30: "i liked the splash better on the white background
   square" - the opening logo keeps its light card, as it always was. */

