/* ==========================================================================
   CSCS Tap n Track — Typography standard
   --------------------------------------------------------------------------
   WHY THIS FILE EXISTS
   The application renders in one family — Times New Roman, regular and bold —
   and this file is where that decision is enforced. The tokens live in
   app.css :root (--font-family-base and the --fs-* ladder); this sheet turns
   them into a hierarchy: page titles, section headers, card titles, body,
   labels, captions and buttons each get one size, one weight and one leading.

   HOW IT IS LOADED
   Last among the stylesheets, in both layout.php (public site) and
   dashboard_layout.php (portals). Being last is load-bearing: it is what lets
   the role rules below settle a tie against dashboard.css or responsive.css
   without either file having to be edited.

   THE TWO !important RULES
   The universal family rule and the two exemptions underneath it are the only
   place !important is used for font-family. They are deliberate: the app
   carries ~1,500 lines of page-local <style> written before this standard
   existed, and a per-selector migration would leave gaps that surface only on
   the screens nobody visits. A blanket rule cannot have gaps.

   SCOPE
   Typography only. This file never sets color, background, border, shadow,
   gradient or opacity, so it cannot drift the palette. The one exception is
   text-transform and letter-spacing, which are typographic properties.
   ========================================================================== */

/* ==========================================================================
   1 — FAMILY: one family, everywhere
   ========================================================================== */

/* Every element renders in Times New Roman. --font-family-base is the token;
   the literal stack after the comma is the browser/system fallback the
   standard permits, so the rule still resolves if the token is ever missing. */
body,
body * {
  font-family: var(--font-family-base, 'Times New Roman', Times, 'Liberation Serif', 'DejaVu Serif', serif) !important;
}

/* ---- Exemption 1 of 2: icons -------------------------------------------
   Bootstrap Icons paints its glyphs from a private font declared on
   ::before/::after. The universal rule above matches elements only, so a
   pseudo-element keeps whatever it declares — but an element that carries the
   icon font directly would lose it, and so would a pseudo-element that relies
   on inheritance. Re-asserting the family here makes the exemption explicit
   rather than incidental. These are icons, not text: they are out of scope for
   a typography standard and their colours are untouched. */
.bi::before,
.bi::after,
[class^="bi-"]::before,
[class^="bi-"]::after,
[class*=" bi-"]::before,
[class*=" bi-"]::after {
  font-family: "bootstrap-icons" !important;
}

/* ---- Exemption 2 of 2: machine-readable identifiers --------------------
   Audit hashes, before/after diff values, raw field names and backup file
   names are read character by character, and a proportional serif makes 0/O
   and 1/l ambiguous at the sizes these appear in. A fixed-width face is a
   legibility requirement here, not a second brand voice — so the exception is
   confined to these four components and nothing else may opt in. */
.audit-code,
.audit-diff-before,
.audit-diff-after,
.audit-field-name,
.backups-file-name,
.audit-meta code,
.audit-detail-text code {
  font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace) !important;
}

/* ==========================================================================
   2 — WEIGHT: two cuts, and no inventions between them
   Times New Roman ships regular (400) and bold (700). Anything in between is
   drawn by the browser as a smeared, over-inked imitation of bold — the single
   most common reason a serif interface reads as unpolished. The scale is
   therefore binary, and the roles below are the only place that decides which
   cut a given element gets.
   ========================================================================== */

body {
  font-weight: var(--font-weight-normal);
}

/* Emphasis roles: titles, headers, controls, labels and table headers.
   These are the elements a reader scans rather than reads. */
h1, h2, h3, h4, h5, h6,
strong, b,
th, legend, dt, summary,
caption,
.page-title,
.admin-page-header__title,
.section-title,
.card-title,
.card-header,
.custom-modal-title,
.modal-title,
.toast-title,
.accordion-button,
.btn,
button,
input[type="submit"],
input[type="button"],
input[type="reset"],
.form-label,
.col-form-label,
label,
.badge,
.nav-link,
.navbar-nav .nav-link,
.pagination .page-item.active .page-link,
.stat-value,
.stat-label,
.metric-value,
.summary-value,
.legend-title,
.chart-title,
.empty-state__title {
  font-weight: var(--font-weight-bold);
}

/* Reading roles: body prose, table cells, supporting copy and every value a
   person types. Keeping these at 400 is what gives the bold above its meaning. */
p, li, dd, address, blockquote,
td,
.lead,
small,
.form-text,
.form-control,
.form-select,
textarea,
input:not([type="submit"]):not([type="button"]):not([type="reset"]),
.text-muted,
.card-text,
.card-subtitle,
.admin-page-header__subtitle,
.custom-modal-text,
.toast-body,
.help-text,
.input-hint,
.empty-state__text {
  font-weight: var(--font-weight-normal);
}

/* ==========================================================================
   MOBILE INPUT FONT FLOOR — 16px, and it has to live HERE rather than in
   responsive.css, because this file is linked after responsive.css and would
   otherwise win the cascade.

   iOS Safari zooms the entire page when a focused form control renders below
   16px, and the user then has to pinch back out to finish the form. Measured
   on /register at 390px: all six visible inputs computed to 14.4px, so every
   one of them triggered the zoom. The rule is scoped to the phone breakpoint
   so the desktop type ladder is untouched.
   ========================================================================== */
@media (max-width: 768px) {
  .form-control,
  .form-select,
  .custom-field,
  textarea,
  input:not([type="submit"]):not([type="button"]):not([type="reset"]),
  select {
    font-size: 16px !important;
  }
}

/* ==========================================================================
   3 — HIERARCHY: one ladder, seven steps
   Page title > section header > card title > body > label > caption, plus the
   display step used by the hero and the landing headline. Sizes come from the
   --fs-* ladder in app.css; nothing here invents a new value, so re-tuning the
   ladder moves every screen at once.
   ========================================================================== */

/* Display — hero and landing headlines only. */
.hero-title,
.cta-title,
.brand-gradient-heading,
.display-1, .display-2, .display-3, .display-4 {
  font-size: var(--type-display);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-display);
}

/* Page title — the strongest element in the page content. */
h1,
.page-title,
.admin-page-header__title,
.dashboard-header h2,
.dashboard-header h1 {
  font-size: var(--type-title);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-display);
}

/* Section header — clearly distinct from body, consistently spaced. */
h2,
.section-title,
.card-header h3,
.card-header h4 {
  font-size: var(--type-section);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  margin-bottom: 0.5rem;
}

/* Card title — scannable, one step below a section header. */
h3,
h4,
.card-title,
.custom-modal-title,
.modal-title,
.toast-title,
.accordion-button {
  font-size: var(--type-card);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

h5,
h6,
.card-header {
  font-size: var(--type-body);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

/* Body — comfortable leading, consistent paragraph rhythm. */
body,
p,
li,
dd,
address,
blockquote,
td,
.card-text,
.custom-modal-body,
.modal-body {
  font-size: var(--type-body);
  line-height: var(--line-height-body);
}

/* Supporting / caption — the smallest step, always regular. */
small,
caption,
.form-text,
.help-text,
.input-hint,
.card-subtitle,
.admin-page-header__subtitle,
.empty-state__text,
.meta,
.muted {
  font-size: var(--type-caption);
  line-height: var(--line-height-body);
}

/* ==========================================================================
   4 — COMPONENTS
   Component-scoped rules only. Anything a component already sets for itself in
   admin-ui.css or dashboard.css is left alone: those files read the same
   tokens, so they are already on the standard.
   ========================================================================== */

/* ---- Tables ------------------------------------------------------------
   Header bold and tracked out, content regular, pagination on the same scale.
   The colour decisions belong to the table stylesheets and are untouched. */
th,
.table thead th {
  font-size: var(--type-caption);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-caps);
  line-height: var(--line-height-tight);
}

td,
.table tbody td {
  font-size: var(--fs-sm);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

caption,
.table caption {
  font-size: var(--type-caption);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

.pagination {
  font-size: var(--fs-sm);
}

.pagination .page-link {
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-tight);
}

/* Sorting and filter affordances sit with the header, so they take its weight. */
.sortable,
.sort-indicator,
th.sortable,
.filter-label,
.admin-filter-bar .form-label {
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-caps);
}

/* ---- Forms -------------------------------------------------------------
   Field text, helpers and validation messages. Sizes stay at Bootstrap's own
   scale so no control changes width; only family, weight and leading are
   standardised. */
.form-control,
.form-select,
.form-control-sm,
.form-select-sm,
.form-control-lg,
.form-select-lg,
textarea,
input:not([type="submit"]):not([type="button"]):not([type="reset"]),
select,
.input-group-text {
  font-family: inherit;
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

::placeholder {
  font-family: inherit;
  font-weight: var(--font-weight-normal);
}

.form-label,
.col-form-label {
  font-size: var(--type-label);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  margin-bottom: 0.35rem;
}

.form-text,
.invalid-feedback,
.valid-feedback,
.help-block,
.field-error {
  font-size: var(--type-caption);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

/* Select options render with the platform's own widget; naming the family
   keeps the open list consistent with the closed control where supported. */
option,
optgroup {
  font-family: inherit;
}

/* ---- Buttons -----------------------------------------------------------
   Weight and tracking only: size and colour belong to the design system the
   button already belongs to. */
.btn,
button,
input[type="submit"],
input[type="button"],
input[type="reset"],
.btn-sm,
.btn-lg {
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
  letter-spacing: var(--letter-spacing-ui);
}

/* ---- Tabs, dropdowns, tooltips, accordions ---------------------------- */
.nav-tabs .nav-link,
.nav-pills .nav-link,
.dropdown-item,
.dropdown-header,
.accordion-button,
.list-group-item {
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

.dropdown-header {
  font-size: var(--type-caption);
  letter-spacing: var(--letter-spacing-caps);
  text-transform: uppercase;
}

.tooltip,
.tooltip-inner,
.popover,
.popover-body,
.popover-header {
  font-size: var(--type-caption);
  line-height: var(--line-height-body);
}

.popover-header {
  font-weight: var(--font-weight-bold);
}

/* ---- Modals and dialogs ------------------------------------------------
   One modal typography, shared by Bootstrap modals, the custom modal system
   and confirmation dialogs. */
.modal-title,
.custom-modal-title {
  font-size: var(--type-card);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

.modal-body,
.custom-modal-body,
.modal-text,
.custom-modal-text {
  font-size: var(--type-body);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

.modal-footer .btn,
.custom-modal-footer .btn {
  font-weight: var(--font-weight-bold);
}

/* ---- Toasts and notifications ------------------------------------------
   Title bold, description regular, actions bold. No colour is touched, so
   success / warning / error / info keep their existing identities. */
.toast-title,
.notification-title {
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

.toast-body,
.toast-description,
.notification-text {
  font-size: var(--fs-sm);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

.toast .btn {
  font-weight: var(--font-weight-bold);
}

/* ---- Badges, chips, pills --------------------------------------------- */
.badge,
.chip,
.tag,
.subject-badge,
.status-badge {
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-ui);
  line-height: var(--line-height-tight);
}

/* ---- Charts and data visualisation ------------------------------------
   Ticks, legends, axis values and data labels are painted onto <canvas>, so
   they are set from JavaScript (the Chart.defaults.font.family assignment the
   portal views make after Chart.js loads). What CSS owns is the text around
   the canvas, normalised here so a chart heading matches a card title and a
   stat value matches the ladder. Datasets and chart colours are untouched. */
.chart-title,
.chart-header {
  font-size: var(--type-card);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

.chart-legend,
.legend,
.chart-caption,
.chart-note {
  font-size: var(--type-caption);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

.stat-value,
.metric-value,
.summary-value {
  font-size: var(--fs-xl);
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

.stat-label,
.metric-label,
.summary-label {
  font-size: var(--type-caption);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-caps);
  line-height: var(--line-height-tight);
}

/* ---- Navigation, sidebars, topbars ------------------------------------
   Navigation is typography too: same family, same two weights. */
.site-nav .nav-link,
.site-nav a,
.app-sidebar .nav-link,
.sidebar .nav-link,
.breadcrumb-item {
  font-weight: var(--font-weight-bold);
}

.app-sidebar .nav-section-title,
.sidebar-heading,
.nav-section-title {
  font-size: var(--type-caption);
  font-weight: var(--font-weight-bold);
  letter-spacing: var(--letter-spacing-caps);
  text-transform: uppercase;
}

/* ---- Empty, loading and error states ---------------------------------- */
.empty-state__title,
.loading-text,
.error-title,
.success-title,
.error-page-title {
  font-weight: var(--font-weight-bold);
  line-height: var(--line-height-tight);
}

.empty-state__text,
.error-message,
.success-message,
.error-page-message {
  font-size: var(--fs-sm);
  font-weight: var(--font-weight-normal);
  line-height: var(--line-height-body);
}

/* ==========================================================================
   5 — RESPONSIVE
   The family never changes across breakpoints; only the display and page-title
   steps step down. That is what keeps a large hero legible on a phone without
   introducing a second typeface for small screens.
   ========================================================================== */

@media (max-width: 991.98px) {
  :root {
    --type-display: clamp(1.75rem, 1.2rem + 2.2vw, 2.25rem);
  }
}

@media (max-width: 767.98px) {
  :root {
    --type-title: var(--fs-lg);
    --type-section: var(--fs-md);
  }
}

@media (max-width: 575.98px) {
  :root {
    --type-display: 1.75rem;
    --type-title: var(--fs-md);
    --type-section: var(--fs-md);
    --type-card: var(--fs-base);
  }

  h1,
  .page-title,
  .admin-page-header__title {
    letter-spacing: normal;
  }
}

/* ==========================================================================
   6 — PRINT AND EXPORT
   Printable reports, print previews, export views and PDF-ready layouts use
   the same family as the screen. The generated report stylesheet already sets
   Times New Roman for the documents it produces; this block covers everything
   printed from a normal screen.
   ========================================================================== */

@media print {
  body,
  body * {
    font-family: 'Times New Roman', Times, 'Liberation Serif', 'DejaVu Serif', serif !important;
    letter-spacing: normal !important;
  }

  body {
    font-size: 12pt;
    line-height: 1.4;
  }

  h1, .page-title { font-size: 18pt; }
  h2, .section-title { font-size: 15pt; }
  h3, .card-title { font-size: 13pt; }
  h4, h5, h6, .card-header { font-size: 12pt; }

  p, li, td, dd, blockquote {
    font-size: 10pt;
    line-height: 1.35;
  }

  th {
    font-size: 9.5pt;
    letter-spacing: 0.02em;
  }

  small, caption, .form-text, .help-text {
    font-size: 9pt;
  }

  /* Cards, tables and dialogs are reprinted without decoration, so the sizes
     above carry the hierarchy on their own. */
  .badge,
  .btn {
    font-size: 9.5pt;
  }
}
