:root {
  /* Lud Works palette: cream page, white cards, near-black hero bands,
     mint accent. The token names (gold, parchment) predate this palette
     and are kept so every existing rule picks the new colors up. */
  --ink: #16181a;
  --ink-soft: #6c7073;
  --parchment: #ffffff;
  --parchment-deep: #e6e4dd;
  --page-bg: #f4f3ef;
  --gold: #5fd4a4;
  --gold-bright: #7fe0b8;
  --gold-ink: #0b2a1e;
  /* Mint is too light to read as text on cream/white, so text and
     icons that use the accent use this deeper shade instead. */
  --accent-text: #1a8f62;
  --accent-soft: rgba(95, 212, 164, 0.16);
  --green: #1f9d6c;
  --red: #d64541;
  --hero-bg: #111210;
  --hero-bg-2: #1b1c1a;
  --card-radius: 14px;
  --card-shadow: 0 1px 2px rgba(20, 20, 15, 0.04), 0 4px 18px -8px rgba(20, 20, 15, 0.10);
  --display: 'Sora', -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  --body: 'Inter', -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* Dark hero bands (top header, GPA ribbon, sign-in brand panel,
   graduate hero) keep the near-black look, so they flip the tokens
   back to light-on-dark for everything inside them. */
.site-header,
.gpa-ribbon,
.auth-brand-panel,
.grad-hero {
  --ink: #f4f3ef;
  --ink-soft: #9a9d98;
  --parchment: #111210;
  --parchment-deep: #2a2b28;
  --accent-text: #5fd4a4;
  --accent-soft: rgba(95, 212, 164, 0.14);
}

* { box-sizing: border-box; }

html {
  /* Without this, browsers assume a light UI for form controls (text
     inputs, selects, autofill, scrollbars) regardless of the page's
     own dark background/colors — which renders input TEXT in black,
     nearly invisible on our dark input fields. This tells the browser
     the page is light so it picks legible native defaults everywhere,
     on top of the explicit `color` we still set below. */
  color-scheme: light;
}

body {
  margin: 0;
  background: var(--page-bg);
  color: var(--ink);
  font-family: var(--body);
  line-height: 1.5;
}

a { color: inherit; }

/* ---- Header ---- */
.site-header {
  background: var(--hero-bg);
  color: var(--ink);
  border-bottom: 1px solid var(--parchment-deep);
}

.header-inner {
  max-width: 980px;
  margin: 0 auto;
  padding: 1.1rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.crest {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--ink);
}

.crest-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2rem;
  height: 2rem;
  font-family: var(--display);
  font-weight: 800;
  font-size: 1rem;
  letter-spacing: 0.02em;
  padding: 0 0.4rem;
  border-radius: 8px;
  background: linear-gradient(155deg, var(--gold), var(--gold-bright));
  color: var(--gold-ink);
}

.crest-name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.01em;
  opacity: 0.92;
  display: none;
}

@media (min-width: 480px) {
  .crest-name { display: inline; }
}

.header-right {
  display: flex;
  align-items: center;
  gap: 1.3rem;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  font-size: 0.9rem;
  flex-shrink: 0;
}

.profile-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  color: var(--ink);
  padding: 0.2rem 0.6rem 0.2rem 0.2rem;
  border-radius: 999px;
  border: 1px solid transparent;
  transition: border-color 0.15s ease, background 0.15s ease;
  flex-shrink: 0;
}

.profile-chip:hover {
  border-color: var(--gold);
  background: rgba(0, 0, 0, 0.04);
}

.profile-chip-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  border: 1.5px solid var(--gold);
  display: block;
  background: var(--ink-soft);
}

.profile-chip-name {
  font-size: 0.85rem;
  opacity: 0.9;
  display: none;
}

@media (min-width: 480px) {
  .profile-chip-name { display: inline; }
}

/* ---- Notification bell ---- */
.notif-bell {
  position: relative;
  flex-shrink: 0;
}
.notif-bell-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid transparent;
  color: var(--ink-soft);
  cursor: pointer;
  list-style: none;
  position: relative;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.notif-bell-btn::-webkit-details-marker,
.notif-bell-btn::marker {
  display: none;
  content: "";
}
.notif-bell-btn i {
  font-size: 1.25rem;
}
.notif-bell-btn:hover {
  border-color: var(--gold);
  background: rgba(0, 0, 0, 0.04);
  color: var(--ink);
}
.notif-bell[open] .notif-bell-btn {
  border-color: var(--gold);
  background: var(--parchment-deep);
  color: var(--ink);
}
.notif-bell-badge {
  position: absolute;
  top: 1px;
  right: 1px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  border: 1.5px solid var(--parchment);
}

.report-problem-btn {
  flex-shrink: 0;
  text-decoration: none;
}
.nav-count {
  display: inline-block;
  min-width: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 0.68rem;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
  vertical-align: 1px;
}

.notif-panel {
  position: absolute;
  top: calc(100% + 0.6rem);
  right: 0;
  width: 320px;
  max-width: min(320px, 90vw);
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-top: 3px solid var(--gold);
  border-radius: 8px;
  box-shadow: 0 12px 30px rgba(20, 20, 15, 0.16);
  z-index: 40;
  overflow: hidden;
}
.notif-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem 0.7rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--ink);
  border-bottom: 1px solid var(--parchment-deep);
}
.notif-mark-read {
  background: none;
  border: none;
  color: var(--green);
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.notif-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 340px;
  overflow-y: auto;
}
.notif-item {
  border-bottom: 1px solid var(--parchment-deep);
}
.notif-item:last-child {
  border-bottom: none;
}
.notif-item-inner {
  display: block;
  padding: 0.7rem 1rem;
  text-decoration: none;
  color: var(--ink);
}
a.notif-item-inner:hover {
  background: var(--page-bg);
}
.notif-item.unread {
  background: rgba(95, 212, 164, 0.08);
  position: relative;
}
.notif-item.unread::before {
  content: "";
  position: absolute;
  top: 1.05rem;
  left: 0.35rem;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
}
.notif-item.unread .notif-item-inner {
  padding-left: 1.35rem;
}
.notif-message {
  display: block;
  font-size: 0.85rem;
  line-height: 1.4;
  margin-bottom: 0.2rem;
}
.notif-time {
  display: block;
  font-size: 0.72rem;
  color: var(--ink-soft);
}
.notif-empty {
  padding: 1.4rem 1rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  text-align: center;
  margin: 0;
}
.notif-viewall {
  display: block;
  text-align: center;
  padding: 0.7rem 1rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--green);
  text-decoration: none;
  background: var(--page-bg);
}
.notif-viewall:hover {
  background: var(--parchment-deep);
}

/* ---- Notifications page ---- */
.notif-page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.2rem;
}
.notif-page-list {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  overflow: hidden;
}
.notif-page-item {
  display: flex;
  gap: 0.7rem;
  padding: 1rem 1.1rem;
  border-bottom: 1px solid var(--parchment-deep);
}
.notif-page-item:last-child {
  border-bottom: none;
}
.notif-page-item.unread {
  background: rgba(95, 212, 164, 0.07);
}
.notif-page-dot {
  flex: none;
  width: 8px;
  height: 8px;
  margin-top: 0.35rem;
  border-radius: 50%;
  background: var(--gold);
  opacity: 0;
}
.notif-page-item.unread .notif-page-dot {
  opacity: 1;
}
.notif-page-message {
  margin: 0 0 0.2rem;
  font-size: 0.92rem;
  color: var(--ink);
}
.notif-page-message a {
  text-decoration: none;
  color: inherit;
}
.notif-page-message a:hover {
  text-decoration: underline;
}
.notif-page-time {
  margin: 0;
  font-size: 0.76rem;
  color: var(--ink-soft);
}

.site-nav a {
  text-decoration: none;
  opacity: 0.85;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  white-space: nowrap;
  flex-shrink: 0;
}
.site-nav a:hover { opacity: 1; border-bottom-color: var(--gold); }

/* ---- GPA ribbon: the signature element ---- */
.gpa-ribbon {
  background: linear-gradient(180deg, var(--hero-bg-2), var(--hero-bg));
  border-top: 1px solid rgba(95, 212, 164, 0.25);
}

.gpa-ribbon-inner {
  max-width: 900px;
  margin: 0 auto;
  padding: 0.85rem 1.5rem 1rem;
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  position: relative;
}

.gpa-ribbon-inner::after {
  content: "";
  position: absolute;
  left: 1.5rem;
  right: 1.5rem;
  bottom: -1px;
  height: 2px;
  background: repeating-linear-gradient(
    90deg, var(--gold) 0 10px, transparent 10px 16px
  );
  opacity: 0.6;
}

.gpa-label {
  font-family: var(--display);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--accent-text);
}

.gpa-value {
  font-family: var(--display);
  font-size: 2rem;
  font-weight: 700;
  color: #fff;
  line-height: 1;
}

.gpa-track {
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin-left: auto;
}

/* ---- Main ---- */
.site-main {
  max-width: 900px;
  margin: 0 auto;
  padding: 2.5rem 1.5rem 4rem;
}

.eyebrow {
  font-family: var(--display);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.78rem;
  color: var(--green);
  margin: 0 0 0.4rem;
}

h1 {
  font-family: var(--display);
  font-size: 2.1rem;
  margin: 0 0 0.6rem;
  color: var(--ink);
}

.hero { max-width: 620px; padding-top: 1rem; }
.hero-sub { font-size: 1.05rem; color: var(--ink-soft); }
.hero-actions { display: flex; gap: 0.9rem; margin: 1.6rem 0 1rem; flex-wrap: wrap; }
.hero-note { font-size: 0.85rem; color: var(--ink-soft); }

/* ---- Buttons ---- */
.btn {
  display: inline-block;
  font-family: var(--body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 0.75rem 1.4rem;
  border-radius: 999px;
  text-decoration: none;
  border: 1.5px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}

.btn-primary { background: var(--gold); color: var(--gold-ink); }
.btn-primary:hover { background: var(--gold-bright); transform: translateY(-1px); box-shadow: 0 8px 22px rgba(95, 212, 164, .28); }

.btn-ghost { border-color: var(--parchment-deep); color: var(--ink); background: var(--parchment); }
.btn-ghost:hover { border-color: var(--gold-dim, var(--gold)); }

.btn-google {
  background: #fff;
  color: #3c4043;
  border-color: #dadce0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
}
.btn-google:hover { background: #f8f9fa; }
.google-icon { width: 18px; height: 18px; }

.or-divider {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin: 1.1rem 0;
  color: var(--ink-soft);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.or-divider::before, .or-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--parchment-deep);
}

.btn-block { display: block; width: 100%; text-align: center; margin-top: 0.5rem; }

/* ---- Forms ---- */
.form-card {
  max-width: 440px;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-top: 4px solid var(--gold);
  border-radius: 6px;
  padding: 2rem 2rem 1.6rem;
  margin: 0 auto;
}

.form-sub { color: var(--ink-soft); font-size: 0.92rem; margin-bottom: 1.3rem; }

.account-info-block {
  padding-bottom: 0.6rem;
  border-bottom: 1px dashed var(--parchment-deep);
}
.account-info-block form {
  margin-top: 0.4rem;
}

.form-card label,
.grades-page label:not(.score-field):not(.pill) {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin: 1rem 0 0.3rem;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"] {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--parchment-deep);
  border-radius: 4px;
  font-size: 0.95rem;
  font-family: var(--body);
  background: var(--parchment);
  color: var(--ink);
}

input:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}

input::placeholder,
textarea::placeholder {
  color: var(--ink-soft);
  opacity: 1;
}

.form-footer { margin-top: 1.3rem; font-size: 0.88rem; color: var(--ink-soft); text-align: center; }

/* ---- Profile page ---- */
.profile-section {
  max-width: 520px;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-top: 4px solid var(--gold);
  border-radius: 6px;
  padding: 1.8rem 2rem;
  margin: 0 auto 1.6rem;
}

.profile-section h2 {
  font-family: var(--display);
  font-size: 1.15rem;
  margin: 0 0 0.9rem;
}

.profile-photo-row {
  display: flex;
  align-items: center;
  gap: 1.4rem;
  margin-bottom: 0.6rem;
}

.profile-photo-large {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--gold);
  background: var(--ink-soft);
  flex-shrink: 0;
}
.profile-photo-large.graduation-preview {
  width: 88px;
  height: 118px;
  border-radius: 8px;
  object-fit: cover;
}

.profile-identity h1 {
  font-family: var(--display);
  font-size: 1.35rem;
  margin: 0 0 0.2rem;
}

.profile-identity .username {
  color: var(--ink-soft);
  font-size: 0.88rem;
}

.profile-photo-actions {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

.profile-photo-actions .btn {
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
}

.file-input-label {
  display: inline-block;
  cursor: pointer;
}

.file-input-label input[type="file"] {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}

.status-display {
  font-style: italic;
  color: var(--ink-soft);
  margin: 0.4rem 0 1.1rem;
}

.status-display.empty {
  color: var(--ink-soft);
}

/* ---- Name & username editor ---- */
.account-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 1.2rem;
}
@media (max-width: 700px) {
  .account-form-grid { grid-template-columns: 1fr; }
}

.account-form-grid label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.account-form-grid label i { color: var(--accent-text); font-size: 1rem; }

/* Bakes an "@" into the username field itself, sharing one border with
   the input, so it visually reads as a handle rather than a plain
   text box — the same affordance most social apps use for a username. */
.username-input-group {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--parchment-deep);
  border-radius: 4px;
  overflow: hidden;
  background: var(--parchment);
}
.username-input-group:focus-within {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}
.username-input-group .at-prefix {
  display: flex;
  align-items: center;
  padding: 0 0.6rem;
  background: var(--parchment-deep);
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 0.95rem;
  border-right: 1px solid var(--parchment-deep);
}
.username-input-group input {
  border: none;
  border-radius: 0;
  flex: 1;
  min-width: 0;
}
.username-input-group input:focus { outline: none; }

.account-identity-preview {
  margin: 1rem 0 0;
  padding: 0.7rem 0.9rem;
  background: var(--parchment-deep);
  border-radius: 4px;
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.account-identity-preview strong {
  font-family: var(--display);
  color: var(--ink);
}

.char-count {
  font-size: 0.78rem;
  color: var(--ink-soft);
  text-align: right;
  margin-top: 0.2rem;
}

/* ---- Avatars in admin views ---- */
.avatar-sm {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--parchment-deep);
  border: 1px solid var(--parchment-deep);
  display: block;
}

.avatar-md {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--parchment-deep);
  border: 2px solid var(--gold);
  flex-shrink: 0;
}

.admin-student-heading {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.5rem;
}

/* ---- Pills (grade / track selection) ---- */
.pill-group { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 0.5rem; }
.pill {
  border: 1.5px solid var(--parchment-deep);
  border-radius: 999px;
  padding: 0.5rem 1.1rem;
  cursor: pointer;
  font-size: 0.9rem;
}
.pill input { position: absolute; opacity: 0; pointer-events: none; }
.pill:has(input:checked) { background: var(--gold); color: var(--gold-ink); border-color: var(--gold); }

/* ---- Flash messages ---- */
.flash-stack { margin-bottom: 1.5rem; display: grid; gap: 0.6rem; }
.flash {
  padding: 0.75rem 1rem;
  border-radius: 4px;
  font-size: 0.9rem;
  border-left: 3px solid;
}
.flash-error { background: rgba(226,100,95,0.12); border-color: var(--red); color: var(--red); }
.flash-success { background: rgba(31, 157, 108, 0.12); border-color: var(--green); color: var(--green); }

/* ---- Subject tabs ---- */
.subject-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 1.2rem;
  border-bottom: 1px solid var(--parchment-deep);
  padding-bottom: 0.8rem;
}
.subject-tab {
  text-decoration: none;
  font-size: 0.85rem;
  padding: 0.4rem 0.85rem;
  border-radius: 4px;
  color: var(--ink-soft);
}
.subject-tab.active { background: var(--gold); color: var(--gold-ink); }
.subject-tab:not(.active):hover { background: var(--parchment-deep); }

/* ---- Subject header + progress bar ---- */
.subject-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.subject-header h1 { margin-bottom: 0.4rem; }
.subject-header .form-sub { margin-bottom: 0; max-width: 560px; }

.secondary-view-banner {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  background: rgba(95, 212, 164, 0.1);
  border: 1px solid var(--gold);
  border-radius: 6px;
  padding: 0.9rem 1.1rem;
  margin-bottom: 1.5rem;
}
.secondary-view-banner strong {
  font-family: var(--display);
  font-size: 0.95rem;
  color: var(--ink);
}
.secondary-view-toggle {
  margin-bottom: 1.5rem;
}
.secondary-view-picker {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  padding: 0.9rem 1.1rem;
  margin-bottom: 1.5rem;
}

.subject-progress {
  min-width: 220px;
  flex-shrink: 0;
}
.subject-progress-label {
  font-family: var(--display);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--ink-soft);
  margin-bottom: 0.35rem;
  text-align: right;
}
.subject-progress-track {
  width: 220px;
  max-width: 100%;
  height: 10px;
  background: var(--parchment-deep);
  border-radius: 999px;
  overflow: hidden;
}
.subject-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--green), var(--gold));
  border-radius: 999px;
  transition: width 0.3s ease;
}

/* ---- Choice-group picker (e.g. English III OR English IV) ---- */
.choice-block { background: var(--parchment-deep); }
.choice-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 0.8rem;
}
.choice-option-form { margin: 0; }
.choice-option-btn {
  text-align: left;
  line-height: 1.5;
  padding: 0.7rem 1rem;
}

/* ---- Score entry grid ---- */
.score-block {
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  padding: 1rem 1.2rem 1.3rem;
  margin-bottom: 1.2rem;
}
.score-block legend {
  font-family: var(--display);
  padding: 0 0.4rem;
  color: var(--green);
  font-weight: 700;
}
.score-block-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.score-block-header legend {
  font-family: var(--display);
  padding: 0 0.4rem;
  color: var(--green);
  font-weight: 700;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
.category-grade {
  font-family: var(--body);
  font-weight: 400;
  font-size: 0.75rem;
  color: var(--ink-soft);
}
.category-note {
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin: 0.3rem 0 0.8rem;
}
.score-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: 0.7rem;
}
.category-average {
  text-align: right;
  margin-top: 0.9rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--parchment-deep);
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.category-average strong {
  color: var(--green);
  font-family: var(--display);
  font-size: 1rem;
}
.four-target {
  text-align: right;
  margin-top: 0.4rem;
  font-size: 0.82rem;
  color: var(--accent-text);
  min-height: 1.2em;
}
.four-target strong {
  font-family: var(--display);
  font-size: 0.95rem;
}
.four-target-unreachable {
  color: var(--red);
  font-weight: 600;
}
.score-field { font-size: 0.78rem; color: var(--ink-soft); position: relative; }
.score-field span { display: block; margin-bottom: 0.25rem; }

.score-delete-btn {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1.5px solid #fff;
  border-radius: 50%;
  background: var(--red);
  color: #fff;
  font-size: 0.6rem;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0.75;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.score-delete-btn:hover {
  opacity: 1;
  transform: scale(1.1);
}
.score-delete-btn i {
  font-size: 0.6rem;
}

.pending-remove-check {
  accent-color: var(--red);
  color-scheme: light;
  cursor: pointer;
}
.pending-row-marked td {
  background: rgba(226,100,95,0.10);
  text-decoration: line-through;
  text-decoration-color: rgba(226,100,95,0.6);
}

/* ---- Dashboard table ---- */
.gpa-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.2rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  overflow: hidden;
}
.gpa-table th, .gpa-table td {
  text-align: left;
  padding: 0.7rem 0.9rem;
  font-size: 0.9rem;
  border-bottom: 1px solid var(--parchment-deep);
  vertical-align: middle;
}
.gpa-table th {
  background: var(--parchment-deep);
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.empty-state,
.ap-empty-state {
  margin-top: 1.5rem;
  padding: 2.4rem 1.5rem;
  text-align: center;
  background: var(--page-bg);
  border: 1px solid var(--parchment-deep);
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
.empty-state-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--parchment-deep);
  color: var(--accent-text);
  font-size: 1.5rem;
  margin-bottom: 0.3rem;
}
.empty-state p, .ap-empty-state p { color: var(--ink-soft); margin: 0; max-width: 34ch; }
.empty-state p + a, .empty-state p + .btn { margin-top: 0.5rem; }

/* ---- Guidelines / school resources ---- */
.resource-list { display: grid; gap: 0.7rem; }
.resource-card {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.1rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.resource-card:hover { border-color: var(--gold); box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.resource-card-icon {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 6px;
  background: var(--parchment);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-text);
  font-size: 1.2rem;
}
.resource-card-body { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1; }
.resource-card-title { font-weight: 600; color: var(--ink); }
.resource-card-meta { font-size: 0.82rem; color: var(--ink-soft); }
.resource-card-download { color: var(--ink-soft); font-size: 1.1rem; flex-shrink: 0; }
.resource-card-admin { padding-right: 0.7rem; }
.resource-card-link {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  flex: 1;
  min-width: 0;
  text-decoration: none;
  color: inherit;
}

/* ---- Admin ---- */
.badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  margin-left: 0.4rem;
  white-space: nowrap;
}
.badge-success { background: rgba(31, 157, 108, 0.16); color: var(--green); }
.badge-danger { background: rgba(226,100,95,0.16); color: var(--red); }
.badge-neutral { background: var(--parchment-deep); color: var(--ink-soft); }
.admin-badge-eighth-grade { background: rgba(95, 212, 164, 0.18); color: var(--accent-text); border: 1px solid rgba(95, 212, 164, 0.4); }

.admin-panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.5rem;
  margin-top: 1.5rem;
}
@media (max-width: 700px) {
  .admin-panels { grid-template-columns: 1fr; }
}

/* ---- Admin dashboard ---- */
.admin-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

.admin-stats {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0.9rem;
  margin: 1.5rem 0 1.6rem;
}
@media (max-width: 900px) {
  .admin-stats { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 500px) {
  .admin-stats { grid-template-columns: repeat(2, 1fr); }
}
.admin-stat-card {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-top: 3px solid var(--gold);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.admin-stat-value {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.5rem;
  color: var(--ink);
}
.admin-stat-label {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-soft);
}
.admin-stat-card.admin-stat-warn { border-top-color: var(--gold-bright); }
.admin-stat-card.admin-stat-warn .admin-stat-value { color: var(--accent-text); }
.admin-stat-card.admin-stat-danger { border-top-color: var(--red); }
.admin-stat-card.admin-stat-danger .admin-stat-value { color: var(--red); }

.admin-stat-action {
  margin-top: 0.4rem;
  align-self: flex-start;
  background: var(--gold);
  color: var(--gold-ink);
  border: none;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  cursor: pointer;
}
.admin-stat-action:hover {
  background: var(--gold-bright);
}

.admin-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 0.5rem;
}
.admin-search {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 999px;
  padding: 0.55rem 1rem;
  flex: 1;
  min-width: 220px;
  max-width: 360px;
  color: var(--ink-soft);
}
.admin-search i { font-size: 1rem; }
.admin-search input {
  border: none;
  outline: none;
  font-size: 0.88rem;
  flex: 1;
  font-family: var(--body);
  color: var(--ink);
  background: transparent;
}
.admin-filter-pills {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.admin-filter-pill {
  border: 1px solid var(--parchment-deep);
  background: var(--parchment);
  color: var(--ink-soft);
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.42rem 0.9rem;
  border-radius: 999px;
  cursor: pointer;
}
.admin-filter-pill:hover { background: var(--page-bg); }
.admin-filter-pill.active {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--gold-ink);
}

.admin-student-table th.sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.admin-student-table th.sortable i {
  font-size: 0.8rem;
  opacity: 0.5;
  margin-left: 0.15rem;
}
.admin-student-table th.sortable:hover { color: var(--ink); }
.admin-student-table tbody tr:hover { background: var(--page-bg); }

.admin-row-name {
  text-decoration: none;
  color: var(--ink);
  font-weight: 600;
}
.admin-row-name:hover { color: var(--green); text-decoration: underline; }

.admin-gpa-pill {
  display: inline-block;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.85rem;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: var(--parchment-deep);
  color: var(--ink);
}
.admin-gpa-pill.admin-gpa-high { background: rgba(31, 157, 108, 0.16); color: var(--green); }
.admin-gpa-pill.admin-gpa-low { background: rgba(226,100,95,0.16); color: var(--red); }
.admin-gpa-pill.admin-gpa-empty { background: transparent; color: var(--ink-soft); }

.admin-no-results {
  text-align: center;
  padding: 2rem;
  color: var(--ink-soft);
  border: 1px dashed var(--parchment-deep);
  border-radius: 6px;
  margin-top: 0;
}

.admin-slip-shortcut {
  position: relative;
  padding: 0.4rem 0.6rem !important;
  margin-right: 0.4rem;
  font-size: 1rem !important;
  line-height: 1;
}
.admin-slip-shortcut i {
  vertical-align: -2px;
}
.admin-slip-shortcut.has-pending {
  border-color: var(--gold);
  background: rgba(95, 212, 164, 0.1);
  color: var(--accent-text);
}
.admin-slip-badge {
  position: absolute;
  top: -6px;
  right: -6px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--gold);
  color: var(--ink);
  font-size: 0.62rem;
  font-weight: 800;
  line-height: 16px;
  text-align: center;
  border: 1.5px solid #fff;
}

.admin-section-title {
  font-family: var(--display);
  font-size: 1.2rem;
  margin-top: 2.5rem;
}

/* ---- Congratulations Slip: admin pending/history view ---- */
.slip-history {
  display: grid;
  gap: 1rem;
  margin-top: 1rem;
}
.slip-history-card {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-top: 3px solid var(--gold);
  border-radius: 8px;
  padding: 1.1rem 1.3rem;
}
.slip-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.slip-history-head strong {
  display: block;
  font-family: var(--display);
  font-size: 0.95rem;
}
.slip-undo-btn {
  padding: 0.4rem 0.9rem;
  font-size: 0.78rem;
  color: var(--red);
  border-color: rgba(226, 100, 95, 0.35);
}
.slip-undo-btn:hover {
  background: #fbeceb;
  border-color: var(--red);
}

/* ---- Congratulations Slip: student certificate view ---- */
.slip-certificate-stack {
  display: grid;
  gap: 1.8rem;
}
.slip-certificate {
  position: relative;
  background: linear-gradient(165deg, #eef2fb 0%, #dde6f7 100%);
  border: 1px solid #c9d3ea;
  border-radius: 10px;
  padding: 1.8rem 2rem 1.6rem;
  box-shadow: 0 10px 26px rgba(27, 42, 74, 0.1);
  /* This certificate keeps its own light "paper" look, deliberately
     apart from the site's dark theme (it's meant to read like a
     printed document), so its text uses fixed ink tones rather than
     the site-wide (now light) --ink/--ink-soft variables. */
  color: #1b2a4a;
}
.slip-certificate::before {
  content: "";
  position: absolute;
  inset: 8px;
  border: 1.5px dashed rgba(27, 42, 74, 0.25);
  border-radius: 6px;
  pointer-events: none;
}
.slip-certificate-banner {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.7rem;
  letter-spacing: 0.02em;
  color: #1b2a4a;
  text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.6);
  margin-bottom: 0.3rem;
}
.slip-certificate-sub {
  font-size: 0.95rem;
  color: #435260;
  margin: 0 0 1.1rem;
}
.slip-certificate-table-wrap {
  background: rgba(255, 255, 255, 0.65);
  border-radius: 6px;
  padding: 0.2rem;
}
.slip-certificate-table {
  margin-top: 0;
  background: transparent;
  border: none;
}
.slip-certificate-table th {
  background: rgba(27, 42, 74, 0.08);
}
.slip-certificate-table td,
.slip-certificate-table th {
  border-bottom-color: rgba(27, 42, 74, 0.12);
}
.slip-certificate-note {
  margin: 1rem 0 0;
}
.slip-certificate-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1.4rem;
  padding-top: 1rem;
  border-top: 1px dashed rgba(27, 42, 74, 0.25);
}
.slip-certificate-footer-label {
  display: block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #435260;
}
.slip-certificate-footer-value {
  display: block;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.92rem;
  color: #1b2a4a;
}
.slip-certificate-crest {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.85rem;
  color: #435260;
}
.slip-certificate-crest .crest-mark {
  font-size: 1rem;
  padding: 0.05rem 0.4rem;
  color: var(--gold-ink);
}

/* ---- Congratulations Slip: admin's editable version of the same
   certificate card, used in Release History. Inputs get their own
   light "paper" colors (not the site's dark --page-bg/--parchment
   variables) for the same reason the card itself does — they sit on
   the light certificate background, not the dark dashboard. ---- */
input[type="number"].slip-certificate-score-input {
  width: 80px;
  padding: 0.3rem 0.5rem;
  font-family: var(--body);
  font-size: 0.88rem;
  color: #1b2a4a;
  background: #fff;
  border: 1px solid #c9d3ea;
  border-radius: 4px;
}
.slip-certificate-note-edit {
  display: block;
  margin: 1rem 0 0;
}
.slip-certificate-note-edit textarea {
  display: block;
  width: 100%;
  margin-top: 0.3rem;
  font-family: var(--body);
  font-size: 0.85rem;
  color: #1b2a4a;
  background: #fff;
  border: 1px solid #c9d3ea;
  border-radius: 6px;
  padding: 0.5rem 0.6rem;
  resize: vertical;
}
.slip-certificate-footer-field {
  display: block;
}
input[type="text"].slip-certificate-footer-input {
  display: block;
  margin-top: 0.15rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.92rem;
  color: #1b2a4a;
  background: #fff;
  border: 1px solid #c9d3ea;
  border-radius: 4px;
  padding: 0.25rem 0.5rem;
}
.slip-certificate-actions {
  margin-top: 1rem;
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.slip-certificate-subject-title {
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 0.4rem;
  color: #1b2a4a;
}
.slip-certificate-badge.manual-entry-badge {
  color: #8a6a1a;
  background: rgba(27, 42, 74, 0.08);
}
.slip-certificate-empty {
  text-align: center;
  padding: 2rem 1rem;
  margin-bottom: 1rem;
  color: #435260;
}
.slip-certificate-empty i {
  font-size: 1.6rem;
  color: #8a9ac0;
}
.slip-certificate-empty p {
  margin: 0.5rem 0 0;
}

/* ---- Footer ---- */
.site-footer {
  text-align: center;
  padding: 1.5rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.9rem;
  flex-wrap: wrap;
}
.footer-link {
  color: var(--ink-soft);
  text-decoration: underline;
}
.footer-link:hover { color: var(--ink); }

.static-page {
  max-width: 720px;
  margin: 0 auto;
  padding: 2.5rem 1.4rem 4rem;
  line-height: 1.6;
}
.static-page h1 { margin-bottom: 0.2rem; }
.static-page-updated {
  color: var(--ink-soft);
  font-size: 0.85rem;
  margin-bottom: 1.6rem;
}
.static-page h2 {
  margin-top: 2rem;
  margin-bottom: 0.5rem;
  font-size: 1.15rem;
}
.static-page ul { padding-left: 1.3rem; }
.static-page li { margin-bottom: 0.4rem; }

/* ---- AP tier badge + ribbon glow ---- */
.ap-tier-badge {
  font-family: var(--body);
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  white-space: nowrap;
}
.ap-tier-badge.tier-1 { background: #6b6f76; color: #f5f5f5; }
.ap-tier-badge.tier-2 { background: #4a7a5c; color: #ecf9f0; }
.ap-tier-badge.tier-3 { background: var(--gold); color: var(--gold-ink); }
.ap-tier-badge.tier-4 {
  background: var(--gold-bright);
  color: var(--gold-ink);
  box-shadow: 0 0 8px rgba(95, 212, 164, 0.7);
}

.gpa-ribbon.glow-tier-2 { box-shadow: 0 4px 16px -2px rgba(74, 122, 92, 0.45); }
.gpa-ribbon.glow-tier-3 { box-shadow: 0 4px 22px -2px rgba(95, 212, 164, 0.55); }
.gpa-ribbon.glow-tier-3 .gpa-value { text-shadow: 0 0 10px rgba(95, 212, 164, 0.7); }
.gpa-ribbon.glow-tier-4 {
  box-shadow: 0 4px 30px -2px rgba(95, 212, 164, 0.75);
  border-top: 1px solid rgba(95, 212, 164, 0.5);
}
.gpa-ribbon.glow-tier-4 .gpa-value { text-shadow: 0 0 16px rgba(95, 212, 164, 0.95); }

/* ---- Dashboard two-column layout ---- */
.dashboard-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 1.5rem;
  align-items: start;
}
@media (max-width: 900px) {
  .dashboard-grid { grid-template-columns: 1fr; }
}

/* ---- AP Exams panel ---- */
.ap-panel {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-top: 4px solid var(--gold);
  border-radius: 6px;
  padding: 1.5rem;
}
.ap-panel-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 1.2rem;
  gap: 1rem;
}
.ap-panel-header h2 {
  font-family: var(--display);
  font-size: 1.2rem;
  margin: 0;
  color: var(--ink);
}
.ap-grade-group {
  background: var(--parchment);
  border-radius: 8px;
  padding: 1rem;
  margin-bottom: 1rem;
}
.ap-grade-group:last-child { margin-bottom: 0; }
.ap-grade-label {
  font-family: var(--body);
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--ink);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 0.8rem;
}
.ap-card-list { display: flex; flex-direction: column; gap: 0.7rem; }
.ap-card {
  position: relative;
  overflow: hidden;
  background: var(--parchment);
  border-left: 6px solid var(--ap-color);
  border-radius: 4px;
  padding: 0.85rem 1.1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  text-decoration: none;
  color: inherit;
}
.ap-card-icon-bg {
  position: absolute;
  right: 8px;
  bottom: -16px;
  font-size: 4.6rem;
  color: var(--ap-color);
  opacity: 0.09;
}
.ap-card-score {
  font-family: var(--display);
  font-size: 2.4rem;
  font-weight: bold;
  color: var(--ap-color);
  line-height: 1;
  min-width: 44px;
  z-index: 1;
}
.ap-card-body { z-index: 1; min-width: 0; }
.ap-card-title-row { display: flex; align-items: center; gap: 8px; }
.ap-card-icon-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  background: var(--ap-bg);
  flex-shrink: 0;
}
.ap-card-icon-chip i { font-size: 14px; color: var(--ap-color); }
.ap-card-subject {
  font-family: var(--body);
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ap-card-qualifier {
  font-family: var(--body);
  font-size: 0.73rem;
  color: var(--ink-soft);
  margin: 3px 0 0 34px;
}
.ap-add-link {
  font-family: var(--body);
  font-size: 0.8rem;
  font-weight: 600;
  background: var(--gold);
  color: var(--gold-ink);
  border: none;
  border-radius: 4px;
  padding: 0.55rem 1rem;
  text-decoration: none;
  white-space: nowrap;
}
.ap-add-link:hover { background: var(--gold-bright); }

select {
  width: 100%;
  padding: 0.6rem 2.2rem 0.6rem 0.7rem;
  border: 1px solid var(--parchment-deep);
  border-radius: 4px;
  font-size: 0.95rem;
  font-family: var(--body);
  color: var(--ink);
  /* Safari ignores padding/height on a native select unless its
     built-in look is turned off, which is why dropdowns rendered as a
     thin bar there. Draw our own chevron instead. */
  -webkit-appearance: none;
  appearance: none;
  background: var(--parchment) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23adadb8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 0.8rem center;
}
select:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}

/* ---- AP card: in-progress (no score yet) state ---- */
.ap-card-pending {
  border-left-style: dashed;
}
.ap-card-score-icon {
  font-size: 1.9rem;
  color: var(--ap-color);
  min-width: 44px;
  text-align: center;
  z-index: 1;
}
.ap-pending-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ap-color);
  margin-right: 5px;
  animation: ap-pulse 1.6s ease-in-out infinite;
}
@keyframes ap-pulse {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}

/* =====================================================================
   Dashboard shell (PACE / AP / Chat / Feed tabs)
   ===================================================================== */

body.dash-body .site-main {
  max-width: none;
  padding: 0;
}
body.dash-body .site-footer { display: none; }

/* Every dashboard page (the icon rail + main panel layout, see
   _dash_sidebar.html) behaves like a fixed app screen: the rail and
   the header/GPA ribbon stay in place, and only the main panel (or,
   on chat, its own message list — see .dash-panel-flush below)
   scrolls. .dash-shell gets a real ceiling — not just enough to look
   right on a short page — so nothing inside it (a long rail, a tall
   panel) can push the actual page taller than the viewport and make
   the whole page scroll as one block instead. This used to be scoped
   to chat only; generalized so every page gets the same "rail doesn't
   move when you scroll the content, and vice versa" behavior instead
   of just one.

   The actual `height` value is set by JS in base.html, not a fixed
   calc() here — a hardcoded "header + ribbon are ~132px" guess breaks
   the instant a flash message (base.html's .flash-stack, rendered
   above .dash-shell on ANY page load that has one pending) adds
   unaccounted-for height above it, silently reopening the whole-page-
   scrolls bug this rule exists to prevent. Measuring .dash-shell's own
   actual top offset at load time is correct regardless of what
   happens to be rendered above it on any given page. */
.dash-shell {
  display: flex;
  align-items: stretch;
  overflow: hidden;
}

/* ---- Left icon rail ---- */
.dash-rail {
  flex-shrink: 0;
  width: 84px;
  background: var(--parchment);
  border-right: 1px solid var(--parchment-deep);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 1.4rem 0;
  gap: 0.3rem;
  /* Lets the rail scroll on its own if its content (nav buttons) is
     taller than whatever height it's stretched to, now that
     .dash-shell's own height is always bounded (see its own rule
     above) — so a long rail scrolls internally instead of pushing
     the whole page taller. */
  overflow-y: auto;
  min-height: 0;
}
.dash-rail-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.85rem 0.3rem;
  margin: 0 0.5rem;
  border-radius: 8px;
  text-decoration: none;
  color: var(--ink-soft);
  font-size: 0.68rem;
  letter-spacing: 0.03em;
}
.dash-rail-btn i { font-size: 1.4rem; }
.dash-rail-btn:hover { background: var(--accent-soft); color: var(--ink); }
.dash-rail-btn.active {
  background: var(--accent-soft);
  color: var(--accent-text);
  font-weight: 600;
}
.dash-rail-btn { position: relative; }
.dash-rail-badge {
  position: absolute;
  top: 0.35rem;
  right: 0.55rem;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
}

/* ---- Right-hand panel ---- */
.dash-panel {
  flex: 1;
  min-width: 0;
  padding: 2rem 2.5rem 3rem;
  overflow-y: auto;
}
.dash-panel-flush {
  padding: 0;
  display: flex;
  /* Chat needs its inner layout (roster, header, composer) pinned in
     place while only the message list scrolls, rather than just
     letting .dash-panel's own overflow-y:auto (below) scroll the
     whole thing as one block. Its real height comes from stretching
     to match its parent .dash-shell, whose own height is measured and
     set by JS in base.html (see .dash-shell's own rule above for why
     that's JS-driven rather than a fixed calc()) — `overflow: hidden`
     here is just a safety net in case anything inside still doesn't
     fit that. Scoped to this one class (chat's only user) rather than
     .dash-panel generally, which scrolls its content directly. */
  overflow: hidden;
}
@media (max-width: 700px) {
  .dash-panel { padding: 1.4rem 1.2rem 2.5rem; }
  .dash-rail { width: 64px; }
  .dash-rail-btn span { display: none; }
}

/* =====================================================================
   Chat tab (iMessage-style)
   ===================================================================== */

.chat-shell {
  display: flex;
  flex: 1;
  min-width: 0;
}

.chat-roster {
  width: 280px;
  flex-shrink: 0;
  border-right: 1px solid var(--parchment-deep);
  display: flex;
  flex-direction: column;
  background: var(--parchment);
}
.chat-roster-header {
  font-family: var(--display);
  font-weight: 700;
  padding: 1.2rem 1.2rem 0.8rem;
  color: var(--ink-soft);
}
.chat-roster-list { overflow-y: auto; flex: 1; min-height: 0; }
.chat-roster-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 1.2rem;
  text-decoration: none;
  color: var(--ink);
  border-left: 3px solid transparent;
}
.chat-roster-item:hover { background: var(--parchment); }
.chat-roster-item.active { background: var(--parchment); border-left-color: var(--gold); }
.chat-roster-item-body { min-width: 0; flex: 1; }
.chat-roster-item-top { display: flex; align-items: center; justify-content: space-between; gap: 0.4rem; }
.chat-roster-name { font-size: 0.9rem; font-weight: 600; }
.chat-unread-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--red); flex-shrink: 0; }
.chat-roster-preview {
  display: block;
  font-size: 0.78rem;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chat-roster-empty { padding: 1rem 1.2rem; color: var(--ink-soft); font-size: 0.88rem; }

.chat-window {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--parchment);
}
.chat-window-header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 1rem 1.4rem;
  border-bottom: 1px solid var(--parchment-deep);
  background: var(--parchment);
  font-weight: 600;
}
.chat-back-btn {
  display: none;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin: -0.3rem 0.1rem -0.3rem -0.5rem;
  border-radius: 50%;
  color: var(--ink-soft);
  font-size: 1.3rem;
}
.chat-back-btn:hover { background: var(--parchment); }

/* Stack roster/window on narrow screens, iMessage-app style: show the
   list by default, and only the open thread once a student is picked. */
@media (max-width: 700px) {
  .chat-roster { width: 100%; }
  .chat-shell.chat-has-partner .chat-roster { display: none; }
  .chat-shell:not(.chat-has-partner) .chat-window { display: none; }
  .chat-back-btn { display: flex; }
}
.chat-empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  color: var(--ink-soft);
}

.chat-messages {
  flex: 1;
  /* Without this, a flex item's default min-height:auto refuses to
     shrink below its own content size — meaning "flex:1" here would
     lose to "however tall all the bubbles add up to", overflow-y:auto
     would never actually trigger, and .dash-panel-flush's bounded
     height above would just get pushed open instead of clipping this
     element. This is what makes it a real internally-scrolling pane. */
  min-height: 0;
  overflow-y: auto;
  padding: 1.2rem 1.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.bubble-row { display: flex; flex-direction: column; max-width: 68%; position: relative; }
.bubble-row.grouped { margin-top: -0.45rem; }
.bubble-row.mine { align-self: flex-end; align-items: flex-end; }
.bubble-row.theirs { align-self: flex-start; align-items: flex-start; }
.bubble {
  padding: 0.55rem 0.85rem;
  border-radius: 16px;
  font-size: 0.92rem;
  line-height: 1.4;
  word-break: break-word;
}
.bubble-row.mine .bubble { background: var(--gold); color: var(--gold-ink); border-bottom-right-radius: 4px; }
.bubble-row.theirs .bubble { background: var(--parchment); color: var(--ink); border: 1px solid var(--parchment-deep); border-bottom-left-radius: 4px; }
.bubble-text { white-space: pre-wrap; }
.bubble-deleted-text { display: flex; align-items: center; gap: 0.3rem; font-style: italic; opacity: 0.7; }

/* Reply/delete icons — hidden until the bubble is hovered (or tapped
   on touch, via :focus-within on the button), same "reveal on hover"
   pattern as most chat apps rather than permanent clutter next to
   every single bubble. */
.bubble-actions {
  position: absolute;
  top: -0.35rem;
  display: flex;
  gap: 0.25rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.bubble-row.mine .bubble-actions { right: 0; }
.bubble-row.theirs .bubble-actions { left: 0; }
.bubble-row:hover .bubble-actions,
.bubble-actions:focus-within {
  opacity: 1;
  pointer-events: auto;
}
.bubble-action-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--parchment-deep);
  color: var(--ink-soft);
  font-size: 0.75rem;
  border: 1px solid var(--parchment-deep);
}
.bubble-action-btn:hover { color: var(--ink); background: var(--accent-soft); }
.bubble-delete-btn:hover { color: var(--red); }

/* Quoted-message preview shown above a reply's own bubble content. */
.bubble-quote {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.35rem 0.55rem;
  margin-bottom: 0.4rem;
  border-left: 3px solid var(--gold-bright);
  background: rgba(0,0,0,0.12);
  border-radius: 6px;
  font-size: 0.78rem;
}
.bubble-row.mine .bubble-quote { background: rgba(0,0,0,0.14); }
.bubble-quote-author { font-weight: 700; opacity: 0.85; }
.bubble-quote-snippet {
  opacity: 0.75;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 240px;
}

/* "Replying to ..." banner above the composer, with a cancel (x)
   button — cleared on send or explicit cancel. */
.chat-reply-preview {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.5rem 1.2rem;
  background: var(--parchment);
  border-top: 1px solid var(--parchment-deep);
  font-size: 0.82rem;
}
.chat-reply-preview[hidden] { display: none; }
.chat-reply-preview-body { min-width: 0; display: flex; flex-direction: column; gap: 0.1rem; }
.chat-reply-preview-label { color: var(--ink-soft); }
.chat-reply-preview-label span { color: var(--accent-text); font-weight: 600; }
.chat-reply-preview-snippet {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 420px;
  opacity: 0.85;
}
#chat-reply-cancel {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  color: var(--ink-soft);
  flex-shrink: 0;
}
#chat-reply-cancel:hover { background: var(--parchment-deep); color: var(--ink); }
.bubble-img { max-width: 220px; max-height: 220px; border-radius: 10px; display: block; margin-bottom: 0.3rem; }
.bubble-file {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  text-decoration: none;
  color: inherit;
  font-size: 0.85rem;
  margin-bottom: 0.3rem;
  padding: 0.3rem 0.5rem;
  background: rgba(0,0,0,0.06);
  border-radius: 8px;
}
.bubble-meta { display: flex; align-items: center; gap: 5px; margin: 0.15rem 0.3rem; }
.bubble-time { font-size: 0.7rem; color: var(--ink-soft); }
.bubble-unread {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--accent-text);
  transition: opacity 0.4s ease;
}

/* Shared-post card, rendered inside a chat bubble when a feed post is
   shared into the conversation. */
.chat-shared-card {
  display: flex;
  gap: 0.55rem;
  text-decoration: none;
  color: inherit;
  background: rgba(0,0,0,0.04);
  border-radius: 10px;
  padding: 0.6rem 0.7rem;
  min-width: 200px;
  max-width: 260px;
}
.bubble-row.theirs .chat-shared-card { background: var(--parchment); }
.chat-shared-card-avatar { width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0; object-fit: cover; }
.chat-shared-card-body { min-width: 0; flex: 1; }
.chat-shared-card-author { display: block; font-size: 0.78rem; font-weight: 700; margin-bottom: 0.15rem; }
.chat-shared-card-snippet { margin: 0 0 0.3rem; font-size: 0.78rem; line-height: 1.35; opacity: 0.9; }
.chat-shared-card-img { width: 100%; max-height: 100px; object-fit: cover; border-radius: 6px; margin-bottom: 0.3rem; display: block; }
.chat-shared-card-cta { display: flex; align-items: center; gap: 3px; font-size: 0.7rem; font-weight: 600; color: var(--accent-text); }
.chat-shared-card-missing { align-items: center; color: var(--ink-soft); font-style: italic; font-size: 0.8rem; }

.chat-composer {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.8rem 1.2rem;
  background: var(--parchment);
  border-top: 1px solid var(--parchment-deep);
}
.chat-attach-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  color: var(--ink-soft);
  cursor: pointer;
  flex-shrink: 0;
}
.chat-attach-btn:hover { background: var(--parchment-deep); }
.chat-file-chip {
  font-size: 0.78rem;
  background: var(--parchment-deep);
  padding: 0.25rem 0.6rem;
  border-radius: 999px;
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 0;
}
#chat-body-input {
  flex: 1;
  border: 1px solid var(--parchment-deep);
  border-radius: 999px;
  padding: 0.55rem 1rem;
  font-size: 0.92rem;
  font-family: var(--body);
  background: var(--parchment);
}
#chat-body-input:focus { outline: none; border-color: var(--gold); }
.chat-send-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: none;
  background: var(--gold);
  color: var(--gold-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
}
.chat-send-btn:hover { background: var(--gold-bright); }

/* =====================================================================
   Feed tab (group board)
   ===================================================================== */

.feed-composer {
  display: flex;
  gap: 0.8rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 10px;
  padding: 1rem 1.2rem;
  margin-bottom: 1.6rem;
}
.feed-composer-main { flex: 1; display: flex; flex-direction: column; gap: 0.6rem; }
.feed-composer textarea {
  width: 100%;
  border: 1px solid var(--parchment-deep);
  border-radius: 8px;
  padding: 0.6rem 0.75rem;
  font-family: var(--body);
  font-size: 0.92rem;
  resize: vertical;
  background: var(--parchment);
}
.feed-composer textarea:focus { outline: none; border-color: var(--gold); }
.feed-composer-footer { display: flex; align-items: center; gap: 0.7rem; }
.feed-composer-footer .btn { margin-left: auto; padding: 0.5rem 1.2rem; }

.feed-list { display: flex; flex-direction: column; gap: 1rem; }
.feed-post {
  display: flex;
  gap: 0.8rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 10px;
  padding: 1rem 1.2rem;
}
.feed-post-body { min-width: 0; flex: 1; }
.feed-post-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.3rem; }
.feed-post-author { font-weight: 700; font-family: var(--display); }
.feed-post-time { font-size: 0.78rem; color: var(--ink-soft); }
.feed-post-delete-form { margin-left: auto; }
.feed-post-delete {
  border: none;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
  padding: 0.2rem;
  font-size: 0.95rem;
  line-height: 1;
}
.feed-post-delete:hover { color: var(--red); }

.feed-post-actions { display: flex; align-items: center; gap: 0.4rem; margin-top: 0.6rem; }
.feed-reaction-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--parchment-deep);
  background: var(--parchment);
  border-radius: 999px;
  padding: 0.35rem 0.7rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.feed-reaction-btn:hover { border-color: var(--gold); }
.feed-share-btn { margin-left: auto; }
.feed-like-btn.active { background: var(--gold); color: var(--gold-ink); border-color: var(--gold); }
/* Love uses a dedicated pink — Instagram-style filled heart — rather
   than the site's crimson, since crimson already means "error/danger"
   elsewhere on the site and this needs to read as delight, not alarm. */
.feed-love-btn.active { background: #e0447c; color: #fff; border-color: #e0447c; }
.feed-love-btn.active i { color: #fff; }

.feed-share-panel {
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--parchment-deep);
}
.feed-share-label { font-size: 0.72rem; color: var(--ink-soft); margin: 0 0 0.4rem; }
.feed-share-contacts { display: flex; flex-direction: column; gap: 0.35rem; }
.feed-share-contact {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.35rem 0.6rem;
  border-radius: 8px;
  background: var(--parchment);
  font-size: 0.8rem;
}
.feed-share-send-btn {
  border: none;
  background: var(--gold);
  color: var(--gold-ink);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  font-size: 0.72rem;
  cursor: pointer;
}
.feed-share-send-btn:disabled { background: var(--green); cursor: default; opacity: 0.9; }
.feed-share-empty { font-size: 0.8rem; color: var(--ink-soft); font-style: italic; margin: 0; }
.feed-post-text { margin: 0 0 0.5rem; white-space: pre-wrap; font-size: 0.94rem; }
.feed-post-img { max-width: 100%; max-height: 360px; border-radius: 8px; display: block; }

/* ---- Extracurriculars ---- */
.ec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1rem;
}

.ec-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 12px;
  padding: 1.1rem 1.3rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.ec-card:hover { border-color: var(--gold); box-shadow: 0 2px 10px -4px rgba(0,0,0,0.12); }

.ec-card-ring { position: relative; width: 84px; height: 84px; flex-shrink: 0; }
.ec-card-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.ec-ring-track { fill: none; stroke: var(--parchment-deep); stroke-width: 12; }
.ec-ring-fill { fill: none; stroke: var(--gold); stroke-width: 12; stroke-linecap: round; transition: stroke-dashoffset 0.4s ease; }
.ec-ring-center {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 14px;
}
.ec-ring-count { font-size: 1.3rem; font-weight: 700; color: var(--ink); line-height: 1.1; }
.ec-ring-label {
  font-size: 0.55rem;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-align: center;
  line-height: 1.2;
  word-break: break-word;
}

.ec-card-body { min-width: 0; }
.ec-card-head { display: flex; align-items: center; gap: 0.4rem; }
.ec-card-head i { font-size: 1.1rem; color: var(--accent-text); }
.ec-card-name { font-family: var(--display); font-weight: 700; font-size: 1.05rem; }
.ec-card-full-name { margin: 0.1rem 0 0.5rem; font-size: 0.82rem; color: var(--ink-soft); }
.ec-card-hours { margin: 0; font-size: 1.1rem; font-weight: 700; color: var(--ink); }
.ec-card-sub { margin: 0.15rem 0 0; font-size: 0.78rem; color: var(--ink-soft); }

.ec-back-link {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  text-decoration: none;
  margin-bottom: 1rem;
}
.ec-back-link:hover { color: var(--accent-text); }

.ec-detail-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.4rem;
  flex-wrap: wrap;
}
.ec-detail-stat { text-align: right; }
.ec-detail-stat-value { display: block; font-size: 2rem; font-weight: 700; color: var(--accent-text); line-height: 1.1; }
.ec-detail-stat-label { font-size: 0.75rem; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.03em; }

.ec-calendar-shell {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 12px;
  padding: 1.2rem 1.4rem;
  max-width: 420px;
}
.ec-calendar-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.8rem;
}
.ec-calendar-nav .btn { padding: 0.3rem 0.6rem; }
.ec-month-label { font-family: var(--display); font-weight: 700; font-size: 1.05rem; }

.ec-weekday-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-size: 0.7rem;
  color: var(--ink-soft);
  margin-bottom: 0.4rem;
}

.ec-calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.ec-day {
  aspect-ratio: 1;
  border: none;
  border-radius: 6px;
  font-size: 0.78rem;
  background: transparent;
  color: var(--ink);
  cursor: default;
}
.ec-day-muted { color: var(--parchment-deep); }
.ec-day-future {
  color: var(--ink-soft);
  border: 1.5px dashed var(--parchment-deep);
  cursor: default;
}
.ec-day-loggable {
  border: 1.5px solid var(--parchment-deep);
  cursor: pointer;
  font-weight: 600;
}
.ec-day-loggable:hover { border-color: var(--gold); }
.ec-day-checked {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}

.ec-calendar-note {
  margin: 0.9rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-soft);
}

/* ==========================================================================
   PACE dashboard redesign — credit-weighted "volume boxes" per category,
   non-PACE tick-mark credits, and the Service Internship module.
   ========================================================================== */

.progress-stack {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  min-width: 240px;
  flex-shrink: 0;
}
.progress-stack .subject-progress { min-width: 0; }
.progress-stack .subject-progress-track { width: 100%; }

.credit-fill { background: linear-gradient(90deg, var(--gold), var(--gold-bright)); }
.credit-over-badge {
  display: inline-block;
  margin-left: 0.5rem;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--green);
  background: rgba(31, 157, 108, 0.12);
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
}

.gpa-hero {
  display: flex;
  align-items: center;
  gap: 2.2rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 8px;
  padding: 1rem 1.4rem;
  margin-bottom: 1.6rem;
  flex-wrap: wrap;
}
.gpa-hero-stat {
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
}
.gpa-hero-stat-secondary { opacity: 0.85; }
.gpa-hero-stat-secondary .gpa-hero-value { font-size: 1.9rem; }
.gpa-hero-value {
  font-family: var(--display);
  font-weight: 700;
  font-size: 2.4rem;
  color: var(--ink);
  line-height: 1;
}
.gpa-hero-label {
  font-size: 0.85rem;
  color: var(--ink-soft);
  line-height: 1.3;
}

.pace-subject-group { margin-bottom: 1.8rem; }
.pace-subject-group-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.7rem;
  flex-wrap: wrap;
}
.pace-subject-group-header h2 {
  font-family: var(--display);
  font-size: 1.15rem;
  margin: 0;
}
.pace-subject-group-count {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.pace-box-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.9rem;
}
.pace-box {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 8px;
  padding: 0.9rem 1rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.pace-box:hover {
  border-color: var(--gold);
  box-shadow: 0 2px 10px -4px rgba(0,0,0,0.14);
  transform: translateY(-1px);
}
.pace-box-complete { border-color: var(--green); background: rgba(31, 157, 108, 0.04); }
.pace-box-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  /* Reserves space for a 2-line course name (e.g. "World Geography")
     so every card's name area is the same height whether its title
     wraps to 1 or 2 lines — otherwise the gold PACE-count bar below
     ends up at a different vertical position card to card, since each
     card is just a flex column that stacks its content top-down. */
  min-height: 2.4rem;
}
.pace-box-name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.92rem;
  line-height: 1.25;
}
.pace-box-check { color: var(--green); font-size: 1.1rem; flex-shrink: 0; }
.pace-box .category-grade { display: block; min-height: 1.1em; }

.pace-box-volume {
  position: relative;
  height: 34px;
  border-radius: 6px;
  background: var(--parchment-deep);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.pace-box-volume-fill {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  transition: height 0.3s ease;
}
.pace-box-volume-label {
  position: relative;
  z-index: 1;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.78rem;
  color: var(--ink);
  background: var(--parchment);
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  padding: 0.05rem 0.4rem;
  border-radius: 4px;
}

.pace-box-stats {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.76rem;
  color: var(--ink-soft);
}
.pace-box-credits {
  font-weight: 700;
  color: var(--accent-text);
  background: rgba(95, 212, 164, 0.14);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
}

/* ---- Non-PACE / Internship tick-mark credits ---- */
.tick-credit-list { display: flex; flex-direction: column; gap: 0.6rem; max-width: 480px; }
.tick-credit-form { margin: 0; }
.tick-credit-item {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  cursor: pointer;
  text-align: left;
  font-family: var(--body);
  color: inherit;
  text-decoration: none;
}
.tick-credit-item:hover { border-color: var(--gold); }
.tick-credit-item-checked { border-color: var(--green); background: rgba(31, 157, 108, 0.05); }
.tick-credit-box {
  flex-shrink: 0;
  width: 22px; height: 22px;
  border-radius: 5px;
  border: 1.5px solid var(--gold);
  display: flex; align-items: center; justify-content: center;
  color: var(--green);
}
.tick-credit-item-checked .tick-credit-box { border-color: var(--green); background: rgba(31, 157, 108, 0.14); }
.tick-credit-name { flex: 1; font-weight: 600; font-size: 0.92rem; }
.tick-credit-value {
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--accent-text);
  background: rgba(95, 212, 164, 0.14);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
  flex-shrink: 0;
}

/* ---- Internship checklist ---- */
.checklist { display: flex; flex-direction: column; gap: 0.6rem; }
.checklist-item {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.9rem;
  cursor: pointer;
}
.internship-checklist-item {
  background: var(--page-bg);
  border: 1px solid var(--parchment-deep);
  border-radius: 8px;
  padding: 0.75rem 0.9rem;
  transition: border-color 0.15s ease;
}
.internship-checklist-item:has(input:checked) {
  border-color: var(--green);
  background: rgba(31, 157, 108, 0.05);
}
.checklist-item input[type="checkbox"] {
  margin-top: 0.2rem;
  width: 17px; height: 17px;
  accent-color: var(--green);
  flex-shrink: 0;
}
.project-desc-input {
  width: 100%;
  margin: -0.3rem 0 0.4rem 1.9rem;
  max-width: calc(100% - 1.9rem);
  padding: 0.4rem 0.6rem;
  font-size: 0.82rem;
  border: 1px solid var(--parchment-deep);
  border-radius: 5px;
  font-family: var(--body);
}

/* ==========================================================================
   PACE box category icons (chem flask, physics atom, etc.)
   ========================================================================== */
.pace-box { position: relative; }
.pace-box-icon-bg {
  position: absolute;
  right: 4px;
  bottom: -10px;
  font-size: 3.2rem;
  color: var(--accent-text);
  opacity: 0.10;
  pointer-events: none;
}
.pace-box-icon-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85rem;
  color: var(--accent-text);
  margin-right: 0.3rem;
}
.pace-box-top, .pace-box-stats, .pace-box-volume { position: relative; z-index: 1; }
.pace-subject-group-header h2 { display: flex; align-items: center; gap: 0.5rem; }
.pace-subject-group-header h2 i { color: var(--accent-text); font-size: 1.05rem; }

/* ==========================================================================
   Course setup — track note redesign
   ========================================================================== */
.track-note {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  background: var(--parchment-deep);
  border-left: 3px solid var(--gold);
  border-radius: 6px;
  padding: 0.8rem 1rem;
  margin-top: -0.2rem;
  margin-bottom: 0.6rem;
  font-size: 0.82rem;
  color: var(--ink-soft);
  line-height: 1.5;
}
.track-note i { color: var(--accent-text); font-size: 1.1rem; flex-shrink: 0; margin-top: 0.1rem; }

.status-toggle {
  display: flex;
  align-items: stretch;
  gap: 0.6rem;
  margin-bottom: 1.4rem;
}
.status-toggle .pill {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1.25;
}

/* ==========================================================================
   Graduate dashboard — tile-based landing instead of PACE boxes
   ========================================================================== */
.grad-hero {
  background: linear-gradient(135deg, var(--hero-bg), var(--hero-bg-2));
  color: #fff;
  border-radius: 10px;
  padding: 1.6rem 1.8rem;
  margin-bottom: 1.6rem;
  display: flex;
  align-items: center;
  gap: 1.1rem;
}
.grad-hero-crest {
  flex-shrink: 0;
  width: 48px; height: 48px;
  border-radius: 50%;
  border: 2px solid var(--gold);
  background: rgba(255,255,255,0.06);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem;
  color: var(--accent-text);
}
.grad-hero h1 { color: #fff; margin-bottom: 0.3rem; }
.grad-hero p { color: rgba(255,255,255,0.75); margin: 0; }

.grad-tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}
.grad-tile {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 10px;
  padding: 1.3rem 1.4rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.grad-tile:hover { border-color: var(--gold); transform: translateY(-2px); box-shadow: 0 6px 16px -8px rgba(0,0,0,0.2); }
.grad-tile-highlight { background: rgba(95, 212, 164, 0.06); border-color: var(--gold); }
.grad-tile-icon {
  width: 42px; height: 42px;
  border-radius: 50%;
  border: 1.5px solid var(--gold);
  background: var(--page-bg);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem;
  color: var(--ink);
}
.grad-tile-title { font-family: var(--display); font-weight: 700; font-size: 1.05rem; }
.grad-tile-desc { font-size: 0.82rem; color: var(--ink-soft); margin: 0; }

/* ==========================================================================
   Graduates showcase page (under the AP tab area)
   ========================================================================== */
.grad-card-list {
  display: flex;
  flex-wrap: wrap;
  gap: 1.4rem;
}
.grad-card {
  display: flex;
  flex-direction: column;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 12px;
  overflow: hidden;
  /* Three per row, wrapping to a new row after that — accounts for
     the two 1.4rem gaps between three columns. min-width lets it
     naturally drop to 2-per-row, then 1-per-row, on narrower screens
     instead of squishing indefinitely. */
  flex: 0 1 calc((100% - 2 * 1.4rem) / 3);
  min-width: 300px;
}
.grad-card-photo {
  width: 100%;
  /* Long, wide banner rather than a small avatar — the graduation
     photo is the headline of the card, not a side detail. Height is
     viewport-relative with a sane cap so it stretches nicely on large
     screens without ever becoming an absurd wall of image on a tall
     monitor. */
  height: min(46vh, 480px);
  object-fit: cover;
  object-position: center 20%;
  display: block;
  background: var(--parchment-deep);
}
.grad-card-body { flex: 1; min-width: 0; padding: 1.3rem 1.5rem 1.6rem; }
.grad-card-name-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.grad-card-name { font-family: var(--display); font-weight: 700; font-size: 1.4rem; }
.grad-card-year {
  font-family: var(--body);
  font-weight: 600;
  font-size: 0.72rem;
  color: var(--accent-text);
  border: 1px solid var(--gold);
  border-radius: 999px;
  padding: 0.1rem 0.55rem;
  vertical-align: middle;
  margin-left: 0.3rem;
}
.grad-card-college {
  font-size: 1rem;
  color: var(--green);
  font-weight: 600;
}
.grad-card-track { font-size: 0.85rem; color: var(--ink-soft); margin: 0.2rem 0 0.9rem; }

.grad-advice-quote {
  font-family: var(--display);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--ink);
  border-left: 3px solid var(--gold);
  padding: 0.2rem 0 0.2rem 0.9rem;
  margin: 0 0 0.9rem;
}

.grad-stat-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.7rem; }
.grad-stat-chip {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink);
  background: var(--parchment-deep);
  border-radius: 999px;
  padding: 0.25rem 0.75rem;
}
.grad-stat-chip strong { color: var(--accent-text); }

.grad-ap-list { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.7rem; }
.grad-ap-chip {
  font-size: 0.76rem;
  color: var(--ink-soft);
  border: 1px solid var(--parchment-deep);
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
}

.grad-universities { font-size: 0.85rem; color: var(--ink-soft); margin: 0; }
.grad-universities strong { color: var(--ink); }

.grad-ap-edit-list { list-style: none; padding: 0; margin: 0 0 0.8rem; }
.grad-ap-edit-list li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--parchment-deep);
  font-size: 0.85rem;
}
.grad-ap-edit-list li:last-child { border-bottom: none; }
.grad-ap-edit-list a { font-size: 0.78rem; flex-shrink: 0; margin-left: 0.8rem; }

/* ==========================================================================
   Graduate profile edit form
   ========================================================================== */
.grad-profile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 1rem;
}

/* ==========================================================================
   Scan-a-progress-report feature
   ========================================================================== */
.scan-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-weight: 700;
}
.scan-cta i { font-size: 1.1rem; color: var(--accent-text); }

.scan-upload-card {
  max-width: 460px;
  margin: 0 auto;
}
.scan-upload-drop {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  border: 2px dashed var(--gold);
  border-radius: 12px;
  padding: 2.6rem 1.5rem;
  text-align: center;
  cursor: pointer;
  background: var(--parchment-deep);
  transition: background 0.15s ease;
}
.scan-upload-drop:hover { background: rgba(95, 212, 164, 0.1); }
.scan-upload-icon { font-size: 2.4rem; color: var(--accent-text); margin-bottom: 0.3rem; }
.scan-upload-title { font-family: var(--display); font-weight: 700; font-size: 1.05rem; color: var(--ink); }
.scan-upload-sub { font-size: 0.78rem; color: var(--ink-soft); }
.scan-upload-drop input[type="file"] {
  position: absolute;
  top: 0; left: 0;
  width: 1px; height: 1px;
  opacity: 0; overflow: hidden;
}

.scan-review-block { position: relative; }
.scan-category-picker {
  display: flex;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin: 0.6rem 0 1rem;
}
.scan-category-picker label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.78rem;
  color: var(--ink-soft);
  flex: 1;
  min-width: 160px;
}
.scan-category-picker select {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  font-family: var(--body);
  font-size: 0.88rem;
}

.scan-entry-table { display: flex; flex-direction: column; gap: 0.4rem; }
.scan-entry-row {
  display: grid;
  grid-template-columns: 28px 90px 130px 1fr;
  align-items: center;
  gap: 0.6rem;
}
.scan-entry-header {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  font-weight: 700;
}
.scan-entry-check input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--green); }
.scan-entry-printed {
  font-family: var(--display);
  font-size: 0.85rem;
  color: var(--ink-soft);
}
.scan-pace-input, .scan-score-input {
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--parchment-deep);
  border-radius: 5px;
  font-family: var(--body);
  font-size: 0.85rem;
  width: 100%;
}

/* ==========================================================================
   Non-PACE tick credit icons (Computer Science, Foreign Language, PE)
   ========================================================================== */
.tick-credit-icon {
  font-size: 1.15rem;
  color: var(--accent-text);
  flex-shrink: 0;
}

/* ==========================================================================
   AP registration deadline countdown
   ========================================================================== */
.ap-deadline-banner {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  background: var(--parchment-deep);
  border-left: 3px solid var(--gold);
  border-radius: 6px;
  padding: 0.8rem 1rem;
  margin-bottom: 1.4rem;
  font-size: 0.86rem;
}
.ap-deadline-banner i { color: var(--accent-text); font-size: 1.2rem; margin-top: 0.1rem; flex-shrink: 0; }
.ap-deadline-banner strong { color: var(--ink); }
.ap-deadline-banner span { color: var(--ink-soft); }
.ap-deadline-list { margin: 0.3rem 0 0; font-size: 0.8rem; color: var(--ink-soft); }
.ap-deadline-urgent { border-left-color: var(--red); }
.ap-deadline-urgent i { color: var(--red); }

.ap-registered-badge {
  display: inline-block;
  margin-left: 0.4rem;
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--green);
  background: rgba(31, 157, 108, 0.12);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
}
.ap-registered-badge-off { color: var(--red); background: rgba(226,100,95,0.10); }

/* ==========================================================================
   Admin/founder chat visibility ("staff" badge)
   ========================================================================== */
.chat-staff-badge {
  display: inline-block;
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--accent-text);
  background: rgba(95, 212, 164, 0.16);
  border-radius: 999px;
  padding: 0.05rem 0.4rem;
  margin-left: 0.35rem;
  vertical-align: middle;
}

/* Marks a Congrats Slip row that isn't a real PACE score on the
   student's grade book — see ManualCongratsEntry in models.py. */
.manual-entry-badge {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--accent-text);
  background: rgba(95, 212, 164, 0.14);
  border-radius: 999px;
  padding: 0.05rem 0.4rem;
  margin-left: 0.4rem;
}

/* Subject -> Category -> PACE No. -> Score cascading picker on the
   "Add a manual entry" card. */
.manual-congrats-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.9rem;
}
.manual-congrats-fields label { display: flex; flex-direction: column; gap: 0.3rem; }
.manual-congrats-fields label span { font-size: 0.8rem; color: var(--ink-soft); }

/* ==========================================================================
   Chat emoji picker
   ========================================================================== */
.chat-composer { position: relative; }

.emoji-picker {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0.6rem;
  width: 320px;
  max-width: calc(100vw - 2rem);
  height: 340px;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 12px;
  box-shadow: 0 10px 30px -8px rgba(0,0,0,0.25);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  z-index: 20;
}
/* The [hidden] attribute normally hides an element via the browser's
   own low-specificity stylesheet, but the class rule above (with its
   own `display: flex`) has higher specificity and was silently
   winning — so the panel stayed visible even while `hidden` was set.
   This forces hidden to actually take effect. */
.emoji-picker[hidden] { display: none; }

.emoji-picker-search {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.6rem 0.7rem;
  border-bottom: 1px solid var(--parchment-deep);
  flex-shrink: 0;
}
.emoji-picker-search i { color: var(--ink-soft); font-size: 0.95rem; }
.emoji-picker-search input {
  flex: 1;
  border: none;
  outline: none;
  font-size: 0.86rem;
  font-family: var(--body);
  background: transparent;
}

.emoji-picker-tabs {
  display: flex;
  gap: 0.15rem;
  padding: 0.4rem 0.5rem;
  border-bottom: 1px solid var(--parchment-deep);
  flex-shrink: 0;
  overflow-x: auto;
}
.emoji-picker-tab {
  border: none;
  background: transparent;
  font-size: 1.1rem;
  padding: 0.25rem 0.4rem;
  border-radius: 6px;
  cursor: pointer;
  flex-shrink: 0;
  opacity: 0.55;
}
.emoji-picker-tab:hover { background: var(--parchment-deep); opacity: 0.85; }
.emoji-picker-tab.active { background: var(--parchment-deep); opacity: 1; }

.emoji-picker-grid {
  flex: 1;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.1rem;
  padding: 0.5rem;
  align-content: start;
}
.emoji-picker-item {
  border: none;
  background: transparent;
  font-size: 1.35rem;
  line-height: 1;
  padding: 0.35rem 0;
  border-radius: 6px;
  cursor: pointer;
}
.emoji-picker-item:hover { background: var(--parchment-deep); }
.emoji-picker-empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--ink-soft);
  font-size: 0.85rem;
  padding: 2rem 0;
}

/* ==========================================================================
   AP form — Seven Star Academy study-mode picker
   ========================================================================== */
.pill-disabled { opacity: 0.4; cursor: not-allowed; }
.pill-disabled input { cursor: not-allowed; }

/* ==========================================================================
   Seven Star Academy AP course badge
   ========================================================================== */
.seven-star-badge {
  display: inline-block;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--accent-text);
  background: rgba(95, 212, 164, 0.16);
  border-radius: 999px;
  padding: 0.05rem 0.4rem;
  margin-left: 0.35rem;
  vertical-align: middle;
}

/* ============================================================
   Graduate Profile — diploma-inspired record page.
   Reuses the site's existing navy/gold/parchment palette rather
   than introducing a new one; the distinctive move here is
   structural — a diploma double-border, a wax-seal crest, and
   "record" sections with icon badges — since a graduate profile
   is, functionally, the artifact of having graduated.
   ============================================================ */

.grad-form-shell {
  position: relative;
  max-width: 880px;
  margin: 0 auto 3rem;
  background: var(--parchment);
  border: 6px double var(--gold);
  border-radius: 10px;
  padding: 3.2rem 2.6rem 2.4rem;
  overflow: visible;
}
.grad-form-shell::before {
  /* Faint seal watermark behind the crest — pure decoration, kept
     subtle enough not to compete with the actual content. */
  content: "";
  position: absolute;
  top: -40px; left: 50%;
  transform: translateX(-50%);
  width: 340px; height: 340px;
  background: radial-gradient(circle, rgba(95, 212, 164, 0.07) 0%, rgba(95, 212, 164, 0) 70%);
  pointer-events: none;
  z-index: 0;
}

.grad-form-crest { position: relative; z-index: 1; text-align: center; margin-bottom: 2.2rem; }
.grad-form-crest-ring {
  width: 62px; height: 62px;
  margin: -3.2rem auto 0.9rem;
  border-radius: 50%;
  background: var(--parchment);
  border: 2px solid var(--gold);
  box-shadow: 0 2px 10px -2px rgba(95, 212, 164, 0.35);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem;
  color: var(--ink);
}
.grad-form-eyebrow {
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0 0 0.35rem;
}
.grad-form-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 2rem;
  color: var(--ink);
  margin: 0 0 0.5rem;
}
.grad-form-sub {
  font-size: 0.88rem;
  color: var(--ink-soft);
  max-width: 480px;
  margin: 0 auto;
  line-height: 1.6;
}
.grad-form-sub a { color: var(--accent-text); text-decoration: underline; }

/* --- Portrait row -------------------------------------------------- */
.grad-form-portraits {
  position: relative; z-index: 1;
  display: flex;
  gap: 1.2rem;
  flex-wrap: wrap;
  margin-bottom: 2.2rem;
}
.grad-form-portrait-card {
  flex: 1 1 240px;
  background: var(--page-bg);
  border: 1px solid var(--parchment-deep);
  border-radius: 10px;
  padding: 1.1rem;
  text-align: center;
}
.grad-form-portrait-img {
  width: 96px; height: 96px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid var(--gold);
  background: var(--ink-soft);
  margin-bottom: 0.7rem;
}
.grad-form-portrait-tall-img {
  width: 92px; height: 124px;
  border-radius: 8px;
}
.grad-form-portrait-label {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--ink);
  margin: 0 0 0.3rem;
}
.grad-form-portrait-badge {
  display: inline-block;
  font-family: var(--body);
  font-weight: 600;
  font-size: 0.62rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--gold-bright);
  border-radius: 999px;
  padding: 0.12rem 0.5rem;
  margin-left: 0.4rem;
  vertical-align: middle;
}
.grad-form-portrait-note {
  font-size: 0.74rem;
  color: var(--ink-soft);
  line-height: 1.5;
  margin: 0 0 0.8rem;
}
.grad-form-portrait-actions { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
.grad-form-upload-status { font-size: 0.72rem; color: var(--ink-soft); min-height: 1.2em; margin: 0.5rem 0 0; }

/* --- Record grid ----------------------------------------------------- */
.grad-form-grid {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.1rem;
  margin-bottom: 1.8rem;
}
.grad-form-record-wide { grid-column: 1 / -1; }
@media (max-width: 720px) {
  .grad-form-grid { grid-template-columns: 1fr; }
}

.grad-form-record {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 10px;
  padding: 1.2rem 1.3rem;
  transition: border-color 0.15s ease;
}
.grad-form-record:focus-within,
.grad-form-record:hover { border-color: var(--gold); }
.grad-form-record-highlight {
  background: rgba(95, 212, 164, 0.06);
  border-color: var(--gold);
}

.grad-form-record-head {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 0.85rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--parchment-deep);
}
.grad-form-record-head h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0;
}
.grad-form-icon {
  flex-shrink: 0;
  width: 32px; height: 32px;
  border-radius: 50%;
  border: 1.5px solid var(--gold);
  background: var(--page-bg);
  display: flex; align-items: center; justify-content: center;
  font-size: 0.95rem;
  color: var(--ink);
}

.grad-form-note {
  font-size: 0.78rem;
  color: var(--ink-soft);
  line-height: 1.55;
  margin: 0 0 0.8rem;
}

.grad-form-check {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-size: 0.85rem;
  color: var(--ink);
  line-height: 1.5;
  cursor: pointer;
}
.grad-form-check input { width: auto; margin-top: 0.2rem; flex-shrink: 0; }

.grad-form-field { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.78rem; color: var(--ink-soft); }
.grad-form-field span { font-weight: 600; color: var(--ink); }
.grad-form-field input,
.grad-form-textarea {
  font-family: var(--body);
  font-size: 0.88rem;
  color: var(--ink);
  border: 1px solid var(--parchment-deep);
  border-radius: 6px;
  padding: 0.5rem 0.6rem;
  background: var(--parchment);
}
.grad-form-field input:focus,
.grad-form-textarea:focus { outline: none; border-color: var(--gold); }
.grad-form-field-narrow { max-width: 160px; }
.grad-form-field-row { display: flex; gap: 1rem; flex-wrap: wrap; }
.grad-form-field-row .grad-form-field { flex: 1 1 200px; }

.grad-form-pills { display: flex; flex-wrap: wrap; gap: 0.5rem; }

.grad-form-test-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 0.8rem;
}

.grad-form-textarea { width: 100%; font-family: var(--body); resize: vertical; }

.grad-form-ap-list { list-style: none; padding: 0; margin: 0 0 0.9rem; }
.grad-form-ap-list li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.8rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--parchment-deep);
  font-size: 0.84rem;
}
.grad-form-ap-list li:last-child { border-bottom: none; }
.grad-form-ap-list a { font-size: 0.76rem; flex-shrink: 0; color: var(--accent-text); }
.grad-form-ap-year {
  font-size: 0.7rem;
  color: var(--ink-soft);
  border: 1px solid var(--parchment-deep);
  border-radius: 999px;
  padding: 0.05rem 0.45rem;
  margin-left: 0.3rem;
}

.grad-form-submit {
  position: relative; z-index: 1;
  display: block;
  width: 100%;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink);
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  border: none;
  border-radius: 8px;
  padding: 0.95rem;
  cursor: pointer;
  box-shadow: 0 4px 14px -4px rgba(95, 212, 164, 0.5);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.grad-form-submit:hover { transform: translateY(-1px); box-shadow: 0 6px 18px -4px rgba(95, 212, 164, 0.6); }
.grad-form-submit:active { transform: translateY(0); }

@media (max-width: 560px) {
  .grad-form-shell { padding: 2.6rem 1.2rem 1.8rem; }
  .grad-form-title { font-size: 1.6rem; }
}

/* ============================================================
   Landing page — live preview mockup instead of generic hero art.
   Reuses the real .gpa-hero / .pace-box components with example
   data, so a visitor sees exactly what the product looks like
   before creating an account.
   ============================================================ */

.landing-shell {
  display: flex;
  align-items: center;
  gap: 3rem;
  max-width: 1080px;
  padding: 2.5rem 0 1rem;
  flex-wrap: wrap;
}
.landing-copy { flex: 1 1 420px; max-width: 560px; }

.landing-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  padding: 0.4rem 0.9rem 0.4rem 0.6rem;
  border-radius: 999px;
  font-size: 0.8rem;
  color: var(--ink-soft);
  font-weight: 500;
  margin-bottom: 1rem;
}
.landing-badge .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
  flex-shrink: 0;
}
.landing-badge strong { color: var(--ink); font-weight: 600; }

.landing-preview {
  flex: 1 1 420px;
  max-width: 480px;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 14px;
  box-shadow: 0 24px 60px -24px rgba(0,0,0,0.55);
  overflow: hidden;
  transform: rotate(1.2deg);
  transition: transform 0.25s ease;
}
.landing-preview:hover { transform: rotate(0deg) translateY(-2px); }

.landing-preview-chrome {
  display: flex;
  gap: 0.4rem;
  padding: 0.7rem 0.9rem;
  background: var(--parchment-deep);
}
.landing-preview-chrome span {
  width: 9px; height: 9px;
  border-radius: 50%;
  background: rgba(0,0,0,0.12);
}

.landing-preview-body {
  padding: 1.1rem 1.1rem 1.3rem;
  transform: scale(0.94);
  transform-origin: top left;
}
.landing-preview-body .gpa-hero { margin-bottom: 1rem; padding: 0.8rem 1rem; }
.landing-preview-body .gpa-hero-value { font-size: 1.8rem; }
.landing-preview-body .pace-box-grid { grid-template-columns: 1fr 1fr; gap: 0.7rem; }

@media (max-width: 860px) {
  .landing-shell { flex-direction: column; padding-top: 1.5rem; }
  .landing-preview { max-width: 100%; transform: none; }
}

/* ============================================================
   Auth pages (login/signup) — branded split panel. Kept the
   actual form simple and fast (this is a high-frequency, low-
   patience page), and put the personality in a companion panel
   instead of the form itself.
   ============================================================ */

.auth-shell {
  display: flex;
  max-width: 880px;
  margin: 1.5rem auto 2rem;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 20px 50px -28px rgba(0,0,0,0.55);
}

.auth-brand-panel {
  flex: 1 1 300px;
  background: linear-gradient(160deg, var(--hero-bg-2) 0%, var(--hero-bg) 100%);
  color: #fff;
  padding: 2.6rem 2.2rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.auth-brand-crest {
  width: 54px; height: 54px;
  border-radius: 50%;
  border: 2px solid var(--gold);
  background: rgba(255,255,255,0.06);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.3rem;
  color: var(--accent-text);
  margin-bottom: 1.1rem;
}
.auth-brand-eyebrow {
  font-family: var(--display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0 0 0.4rem;
}
.auth-brand-title {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.5rem;
  margin: 0 0 0.7rem;
  color: #fff;
}
.auth-brand-sub {
  font-size: 0.88rem;
  line-height: 1.6;
  color: rgba(255,255,255,0.75);
  margin: 0;
}

.auth-form-card {
  flex: 1 1 360px;
  max-width: none;
  border: none;
  border-top: none;
  border-radius: 0;
  margin: 0;
  padding: 2.6rem 2.4rem;
}

@media (max-width: 720px) {
  .auth-shell { flex-direction: column; margin: 0.5rem auto 1.5rem; box-shadow: none; }
  .auth-brand-panel { padding: 1.8rem 1.6rem; }
  .auth-brand-crest { width: 44px; height: 44px; font-size: 1.1rem; }
}

/* ============================================================
   Error page (404/500)
   ============================================================ */
.error-page { text-align: center; max-width: 420px; margin: 3.5rem auto 0; }
.error-crest {
  width: 68px; height: 68px;
  margin: 0 auto 1.1rem;
  border-radius: 50%;
  border: 2px solid var(--gold);
  background: var(--page-bg);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.6rem;
  color: var(--ink-soft);
}
.error-code {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-text);
  margin: 0 0 0.4rem;
}
.error-page h1 { margin-bottom: 0.6rem; }
.error-message { color: var(--ink-soft); margin-bottom: 2rem; }

/* ============================================================
   PACE score entry page — live-colored inputs + icon headers
   ============================================================ */

.subject-tab { display: inline-flex; align-items: center; gap: 0.4rem; }
.subject-tab i { font-size: 0.9rem; }

.subject-header-title { display: flex; align-items: flex-start; gap: 1rem; flex: 1 1 320px; }
.subject-header-icon {
  flex-shrink: 0;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1.5px solid var(--gold);
  background: var(--page-bg);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.2rem;
  color: var(--ink);
}

/* Score inputs get a live color cue as soon as a value lands in a
   real grade bucket — 94+ is a 4.0, 88-93.99 is a 3.0, below 88 is a
   0.0 (see config.GRADE_SCALE) — so the grid reads at a glance
   instead of requiring you to do the math yourself. */
.score-input { transition: border-color 0.15s ease, background 0.15s ease; }
.score-input-strong { border-color: var(--green) !important; background: rgba(31, 157, 108, 0.07); }
.score-input-ok { border-color: var(--gold) !important; background: rgba(95, 212, 164, 0.08); }
.score-input-low { border-color: var(--red) !important; background: rgba(226,100,95,0.07); }

.score-footer {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.6rem 1.5rem;
  margin-top: 0.9rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--parchment-deep);
}
.score-footer .category-average { margin-top: 0; padding-top: 0; border-top: none; text-align: left; }
.score-footer .four-target { margin-top: 0; text-align: right; }

/* ---- SAT Prep ---- */
.sat-subject-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem; }
.sat-subject-card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.4rem 1.2rem;
  border: 1.5px solid var(--parchment-deep);
  border-radius: 10px;
  background: var(--parchment);
  text-decoration: none;
  color: var(--ink);
}
.sat-subject-card:hover { border-color: var(--gold); box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
.sat-subject-card-icon {
  width: 48px;
  height: 48px;
  border-radius: 10px;
  background: rgba(95, 212, 164, 0.14);
  color: var(--accent-text);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  flex-shrink: 0;
}
.sat-subject-card-body { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; min-width: 0; }
.sat-subject-card-title { font-weight: 600; font-size: 1.05rem; }
.sat-subject-card-meta { font-size: 0.85rem; color: var(--ink-soft); }
.sat-subject-card-arrow { color: var(--ink-soft); flex-shrink: 0; }

.sat-quiz-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.6rem; }
.sat-quiz-progress { font-size: 0.9rem; color: var(--ink-soft); }
.sat-quiz-timer {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--accent-text);
}
.sat-quiz-timer-low { color: var(--red); }

.sat-question-card {
  background: #ffffff;
  border-radius: 10px;
  padding: 1.4rem;
  margin-bottom: 1.4rem;
  overflow-x: auto;
}
.sat-question-image { display: block; width: 100%; height: auto; }

/* A text-format question (see SATQuestion.question_text in models.py)
   has no screenshot to put in the plain white .sat-question-card —
   it's just a passage/prompt, so it fits the app's normal dark theme
   instead of needing a white background of its own. */
.sat-question-card-text {
  background: var(--parchment);
  color: var(--ink);
  border: 1px solid var(--parchment-deep);
}
.sat-question-card-text p { margin: 0; line-height: 1.6; font-size: 1rem; white-space: pre-wrap; }

.sat-choice-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 0.8rem; margin-bottom: 1rem; }
.sat-choice-btn {
  padding: 1rem;
  font-family: var(--display);
  font-size: 1.3rem;
  font-weight: 700;
  border-radius: 8px;
  border: 1.5px solid var(--parchment-deep);
  background: var(--parchment);
  color: var(--ink);
  cursor: pointer;
}
.sat-choice-btn:hover { border-color: var(--gold); background: var(--parchment-deep); }

/* Real answer-choice text (a text-format question — see
   SATQuestion.choices in models.py) needs room to read each option,
   unlike .sat-choice-grid's bare-letter buttons (which are all an
   image-format question needs, since the choices are already baked
   into its screenshot) — one full-width row per choice instead of a
   compact letter grid. */
.sat-choice-list { display: flex; flex-direction: column; gap: 0.7rem; margin-bottom: 1rem; }
.sat-choice-option {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0.85rem 1rem;
  border-radius: 8px;
  border: 1.5px solid var(--parchment-deep);
  background: var(--parchment);
  color: var(--ink);
  cursor: pointer;
  text-align: left;
  font-size: 0.95rem;
  line-height: 1.45;
  width: 100%;
}
.sat-choice-option:hover { border-color: var(--gold); background: var(--parchment-deep); }
.sat-choice-letter {
  flex-shrink: 0;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--parchment-deep);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--accent-text);
}
.sat-choice-text { flex: 1; padding-top: 0.15rem; }

.sat-gridin { display: flex; align-items: flex-end; gap: 1rem; margin-bottom: 1rem; }

.sat-skip-btn {
  display: block;
  margin: 0 auto;
  background: none;
  border: none;
  color: var(--ink-soft);
  text-decoration: underline;
  cursor: pointer;
  font-size: 0.85rem;
}
.sat-skip-btn:hover { color: var(--ink); }

.sat-results-card { display: flex; gap: 2rem; flex-wrap: wrap; padding: 1.4rem 0; }
.sat-results-stat { display: flex; flex-direction: column; gap: 0.2rem; }
.sat-results-stat-value { font-family: var(--display); font-size: 2.2rem; font-weight: 700; color: var(--accent-text); }
.sat-results-stat-label { font-size: 0.85rem; color: var(--ink-soft); }

.sat-leaderboard-rank { font-family: var(--display); font-weight: 700; color: var(--ink-soft); width: 2.2rem; flex-shrink: 0; text-align: center; }
.sat-leaderboard-stat { font-family: var(--display); font-weight: 700; font-size: 1.15rem; color: var(--accent-text); flex-shrink: 0; }

.sat-feedback {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.9rem 1.1rem;
  border-radius: 8px;
  margin-bottom: 1.2rem;
  font-size: 0.95rem;
}
.sat-feedback i { font-size: 1.4rem; flex-shrink: 0; }
.sat-feedback-correct { background: rgba(31, 157, 108, 0.12); border: 1px solid var(--green); color: var(--green); }
.sat-feedback-incorrect { background: rgba(226,100,95,0.12); border: 1px solid var(--red); color: var(--red); }
.sat-feedback-correct strong, .sat-feedback-incorrect strong { color: inherit; }

.sat-explanation {
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 8px;
  padding: 1rem 1.2rem;
  margin-bottom: 1.2rem;
}
.sat-explanation h3 {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-size: 0.95rem;
  margin: 0 0 0.5rem;
  color: var(--accent-text);
}
.sat-explanation p { margin: 0; color: var(--ink); line-height: 1.55; }
.sat-explanation p.category-note { color: var(--ink-soft); }

.sat-feedback-actions { display: flex; justify-content: space-between; gap: 0.8rem; flex-wrap: wrap; }

.sat-review-list { display: grid; gap: 0.6rem 0; }
.sat-review-list .sat-explanation { margin-bottom: 2rem; }

/* ---- Dropdown picker (static/picker.js replaces every <select>) ---- */
.picker { position: relative; width: 100%; }
.picker-native {
  position: absolute !important; width: 1px !important; height: 1px !important;
  opacity: 0; pointer-events: none; bottom: 0; left: 50%; padding: 0 !important; border: 0 !important;
}
.picker-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 46px;
  padding: 0.55rem 0.85rem;
  border: 1.5px solid var(--parchment-deep);
  border-radius: 10px;
  background: var(--parchment);
  color: var(--ink-soft);
  font-family: var(--body);
  font-size: 0.95rem;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.picker-trigger:hover { border-color: var(--accent-text); }
.picker.open .picker-trigger,
.picker-trigger:focus-visible { border-color: var(--gold); outline: none; }
.picker-trigger.has-value { color: var(--ink); font-weight: 600; }
.picker.is-invalid .picker-trigger { border-color: var(--red); }
.picker.is-disabled .picker-trigger { opacity: 0.5; cursor: not-allowed; }
.picker-icon {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  border-radius: 8px;
  background: var(--parchment-deep);
  color: var(--ink-soft);
  font-size: 1rem;
}
.picker-icon[hidden] { display: none; }
.picker-trigger.has-value .picker-icon { background: rgba(95, 212, 164, 0.12); color: var(--accent-text); }
.picker-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-chevron { color: var(--ink-soft); transition: transform 0.15s; }
.picker.open .picker-chevron { transform: rotate(180deg); }
.picker-panel {
  position: fixed;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  background: var(--parchment);
  border: 1px solid var(--parchment-deep);
  border-radius: 12px;
  box-shadow: 0 18px 40px rgba(20,20,15,0.16);
  overflow: hidden;
  font-family: var(--body);
}
.picker-panel[hidden] { display: none; }
.picker-search {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.55rem 0.8rem;
  border-bottom: 1px solid var(--parchment-deep);
  color: var(--ink-soft);
  flex: none;
}
.picker-search[hidden] { display: none; }
.picker-search input[type="text"] {
  border: none; background: transparent; padding: 0.35rem 0;
  outline: none; font-size: 0.95rem;
}
.picker-search input[type="text"]:focus { outline: none; }
.picker-list { list-style: none; margin: 0; padding: 0.35rem; overflow-y: auto; outline: none; }
.picker-option {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.55rem 0.65rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.92rem;
  color: var(--ink);
}
.picker-option[hidden] { display: none; }
.picker-option.active { background: var(--page-bg); }
.picker-option.active .picker-icon { color: var(--accent-text); }
.picker-option[aria-selected="true"] { background: rgba(95, 212, 164, 0.12); }
.picker-option[aria-selected="true"] .picker-icon { background: var(--gold); color: var(--gold-ink); }
.picker-option.is-disabled { opacity: 0.45; cursor: not-allowed; }
.picker-option-name { flex: 1; min-width: 0; }
.picker-badge {
  font-size: 0.68rem; font-weight: 600; letter-spacing: 0.02em;
  color: var(--green);
  background: rgba(31, 157, 108, 0.14);
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
  white-space: nowrap;
}
.picker-empty { margin: 0; padding: 1rem; text-align: center; color: var(--ink-soft); font-size: 0.88rem; }

/* ==========================================================================
   Lud Works card treatment: white cards with soft rounded corners and a
   gentle shadow on the cream page. Kept in one place so the palette's
   card look can be tuned without touching every component above.
   ========================================================================== */
.form-card,
.gpa-hero,
.pace-box,
.ap-card,
.ec-card,
.grad-tile,
.resource-card,
.sat-subject-card,
.admin-stat-card,
.auth-shell {
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}
.pace-box-complete { background: var(--parchment); }
.pace-box-volume { background: var(--page-bg); }

/* Installable app offline mode (static/offline.js): a status pill
   pinned to the bottom of the screen, and a dashed outline on score
   boxes saved on this device but not synced yet. */
.offline-status {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 1000;
  width: max-content;
  max-width: calc(100% - 32px);
  padding: 0.65rem 1rem;
  border-radius: 999px;
  background: var(--hero-bg);
  color: #f4f3ef;
  font-size: 0.88rem;
  line-height: 1.35;
  text-align: center;
  box-shadow: 0 6px 24px -8px rgba(0, 0, 0, 0.35);
}
.offline-status[hidden] { display: none; }
.offline-status-offline { border-left: 4px solid #e8b04a; }
.offline-status-pending { border-left: 4px solid var(--gold); }
.offline-status-done { border-left: 4px solid var(--green); }
.score-input-pending { border-style: dashed !important; border-color: #c98a1a !important; }

/* =====================================================================
   App mode: the phone-app layout (html.app-mode, set in base.html
   inside the iPhone app and the app installed to a phone's home
   screen). Same pages as the website, restyled: a compact header with
   the GPA, a bottom tab bar instead of the header links and the
   dashboard's left rail (_app_tabbar.html), and bigger tap targets.
   ===================================================================== */

.app-tabbar,
.app-pull { display: none; }

html.app-mode {
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}

/* Header: one slim bar. Navigation moves to the tab bar. */
html.app-mode .site-nav,
html.app-mode .report-problem-btn,
html.app-mode .site-footer,
html.app-mode .dash-rail,
html.app-mode .profile-chip-name { display: none; }

html.app-mode .site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  border-bottom: none;
}
html.app-mode .header-inner { padding: 0.55rem 1rem; }
html.app-mode .crest { min-width: 0; }
html.app-mode .crest-name {
  display: inline;
  font-size: 0.95rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
html.app-mode .crest-mark { height: 1.8rem; min-width: 1.8rem; font-size: 0.85rem; }
html.app-mode .header-right { gap: 0.4rem; }
html.app-mode .profile-chip { padding: 0.2rem; }

/* GPA ribbon: a compact strip under the header. */
html.app-mode .gpa-ribbon-inner {
  padding: 0.45rem 1rem 0.6rem;
  gap: 0.6rem;
  align-items: center;
}
html.app-mode .gpa-ribbon-inner::after { left: 1rem; right: 1rem; }
html.app-mode .gpa-label { font-size: 0.66rem; }
html.app-mode .gpa-value { font-size: 1.45rem; }
html.app-mode .gpa-track { font-size: 0.74rem; }
html.app-mode .ap-tier-badge { display: none; }

/* Room at the bottom so the tab bar never covers the last of a page,
   nor the offline banner above it (--offline-status-space, set by
   static/offline.js while the banner shows) the grades Save button. */
html.app-mode .site-main {
  padding: 1.4rem 1rem calc(96px + env(safe-area-inset-bottom) + var(--offline-status-space, 0px));
}
html.app-mode body.dash-body .site-main { padding: 0; }
html.app-mode .dash-panel { padding: 1.3rem 1rem 2rem; }
html.app-mode .dash-panel-flush { padding: 0; }
html.app-mode .flash-stack { margin: 0.6rem 1rem 0; }

/* Thumb-sized controls; 16px text stops iOS zooming into inputs. */
html.app-mode input:not([type=checkbox]):not([type=radio]):not([type=file]),
html.app-mode select,
html.app-mode textarea { font-size: 16px; }
html.app-mode .btn,
html.app-mode button[type=submit] { min-height: 44px; }

/* ---- Bottom tab bar ---- */
html.app-mode .app-tabbar {
  display: flex;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 50;
  padding: 0.35rem 0.4rem calc(0.35rem + env(safe-area-inset-bottom));
  background: rgba(255, 255, 255, 0.92);
  -webkit-backdrop-filter: saturate(1.6) blur(18px);
  backdrop-filter: saturate(1.6) blur(18px);
  border-top: 1px solid var(--parchment-deep);
  user-select: none;
  -webkit-user-select: none;
}
.app-tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.3rem 0 0.2rem;
  border: none;
  background: none;
  font: inherit;
  color: var(--ink-soft);
  text-decoration: none;
  cursor: pointer;
  min-width: 0;
}
.app-tab-icon {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.2rem;
  height: 1.9rem;
  border-radius: 999px;
  transition: background 0.15s ease;
}
.app-tab-icon i { font-size: 1.45rem; }
.app-tab-label {
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}
.app-tab.active { color: var(--accent-text); }
.app-tab.active .app-tab-icon { background: var(--accent-soft); }
.app-tab.active .app-tab-label { font-weight: 700; }
.app-tab:active .app-tab-icon { background: var(--accent-soft); }
.app-tab-badge {
  position: absolute;
  top: -0.15rem;
  right: 0.35rem;
  min-width: 17px;
  height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 17px;
  text-align: center;
  border: 2px solid #fff;
  box-sizing: content-box;
}

/* ---- Header menu button ---- */
.app-menu-btn { display: none; }
html.app-mode .app-menu-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  margin: 0 -0.2rem 0 -0.4rem;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--ink);
  cursor: pointer;
}
html.app-mode .app-menu-btn i { font-size: 1.45rem; }
html.app-mode .app-menu-btn:active { background: rgba(255, 255, 255, 0.08); }
html.app-mode .crest { margin-right: auto; }

/* ---- Side menu (slides in from the left) ---- */
.app-drawer { display: none; }
html.app-mode .app-drawer:not([hidden]) {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 60;
}
.app-drawer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(17, 18, 16, 0.5);
  opacity: 0;
  transition: opacity 0.22s ease;
}
.app-drawer-panel {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: min(84vw, 340px);
  display: flex;
  flex-direction: column;
  background: var(--page-bg);
  box-shadow: 8px 0 30px rgba(0, 0, 0, 0.18);
  transform: translateX(-100%);
  transition: transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1);
  /* The profile header and Log Out stay put; only the list between
     them scrolls. */
  overflow: hidden;
  padding-bottom: env(safe-area-inset-bottom);
}
.app-drawer.open .app-drawer-backdrop { opacity: 1; }
.app-drawer.open .app-drawer-panel { transform: none; }

.app-drawer-head {
  position: relative;
  padding: calc(1.2rem + env(safe-area-inset-top)) 1.1rem 1.1rem;
  background: linear-gradient(160deg, var(--hero-bg-2), var(--hero-bg));
  color: #f4f3ef;
}
.app-drawer-close {
  position: absolute;
  top: calc(0.7rem + env(safe-area-inset-top));
  right: 0.7rem;
  width: 34px;
  height: 34px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: #c9ccc6;
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.app-drawer-profile {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding-right: 2.6rem;
  text-decoration: none;
  color: inherit;
}
.app-drawer-profile img {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--gold);
  background: #3a3c38;
  flex-shrink: 0;
}
.app-drawer-profile span { min-width: 0; display: flex; flex-direction: column; }
.app-drawer-profile strong { font-family: var(--display); font-size: 1.08rem; line-height: 1.25; }
.app-drawer-profile small { color: #9a9d98; font-size: 0.78rem; }
.app-drawer-stats {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
}
.app-drawer-stats div {
  flex: 1;
  min-width: 0;
  padding: 0.5rem 0.6rem;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(95, 212, 164, 0.18);
}
.app-drawer-stats span {
  display: block;
  font-size: 0.64rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--gold);
}
.app-drawer-stats strong {
  display: block;
  font-family: var(--display);
  font-size: 0.95rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.app-drawer-head { flex-shrink: 0; }
.app-drawer-list {
  padding: 0.4rem 0.6rem 0.6rem;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.app-drawer-group {
  margin: 0.9rem 0.6rem 0.3rem;
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-soft);
}
.app-drawer-link {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  min-height: 46px;
  padding: 0 0.7rem;
  border-radius: 12px;
  text-decoration: none;
  color: var(--ink);
  font-size: 0.95rem;
  font-weight: 500;
}
.app-drawer-link i { font-size: 1.3rem; color: var(--ink-soft); width: 1.4rem; text-align: center; }
.app-drawer-link span:first-of-type { flex: 1; }
.app-drawer-link:active { background: var(--parchment-deep); }
.app-drawer-link.active { background: var(--accent-soft); color: var(--accent-text); font-weight: 700; }
.app-drawer-link.active i { color: var(--accent-text); }
.app-drawer-badge {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}
.app-drawer-logout {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-shrink: 0;
  margin: 0 1.2rem;
  padding: 0.9rem 0.1rem 1.1rem;
  border-top: 1px solid var(--parchment-deep);
  color: var(--red);
  font-weight: 600;
  text-decoration: none;
}

/* ---- Pull to refresh ---- */
html.app-mode .app-pull {
  display: flex;
  position: fixed;
  top: 0.6rem;
  left: 50%;
  z-index: 70;
  width: 38px;
  height: 38px;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: #fff;
  color: var(--ink-soft);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15);
  opacity: 0;
  transform: translate(-50%, 0);
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.app-pull i { font-size: 1.3rem; }
.app-pull.ready { color: var(--accent-text); }
.app-pull.spinning i { animation: app-pull-spin 0.7s linear infinite; }
@keyframes app-pull-spin { to { transform: rotate(360deg); } }

/* Enter Grades: subjects become one swipeable row of chips, and the
   long explanation under the title is left to the website. */
html.app-mode .subject-tabs {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  margin: -0.4rem -1rem 1rem;
  padding: 0.2rem 1rem 0.8rem;
  gap: 0.45rem;
  border-bottom: none;
}
html.app-mode .subject-tabs::-webkit-scrollbar { display: none; }
html.app-mode .subject-tab {
  flex-shrink: 0;
  white-space: nowrap;
  border-radius: 999px;
  padding: 0.5rem 0.9rem;
  background: var(--parchment);
  box-shadow: var(--card-shadow);
}
html.app-mode .subject-tab.active { background: var(--gold); color: var(--gold-ink); }
html.app-mode .subject-header .form-sub { display: none; }
html.app-mode .subject-header h1 { font-size: 1.8rem; margin: 0; }
html.app-mode .subject-header-title { align-items: center; }
html.app-mode .subject-progress { width: 100%; max-width: none; }

/* Wide tables: never let them widen the whole screen (that pushes the
   tab bar out of view); they scroll sideways on their own instead. The
   admin student list drops username and email, which the student's
   own page still shows. */
html.app-mode .site-main { overflow-x: clip; }
html.app-mode .gpa-table {
  display: block;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
html.app-mode .admin-student-table th:nth-child(3),
html.app-mode .admin-student-table td:nth-child(3),
html.app-mode .admin-student-table th:nth-child(4),
html.app-mode .admin-student-table td:nth-child(4) { display: none; }

/* =====================================================================
   App mode: fixed screen and app-sized text. The page itself never
   scrolls or bounces; the header stays at the top, the tab bar at the
   bottom, and only the content between them scrolls.
   ===================================================================== */
html.app-mode {
  font-size: 17px;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}
html.app-mode body {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  overscroll-behavior: none;
}
html.app-mode .site-header { position: relative; flex-shrink: 0; }
html.app-mode .site-main {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: none;
  margin: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
/* Pages keep a comfortable reading width on big phones and tablets. */
html.app-mode body:not(.dash-body) .site-main > * {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}
html.app-mode .app-tabbar,
html.app-mode .site-header,
html.app-mode .app-drawer-panel {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* Bigger, app-like type. */
html.app-mode h1 { font-size: 1.75rem; line-height: 1.2; }
html.app-mode .form-sub { font-size: 0.95rem; }
html.app-mode .btn { font-size: 1rem; padding: 0.85rem 1.4rem; }
html.app-mode .form-card label { font-size: 0.9rem; }
html.app-mode input[type="text"],
html.app-mode input[type="email"],
html.app-mode input[type="password"],
html.app-mode input[type="number"],
html.app-mode select,
html.app-mode textarea {
  min-height: 48px;
  border-radius: 12px;
  padding: 0.7rem 0.9rem;
}
html.app-mode .crest-name { font-size: 1rem; }
html.app-mode .gpa-label { font-size: 0.7rem; }
html.app-mode .gpa-value { font-size: 1.55rem; }
html.app-mode .gpa-track { font-size: 0.8rem; }
html.app-mode .app-tab-label { font-size: 0.72rem; }
html.app-mode .app-drawer-link { font-size: 1.02rem; min-height: 50px; }

/* The offline status pill sits just above the tab bar. */
html.app-mode .offline-status { bottom: calc(84px + env(safe-area-inset-bottom)); }

/* ---- App mode: sign-in screens (login, signup) ----
   A full-screen dark welcome with the app icon, and the form on a
   white sheet below it, instead of the website's two-panel card. */
.app-auth-hero { display: none; }
html.app-mode body:has(.auth-shell) .site-header,
html.app-mode body:has(.auth-shell) .flash-stack:empty { display: none; }
html.app-mode body:has(.auth-shell) { background: var(--hero-bg); }
html.app-mode body:has(.auth-shell) .site-main {
  padding: 0;
  background: linear-gradient(180deg, var(--hero-bg-2), var(--hero-bg) 45%);
}
html.app-mode body:has(.auth-shell) .site-main > * { max-width: none; }
html.app-mode body:has(.auth-shell) .flash-stack {
  max-width: 480px;
  margin: 1rem auto 0;
  padding: 0 1rem;
}
html.app-mode .auth-shell {
  flex-direction: column;
  min-height: 100%;
  max-width: none;
  margin: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}
html.app-mode .auth-brand-panel { display: none; }
html.app-mode .app-auth-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: calc(2.6rem + env(safe-area-inset-top)) 1.5rem 2.2rem;
  color: #f4f3ef;
}
.app-auth-icon {
  width: 92px;
  height: 92px;
  border-radius: 22px;
  box-shadow: 0 12px 30px -10px rgba(95, 212, 164, 0.45), 0 0 0 1px rgba(95, 212, 164, 0.25);
}
.app-auth-title {
  font-family: var(--display);
  font-size: 1.9rem;
  font-weight: 800;
  margin: 1.1rem 0 0.35rem;
  color: #fff;
}
.app-auth-sub {
  margin: 0;
  font-size: 1rem;
  color: #a9ada6;
}
html.app-mode .auth-form-card {
  flex: 1;
  width: 100%;
  max-width: none;
  margin: 0;
  border: none;
  border-radius: 28px 28px 0 0;
  box-shadow: 0 -10px 30px -18px rgba(0, 0, 0, 0.6);
  padding: 2rem 1.4rem calc(2rem + env(safe-area-inset-bottom));
  background: var(--page-bg);
}
html.app-mode .auth-form-card > * { max-width: 480px; margin-left: auto; margin-right: auto; }
html.app-mode .auth-form-card .eyebrow { display: none; }
html.app-mode .auth-form-card h1 { font-size: 1.6rem; margin-bottom: 0.4rem; }
html.app-mode .auth-form-card label { margin-top: 1.1rem; }
html.app-mode .auth-form-card input[type="text"],
html.app-mode .auth-form-card input[type="email"],
html.app-mode .auth-form-card input[type="password"] {
  min-height: 54px;
  border-radius: 14px;
  border: 1.5px solid transparent;
  background: #fff;
  box-shadow: var(--card-shadow);
}
html.app-mode .auth-form-card input:focus { border-color: var(--gold); outline: none; }
html.app-mode .auth-form-card .btn-block {
  min-height: 54px;
  margin-top: 1.6rem;
  border-radius: 14px;
  font-size: 1.05rem;
}
html.app-mode .auth-form-card .form-footer { font-size: 0.95rem; margin-top: 1.6rem; }

/* Dashboard progress block spans the full phone width. */
html.app-mode .subject-header { flex-direction: column; align-items: stretch; gap: 1rem; }
html.app-mode .subject-header > * { flex: none; }
html.app-mode .progress-stack { width: 100%; max-width: none; }
html.app-mode .subject-progress-label { text-align: left; }
html.app-mode .subject-header .subject-progress { width: 100%; max-width: none; }

/* ---- App mode: sign-in screen is locked ----
   The welcome and the sheet fill exactly one screen and never scroll
   or bounce. Only a long form (signup, or with the keyboard open)
   scrolls, and then just inside the white sheet. */
html.app-mode body:has(.auth-shell) .site-main {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
html.app-mode body:has(.auth-shell) .auth-shell {
  flex: 1;
  min-height: 0;
  height: 100%;
}
html.app-mode body:has(.auth-shell) .app-auth-hero {
  flex-shrink: 0;
  padding: calc(clamp(1.2rem, 5vh, 2.6rem) + env(safe-area-inset-top)) 1.5rem clamp(1.2rem, 4vh, 2.2rem);
}
html.app-mode body:has(.auth-shell) .auth-form-card {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: none;
}
html.app-mode .auth-form-card .native-app-note { font-size: 0.85rem; }
@media (max-height: 720px) {
  .app-auth-icon { width: 68px; height: 68px; border-radius: 17px; }
  .app-auth-title { font-size: 1.5rem; margin-top: 0.7rem; }
}

/* ---- App mode: page transitions ----
   The header and tab bar stay still while the page content softly
   fades and slides in, like moving between screens in an app. */
html.app-mode .site-header { view-transition-name: app-header; }
/* The tab bar gets its own layer only while a transition runs (so the
   sliding page passes under it): a view-transition-name makes it a
   backdrop root, which would switch off its glass blur the rest of the
   time. html.vt-active is set in base.html. */
html.app-mode.vt-active .app-tabbar { view-transition-name: app-tabbar; }
::view-transition-group(app-tabbar),
::view-transition-old(app-tabbar),
::view-transition-new(app-tabbar) { animation: none; }
::view-transition-old(app-tabbar) { display: none; }
html.app-mode .site-main { view-transition-name: app-main; }
/* Everything outside the header and page content (the tab bar, the
   background) switches at once instead of cross-fading, so the glass
   bar never flickers. */
::view-transition-old(root),
::view-transition-new(root) { animation: none; }
/* Switching tabs (tab bar, side menu): a quick soft fade, no sliding,
   the way app tabs behave. html.nav-* is set in base.html from how the
   user left the previous page. */
::view-transition-group(app-main) { animation-duration: 0s; }
::view-transition-old(app-main) { animation: app-fade-out 120ms ease-out both; }
::view-transition-new(app-main) { animation: app-fade-in 180ms ease-out both; }
/* Opening something (a subject, a chat, a post): the new screen slides
   in from the right over the old one, like a pushed screen. */
html.nav-push::view-transition-old(app-main) { animation: app-push-out 280ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
html.nav-push::view-transition-new(app-main) { animation: app-push-in 280ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
/* Going back: the reverse. */
html.nav-back::view-transition-old(app-main) { animation: app-pop-out 260ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
html.nav-back::view-transition-new(app-main) { animation: app-pop-in 260ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes app-fade-out { to { opacity: 0; } }
@keyframes app-fade-in { from { opacity: 0; } }
@keyframes app-push-out { to { opacity: 0.6; transform: translateX(-25%); } }
@keyframes app-push-in { from { transform: translateX(100%); } }
@keyframes app-pop-out { to { transform: translateX(100%); } }
@keyframes app-pop-in { from { opacity: 0.6; transform: translateX(-25%); } }
html.nav-back::view-transition-old(app-main) { z-index: 1; }

/* While the next page loads: a thin mint bar runs along the top and
   the current page dims slightly, so a tap always answers at once. */
.app-loading-bar { display: none; }
html.app-mode.app-leaving .app-loading-bar {
  display: block;
  position: fixed;
  top: env(safe-area-inset-top);
  left: 0;
  height: 3px;
  width: 100%;
  z-index: 200;
  background: var(--gold);
  transform-origin: left;
  animation: app-loading 1.6s cubic-bezier(0.1, 0.7, 0.2, 1) both;
}
html.app-mode.app-leaving .site-main { opacity: 0.6; transition: opacity 120ms; }
@keyframes app-loading { from { transform: scaleX(0); } to { transform: scaleX(0.85); } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }
}
/* Instant feedback when a tab or menu item is tapped. */
html.app-mode .app-tab:active,
html.app-mode .app-drawer-link:active { opacity: 0.55; transform: scale(0.96); }
html.app-mode .app-tab,
html.app-mode .app-drawer-link { transition: opacity 120ms, transform 120ms; -webkit-tap-highlight-color: transparent; }

/* ---- App mode: floating glass tab bar ----
   Like 열품타: a dark frosted-glass pill floating above the bottom of
   the screen. Page content scrolls underneath and shows, blurred,
   through the glass. */
html.app-mode .app-tabbar {
  left: 12px;
  right: 12px;
  bottom: calc(8px + env(safe-area-inset-bottom));
  gap: 0;
  padding: 5px;
  border-radius: 999px;
  background: rgba(30, 31, 29, 0.78);
  -webkit-backdrop-filter: saturate(1.8) blur(10px);
  backdrop-filter: saturate(1.8) blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.09);
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
html.app-mode .app-tab {
  position: relative;
  height: 56px;
  padding: 0;
  justify-content: center;
  color: rgba(255, 255, 255, 0.62);
  border-radius: 999px;
}
html.app-mode .app-tab-icon { width: auto; height: auto; background: none !important; }
html.app-mode .app-tab-icon i { font-size: 1.5rem; }
html.app-mode .app-tab-label { font-size: 0.68rem; }
html.app-mode .app-tab.active {
  color: #fff;
  background: rgba(255, 255, 255, 0.13);
}
html.app-mode .app-tab.active .app-tab-icon i { color: var(--gold); }
html.app-mode .app-tab-badge { border-color: #1e1f1d; right: -0.6rem; }

/* Dashboard pages run under the glass bar too, leaving room at the end
   (--app-tabbar-space is measured in base.html). */
html.app-mode .dash-panel:not(.dash-panel-flush) {
  padding-bottom: calc(var(--app-tabbar-space, 90px) + 1.5rem + var(--offline-status-space, 0px));
}
html.app-mode .chat-roster-list { padding-bottom: var(--app-tabbar-space, 90px); }
html.app-mode .chat-composer { margin-bottom: var(--app-tabbar-space, 90px); }

/* Edge to edge on iPhone: the dark header runs up behind the status
   bar, and the glass tab bar floats above the home indicator. */
html.app-mode .site-header { padding-top: env(safe-area-inset-top); }
html.app-mode body:has(.auth-shell) .site-header { padding-top: 0; }

/* ---- App mode: file viewer (static/app-viewer.js) ----
   Photos and files from chat, the feed and Guidelines open here, on
   top of the page, instead of leaving the app for Safari. */
.app-viewer {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  background: #0b0c0b;
  color: #f4f3ef;
}
.app-viewer-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: calc(env(safe-area-inset-top, 0px) + 0.5rem) 0.75rem 0.5rem;
  background: #111210;
}
.app-viewer-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: center;
  font-weight: 600;
}
.app-viewer-btn {
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: inherit;
  font-size: 1.3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.app-viewer-btn[hidden] { visibility: hidden; display: inline-flex; }
.app-viewer-body {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  -webkit-overflow-scrolling: touch;
}
.app-viewer-img { max-width: 100%; max-height: 100%; object-fit: contain; }
.app-viewer-frame { width: 100%; height: 100%; border: 0; background: #fff; }
.app-viewer-file {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
  padding: 1.5rem;
  text-align: center;
  word-break: break-word;
}
.app-viewer-file .ti { font-size: 3.5rem; color: var(--gold); }
.app-viewer-note { color: #9a9d98; margin: 0; padding: 1rem; text-align: center; }

/* Show/hide password eye button (static/password-toggle.js). */
.pw-field {
  position: relative;
  display: block;
}
.pw-field > input { padding-right: 2.8rem !important; }
.pw-toggle {
  position: absolute;
  top: 50%;
  right: 0.3rem;
  transform: translateY(-50%);
  width: 2.3rem;
  height: 2.3rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 1.2rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.pw-toggle:hover { color: var(--ink); background: var(--accent-soft); }
.pw-toggle[aria-pressed="true"] { color: var(--accent-text); }
.pw-toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
html.app-mode .pw-toggle { width: 2.75rem; height: 2.75rem; font-size: 1.35rem; }
/* Edge and the Windows app have their own eye button; use ours only. */
.pw-field > input::-ms-reveal,
.pw-field > input::-ms-clear { display: none; }
