/* =====================================================================
   EduNest LMS — the client's four-colour scheme, on Bootstrap 5.3

   Light-first. The reference the client supplied is a light interface: white
   panels on a very light grey page, with the colour carried by four brights —
   magenta, indigo, cyan and orange — that run across the dashboard's stat
   cards in that order. Indigo is the one that also does the ordinary work of
   a primary colour: buttons, links, the active page.

   Flat throughout; there is not a gradient in this file. The dark palette
   further down is kept so the toggle still works, but light is what loads.
   Themes are switched with [data-bs-theme] on <html>.
   ===================================================================== */

/* -------------------------------------------------------------- Fonts */
/* Two voices: Space Grotesk says the headings, Inter says everything else.
   Both are served from this site, so the content security policy needs no
   exception and the page never waits on somebody else's server. */
@font-face {
  font-family: 'SpaceGrotesk';
  font-style: normal;
  font-display: swap;
  font-weight: 300 700;
  src: url('../vendor/fonts/space-grotesk-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
                 U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'InterVariable';
  font-style: normal;
  font-display: swap;
  font-weight: 100 900;
  src: url('../vendor/fonts/inter-latin-wght-normal.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
                 U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ------------------------------------------------------- Tokens: dark */
/*
 * The night version of the same scheme.
 *
 * The four brights are the constant — magenta, indigo, cyan and orange are
 * what the client's design is recognisable by, and they survive on a dark
 * ground almost unchanged. What has to move is indigo as *text*: #3B2FE0 on
 * near-black is 2.1:1, so it lifts to #8B84FF. Everything below follows the
 * same fill/text pairing.
 */
:root,
[data-bs-theme="dark"] {
  --lms-primary: #4F46E5;          /* indigo — anything actionable */
  --lms-primary-rgb: 79, 70, 229;
  --lms-primary-hover: #6366F1;
  --lms-accent: #00AEEF;           /* cyan — links, progress, success */
  --lms-accent-rgb: 0, 174, 239;
  --lms-accent-soft: rgba(79, 70, 229, .22);
  --lms-on-primary: #FFFFFF;
  --lms-primary-text: #8B84FF;

  --lms-hot: #FF3D8F;              /* magenta — money, urgency, failure */
  --lms-hot-rgb: 255, 61, 143;
  --lms-hot-soft: rgba(255, 61, 143, .16);

  /* The four the stat tiles run on, in the order the reference uses them.
     The tints are opaque rather than translucent: a tile sits on the page in
     some places and inside a panel in others, and a translucent tint gives a
     different colour in each, which is impossible to check and looked it. */
  --lms-c1: #FF3D8F;   --lms-c1-tint: #2A1424;
  --lms-c2: #6366F1;   --lms-c2-tint: #1A1B34;
  --lms-c3: #00AEEF;   --lms-c3-tint: #0F2330;
  --lms-c4: #FB7A32;   --lms-c4-tint: #2B1B12;
  --lms-c5: #94A3B8;   --lms-c5-tint: #1A1E2A;
  --lms-on-c: #0B0D14;

  --lms-canvas: #0B0D14;
  --lms-surface: #141824;
  --lms-surface-2: #1C2130;
  --lms-border: #2A3044;
  --lms-border-strong: #414A63;
  --lms-text: #F4F6FB;
  --lms-text-rgb: 244, 246, 251;
  --lms-muted: #99A2B8;

  --lms-positive: var(--lms-accent);
  --lms-attention: var(--lms-primary-text);
  --lms-negative: var(--lms-hot);

  /* Corners tighten up: a bold face and a soft radius pull against each
     other, and the type is doing the talking now. */
  --lms-radius: .5rem;

  --bs-body-font-family: 'InterVariable', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --lms-display-font: 'SpaceGrotesk', 'InterVariable', system-ui, sans-serif;

  --bs-body-bg: var(--lms-canvas);
  --bs-body-color: var(--lms-text);
  /* Bootstrap builds .text-body from the -rgb pair; without it the card
     titles fall back to its stock #212529 rather than our own text colour. */
  --bs-body-color-rgb: var(--lms-text-rgb);
  /* List group actions inherit this; Bootstrap's stock value is pure black. */
  --bs-emphasis-color: var(--lms-text);
  --bs-emphasis-color-rgb: var(--lms-text-rgb);
  --bs-secondary-color: var(--lms-muted);
  --bs-border-color: var(--lms-border);
  --bs-link-color: var(--lms-accent);
  --bs-link-hover-color: var(--lms-accent);
  --bs-primary: var(--lms-primary);
  --bs-primary-rgb: var(--lms-primary-rgb);
  --bs-tertiary-bg: var(--lms-surface-2);
}

/* ------------------------------------------------------ Tokens: light */
/*
 * The one the client asked for, and the one that loads.
 *
 * White panels on a very light grey page, the way the reference screenshots
 * are built — the grey is what makes a white card read as a card without
 * needing a shadow under it. Indigo does the primary work; magenta, cyan and
 * orange join it on the stat cards and in the charts.
 *
 * As always the fill and the text value of a colour are not the same. Cyan
 * fills at #00AEEF and takes white, but as text on white it is 2.4:1, so
 * anything written in cyan uses the darker #0E7490. The four --lms-cN below
 * are fills only; they are never used for text.
 */
[data-bs-theme="light"] {
  --lms-primary: #3B2FE0;          /* indigo — anything actionable */
  --lms-primary-rgb: 59, 47, 224;
  --lms-primary-hover: #2E23BE;
  --lms-accent: #0E7490;           /* cyan, darkened so it can be read */
  --lms-accent-rgb: 14, 116, 144;
  --lms-accent-soft: rgba(59, 47, 224, .09);
  --lms-on-primary: #FFFFFF;
  --lms-primary-text: #3B2FE0;

  --lms-hot: #D6006C;              /* magenta — money, urgency, failure */
  --lms-hot-rgb: 214, 0, 108;
  --lms-hot-soft: rgba(214, 0, 108, .08);

  /* The four the stat tiles run on, in the order the reference uses them:
     magenta, indigo, cyan, orange. Each is a fill carrying a white icon, and
     each has a tint pale enough to sit under body text.

     Cyan and orange are a shade deeper than the reference's own. White on
     #00AEEF is 2.53:1 and on #F96A21 is 2.95:1 — both under the 3:1 a
     non-text graphic needs, so the icon on those two bars was the weakest
     thing on the dashboard. A step down the same hue puts them at 3.5:1 and
     3.7:1; side by side with the originals the difference is barely visible,
     and the icons stop dissolving into the bar. */
  --lms-c1: #FF0080;   --lms-c1-tint: #FFF0F7;
  --lms-c2: #3B2FE0;   --lms-c2-tint: #F0EFFE;
  --lms-c3: #0192C6;   --lms-c3-tint: #EAF7FE;
  --lms-c4: #E05A08;   --lms-c4-tint: #FFF3EC;
  --lms-c5: #64748B;   --lms-c5-tint: #F1F5F9;
  --lms-on-c: #FFFFFF;

  --lms-canvas: #F6F7FB;
  --lms-surface: #FFFFFF;
  --lms-surface-2: #F1F3F9;
  --lms-border: #E3E6EF;
  --lms-border-strong: #C3C8D6;
  --lms-text: #14162B;
  --lms-text-rgb: 20, 22, 43;
  --lms-muted: #5A6178;

  --lms-positive: var(--lms-accent);
  --lms-attention: var(--lms-primary-text);
  --lms-negative: var(--lms-hot);

  --bs-body-bg: var(--lms-canvas);
  --bs-body-color: var(--lms-text);
  --bs-body-color-rgb: var(--lms-text-rgb);
  --bs-emphasis-color: var(--lms-text);
  --bs-emphasis-color-rgb: var(--lms-text-rgb);
  --bs-secondary-color: var(--lms-muted);
  --bs-border-color: var(--lms-border);
  --bs-link-color: var(--lms-accent);
  --bs-link-hover-color: var(--lms-accent);
  --bs-primary: var(--lms-primary);
  --bs-primary-rgb: var(--lms-primary-rgb);
  --bs-tertiary-bg: var(--lms-surface-2);
}

/* --------------------------------------------------------------- Base */
body {
  font-family: var(--bs-body-font-family);
  background: var(--bs-body-bg);
  color: var(--bs-body-color);
  -webkit-font-smoothing: antialiased;
}

/* ---- Type scale -------------------------------------------------------
   Six steps, all in rem. Bootstrap sizes .small and .badge in em, which
   compounds every time one nests inside another — that alone was producing
   10.5px, 10.88px, 11.52px, 12.48px and 13.12px across the site. Fixing the
   two units collapses the whole page down to this scale.

   Headings are set in Space Grotesk and now run considerably larger and
   heavier. With no gradients and no shadows left in the file, size and weight
   are what the design has to make an impression with — so the hero lands at
   72px rather than 52, and every heading goes to 800 with the tracking pulled
   in to keep the words reading as one block rather than drifting apart.

   Body text does not follow them up. A heading is looked at; a paragraph is
   read, and 17px is where it stays comfortable. */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6,
.display-5, .display-6 {
  font-family: var(--lms-display-font);
  letter-spacing: -.032em;
  font-weight: 800;
  line-height: 1.1;
}
.display-5, .display-6 { letter-spacing: -.045em; font-weight: 800; }

/*
 * The hero scales with the viewport rather than sitting at one size.
 *
 * A flat 72px looked right at 1400 and broke everywhere else: the headline
 * sits in a half-width column, "Master a new skill —" needs 9.7 times the
 * font size to stay on one line, and at 1200 that is 698px in a 582px
 * column — so the em dash dropped onto a line of its own. 4.8vw is the
 * largest slope that keeps it whole at every width from 992 up, and the
 * ceiling stops it running away on a very wide monitor.
 */
.display-5 {
  font-size: clamp(2.375rem, 4.8vw, 4.5rem);
  line-height: .98;
  /* Spread the words evenly over however many lines they need. Without it a
     phone left the em dash stranded on a line by itself, because "Master a
     new skill" alone is wider than a 390px screen at this size. */
  text-wrap: balance;
}
.display-6 { font-size: 2.75rem; line-height: 1.05; }  /* 44 */
h1, .h1 { font-size: 2.75rem; }     /* 44 */
h2, .h2 { font-size: 2.125rem; }    /* 34 */
h3, .h3 { font-size: 1.5rem; }      /* 24 */
h4, .h4 { font-size: 1.3125rem; }   /* 21 */
h5, .h5 { font-size: 1.125rem; }    /* 18 */
/* h6 stays sentence case. It is the tag the course cards use for their
   titles, and setting it in capitals turned every course name in the
   catalogue into shouting. */
h6, .h6 { font-size: .9375rem; }

body { font-size: 1.0625rem; }         /* 17 — the reading size */
.lead { font-size: 1.1875rem; font-weight: 400; }
small, .small { font-size: .875rem; }  /* 14 — never relative, never compounds */
.badge { font-size: .75rem; }          /* 12 */
.fs-4 { font-size: 1.3125rem !important; }
.fs-3 { font-size: 1.625rem !important; }

/* The rest step down at breakpoints. Only the hero needs to scale smoothly,
   because only the hero is big enough for one wrapped word to look wrong. */
@media (max-width: 991.98px) {
  .display-6 { font-size: 2.25rem; }
  h1, .h1 { font-size: 2.25rem; }
  h2, .h2 { font-size: 1.75rem; }
}
@media (max-width: 767.98px) {
  .display-6 { font-size: 1.875rem; }
  h1, .h1 { font-size: 1.875rem; }
  h2, .h2 { font-size: 1.5rem; }
  h3, .h3 { font-size: 1.25rem; }
  body { font-size: 1rem; }
  .lead { font-size: 1.0625rem; }
}

/* Prices, counts and table figures line up when the digits are one width. */
.kpi-value, .price, .table td, .table th, .badge { font-variant-numeric: tabular-nums; }

.bg-body-tertiary { background-color: var(--lms-surface-2) !important; }
.text-secondary { color: var(--lms-muted) !important; }

/* Every semantic utility, in both its plain and -emphasis form, resolves to
   the three quiet state tokens. Nothing in a view needs to know this. */
.text-success, .text-success-emphasis { color: var(--lms-positive) !important; }
.text-warning, .text-warning-emphasis { color: var(--lms-attention) !important; }
.text-danger,  .text-danger-emphasis  { color: var(--lms-negative) !important; }
.text-info,    .text-info-emphasis    { color: var(--lms-muted) !important; }
/* Primary now means violet, so the icons marked .text-primary throughout the
   views become the accent colour rather than another shade of the text. */
.text-primary, .text-primary-emphasis { color: var(--lms-primary-text) !important; }
/* Bootstrap's tertiary text is another stock grey; fold it into the muted token. */
.text-body-tertiary, .text-body-secondary { color: var(--lms-muted) !important; }
.link-primary, a { color: var(--lms-accent); }
a { text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--lms-primary); }

:focus-visible { outline: 2px solid var(--lms-accent); outline-offset: 2px; border-radius: 4px; }
::selection { background: var(--lms-accent-soft); color: var(--lms-text); }

/* Structure comes from raised panels and one hairline, not from drop shadows.
   The only glow in the file is the hero's, and it is a background, not a
   shadow — no view should reach for Bootstrap's .shadow-* either. */

/* ------------------------------------------------------------ Buttons */
/* Heavier and tighter, to match the headings. Outlines are two pixels rather
   than one — at one pixel an outline button beside a filled amber one looked
   like an afterthought instead of the second choice. */
.btn {
  --bs-btn-border-radius: .4rem;
  --bs-btn-font-weight: 700;
  --bs-btn-border-width: 2px;
  letter-spacing: -.01em;
  transition: background-color .14s ease, border-color .14s ease, color .14s ease;
}
.btn-primary {
  --bs-btn-bg: var(--lms-primary);
  --bs-btn-border-color: var(--lms-primary);
  --bs-btn-hover-bg: var(--lms-primary-hover);
  --bs-btn-hover-border-color: var(--lms-primary-hover);
  --bs-btn-active-bg: var(--lms-primary-hover);
  --bs-btn-disabled-bg: var(--lms-primary);
  --bs-btn-disabled-border-color: var(--lms-primary);
  /* Amber is a light colour in both themes, so its label is ink in both.
     White here would fail contrast badly — white on #FFB020 is 1.8:1. */
  --bs-btn-color: var(--lms-on-primary);
  --bs-btn-hover-color: var(--lms-on-primary);
  --bs-btn-active-color: var(--lms-on-primary);
  --bs-btn-disabled-color: var(--lms-on-primary);
}
/* Outline-primary carries the accent; outline-secondary stays neutral, so the
   two are finally telling the reader different things. */
.btn-outline-primary {
  --bs-btn-color: var(--lms-primary-text);
  --bs-btn-border-color: var(--lms-primary);
  --bs-btn-hover-bg: var(--lms-primary);
  --bs-btn-hover-border-color: var(--lms-primary);
  --bs-btn-hover-color: var(--lms-on-primary);
  --bs-btn-active-bg: var(--lms-primary);
  --bs-btn-active-border-color: var(--lms-primary);
  --bs-btn-active-color: var(--lms-on-primary);
}
.btn-outline-secondary {
  --bs-btn-color: var(--lms-text);
  --bs-btn-border-color: var(--lms-border-strong);
  --bs-btn-hover-bg: var(--lms-surface-2);
  --bs-btn-hover-border-color: var(--lms-border-strong);
  --bs-btn-hover-color: var(--lms-text);
  --bs-btn-active-bg: var(--lms-surface-2);
  --bs-btn-active-border-color: var(--lms-border-strong);
  --bs-btn-active-color: var(--lms-text);
}
/*
 * Teal and coral need the opposite label to amber, and it flips with the
 * theme: at night they are bright and want an ink label, in daylight they are
 * dark and want a white one. --lms-canvas is exactly that value in each theme
 * — near-black in dark, white in light — so it does the job without a pair of
 * extra tokens. Ink on the daylight coral would be 3.1:1, which is why this
 * cannot just reuse --lms-on-primary the way the amber buttons do.
 */
.btn-outline-success {
  --bs-btn-color: var(--lms-positive);
  --bs-btn-border-color: var(--lms-positive);
  --bs-btn-hover-bg: var(--lms-positive);
  --bs-btn-hover-border-color: var(--lms-positive);
  --bs-btn-hover-color: var(--lms-canvas);
}
.btn-outline-danger {
  --bs-btn-color: var(--lms-negative);
  --bs-btn-border-color: var(--lms-negative);
  --bs-btn-hover-bg: var(--lms-negative);
  --bs-btn-hover-border-color: var(--lms-negative);
  --bs-btn-hover-color: var(--lms-canvas);
}
.btn-success {
  --bs-btn-bg: var(--lms-positive); --bs-btn-border-color: var(--lms-positive);
  --bs-btn-color: var(--lms-canvas);
  --bs-btn-hover-bg: var(--lms-positive); --bs-btn-hover-border-color: var(--lms-positive);
  --bs-btn-hover-color: var(--lms-canvas);
  --bs-btn-active-color: var(--lms-canvas); --bs-btn-disabled-color: var(--lms-canvas);
}
.btn-danger {
  --bs-btn-bg: var(--lms-negative); --bs-btn-border-color: var(--lms-negative);
  --bs-btn-color: var(--lms-canvas);
  --bs-btn-hover-bg: var(--lms-negative); --bs-btn-hover-border-color: var(--lms-negative);
  --bs-btn-hover-color: var(--lms-canvas);
  --bs-btn-active-color: var(--lms-canvas); --bs-btn-disabled-color: var(--lms-canvas);
}
.bg-primary { background-color: var(--lms-primary) !important; }
.badge.bg-primary, .bg-primary { color: var(--lms-on-primary) !important; }
.btn-light {
  --bs-btn-bg: var(--lms-surface-2);
  --bs-btn-border-color: var(--lms-border-strong);
  --bs-btn-color: var(--lms-text);
  --bs-btn-hover-bg: var(--lms-border);
  --bs-btn-hover-color: var(--lms-text);
}

/* --------------------------------------------------------------- Cards
   With no shadows and no gradients, a card is defined by its edge, so the
   edge is drawn properly rather than hinted at. */
.card {
  --bs-card-bg: var(--lms-surface);
  --bs-card-border-color: var(--lms-border-strong);
  --bs-card-border-radius: var(--lms-radius);
  --bs-card-inner-border-radius: calc(var(--lms-radius) - 1px);
  border: 1px solid var(--lms-border-strong);
}
/* The header sits inside the card's own border rather than being boxed off
   again, so it carries no background and no rule of its own. */
.card-header { background: transparent; border-bottom: 0; }
.list-group { --bs-list-group-bg: transparent; --bs-list-group-border-color: var(--lms-border); }
.list-group-item-action:hover { background: var(--lms-surface-2); }
.list-group-item.active {
  background: var(--lms-accent-soft); border-color: var(--lms-border);
  color: var(--lms-text); font-weight: 600;
  box-shadow: inset 3px 0 0 var(--lms-primary);
}

/* ------------------------------------------------------------ Navbars */
.site-navbar {
  background: var(--lms-surface);
  border-bottom: 1px solid var(--lms-border);
}
.navbar .nav-link { font-weight: 500; color: var(--lms-muted); padding-inline: .7rem; }
.navbar .nav-link:hover, .navbar .nav-link.active { color: var(--lms-text); }
.navbar-brand {
  font-family: var(--lms-display-font);
  letter-spacing: -.03em; font-weight: 700; color: var(--lms-text) !important;
}
/* The mortarboard in the wordmark is the one place the accent is decorative. */
.navbar-brand .bi { color: var(--lms-primary-text); }
.dropdown-menu {
  background: var(--lms-surface);
  border-color: var(--lms-border); border-radius: var(--lms-radius);
}
.dropdown-item:hover, .dropdown-item:focus { background: var(--lms-surface-2); color: var(--lms-text); }

.theme-toggle {
  border: 1px solid var(--lms-border); background: transparent; color: inherit;
  width: 32px; height: 32px; border-radius: .5rem;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s ease;
}
.theme-toggle:hover { background: var(--lms-surface-2); }
html[data-bs-theme="light"] .theme-toggle .icon-dark,
html[data-bs-theme="dark"] .theme-toggle .icon-light { display: none; }

/* ------------------------------------------------------------ Avatars */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--lms-surface-2); border: 1px solid var(--lms-border);
  color: var(--lms-text); font-weight: 600; font-size: .8rem; flex: 0 0 auto;
}
.avatar-sm { width: 30px; height: 30px; font-size: .75rem; }
.avatar-lg { width: 60px; height: 60px; font-size: 1.1rem; }
.avatar-xl { width: 88px; height: 88px; font-size: 1.5rem; }

/* ---------------------------------------------------- Hero / page head */
/*
 * Flat, and separated from the page by a rule rather than a glow.
 *
 * This used to carry two soft pools of colour behind the headline. They were
 * the only gradients on the site and they are gone: the hero is one flat
 * surface, and what marks it out now is the four-pixel amber rule along the
 * bottom — a hard edge instead of a fade. On a phone that edge survives being
 * looked at in sunlight, which the pools never did.
 */
.hero {
  position: relative;
  isolation: isolate;
  /* A pale indigo rather than plain white. The first screenful was the most
     colourless part of the whole site — white panel on a near-white page,
     with a single button on it — and it is the screen every visitor sees
     first. The tint is the same one the indigo stat tile uses, so this is the
     palette's own colour rather than a new one, and it is still flat. */
  background: var(--lms-c2-tint);
  border-bottom: 4px solid var(--lms-primary);
  color: var(--lms-text);
}
.hero .text-secondary, .hero .lead { color: var(--lms-muted) !important; }
.hero .breadcrumb-item a, .hero .link-light { color: var(--lms-muted) !important; }
.hero .text-light { color: var(--lms-text) !important; }
.hero .stat-value {
  font-family: var(--lms-display-font);
  font-size: 1.75rem; font-weight: 700; letter-spacing: -.02em;
}
/* The eyebrow above the headline: solid amber with an ink label, square-ish
   rather than a pill, so it reads as a stamp on the page instead of a soft
   chip floating above it. */
.hero-badge {
  display: inline-block;
  border: 0; color: var(--lms-on-primary);
  background: var(--lms-primary);
  border-radius: .3rem; padding: .35rem .75rem; font-size: .75rem; font-weight: 800;
  letter-spacing: .06em; text-transform: uppercase;
}
.hero .btn-light {
  --bs-btn-bg: var(--lms-primary); --bs-btn-color: var(--lms-on-primary);
  --bs-btn-border-color: var(--lms-primary);
  --bs-btn-hover-bg: var(--lms-primary-hover); --bs-btn-hover-color: var(--lms-on-primary);
  --bs-btn-hover-border-color: var(--lms-primary-hover);
}
.hero .btn-outline-light {
  --bs-btn-color: var(--lms-accent); --bs-btn-border-color: var(--lms-accent);
  --bs-btn-hover-bg: var(--lms-accent); --bs-btn-hover-color: var(--lms-canvas);
  --bs-btn-hover-border-color: var(--lms-accent);
}

.page-head {
  background: var(--lms-surface);
  border-bottom: 2px solid var(--lms-border-strong);
}

@media (max-width: 575.98px) {
  .hero .lead { font-size: 1rem; }
  .hero .stat-value { font-size: 1.4rem; }
}

/* -------------------------------------------------------- Course cards */
.course-card { transition: border-color .15s ease, transform .15s ease; }
.course-card:hover {
  border-color: var(--lms-primary-text) !important;
  transform: translateY(-2px);
}
.course-thumb {
  position: relative;
  height: 116px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.6rem;
  background: var(--thumb-bg, var(--lms-surface-2));
  color: var(--thumb-fg, var(--lms-primary-text));
  border-bottom: 1px solid var(--lms-border);
}
/*
 * The placeholder behind a course without its own image.
 *
 * These were all one grey, on the reasoning that five tinted variants made a
 * catalogue look like a paint chart. That was right for a restrained design
 * and wrong for this one: measured, the public home page came out at 1%
 * coloured surface, which is why a client looking at it said there were no
 * colours on the site at all. The four brights were only ever on the
 * dashboards, behind a login.
 *
 * So the thumbnails cycle the same four, by course id — the accents are the
 * design's own, not a new palette, and a grid of cards now carries them.
 * The tint is the fill at low strength and the icon is the fill itself, so
 * both stay in step with the tokens whichever theme is on.
 */
.thumb-0 { --thumb-bg: var(--lms-c1-tint); --thumb-fg: var(--lms-c1); }
.thumb-1 { --thumb-bg: var(--lms-c2-tint); --thumb-fg: var(--lms-c2); }
.thumb-2 { --thumb-bg: var(--lms-c3-tint); --thumb-fg: var(--lms-c3); }
.thumb-3 { --thumb-bg: var(--lms-c4-tint); --thumb-fg: var(--lms-c4); }
.thumb-4 { --thumb-bg: var(--lms-c5-tint); --thumb-fg: var(--lms-c5); }

/*
 * The category tiles on the home page, same idea. The colour is on the icon
 * only — a full tint behind five tiles in a row competes with the course
 * grid underneath them, which is the thing meant to be looked at.
 */
.cat-tile .bi { font-size: 1.6rem; }
.cat-0 .bi { color: var(--lms-c1); }
.cat-1 .bi { color: var(--lms-c2); }
.cat-2 .bi { color: var(--lms-c3); }
.cat-3 .bi { color: var(--lms-c4); }
.cat-4 .bi { color: var(--lms-c5); }
.cat-tile { transition: border-color .15s ease, transform .15s ease; }
.cat-tile:hover { transform: translateY(-2px); }
.cat-0:hover { border-color: var(--lms-c1) !important; }
.cat-1:hover { border-color: var(--lms-c2) !important; }
.cat-2:hover { border-color: var(--lms-c3) !important; }
.cat-3:hover { border-color: var(--lms-c4) !important; }
.cat-4:hover { border-color: var(--lms-c5) !important; }
.bundle-thumb { height: 96px; }
.course-thumb.has-image { padding: 0; background: var(--lms-surface-2); }
.course-thumb.has-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Reserve two lines for every title and clamp anything longer, so a grid of
   cards keeps one height whether a name runs to one line or three. */
.course-card .card-title {
  min-height: calc(2 * 1.3em);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  line-height: 1.3;
}

/* Coral's job on the shop pages: how much is coming off. The saving is the
   only thing on a course card that is neither the title nor the price, so it
   gets the one colour nothing else on that card uses. */
/*
 * Coral's job on the shop pages: how much is coming off. The saving is the
 * only thing on a course card that is neither the title nor the price, so it
 * gets the one colour nothing else on that card uses.
 *
 * The price itself never wraps. "PKR 10,900.00" set large enough to matter is
 * wider than a card column has to spare once the struck-through price and the
 * percentage sit beside it, and the first thing to break was the price
 * splitting after "PKR". Holding it on one line and letting the row wrap
 * underneath keeps the number readable at any card width.
 */
.discount-note { font-size: .8125rem; color: var(--lms-hot); font-weight: 700; white-space: nowrap; }
.price-now {
  font-family: var(--lms-display-font);
  font-size: 1.25rem; font-weight: 800; letter-spacing: -.03em;
  white-space: nowrap;
}
.price-was { font-size: .8125rem; color: var(--lms-muted); white-space: nowrap; }
.course-card .mt-auto.d-flex { flex-wrap: wrap; row-gap: .15rem; }

/* ---------------------------------------------------------- Admin shell */
.admin-body { background: var(--bs-body-bg); }
.admin-topbar { background: var(--lms-surface); border-bottom: 1px solid var(--lms-border); }
.admin-topbar .navbar-brand,
.admin-topbar .dropdown-toggle { color: var(--lms-text) !important; }
.admin-topbar .text-white-50 { color: var(--lms-muted) !important; }
.admin-shell { display: flex; align-items: stretch; min-height: calc(100vh - 56px); }
.admin-sidebar {
  background: var(--lms-surface);
  border-right: 1px solid var(--lms-border);
  width: 232px; flex: 0 0 232px; color: var(--lms-text);
}
.admin-sidebar .offcanvas-body { display: flex; }
.admin-sidebar .nav-link {
  color: var(--lms-muted); border-radius: .4rem;
  padding: .48rem .7rem; margin-bottom: .05rem;
  display: flex; align-items: center; gap: .65rem; font-size: .9rem; font-weight: 450;
  transition: background .12s ease, color .12s ease;
}
.admin-sidebar .nav-link:hover { background: var(--lms-surface-2); color: var(--lms-text); }
/* The active row is the only violet in the sidebar, so it is unmistakable
   which screen you are on without reading a single label. */
.admin-sidebar .nav-link.active {
  background: var(--lms-accent-soft); color: var(--lms-text); font-weight: 600;
  box-shadow: inset 3px 0 0 var(--lms-primary);
}
.admin-sidebar .nav-link.active i { color: var(--lms-primary-text); }
.admin-sidebar .nav-link i { width: 1.05rem; text-align: center; }
.admin-sidebar .nav-section {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--lms-muted); padding: .85rem .7rem .25rem; font-weight: 600;
}
.admin-content { flex: 1 1 auto; padding: 1.5rem; min-width: 0; }

@media (min-width: 992px) {
  /* The sidebar still follows the reader down a long table — that is what it
     is for. It anchors at the very top now rather than under the topbar,
     because the topbar no longer stays there to sit under. */
  .admin-sidebar.offcanvas-lg {
    position: sticky; top: 0; height: 100vh;
    overflow-y: auto;
    background: var(--lms-surface) !important;
  }
}
@media (max-width: 991.98px) {
  .admin-sidebar { width: 250px; }
  .admin-content { padding: 1rem; }
}

/* ----------------------------------------------------------- Stat tiles */
/*
 * The client's shape: a solid colour bar across the top carrying the icon,
 * the figure large underneath, and the whole tile sitting on a pale tint of
 * the same colour.
 *
 * The colour arrives as .stat-c1 … .stat-c5 from kpi_card(), which maps the
 * Bootstrap name each caller passes onto one of five slots. Only the two
 * custom properties change per slot; every rule below reads them, so a tile
 * needs no other per-colour styling.
 *
 * overflow: hidden is what lets the bar take the tile's own top corners
 * rather than needing its own radius — the detail that makes the bar look
 * like part of the tile instead of a stripe laid on top of it. It is also
 * why this is .stat-tile and not .kpi-card: .kpi-card is the plain panel the
 * admin views use for forms and tables, and clipping those would hide the
 * dropdowns inside them.
 */
.stat-tile {
  --stat: var(--lms-c5);
  --stat-tint: var(--lms-c5-tint);
  border: 1px solid var(--lms-border);
  border-radius: var(--lms-radius);
  background: var(--stat-tint);
  overflow: hidden;
  container-type: inline-size;
}
.stat-c1 { --stat: var(--lms-c1); --stat-tint: var(--lms-c1-tint); }
.stat-c2 { --stat: var(--lms-c2); --stat-tint: var(--lms-c2-tint); }
.stat-c3 { --stat: var(--lms-c3); --stat-tint: var(--lms-c3-tint); }
.stat-c4 { --stat: var(--lms-c4); --stat-tint: var(--lms-c4-tint); }
.stat-c5 { --stat: var(--lms-c5); --stat-tint: var(--lms-c5-tint); }

.stat-bar {
  background: var(--stat);
  color: var(--lms-on-c);
  height: 34px;
  display: flex; align-items: center;
  padding-inline: .8rem;
  font-size: .95rem;
}

/* ------------------------------------------------------------ KPI panels */
/* The plain panel the admin screens are built from. Left as it was. */
.kpi-card {
  border: 1px solid var(--lms-border);
  border-radius: var(--lms-radius);
  background: var(--lms-surface);
}
.min-w-0 { min-width: 0; }

/* The figure wants to be big, but "PKR 652,620.00" has to stay on one line in
   a tile that is 171px wide on a phone and 360px on a tablet. The slope below
   was measured, not guessed: at each breakpoint the largest size that still
   fits was recorded, and this line sits just under that ceiling everywhere. */
.kpi-value {
  font-family: var(--lms-display-font);
  font-size: clamp(.85rem, 11.5cqi - .375rem, 1.75rem);
  font-weight: 800;
  letter-spacing: -.03em; line-height: 1.15;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.kpi-label {
  font-size: .75rem; text-transform: uppercase; letter-spacing: .07em;
  font-weight: 600; color: var(--lms-muted);
  margin-top: .15rem;
}
.trend-up { color: var(--lms-positive); font-weight: 700; }
.trend-down { color: var(--lms-negative); font-weight: 700; }

@media (max-width: 575.98px) {
  /* No font-size here: the container query above already sizes the figure to
     the tile it is actually in, and a flat value at this width overrode it
     and put the currency back on two lines. */
  .stat-bar { height: 26px; font-size: .78rem; padding-inline: .6rem; }
  .stat-tile .card-body { padding: .8rem; }
  .kpi-label { font-size: .7rem; }
}

.chart-box { position: relative; height: 300px; }
.chart-box-sm { position: relative; height: 220px; }

/* ------------------------------------------------------------- Tables */
.table {
  --bs-table-bg: transparent;
  --bs-table-border-color: var(--lms-border);
  --bs-table-hover-bg: var(--lms-surface-2);
}
.table > thead th {
  font-size: .75rem; text-transform: uppercase; letter-spacing: .06em;
  font-weight: 600; color: var(--lms-muted);
  background: transparent;
  border-bottom: 1px solid var(--lms-border);
  white-space: nowrap;
}
/* Bootstrap's .table-light ships its own near-black --bs-table-color, which
   in dark mode painted the reports totals black on a charcoal panel at
   1.27:1. Setting the colour alongside the background is what fixes it. */
.table-light, .table > tfoot.table-light, .table > thead.table-light {
  --bs-table-bg: var(--lms-surface-2);
  --bs-table-color: var(--lms-text);
  --bs-table-striped-color: var(--lms-text);
  --bs-table-hover-color: var(--lms-text);
  color: var(--lms-text);
}
.table-sticky thead th { position: sticky; top: 0; z-index: 1; background: var(--lms-surface); }
.font-monospace { font-size: .875rem; }

/* Inline code was Bootstrap's stock pink, which fails on the tinted panel. */
code, kbd {
  color: var(--lms-primary-text);
  background: var(--lms-surface-2);
  border-radius: .3rem; padding: .05rem .3rem;
}

/* Pagination came through with Bootstrap's own greys and blues. */
.pagination {
  --bs-pagination-bg: var(--lms-surface);
  --bs-pagination-color: var(--lms-text);
  --bs-pagination-border-color: var(--lms-border);
  --bs-pagination-hover-bg: var(--lms-surface-2);
  --bs-pagination-hover-color: var(--lms-text);
  --bs-pagination-hover-border-color: var(--lms-border-strong);
  --bs-pagination-focus-bg: var(--lms-surface-2);
  --bs-pagination-focus-color: var(--lms-text);
  --bs-pagination-focus-box-shadow: 0 0 0 3px var(--lms-accent-soft);
  --bs-pagination-active-bg: var(--lms-primary);
  --bs-pagination-active-border-color: var(--lms-primary);
  --bs-pagination-active-color: var(--lms-on-primary);
  --bs-pagination-disabled-bg: var(--lms-surface);
  --bs-pagination-disabled-color: var(--lms-muted);
  --bs-pagination-disabled-border-color: var(--lms-border);
  --bs-pagination-border-radius: .6rem;
}

/* --------------------------------------------------------------- Forms */
.form-control, .form-select {
  border-radius: .6rem;
  border-color: var(--lms-border-strong);
  background-color: var(--lms-surface-2);
  color: var(--bs-body-color);
}
.form-control::placeholder { color: var(--lms-muted); opacity: 1; }
.form-control:focus, .form-select:focus {
  border-color: var(--lms-primary);
  background-color: var(--lms-surface);
  box-shadow: 0 0 0 3px var(--lms-accent-soft);
}
.form-label { font-weight: 600; }
.input-group-text { background: var(--lms-surface-2); border-color: var(--lms-border-strong); color: var(--lms-muted); }
.form-check-input:checked { background-color: var(--lms-primary); border-color: var(--lms-primary); }
.form-check-input:focus { box-shadow: 0 0 0 3px var(--lms-accent-soft); border-color: var(--lms-primary); }
.nav-pills {
  --bs-nav-pills-link-active-bg: var(--lms-primary);
  --bs-nav-pills-link-active-color: var(--lms-on-primary);
  --bs-nav-pills-border-radius: .6rem;
}
.nav-pills .nav-link { color: var(--lms-muted); font-weight: 500; }

/* -------------------------------------------------------- Course learn */
.lesson-list .list-group-item { border-left: 0; border-right: 0; }
.lesson-list .list-group-item.active-lesson {
  background: var(--lms-accent-soft);
  box-shadow: inset 3px 0 0 var(--lms-primary);
  font-weight: 600;
}
.learn-sidebar { max-height: calc(100vh - 100px); overflow-y: auto; }
.learn-sidebar::-webkit-scrollbar { width: 6px; }
.learn-sidebar::-webkit-scrollbar-thumb { background: var(--lms-border-strong); border-radius: 6px; }
.video-frame {
  aspect-ratio: 16 / 9;
  background: var(--lms-surface-2);
  border-bottom: 1px solid var(--lms-border);
  color: var(--lms-muted);
}
.settings-tabs { border-bottom: 1px solid var(--lms-border); gap: .15rem; flex-wrap: wrap; }
.settings-tabs .nav-link {
  border: 0; border-bottom: 2px solid transparent; border-radius: 0;
  color: var(--lms-muted); font-weight: 500; padding: .55rem .9rem;
}
.settings-tabs .nav-link:hover { color: var(--lms-text); background: var(--lms-surface-2); }
.settings-tabs .nav-link.active {
  color: var(--lms-primary-text); background: transparent; border-bottom-color: var(--lms-primary);
}

.lesson-no-video {
  padding: 1rem 1.25rem;
  background: var(--lms-surface-2);
  border-bottom: 1px solid var(--lms-border);
  color: var(--lms-text);
}
.lesson-no-video .bi { font-size: 1.5rem; color: var(--lms-primary-text); }

.lesson-content { line-height: 1.75; }
.lesson-content ul { padding-left: 1.1rem; }

/* ---------------------------------------------------------- Certificates
   Fixed colours on purpose. A certificate is printed and shared as an image,
   so it has to look the same to everyone whatever theme they are in — which
   is why the brand colour here is the deep cobalt rather than the light one:
   #7DA5FF on white paper is around 2.2:1 and effectively invisible. */
.certificate {
  background: #fff;
  border: 1px solid #d4d4d8;
  padding: 4rem 3rem;
  position: relative;
  color: #18181b;
}
.certificate .cert-title {
  font-family: 'SpaceGrotesk', system-ui, sans-serif;
  font-size: 1.5rem; letter-spacing: .26em; text-transform: uppercase; font-weight: 500;
  color: #1D4ED8;
}
.certificate .cert-name {
  font-family: 'SpaceGrotesk', system-ui, sans-serif;
  font-size: 2.75rem; font-weight: 700; letter-spacing: -.03em;
  display: inline-block; padding: .5rem 0;
}
.certificate .cert-course { font-size: 1.15rem; font-weight: 500; }
.certificate .cert-rule { width: 72px; height: 3px; background: #1D4ED8; margin: 1.25rem auto; }
.certificate .cert-seal {
  width: 68px; height: 68px; border-radius: 50%;
  border: 2px solid #1D4ED8; color: #1D4ED8;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .6rem; font-weight: 600; text-align: center; line-height: 1.2;
  letter-spacing: .06em;
}
.cert-sign-line { border-top: 1px solid #d4d4d8; padding-top: .4rem; min-width: 170px; display: inline-block; }

@media (max-width: 575.98px) {
  .certificate { padding: 2rem 1.25rem; }
  .certificate .cert-title { font-size: 1rem; letter-spacing: .16em; }
  .certificate .cert-name { font-size: 1.6rem; }
  .certificate .cert-course { font-size: 1rem; }
}

@media print {
  body * { visibility: hidden; }
  .certificate, .certificate * { visibility: visible; }
  .certificate { position: absolute; inset: 0; margin: 0; border: 1px solid #d4d4d8; }
  .invoice-sheet, .invoice-sheet * { visibility: visible; }
  .invoice-sheet { position: absolute; inset: 0; margin: 0; box-shadow: none !important; }
  .no-print { display: none !important; }
}

/* ------------------------------------------------- Reviews and WhatsApp */
.rating-input { display: flex; flex-wrap: wrap; gap: .4rem; }

.whatsapp-fab {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 1030;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .6rem .9rem; border-radius: 999px;
  background: #25d366; color: #fff; font-weight: 600; font-size: .875rem;
  text-decoration: none; box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
}
.whatsapp-fab:hover { color: #fff; filter: brightness(.95); }
.whatsapp-fab i { font-size: 1.15rem; }
/* Keep the floating buttons from sitting on top of the footer links. */
body:has(.whatsapp-fab) .site-footer,
body:has(.assistant-fab) .site-footer { padding-bottom: 5.5rem !important; }
body:has(.whatsapp-fab):has(.assistant-fab) .site-footer { padding-bottom: 9rem !important; }

/* --------------------------------------------------- Study assistant */
/* The chat bubble sits in the corner; WhatsApp steps up to make room. */
body:has(.assistant-fab) .whatsapp-fab { bottom: 4.5rem; }

.assistant-fab {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 1035;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .65rem 1rem; border: 1px solid var(--lms-primary); border-radius: 999px;
  background: var(--lms-primary); color: var(--lms-on-primary);
  font-weight: 600; font-size: .875rem;
}
.assistant-fab:hover {
  background: var(--lms-primary-hover); border-color: var(--lms-primary-hover);
  color: var(--lms-on-primary);
}
.assistant-fab i { font-size: 1.1rem; }
.assistant.is-open .assistant-fab { display: none; }

.assistant-panel {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 1040;
  display: flex; flex-direction: column;
  width: min(23rem, calc(100vw - 2rem)); max-height: min(34rem, calc(100vh - 2rem));
  background: var(--lms-surface); border: 1px solid var(--lms-border);
  border-radius: var(--lms-radius); overflow: hidden;
}
.assistant-panel[hidden] { display: none; }

.assistant-head {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  padding: .75rem .9rem; border-bottom: 1px solid var(--lms-border);
}
.assistant-course { padding: .75rem .9rem 0; }

.assistant-log {
  flex: 1 1 auto; min-height: 8rem; overflow-y: auto;
  padding: .9rem; display: flex; flex-direction: column; gap: .6rem;
}
.assistant-msg { max-width: 88%; padding: .5rem .7rem; border-radius: var(--lms-radius); font-size: .875rem; }
.assistant-msg p { margin: 0 0 .5rem; }
.assistant-msg p:last-child, .assistant-msg ul:last-child { margin-bottom: 0; }
.assistant-msg ul { margin: 0 0 .5rem; padding-left: 1.1rem; }
.assistant-msg li { margin-bottom: .2rem; }
.assistant-msg-student { align-self: flex-end; background: var(--lms-primary); color: var(--lms-on-primary); }
.assistant-msg-assistant { align-self: flex-start; background: var(--lms-surface-2); border: 1px solid var(--lms-border); }
.assistant-msg.is-waiting { color: var(--lms-muted); }
.assistant-notice { margin: 0; font-size: .8125rem; color: var(--lms-muted); }

.assistant-chips { display: flex; flex-wrap: wrap; gap: .35rem; padding: 0 .9rem .5rem; }
.assistant-chips[hidden] { display: none; }
.assistant-chip {
  padding: .25rem .55rem; border: 1px solid var(--lms-border); border-radius: 999px;
  background: var(--lms-surface); color: var(--lms-muted); font-size: .75rem;
}
.assistant-chip:hover { border-color: var(--lms-border-strong); color: var(--lms-text); }
/* Also used by the mail provider presets, to show which one was picked. */
.assistant-chip.is-chosen {
  border-color: var(--lms-primary); background: var(--lms-accent-soft);
  color: var(--lms-primary-text); font-weight: 600;
}

.assistant-ask {
  display: flex; align-items: flex-end; gap: .5rem;
  padding: .75rem .9rem 0;
}
.assistant-ask textarea { resize: none; max-height: 7.5rem; }
.assistant-note { margin: .5rem .9rem .75rem; font-size: .6875rem; color: var(--lms-muted); }

@media (max-width: 575.98px) {
  .assistant-panel {
    right: 0; left: 0; bottom: 0;
    width: 100%; max-height: 85vh;
    border-radius: var(--lms-radius) var(--lms-radius) 0 0; border-bottom: 0;
  }
}

/* ------------------------------------------------- Password rule list */
.pw-rules {
  list-style: none; margin: .5rem 0 0; padding: 0;
  font-size: .8125rem; color: var(--lms-muted);
}
.pw-rule { display: flex; align-items: center; gap: .4rem; padding: .1rem 0; }
.pw-rule i { font-size: .75rem; }
.pw-rule.is-met { color: var(--lms-positive); }
/* Before anything is typed the list reads as requirements, not as failures,
   so an empty box is not a wall of red. */
.pw-rules:not(.is-typing) .pw-rule { color: var(--lms-muted); }

/* -------------------------------------------------------- Legal copy */
.legal-copy { line-height: 1.75; }
.legal-copy h2 {
  font-family: var(--lms-display-font);
  font-size: 1.15rem; font-weight: 600;
  margin: 2rem 0 .6rem; padding-top: 1.25rem;
  border-top: 1px solid var(--lms-border);
}
.legal-copy h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.legal-copy h3 { font-size: .95rem; font-weight: 600; margin: 1.25rem 0 .4rem; }
.legal-copy p, .legal-copy li { color: var(--lms-muted); }
.legal-copy ul, .legal-copy ol { padding-left: 1.15rem; }
.legal-copy li { margin-bottom: .35rem; }
.legal-copy code {
  background: var(--lms-surface-2); border: 1px solid var(--lms-border);
  border-radius: .25rem; padding: .05rem .3rem; color: var(--lms-text);
}

/* ---------------------------------------------------------- Leaderboard */
.rank-badge {
  width: 34px; height: 34px; border-radius: .4rem; display: inline-flex;
  align-items: center; justify-content: center; font-weight: 600; font-size: .75rem;
  background: var(--lms-surface-2); color: var(--lms-muted);
  border: 1px solid var(--lms-border);
  font-variant-numeric: tabular-nums;
}
.rank-1, .rank-2, .rank-3 {
  background: var(--lms-primary); color: var(--lms-on-primary); border-color: var(--lms-primary);
}
.step-number {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: .5rem;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--lms-primary); background: var(--lms-accent-soft);
  color: var(--lms-primary-text); font-size: .75rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.podium-card { border-radius: var(--lms-radius); }
.podium-card.podium-1 { border-color: var(--lms-primary) !important; }
.leaderboard-me {
  background: var(--lms-accent-soft) !important;
  box-shadow: inset 3px 0 0 var(--lms-primary);
}

/* ----------------------------------------------------------------- Misc */
.progress { background: var(--lms-surface-2); border-radius: 999px; }
.progress-thin { height: 4px; }
/* Progress is teal, flat — it says "this much is done", which is the one
   thing teal means everywhere else on the site too. */
.progress-bar {
  background: var(--lms-accent);
  border-radius: 999px;
}
/* Stars go back to amber. In a monochrome palette they had to be ink; here
   there is room for the one colour everybody already reads as a rating. */
.rating-stars { color: var(--lms-attention); letter-spacing: .02em; }
.rating-stars .bi-star { color: var(--lms-border-strong); }
.rating-inline { display: inline-flex; align-items: center; gap: .25rem; }
.rating-inline .bi { color: var(--lms-attention); font-size: .8em; }

.badge { font-weight: 600; letter-spacing: .01em; border-radius: .4rem; }
.badge[class*="-subtle"] {
  background: var(--lms-surface-2) !important;
  color: var(--lms-muted) !important;
  border: 1px solid var(--lms-border);
}
/* A badge is a neutral chip; only its text takes the state colour, and only
   where a state actually exists. */
.badge.bg-success-subtle { color: var(--lms-positive) !important; }
.badge.bg-danger-subtle  { color: var(--lms-negative) !important; }
.badge.bg-warning-subtle { color: var(--lms-attention) !important; }
/*
 * Bootstrap's own filled badges.
 *
 * .bg-warning, .bg-success and .bg-danger ship stock yellow, green and red
 * that belong to no palette here — the "2 pending" chip on the admin
 * dashboard was arriving in #ffc107 whatever the site was set to. They only
 * escaped notice under the amber scheme because stock yellow happened to
 * look close to it. Each is folded onto its own accent, and the label takes
 * the canvas colour, which is ink at night and white in daylight — the one
 * value that reads on all three fills in both themes.
 */
.badge.bg-warning, .badge.text-bg-warning {
  background-color: var(--lms-primary) !important;
  color: var(--lms-on-primary) !important;
}
.badge.bg-success, .badge.text-bg-success {
  background-color: var(--lms-positive) !important;
  color: var(--lms-canvas) !important;
}
.badge.bg-danger, .badge.text-bg-danger {
  background-color: var(--lms-negative) !important;
  color: var(--lms-canvas) !important;
}
/* .text-dark is bolted onto the pending chip in the markup to make stock
   yellow readable; it is wrong for every fill above, so it loses here — and
   it has to lose to the right value per fill, not one value for all three. */
.badge.bg-warning.text-dark { color: var(--lms-on-primary) !important; }
.badge.bg-success.text-dark,
.badge.bg-danger.text-dark  { color: var(--lms-canvas) !important; }
.alert {
  border: 1px solid var(--lms-border);
  border-radius: var(--lms-radius);
  background: var(--lms-surface-2) !important;
  color: var(--bs-body-color) !important;
}
.alert-success { box-shadow: inset 3px 0 0 var(--lms-positive); }
.alert-danger  { box-shadow: inset 3px 0 0 var(--lms-negative); }
.alert-warning { box-shadow: inset 3px 0 0 var(--lms-attention); }
.alert-info    { box-shadow: inset 3px 0 0 var(--lms-primary); }
.stat-pill { font-size: .75rem; padding: .2rem .55rem; border-radius: 999px; }
.copy-input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: .85rem; }
.empty-state { padding: 3rem 1rem; text-align: center; color: var(--lms-muted); }
.empty-state i { font-size: 2.25rem; color: var(--lms-primary-text); opacity: .7; display: block; margin-bottom: .75rem; }
/* The headline carries the message; the supporting line stays quiet. */
.empty-state p { color: var(--lms-text); }
.empty-state p.small { color: var(--lms-muted); }
hr { border-color: var(--lms-border); opacity: 1; }
.accordion { --bs-accordion-border-color: var(--lms-border); --bs-accordion-btn-focus-box-shadow: none; }
.accordion-button:not(.collapsed) { background: var(--lms-surface-2); color: var(--lms-text); }

/* Footer follows the page instead of a heavy dark block. */
footer.site-footer {
  background: var(--lms-surface) !important;
  border-top: 1px solid var(--lms-border);
  color: var(--lms-text) !important;
}
footer.site-footer .text-secondary { color: var(--lms-muted) !important; }
footer.site-footer a, footer.site-footer .link-light { color: var(--lms-muted) !important; }
footer.site-footer a:hover { color: var(--lms-text) !important; }
footer.site-footer hr { border-color: var(--lms-border); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* Live preview of the one-per-line outcome and requirement fields. */
.bullet-preview { list-style: none; padding-left: 0; margin-bottom: 0; }
.bullet-preview li { color: var(--lms-muted); padding: .1rem 0; }
.bullet-preview:empty { display: none; }

/* Confirmation screen icon. */
.verify-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 4rem; height: 4rem; border-radius: 50%;
  background: var(--lms-surface-2); border: 1px solid var(--lms-border);
  font-size: 1.75rem; color: var(--lms-text);
}
