/* ==========================================================================
   Apply Hub — Soft Sun design system
   One token set, one type scale, one book. Replaces the four stacked
   generations that used to live in this file and in base.html's <style>.
   ========================================================================== */

/* --- 1. Tokens ---------------------------------------------------------- */

:root {
  /* Surfaces & ink */
  --bg: #fff8ee;
  --bg-tint: #fdf2e2;
  --card: #ffffff;
  --card-soft: #faefde;
  --ink: #221912;
  --ink-2: #4d3d31;
  --ink-3: #8a7868;
  --ink-4: #b7a99a;
  --rule: #f0e5d3;
  --rule-2: #faefde;
  --rule-strong: #e4d4bd;

  /* Accents */
  --coral: #f37c5f;
  --coral-2: #ffe2d5;
  --coral-ink: #c24a2a;
  --sun: #ffc857;
  --sun-2: #fff1cc;
  --mint: #87c7a4;
  --mint-2: #dcefe3;
  --sky: #7fb7e0;
  --sky-2: #dceef8;
  --lilac: #b6a4d6;
  --lilac-2: #ece3f8;

  /* Paper (book surfaces) */
  --leaf: #fffdf7;
  --leaf-edge: #efe2cd;


  /* Type scale — nothing in this product is larger than --text-3xl. */
  --text-2xs: 11px;
  --text-xs: 12px;
  --text-sm: 13px;
  --text-base: 14px;
  --text-md: 16px;
  --text-lg: 20px;
  --text-xl: 26px;
  --text-2xl: 34px;
  --text-3xl: 44px;

  --leading-tight: 1.18;
  --leading-snug: 1.35;
  --leading: 1.55;
  --measure: 62ch;

  --font-ui: "Outfit", "Vazirmatn", system-ui, -apple-system, sans-serif;
  --font-display: "Fraunces", "Vazirmatn", Georgia, serif;

  /* Space — 4px base */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Radius */
  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-pill: 999px;

  /* Elevation */
  --shadow-1: 0 1px 2px rgba(34, 25, 18, .06);
  --shadow-2: 0 8px 24px -12px rgba(80, 52, 28, .28);
  --shadow-3: 0 20px 48px -24px rgba(80, 52, 28, .36);
  --shadow-accent: 0 12px 28px -16px rgba(243, 124, 95, .75);

  /* Motion */
  --ease-page: cubic-bezier(.22, .61, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.4, .64, 1);

  /* Back-compat aliases. Older rules and templates still name these. */
  --bg-color: var(--bg);
  --surface: var(--card);
  --surface-soft: var(--card-soft);
  --text-heading: var(--ink);
  --text-body: var(--ink-2);
  --text-muted-warm: var(--ink-3);
  --primary: var(--coral);
  --primary-hover: var(--coral-ink);
  --primary-soft: var(--coral-2);
  --mint-soft: var(--mint-2);
  --sky-soft: var(--sky-2);
  --lilac-soft: var(--lilac-2);
  --sun-soft: var(--sun-2);
  --border-radii: var(--radius-lg);
  --shadow-soft: var(--shadow-2);
  --shadow-hover: var(--shadow-3);
  --shadow-primary: var(--shadow-accent);
  --v2-bg: var(--bg);
  --v2-card: var(--card);
  --v2-ink: var(--ink);
  --v2-ink-2: var(--ink-2);
  --v2-ink-3: var(--ink-3);
  --v2-ink-4: var(--ink-4);
  --v2-rule: var(--rule);
  --v2-rule-2: var(--rule-2);
  --v2-coral: var(--coral);
  --v2-coral-2: var(--coral-2);
  --v2-coral-ink: var(--coral-ink);
  --v2-sun: var(--sun);
  --v2-sun-2: var(--sun-2);
  --v2-mint: var(--mint);
  --v2-mint-2: var(--mint-2);
  --v2-sky: var(--sky);
  --v2-sky-2: var(--sky-2);
  --v2-lilac: var(--lilac);
  --v2-lilac-2: var(--lilac-2);
}

html[data-theme="dark"] {
  --bg: #17120e;
  --bg-tint: #1d1712;
  --card: #221b15;
  --card-soft: #2a211a;
  --ink: #f7efe4;
  --ink-2: #ddcfbe;
  --ink-3: #ab9884;
  --ink-4: #7d6c5c;
  --rule: #33291f;
  --rule-2: #2a211a;
  --rule-strong: #3f3326;

  --coral: #ff9678;
  --coral-2: #46271e;
  --coral-ink: #ffb9a3;
  --sun: #ffd071;
  --sun-2: #453619;
  --mint: #9ad6b6;
  --mint-2: #22392d;
  --sky: #97c7ea;
  --sky-2: #1f3242;
  --lilac: #c6b7e2;
  --lilac-2: #2f2740;

  --leaf: #241d17;
  --leaf-edge: #3a2f24;


  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 8px 24px -12px rgba(0, 0, 0, .6);
  --shadow-3: 0 20px 48px -24px rgba(0, 0, 0, .7);
  --shadow-accent: 0 12px 28px -16px rgba(255, 150, 120, .45);
}

/* --- 2. Base ------------------------------------------------------------ */

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading);
  margin: 0;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

html[lang="ar"] body,
html[lang="fa"] body { font-family: "Noto Naskh Arabic", "Vazirmatn", system-ui, sans-serif; }

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 600;
  line-height: var(--leading-snug);
  margin: 0 0 var(--space-3);
}

h1, .h1 { font-size: var(--text-2xl); line-height: var(--leading-tight); letter-spacing: -.015em; }
h2, .h2 { font-size: var(--text-xl); letter-spacing: -.01em; }
h3, .h3 { font-size: var(--text-lg); }
h4, .h4 { font-size: var(--text-md); }
h5, .h5 { font-size: var(--text-base); }
h6, .h6 { font-size: var(--text-sm); }

/* Bootstrap's display classes top out at 80px. Cap them to our ceiling. */
.display-1, .display-2, .display-3 { font-size: var(--text-3xl); font-family: var(--font-display); line-height: var(--leading-tight); }
.display-4, .display-5, .display-6 { font-size: var(--text-2xl); font-family: var(--font-display); line-height: var(--leading-tight); }

p { margin: 0 0 var(--space-4); }
p, li { max-width: var(--measure); }
.lead { font-size: var(--text-md); color: var(--ink-2); line-height: var(--leading); }
small, .small { font-size: var(--text-xs); }

a { color: var(--coral-ink); text-decoration: none; }
a:hover { color: var(--coral); text-decoration: underline; }

hr { border: 0; border-top: 1px solid var(--rule); opacity: 1; margin: var(--space-5) 0; }

code, pre, kbd, samp { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--text-xs); }
pre { background: var(--card-soft); border: 1px solid var(--rule); border-radius: var(--radius); padding: var(--space-4); overflow-x: auto; }

::selection { background: var(--coral-2); color: var(--coral-ink); }

:focus-visible { outline: 2px solid var(--coral); outline-offset: 2px; border-radius: var(--radius-sm); }

.text-muted, .text-secondary { color: var(--ink-3) !important; }
.text-body { color: var(--ink-2) !important; }
.bg-light, .bg-white { background: var(--card) !important; }

.text-truncate-3 {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.measure { max-width: var(--measure); }

/* --- 3. Bootstrap components, restyled ---------------------------------- */

.card {
  background: var(--card) !important;
  border: 1px solid var(--rule) !important;
  border-radius: var(--radius-lg) !important;
  box-shadow: var(--shadow-1);
  color: var(--ink-2);
}

.card-header, .card-footer {
  background: transparent !important;
  border-color: var(--rule) !important;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
}

.card-title { font-size: var(--text-md); }
.card-body { padding: var(--space-5); }

.btn {
  border-radius: var(--radius-pill);
  font-size: var(--text-sm);
  font-weight: 600;
  padding: var(--space-2) var(--space-4);
  transition: transform .15s var(--ease-page), box-shadow .2s var(--ease-page), background-color .2s;
}
.btn:active { transform: translateY(1px); }
.btn-lg { font-size: var(--text-base); padding: var(--space-3) var(--space-5); }
.btn-sm { font-size: var(--text-xs); padding: var(--space-1) var(--space-3); }

.btn-primary {
  background: var(--coral);
  border-color: var(--coral);
  color: #fff;
  box-shadow: var(--shadow-accent);
}
.btn-primary:hover, .btn-primary:focus {
  background: var(--coral-ink);
  border-color: var(--coral-ink);
  color: #fff;
}

.btn-outline-primary { border-color: var(--rule-strong); color: var(--coral-ink); background: transparent; }
.btn-outline-primary:hover, .btn-outline-primary:focus { background: var(--coral-2); border-color: var(--coral); color: var(--coral-ink); }

.btn-secondary, .btn-outline-secondary { border-color: var(--rule-strong); color: var(--ink-2); background: transparent; }
.btn-secondary:hover, .btn-outline-secondary:hover { background: var(--card-soft); color: var(--ink); border-color: var(--rule-strong); }

.btn-link { color: var(--coral-ink); }

.form-control, .form-select, .form-check-input {
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink);
  font-size: var(--text-sm);
  padding: var(--space-2) var(--space-3);
}
.form-control::placeholder { color: var(--ink-4); }
.form-control:focus, .form-select:focus {
  background: var(--card);
  border-color: var(--coral);
  box-shadow: 0 0 0 3px var(--coral-2);
  color: var(--ink);
}
.form-check-input:checked { background-color: var(--coral); border-color: var(--coral); }
.form-label { color: var(--ink-2); font-size: var(--text-xs); font-weight: 600; margin-bottom: var(--space-1); }
.form-text { color: var(--ink-3); font-size: var(--text-xs); }
.input-group-text { background: var(--card-soft); border-color: var(--rule-strong); color: var(--ink-3); font-size: var(--text-xs); }

.table { color: var(--ink-2); font-size: var(--text-sm); --bs-table-bg: transparent; }
.table > thead th {
  border-bottom: 1px solid var(--rule-strong);
  color: var(--ink-3);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  padding: var(--space-2) var(--space-3);
}
.table > tbody td { border-color: var(--rule); padding: var(--space-3); vertical-align: middle; }
.table-hover > tbody > tr:hover > * { background: var(--card-soft); color: var(--ink); }

.badge { border-radius: var(--radius-pill); font-size: var(--text-2xs); font-weight: 600; padding: .34em .75em; }
.bg-primary { background: var(--coral) !important; }
.bg-success { background: var(--mint) !important; color: var(--ink) !important; }
.bg-warning { background: var(--sun) !important; color: var(--ink) !important; }
.bg-info { background: var(--sky) !important; color: var(--ink) !important; }

.alert {
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  padding: var(--space-3) var(--space-4);
}
.alert-success { background: var(--mint-2); border-color: var(--mint); color: var(--ink); }
.alert-danger { background: var(--coral-2); border-color: var(--coral); color: var(--coral-ink); }
.alert-warning { background: var(--sun-2); border-color: var(--sun); color: var(--ink); }
.alert-info { background: var(--sky-2); border-color: var(--sky); color: var(--ink); }

.modal-content, .dropdown-menu, .offcanvas {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  color: var(--ink-2);
  box-shadow: var(--shadow-3);
}
.dropdown-item { color: var(--ink-2); font-size: var(--text-sm); }
.dropdown-item:hover { background: var(--card-soft); color: var(--ink); }

.list-group-item { background: var(--card); border-color: var(--rule); color: var(--ink-2); font-size: var(--text-sm); }

.nav-tabs { border-bottom: 1px solid var(--rule); }
.nav-tabs .nav-link { border: 0; color: var(--ink-3); font-size: var(--text-sm); font-weight: 600; }
.nav-tabs .nav-link.active { background: transparent; border-bottom: 2px solid var(--coral); color: var(--ink); }

.breadcrumb { font-size: var(--text-xs); }
.breadcrumb-item + .breadcrumb-item::before { color: var(--ink-4); }

.page-link { background: var(--card); border-color: var(--rule); color: var(--ink-2); font-size: var(--text-sm); }
.page-item.active .page-link { background: var(--coral); border-color: var(--coral); color: #fff; }

.accordion-item { background: var(--card); border: 1px solid var(--rule); border-radius: var(--radius-lg); margin-bottom: var(--space-2); overflow: hidden; }
.accordion-button { background: var(--card); color: var(--ink); font-size: var(--text-sm); font-weight: 600; }
.accordion-button:not(.collapsed) { background: var(--coral-2); color: var(--coral-ink); box-shadow: none; }
.accordion-button:focus { border-color: var(--coral); box-shadow: 0 0 0 3px var(--coral-2); }

.progress { background: var(--rule-2); border-radius: var(--radius-pill); height: 6px; }
.progress-bar { background: var(--coral); }

.tooltip-inner { background: var(--ink); border-radius: var(--radius); font-size: var(--text-xs); }

/* --- 4. The book -------------------------------------------------------- */

/* 4b. Spine + page edges. Pure CSS, always present, no JS. */
.book-frame {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}

.book-frame::before,
.book-frame::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 10px;
  background:
    repeating-linear-gradient(90deg,
      var(--leaf-edge) 0 1px,
      transparent 1px 3px);
  opacity: .5;
}
.book-frame::before { left: 0; }
.book-frame::after { right: 0; }

/* 4c. Public two-page spread. */
.book-spread {
  background: var(--bg-tint);
  min-height: 100vh;
  padding: var(--space-5) var(--space-4);
}

.book-spread__book {
  background: var(--leaf);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  margin: 0 auto;
  max-width: 1180px;
  position: relative;
  overflow: hidden;
}

/* The gutter shadow down the middle of the spread. */
.book-spread__book::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 46px;
  margin-left: -23px;
  background: linear-gradient(90deg,
    transparent,
    rgba(138, 120, 104, .10) 42%,
    rgba(138, 120, 104, .16) 50%,
    rgba(138, 120, 104, .10) 58%,
    transparent);
  pointer-events: none;
  z-index: 2;
}

.book-spread__leaves {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.book-spread__leaf { padding: var(--space-7) var(--space-6); }
.book-spread__leaf--full { grid-column: 1 / -1; }

.book-spread__foot {
  border-top: 1px solid var(--rule);
  color: var(--ink-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  font-size: var(--text-2xs);
  justify-content: space-between;
  padding: var(--space-3) var(--space-6);
}

@media (max-width: 900px) {
  .book-spread__leaves { grid-template-columns: 1fr; }
  .book-spread__book::before { display: none; }
  .book-spread__leaf { padding: var(--space-6) var(--space-5); }
}

/* --- 5. App shell ------------------------------------------------------- */

.v2-shell {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading);
  min-height: 100vh;
  position: relative;
  z-index: 2;
}

.v2-shell[dir="rtl"] { grid-template-columns: minmax(0, 1fr) 240px; }
.v2-shell[lang="ar"], .v2-shell[lang="fa"] { font-family: "Noto Naskh Arabic", "Vazirmatn", system-ui, sans-serif; }

.v2-side {
  background: var(--card);
  border-right: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-height: 100vh;
  padding: var(--space-5) var(--space-4);
}
.v2-shell[dir="rtl"] .v2-side { border-left: 1px solid var(--rule); border-right: 0; order: 2; }

.v2-brand {
  align-items: center;
  color: var(--ink);
  display: flex;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
  text-decoration: none;
}
.v2-brand:hover { text-decoration: none; }

.v2-mark {
  align-items: center;
  background: linear-gradient(140deg, var(--coral), var(--coral-ink));
  border-radius: var(--radius);
  color: #fff;
  display: flex;
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  height: 30px;
  justify-content: center;
  width: 30px;
}

.v2-brand-name { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 600; }
.v2-brand-name em { color: var(--coral); font-style: normal; }

.v2-nav { display: flex; flex-direction: column; gap: 2px; }

.v2-nav-label {
  color: var(--ink-4);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .1em;
  margin: var(--space-4) 0 var(--space-1);
  padding: 0 var(--space-2);
  text-transform: uppercase;
}

.v2-nav-item {
  align-items: center;
  border-radius: var(--radius);
  color: var(--ink-2);
  display: flex;
  font-size: var(--text-sm);
  gap: var(--space-2);
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
  text-decoration: none;
  transition: background-color .15s, color .15s;
}
.v2-nav-item > span { align-items: center; display: flex; gap: var(--space-2); min-width: 0; }
.v2-nav-item i { color: var(--ink-3); font-size: var(--text-md); }
.v2-nav-item:hover { background: var(--card-soft); color: var(--ink); text-decoration: none; }
.v2-nav-item.active { background: var(--coral-2); color: var(--coral-ink); font-weight: 600; }
.v2-nav-item.active i { color: var(--coral-ink); }

.v2-count {
  background: var(--rule-2);
  border-radius: var(--radius-pill);
  color: var(--ink-3);
  font-size: var(--text-2xs);
  font-weight: 600;
  padding: 1px var(--space-2);
}

.v2-cycle { margin-top: var(--space-1); }
.v2-dot { background: var(--mint); border-radius: 50%; flex: none; height: 7px; width: 7px; }

.v2-side-foot {
  align-items: center;
  border-top: 1px solid var(--rule);
  display: flex;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-4);
}

.v2-avatar {
  align-items: center;
  background: linear-gradient(140deg, var(--sun), var(--coral));
  border-radius: 50%;
  color: #fff;
  display: flex;
  flex: none;
  font-size: var(--text-sm);
  font-weight: 600;
  height: 30px;
  justify-content: center;
  width: 30px;
}

.v2-side-user { min-width: 0; }
.v2-side-name { color: var(--ink); font-size: var(--text-xs); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.v2-side-user a, .v2-link-button { color: var(--ink-3); font-size: var(--text-2xs); }
.v2-link-button { background: none; border: 0; cursor: pointer; padding: 0; }
.v2-link-button:hover { color: var(--coral-ink); }

.v2-main { display: flex; flex-direction: column; min-width: 0; }

.v2-top {
  align-items: center;
  background: var(--bg);
  border-bottom: 1px solid var(--rule);
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-6);
  position: sticky;
  top: 0;
  z-index: 20;
}

.v2-search {
  align-items: center;
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-pill);
  display: flex;
  flex: 1;
  gap: var(--space-2);
  min-width: 0;
  padding: var(--space-2) var(--space-4);
}
.v2-search i { color: var(--ink-4); }
.v2-search input {
  background: none;
  border: 0;
  color: var(--ink);
  flex: 1;
  font-family: inherit;
  font-size: var(--text-sm);
  min-width: 0;
  outline: none;
}
.v2-search input::placeholder { color: var(--ink-4); }
.v2-search:focus-within { border-color: var(--coral); box-shadow: 0 0 0 3px var(--coral-2); }

.v2-language-form { margin-left: auto; }
.v2-shell[dir="rtl"] .v2-language-form { margin-left: 0; margin-right: auto; }
.v2-language-form .form-select { font-size: var(--text-xs); padding: var(--space-1) var(--space-5) var(--space-1) var(--space-2); }

.v2-btn {
  align-items: center;
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  display: inline-flex;
  flex: none;
  font-size: var(--text-sm);
  font-weight: 600;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  text-decoration: none;
  transition: transform .15s var(--ease-page), box-shadow .2s;
}
.v2-btn:hover { text-decoration: none; transform: translateY(-1px); }
.v2-btn.coral { background: var(--coral); border-color: var(--coral); color: #fff; box-shadow: var(--shadow-accent); }
.v2-btn.coral:hover { background: var(--coral-ink); border-color: var(--coral-ink); color: #fff; }

.v2-content { flex: 1; padding: var(--space-6) var(--space-6) var(--space-8); }
.v2-content > .container, .v2-content > .container-fluid { padding-left: 0; padding-right: 0; max-width: none; }

/* --- 6. Page furniture -------------------------------------------------- */

.v2-page-heading { margin-bottom: var(--space-5); }

.v2-eyebrow, .soft-eyebrow {
  color: var(--coral-ink);
  font-size: var(--text-2xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
}
html[dir="rtl"] .v2-eyebrow, html[dir="rtl"] .soft-eyebrow { letter-spacing: 0; text-transform: none; }

.v2-title, .soft-hero h1 {
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 44px);
  letter-spacing: -.02em;
  line-height: var(--leading-tight);
}

.soft-hero {
  background: linear-gradient(140deg, var(--card) 0%, var(--card-soft) 100%);
  border: 1px solid var(--rule);
  border-radius: var(--radius-xl);
  overflow: hidden;
  padding: var(--space-7) var(--space-6);
  position: relative;
}
.soft-hero::after {
  content: "";
  position: absolute;
  top: -70px;
  right: -70px;
  width: 220px;
  height: 220px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--sun-2), transparent 68%);
  pointer-events: none;
}
html[dir="rtl"] .soft-hero::after { right: auto; left: -70px; }
.soft-hero .lead { font-size: var(--text-md); max-width: 54ch; }

.soft-stat, .v2-stat {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-4);
}
.soft-stat strong, .v2-stat strong { color: var(--ink); font-family: var(--font-display); font-size: var(--text-xl); line-height: 1; }
.soft-stat span, .v2-stat span { color: var(--ink-3); font-size: var(--text-xs); }

.soft-feature-card, .v2-action-card, .v2-filter-card, .v2-profile-card, .professor-card {
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--space-5);
  transition: transform .2s var(--ease-page), box-shadow .2s var(--ease-page);
}
.soft-feature-card:hover, .v2-action-card:hover, .professor-card:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }
.soft-feature-card p, .professor-card p { color: var(--ink-3); font-size: var(--text-sm); }

.soft-orb {
  align-items: center;
  background: linear-gradient(140deg, var(--coral), var(--sun));
  border-radius: var(--radius);
  color: #fff;
  display: flex;
  font-size: var(--text-md);
  height: 36px;
  justify-content: center;
  margin-bottom: var(--space-3);
  width: 36px;
}

.professor-avatar, .detail-avatar {
  align-items: center;
  background: linear-gradient(140deg, var(--sky), var(--lilac));
  border-radius: 50%;
  color: #fff;
  display: flex;
  font-weight: 600;
  justify-content: center;
}
.professor-avatar { font-size: var(--text-sm); height: 36px; width: 36px; }
.detail-avatar { font-size: var(--text-xl); height: 64px; width: 64px; }

.v2-pill, .badge.v2-pill {
  align-items: center;
  background: var(--rule-2);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  display: inline-flex;
  font-size: var(--text-2xs);
  font-weight: 600;
  gap: var(--space-1);
  padding: 2px var(--space-2);
}
.v2-pill.coral { background: var(--coral-2); color: var(--coral-ink); }
.v2-pill.mint { background: var(--mint-2); color: #276b4a; }
.v2-pill.sun { background: var(--sun-2); color: #8a6512; }
.v2-pill.sky { background: var(--sky-2); color: #1f5d8a; }
.v2-pill.lilac { background: var(--lilac-2); color: #5b4585; }
.v2-pill.solid { background: var(--coral); color: #fff; }
html[data-theme="dark"] .v2-pill.mint { color: var(--mint); }
html[data-theme="dark"] .v2-pill.sun { color: var(--sun); }
html[data-theme="dark"] .v2-pill.sky { color: var(--sky); }
html[data-theme="dark"] .v2-pill.lilac { color: var(--lilac); }

.v2-filter-card .form-check { padding-left: 1.6em; }
html[dir="rtl"] .v2-filter-card .form-check { padding-left: 0; padding-right: 1.6em; }

/* Program catalog — now on real tokens instead of raw --bs-* and hex. */
.program-beta-banner {
  background: var(--sun-2);
  border: 1px solid var(--sun);
  border-radius: var(--radius-lg);
  color: var(--ink);
  font-size: var(--text-sm);
  padding: var(--space-3) var(--space-4);
}
.program-card, .department-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  height: 100%;
  transition: transform .2s var(--ease-page), box-shadow .2s var(--ease-page);
}
.program-card:hover, .department-card:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }
.program-card-facts dt { color: var(--ink-3); font-size: var(--text-2xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
.program-card-facts dd { color: var(--ink-2); font-size: var(--text-sm); margin-bottom: var(--space-2); }
.program-completeness { background: var(--rule-2); border-radius: var(--radius-pill); height: 5px; overflow: hidden; }
.program-completeness > span { background: var(--mint); display: block; height: 100%; }
.program-filter-section { border-bottom: 1px solid var(--rule); padding-bottom: var(--space-3); margin-bottom: var(--space-3); }
.program-source { color: var(--ink-3); font-size: var(--text-xs); }
.program-missing { color: var(--ink-4); font-style: italic; }
.university-crest {
  align-items: center;
  background: var(--card-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  color: var(--ink-3);
  display: flex;
  font-weight: 600;
  height: 40px;
  justify-content: center;
  width: 40px;
}

/* --- 7. Auth & public layouts ------------------------------------------- */

.auth-page {
  align-items: center;
  background:
    radial-gradient(900px 420px at 12% -8%, var(--sun-2), transparent 62%),
    radial-gradient(760px 420px at 92% 108%, var(--coral-2), transparent 62%),
    var(--bg);
  display: flex;
  justify-content: center;
  min-height: 100vh;
  padding: var(--space-6) var(--space-4);
}

.auth-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-3);
  max-width: 420px;
  padding: var(--space-7) var(--space-6);
  width: 100%;
}
.auth-card h1 { font-size: var(--text-xl); }
.auth-card .form-control { padding: var(--space-3); }

.auth-brand {
  align-items: center;
  color: var(--ink);
  display: inline-flex;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
  text-decoration: none;
}
.auth-foot { color: var(--ink-3); font-size: var(--text-xs); margin-top: var(--space-5); text-align: center; }

.public-nav {
  align-items: center;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
  margin: 0 auto var(--space-5);
  max-width: 1180px;
  padding: 0 var(--space-2);
}
.public-nav__links { align-items: center; display: flex; gap: var(--space-4); }
.public-nav__links a { color: var(--ink-2); font-size: var(--text-sm); font-weight: 600; }

/* --- 8. Utilities & motion ---------------------------------------------- */

.skeleton {
  background: linear-gradient(90deg, var(--rule-2) 25%, var(--card-soft) 37%, var(--rule-2) 63%);
  background-size: 400% 100%;
  animation: skeleton-shimmer 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
@keyframes skeleton-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

.toast-stack { bottom: var(--space-5); position: fixed; right: var(--space-5); z-index: 1080; }
html[dir="rtl"] .toast-stack { left: var(--space-5); right: auto; }

.animate-on-load { animation: fadeSlideUp .45s var(--ease-page) both; }
@keyframes fadeSlideUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

#cookie-banner {
  background: var(--card) !important;
  border: 1px solid var(--rule) !important;
  border-radius: var(--radius-lg) !important;
  box-shadow: var(--shadow-3);
  font-size: var(--text-sm);
}

footer { color: var(--ink-3); font-size: var(--text-xs); }

body.protect-professor-data { -webkit-user-select: none; user-select: none; }
body.protect-professor-data .copy-allowed { -webkit-user-select: text; user-select: text; }

/* --- 9. Responsive ------------------------------------------------------ */

@media (max-width: 900px) {
  .v2-shell, .v2-shell[dir="rtl"] { grid-template-columns: 1fr; }
  .v2-side {
    border-bottom: 1px solid var(--rule);
    border-right: 0;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--space-2);
    min-height: 0;
    overflow-x: auto;
    padding: var(--space-3) var(--space-4);
  }
  .v2-shell[dir="rtl"] .v2-side { border-left: 0; order: 0; }
  .v2-brand { margin-bottom: 0; }
  .v2-nav { flex-direction: row; flex-wrap: nowrap; }
  .v2-nav-label, .v2-side-foot, .v2-cycle { display: none; }
  .v2-nav-item { padding: var(--space-1) var(--space-2); white-space: nowrap; }
  .v2-top { padding: var(--space-3) var(--space-4); }
  .v2-content { padding: var(--space-5) var(--space-4) var(--space-7); }
  .book-frame { display: none; }
}

@media (max-width: 575.98px) {
  .v2-top { flex-wrap: wrap; }
  .v2-search { order: 3; width: 100%; flex-basis: 100%; }
  .soft-hero { padding: var(--space-6) var(--space-4); }
  .auth-card { padding: var(--space-6) var(--space-5); }
}

/* --- 10. Reduced motion ------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- 11. Paper-plane scene ---------------------------------------------- */
/* Timeline is 8.2s. Static default (no JS, or reduced motion) renders the
   final happy frame, so the story still reads without any animation. */

.plane-scene {
  display: block;
  height: auto;
  width: 100%;
  min-height: 210px;
  margin: 0 auto;
  overflow: visible;
  --ps-dur: 8.2s;
}

.plane-scene.is-clickable { cursor: pointer; }

/* Static frame: happy professor, no flyer, no plane. */
.ps-flyer, .ps-plane, .ps-trail, .ps-spark, .ps-stars, .ps-burst, .ps-arms-up { opacity: 0; }
.ps-face-idle { opacity: 0; }
.ps-face-happy { opacity: 1; }
.ps-note-held { opacity: 1; }

/* While playing, the timeline takes over. */
.plane-scene.is-playing .ps-face-idle { animation: ps-face-idle var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-face-happy { animation: ps-face-happy var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-note-held { animation: ps-note var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-flyer { animation: ps-flyer var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-spark { animation: ps-spark var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-plane { animation: ps-plane var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-trail { animation: ps-trail var(--ps-dur) linear infinite; }
.plane-scene.is-playing .ps-arm { animation: ps-arm var(--ps-dur) ease-in-out infinite; }
.plane-scene.is-playing .ps-student { animation: ps-student var(--ps-dur) var(--ease-spring) infinite; }
.plane-scene.is-playing .ps-arms-up { animation: ps-arms-up var(--ps-dur) var(--ease-spring) infinite; }
.plane-scene.is-playing .ps-prof { animation: ps-prof var(--ps-dur) var(--ease-spring) infinite; }
.plane-scene.is-playing .ps-prof-head { animation: ps-head var(--ps-dur) var(--ease-spring) infinite; }
.plane-scene.is-playing .ps-glasses { animation: ps-glasses var(--ps-dur) var(--ease-spring) infinite; }
.plane-scene.is-playing .ps-stars { animation: ps-stars var(--ps-dur) ease-out infinite; }
.plane-scene.is-playing .ps-mug { animation: ps-mug var(--ps-dur) ease-out infinite; }
.plane-scene.is-playing .ps-burst { animation: ps-burst var(--ps-dur) var(--ease-spring) infinite; }
.plane-scene.is-playing .ps-lamp-glow { animation: ps-lamp var(--ps-dur) ease-in-out infinite; }

/* The flyer folds into a plane: three shape beats before launch. */
@keyframes ps-flyer {
  0%, 6% { opacity: 0; transform: translateY(0) scale(.6) rotate(0deg); }
  8% { opacity: 1; transform: translateY(-4px) scale(1) rotate(-4deg); }
  12% { opacity: 1; transform: translateY(-6px) scale(.94) rotate(6deg); }
  15% { opacity: 1; transform: translateY(-4px) scale(.82) rotate(-10deg); }
  17.1% { opacity: 0; transform: translateY(-2px) scale(.7) rotate(-14deg); }
  100% { opacity: 0; }
}

@keyframes ps-spark {
  0%, 4% { opacity: 0; transform: scale(.4); }
  6.5% { opacity: 1; transform: scale(1.15); }
  10% { opacity: 0; transform: scale(1.4); }
  100% { opacity: 0; }
}

/* Wind up, then throw. */
@keyframes ps-arm {
  0%, 14% { transform: rotate(0deg); }
  18% { transform: rotate(-34deg); }
  20.7% { transform: rotate(46deg); }
  24% { transform: rotate(10deg); }
  30%, 100% { transform: rotate(0deg); }
}

/* Flight along the arc. offset-rotate makes it bank into the curve. */
@keyframes ps-plane {
  0%, 20.4% { opacity: 0; offset-distance: 0%; }
  20.7% { opacity: 1; offset-distance: 0%; }
  37.8% { opacity: 1; offset-distance: 100%; }
  39.2% { opacity: 0; offset-distance: 100%; }
  100% { opacity: 0; }
}

@keyframes ps-trail {
  0%, 20.7% { opacity: 0; stroke-dashoffset: 760; }
  22% { opacity: .55; }
  37.8% { opacity: .55; stroke-dashoffset: 0; }
  44% { opacity: 0; stroke-dashoffset: 0; }
  100% { opacity: 0; }
}

/* Bonk: head jolts back, then settles. */
@keyframes ps-head {
  0%, 37.5% { transform: translate(0, 0) rotate(0deg); }
  38.6% { transform: translate(7px, -3px) rotate(7deg); }
  40% { transform: translate(-2px, 1px) rotate(-3deg); }
  42%, 55% { transform: translate(0, 0) rotate(0deg); }
  57% { transform: translate(-4px, 0) rotate(-5deg); }
  61% { transform: translate(-2px, -3px) rotate(-2deg); }
  66% { transform: translate(-2px, -6px) rotate(0deg); }
  100% { transform: translate(-2px, -4px) rotate(0deg); }
}

@keyframes ps-glasses {
  0%, 37.8% { transform: translateY(0) rotate(0deg); }
  38.8% { transform: translateY(-9px) rotate(9deg); }
  40.5% { transform: translateY(2px) rotate(-3deg); }
  42%, 100% { transform: translateY(0) rotate(0deg); }
}

@keyframes ps-stars {
  0%, 37.6% { opacity: 0; transform: scale(.3); }
  38.8% { opacity: 1; transform: scale(1.15); }
  45% { opacity: 1; transform: scale(1.3); }
  49% { opacity: 0; transform: scale(1.5); }
  100% { opacity: 0; }
}

@keyframes ps-mug {
  0%, 37.8% { transform: translateY(0) rotate(0deg); }
  39% { transform: translateY(-2px) rotate(-4deg); }
  41% { transform: translateY(0) rotate(3deg); }
  43%, 100% { transform: translateY(0) rotate(0deg); }
}

/* Slumped while reading, pops upright when delighted. */
@keyframes ps-prof {
  0% { transform: translateY(3px); }
  30% { transform: translateY(4px); }
  37.8% { transform: translateY(3px); }
  39% { transform: translateY(6px); }
  56% { transform: translateY(3px); }
  61% { transform: translateY(-8px); }
  66% { transform: translateY(-4px); }
  70% { transform: translateY(-7px); }
  100% { transform: translateY(-6px); }
}

@keyframes ps-face-idle {
  0%, 56% { opacity: 1; }
  60% { opacity: 0; }
  100% { opacity: 0; }
}

@keyframes ps-face-happy {
  0%, 57% { opacity: 0; }
  61% { opacity: 1; }
  100% { opacity: 1; }
}

/* The note only exists in the professor's hands after the bonk. */
@keyframes ps-note {
  0%, 39.5% { opacity: 0; transform: translateY(-6px) rotate(-12deg); }
  43.9% { opacity: 1; transform: translateY(0) rotate(0deg); }
  100% { opacity: 1; transform: translateY(0) rotate(0deg); }
}

@keyframes ps-burst {
  0%, 59% { opacity: 0; transform: scale(.4) rotate(0deg); }
  63% { opacity: .9; transform: scale(1.05) rotate(8deg); }
  70% { opacity: .55; transform: scale(1) rotate(14deg); }
  100% { opacity: .55; transform: scale(1) rotate(20deg); }
}

@keyframes ps-lamp {
  0%, 58% { opacity: .18; }
  62% { opacity: .62; }
  100% { opacity: .5; }
}

/* Student cheers back. */
@keyframes ps-student {
  0%, 60% { transform: translateY(0); }
  63% { transform: translateY(-9px); }
  68% { transform: translateY(0); }
  71% { transform: translateY(-5px); }
  100% { transform: translateY(0); }
}

@keyframes ps-arms-up {
  0%, 60% { opacity: 0; transform: translateY(6px); }
  63% { opacity: 1; transform: translateY(0); }
  100% { opacity: 1; transform: translateY(0); }
}


/* Send-confirmation overlay */
.send-success {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: grid;
  place-items: center;
  padding: var(--space-5);
  background: rgba(34, 25, 18, .48);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s var(--ease-page), visibility .3s;
}
.send-success.is-open { opacity: 1; visibility: visible; }
.send-success__card {
  background: var(--card);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-3);
  max-width: 360px;
  padding: var(--space-6);
  text-align: center;
  width: 100%;
}

@media (prefers-reduced-motion: reduce) {
  .plane-scene.is-playing *,
  .plane-send * { animation: none !important; }
  .plane-scene .ps-face-happy, .plane-send .ps-face-happy { opacity: 1; }
  .plane-scene .ps-face-idle, .plane-send .ps-face-idle { opacity: 0; }
  .plane-scene .ps-note-held { opacity: 1; }
  .plane-scene .ps-burst { opacity: .55; }
}

/* Transform origins for the scene's moving parts. Not applied to .ps-plane,
   which is positioned by offset-path and must stay in user space. */
.plane-scene .ps-flyer,
.plane-scene .ps-spark,
.plane-scene .ps-arm,
.plane-scene .ps-student,
.plane-scene .ps-arms-up,
.plane-scene .ps-prof,
.plane-scene .ps-prof-head,
.plane-scene .ps-glasses,
.plane-scene .ps-stars,
.plane-scene .ps-mug,
.plane-scene .ps-note-held,
.plane-scene .ps-burst { transform-box: fill-box; transform-origin: center; }

.plane-scene .ps-arm { transform-origin: 8% 50%; }
.plane-scene .ps-prof-head { transform-origin: 50% 88%; }
.plane-scene .ps-prof { transform-origin: 50% 100%; }
.plane-scene .ps-student { transform-origin: 50% 100%; }
.plane-scene .ps-mug { transform-origin: 50% 100%; }
.plane-scene .ps-burst { transform-origin: 50% 70%; }
.plane-scene .ps-flyer { transform-origin: 30% 60%; }

/* Fallback for browsers without CSS motion paths: keyframed translate. */
.plane-scene.no-offset-path .ps-plane { offset-path: none; }
.plane-scene.no-offset-path.is-playing .ps-plane { animation: ps-plane-fallback var(--ps-dur) linear infinite; }

@keyframes ps-plane-fallback {
  0%, 20.4% { opacity: 0; transform: translate(200px, 186px) rotate(-20deg); }
  20.7% { opacity: 1; transform: translate(200px, 186px) rotate(-20deg); }
  26% { transform: translate(340px, 104px) rotate(-10deg); }
  31% { transform: translate(470px, 78px) rotate(0deg); }
  37.8% { opacity: 1; transform: translate(712px, 152px) rotate(16deg); }
  39.2% { opacity: 0; transform: translate(712px, 152px) rotate(16deg); }
  100% { opacity: 0; }
}

/* Django renders these form widgets without Bootstrap classes, so style the
   bare inputs directly rather than patching every auth template. */
.auth-card input[type="text"],
.auth-card input[type="email"],
.auth-card input[type="password"],
.auth-card input[type="number"],
.auth-card select,
.auth-card textarea {
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius);
  color: var(--ink);
  display: block;
  font-family: inherit;
  font-size: var(--text-sm);
  padding: var(--space-3);
  width: 100%;
}
.auth-card input:focus,
.auth-card select:focus,
.auth-card textarea:focus {
  border-color: var(--coral);
  box-shadow: 0 0 0 3px var(--coral-2);
  outline: none;
}
.auth-card label { color: var(--ink-2); font-size: var(--text-xs); font-weight: 600; margin-bottom: var(--space-1); }
.auth-card ul.errorlist { color: var(--coral-ink); font-size: var(--text-xs); list-style: none; margin: var(--space-1) 0 0; padding: 0; }
.auth-card .helptext { color: var(--ink-3); display: block; font-size: var(--text-2xs); margin-top: var(--space-1); }

/* Success mark used by the password-reset confirmations. */
.state-mark {
  align-items: center;
  border-radius: 50%;
  display: inline-flex;
  font-size: var(--text-xl);
  height: 56px;
  justify-content: center;
  margin-bottom: var(--space-3);
  width: 56px;
}
.state-mark.mint { background: var(--mint-2); color: #276b4a; }
html[data-theme="dark"] .state-mark.mint { color: var(--mint); }

/* --- 12. Pricing -------------------------------------------------------- */

.measure-wide { max-width: 880px; }

.pricing-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.pricing-tier {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  padding: var(--space-6) var(--space-5);
  position: relative;
}

.pricing-tier.is-featured {
  border-color: var(--coral);
  box-shadow: var(--shadow-2);
}

.pricing-tier.is-current { border-color: var(--mint); }

.pricing-tier__flag {
  position: absolute;
  top: calc(var(--space-3) * -1);
  left: var(--space-5);
}
html[dir="rtl"] .pricing-tier__flag { left: auto; right: var(--space-5); }

.pricing-tier__price {
  color: var(--ink);
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  line-height: 1.1;
  margin-bottom: var(--space-2);
}
.pricing-tier__price span { color: var(--ink-3); font-family: var(--font-ui); font-size: var(--text-sm); }

.pricing-tier__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
}
.pricing-tier__list li {
  align-items: flex-start;
  color: var(--ink-2);
  display: flex;
  font-size: var(--text-sm);
  gap: var(--space-2);
  max-width: none;
}
.pricing-tier__list i { color: var(--mint); flex: none; margin-top: 2px; }

/* --- 13. Empty states --------------------------------------------------- */

.empty-state {
  align-items: center;
  border: 1px dashed var(--rule-strong);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-7) var(--space-5);
  text-align: center;
}
.empty-state__art { color: var(--ink-4); font-size: var(--text-2xl); }
.empty-state h3 { font-size: var(--text-md); margin: 0; }
.empty-state p { color: var(--ink-3); font-size: var(--text-sm); margin: 0; max-width: 46ch; }

/* --- 14. Page-specific, lifted out of per-template <style> blocks -------- */


/* selection_flow: bounded pick lists */
.scroll-box {
  background: var(--card);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
  max-height: 150px;
  overflow-y: auto;
  padding: var(--space-1);
}
.scroll-box ul { list-style: none; margin-bottom: 0; padding-left: 0; }
.scroll-box li { margin-bottom: 3px; max-width: none; }

/* Search results are unbounded, and a broad filter used to push the
   "generate emails" step far below the fold. Cap the list and give it its own
   scrollbar so the next step stays visible however many professors match. */
.results-scroll {
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  max-height: 45vh;
  min-height: 160px;
  overflow: auto;
}
.results-scroll table { margin-bottom: 0; }

/* Column labels have to survive scrolling inside the box, otherwise the
   checkbox column is unidentifiable a few rows down. */
.results-scroll thead th {
  background: var(--card);
  box-shadow: inset 0 -1px 0 var(--rule-strong);
  position: sticky;
  top: 0;
  z-index: 2;
}

.university-crest-img {
  background: var(--card-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  object-fit: contain;
  padding: 4px;
}

/* --- 15. Usage meters --------------------------------------------------- */

.usage-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.usage-meter {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
}
.usage-meter__head {
  align-items: baseline;
  display: flex;
  gap: var(--space-2);
  justify-content: space-between;
  margin-bottom: var(--space-2);
}
.usage-meter__head span { color: var(--ink-3); font-size: var(--text-xs); }
.usage-meter__head strong { color: var(--ink); font-size: var(--text-md); font-family: var(--font-display); }
.usage-meter__head strong span { color: var(--ink-4); font-family: var(--font-ui); font-size: var(--text-xs); }

.progress-bar.is-mint { background: var(--mint); }

.pricing-tier__list li.is-off { color: var(--ink-4); }
.pricing-tier__list li.is-off i { color: var(--ink-4); }

/* --- 16. Page header + toolbar ------------------------------------------ */

.page-toolbar {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: space-between;
  margin-bottom: var(--space-5);
}
.page-toolbar__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.stat-strip {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-bottom: var(--space-5);
}

/* --- 17. Inline notes and setting rows ---------------------------------- */

.inline-note {
  align-items: center;
  background: var(--card-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
}
.inline-note.is-mint { background: var(--mint-2); border-color: var(--mint); }
.inline-note.is-sun { background: var(--sun-2); border-color: var(--sun); }
.inline-note strong { color: var(--ink); font-size: var(--text-sm); }

.setting-row {
  align-items: center;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  padding: var(--space-4) 0;
}
.setting-row:first-of-type { border-top: 0; padding-top: 0; }
.setting-row:last-child { padding-bottom: 0; }
.setting-row strong { color: var(--ink); font-size: var(--text-sm); }
.setting-row--stack { align-items: flex-start; }

@media (max-width: 575.98px) {
  .setting-row, .inline-note { align-items: flex-start; flex-direction: column; }
}

/* --- 18. Long-form text ------------------------------------------------- */

.prose { color: var(--ink-2); font-size: var(--text-sm); line-height: 1.7; max-width: var(--measure); }
.prose p { margin-bottom: var(--space-3); }
.prose p:last-child { margin-bottom: 0; }
.prose a { text-decoration: underline; }

/* --- 19. Professor card ------------------------------------------------- */

.prof-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  height: 100%;
  padding: var(--space-4);
  transition: transform .2s var(--ease-page), box-shadow .2s var(--ease-page);
}
.prof-card:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); }

.prof-card__head { align-items: flex-start; display: flex; gap: var(--space-2); }
.prof-card__id { flex: 1; min-width: 0; }
.prof-card__name { font-size: var(--text-md); margin: 0 0 2px; line-height: 1.25; }
.prof-card__name a { color: var(--ink); }
.prof-card__name a:hover { color: var(--coral-ink); }
.prof-card__org {
  color: var(--ink-3);
  font-size: var(--text-xs);
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.prof-card__tools { align-items: center; display: flex; flex: none; gap: var(--space-2); }
.prof-card__bookmark {
  background: none;
  border: 0;
  color: var(--ink-4);
  cursor: pointer;
  font-size: var(--text-md);
  line-height: 1;
  padding: 0;
}
.prof-card__bookmark:hover { color: var(--sun); }
.prof-card__bookmark .is-on { color: var(--sun); }

.prof-card__tags { display: flex; flex-wrap: wrap; gap: var(--space-1); }

.prof-card__bio {
  color: var(--ink-3);
  font-size: var(--text-xs);
  margin: 0;
  max-width: none;
}

.prof-card__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: auto;
  padding-top: var(--space-2);
}

/* --- 20. Pipeline board ------------------------------------------------- */

.kanban {
  display: flex;
  gap: var(--space-3);
  overflow-x: auto;
  padding-bottom: var(--space-4);
}

.kanban-col {
  background: var(--card-soft);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  flex: 0 0 272px;
  max-height: 72vh;
}

.kanban-col__head {
  align-items: center;
  border-bottom: 1px solid var(--rule);
  color: var(--ink-2);
  display: flex;
  font-size: var(--text-2xs);
  font-weight: 700;
  gap: var(--space-2);
  justify-content: space-between;
  letter-spacing: .08em;
  padding: var(--space-3);
  text-transform: uppercase;
}
html[dir="rtl"] .kanban-col__head { letter-spacing: 0; text-transform: none; }

.kanban-drop {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  flex: 1;
  min-height: 140px;
  overflow-y: auto;
  padding: var(--space-3);
}
.kanban-drop.drag-over { background: var(--coral-2); }

.kanban-col__empty {
  color: var(--ink-4);
  font-size: var(--text-xs);
  margin: 0;
  padding: var(--space-5) 0;
  text-align: center;
}

.kanban-card {
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  cursor: grab;
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  padding: var(--space-3);
}
.kanban-card:active { cursor: grabbing; }
.kanban-card.dragging { opacity: .45; }
.kanban-card__name { color: var(--ink); font-size: var(--text-sm); font-weight: 600; }
.kanban-card__org { color: var(--ink-3); font-size: var(--text-2xs); margin: 0; max-width: none; }
.kanban-card__note {
  color: var(--ink-3);
  font-size: var(--text-2xs);
  margin: var(--space-1) 0 0;
  max-width: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kanban-card__due {
  align-items: center;
  color: var(--coral-ink);
  display: flex;
  font-size: var(--text-2xs);
  gap: var(--space-1);
  margin: var(--space-1) 0 0;
  max-width: none;
}

.add-results { max-height: 240px; overflow-y: auto; }
.add-results .list-group-item { font-size: var(--text-xs); }

/* --- 21. Draft review rows ---------------------------------------------- */

.draft-head {
  align-items: stretch;
  display: flex;
  margin: 0;
}

.draft-head__check {
  align-items: center;
  border-right: 1px solid var(--rule);
  display: flex;
  flex: none;
  padding: 0 var(--space-4);
}
html[dir="rtl"] .draft-head__check { border-left: 1px solid var(--rule); border-right: 0; }
.draft-head__check .form-check-input { cursor: pointer; height: 18px; margin: 0; width: 18px; }

.draft-head__btn {
  align-items: center;
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: var(--space-3);
  justify-content: space-between;
  min-width: 0;
}
.draft-head__btn.accordion-button { background: transparent; box-shadow: none; }
.draft-head__btn.accordion-button:not(.collapsed) { background: var(--card-soft); color: var(--ink); }

.draft-head__who {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  text-align: start;
}
.draft-head__who strong { color: var(--ink); font-size: var(--text-sm); }
.draft-head__who .text-muted { font-size: var(--text-2xs); }

.draft-head__tags { display: flex; flex-wrap: wrap; gap: var(--space-1); }

/* --- 22. Application flow ----------------------------------------------- */

.flow-step__head {
  align-items: flex-start;
  border-bottom: 1px solid var(--rule);
  display: flex;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-4);
}

.flow-step__num {
  align-items: center;
  background: var(--coral);
  border-radius: 50%;
  color: #fff;
  display: flex;
  flex: none;
  font-family: var(--font-display);
  font-size: var(--text-md);
  font-weight: 600;
  height: 32px;
  justify-content: center;
  width: 32px;
}

/* Tick-to-pick card, used for the shortlist quick-pick. */
.pick-card {
  align-items: flex-start;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  cursor: pointer;
  display: flex;
  gap: var(--space-2);
  height: 100%;
  padding: var(--space-3);
  transition: border-color .15s, background-color .15s;
}
.pick-card:hover { border-color: var(--rule-strong); background: var(--card-soft); }
.pick-card:has(input:checked) { border-color: var(--coral); background: var(--coral-2); }
.pick-card input { flex: none; margin-top: 2px; }
.pick-card__body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.pick-card__body strong { color: var(--ink); font-size: var(--text-sm); }
.pick-card__body .text-muted { font-size: var(--text-2xs); }

/* The filter form renders Django multi-selects straight into these boxes. */
.scroll-box select { border: 0; font-size: var(--text-sm); width: 100%; }
.scroll-box select:focus { box-shadow: none; outline: none; }

/* Pills are inline-flex, so inside a column flex card they stretch to the full
   width unless told otherwise. */
.soft-feature-card > .v2-pill,
.v2-action-card > .v2-pill,
.prof-card > .v2-pill,
.pricing-tier > .v2-pill { align-self: flex-start; }

/* Buttons in a column flex card stretch the same way. */
.soft-feature-card > .btn,
.v2-action-card > .btn { align-self: flex-start; }

/* ==========================================================================
   23. Illustrated scenes — shared character kit
   Every scene's STATIC state is its resting frame, so with JS off or reduced
   motion on the drawing still reads. Story beats run once under .is-playing;
   only idle motion (breathing, sway, blink) loops.
   ========================================================================== */

.scene {
  display: block;
  height: auto;
  overflow: visible;
  width: 100%;
}
.scene.is-clickable { cursor: pointer; }

/* NOTE for new scenes: a CSS transform (including one from an animation)
   overrides the SVG `transform` presentation attribute outright. Never put
   both on the same element, or the figure snaps to the origin and disappears.
   Position with a plain wrapper <g transform="translate(x,y)"> and animate the
   <g> inside it. */

/* Everything animated gets a sane transform box. Figures rotate about their
   feet, props about their own centre. */
.scene [class*="sc-"] { transform-box: fill-box; transform-origin: center; }
.scene .sc-bob,
.scene .sc-sway,
.scene .sc-figure { transform-origin: 50% 100%; }
/* An arm (and whatever it holds) pivots at the shoulder, near its bbox top. */
.scene .sc-arm { transform-origin: 50% 8%; }
/* A hinged prop — lid, door, page — pivots at one edge. */
.scene .sc-hinge-l { transform-origin: 0% 50%; }
.scene .sc-hinge-b { transform-origin: 50% 100%; }

/* ---- idle: always running ---- */
.scene .sc-bob { animation: sc-bob 3.2s ease-in-out infinite; }
.scene .sc-sway { animation: sc-sway 4.4s ease-in-out infinite; }
.scene .sc-float { animation: sc-float 3.6s ease-in-out infinite; }
.scene .sc-blink { animation: sc-blink 5.2s steps(1, end) infinite; }
.scene .sc-spin { animation: sc-spin 9s linear infinite; }
.scene .sc-pulse { animation: sc-pulse 2.4s ease-in-out infinite; }

/* Must out-specify the `animation:` shorthands below, which reset the delay. */
.scene .sc-d1, .scene.is-playing .sc-d1 { animation-delay: .25s; }
.scene .sc-d2, .scene.is-playing .sc-d2 { animation-delay: .5s; }
.scene .sc-d3, .scene.is-playing .sc-d3 { animation-delay: .8s; }
.scene .sc-d4, .scene.is-playing .sc-d4 { animation-delay: 1.15s; }

@keyframes sc-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-3px); }
}
@keyframes sc-sway {
  0%, 100% { transform: rotate(-1.6deg); }
  50% { transform: rotate(1.6deg); }
}
@keyframes sc-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}
@keyframes sc-blink {
  0%, 92%, 96% { transform: scaleY(1); }
  94% { transform: scaleY(.15); }
}
@keyframes sc-spin { to { transform: rotate(360deg); } }
@keyframes sc-pulse {
  0%, 100% { opacity: .35; transform: scale(1); }
  50% { opacity: .8; transform: scale(1.06); }
}

/* ---- story beats: play once when the scene comes into view ---- */
/* Props that only exist mid-story rest at opacity 0. */
.scene .sc-cue { opacity: 0; }
.scene.is-playing .sc-cue { animation: sc-cue 4.2s ease-out 1 both; }
@keyframes sc-cue {
  0%, 8% { opacity: 0; transform: translateY(4px) scale(.6); }
  22% { opacity: 1; transform: translateY(-2px) scale(1.08); }
  46% { opacity: 1; transform: translateY(-4px) scale(1); }
  62%, 100% { opacity: 0; transform: translateY(-8px) scale(.9); }
}

/* Two-state faces: resting shows the resolved one. */
.scene .sc-before { opacity: 0; }
.scene .sc-after { opacity: 1; }
.scene.is-playing .sc-before { animation: sc-before 4.2s linear 1 both; }
.scene.is-playing .sc-after { animation: sc-after 4.2s linear 1 both; }
@keyframes sc-before { 0%, 62% { opacity: 1; } 70%, 100% { opacity: 0; } }
@keyframes sc-after { 0%, 64% { opacity: 0; } 72%, 100% { opacity: 1; } }

/* A prop that swings once (wrench, pen, rod, arm). */
.scene.is-playing .sc-swing { animation: sc-swing 4.2s ease-in-out 1 both; }
@keyframes sc-swing {
  0%, 10% { transform: rotate(0deg); }
  26% { transform: rotate(-24deg); }
  42% { transform: rotate(16deg); }
  58% { transform: rotate(-10deg); }
  72%, 100% { transform: rotate(0deg); }
}

/* A prop that is thrown up and comes back. */
.scene.is-playing .sc-toss { animation: sc-toss 4.2s cubic-bezier(.3,.1,.5,1) 1 both; }
@keyframes sc-toss {
  0%, 14% { transform: translateY(0) rotate(0deg); }
  40% { transform: translateY(-46px) rotate(180deg); }
  66% { transform: translateY(-10px) rotate(320deg); }
  78%, 100% { transform: translateY(0) rotate(360deg); }
}

/* A line or path that draws itself in. */
.scene .sc-draw { stroke-dasharray: 260; stroke-dashoffset: 0; }
.scene.is-playing .sc-draw { animation: sc-draw 4.2s ease-out 1 both; }
@keyframes sc-draw {
  0%, 12% { stroke-dashoffset: 260; }
  62%, 100% { stroke-dashoffset: 0; }
}

/* A small celebration pop at the end of the beat. */
.scene.is-playing .sc-cheer { animation: sc-cheer 4.2s var(--ease-spring) 1 both; }
@keyframes sc-cheer {
  0%, 66% { transform: translateY(0); }
  74% { transform: translateY(-9px); }
  84% { transform: translateY(-2px); }
  90%, 100% { transform: translateY(-5px); }
}

/* Something sliding in from the left, then settling. */
.scene.is-playing .sc-enter { animation: sc-enter 4.2s var(--ease-page) 1 both; }
@keyframes sc-enter {
  0% { opacity: 0; transform: translateX(-38px); }
  30%, 100% { opacity: 1; transform: translateX(0); }
}

/* Something that fills up (water, progress, a jar). */
.scene.is-playing .sc-fill { animation: sc-fill 4.2s ease-out 1 both; }
@keyframes sc-fill {
  0%, 10% { transform: scaleY(0); }
  70%, 100% { transform: scaleY(1); }
}
.scene .sc-fill { transform-origin: 50% 100%; }

/* ---- the hero band each page opens with ---- */

.page-hero {
  align-items: center;
  display: flex;
  gap: var(--space-5);
  justify-content: space-between;
  margin-bottom: var(--space-5);
}
.page-hero__text { flex: 1; min-width: 0; }
.page-hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); }
.page-hero__art { flex: none; width: 280px; }
.page-hero__art .scene { max-height: 180px; }

@media (max-width: 991.98px) { .page-hero__art { width: 210px; } }
@media (max-width: 767.98px) { .page-hero__art { display: none; } }
/* --- 25. Tiny status figures -------------------------------------------- */

.mini-fig {
  display: inline-block;
  height: 30px;
  width: 24px;
  vertical-align: middle;
  overflow: visible;
}
.mini-fig [class*="mf-"] { transform-box: fill-box; transform-origin: 50% 100%; }

.mini-fig--happy .mf-jump { animation: mf-jump 1.1s var(--ease-spring) 2 both; }
@keyframes mf-jump {
  0% { transform: translateY(0); }
  30% { transform: translateY(-7px); }
  55% { transform: translateY(0); }
  70% { transform: translateY(-3px); }
  100% { transform: translateY(0); }
}

.mini-fig--sad .mf-slump { animation: mf-slump 1.3s ease-out 1 both; }
@keyframes mf-slump {
  0% { transform: translateY(-4px) rotate(0deg); }
  60% { transform: translateY(1px) rotate(-3deg); }
  100% { transform: translateY(0) rotate(-2deg); }
}
.mini-fig--sad .mf-rain { animation: mf-rain 1.4s ease-in-out infinite; transform-origin: 50% 0%; }
@keyframes mf-rain {
  0%, 100% { transform: translateY(0); opacity: .85; }
  50% { transform: translateY(2px); opacity: 1; }
}

.status-with-fig { align-items: center; display: inline-flex; gap: var(--space-2); }

@media (prefers-reduced-motion: reduce) {
  .mini-fig * { animation: none !important; }
}

/* --- 26. Postman and money-grab, both one-shot on .is-sent --------------- */

.plane-send [class*="pm-"],
.plane-send [class*="mn-"] { transform-box: fill-box; transform-origin: center; }
.plane-send .pm-arm, .plane-send .mn-reach { transform-origin: 50% 8%; }

/* -- postman -- */
.plane-send .pm-walk { transform: translateX(120px); opacity: 0; }
.plane-send .pm-letters { opacity: 1; }

.plane-send.is-sent .pm-walk { animation: pm-walk 2.2s var(--ease-page) 1 both; }
.plane-send.is-sent .pm-arm { animation: pm-arm 2.2s ease-in-out 1 both; }
.plane-send.is-sent .pm-letters { animation: pm-letters 2.2s ease-in 1 both; }

@keyframes pm-walk {
  0% { opacity: 0; transform: translateX(120px); }
  22% { opacity: 1; transform: translateX(0); }
  62% { opacity: 1; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(150px); }
}
@keyframes pm-arm {
  0%, 24% { transform: rotate(0deg); }
  38% { transform: rotate(-52deg); }
  52% { transform: rotate(-10deg); }
  70% { transform: rotate(-44deg); }
  82% { transform: rotate(-18deg); }
  100% { transform: rotate(-40deg); }
}
@keyframes pm-letters {
  0%, 36% { opacity: 1; transform: translate(0, 0) scale(1); }
  54% { opacity: 0; transform: translate(60px, -26px) scale(.7); }
  100% { opacity: 0; transform: translate(60px, -26px) scale(.7); }
}

/* -- money grab -- */
.plane-send .mn-note { transform: translate(0, 0); }
.plane-send .mn-coin { opacity: 0; }
.plane-send .mn-taker { opacity: 1; }

.plane-send.is-sent .mn-note { animation: mn-note 1.8s var(--ease-page) 1 both; }
.plane-send.is-sent .mn-reach { animation: mn-reach 1.8s ease-in-out 1 both; }
.plane-send.is-sent .mn-coin--1 { animation: mn-coin 1.8s ease-out 1 both; animation-delay: .35s; }
.plane-send.is-sent .mn-coin--2 { animation: mn-coin 1.8s ease-out 1 both; animation-delay: .55s; }
.plane-send.is-sent .mn-taker { animation: mn-taker 1.8s var(--ease-spring) 1 both; }

@keyframes mn-note {
  0%, 12% { transform: translate(0, 0) rotate(0deg); }
  70% { transform: translate(112px, -28px) rotate(12deg); }
  100% { transform: translate(122px, -30px) rotate(10deg); }
}
@keyframes mn-reach {
  0% { transform: rotate(0deg); }
  30% { transform: rotate(16deg); }
  75%, 100% { transform: rotate(-8deg); }
}
@keyframes mn-coin {
  0% { opacity: 0; transform: translate(0, 10px) scale(.5); }
  45% { opacity: 1; transform: translate(14px, -10px) scale(1); }
  100% { opacity: 0; transform: translate(30px, -26px) scale(.8); }
}
@keyframes mn-taker {
  0%, 60% { transform: translateY(0); }
  76% { transform: translateY(-7px); }
  100% { transform: translateY(-3px); }
}

@media (prefers-reduced-motion: reduce) {
  .plane-send * { animation: none !important; }
  .plane-send .pm-walk { opacity: 1; transform: none; }
  .plane-send .mn-coin { opacity: 1; }
}

/* Shared frame for the one-shot action scenes (postman, money grab). */
.plane-send {
  display: block;
  height: auto;
  margin: 0 auto;
  max-width: 300px;
  overflow: visible;
  width: 100%;
}



/* ==========================================================================
   24. Page transition — the page's own character rolls the page away
   The figure standing in this page's hero scene is cloned out, jumps to the top
   of the viewport, takes hold of the page and rolls it down like a blind.
   Everything above the roller is the next page; everything below is still the
   old one.

   Only transform and opacity are animated, so the whole thing stays on the
   compositor. The cover, the roller and the rider share one duration, one delay
   and one easing curve, which is what keeps them locked to each other.
   ========================================================================== */

:root {
  --roll-jump-ms: 2000ms;
  --roll-down-ms: 3000ms;
  --roll-bar-h: 30px;
  /* Weighty: reluctant to start, confident through the middle, soft landing. */
  --ease-roll: cubic-bezier(.62, .03, .30, 1);
}

.roll-stage {
  position: fixed;
  inset: 0;
  z-index: 9996;
  pointer-events: none;
  visibility: hidden;
}
/* While it runs it swallows clicks; a second click is handled in JS, which
   skips the rest of the animation rather than queueing another navigation. */
.roll-stage.is-rolling { visibility: visible; pointer-events: auto; }

/* ---- the fresh surface being uncovered ---- */

.roll-cover {
  position: absolute;
  inset: 0;
  background: var(--bg);
  transform-origin: 50% 0%;
  transform: scaleY(0);
  will-change: transform;
}
.roll-stage.is-rolling .roll-cover {
  animation: roll-cover var(--roll-down-ms) var(--ease-roll) var(--roll-jump-ms) both;
}
@keyframes roll-cover {
  from { transform: scaleY(0); }
  to { transform: scaleY(1); }
}

/* ---- the roller ---- */

.roll-bar {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--roll-bar-h);
  border-radius: 4px;
  background: linear-gradient(180deg,
    #cbb69a 0%,
    #f6ead7 24%,
    #e0cdb0 52%,
    #a98e6d 100%);
  box-shadow: 0 14px 28px -10px rgba(34, 25, 18, .45);
  /* centre of the roller sits on the cover's bottom edge */
  transform: translate3d(0, calc(var(--roll-bar-h) / -2), 0);
  will-change: transform;
  opacity: 0;
}
.roll-stage.is-rolling .roll-bar {
  animation: roll-bar var(--roll-down-ms) var(--ease-roll) var(--roll-jump-ms) both,
             roll-bar-in 240ms ease-out var(--roll-jump-ms) both;
}
@keyframes roll-bar {
  from { transform: translate3d(0, calc(var(--roll-bar-h) / -2), 0); }
  to { transform: translate3d(0, calc(100vh - var(--roll-bar-h) / 2), 0); }
}
@keyframes roll-bar-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.roll-bar__cap {
  position: absolute;
  top: 50%;
  width: 14px;
  height: calc(var(--roll-bar-h) + 6px);
  margin-top: calc((var(--roll-bar-h) + 6px) / -2);
  border-radius: 50%;
  background: linear-gradient(180deg, #e6d6bd, #9c8263);
}
.roll-bar__cap--l { left: -5px; }
.roll-bar__cap--r { right: -5px; }

html[data-theme="dark"] .roll-bar {
  background: linear-gradient(180deg, #4a3d2e 0%, #6d5a44 24%, #52442f 52%, #33291f 100%);
}
html[data-theme="dark"] .roll-bar__cap {
  background: linear-gradient(180deg, #6d5a44, #2b221a);
}

/* ---- the rider ---- */

.roll-actor {
  position: fixed;
  left: 0;
  top: 0;
  transform-origin: 50% 100%;   /* squash from the feet */
  will-change: transform;
  opacity: 0;
}
.roll-actor__ride { will-change: transform; }
.roll-actor__art { display: block; width: 100%; height: 100%; overflow: visible; }

.roll-stage.is-rolling .roll-actor {
  animation: roll-jump var(--roll-jump-ms) linear both;
  opacity: 1;
}
.roll-stage.is-rolling .roll-actor__ride {
  animation: roll-ride var(--roll-down-ms) var(--ease-roll) var(--roll-jump-ms) both;
}

/* Ballistic, with the easing set per segment: sink into the crouch, snap out of
   it, coast through the arc, settle on the roller. --jx/--jy are the offsets
   from where the figure was actually standing, measured at transition time. */
@keyframes roll-jump {
  0% {
    transform: translate3d(0, 0, 0) scale(1, 1);
    animation-timing-function: cubic-bezier(.4, 0, .6, 1);
  }
  9% {
    transform: translate3d(0, 10px, 0) scale(1.09, .86);
    animation-timing-function: cubic-bezier(.2, .7, .4, 1);
  }
  21% {
    transform: translate3d(calc(var(--jx) * .16), calc(var(--jy) * .30), 0) scale(.9, 1.16);
    animation-timing-function: cubic-bezier(.25, .6, .45, 1);
  }
  44% {
    transform: translate3d(calc(var(--jx) * .60), calc(var(--jy) * .90), 0) scale(1, 1);
    animation-timing-function: cubic-bezier(.3, .5, .5, 1);
  }
  62% {
    transform: translate3d(calc(var(--jx) * .93), calc(var(--jy) * 1.05), 0) scale(1.03, .96);
    animation-timing-function: cubic-bezier(.35, 1.3, .55, 1);
  }
  78%, 100% {
    transform: translate3d(var(--jx), var(--jy), 0) scale(1, 1);
  }
}

@keyframes roll-ride {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(0, 100vh, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .roll-stage { display: none !important; }
}
