/* ==========================================================================
   FacultyLens — Design System
   Drop into: src/main/resources/static/css/app.css
   Load AFTER any framework CSS so these rules win.
   Requires Inter:
     <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">

   Aesthetic: light, calm, dense. Neutral canvas, white cards, soft borders,
   one accent colour, colour reserved for status only.

   1. Tokens   2. Base & type   3. App shell   4. Card   5. Stat tile
   6. Badges   7. Buttons       8. Table       9. Progress bar
   10. AI insight card  11. Exception row  12. Heatmap  13. Forms
   14. Empty state      15. Utilities      16. Responsive

   Nothing below the token block hardcodes a colour — restyle by
   overriding :root only.
   ========================================================================== */

/* --- 1. Tokens ---------------------------------------------------------- */
:root {
  /* Canvas & surfaces */
  --fl-bg:            #F6F7F9;
  --fl-surface:       #FFFFFF;
  --fl-surface-alt:   #FAFBFC;
  --fl-border:        #E4E7EC;
  --fl-border-strong: #D0D5DD;

  /* Text */
  --fl-text:          #101828;
  --fl-text-muted:    #667085;
  --fl-text-subtle:   #98A2B3;
  --fl-text-invert:   #FFFFFF;

  /* Accent (single) */
  --fl-accent:        #0F6FDE;
  --fl-accent-hover:  #0B58B2;
  --fl-accent-soft:   #EAF2FE;

  /* Status — used ONLY for state, never decoration */
  --fl-ok:            #12B76A;
  --fl-ok-soft:       #ECFDF3;
  --fl-ok-ink:        #067647;
  --fl-warn:          #F79009;
  --fl-warn-soft:     #FFFAEB;
  --fl-warn-ink:      #B54708;
  --fl-danger:        #F04438;
  --fl-danger-soft:   #FEF3F2;
  --fl-danger-ink:    #B42318;
  --fl-danger-line:   #FDA29B;
  --fl-neutral:       #98A2B3;
  --fl-neutral-soft:  #F2F4F7;
  --fl-neutral-ink:   #475467;

  /* Heatmap intensity ramp */
  --fl-heat-0: #F2F4F7;
  --fl-heat-1: #D9E8FC;
  --fl-heat-2: #9CC4F5;
  --fl-heat-3: #3B85E4;
  --fl-heat-4: #0B58B2;

  /* Radius */
  --fl-r-sm: 6px;
  --fl-r:    10px;
  --fl-r-lg: 14px;
  --fl-r-pill: 999px;

  /* Shadow — soft, barely there */
  --fl-shadow-sm: 0 1px 2px rgba(16,24,40,.05);
  --fl-shadow:    0 1px 3px rgba(16,24,40,.08), 0 1px 2px rgba(16,24,40,.04);
  --fl-shadow-md: 0 4px 12px rgba(16,24,40,.08);
  --fl-ring:      0 0 0 3px var(--fl-accent-soft);

  /* Spacing scale */
  --fl-s1: 4px;  --fl-s2: 8px;  --fl-s3: 12px; --fl-s4: 16px;
  --fl-s5: 20px; --fl-s6: 24px; --fl-s8: 32px; --fl-s10: 40px;

  /* Type */
  --fl-font: 'Inter', -apple-system, 'Segoe UI', Roboto, sans-serif;
  --fl-font-mono: 'JetBrains Mono', 'SF Mono', Menlo, monospace;
}

/* --- 2. Base & typography ----------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--fl-bg);
  color: var(--fl-text);
  font-family: var(--fl-font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-wrap: pretty;
}

h1,h2,h3,h4,h5 { font-weight: 600; letter-spacing: -0.011em; color: var(--fl-text); margin: 0; }
h1 { font-size: 24px; }
h2 { font-size: 19px; }
h3 { font-size: 16px; }
h4 { font-size: 14px; }
p  { margin: 0; }

a { color: var(--fl-accent); text-decoration: none; }
a:hover { color: var(--fl-accent-hover); text-decoration: underline; }

.fl-muted   { color: var(--fl-text-muted); }
.fl-subtle  { color: var(--fl-text-subtle); font-size: 12.5px; }
.fl-num     { font-variant-numeric: tabular-nums; }
.fl-mono    { font-family: var(--fl-font-mono); font-size: 12.5px; }
.fl-label   { font-size: 11.5px; font-weight: 600; letter-spacing: .04em;
              text-transform: uppercase; color: var(--fl-text-subtle); }

/* --- 3. App shell ------------------------------------------------------- */
.fl-shell { display: flex; min-height: 100vh; }

.fl-sidebar {
  width: 232px; flex-shrink: 0;
  background: var(--fl-surface);
  border-right: 1px solid var(--fl-border);
  padding: var(--fl-s5) var(--fl-s3);
  display: flex; flex-direction: column;
}
.fl-brand {
  display: flex; align-items: center; gap: var(--fl-s2);
  padding: 0 var(--fl-s2) var(--fl-s5);
  font-size: 16px; font-weight: 650; letter-spacing: -0.02em;
}
.fl-brand-mark {
  width: 26px; height: 26px; border-radius: var(--fl-r-sm);
  background: var(--fl-accent); color: var(--fl-text-invert);
  display: grid; place-items: center; font-size: 13px; font-weight: 700;
}

.fl-nav { display: flex; flex-direction: column; gap: 2px; }
.fl-nav-item {
  display: flex; align-items: center; gap: var(--fl-s3);
  padding: 8px var(--fl-s3); border-radius: var(--fl-r-sm);
  color: var(--fl-text-muted); font-weight: 500; font-size: 13.5px;
}
.fl-nav-item:hover { background: var(--fl-surface-alt); color: var(--fl-text); text-decoration: none; }
.fl-nav-item.active { background: var(--fl-accent-soft); color: var(--fl-accent); font-weight: 600; }
.fl-nav-item.active:hover { background: var(--fl-accent-soft); color: var(--fl-accent); }
/* Pre-icon placeholder slot. The sidebar now renders real .fl-icon glyphs; this
   dashed 16px box survives only for the /dev/styleguide shell specimen. */
.fl-nav-icon { width: 16px; height: 16px; flex-shrink: 0; border-radius: 3px;
               border: 1px dashed var(--fl-border-strong); }
.fl-nav-item.active .fl-nav-icon { border-color: var(--fl-accent); }
.fl-nav-section { padding: var(--fl-s5) var(--fl-s3) var(--fl-s2); }
.fl-nav-foot { margin-top: auto; padding-top: var(--fl-s5); }

.fl-main { flex: 1; min-width: 0; }
.fl-topbar {
  height: 60px; background: var(--fl-surface);
  border-bottom: 1px solid var(--fl-border);
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--fl-s6);
}
.fl-page { padding: var(--fl-s6); max-width: 1400px; }
.fl-page-head { margin-bottom: var(--fl-s6); }
.fl-page-head h1 { margin: 0 0 2px; }

/* --- 4. Card ------------------------------------------------------------ */
.fl-card {
  background: var(--fl-surface);
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-r);
  box-shadow: var(--fl-shadow-sm);
}
.fl-card-head {
  padding: var(--fl-s4) var(--fl-s5);
  border-bottom: 1px solid var(--fl-border);
  display: flex; align-items: center; justify-content: space-between; gap: var(--fl-s3);
}
.fl-card-head h3 { margin: 0; }
.fl-card-body { padding: var(--fl-s5); }
.fl-card-body.tight { padding: var(--fl-s3) var(--fl-s4); }
.fl-card-body.flush { padding: 0; }

/* --- 5. Stat tile ------------------------------------------------------- */
.fl-stat {
  display: block;
  background: var(--fl-surface);
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-r);
  padding: var(--fl-s4) var(--fl-s5);
  box-shadow: var(--fl-shadow-sm);
  transition: box-shadow .15s, border-color .15s;
}
a.fl-stat:hover { box-shadow: var(--fl-shadow-md); border-color: var(--fl-border-strong);
                  text-decoration: none; color: inherit; }
.fl-stat-label { font-size: 12.5px; color: var(--fl-text-muted); margin-bottom: var(--fl-s2); }
.fl-stat-value { font-size: 28px; font-weight: 650; letter-spacing: -0.02em;
                 font-variant-numeric: tabular-nums; line-height: 1.1; }
.fl-stat-meta  { font-size: 12.5px; margin-top: var(--fl-s2); color: var(--fl-text-muted); }
.fl-stat-meta.is-down { color: var(--fl-danger); }
.fl-stat-meta.is-up   { color: var(--fl-ok); }

/* --- 6. Badges (status) ------------------------------------------------- */
.fl-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--fl-r-pill);
  font-size: 12px; font-weight: 550; line-height: 1.4;
  border: 1px solid transparent; white-space: nowrap;
}
.fl-badge::before { content:''; width:6px; height:6px; border-radius:50%; background: currentColor; }
.fl-badge.ok      { background: var(--fl-ok-soft);      color: var(--fl-ok-ink); }
.fl-badge.warn    { background: var(--fl-warn-soft);    color: var(--fl-warn-ink); }
.fl-badge.danger  { background: var(--fl-danger-soft);  color: var(--fl-danger-ink); }
.fl-badge.neutral { background: var(--fl-neutral-soft); color: var(--fl-neutral-ink); }
.fl-badge.accent  { background: var(--fl-accent-soft);  color: var(--fl-accent); }
.fl-badge.plain   { background: var(--fl-surface); color: var(--fl-text-muted);
                    border-color: var(--fl-border-strong); border-radius: var(--fl-r-sm);
                    font-size: 11.5px; font-weight: 600; letter-spacing: .04em;
                    text-transform: uppercase; padding: 2px 7px; }
.fl-badge.plain::before { display: none; }

/* --- 7. Buttons --------------------------------------------------------- */
.fl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--fl-s2);
  padding: 8px 14px; border-radius: var(--fl-r-sm);
  font-family: inherit; font-size: 13.5px; font-weight: 550; line-height: 1.3;
  border: 1px solid transparent; cursor: pointer;
  transition: background .15s, border-color .15s, box-shadow .15s;
}
.fl-btn:hover { text-decoration: none; }
.fl-btn:focus-visible { outline: none; box-shadow: var(--fl-ring); }
.fl-btn-primary   { background: var(--fl-accent); color: var(--fl-text-invert); }
.fl-btn-primary:hover { background: var(--fl-accent-hover); color: var(--fl-text-invert); }
.fl-btn-secondary { background: var(--fl-surface); color: var(--fl-text);
                    border-color: var(--fl-border-strong); box-shadow: var(--fl-shadow-sm); }
.fl-btn-secondary:hover { background: var(--fl-surface-alt); color: var(--fl-text); }
.fl-btn-ghost     { background: transparent; color: var(--fl-text-muted); }
.fl-btn-ghost:hover { background: var(--fl-surface-alt); color: var(--fl-text); }
.fl-btn-danger    { background: var(--fl-danger); color: var(--fl-text-invert); }
.fl-btn-danger:hover { background: var(--fl-danger-ink); color: var(--fl-text-invert); }
.fl-btn-sm        { padding: 5px 10px; font-size: 12.5px; }
.fl-btn:disabled, .fl-btn.is-disabled { opacity: .5; cursor: not-allowed; }

/* --- 8. Table ----------------------------------------------------------- */
.fl-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.fl-table thead th {
  position: sticky; top: 0; z-index: 1;
  text-align: left; padding: 10px var(--fl-s4);
  font-size: 11.5px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--fl-text-subtle);
  background: var(--fl-surface-alt);
  border-bottom: 1px solid var(--fl-border);
  white-space: nowrap;
}
.fl-table tbody td {
  padding: 12px var(--fl-s4);
  border-bottom: 1px solid var(--fl-border);
  vertical-align: middle;
}
.fl-table tbody tr:last-child td { border-bottom: none; }
.fl-table tbody tr:hover { background: var(--fl-surface-alt); }
.fl-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.fl-table-wrap { overflow-x: auto; }
.fl-cell-person { display: flex; align-items: center; gap: var(--fl-s3); min-width: 190px; }
.fl-cell-person .name { font-weight: 550; }

/* --- 9. Progress bar ---------------------------------------------------- */
.fl-bar { height: 6px; border-radius: var(--fl-r-pill); background: var(--fl-neutral-soft); overflow: hidden; }
.fl-bar > span { display: block; height: 100%; border-radius: inherit; background: var(--fl-accent); }
.fl-bar.ok     > span { background: var(--fl-ok); }
.fl-bar.warn   > span { background: var(--fl-warn); }
.fl-bar.danger > span { background: var(--fl-danger); }
.fl-bar-inline { display: flex; align-items: center; gap: var(--fl-s3); }
.fl-bar-inline .fl-bar { flex: 1; min-width: 70px; }
.fl-bar-inline .fl-num { min-width: 34px; text-align: right; }

/* --- 10. AI insight card ------------------------------------------------ */
.fl-ai {
  border: 1px solid var(--fl-border);
  border-radius: var(--fl-r);
  background: linear-gradient(180deg, var(--fl-accent-soft) 0%, var(--fl-surface) 68px);
  box-shadow: var(--fl-shadow-sm);
  overflow: hidden;
}
.fl-ai-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--fl-s3); flex-wrap: wrap;
  padding: var(--fl-s4) var(--fl-s5);
}
.fl-ai-title { display: flex; align-items: center; gap: var(--fl-s3); font-weight: 600; font-size: 14px; }
.fl-ai-chip {
  display: inline-flex; align-items: center; padding: 2px 8px;
  border-radius: var(--fl-r-sm); background: var(--fl-accent); color: var(--fl-text-invert);
  font-size: 11px; font-weight: 700; letter-spacing: .06em;
}
.fl-ai-tools { display: flex; align-items: center; gap: var(--fl-s3); }
.fl-ai-body { padding: 0 var(--fl-s5) var(--fl-s5); }
.fl-ai-summary { font-size: 14px; line-height: 1.6; margin-bottom: var(--fl-s5); max-width: 78ch; }
.fl-ai-cols { display: grid; gap: var(--fl-s5); grid-template-columns: repeat(3, minmax(0,1fr)); }
.fl-ai-section { margin-bottom: 0; }
.fl-ai-list { list-style: none; padding: 0; margin: var(--fl-s2) 0 0; }
.fl-ai-list li {
  position: relative; padding-left: 18px; margin-bottom: 6px;
  font-size: 13.5px; color: var(--fl-text);
}
.fl-ai-list li::before {
  content: ''; position: absolute; left: 4px; top: 8px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--fl-text-subtle);
}
.fl-ai-list.ok li::before     { background: var(--fl-ok); }
.fl-ai-list.warn li::before   { background: var(--fl-warn); }
.fl-ai-list.action li::before { background: var(--fl-accent); }
.fl-ai-caveat {
  margin-top: var(--fl-s5); padding: var(--fl-s3) var(--fl-s4);
  background: var(--fl-surface-alt); border: 1px solid var(--fl-border);
  border-radius: var(--fl-r-sm); font-size: 12.5px; color: var(--fl-text-muted);
}
.fl-ai-caveat .fl-label { margin-bottom: var(--fl-s1); }
.fl-ai-stamp { font-size: 12px; color: var(--fl-text-subtle); }

/* --- 11. Exception / alert row ----------------------------------------- */
.fl-alert {
  display: flex; align-items: flex-start; gap: var(--fl-s4);
  padding: var(--fl-s4) var(--fl-s5);
  border-bottom: 1px solid var(--fl-border);
}
.fl-alert:last-child { border-bottom: none; }
.fl-alert:hover { background: var(--fl-surface-alt); }
.fl-alert-mark { width: 3px; align-self: stretch; border-radius: 2px; background: var(--fl-neutral); }
.fl-alert.sev-high .fl-alert-mark { background: var(--fl-danger); }
.fl-alert.sev-med  .fl-alert-mark { background: var(--fl-warn); }
.fl-alert.sev-low  .fl-alert-mark { background: var(--fl-neutral); }
.fl-alert-body { flex: 1; min-width: 0; }
.fl-alert-text { font-size: 13.5px; font-weight: 500; margin-bottom: 3px; }
.fl-alert-meta { font-size: 12.5px; color: var(--fl-text-muted); }
.fl-alert-action { flex-shrink: 0; }

/* --- 12. Heatmap -------------------------------------------------------- */
.fl-heat-row { display: flex; align-items: center; gap: var(--fl-s4); flex-wrap: wrap; }
.fl-heat-name { width: 150px; flex-shrink: 0; font-size: 13.5px; font-weight: 550; }
.fl-heat { display: flex; gap: 3px; }
.fl-heat-cell {
  width: 22px; height: 22px; border-radius: 4px;
  background: var(--fl-heat-0);
}
.fl-heat-cell.l1 { background: var(--fl-heat-1); }
.fl-heat-cell.l2 { background: var(--fl-heat-2); }
.fl-heat-cell.l3 { background: var(--fl-heat-3); }
.fl-heat-cell.l4 { background: var(--fl-heat-4); }
.fl-heat-cell.miss   { background: var(--fl-danger-soft); border: 1px solid var(--fl-danger-line); }
.fl-heat-cell.future { background: transparent; border: 1px dashed var(--fl-border-strong); }
.fl-heat-legend { display: flex; align-items: center; gap: var(--fl-s4); flex-wrap: wrap;
                  font-size: 12.5px; color: var(--fl-text-muted); }
.fl-heat-key { display: flex; align-items: center; gap: 6px; }
.fl-heat-key .fl-heat-cell { width: 14px; height: 14px; border-radius: 3px; }

/* --- 13. Forms ---------------------------------------------------------- */
.fl-field { margin-bottom: var(--fl-s4); }
.fl-field:last-child { margin-bottom: 0; }
.fl-field label { display:block; font-size: 13px; font-weight: 550; margin-bottom: 5px; }
.fl-input, .fl-select, .fl-textarea {
  width: 100%; padding: 8px var(--fl-s3);
  border: 1px solid var(--fl-border-strong); border-radius: var(--fl-r-sm);
  background: var(--fl-surface); font-size: 13.5px; font-family: inherit; color: var(--fl-text);
}
.fl-input::placeholder, .fl-textarea::placeholder { color: var(--fl-text-subtle); }
.fl-input:focus, .fl-select:focus, .fl-textarea:focus,
.fl-input.is-focus, .fl-select.is-focus, .fl-textarea.is-focus {
  outline: none; border-color: var(--fl-accent);
  box-shadow: var(--fl-ring);
}
.fl-textarea { min-height: 140px; resize: vertical; font-family: var(--fl-font-mono); font-size: 13px; }
.fl-hint { font-size: 12.5px; color: var(--fl-text-subtle); margin-top: 4px; }

/* --- 14. Empty state ---------------------------------------------------- */
.fl-empty { padding: var(--fl-s10) var(--fl-s5); text-align: center; color: var(--fl-text-muted); }
.fl-empty h4 { color: var(--fl-text); margin-bottom: 4px; }
.fl-empty p { max-width: 44ch; margin: 0 auto var(--fl-s5); font-size: 13.5px; }

/* --- 15. Utilities ------------------------------------------------------ */
.fl-grid    { display: grid; gap: var(--fl-s4); }
.fl-grid-2  { grid-template-columns: repeat(2, minmax(0,1fr)); }
.fl-grid-3  { grid-template-columns: repeat(3, minmax(0,1fr)); }
.fl-grid-4  { grid-template-columns: repeat(4, minmax(0,1fr)); }
.fl-row     { display: flex; align-items: center; gap: var(--fl-s3); }
.fl-row-wrap { display: flex; align-items: center; gap: var(--fl-s3); flex-wrap: wrap; }
.fl-row-between { display: flex; align-items: center; justify-content: space-between; gap: var(--fl-s3); }
.fl-stack   { display: flex; flex-direction: column; gap: var(--fl-s4); }
.fl-divider { height: 1px; background: var(--fl-border); margin: var(--fl-s4) 0; }
.fl-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: var(--fl-accent-soft); color: var(--fl-accent);
  display: grid; place-items: center; font-size: 12px; font-weight: 650; flex-shrink: 0;
}
.fl-avatar.sm { width: 24px; height: 24px; font-size: 10.5px; }
.fl-avatar.lg { width: 40px; height: 40px; font-size: 14px; }
.fl-avatar.muted { background: var(--fl-neutral-soft); color: var(--fl-neutral-ink); }

/* Icons — Bootstrap Icons, loaded from the CDN in fragments/layout.html.
   Sized and coloured entirely by the text the icon sits in: 1.1em keeps the glyph
   in proportion to its label at any font size, `color: inherit` means currentColor
   carries nav active/hover and badge colours through with no per-state rules, and
   the negative vertical-align seats the glyph on the label's optical baseline
   (flex parents such as .fl-nav-item centre it instead). Every icon in the markup
   also carries aria-hidden="true" — the label beside it is the accessible name. */
.fl-icon {
  display: inline-block;
  width: 1em; height: 1em;
  flex-shrink: 0;
  font-size: 1.1em;
  line-height: 1;
  color: inherit;
  vertical-align: -0.125em;
}

/* --- 16. Responsive ----------------------------------------------------- */
@media (max-width: 1100px) {
  .fl-grid-4 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .fl-grid-3 { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .fl-ai-cols { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .fl-sidebar { display: none; }
  .fl-grid-4, .fl-grid-3, .fl-grid-2 { grid-template-columns: 1fr; }
  .fl-page { padding: var(--fl-s4); }
  .fl-heat-name { width: auto; }
}

/* --- 17. Spinner -------------------------------------------------------- */
/*
  Added by feature 03, under the escape hatch in DESIGN.md rule 2: a new numbered
  section, tokens only, no literal colours or spacing. The design system had no
  busy indicator and AI-1 takes 7-11 seconds -- a button that sits there looking
  idle for eleven seconds gets clicked again on stage.

  Sized in em so it matches whatever text it sits next to, and marked
  aria-hidden at the call site: the button's own label changes to "Generating...",
  which is what a screen reader should read.
*/
.fl-spinner {
  display: inline-block; width: 1em; height: 1em; vertical-align: -0.125em;
  border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%;
  animation: fl-spin 0.7s linear infinite;
}
@keyframes fl-spin { to { transform: rotate(360deg); } }
/* Respect the reader's motion preference: still visibly busy, just not rotating. */
@media (prefers-reduced-motion: reduce) {
  .fl-spinner { animation-duration: 2.4s; }
}

/* --- 18. Coverage chart ------------------------------------------------- */
/*
  Added for the "Coverage by faculty" chart on /hod and "Coverage by department" on /dean,
  under DESIGN.md rule 2. No charting library: bars are divs with a percentage height
  inside a fixed-height track, and the gridlines and the dashed target line are positioned
  over the same height. Markup in fragments/coverage-chart.html.

  The top padding is room for the value label above a 100% bar; the left padding is the
  y-axis gutter the tick labels sit in. The grid and the target line are offset by exactly
  those two paddings so they share the tracks' coordinate space.

  Bar colours are the status tokens and nothing else -- pace, not decoration.
*/
.fl-chart {
  --fl-chart-h: 220px;
  position: relative;
  padding: var(--fl-s6) 0 0 var(--fl-s10);
}
/* Two overlays on the tracks' box. The gridlines paint below the bars (earlier in the DOM,
   no z-index); the target line paints above the bars (z-index 2); the value labels paint
   above the line (z-index 3, on a surface ground) so a bar ending near the target still
   reads. The columns deliberately create no stacking context, or the labels could not
   rise above the overlay. */
.fl-chart-grid,
.fl-chart-overlay {
  position: absolute; top: var(--fl-s6); left: var(--fl-s10); right: 0;
  height: var(--fl-chart-h);
  pointer-events: none;
}
.fl-chart-overlay { z-index: 2; }
.fl-chart-gridline { position: absolute; left: 0; right: 0; border-top: 1px solid var(--fl-border); }
.fl-chart-gridline > span {
  position: absolute; right: 100%; top: 0; transform: translateY(-50%);
  padding-right: var(--fl-s2);
  font-size: 11.5px; color: var(--fl-text-subtle); font-variant-numeric: tabular-nums;
}
.fl-chart-target { position: absolute; left: 0; right: 0; border-top: 2px dashed var(--fl-text-muted); }
.fl-chart-target-label {
  position: absolute; left: var(--fl-s2); bottom: 100%; margin-bottom: var(--fl-s1);
  padding: 1px var(--fl-s2);
  background: var(--fl-surface); border: 1px solid var(--fl-border-strong);
  border-radius: var(--fl-r-sm);
  font-size: 11.5px; font-weight: 600; color: var(--fl-text);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}

.fl-chart-cols { display: flex; gap: var(--fl-s3); }
.fl-chart-col {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: var(--fl-s1);
  color: var(--fl-text-muted); border-radius: var(--fl-r-sm);
}
.fl-chart-col:hover { text-decoration: none; color: var(--fl-text); }
.fl-chart-col:focus-visible { outline: none; box-shadow: var(--fl-ring); }
.fl-chart-track {
  position: relative; width: 100%; height: var(--fl-chart-h);
  display: flex; align-items: flex-end; justify-content: center;
  margin-bottom: var(--fl-s2);
}
.fl-chart-bar {
  position: relative; width: 100%; max-width: 56px; min-height: 2px;
  border-radius: var(--fl-r-sm) var(--fl-r-sm) 0 0;
  background: var(--fl-neutral);
  transition: opacity .15s;
}
.fl-chart-bar.ok     { background: var(--fl-ok); }
.fl-chart-bar.warn   { background: var(--fl-warn); }
.fl-chart-bar.danger { background: var(--fl-danger); }
.fl-chart-col:hover .fl-chart-bar { opacity: .8; }
.fl-chart-value {
  position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); z-index: 3;
  margin-bottom: 2px; padding: 0 var(--fl-s1);
  background: var(--fl-surface); border-radius: var(--fl-r-sm); line-height: 1.4;
  font-size: 12px; font-weight: 600; color: var(--fl-text);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Full names, rotated 45 degrees about the label's top-right corner, which is pinned under
   the column's centre -- so each name reads upward to its own bar. The band is the rotated
   label's vertical extent, 0.71 x (width + line height), with width estimated from the
   longest label's character count (--fl-chart-chars, set from the DTO) at 0.6em a
   character. Sized in em so it follows the label's font size. */
.fl-chart-band {
  position: relative; display: block; width: 100%;
  font-size: 12.5px; line-height: 1.4;
  height: calc((var(--fl-chart-chars, 12) * 0.6em + 1.4em) * 0.71);
}
.fl-chart-name {
  position: absolute; top: 0; right: 50%;
  transform-origin: 100% 0; transform: rotate(-45deg);
  white-space: nowrap; font-weight: 550;
}

/* --- 19. Busy hourglass ------------------------------------------------- */
/*
  The AI card's Regenerate button while a generation is in flight. Flips half a turn,
  holds, flips again: 1.5s per loop, ending where it started so the loop has no snap.
*/
.fl-hourglass { animation: fl-hourglass 1.5s ease-in-out infinite; }
@keyframes fl-hourglass {
  0%   { transform: rotate(0deg); }
  25%  { transform: rotate(180deg); }
  50%  { transform: rotate(180deg); }
  75%  { transform: rotate(360deg); }
  100% { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .fl-hourglass { animation: none; }
}
