/* ========================================================
   TYPOGRAPHY SYSTEM - REM-BASED SCALE & VERTICAL RHYTHM
   ======================================================== */

/* ========================================================
   INTER — SELF-HOSTED
   ========================================================
   These three files replace the Google Fonts <link> that base.html used to
   carry. That link was two DNS lookups (fonts.googleapis.com and
   fonts.gstatic.com) plus a RENDER-BLOCKING stylesheet request, on every
   page load, before anything could paint — and on a mill network with poor
   or filtered external connectivity it was a third party the app did not
   need to depend on. 72 KB of woff2 served from our own /static/ removes
   all of it.

   The files are the latin subset of Inter 400/600/700, taken from the
   @fontsource/inter npm package (SIL Open Font License 1.1 — the licence
   text ships beside them in static/fonts/LICENSE.txt, which the OFL
   requires). Same three weights the Google link requested, so nothing about
   how the app renders changes.

   ABSOLUTE paths, deliberately. A relative url() resolves against the
   stylesheet's own URL, and this file is served from two different
   locations: /static/css/base/typography.css unbundled, and inlined into
   /static/css/app.bundle.css when the bundle is fresh. A relative path
   would therefore be correct in one and broken in the other.

   font-display: swap keeps text visible while the font loads, exactly as
   the &display=swap parameter on the old Google URL did.

   unicode-range is what makes the latin subset safe: a character outside
   this range (Sinhala, for instance) never waits on these files at all —
   the browser goes straight to the next font in --font-sans. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/inter-400.woff2') format('woff2');
  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;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/static/fonts/inter-600.woff2') format('woff2');
  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;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/static/fonts/inter-700.woff2') format('woff2');
  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;
}

/* BASE CONFIGURATION */
:root {
  /* Type scale modular (1.125 ratio) */
  --fs-xs: 0.75rem;      /* 12px */
  --fs-sm: 0.875rem;     /* 14px */
  --fs-base: 1rem;       /* 16px (body) */
  --fs-lg: 1.125rem;     /* 18px */
  --fs-xl: 1.25rem;      /* 20px */
  --fs-2xl: 1.5rem;      /* 24px */
  --fs-3xl: 1.875rem;    /* 30px */
  --fs-4xl: 2.25rem;     /* 36px */
  --fs-5xl: 2.813rem;    /* 45px */
  
  /* Line height / Vertical rhythm (1.5rem baseline) */
  --lh-tight: 1.2;
  --lh-normal: 1.5;
  --lh-relaxed: 1.75;
  
  /* Font weights */
  --fw-light: 300;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;
  
  /* Letter spacing */
  --ls-tight: -0.02em;
  --ls-normal: 0;
  --ls-wide: 0.05em;
  --ls-wider: 0.1em;
}

/* ========================================================
   GLOBAL TEXT STYLES
   ======================================================== */

html {
  font-size: 16px; /* Base = 1rem */
}

body {
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  font-weight: var(--fw-regular);
  color: var(--text-main);
  letter-spacing: var(--ls-normal);
}

/* ========================================================
   HEADINGS (H1-H6)
   ======================================================== */

/* Headings scale FLUIDLY with clamp() rather than stepping down at two
   breakpoints. This replaces the `@media (max-width:767px)` and
   `@media (max-width:639px)` heading blocks further down this file — those
   produced a visible jump at each breakpoint and, worse, the 639px block
   also shrank the ROOT font size to 15px, which dragged body copy below a
   comfortable reading size on exactly the devices that need it most.

   Line height tightens as size grows: 1.2 is right at 36px but noticeably
   loose on a two-line 20px heading. */
h1, h2, h3, h4, h5, h6 {
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin-top: 0;
  margin-bottom: 1rem; /* 1 vertical rhythm unit */
  text-wrap: balance;  /* avoid a lone trailing word; ignored where unsupported */
}

h1 {
  font-size: clamp(1.5rem, 1.1rem + 2vw, 2.25rem);   /* 24px -> 36px */
  line-height: 1.15;
  font-weight: var(--fw-bold);
  margin-bottom: 1.5rem;
  letter-spacing: var(--ls-tight);
}

h2 {
  font-size: clamp(1.25rem, 1rem + 1.4vw, 1.875rem); /* 20px -> 30px */
  line-height: 1.18;
  font-weight: var(--fw-bold);
  margin-bottom: 1.25rem;
}

h3 {
  font-size: clamp(1.125rem, 1rem + 0.7vw, 1.5rem);  /* 18px -> 24px */
  line-height: 1.25;
  font-weight: var(--fw-semibold);
  margin-bottom: 1rem;
}

h4 {
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.25rem);  /* 16px -> 20px */
  line-height: 1.3;
  font-weight: var(--fw-semibold);
  margin-bottom: 1rem;
}

h5 {
  font-size: var(--fs-lg);        /* 18px */
  font-weight: var(--fw-semibold);
  margin-bottom: 0.75rem;
}

h6 {
  font-size: var(--fs-base);      /* 16px */
  font-weight: var(--fw-semibold);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  margin-bottom: 0.75rem;
}

/* ========================================================
   PARAGRAPH & BODY TEXT
   ======================================================== */

p {
  margin-top: 0;
  margin-bottom: 1.5rem; /* Full vertical rhythm unit */
  line-height: var(--lh-normal);
}

/* Remove bottom margin from last p in containers */
p:last-child {
  margin-bottom: 0;
}

/* ========================================================
   TEXT UTILITIES & SEMANTIC CLASSES
   ======================================================== */

.text-xs {
  font-size: var(--fs-xs);
  line-height: 1.2;
}

.text-sm {
  font-size: var(--fs-sm);
  line-height: 1.4;
}

.text-base {
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
}

.text-lg {
  font-size: var(--fs-lg);
  line-height: 1.5;
}

.text-xl {
  font-size: var(--fs-xl);
  line-height: 1.5;
}

.text-2xl {
  font-size: var(--fs-2xl);
  line-height: 1.3;
}

.text-3xl {
  font-size: var(--fs-3xl);
  line-height: 1.2;
}

.text-4xl {
  font-size: var(--fs-4xl);
  line-height: 1.1;
}

/* Font weight utilities */
.font-light {
  font-weight: var(--fw-light);
}

.font-normal {
  font-weight: var(--fw-regular);
}

.font-medium {
  font-weight: var(--fw-medium);
}

.font-semibold {
  font-weight: var(--fw-semibold);
}

.font-bold {
  font-weight: var(--fw-bold);
}

/* Line height utilities */
.leading-tight {
  line-height: var(--lh-tight);
}

.leading-normal {
  line-height: var(--lh-normal);
}

.leading-relaxed {
  line-height: var(--lh-relaxed);
}

/* Letter spacing utilities */
.tracking-tight {
  letter-spacing: var(--ls-tight);
}

.tracking-normal {
  letter-spacing: var(--ls-normal);
}

.tracking-wide {
  letter-spacing: var(--ls-wide);
}

.tracking-wider {
  letter-spacing: var(--ls-wider);
}

/* Text color utilities */
.text-muted {
  color: var(--text-muted);
}

.text-error {
  color: var(--color-error);
}

.text-success {
  color: var(--accent-green);
}

.text-primary {
  color: var(--color-primary);
}

/* ========================================================
   SEMANTIC TEXT ELEMENTS
   ======================================================== */

strong, .font-bold {
  font-weight: var(--fw-bold);
}

em, .italic {
  font-style: italic;
}

small, .text-small {
  font-size: var(--fs-sm);
  line-height: 1.4;
}

mark {
  background-color: rgba(255, 193, 7, 0.2);
  padding: 0.125rem 0.25rem;
  border-radius: var(--radius-xs);
}

code, pre {
  font-family: 'Fira Code', 'Courier New', monospace;
  font-size: 0.875rem;
  line-height: 1.5;
}

code {
  background: var(--color-muted);
  color: white;
  padding: 0.125rem 0.375rem;
  border-radius: var(--radius-sm);
}

pre {
  background: var(--color-muted);
  color: white;
  padding: 1rem;
  border-radius: var(--radius-md);
  overflow-x: auto;
  margin-bottom: 1.5rem;
}

pre code {
  background: none;
  color: inherit;
  padding: 0;
}

/* ========================================================
   LIST STYLES
   ======================================================== */

ul, ol {
  margin-top: 0;
  margin-bottom: 1.5rem; /* Full vertical rhythm */
  padding-left: 1.5rem;
  line-height: var(--lh-normal);
}

li {
  margin-bottom: 0.5rem;
}

li > ul, li > ol {
  margin-bottom: 0.5rem;
  margin-top: 0.5rem;
}

/* ========================================================
   BLOCKQUOTE & CITATION
   ========================================================== */

blockquote {
  margin: 1.5rem 0;
  padding: 1rem 1.5rem;
  border-left: 4px solid var(--color-primary);
  background: rgba(11, 95, 255, 0.05);
  font-style: italic;
  line-height: var(--lh-relaxed);
  color: var(--text-muted);
}

blockquote p {
  margin-bottom: 0;
}

blockquote footer {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin-top: 0.5rem;
}

/* ========================================================
   LINKS
   ========================================================== */

/* Uses --brand-ink, not --brand. The brand orange is a FILL colour: at
   5.0:1 on white it clears AA for normal text by a hair and fails for the
   12px links in table cells once a browser's subpixel rendering thins the
   strokes. --brand-ink is the same hue two steps darker (7.2:1) and is the
   token that exists for exactly this. Both themes define it, which is why
   the `html.dark-theme a { ... }` patch further down this file is now
   redundant rather than load-bearing. */
a {
  color: var(--brand-ink);
  text-decoration: none;
  transition: color 0.2s ease;
  cursor: pointer;
}

a:hover {
  color: var(--brand-hover);
  text-decoration: underline;
}

/* :focus-visible rather than :focus so the ring appears for keyboard
   users but not on every mouse click. Matches the convention already
   used in layout/main.css and components/buttons.css. */
a:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* NOTE: the `a:visited { color: #7c3aed }` rule that used to live here has
   been removed. In an internal MIS every link is visited within a day, so
   it turned the whole navigation, every table edit link and all pagination
   controls purple and off-brand within one session. Visited styling is a
   web-document convention that does not apply to an application UI. */

/* ========================================================
   TABULAR NUMERALS
   ========================================================
   Inter's default figures are PROPORTIONAL — a '1' is narrower than a '8'.
   In a column of numbers that means the digits don't line up vertically,
   and a KPI value visibly jitters sideways when it updates.

   Every element that displays a quantity, currency amount, percentage or
   timestamp opts into tabular (fixed-width) figures. This is a small change
   with an outsized effect on how precise the interface looks.
   ======================================================== */
.kpi-value,
.inv-value,
.progress-labels,
.achievement-pill,
.recent-meta,
.error-code,
table.dataTable tbody td,
.dataTables_wrapper .dataTables_info,
.status-badge,
td, th,
time,
.tabular {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ========================================================
   RESPONSIVE TYPOGRAPHY
   ========================================================
   The two heading-shrink blocks that used to live here are gone — headings
   now scale continuously via clamp() (see the HEADINGS section above),
   which removes the visible jump at 767px and 639px.

   The old 639px block also set `html { font-size: 15px }`, shrinking EVERY
   dimension expressed in rem — body copy, form labels, table text — on the
   smallest screens. That is backwards: a phone held at arm's length on a
   factory floor needs body text no smaller than on desktop. The root size
   now stays at 16px everywhere.
   ======================================================== */
@media (max-width: 639px) {
  body {
    font-size: var(--fs-base);
    line-height: 1.6;   /* slightly looser for small-screen reading */
  }

  p {
    margin-bottom: 1rem; /* Reduce vertical rhythm on mobile */
  }

  ul, ol {
    margin-bottom: 1rem;
    padding-left: 1.25rem;
  }
}

/* ========================================================
   DARK THEME TYPOGRAPHY
   ======================================================== */

html.dark-theme body {
  color: var(--text-main);
}

/* REMOVED in v1.16.0: `html.dark-theme a { color: var(--brand-ink) }` and its
   :hover twin.

   They were already redundant — both themes define --brand-ink, so the plain
   `a` rule near the top of this file resolves correctly on dark, and the
   comment above them said as much. What was not obvious is that they were
   also harmful. `html.dark-theme a` is specificity (0,1,2); a component rule
   like `a.btn-submit` is (0,1,1). So the dark-theme rule WON, and every link
   styled as a button — the Admin Panel's backup downloads, and anything
   similar added later — rendered its label in --brand-ink ON the --brand
   fill in dark mode: pale orange on orange, measured at 1.2:1.

   That is the FILL-vs-INK failure from CLAUDE.md arriving through a route the
   rule there does not cover: not a hardcoded #fff, but the default anchor
   colour outranking the component that meant to override it. Deleting these
   two lines removes the landmine rather than working around it one component
   at a time. Do not reinstate them. */

html.dark-theme code {
  background: rgba(255, 255, 255, 0.1);
  color: var(--text);
}

html.dark-theme pre {
  background: rgba(0, 0, 0, 0.3);
  color: var(--text);
}

html.dark-theme blockquote {
  background: var(--brand-wash);
  color: var(--text-muted);
}

/* ========================================================
   PRINT STYLES
   ======================================================== */

@media print {
  body {
    font-size: 12pt;
    line-height: 1.5;
  }

  h1, h2, h3 {
    page-break-after: avoid;
  }

  p, ul, ol {
    page-break-inside: avoid;
  }
}
