/* ── Grades theme ───────────────────────────────────────────────────────
   Light mode: light blue. Dark mode: a dark navy palette close to zenow's
   sidebar (--sidebar-bg in main.css), with .ng-header/.ng-nav bumped to a
   lighter shade of it (below) so they read as distinct from the sidebar
   rather than blending into it. Everything else (buttons, inputs, section
   titles, empty-state, .load-dot) is inherited from main.css's token-driven
   components -- only the palette is overridden here. */

:root {
  --bg:           #EAF2FE;
  --surface:      #FFFFFF;
  --surface2:     #E1EBFC;
  --surface3:     #D2E2FA;
  --border:       #C9DDF6;
  --border2:      #AFC9EC;
  --primary:      #2F6FED;
  --primary-dim:  #2558C5;
  --primary-glow: rgba(47,111,237,0.10);
}

:root[data-theme="dark"] {
  --bg:           #0E1729;
  --surface:      #14213D;
  --surface2:     #182A4A;
  --surface3:     #1D3157;
  --border:       #24365C;
  --border2:      #2E4272;
  --primary:      #7EA6FF;
  --primary-dim:  #5C89E0;
  --primary-glow: rgba(126,166,255,0.14);
}

/* The blue is Grades' own content only. Chrome shared with zenow and
   Curriculum (sidebar, modals, menus, Chrono, toasts) keeps zenow's palette
   so it looks the same in all three apps. Values mirror main.css :root. */
.sidebar, .modal-overlay, .context-menu, .academic-filter-menu,
.zeno-panel, .chrono-quick-bar, .toast-container, .ob-overlay {
  --bg:           #F7F7F2;
  --surface:      #FFFFFF;
  --surface2:     #F3F4F6;
  --surface3:     #EAECF0;
  --border:       #E5E7EB;
  --border2:      #D1D5DB;
  --primary:      #14213D;
  --primary-dim:  #0f1a2e;
  --primary-glow: rgba(20,33,61,0.06);
}
:root[data-theme="dark"] :is(.sidebar, .modal-overlay, .context-menu, .academic-filter-menu,
.zeno-panel, .chrono-quick-bar, .toast-container, .ob-overlay) {
  --bg:           #0E1116;
  --surface:      #171B22;
  --surface2:     #1E232C;
  --surface3:     #262C38;
  --border:       #2A313D;
  --border2:      #3B4453;
  --primary:      #A5E0A4;
  --primary-dim:  #C0EDBE;
  --primary-glow: rgba(165,224,164,0.12);
}

/* .ng-header/.ng-nav default to var(--surface), which in dark mode is the
   same navy as zenow's --sidebar-bg (main.css) -- was intentional at first
   (a "flows out of the sidebar" look) but reads as no boundary between the
   sidebar and the header/nav column. A lighter blue from the same palette
   (--surface3) keeps it on-brand while actually separating the two. */
:root[data-theme="dark"] .ng-header,
:root[data-theme="dark"] .ng-nav {
  background: var(--surface3);
}

#ng-loading {
  position: fixed; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 1.625rem;
  background: var(--bg);
}

/* ── App shell: zenow's own sidebar + a scrollable content column ────────
   Same #screen-app/.sidebar/.main split as the main app (main.css), reused
   here so Grades feels like a section of zenow, not a separate product. */
#ng-app { display: flex; height: 100vh; height: 100dvh; overflow: hidden; }
.ng-content { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
.ng-main { flex: 1; overflow-y: auto; max-width: 47.5rem; margin: 0 auto; padding: 1.75rem 1.5rem 3.75rem; width: 100%; }

/* Loading-screen scale of the shared .grades-wordmark-hero (main.css):
   bigger, sitting above the spinner -- same stacking as zenow's own
   #screen-loading .loading-logo. The crisp per-letter text-shadow (not a
   blurred filter -- filter+gradient-clip-text rasterizes soft) is what
   gives the "shadowed" look without going blurry. */
.ng-loading-logo {
  display: flex;
  font-size: 2.625rem; letter-spacing: -1.5px;
  animation: pulse 1.5s ease-in-out infinite;
}

/* Same fixed height as .sidebar-header (main.css) so the two header rows'
   bottom borders line up exactly where the sidebar meets this column,
   regardless of what each one's content naturally measures. */
/* Flex row (hamburger, actions pushed right via margin-left:auto) with the
   wordmark absolutely centered on top of it -- NOT a 1fr/auto/1fr grid: a
   bare 1fr column claims its full proportional share of the row regardless
   of its content's actual width, so a lone hamburger button still got a
   track as wide as the whole actions cluster, leaving a huge dead gap and
   squashing everything toward the edges. Absolute centering is immune to
   that since it's positioned purely off the header's own width. */
.ng-header {
  display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0;
  height: 4.625rem; box-sizing: border-box; padding: 0 1.5rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  position: relative;
}
.ng-header-wordmark { font-size: 1.625rem; }
/* Scoped to .ng-header, not the bare class -- .grades-logo-lockup is also
   used unscoped on the loading screen, where it needs normal flex-column
   flow (see #ng-loading), not this header-only absolute centering. */
.ng-header .grades-logo-lockup { position: absolute; left: 50%; transform: translateX(-50%); transition: transform 0.2s ease; }
.ng-header-actions { margin-left: auto; display: flex; align-items: center; gap: 0.75rem; }

.ng-page-title { font-size: 1.25rem; font-weight: 800; color: var(--text); margin-bottom: 1rem; }

/* Skeleton loading placeholders -- a plain shimmering bar shown in place of
   a view's real content while its data fetches. Reuses main.css's own
   `pulse` keyframe (already loaded here) rather than defining a near-
   identical one. Bar geometry is set per call site via inline width/height
   (see grades.js's ngSkel* helpers), so this stays a single rule. */
.ng-skel {
  display: block;
  background: var(--surface2);
  border-radius: 0.3125rem;
  animation: pulse 1.3s ease-in-out infinite;
}
.ng-skel-card { pointer-events: none; }

.ng-subject-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(13.75rem, 1fr)); gap: 0.75rem; }

.ng-subject-card {
  display: flex; flex-direction: column; gap: 0.5rem;
  padding: 1rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface); cursor: pointer; transition: box-shadow 0.15s, transform 0.1s;
  text-align: left;
}
.ng-subject-card:hover { box-shadow: var(--shadow-sm); }
.ng-subject-card:active { transform: scale(0.98); }
.ng-subject-card-top { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.ng-subject-name { min-width: 0; font-size: 0.875rem; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ng-subject-card-top .load-dot { flex-shrink: 0; }
.ng-subject-card-avg { font-size: 1.375rem; font-weight: 800; color: var(--text); }
.ng-subject-card-meta { display: flex; align-items: center; gap: 0.375rem; font-size: 0.75rem; color: var(--text-muted); }
.ng-trend-up { color: var(--green); }
.ng-trend-down { color: var(--red); }

.ng-subject-back {
  display: inline-flex; align-items: center; gap: 0.375rem;
  background: none; border: none; color: var(--text-muted);
  font-size: 0.8125rem; font-weight: 600; padding: 0.25rem 0; margin-bottom: 0.75rem; cursor: pointer;
}
.ng-subject-back:hover { color: var(--text); }

.ng-subject-heading { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 1.375rem; }
.ng-subject-title { font-size: 1.375rem; font-weight: 800; color: var(--text); }
.ng-subject-average { font-size: 1.375rem; font-weight: 800; color: var(--primary); }

.ng-category {
  border: 1px solid var(--border); border-radius: var(--radius); padding: 0.75rem 0.875rem; margin-bottom: 0.625rem;
  background: var(--surface);
}
.ng-category-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-bottom: 0.375rem; }
.ng-category-name { font-size: 0.8125rem; font-weight: 700; color: var(--text); }
.ng-category-stats { font-size: 0.75rem; color: var(--text-muted); margin-left: auto; }
/* Filled by the school, not by the student. The chip is the only warning
   they get that a mark typed here would be corrected away on the next sync,
   so it sits next to the name rather than at the end of the row. */
.ng-category-src {
  font-size: 0.5625rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--accent, #2A9D8F);
  background: color-mix(in srgb, var(--accent, #2A9D8F) 14%, transparent);
  border-radius: 62.4375rem; padding: 0.0625rem 0.375rem; white-space: nowrap; flex-shrink: 0;
}
.ng-category-delete { background: none; border: none; color: var(--text-dim); cursor: pointer; padding: 0.125rem; }
.ng-category-delete:hover { color: var(--red); }

.ng-entry-row {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.3125rem 0; font-size: 0.8125rem;
  border-top: 1px solid var(--border);
}
.ng-entry-row:first-of-type { border-top: none; }
.ng-entry-label { flex: 1; color: var(--text); }
.ng-entry-score { font-weight: 700; color: var(--text); }
.ng-entry-delete { background: none; border: none; color: var(--text-dim); cursor: pointer; padding: 0.125rem; flex-shrink: 0; }
.ng-entry-delete:hover { color: var(--red); }
/* The teacher's correction on a mark: a quiet camera until one is read,
   then "Correction" to open it under the mark. */
.ng-entry-photo {
  display: grid; place-items: center; width: 1.625rem; height: 1.625rem; flex-shrink: 0; padding: 0;
  border: 0; border-radius: 62.4375rem; background: none; color: var(--text-dim); cursor: pointer;
  opacity: 0.55; transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.ng-entry-row:hover .ng-entry-photo, .ng-entry-photo:focus-visible { opacity: 1; }
.ng-entry-photo:hover { color: var(--accent, var(--primary)); background: color-mix(in srgb, var(--accent, var(--primary)) 10%, transparent); }
@media (hover: none) { .ng-entry-photo { opacity: 0.8; } }
.ng-entry-correction {
  display: inline-flex; align-items: center; gap: 0.375rem; flex-shrink: 0; height: 1.5rem; padding: 0 0.625rem;
  border: 0; border-radius: 62.4375rem; font: inherit; font-size: 0.75rem; font-weight: 600; cursor: pointer;
  color: var(--accent, var(--primary)); background: color-mix(in srgb, var(--accent, var(--primary)) 10%, transparent);
}
.ng-entry-correction:hover, .ng-entry-correction.is-open { background: color-mix(in srgb, var(--accent, var(--primary)) 17%, transparent); }
.ng-entry-correction.is-reading { cursor: default; color: var(--text-muted); background: color-mix(in srgb, var(--text) 6%, transparent); font-weight: 500; }
.ng-correction-spinner { width: 0.75rem; height: 0.75rem; border-radius: 50%; border: 1.5px solid currentColor; border-right-color: transparent; animation: ng-spin 0.8s linear infinite; }
@keyframes ng-spin { to { transform: rotate(360deg); } }
.ng-correction {
  margin: 0.125rem 0 0.5rem; padding: 0.625rem 0.75rem; border-radius: 0.75rem;
  background: color-mix(in srgb, var(--text) 4%, transparent); font-size: 0.8125rem; line-height: 1.45; color: var(--text);
}
.ng-correction-summary { margin: 0 0 0.375rem; }
.ng-correction-marks { margin: 0 0 0.375rem; padding-left: 1.1rem; color: var(--text-muted); }
.ng-correction-marks b { color: var(--text); font-weight: 600; }
.ng-correction-focus { margin: 0 0 0.375rem; color: var(--text-muted); }
.ng-correction-replace {
  display: inline-flex; align-items: center; gap: 0.3125rem; padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; font-size: 0.75rem; font-weight: 600; color: var(--accent, var(--primary));
}
/* Admission goal's target-score grid -- an .ng-entry-row whose "score" slot
   is a live editable input instead of static text, colored red->green via
   inline style from ngTargetColor() in grades.js. */
.ng-test-actual-input { width: 4.5rem; text-align: right; flex-shrink: 0; transition: background 0.15s var(--ease); }

.ng-add-entry-form { display: flex; gap: 0.375rem; margin-top: 0.5rem; }
.ng-add-entry-form input { padding: 0.375rem 0.5625rem; font-size: 0.75rem; }
.ng-add-entry-form input[data-role="label"] { flex: 1; }
.ng-add-entry-form input[data-role="score"] { width: 5.5rem; }
.ng-add-entry-form button { padding: 0.25rem 0.625rem; }

.ng-inline-form { display: flex; gap: 0.5rem; margin-top: 0.625rem; flex-wrap: wrap; }
.ng-inline-form input, .ng-inline-form select { width: auto; flex: 1; min-width: 7.5rem; }
.ng-inline-form { align-items: flex-end; }
.ng-field { display: flex; flex-direction: column; gap: 0.25rem; flex: 1; min-width: 7.5rem; }
.ng-field.hidden { display: none; }
.ng-field > span { font-size: 0.6875rem; font-weight: 600; color: var(--text-muted); padding-left: 0.125rem; }
.ng-field input, .ng-field select { width: 100%; min-width: 0; }
.ng-target-hint { font-size: 0.71875rem; color: var(--text-dim); margin-top: 0.375rem; line-height: 1.4; }

/* School search combobox -- a plain text input + an absolutely-positioned
   results list underneath, no library, this app has no other combobox to
   match. .ng-school-combobox itself is the positioning context so the
   list sits directly under the input regardless of where the form lives
   (Settings vs the Walkthrough modal). */
.ng-school-combobox { position: relative; }
.ng-school-results {
  position: absolute; top: calc(100% + 0.25rem); left: 0; right: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow);
  max-height: 13.75rem; overflow-y: auto; z-index: 20;
}
.ng-school-result {
  padding: 0.5rem 0.75rem; cursor: pointer; font-size: 0.8125rem;
  display: flex; align-items: baseline; gap: 0.375rem;
}
.ng-school-result-country { color: var(--text-muted); font-size: 0.71875rem; }
.ng-school-result:hover, .ng-school-result.active { background: var(--surface2); }
.ng-school-result-empty { padding: 0.5rem 0.75rem; font-size: 0.8125rem; color: var(--text-muted); }

/* The program goal and the admission goal stack rather than replace each
   other -- a student can have both at once. */
.ng-goal-slot-stacked { margin-top: 0.75rem; }
.ng-goal-slot-stacked:empty { margin-top: 0; }
/* Quiet stand-in for an empty admission card: most students never apply
   anywhere, so this stays discoverable without occupying a whole card. */
.ng-goal-add-row {
  display: flex; align-items: center; gap: 0.5rem; width: 100%;
  padding: 0.6875rem 0.875rem; border-radius: var(--radius);
  border: 1px dashed var(--border2); background: none;
  font-size: 0.8125rem; font-weight: 600; color: var(--text-muted);
  cursor: pointer; transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.ng-goal-add-row:hover {
  color: var(--primary); border-color: var(--primary);
  background: var(--primary-glow);
}
.ng-goal-add-plus { font-size: 1rem; line-height: 1; }

.ng-locked { padding: 0.875rem; border-radius: var(--radius); background: var(--surface2); text-align: center; }
.ng-locked p { font-size: 0.8125rem; color: var(--text-muted); margin-bottom: 0.625rem; }

.ng-result { margin-top: 0.625rem; padding: 0.625rem 0.875rem; border-radius: var(--radius); background: var(--primary-glow); font-size: 0.8125rem; color: var(--text); }
.ng-result.ng-infeasible { background: color-mix(in srgb, var(--red) 12%, transparent); }

/* ── Nav bar ────────────────────────────────────────────────────────────── */
.ng-nav {
  display: flex; gap: 0.25rem; padding: 0 1.5rem; overflow-x: auto; flex-shrink: 0;
  background: var(--surface); border-bottom: 1px solid var(--border);
}
.ng-nav-link {
  padding: 0.75rem 0.625rem; font-size: 0.8125rem; font-weight: 600; color: var(--text-muted);
  text-decoration: none; border-bottom: 0.125rem solid transparent; white-space: nowrap;
  transition: color 0.15s, border-color 0.15s;
}
.ng-nav-link:hover { color: var(--text); }
.ng-nav-link.active { color: var(--primary); border-bottom-color: var(--primary); }

/* ── Risk banner ────────────────────────────────────────────────────────── */
.ng-risk-banner { display: flex; flex-direction: column; gap: 0.5rem; margin-bottom: 1rem; }
.ng-risk-card {
  display: flex; align-items: flex-start; gap: 0.625rem;
  padding: 0.75rem 0.875rem; border-radius: var(--radius);
  background: color-mix(in srgb, var(--red) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--red) 25%, transparent);
  border-left: 0.1875rem solid var(--red);
}
.ng-risk-card.watch {
  background: color-mix(in srgb, var(--amber) 10%, var(--surface));
  border-color: color-mix(in srgb, var(--amber) 30%, transparent);
  border-left-color: var(--amber);
}
.ng-risk-card-icon { width: 1.125rem; height: 1.125rem; flex-shrink: 0; margin-top: 0.0625rem; color: var(--red); }
.ng-risk-card.watch .ng-risk-card-icon { color: var(--amber); }
.ng-risk-card-body { min-width: 0; flex: 1; }
.ng-risk-card-top { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.ng-risk-card-name { font-size: 0.8125rem; font-weight: 700; color: var(--text); }
.ng-risk-card-level {
  font-size: 0.625rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--red); background: color-mix(in srgb, var(--red) 15%, transparent);
  padding: 0.125rem 0.4375rem; border-radius: 62.4375rem; flex-shrink: 0;
}
.ng-risk-card.watch .ng-risk-card-level { color: var(--amber); background: color-mix(in srgb, var(--amber) 18%, transparent); }
.ng-risk-card-reasons { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3125rem 0.5rem; margin-top: 0.3125rem; }
.ng-risk-reason { display: inline-flex; align-items: center; gap: 0.3125rem; font-size: 0.75rem; color: var(--text-muted); line-height: 1.3; }
.ng-risk-reason-tag {
  font-size: 0.625rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
  color: var(--text-muted); background: var(--surface2);
  padding: 0.0625rem 0.375rem; border-radius: 0.25rem; flex-shrink: 0;
}
/* Carousel: one warning per slide. Arrows + dots only appear when there are
   several slides; a lone warning stays a plain, full-width card. */
.ng-risk-carousel { display: flex; flex-direction: column; gap: 0.4375rem; }
.ng-risk-carousel-viewport { overflow: hidden; border-radius: var(--radius); }
.ng-risk-carousel-stage { display: flex; transition: transform 0.3s var(--ease); }
.ng-risk-carousel-stage > .ng-risk-card { flex: 0 0 100%; min-width: 0; }
.ng-risk-carousel-dots { display: flex; align-items: center; justify-content: center; gap: 0.3125rem; }
.ng-risk-carousel-dot {
  width: 0.4375rem; height: 0.4375rem; padding: 0;
  border: none; border-radius: 62.4375rem; cursor: pointer;
  background: var(--border2); transition: background 0.15s ease, transform 0.15s ease;
}
.ng-risk-carousel-dot:hover { background: var(--text-dim); }
.ng-risk-carousel-dot.is-active { background: var(--primary); transform: scale(1.25); }

/* ── Goals page ─────────────────────────────────────────────────────────── */
.ng-goals-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 1.125rem; flex-wrap: wrap; }
.ng-goals-header .ng-page-title { margin-bottom: 0.25rem; }

.ng-goals-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.75rem; }
.ng-goal-card {
  display: flex; flex-direction: column; gap: 0.5rem;
  padding: 1rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface);
}
.ng-goal-card-top { display: flex; align-items: center; gap: 0.5rem; }
.ng-goal-card-top .subject-dot { width: 0.5625rem; height: 0.5625rem; }
.ng-goal-name { flex: 1; min-width: 0; font-size: 0.875rem; font-weight: 700; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ng-goal-discuss-btn {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 1.375rem; height: 1.375rem; padding: 0; border: none; background: none; cursor: pointer;
}
.ng-goal-discuss-btn::after {
  content: ''; width: 0.5rem; height: 0.5rem; border-radius: 50%;
  background: var(--amber); transition: transform 0.15s;
}
.ng-goal-discuss-btn:hover::after { transform: scale(1.35); }

.ng-goal-avg { font-size: 1.5rem; font-weight: 800; color: var(--text); }
.ng-goal-gap { font-size: 0.75rem; font-weight: 600; }
.ng-goal-gap-none { color: var(--text-dim); font-weight: 500; }
.ng-goal-gap-above { color: var(--green); }
.ng-goal-gap-close { color: var(--amber); }
.ng-goal-gap-below { color: var(--red); }

.ng-goal-bar-wrap { position: relative; height: 0.375rem; border-radius: 6.1875rem; background: var(--surface2); overflow: visible; }
.ng-goal-bar { position: absolute; inset: 0 auto 0 0; height: 100%; border-radius: 6.1875rem; background: var(--text-dim); transition: width 0.3s; }
.ng-goal-bar.ng-goal-gap-above { background: var(--green); }
.ng-goal-bar.ng-goal-gap-close { background: var(--amber); }
.ng-goal-bar.ng-goal-gap-below { background: var(--red); }
.ng-goal-bar-target {
  position: absolute; top: -0.1875rem; bottom: -0.1875rem; width: 0.125rem; background: var(--text);
  transform: translateX(-1px); border-radius: 0.0625rem;
}

.ng-goal-input-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.125rem; font-size: 0.75rem; color: var(--text-muted); font-weight: 600; }
.ng-goal-input-row input { width: 4.75rem; text-align: right; }

/* ── Charts (hand-rolled inline SVG, no external library) ──────────────── */
.ng-chart { margin: 0.25rem 0 1.375rem; }
.ng-chart svg { width: 100%; height: auto; display: block; }
.ng-chart-empty { font-size: 0.75rem; color: var(--text-dim); padding: 1.25rem 0; text-align: center; }

/* ── Toggle switch ──────────────────────────────────────────────────────── */
.ng-toggle { position: relative; display: inline-block; width: 2.5rem; height: 1.5rem; flex-shrink: 0; }
.ng-toggle input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.ng-toggle-slider {
  position: absolute; inset: 0; background: var(--border2); border-radius: 62.4375rem;
  transition: background 0.15s var(--ease);
}
.ng-toggle-slider::before {
  content: ''; position: absolute; width: 1.125rem; height: 1.125rem; left: 0.1875rem; top: 0.1875rem;
  background: #fff; border-radius: 50%; transition: transform 0.15s var(--ease);
  box-shadow: 0 1px 0.1875rem rgba(0,0,0,0.2);
}
.ng-toggle input:checked + .ng-toggle-slider { background: var(--primary); }
.ng-toggle input:checked + .ng-toggle-slider::before { transform: translateX(1rem); }

/* ── Terms & GPA ────────────────────────────────────────────────────────── */
.ng-term-row {
  display: flex; align-items: center; justify-content: space-between; gap: 0.625rem;
  padding: 0.625rem 0; border-top: 1px solid var(--border); font-size: 0.8125rem;
}
.ng-term-row:first-of-type { border-top: none; }
.ng-term-name { font-weight: 700; color: var(--text); }
.ng-term-name.current::after { content: '●'; color: var(--primary); font-size: 0.5rem; margin-left: 0.375rem; vertical-align: middle; }
.ng-term-actions { display: flex; gap: 0.25rem; }
.ng-gpa-readout { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.625rem; }
.ng-gpa-value { font-size: 2rem; font-weight: 800; color: var(--primary); }
.ng-gpa-label { font-size: 0.75rem; color: var(--text-muted); }

/* ── Review ─────────────────────────────────────────────────────────────── */
/* Rendered via renderZenoMarkdownNG now (real <h3-5>/<p>/<ul> elements), not
   raw textContent -- no white-space:pre-wrap needed, block spacing below
   does that job instead, and it'd otherwise double up around the tags. */
.ng-review-result {
  margin-top: 1rem; padding: 1rem 1.125rem; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border);
  font-size: 0.875rem; line-height: 1.6; color: var(--text);
}
.ng-review-result p { margin: 0; }
.ng-review-result p + p { margin-top: 0.75rem; }
.ng-review-result ul, .ng-review-result ol { margin: 0.5rem 0 0; padding-left: 1.25rem; }
.ng-review-result li + li { margin-top: 0.25rem; }
.ng-review-result h3, .ng-review-result h4, .ng-review-result h5 {
  font-weight: 700; color: var(--text); line-height: 1.3;
  margin: 1.25rem 0 0.5rem;
}
.ng-review-result h3:first-child, .ng-review-result h4:first-child, .ng-review-result h5:first-child { margin-top: 0; }
.ng-review-result h3 { font-size: 1.0625rem; }
.ng-review-result h4 { font-size: 0.9375rem; }
.ng-review-result h5 { font-size: 0.875rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); }
.ng-review-result strong { font-weight: 700; }
.ng-review-meta { font-size: 0.75rem; color: var(--text-dim); margin-top: 0.625rem; }

/* ── Chrono, embedded: same .zeno-* classes/styles as zenow's own panel
   (main.css), just re-scoped from #screen-app.chrono-open to
   #ng-app.chrono-open since this is a different page shell. ──────────── */
#ng-app.chrono-open .zeno-panel { flex-basis: var(--zeno-w, 21.25rem); }
#ng-app.chrono-open .zeno-panel-inner { box-shadow: -0.25rem 0 1.5rem rgba(0,0,0,0.06); }
#ng-app.chrono-open #ng-btn-chrono { display: none; }
#ng-app.chrono-open.chrono-max .zeno-panel-inner { box-shadow: none; }

@media (max-width: 768px) {
  #ng-app.chrono-open .zeno-panel { width: 100%; transform: translateX(0); }
  #ng-app.chrono-open .zeno-panel-inner { box-shadow: none; }
  #ng-app.chrono-open #ng-chrono-backdrop { opacity: 1; pointer-events: auto; }
}

/* Quick Ask (main.css's .chrono-quick-bar) is a fixed-position overlay
   pinned to #ng-btn-chrono's right edge. The wordmark never moves for it: the bar
   is sized to the room beside the wordmark (positionChronoQuickBarNG), and
   only where there is too little does it cover the wordmark, which then
   fades. Desktop-only: on mobile the bar docks to the bottom of the screen. */
@media (min-width: 769px) {
  #ng-app.chrono-quick-open.chrono-quick-covers .grades-logo-lockup { opacity: 0; transition: opacity 0.2s ease; }
}
.ng-chat-toggle {
  position: fixed; right: 1.375rem; bottom: 1.375rem; z-index: 40;
  width: 3.25rem; height: 3.25rem; border-radius: 50%; border: none;
  background: var(--primary); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0.375rem 1.125rem rgba(47,111,237,0.4);
  transition: transform 0.15s var(--ease);
}
.ng-chat-toggle:hover { transform: scale(1.06); }
.ng-chat-toggle:active { transform: scale(0.96); }

.ng-chat-panel {
  position: fixed; right: 1.375rem; bottom: 5.375rem; z-index: 41;
  width: 22.5rem; max-width: calc(100vw - 2rem); height: 30rem; max-height: 70vh;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow); display: flex; flex-direction: column; overflow: hidden;
}
.ng-chat-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem 0.875rem; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.ng-chat-close { background: none; border: none; color: var(--text-muted); font-size: 1.25rem; line-height: 1; cursor: pointer; padding: 0.125rem 0.375rem; }
.ng-chat-close:hover { color: var(--text); }
.ng-chat-messages { flex: 1; overflow-y: auto; padding: 0.75rem 0.875rem; display: flex; flex-direction: column; gap: 0.625rem; }
.ng-chat-empty { font-size: 0.75rem; color: var(--text-dim); text-align: center; padding: 1.25rem 0.5rem; }
.ng-chat-msg { max-width: 85%; padding: 0.5rem 0.75rem; border-radius: 0.875rem; font-size: 0.8125rem; line-height: 1.5; white-space: pre-wrap; }
.ng-chat-msg.user { align-self: flex-end; background: var(--primary); color: #fff; border-bottom-right-radius: 0.25rem; }
.ng-chat-msg.assistant { align-self: flex-start; background: var(--surface2); color: var(--text); border-bottom-left-radius: 0.25rem; }
.ng-chat-typing { display: flex; gap: 0.25rem; padding: 0 0.875rem 0.5rem; flex-shrink: 0; }
.ng-chat-typing span {
  width: 0.375rem; height: 0.375rem; border-radius: 50%; background: var(--text-dim);
  animation: ng-typing-bounce 1s infinite ease-in-out;
}
.ng-chat-typing span:nth-child(2) { animation-delay: 0.15s; }
.ng-chat-typing span:nth-child(3) { animation-delay: 0.3s; }
@keyframes ng-typing-bounce { 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; } 30% { transform: translateY(-0.25rem); opacity: 1; } }
.ng-chat-form { display: flex; gap: 0.5rem; padding: 0.625rem; border-top: 1px solid var(--border); flex-shrink: 0; }
.ng-chat-form textarea {
  flex: 1; resize: none; max-height: 5.625rem; padding: 0.5rem 0.6875rem; font-size: 0.8125rem;
}
.ng-chat-form button { flex-shrink: 0; align-self: flex-end; }

/* ── Reports ────────────────────────────────────────────────────────────── */
.ng-report-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.125rem; align-items: center; }
.ng-report-term-select {
  margin-right: auto; padding: 0.4375rem 0.625rem; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface); color: var(--text);
  font-size: 0.78125rem; font-weight: 600;
}
.ng-report-summary {
  padding: 0.875rem 1.125rem; margin-bottom: 1.125rem; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border);
}
.ng-report-summary-title { font-weight: 700; color: var(--text); margin-bottom: 0.375rem; }
.ng-report-summary-stats { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.375rem 1.25rem; font-size: 0.78125rem; color: var(--text-muted); }
.ng-report-summary-stats strong { color: var(--primary); font-size: 1.125rem; font-weight: 800; margin-right: 0.1875rem; font-variant-numeric: tabular-nums; }
.ng-report-content { font-size: 0.8125rem; }
.ng-report-subject { margin-bottom: 1.125rem; padding-bottom: 0.875rem; border-bottom: 1px solid var(--border); }
.ng-report-subject-head { display: flex; justify-content: space-between; gap: 0.75rem; font-weight: 700; color: var(--text); margin-bottom: 0.375rem; }
.ng-report-subject-head span:first-child { min-width: 0; overflow-wrap: anywhere; }
.ng-report-subject-head span:last-child { flex-shrink: 0; font-variant-numeric: tabular-nums; }
.ng-report-table { width: 100%; border-collapse: collapse; font-size: 0.75rem; }
.ng-report-table td { padding: 0.25rem 0; color: var(--text-muted); overflow-wrap: anywhere; }
.ng-report-table td:last-child { text-align: right; color: var(--text); font-weight: 600; white-space: nowrap; padding-left: 0.75rem; font-variant-numeric: tabular-nums; }

/* ── Stats & Badges ───────────────────────────────────────────────────────── */
.ng-stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(8.75rem, 1fr)); gap: 0.625rem; margin-bottom: 1.375rem; }
.ng-stats-card {
  padding: 0.875rem 1rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface);
}
.ng-stats-value { font-size: 1.375rem; font-weight: 800; color: var(--primary); }
.ng-stats-label { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.125rem; }

.ng-stats-streak-card {
  display: flex; align-items: center; gap: 0.875rem; width: 100%;
  padding: 0.875rem 1.125rem; margin-bottom: 1.375rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface); cursor: pointer; text-align: left;
  font-family: var(--font); transition: box-shadow 0.15s, transform 0.1s;
}
.ng-stats-streak-card:hover { box-shadow: var(--shadow-sm); }
.ng-stats-streak-card:active { transform: scale(0.99); }
.ng-stats-streak-card .streak-flame svg { width: 2.25rem; height: 2.25rem; }
.ng-stats-streak-count { font-size: 1.5rem; font-weight: 800; color: var(--text); }
.ng-stats-streak-label { font-size: 0.78125rem; color: var(--text-muted); }

.ng-badges-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(11.25rem, 1fr)); gap: 0.75rem; }
.ng-badge-card {
  position: relative;
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.375rem;
  padding: 1rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface);
}
.ng-badge-share {
  position: absolute; top: 0.625rem; right: 0.625rem;
  width: 1.5rem; height: 1.5rem; padding: 0; border: none; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: transparent; color: var(--text-muted); cursor: pointer;
  transition: background 0.12s var(--ease), color 0.12s var(--ease);
}
.ng-badge-share svg { width: 0.8125rem; height: 0.8125rem; }
.ng-badge-share:hover { background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--primary); }
.ng-badge-icon {
  width: 2.25rem; height: 2.25rem; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--primary);
}
.ng-badge-icon svg { width: 1.125rem; height: 1.125rem; }
.ng-badge-card.premium .ng-badge-icon { background: color-mix(in srgb, #F5B301 18%, transparent); color: #B8860B; }
.ng-badge-name { font-size: 0.84375rem; font-weight: 700; color: var(--text); }
.ng-badge-desc { font-size: 0.75rem; color: var(--text-muted); line-height: 1.4; }
.ng-badge-card.locked { opacity: 0.5; }
.ng-badge-card.locked.premium { opacity: 0.7; }
.ng-badge-upgrade { font-size: 0.75rem; font-weight: 700; color: var(--primary); text-decoration: none; margin-top: 0.125rem; }
.ng-badge-upgrade:hover { text-decoration: underline; }

/* ── University goal (cumulative, degree-wide) ─────────────────────────── */
.ng-ug-card:empty { display: none; }
.ng-ug-card { margin-bottom: 0.75rem; }

.ng-ug-empty {
  display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem;
  padding: 1.125rem 1.25rem; border-radius: var(--radius); border: 1px dashed var(--border2);
  background: var(--surface2);
}
.ng-ug-empty-title { font-size: 0.9375rem; font-weight: 700; color: var(--text); }
.ng-ug-empty-sub { font-size: 0.8125rem; color: var(--text-muted); line-height: 1.5; max-width: 34rem; }

.ng-ug-set {
  display: flex; align-items: center; gap: 1.25rem; flex-wrap: wrap;
  padding: 1.125rem 1.25rem; border-radius: var(--radius); border: 1px solid var(--border);
  background: var(--surface);
}
/* Reuses the Study Timer's own SVG progress-ring markup+CSS verbatim
   (.study-timer-ring* in main.css, already loaded on this page) rather than
   a new implementation -- just resized down here and repurposed to show
   years-into-program instead of a countdown. */
.ng-ug-ring-col { flex-shrink: 0; display: flex; flex-direction: column; align-items: center; }
.ng-ug-ring-col .study-timer-ring-wrap { width: 5.5rem; height: 5.5rem; margin: 0; }
.ng-ug-ring-col .study-timer-ring { width: 100%; height: 100%; }
/* Override the Study Timer's own red (a countdown/urgency color) -- this
   ring shows plain positive progress through the program, not a countdown. */
.ng-ug-ring-col .study-timer-ring-fg { stroke: var(--accent); }
.ng-ug-ring-label { font-size: 0.6875rem; font-weight: 700; color: var(--text-muted); margin-top: 0.25rem; white-space: nowrap; }
.ng-ug-main { flex: 1; min-width: 12rem; display: flex; flex-direction: column; gap: 0.25rem; }
.ng-ug-title-row { display: flex; align-items: center; gap: 0.5rem; }
.ng-ug-title { font-size: 0.75rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.ng-ug-school { font-size: 0.75rem; color: var(--text-muted); line-height: 1.4; margin: 0.125rem 0 0.25rem; }
.ng-ug-standing { font-size: 1.375rem; font-weight: 800; color: var(--text); }
.ng-ug-standing .ng-ug-arrow { color: var(--text-dim); font-weight: 500; margin: 0 0.375rem; }
.ng-ug-gap { font-size: 0.8125rem; font-weight: 600; }
.ng-ug-required { font-size: 0.78125rem; color: var(--text-muted); line-height: 1.45; }
.ng-ug-required.ng-ug-infeasible { color: var(--red); font-weight: 600; }
.ng-ug-actions { display: flex; gap: 0.5rem; margin-top: 0.375rem; }

/* Admission (prospective-mode) goal card's own detail rows -- tests
   recorded / next deadline / activity count have no equivalent in the
   enrolled card, so unlike .ng-ug-required these get a small icon each. */
.ng-ag-rows { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.25rem; }
.ng-ag-row { display: flex; align-items: center; gap: 0.4375rem; font-size: 0.78125rem; color: var(--text-muted); line-height: 1.35; }
.ng-ag-row-icon { flex-shrink: 0; width: 1rem; height: 1rem; display: flex; align-items: center; justify-content: center; color: var(--accent); opacity: 0.85; }
.ng-ag-row-icon svg { width: 100%; height: 100%; }

/* ── University goal walkthrough modal ──────────────────────────────────── */
.ng-wt-dots { display: flex; justify-content: center; gap: 0.5rem; margin-bottom: 1.125rem; }
.ng-wt-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--border2); transition: background 0.15s, transform 0.15s; }
.ng-wt-dot.active { background: var(--primary); transform: scale(1.25); }
.ng-wt-dot.done { background: var(--primary); opacity: 0.5; }

.ng-wt-pane { display: none; }
.ng-wt-pane.active { display: block; animation: fadeIn 0.2s var(--ease); }
.ng-wt-step-title { font-size: 1rem; font-weight: 700; color: var(--text); margin-bottom: 0.25rem; }
.ng-wt-step-hint { font-size: 0.8125rem; color: var(--text-muted); line-height: 1.5; margin-bottom: 0.875rem; }

.ng-wt-standing { display: flex; flex-direction: column; gap: 0.625rem; }
.ng-wt-standing-row { display: flex; justify-content: space-between; align-items: baseline; padding: 0.5rem 0; border-bottom: 1px solid var(--border); font-size: 0.8125rem; }
.ng-wt-standing-row:last-child { border-bottom: none; }
.ng-wt-standing-row-label { color: var(--text-muted); }
.ng-wt-standing-row-value { font-weight: 700; color: var(--text); }
.ng-wt-standing-banner { padding: 0.75rem 0.875rem; border-radius: var(--radius-sm); font-size: 0.8125rem; font-weight: 600; margin-top: 0.5rem; }
.ng-wt-standing-banner.on-track { background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green); }
.ng-wt-standing-banner.at-risk { background: color-mix(in srgb, var(--red) 14%, transparent); color: var(--red); }

.ng-wt-suggestions { display: flex; flex-direction: column; gap: 0.5rem; max-height: 18rem; overflow-y: auto; }
.ng-wt-suggestion-row { display: flex; align-items: center; gap: 0.625rem; padding: 0.5rem 0.625rem; border-radius: var(--radius-sm); background: var(--surface2); }
.ng-wt-suggestion-name { flex: 1; min-width: 0; font-size: 0.8125rem; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ng-wt-suggestion-current { font-size: 0.75rem; color: var(--text-dim); white-space: nowrap; }
.ng-wt-suggestion-arrow { color: var(--text-dim); }
.ng-wt-suggestion-input { width: 4.5rem; text-align: right; flex-shrink: 0; }

@media print {
  .sidebar, .ng-header, .ng-nav, .ng-report-actions, .ng-chat-toggle, .ng-chat-panel { display: none !important; }
  body, .ng-main { background: #fff !important; color: #000 !important; }
  .ng-report-subject { break-inside: avoid; }
}

@media (max-width: 768px) {
  .ng-header-wordmark { font-size: 1.25rem; }
}

@media (max-width: 600px) {
  .ng-main { padding: 1.25rem 1rem 3rem; }
  .ng-subject-grid { grid-template-columns: 1fr 1fr; }
  .ng-nav { padding: 0 0.75rem; }
  .ng-chat-panel { right: 1rem; left: 1rem; width: auto; bottom: 4.875rem; }
  .ng-chat-toggle { right: 1rem; bottom: 1rem; }
}

/* ── Admission test rows ────────────────────────────────────────────────
   Four columns rather than the generic entry row's two: the name, the
   target, the score, and the remove. Both numbers are editable now, so
   they need equal weight -- the target used to be a caption. */
.ng-test-row, .ng-test-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 5rem 5rem 1.25rem;
  gap: 0.375rem; align-items: center;
}
.ng-test-head {
  padding: 0 0.25rem 0.125rem;
  font-size: 0.6875rem;
}
/* Right-aligned over the inputs they label. */
.ng-test-head .ng-target-hint { text-align: center; margin: 0; }
.ng-test-row .ng-entry-label {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ng-test-target-input, .ng-test-actual-input { width: 100%; text-align: center; }

.ng-test-add { margin-top: 0.5rem; flex-wrap: wrap; }
.ng-test-pick { flex: 1 1 10rem; min-width: 0; }
/* Narrow: a scale bound is two or three digits, and at full width the pair
   pushes the name field onto its own line for nothing. */
.ng-test-scale { flex: 0 0 5rem; min-width: 0; }

@media (max-width: 480px) {
  /* The head row's labels do not survive the squeeze; the placeholders in
     the inputs say the same thing. */
  .ng-test-head { display: none; }
  .ng-test-row { grid-template-columns: minmax(0, 1fr) 4rem 4rem 1.25rem; }
}

/* ── Semester report ────────────────────────────────────────────────────
   The Review page is a document now, not a paragraph: figures, charts and
   per-subject cards, with the written analysis as one section inside it.
   Laid out to read top to bottom on a phone and to print without being
   re-authored for paper. */

.gr-actions { align-items: center; }
.gr-term-select {
  height: 2rem; padding: 0 0.5rem; font-size: 0.8125rem; font-weight: 600;
  color: var(--text); background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); max-width: 12rem;
}
.gr-export { position: relative; }
.gr-export-menu {
  position: absolute; top: calc(100% + 0.375rem); left: 0; z-index: 30;
  min-width: 10rem; padding: 0.25rem; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow);
}
.gr-export-menu button {
  text-align: left; padding: 0.4375rem 0.625rem; font-size: 0.8125rem; font-weight: 600;
  color: var(--text); background: none; border: 0; border-radius: var(--radius-sm); cursor: pointer;
}
.gr-export-menu button:hover { background: var(--surface2); }

.gr-report { display: flex; flex-direction: column; gap: 1.125rem; }
.gr-head h2 { font-size: 1.375rem; font-weight: 800; color: var(--text); margin: 0; }
.gr-head-sub { font-size: 0.8125rem; color: var(--text-dim); margin: 0.1875rem 0 0; }

/* Figures first, because they are what somebody opening a term report
   actually wants and the only part that is true by construction. */
.gr-figures {
  display: grid; gap: 0.625rem;
  grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
}
.gr-figure {
  padding: 0.875rem 0.9375rem; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border);
}
.gr-figure-value { font-size: 1.5rem; font-weight: 800; color: var(--text); line-height: 1.1; }
.gr-figure-label { font-size: 0.75rem; font-weight: 600; color: var(--text-muted); margin-top: 0.25rem; }
.gr-figure-sub { font-size: 0.6875rem; color: var(--text-dim); margin-top: 0.125rem; }
.gr-figure-good .gr-figure-value { color: var(--accent); }
.gr-figure-warn .gr-figure-value { color: var(--amber); }
.gr-figure-bad .gr-figure-value { color: var(--red); }

.gr-movers { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.gr-mover {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4375rem;
  padding: 0.5rem 0.75rem; border-radius: var(--radius-md);
  background: var(--surface2); font-size: 0.75rem;
}
.gr-mover-title { font-weight: 700; color: var(--text-muted); }
.gr-mover-item { color: var(--text); }
.gr-mover-up b { color: var(--accent); }
.gr-mover-down b { color: var(--red); }

.gr-panel {
  padding: 1.125rem; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--border);
}
.gr-panel > h3 {
  font-size: 0.8125rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); margin: 0 0 0.875rem;
}
.gr-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.875rem; }
.gr-panel-head h3 {
  font-size: 0.8125rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); margin: 0;
}
.gr-panel-note { font-size: 0.6875rem; color: var(--text-dim); margin: 0.625rem 0 0; }

.gr-toggle { display: inline-flex; padding: 0.125rem; gap: 0.125rem; background: var(--surface2); border-radius: var(--radius-sm); }
.gr-toggle-btn {
  padding: 0.25rem 0.625rem; font-size: 0.6875rem; font-weight: 700;
  color: var(--text-muted); background: none; border: 0; border-radius: calc(var(--radius-sm) - 0.0625rem); cursor: pointer;
}
.gr-toggle-btn.is-active { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }

.gr-chart { position: relative; }
.gr-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.gr-chart-empty { font-size: 0.75rem; color: var(--text-dim); padding: 2rem 0; text-align: center; }
.gr-grid { stroke: var(--border); stroke-width: 1; }
.gr-axis { font-size: 0.6875rem; fill: var(--text-dim); font-family: var(--font); }
.gr-line { fill: none; stroke: var(--accent); stroke-width: 2.25; stroke-linejoin: round; stroke-linecap: round; }
.gr-dot { fill: var(--accent); opacity: 0.55; }
.gr-cross { stroke: var(--text-dim); stroke-width: 1; stroke-dasharray: 3 3; }
.gr-cross-dot { fill: var(--accent); stroke: var(--surface); stroke-width: 2; }
.gr-chart .hidden { display: none; }
.gr-readout {
  position: absolute; top: 0; pointer-events: none;
  padding: 0.375rem 0.5rem; border-radius: var(--radius-sm);
  background: var(--primary); color: #fff; font-size: 0.6875rem; line-height: 1.4;
  box-shadow: var(--shadow-sm); white-space: nowrap;
  display: flex; flex-direction: column; gap: 0.0625rem;
}
.gr-readout-date { opacity: 0.7; font-weight: 600; }
.gr-readout-row { display: flex; align-items: center; gap: 0.3125rem; }
.gr-readout-row i { width: 0.4375rem; height: 0.4375rem; border-radius: 50%; flex-shrink: 0; }
.gr-readout-row b { margin-left: auto; padding-left: 0.625rem; font-weight: 800; }

/* A subject line sits behind the term line: thinner, and never darker than
   the thing it is being compared against. */
.gr-line-sub { stroke-width: 1.75; opacity: 0.85; }

.gr-legends { display: flex; flex-wrap: wrap; gap: 0.3125rem; margin-top: 0.625rem; }
.gr-legend {
  display: inline-flex; align-items: center; gap: 0.3125rem;
  padding: 0.1875rem 0.5rem; font-size: 0.6875rem; font-weight: 600;
  color: var(--text-muted); background: var(--surface2);
  border: 1px solid transparent; border-radius: 62.4375rem; cursor: pointer;
  transition: color 0.15s var(--ease), background 0.15s var(--ease), border-color 0.15s var(--ease);
}
.gr-legend:hover:not(:disabled) { color: var(--text); }
.gr-legend.is-on { color: var(--text); background: var(--surface); border-color: var(--border2); }
.gr-legend:disabled { cursor: default; color: var(--text); background: var(--surface); border-color: var(--border2); }
.gr-legend-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; opacity: 0.35; }
.gr-legend.is-on .gr-legend-dot, .gr-legend:disabled .gr-legend-dot { opacity: 1; }

.gr-chart-bars { display: flex; flex-direction: column; gap: 0.625rem; }
.gr-bar-row {
  display: grid; grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr) auto; align-items: center; gap: 0.75rem;
  cursor: pointer; border-radius: 0.5rem;
}
.gr-bar-row:focus { outline: none; }
.gr-bar-row:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
.gr-bar-name { font-size: 0.75rem; font-weight: 600; color: var(--text); text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gr-bar-value { min-width: 3rem; font-size: 0.75rem; font-weight: 700; color: var(--text-muted); text-align: right; font-variant-numeric: tabular-nums; }
.gr-bar-track { position: relative; height: 0.875rem; border-radius: 62rem; background: var(--surface2); }
.gr-bar { position: absolute; inset: 0 auto 0 0; min-width: 0.875rem; border-radius: inherit; background: var(--text-dim); transition: opacity 0.15s var(--ease); }
.gr-bar-over { background: var(--accent); }
.gr-bar-near { background: var(--amber); }
.gr-bar-under { background: color-mix(in srgb, var(--red) 45%, var(--study-red)); }
.gr-bar-none { background: var(--border2); }
.gr-bar-row:hover .gr-bar { opacity: 0.8; }
.gr-target { position: absolute; top: -0.1875rem; bottom: -0.1875rem; width: 2px; margin-left: -1px; border-radius: 1px; background: var(--text); }
@media (max-width: 520px) {
  /* The name above its bar: the whole width for both. */
  .gr-bar-row { grid-template-columns: minmax(0, 1fr) auto; row-gap: 0.3125rem; }
  .gr-bar-name { grid-column: 1 / -1; text-align: left; }
}

.gr-dist { fill: var(--accent); }
.gr-dist-b { fill: color-mix(in srgb, var(--accent) 75%, var(--surface3)); }
.gr-dist-c { fill: var(--amber); }
.gr-dist-d { fill: color-mix(in srgb, var(--study-red) 55%, var(--amber)); }
.gr-dist-f { fill: color-mix(in srgb, var(--red) 45%, var(--study-red)); }
.gr-dist-label { font-weight: 700; }
.gr-dist-col:hover .gr-dist { opacity: 0.82; }

.gr-narrative .ng-review-result { padding: 0; background: none; border: 0; }

.gr-subjects { display: grid; gap: 0.75rem; grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr)); }
.gr-subject {
  min-width: 0; padding: 0.875rem 1rem; border-radius: var(--radius-md);
  background: var(--surface2); border: 1px solid transparent;
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease);
}
.gr-subject.is-highlit { border-color: var(--accent); background: var(--surface); }
.gr-subject-head { display: flex; align-items: center; gap: 0.4375rem; margin-bottom: 0.5rem; }
.gr-subject-head h4 { flex: 1; min-width: 0; font-size: 0.875rem; font-weight: 700; color: var(--text); margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gr-subject-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; flex-shrink: 0; }
.gr-subject-avg { flex-shrink: 0; font-size: 0.9375rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; }
.gr-chip { font-size: 0.6875rem; font-weight: 700; padding: 0.0625rem 0.3125rem; border-radius: 62.4375rem; }
.gr-chip-over { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent-dim); }
.gr-chip-near { background: color-mix(in srgb, var(--amber) 22%, transparent); color: #92400E; }
.gr-chip-under { background: color-mix(in srgb, var(--red) 14%, transparent); color: var(--red); }
.gr-trend { font-size: 0.875rem; font-weight: 700; }
.gr-trend-up { color: var(--accent); }
.gr-trend-down { color: var(--red); }
.gr-trend-flat { color: var(--text-dim); }

.gr-spark { display: block; width: 100%; height: 2.75rem; margin-bottom: 0.5rem; }
.gr-spark-line { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.gr-spark-dot { fill: var(--accent); }

.gr-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.375rem 1rem; margin: 0; }
.gr-facts div { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; min-width: 0; }
.gr-facts dt { flex-shrink: 0; font-size: 0.6875rem; color: var(--text-muted); }
.gr-facts dd { min-width: 0; font-size: 0.75rem; font-weight: 700; color: var(--text); margin: 0; text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* Best and worst carry the mark's name: a line of their own, wrapped. */
.gr-facts .gr-fact-wide { grid-column: 1 / -1; padding-top: 0.375rem; border-top: 1px solid color-mix(in srgb, var(--border) 60%, transparent); }
.gr-facts .gr-fact-wide + .gr-fact-wide { padding-top: 0; border-top: 0; }
.gr-facts .gr-fact-wide dd { white-space: normal; overflow-wrap: anywhere; line-height: 1.4; }
.gr-pos { color: var(--accent); }
.gr-neg { color: var(--red); }

.gr-subject-note { font-size: 0.6875rem; color: var(--text-muted); margin: 0.625rem 0 0; line-height: 1.5; }
.gr-subject-risk { font-size: 0.6875rem; margin: 0.375rem 0 0; line-height: 1.5; }
.gr-risk-high { color: var(--red); }
.gr-risk-medium { color: #92400E; }
.gr-risk-low { color: var(--text-muted); }

.gr-cats { width: 100%; border-collapse: collapse; margin-top: 0.75rem; font-size: 0.6875rem; table-layout: auto; }
.gr-cats th:not(:first-child), .gr-cats td:not(:first-child) { white-space: nowrap; padding-left: 0.625rem; font-variant-numeric: tabular-nums; }
.gr-cats td:first-child { overflow-wrap: anywhere; }
.gr-cats th { text-align: left; font-weight: 700; color: var(--text-dim); padding: 0.25rem 0; border-bottom: 1px solid var(--border); }
.gr-cats th:not(:first-child), .gr-cats td:not(:first-child) { text-align: right; }
.gr-cats td { padding: 0.25rem 0; color: var(--text); border-bottom: 1px solid color-mix(in srgb, var(--border) 50%, transparent); }
.gr-cats tr:last-child td { border-bottom: 0; }

.ng-inline-error { font-size: 0.8125rem; color: var(--red); padding: 0.75rem 0; }

/* Printing the report: everything else on the page goes, the panels stop
   being cards, and nothing is allowed to break across a page in the middle
   of a subject. Produces a real PDF through the browser's own dialog. */
@media print {
  body.gr-printing .gr-actions,
  body.gr-printing .ng-review-meta { display: none !important; }
  .gr-report { gap: 0.75rem; }
  .gr-panel, .gr-figure {
    border: 1px solid #ddd !important; background: #fff !important;
    box-shadow: none !important; break-inside: avoid;
  }
  .gr-subject { background: #fff !important; border: 1px solid #eee !important; break-inside: avoid; }
  .gr-subjects { grid-template-columns: 1fr 1fr; }
  /* The crosshair follows a pointer nobody has on paper, and the
     average/GPA switch is a control, not information. The legend stays --
     printed, it is the key to the lines. */
  .gr-readout, .gr-cross, .gr-cross-dots, .gr-toggle { display: none !important; }
  .gr-legend { cursor: default; }
  .gr-figures { grid-template-columns: repeat(4, 1fr); }
  .gr-narrative { break-before: page; }
}

/* The report carries its own title, so the view's page heading would say
   the same thing twice. */
#ng-view-review .ng-page-title.gr-has-report { display: none; }

@media (max-width: 600px) {
  .gr-facts { grid-template-columns: 1fr; }
  .gr-subjects { grid-template-columns: 1fr; }
  .gr-term-select { max-width: 8rem; }
}
.gr-narrative-wait { font-size: 0.8125rem; color: var(--text-dim); padding: 0.5rem 0; }

/* ── Grade charts ─────────────────────────────────────────────────────────
   Trading-terminal conventions, because the marks behave like a price and
   students already read those shapes: the level in the accent, rising and
   falling in green and red, a dashed target to measure against, and a grid
   quiet enough that the data sits on top of it rather than in it. */
.gc { width: 100%; height: auto; display: block; overflow: visible; }
.gc-grid { stroke: var(--border); stroke-width: 1; opacity: 0.55; }
.gc-axis { font-size: 0.625rem; fill: var(--text-dim); font-family: var(--font); }
/* The chart is drawn at 720 units wide and scaled to its box: on a phone
   the labels and the line are drawn larger so they read at a third of the
   size. */
@media (max-width: 640px) {
  .gc-axis { font-size: 1.375rem; }
  .gc-line, .gc-wick, .gc-bar-line { stroke-width: 4; }
  .gc-grid { stroke-width: 2; }
}
.gc-axis-x { text-anchor: middle; }
.gc-line { fill: none; stroke: var(--primary); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.gc-area { fill: var(--primary); opacity: 0.12; stroke: none; }
.gc-dot { fill: var(--primary); }
.gc-point { fill: var(--primary); opacity: 0.75; }
.gc-fit { stroke: var(--text-dim); stroke-width: 1.5; stroke-dasharray: 5 4; opacity: 0.8; }
.gc-target { stroke: var(--amber); stroke-width: 1.5; stroke-dasharray: 4 4; opacity: 0.9; }
.gc-target-label { fill: var(--amber); }
.gc-wick, .gc-bar-line { stroke-width: 1.5; }
.gc-up .gc-body { fill: var(--gc-up, #16A34A); }
.gc-up .gc-wick, .gc-up .gc-bar-line { stroke: var(--gc-up, #16A34A); }
.gc-down .gc-body { fill: var(--gc-down, #DC2626); }
.gc-down .gc-wick, .gc-down .gc-bar-line { stroke: var(--gc-down, #DC2626); }
.gc-neutral .gc-body { fill: var(--primary); opacity: 0.75; }
.gc g:hover .gc-body { opacity: 0.85; }
:root[data-theme="dark"] { --gc-up: #4ADE80; --gc-down: #F87171; }

/* The type switcher: an arrow that slides the row of types out. */
.ng-chart-head {
  display: flex; align-items: center; gap: 0.75rem;
  margin-bottom: 0.5rem; flex-wrap: wrap;
}
.ng-chart-types {
  display: flex; align-items: center; gap: 0.25rem; margin-left: auto;
  padding: 0.1875rem; border-radius: 62.4375rem; max-width: 100%;
  border: 1px solid transparent; transition: background 0.2s, border-color 0.2s;
}
.ng-chart-types.is-open { background: var(--surface2); border-color: var(--border); }
/* Shut, the switcher is only its arrow. The eight chips are laid out the
   whole time and revealed by width, so opening is a slide rather than a
   jump -- display:none cannot be animated. */
.ng-chart-chips {
  display: flex; gap: 0.25rem;
  max-width: 0; opacity: 0; overflow: hidden;
  transition: max-width 0.28s var(--ease, ease), opacity 0.18s ease;
}
.ng-chart-types.is-open .ng-chart-chips {
  max-width: 20rem; opacity: 1;
  overflow-x: auto; scrollbar-width: none;
}
.ng-chart-chips::-webkit-scrollbar { display: none; }
/* Hidden from the tab order while closed, or Tab walks eight invisible
   buttons before reaching the next real control. */
.ng-chart-types:not(.is-open) .ng-chart-type { visibility: hidden; }
.ng-chart-caret-btn {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 1.75rem; height: 1.75rem;
  border: 1px solid var(--border); border-radius: 50%; background: var(--surface);
  color: var(--text-muted); cursor: pointer;
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.ng-chart-types.is-open .ng-chart-caret-btn { border-color: transparent; background: none; }
.ng-chart-caret-btn:hover { color: var(--text); background: var(--surface3, rgba(127,127,127,0.12)); }
.ng-chart-caret { width: 0.875rem; height: 0.875rem; transition: transform 0.22s var(--ease, ease); }
/* At the right of the header the row opens to the left: the arrow points
   that way shut, and back to the right to close it. */
.ng-chart-types.is-open .ng-chart-caret { transform: rotate(180deg); }
/* Narrow screens: the header stacks and the row sits on the left, so it
   opens to the right -- the arrow turns with it. */
/* Narrow screens: the arrow stays at the end of the title's line; open,
   the row takes a line of its own under the title, full width. */
@media (max-width: 480px) {
  .ng-chart-head { flex-wrap: wrap; row-gap: 0.5rem; }
  .ng-chart-types.is-open { order: 2; flex: 1 0 100%; justify-content: space-between; }
  .ng-chart-types.is-open .ng-chart-chips { max-width: none; flex: 1; }
}
.ng-chart-type {
  display: flex; align-items: center; justify-content: center;
  width: 1.875rem; height: 1.875rem; flex-shrink: 0;
  border: none; border-radius: 62.4375rem; background: none;
  color: var(--text-dim); cursor: pointer;
  transition: background 0.14s, color 0.14s;
}
.ng-chart-type:hover { color: var(--text); background: var(--surface3, rgba(127,127,127,0.12)); }
.ng-chart-type.active { background: var(--surface); color: var(--primary); box-shadow: 0 1px 0.1875rem rgba(0,0,0,0.12); }
.ng-chart-type svg { width: 0.9375rem; height: 0.9375rem; }
.ng-chart-note { font-size: 0.6875rem; color: var(--text-dim); margin-top: 0.375rem; }

/* Phones: same header rhythm as zenow's .topbar (0.5rem padding, hamburger
   8px from the edge) instead of the taller desktop band. */
@media (max-width: 480px) {
  .ng-header { height: auto; padding: 0.5rem; gap: 0.25rem; }
}

/* Reports: the written review sits under the numbers, as its own part. */
.ng-review-head { margin-top: 2.25rem; }

/* Every subject together: the overall average, every mark over time, the
   latest marks (grades.js renderOverview). */
.ng-overview {
  display: grid; gap: 0.75rem; margin-bottom: 1.25rem;
  /* The chart is what is read: the whole width, under the average and the
     latest marks. A third of a row made it a thumbnail. */
  grid-template-columns: minmax(11rem, 15rem) minmax(0, 1fr);
  grid-template-areas: "avg latest" "chart chart";
}
.ng-ov-avg { grid-area: avg; } .ng-ov-latest { grid-area: latest; } .ng-ov-chart { grid-area: chart; }
.ng-overview.hidden { display: none; }
.ng-overview > div { min-width: 0; padding: 1rem 1.125rem; border-radius: var(--radius); border: 1px solid var(--border); background: var(--surface); }
.ng-ov-label { font-size: 0.6875rem; font-weight: 650; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-dim); }
.ng-ov-avg { display: flex; flex-direction: column; justify-content: center; gap: 0.375rem;
  background: radial-gradient(120% 100% at 0% 0%, color-mix(in srgb, var(--accent) 10%, var(--surface)) 0%, var(--surface) 70%) !important; }
.ng-ov-num { font-size: clamp(2.25rem, 4vw, 3rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1; color: var(--text); font-variant-numeric: tabular-nums; }
.ng-ov-sub { font-size: 0.75rem; color: var(--text-muted); }
.ng-ov-chart { display: flex; flex-direction: column; gap: 0.5rem; }
.ng-ov-chart .ng-chart-head { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin: 0; }
.ng-ov-chart .ng-chart { margin: 0; }
.ng-ov-latest { display: flex; flex-direction: column; gap: 0.375rem; }
.ng-ov-list { list-style: none; margin: 0 -0.5rem; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); column-gap: 0.5rem; }
.ng-ov-row { display: flex; align-items: center; gap: 0.625rem; width: 100%; padding: 0.4375rem 0.5rem; border: 0; border-radius: 0.625rem; background: none; cursor: pointer; text-align: left; color: var(--text); font: inherit; }
.ng-ov-row:hover { background: var(--surface2); }
.ng-ov-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; flex-shrink: 0; }
.ng-ov-what { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 0.0625rem; }
.ng-ov-what b { font-size: 0.8125rem; font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ng-ov-what span { font-size: 0.6875rem; color: var(--text-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ng-ov-score { flex-shrink: 0; min-width: 2.75rem; text-align: center; padding: 0.25rem 0.5rem; border-radius: 0.5rem; font-size: 0.8125rem; font-weight: 750; font-variant-numeric: tabular-nums; }
.ng-ov-score.lvl-high { color: var(--green); background: color-mix(in srgb, var(--green) 12%, transparent); }
.ng-ov-score.lvl-mid { color: #B45309; background: color-mix(in srgb, #F59E0B 14%, transparent); }
.ng-ov-score.lvl-low { color: var(--red); background: color-mix(in srgb, var(--red) 11%, transparent); }
@media (max-width: 640px) { .ng-overview { grid-template-columns: 1fr; grid-template-areas: "avg" "chart" "latest"; } .ng-ov-avg { flex-direction: row; flex-wrap: wrap; align-items: baseline; column-gap: 0.75rem; } .ng-ov-avg .ng-ov-label { width: 100%; } }

/* ── Admission goal: where, and what it takes (grades.js ngAg*) ───────── */
.ag { display: flex; flex-direction: column; gap: 1.5rem; }
.ag-label { display: block; font-size: 0.6875rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.5rem; }
.ag-where { display: flex; flex-direction: column; gap: 0.5rem; }
.ag-program { width: 100%; }
.ag-find { display: inline-flex; align-items: center; justify-content: center; gap: 0.4375rem; min-height: 2.625rem; margin-top: 0.25rem; padding: 0 1.125rem; border: 0; border-radius: 0.75rem; background: var(--primary); color: #fff; font: inherit; font-size: 0.875rem; font-weight: 700; cursor: pointer; transition: transform 0.12s var(--ease), opacity 0.15s; }
.ag-find:active { transform: scale(0.98); }
.ag-find:disabled { opacity: 0.4; cursor: default; }
.ag-note { margin: 0.25rem 0 0; padding: 0.75rem 0.875rem; border-radius: 0.75rem; background: color-mix(in srgb, var(--accent) 9%, var(--surface)); font-size: 0.8438rem; line-height: 1.5; color: var(--text); }
.ag-empty { padding: 1rem; border-radius: 0.75rem; border: 1px dashed var(--border2); font-size: 0.8438rem; line-height: 1.5; color: var(--text-muted); }
.ag-list { display: flex; flex-direction: column; gap: 0.5rem; }
.ag-list:empty { display: none; }
.ag-section { display: flex; flex-direction: column; gap: 0.5rem; }
.ag-card { padding: 0.875rem 1rem 0.875rem; border-radius: 0.875rem; background: var(--surface); border: 1px solid var(--border); display: flex; flex-direction: column; gap: 0.625rem; }
.ag-card-head { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.ag-card-name { flex: 1; min-width: 0; font-weight: 700; font-size: 0.9063rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-status { font-size: 0.7188rem; font-weight: 700; padding: 0.1875rem 0.5rem; border-radius: 1rem; white-space: nowrap; }
.ag-status.is-ok { background: color-mix(in srgb, #16A34A 13%, transparent); color: #15803D; }
.ag-status.is-gap { background: color-mix(in srgb, #F59E0B 15%, transparent); color: #B45309; }
.ag-status.is-low { background: color-mix(in srgb, #DC2626 12%, transparent); color: #B91C1C; }
.ag-x { flex: none; width: 1.75rem; height: 1.75rem; display: grid; place-items: center; border: 0; border-radius: 50%; background: transparent; color: var(--text-dim); cursor: pointer; transition: background 0.15s, color 0.15s; }
.ag-x:hover { background: var(--surface2); color: var(--text); }
.ag-bar { position: relative; height: 0.375rem; border-radius: 1rem; background: var(--surface3); }
.ag-bar-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: inherit; background: #F59E0B; transition: width 0.5s var(--ease); }
.ag-bar.is-ok .ag-bar-fill { background: #16A34A; }
.ag-tick { position: absolute; top: -0.25rem; bottom: -0.25rem; width: 0.125rem; margin-left: -0.0625rem; border-radius: 0.125rem; }
.ag-tick.is-min { background: var(--text-dim); }
.ag-tick.is-goal { background: var(--primary); }
.ag-fields { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; }
.ag-avg .ag-fields { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.ag-field { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; margin: 0; }
.ag-field > span { font-size: 0.6875rem; font-weight: 600; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ag-field input { width: 100%; min-width: 0; text-align: left; padding: 0.5rem 0.625rem; font-size: 0.9063rem; font-variant-numeric: tabular-nums; }
.ag-field-ro b { padding: 0.5rem 0; font-size: 0.9063rem; font-variant-numeric: tabular-nums; }
.ag-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding-top: 0.625rem; border-top: 1px solid var(--border); font-size: 0.7813rem; color: var(--text-muted); }
.ag-sim { display: inline-flex; align-items: center; gap: 0.125rem; flex: none; padding: 0.375rem 0.625rem 0.375rem 0.75rem; border-radius: 1rem; background: var(--primary); color: #fff; font-size: 0.7813rem; font-weight: 700; text-decoration: none; transition: transform 0.12s var(--ease); }
.ag-sim:active { transform: scale(0.97); }
.ag-row { display: flex; align-items: center; gap: 0.625rem; padding: 0.625rem 0.5rem 0.625rem 0.875rem; border-radius: 0.75rem; background: var(--surface); border: 1px solid var(--border); }
.ag-row-icon { flex: none; width: 1.125rem; height: 1.125rem; color: var(--accent); }
.ag-row-icon svg { width: 100%; height: 100%; }
.ag-row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ag-row-t { font-size: 0.875rem; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-row-d { font-size: 0.75rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-days { flex: none; font-size: 0.75rem; font-weight: 700; color: var(--text-muted); }
.ag-days.is-soon { color: #B45309; }
.ag-days.is-past { color: var(--text-dim); font-weight: 500; }
.ag-add { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-top: 0.25rem; }
.ag-chip { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.4375rem 0.8125rem; border-radius: 1rem; border: 1px dashed var(--border2); background: transparent; font: inherit; font-size: 0.8125rem; font-weight: 600; color: var(--text-muted); cursor: pointer; transition: background 0.15s, color 0.15s, border-color 0.15s; }
.ag-chip:hover, .ag-chip.is-on { border-style: solid; border-color: var(--border2); background: var(--surface); color: var(--text); }
.ag-form { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.875rem; border-radius: 0.875rem; background: var(--surface2); }
.ag-form.hidden { display: none; }
.ag-form > * { flex: none; }
.ag-form .btn { align-self: flex-start; }
.ag-form-row { display: flex; gap: 0.5rem; }
.ag-form-row:has(> .hidden:first-child) { display: none; }
.ag-form-row input { flex: 1; min-width: 0; }
.ag-subjects { border-top: 1px solid var(--border); padding-top: 0.875rem; }
.ag-subjects summary { cursor: pointer; font-size: 0.8438rem; font-weight: 600; color: var(--text-muted); }
.ag-subjects[open] summary { margin-bottom: 0.75rem; }
.ag-subjects.hidden { display: none; }
/* The goal's card in Obiettivi: each test with its line and a way to practise it. */
.ag-goal-program { font-size: 0.8125rem; color: var(--text-muted); margin-top: -0.125rem; }
.ag-goal-tests { display: flex; flex-direction: column; gap: 0.625rem; margin: 0.5rem 0 0.25rem; }
.ag-goal-test { display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "main sim" "bar sim"; gap: 0.375rem 0.75rem; align-items: center; }
.ag-goal-test-main { grid-area: main; display: flex; flex-wrap: wrap; gap: 0.125rem 0.5rem; align-items: baseline; font-size: 0.8125rem; }
.ag-goal-test-main span { color: var(--text-muted); font-size: 0.75rem; }
.ag-goal-test .ag-bar { grid-area: bar; }
.ag-goal-test .ag-sim { grid-area: sim; }
@media (max-width: 520px) {
  .ag-goal-test { grid-template-columns: minmax(0, 1fr); grid-template-areas: "main" "bar" "sim"; }
  .ag-goal-test .ag-sim { justify-self: start; }
  .ag-fields { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.375rem; }
  .ag-field input { padding: 0.5rem; }
}
:root[data-theme="dark"] .ag-find, :root[data-theme="dark"] .ag-sim { background: #E5E7EB; color: #0F1420; }
:root[data-theme="dark"] .ag-tick.is-goal { background: #E5E7EB; }
:root[data-theme="dark"] .ag-status.is-ok { color: #4ADE80; }
:root[data-theme="dark"] .ag-status.is-gap, :root[data-theme="dark"] .ag-days.is-soon { color: #FBBF24; }
:root[data-theme="dark"] .ag-status.is-low { color: #F87171; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .ag-find, :root:not([data-theme="light"]) .ag-sim { background: #E5E7EB; color: #0F1420; }
  :root:not([data-theme="light"]) .ag-tick.is-goal { background: #E5E7EB; }
  :root:not([data-theme="light"]) .ag-status.is-ok { color: #4ADE80; }
  :root:not([data-theme="light"]) .ag-status.is-gap, :root:not([data-theme="light"]) .ag-days.is-soon { color: #FBBF24; }
  :root:not([data-theme="light"]) .ag-status.is-low { color: #F87171; }
}
