/* ==========================================================================
   Typographic voice — Phase 3 of the Fit and Finish brief.

   The brief asked for "one variable sans and one variable mono, self-hosted,
   subset, preloaded, no CDN, no layout shift". Three of those five are
   satisfied by shipping *no font file at all*.

   Every platform this system runs on already ships a variable sans and a
   variable mono in the system UI stack:

       macOS / iOS   SF Pro Text        (variable weight + optical size)
       Windows 11    Segoe UI Variable  (variable weight + optical size)
       Android       Roboto Flex        (variable weight, width, optical size)
       Linux         Cantarell / DejaVu (static fallback)

   Using them means: zero bytes over the wire, zero FOIT, zero FOUT, zero
   layout shift, no CDN request to block, no licence to audit, and text that
   matches the operating system the counter clerk already reads all day. A
   downloaded webfont could only match that on the second page load.

   What we owe in return is to actually *use* the axes and features these
   faces expose, rather than treating them as a bare fallback stack. That is
   what this file does: optical sizing, real weight steps per type role,
   tracking that tightens as size grows, slashed zeros on every identifier,
   and tabular figures anywhere digits stack.

   If a licensed brand face ever becomes available, drop the .woff2 files in
   custom/fonts/ and uncomment the @font-face block at the foot of this file.
   Nothing else needs to change — everything below reads --font-sans and
   --font-mono.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Axes and features
   -------------------------------------------------------------------------- */

/*
 * Let the variable faces pick their own optical size for the point size they
 * are rendered at. SF Pro switches from Text to Display cuts around 20px;
 * Segoe UI Variable interpolates continuously. Without this, headings are set
 * in the small-text cut and look slightly clumsy at 32px.
 */
html {
	font-optical-sizing: auto;
	text-size-adjust: 100%;
	-webkit-text-size-adjust: 100%;
}

/*
 * Never let the browser fake a weight or a slant. A synthesised semibold on a
 * variable face produces a smeared, heavier-than-asked-for stem that reads as
 * a rendering bug next to the real 600 instance.
 */
body {
	font-synthesis: none;
	font-variant-ligatures: common-ligatures contextual;
}

/* --------------------------------------------------------------------------
   2. The eight type steps, each given a voice

   Phase 1 established the sizes. Sizes alone are not a typographic system:
   the same 32px heading set at body weight and body tracking is indis-
   tinguishable from large body text. Each step below pairs its size with the
   weight, tracking and leading that make its role legible at a glance.

   Tracking runs negative as size grows and positive as size shrinks — the
   standard optical correction. Display type at default tracking looks loose;
   11px caps at default tracking looks jammed.
   -------------------------------------------------------------------------- */

.t-display,
h1, .h1 {
	font-size: var(--t-display);
	font-weight: 680;
	line-height: 1.15;
	letter-spacing: -.022em;
	text-wrap: balance;
}

.t-title,
h2, .h2 {
	font-size: var(--t-title);
	font-weight: 660;
	line-height: 1.2;
	letter-spacing: -.017em;
	text-wrap: balance;
}

.t-heading,
h3, .h3 {
	font-size: var(--t-heading);
	font-weight: 640;
	line-height: 1.28;
	letter-spacing: -.012em;
	text-wrap: balance;
}

.t-subhead,
h4, .h4, h5, .h5, h6, .h6 {
	font-size: var(--t-subhead);
	font-weight: 620;
	line-height: 1.35;
	letter-spacing: -.006em;
	text-wrap: balance;
}

.t-body {
	font-size: var(--t-body);
	font-weight: 400;
	line-height: var(--lh-body);
	letter-spacing: 0;
}

.t-secondary {
	font-size: var(--t-secondary);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: .002em;
}

.t-caption {
	font-size: var(--t-caption);
	font-weight: 450;
	line-height: 1.45;
	letter-spacing: .006em;
}

/*
 * The micro step is the only one that is set in caps. Caps need real tracking
 * or they close up, and they need extra weight or they disappear against body
 * text — both already handled in app.css; this only adds the feature that
 * stops "OPENING STOCK" rendering with lowercase-shaped figures.
 */
.micro,
.t-micro {
	font-variant-numeric: tabular-nums lining-nums;
}

/* --------------------------------------------------------------------------
   3. Running text

   Body copy in this app is short — a state description, a warranty note, a
   confirmation sentence. It still deserves a measure and a ragged edge that
   does not strand single words.
   -------------------------------------------------------------------------- */

p, .prose {
	text-wrap: pretty;
}

/* Law: 65ch measure wherever prose runs free of a table cell. */
.state-desc,
.notice-body,
.page-sub,
.hint-strip,
.prose {
	max-width: 65ch;
}

/*
 * Hanging punctuation pulls opening quotes and bullets into the margin so the
 * left edge of a paragraph stays optically flush. Supported in Safari, which
 * is a large share of the machines this runs on; a no-op elsewhere.
 */
.prose,
.state-desc {
	hanging-punctuation: first last;
}

/* --------------------------------------------------------------------------
   4. Figures

   This is a stock system: almost every screen is a column of numbers that a
   human compares vertically. Proportional figures make that comparison
   actively harder, because a column of 1s is narrower than a column of 8s and
   the digits stop lining up.
   -------------------------------------------------------------------------- */

/*
 * Tabular everywhere digits stack or change in place. `.num` and `.metric`
 * were already covered in app.css; this widens the net to the places digits
 * appear without either class — form inputs the user types quantities into,
 * date pickers, and the DataTables paging control.
 */
input[type="number"],
input[type="date"],
input[type="datetime-local"],
input[type="time"],
.form-control[inputmode="numeric"],
.form-control[inputmode="decimal"],
.dataTables_info,
.dataTables_paginate,
.chip-count,
time {
	font-variant-numeric: tabular-nums;
}

/*
 * Slashed zero on every identifier. A chassis number is read aloud down a
 * phone line, copied onto a logbook, and typed into URA's portal. In most
 * grotesques the capital O and the figure 0 differ by a few percent of width
 * and nothing else — the single most expensive confusion this system can
 * cause. The slash makes it unambiguous, and costs nothing.
 */
.mono,
.serial,
code, kbd, samp, pre {
	font-variant-numeric: tabular-nums slashed-zero;
	font-feature-settings: "ss01" 1, "zero" 1;
}

/*
 * Money is set slightly heavier than its surroundings without changing size,
 * so a total reads as a total when the eye lands on it. Weight, not colour —
 * colour is reserved for meaning (overdue, low stock) elsewhere.
 */
.money-strong,
.doc-totals .value,
.metric-value {
	font-weight: 650;
	font-variant-numeric: tabular-nums lining-nums;
	letter-spacing: -.01em;
}

/* --------------------------------------------------------------------------
   5. Interface text

   Controls are not documents. Their labels are read in a glance-sized
   fixation, never a line at a time, so they take a touch more weight and a
   touch less tracking than body copy at the same size.
   -------------------------------------------------------------------------- */

.btn {
	font-weight: 560;
	letter-spacing: -.003em;
}

.form-label {
	font-weight: 540;
	letter-spacing: -.002em;
}

/*
 * Table headers are the map of the table. They earn weight and a hair of
 * positive tracking because they are set smaller than the rows beneath them.
 */
.table thead th {
	font-weight: 600;
	letter-spacing: .012em;
}

/* Chips carry a state word; they need to survive being read at 11–12px. */
.chip {
	font-weight: 560;
	letter-spacing: .004em;
}

/*
 * Numbers inside a keyboard-shortcut hint should not be mistaken for the
 * surrounding sentence, and a rendered key cap should look like a key cap.
 */
kbd {
	font-family: var(--font-mono);
	font-size: .875em;
	font-weight: 500;
}

/* --------------------------------------------------------------------------
   6. Hyphenation and overflow

   Serial numbers, model codes and Ugandan customer names all overflow narrow
   columns. Breaking them mid-glyph-run is better than a horizontal scrollbar,
   but only where the string is genuinely unbreakable.
   -------------------------------------------------------------------------- */

.break-anywhere,
.table td.mono,
.search-item .label {
	overflow-wrap: anywhere;
}

/* Never hyphenate an identifier — a hyphen inside a chassis number is a lie. */
.mono,
.serial,
code, kbd, samp, pre {
	hyphens: none;
}

/* --------------------------------------------------------------------------
   7. Print

   print.css already sets tabular figures on document tables. The one thing it
   cannot inherit is the slashed zero, and an invoice is exactly where a
   misread chassis number does lasting damage.
   -------------------------------------------------------------------------- */

@media print {
	.mono,
	.serial,
	.doc-table .mono {
		font-variant-numeric: tabular-nums slashed-zero;
	}
}

/* --------------------------------------------------------------------------
   8. Brand face hook

   Self-hosting, ready to switch on. Drop subset .woff2 files into
   custom/fonts/, uncomment, and add to includes/header.php:

     <link rel="preload" href="custom/fonts/brand-sans.woff2"
           as="font" type="font/woff2" crossorigin>

   Two rules keep this from ever causing layout shift:

     font-display: swap   — text paints immediately in the system face
     size-adjust / metric overrides — tuned so the system fallback occupies
                            the same box as the brand face, making the swap
                            invisible rather than a reflow

   Subset to U+0000-00FF plus the punctuation actually used; Latin Extended
   and the currency block are not needed for UGX.
   -------------------------------------------------------------------------- */

/*
@font-face {
	font-family: "Brand Sans";
	src: url("../fonts/brand-sans.woff2") format("woff2-variations");
	font-weight: 300 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+2000-206F, U+2212, U+2192;
}

@font-face {
	font-family: "Brand Sans Fallback";
	src: local("-apple-system"), local("Segoe UI"), local("Roboto");
	size-adjust: 100%;
	ascent-override: 90%;
	descent-override: 22%;
	line-gap-override: 0%;
}

:root {
	--font-sans: "Brand Sans", "Brand Sans Fallback", system-ui, sans-serif;
}
*/
