/*
 * Site theme: green and gold over the vendored Bootstrap 5.3.8 (PRD §9.8).
 * Load it after bootstrap.min.css. It only sets Bootstrap's own custom
 * properties, plus the few rules whose blue Bootstrap compiles in as fixed
 * values (form focus, checked boxes). Every text pair meets 4.5:1 (WCAG 1.4.3);
 * apps/core/tests/test_site_theme.py checks the values below.
 * Screen pages only: PDF report templates never load this file.
 *
 * Page headings use Playfair Display. Plain reading text that carries the site-reading
 * class (intro and help paragraphs) uses Noto Serif. Both are served from static/fonts/
 * and never from a CDN (PRD §9.8 Typography, §9.8.4). Everything else keeps Bootstrap's
 * system font: body text, forms, tables, buttons, the navbar, alerts and stat numbers.
 */

/* One variable file covers every weight from 400 to 900. swap: text shows at once in the fallback font. */
@font-face {
  font-family: "Playfair Display";
  src: url("../fonts/PlayfairDisplay-wght.1021c226803a.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}

/* Same family the PDF reports embed. Regular and Bold only: a 600 weight shows Bold, and italic is not provided. */
@font-face {
  font-family: "Noto Serif";
  src: url("../fonts/NotoSerif-Regular.94f143bf4935.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Noto Serif";
  src: url("../fonts/NotoSerif-Bold.3fa2b3a324ef.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --bs-primary: #0b6b57;
  --bs-primary-rgb: 11, 107, 87;
  --bs-primary-text-emphasis: #042b23;
  --bs-primary-bg-subtle: #cee1dd;
  --bs-primary-border-subtle: #9dc4bc;

  --bs-link-color: #0b6b57;
  --bs-link-color-rgb: 11, 107, 87;
  --bs-link-hover-color: #073a31;
  --bs-link-hover-color-rgb: 7, 58, 49;

  --bs-focus-ring-color: rgba(11, 107, 87, 0.25);

  /* Keyboard focus ring colour: 6.4:1 on white, so it clears the 3:1 an outline needs. */
  --site-focus-ring: #0b6b57;
}

/*
 * Page headings only. Playfair has hairline strokes, so it is kept off the small heading
 * sizes (.h5, .h6) and off all body text. If the file fails to load, the browser shows
 * Bootstrap's own system font, so a heading is never blank. Noto Serif Bengali is listed
 * for a heading that holds Bangla text: Playfair has no Bangla glyphs, and pages that show
 * Bangla already declare that font. Lining figures keep digits in a title level (2019).
 */
:is(h1, .h1, h2, .h2):not(.h5):not(.h6) {
  font-family: "Playfair Display", "Noto Serif Bengali", var(--bs-font-sans-serif);
  font-variant-numeric: lining-nums;
}

/*
 * Intro and help paragraphs only, chosen one by one with this class in the template. Never
 * put it inside a table, form, button, navbar or alert: those need the clear, narrow system
 * font (apps/core/tests/test_site_theme.py checks this). If the file fails to load, the
 * browser shows the system font. Noto Serif Bengali is listed for Bangla words in the text.
 */
.site-reading {
  font-family: "Noto Serif", "Noto Serif Bengali", var(--bs-font-sans-serif);
}

.btn-primary {
  --bs-btn-bg: #0b6b57;
  --bs-btn-border-color: #0b6b57;
  --bs-btn-hover-bg: #095b4a;
  --bs-btn-hover-border-color: #095646;
  --bs-btn-focus-shadow-rgb: 47, 129, 112;
  --bs-btn-active-bg: #095646;
  --bs-btn-active-border-color: #085041;
  --bs-btn-disabled-bg: #0b6b57;
  --bs-btn-disabled-border-color: #0b6b57;
}

.btn-outline-primary {
  --bs-btn-color: #0b6b57;
  --bs-btn-border-color: #0b6b57;
  --bs-btn-hover-bg: #0b6b57;
  --bs-btn-hover-border-color: #0b6b57;
  --bs-btn-focus-shadow-rgb: 11, 107, 87;
  --bs-btn-active-bg: #0b6b57;
  --bs-btn-active-border-color: #0b6b57;
  --bs-btn-disabled-color: #0b6b57;
  --bs-btn-disabled-border-color: #0b6b57;
}

/*
 * Outline red and grey buttons: Bootstrap's #dc3545 and #6c757d give 4.05:1 and 4.20:1 on a striped
 * table row ("Deactivate", "Reports"); the limit is 4.5:1. Bootstrap's darker tones give 5.2:1 or
 * better on a striped row, with or without the hover tint, and 6.5:1 for white text on the filled hover state.
 */
.btn-outline-danger {
  --bs-btn-color: #b02a37;
  --bs-btn-border-color: #b02a37;
  --bs-btn-hover-bg: #b02a37;
  --bs-btn-hover-border-color: #b02a37;
  --bs-btn-focus-shadow-rgb: 176, 42, 55;
  --bs-btn-active-bg: #b02a37;
  --bs-btn-active-border-color: #b02a37;
  --bs-btn-disabled-color: #b02a37;
  --bs-btn-disabled-border-color: #b02a37;
}

.btn-outline-secondary {
  --bs-btn-color: #565e64;
  --bs-btn-border-color: #565e64;
  --bs-btn-hover-bg: #565e64;
  --bs-btn-hover-border-color: #565e64;
  --bs-btn-focus-shadow-rgb: 86, 94, 100;
  --bs-btn-active-bg: #565e64;
  --bs-btn-active-border-color: #565e64;
  --bs-btn-disabled-color: #565e64;
  --bs-btn-disabled-border-color: #565e64;
}

/* Bootstrap compiles the active pill's blue in as a fixed value, like the form focus colour below. */
.nav-pills {
  --bs-nav-pills-link-active-bg: #0b6b57;
}

/*
 * Edge of a form control. Bootstrap's pale grey edge (#dee2e6) measures 1.3:1 against the page, and
 * 3:1 is the least that WCAG 1.4.11 asks when the edge is what shows where a box is. #6c757d is
 * 4.7:1 on white, 4.4:1 on the light panel and 3.9:1 on a read-only grey box. These rules come before
 * the focus, checked and invalid rules below, which are more specific and keep their own colours.
 */
.form-control,
.form-select,
.form-check-input {
  border-color: #6c757d;
}

.form-control:focus,
.form-select:focus,
.form-check-input:focus {
  border-color: var(--bs-primary);
  box-shadow: 0 0 0 0.25rem rgba(11, 107, 87, 0.25);
}

.form-check-input:checked {
  background-color: #0b6b57;
  border-color: #0b6b57;
}

/* Decorative stripe only; gold never sits behind text, so it needs no text contrast. */
.navbar.bg-primary {
  --bs-navbar-color: #ffffff;
  --bs-navbar-hover-color: #ffffff;
  --bs-navbar-active-color: #ffffff;
  border-bottom: 4px solid #e0a93b;
}

/*
 * Keyboard focus: one strong ring on every control. Bootstrap's own marker is a faint glow, and
 * on the navbar links it is Bootstrap blue (rgba(13, 110, 253, 0.25)), which clashes with the green
 * theme. The ring is a 3 px outline, so it needs no shadow. On the dark green bar it turns white.
 * Boxes that take typed text show it for the mouse as well, because the browser treats them that way.
 */
a:focus-visible,
button:focus-visible,
summary:focus-visible,
.btn:focus-visible,
.btn-close:focus-visible,
.nav-link:focus-visible,
.page-link:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible,
#form-error-summary:focus-visible {
  outline: 3px solid var(--site-focus-ring);
  outline-offset: 2px;
  box-shadow: none;
}

.btn-close:focus {
  box-shadow: none;
}

.site-mark-table .form-control:focus-visible {
  outline-offset: 0;
}

.navbar.bg-primary a:focus-visible,
.navbar.bg-primary .btn:focus-visible,
.navbar.bg-primary .nav-link:focus-visible {
  outline-color: #ffffff;
}

/*
 * Top bar: let its inner row wrap. From 1200 px wide Bootstrap lays the brand and the menu on one
 * row that never wraps. At the normal text size they fit; when a person's browser makes the default
 * text 200% larger they are 1345 px wide in a 1178 px bar and the whole page scrolled sideways (WCAG
 * 1.4.4 asks for no loss at 200%). With wrapping, the menu simply drops under the brand. At the normal
 * size nothing wraps, so the bar looks the same.
 */
.navbar.bg-primary > .container-fluid {
  flex-wrap: wrap;
}

/* Landing hero: a subtle gradient within the light range (PRD §1.9.3 Block 2, §9.8.4). */
.site-hero {
  background: linear-gradient(180deg, var(--bs-primary-bg-subtle) 0%, #ffffff 100%);
  border-bottom: 1px solid var(--bs-primary-border-subtle);
}

/* Depth through colour and border, never a shadow on static content (PRD §9.8.4 principle 2). */
.site-card-accent {
  border-top: 4px solid var(--bs-primary);
}

/*
 * Keep everything inside a scrolling table box. Bootstrap's visually-hidden labels are
 * absolutely positioned; without a positioned box they escape it and widen the whole page
 * (12 mark-entry labels stretched a 320 px page to 683 px, WCAG 1.4.10, PRD §9.7).
 */
.table-responsive {
  position: relative;
}

/*
 * Every data table on a screen page: a pale green header band with a green rule under it, and a
 * faint green tint on the row under the pointer. The header pair is the one the theme test already
 * checks for contrast. The hover tint reuses Bootstrap's own row-state variable, so striped rows
 * and the pinned mark-entry columns keep working. PDF report pages never load this file.
 */
main .table > thead > tr > th {
  background-color: var(--bs-primary-bg-subtle);
  color: var(--bs-primary-text-emphasis);
  border-bottom: 2px solid var(--bs-primary);
}

main .table > tbody > tr:hover > * {
  --bs-table-bg-state: rgba(11, 107, 87, 0.08);
}

/* Page-number bar: Bootstrap compiles its active page in blue, so the theme sets the pagination variables. White on this green is the checked primary pair. */
.pagination {
  --bs-pagination-color: var(--bs-link-color);
  --bs-pagination-hover-color: var(--bs-link-hover-color);
  --bs-pagination-focus-color: var(--bs-link-hover-color);
  --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(11, 107, 87, 0.25);
  --bs-pagination-active-bg: #0b6b57;
  --bs-pagination-active-border-color: #0b6b57;
}

/*
 * Top bar: from 1400 px wide, where the menu fits in one row (about 60 px tall; between 1200 and
 * 1399 px it wraps to two rows, 105 px, which is too much to keep on screen), the bar stays at the
 * top of the window while a long page scrolls, so the menu is never far away. Below that it
 * scrolls away as before. scroll-padding keeps a heading reached from a link (for example
 * "On this page") from hiding under the bar, even if a long name makes the bar two rows tall.
 */
@media (min-width: 1400px) {
  .site-top-bar {
    position: sticky;
    top: 0;
    z-index: 1020;
  }

  html {
    scroll-padding-top: 7rem;
  }
}

/*
 * Typed values and column names (X, P, ***, student_id). Bootstrap's pink code colour measured 4.27:1
 * on the grey legend boxes of the Marks upload page (4.5:1 is the limit) and clashes with the green
 * theme. A pale green chip with dark green text is 11:1, the pair the theme test already checks.
 */
code {
  color: var(--bs-primary-text-emphasis);
  background-color: var(--bs-primary-bg-subtle);
  padding: 0.1em 0.35em;
  border-radius: 0.25rem;
  font-weight: 600;
}

/* Key name in a hint, such as the "/" for search. Bootstrap's own kbd is a dark chip; the theme keeps panels light, so this is white with a border. */
kbd {
  background-color: #ffffff;
  color: var(--bs-body-color);
  border: 1px solid var(--bs-border-color);
  font-weight: 600;
}

/*
 * Status text such as "Active" and error text. Bootstrap's own green and red are 4.53:1 on white,
 * which passes, but only 4.06:1 on a striped table row, 3.6:1 under the row-hover tint and 3.8:1 under
 * the mark-entry focus tint (4.5:1 is the limit). These two utilities get a darker green and red
 * (4.8:1 or better on every one of those backgrounds). Only the text utilities change: buttons,
 * badges and alert backgrounds keep Bootstrap's colours. apps/core/tests/test_site_theme.py checks the values.
 */
.text-success {
  --bs-success-rgb: 20, 108, 67;
}

.text-danger {
  --bs-danger-rgb: 176, 42, 55;
}

/*
 * Badges may wrap. Bootstrap forbids a line break inside a badge, so a long name (a committee
 * chairman's full name is normal here) made a 441 px badge and pushed the page to 460 px wide on a
 * 390 px or 320 px phone (WCAG 1.4.10 asks for no sideways scroll). The badge now wraps inside its box. A
 * one-line badge keeps Bootstrap's exact height: 1.25 line height plus 0.225em above and below is the
 * same 1.7em as Bootstrap's 1.0 plus 0.35em above and below.
 */
.badge {
  --bs-badge-padding-y: 0.225em;
  line-height: 1.25;
  white-space: normal;
  overflow-wrap: anywhere;
  max-width: 100%;
  text-align: start;
}

/* Empty list: a dashed green frame instead of a bare sentence, so a blank page still shows what to do next. */
.site-empty-state {
  border: 2px dashed var(--bs-primary-border-subtle);
  background-color: #ffffff;
}

/* Task tile: the whole card is one link; hovering or tabbing in darkens its border (colour, not a shadow). */
.site-task-card {
  transition: border-color 0.15s ease-in-out;
}

.site-task-card:hover,
.site-task-card:focus-within {
  border-color: var(--bs-primary);
}

/*
 * Mark entry table: mark boxes wide enough to show a full value such as 20.00 (they were
 * clipped to "2(" at tablet width), and Student ID and Name kept in view while the other
 * columns scroll sideways. Pinned only from the md breakpoint up: on a phone two pinned
 * columns would leave no room for the boxes.
 */
.site-mark-table {
  width: auto;
  min-width: 100%;
}

.site-mark-table .form-control {
  min-width: 5.5rem;
}

/*
 * Mark entry: the row that holds the cursor gets a green tint and a green bar on its left edge,
 * so a tabulator moving across twelve boxes keeps track of the student. The tint reuses the
 * row-state variable of the hover rule; the bar is a background image, not a shadow. Digits use
 * equal widths so the marks line up down a column.
 */
.site-mark-table tbody tr:focus-within > * {
  --bs-table-bg-state: rgba(11, 107, 87, 0.12);
}

.site-mark-table tbody tr:focus-within > :first-child {
  background-image: linear-gradient(var(--bs-primary), var(--bs-primary));
  background-repeat: no-repeat;
  background-size: 4px 100%;
}

.site-mark-table .form-control {
  font-variant-numeric: tabular-nums;
}

@media (min-width: 768px) {
  .site-sticky-first,
  .site-sticky-second {
    position: sticky;
    z-index: 1;
    background-color: var(--bs-body-bg);
  }

  .site-sticky-first {
    left: 0;
    min-width: 7rem;
  }

  .site-sticky-second {
    left: 7rem;
    min-width: 11rem;
  }
}

/* Red star after the label of a required box on a form that also has optional boxes (added by static/js/required-marks.js).
   The second content line gives the star an empty spoken text where the browser supports it; the box itself carries "required". #b02a37 on white is about 6.9:1. */
.site-required-label::after {
  content: " *";
  content: " *" / "";
  color: #b02a37;
  font-weight: 700;
}

.site-required-note {
  margin-top: 0;
}

/* Collapsible panel heading (a native details element): shows it can be clicked, and keeps a visible keyboard focus ring. */
.site-summary-toggle {
  cursor: pointer;
}

.site-summary-toggle:focus-visible {
  outline: 3px solid var(--bs-primary);
  outline-offset: -3px;
}

details[open] > .site-summary-toggle {
  border-bottom: 1px solid var(--bs-border-color);
}

/* Profile page: a round badge with the first letter of the name. Decorative only (aria-hidden); white on the theme green is above 4.5:1. */
.site-profile-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4rem;
  height: 4rem;
  border-radius: 50%;
  background-color: var(--bs-primary);
  color: #ffffff;
  font-size: 1.75rem;
  font-weight: 600;
}

/* Tabulator card: each group of work (marks, calculation, reports) has a green bar on its left and a numbered dot. */
.site-step {
  border-left: 4px solid var(--bs-primary-border-subtle);
  padding-left: 1rem;
}

.site-step-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  margin-right: 0.25rem;
  border-radius: 50%;
  background-color: var(--bs-primary);
  color: #ffffff;
  font-size: 0.875rem;
  font-weight: 600;
}

/* Same top edge as site-card-accent, in red, for a card that holds a step which changes a record. */
.site-card-danger {
  border-top: 4px solid var(--bs-danger);
}

/* Mark entry: the Back and Save buttons stay at the bottom of the window while a long table scrolls, so Save is never far away. */
.site-action-bar {
  position: sticky;
  bottom: 0;
  z-index: 2;
  padding: 0.75rem 0;
  background-color: var(--bs-body-bg);
  border-top: 1px solid var(--bs-border-color);
}

/* Landing: one step of the "marks to reports" flow; a white box with a green left bar, so the hero gradient stays behind it. */
.site-flow-step {
  padding: 0.75rem 1rem;
  text-align: left;
  background-color: #ffffff;
  border: 1px solid var(--bs-primary-border-subtle);
  border-left: 4px solid var(--bs-primary);
  border-radius: 0.375rem;
}

/*
 * Printing a screen page (a list, the exam page): only the content goes on paper. The top bar,
 * footer, buttons, search boxes, page bars and helper panels are hidden; tables use the full
 * page width and repeat their header on each page; links lose their colour. A printer usually
 * leaves out background colours, so a badge with white text on green or yellow would print as
 * blank, and the badges, the table header band and highlighted words are redrawn with borders
 * and dark text. The PDF reports use their own templates and never load this file.
 */
@media print {
  .site-top-bar,
  footer,
  .visually-hidden-focusable,
  nav[aria-label="Breadcrumb"],
  nav[data-page-sections],
  nav[aria-label$="list pages"],
  .site-scroll-hint,
  .site-action-bar,
  #unsaved-changes-note,
  form[role="search"],
  .bg-body-tertiary:has(form),
  .btn,
  .btn-close {
    display: none !important;
  }

  body {
    background: #ffffff;
    color: #000000;
  }

  main,
  .container {
    max-width: none;
  }

  .table-responsive {
    overflow: visible;
  }

  .table {
    font-size: 10pt;
  }

  thead {
    display: table-header-group;
  }

  tr,
  .card {
    break-inside: avoid;
  }

  h1,
  h2,
  h3 {
    break-after: avoid;
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  .card {
    border: 1px solid #000000;
  }

  main .table > thead > tr > th {
    background-color: transparent;
    color: #000000;
    border-bottom: 2px solid #000000;
  }

  .badge {
    background-color: transparent !important;
    color: #000000 !important;
    border: 1px solid #000000;
  }

  mark {
    background-color: transparent;
    color: inherit;
    text-decoration: underline;
  }
}

/* Four-step progress strip on a draft exam page: done steps are green, the current step is outlined. */
.site-stepper {
  display: flex;
  gap: 0.5rem;
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}
.site-stepper-item {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  border: 1px solid #6c757d;
  border-top: 4px solid #6c757d;
  border-radius: 0.375rem;
  background: #fff;
  color: #495057;
  font-size: 0.9rem;
}
.site-stepper-item.is-done { border-color: #0b6b57; background: #e6f1ee; color: #042b23; }
.site-stepper-item.is-current { border-color: #0b6b57; border-top-width: 4px; color: #042b23; font-weight: 600; }
.site-stepper-mark {
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  border: 2px solid currentColor;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
}
.site-stepper-item.is-done .site-stepper-mark { background: #0b6b57; border-color: #0b6b57; color: #fff; }
.site-stepper-label { overflow-wrap: anywhere; }
@media (max-width: 575.98px) {
  .site-stepper { flex-direction: column; gap: 0.25rem; }
}
