/* VENDORED from ~/Projects/ondsu-web/src/styles/tokens.css (2026-09-21).
 * The quiz is its own app on Vercel, so it carries a copy rather than importing
 * across repos. Change the site's file first, then re-copy here (font paths point
 * at assets/fonts/site/, and only the five faces the quiz uses are declared:
 * Trade Gothic Extended 400, Plex Sans 400/500, Plex Mono 400/500).
 * quiz.css holds everything quiz-specific and names roles only. */
/* ONDSU design tokens
 * Brand: 02 ONDSU/01 Brand/design.md. Font files: 02 ONDSU/01 Brand/Fonts.
 *
 * Design pass, 2026-09-15 (Joris): one system for colour, space, grid and type.
 * - Colour follows Kenan's Graphic Standards Rev 1.6, section 13: neutral greys,
 *   Signal Red, roles instead of values, a dark theme that is the same roles read
 *   the other way. Red Text stays for small orange type on light grounds.
 * - Space follows the standard's unit, U = 20 px: every layout distance is a whole
 *   number of units. Half a unit is allowed inside components only.
 * - The grid is the standard's measure made fluid: twelve columns (its six plus the
 *   columns between them) with a two-unit gutter, inside one page container.
 * - Type keeps the ONDSU rule: Trade Gothic Extended for titles, IBM Plex Sans for
 *   text that is read, IBM Plex Mono for labels, captions, data and controls.
 */

/* ---------------------------------------------------------------- fonts --- */
/* Three families and only these (Joris, 2026-09-15): Trade Gothic Extended for
 * display, in one weight; IBM Plex Sans for reading; IBM Plex Mono for labels and
 * data. The masters live in the vault at 02 ONDSU/01 Brand/Fonts, and the files in
 * /fonts are copies of its web folders. Add a face there first, then here.
 *
 * Trade Gothic Extended is the MyFonts webfont kit, build 3867246 (Linotype Trade
 * Gothic Std Extended, 2020), byte-identical to the kit file. The former "700" file
 * was a transfonter re-export of the same Regular outlines with the embedding flag
 * stripped, not a bold. It was removed on 2026-09-15; the two project-page titles
 * that asked for 700 now ask for 400 and render the same glyphs.
 * LICENCE: whether the kit's licence covers self-hosting on ondsu.com is still
 * UNVERIFIED. Resolve it before the site is served from anywhere but Webflow. */
@font-face {
  font-family: "Trade Gothic Extended";
  src: url("assets/fonts/site/trade-gothic-extended-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("assets/fonts/site/IBMPlexSans-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("assets/fonts/site/IBMPlexSans-Medium.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("assets/fonts/site/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("assets/fonts/site/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}

:root {
  /* ------------------------------------------------------------ colour --- */
  /* The palette (Graphic Standards 13). Components use the roles below; the only
   * direct uses are things that look the same on every ground: the pills, the bar,
   * the menu and the intro. */
  --black: #000000;
  --off-black: #141414;
  --anthracite: #2f2f2f;
  --charcoal: #4c4c4c;
  --dark-grey: #6c6c6c;
  --mid-grey: #8d8d8d;
  --grey-tone: #afafaf;
  --light-grey: #d3d3d3;
  --field-grey: #e5e5e5;
  --off-white: #f8f8f8;
  --white: #ffffff;
  --signal-red: #ff3c00;
  --red-text: #cc3000;

  /* Roles, light ground. Components use these. Dark and grey sections redefine them
   * below, so one rule reads correctly on every ground. */
  --ground: var(--off-white);      /* the page */
  --paper: var(--white);           /* a panel raised off the page */
  --field: var(--field-grey);      /* a band; the placeholder behind an image */
  --line: var(--light-grey);       /* rules and dividers, never type */
  --control: var(--dark-grey);     /* the outline of a control, 3:1 or better */
  --ink: var(--black);             /* type */
  --ink-2: var(--charcoal);        /* secondary type */
  --ink-3: var(--dark-grey);       /* captions, meta, labels */
  --accent: var(--signal-red);     /* rules, markers, large type, fills */
  --accent-text: var(--red-text);  /* orange type under 24 px on a light ground: 4.9:1 */
  --on-accent: var(--black);       /* type on an orange fill: 5.9:1; white fails */

  /* ------------------------------------------------------------- space --- */
  --u: 1.25rem;                              /* 20 px, the unit */
  --space-tiny: calc(var(--u) * 0.5);        /* inside components only */
  --space-small: var(--u);
  --space-medium: calc(var(--u) * 2);
  --space-large: calc(var(--u) * 3);
  --space-xlarge: calc(var(--u) * 6);
  --space-huge: calc(var(--u) * 10);
  --section-y: calc(var(--u) * 8);           /* a chapter */
  --top-offset: calc(var(--u) * 7);          /* first content under the fixed bar */

  /* -------------------------------------------------------------- grid --- */
  /* One container for every page. The content is at most 70 U (1400 px) wide,
   * with 3 U margins, down to 1 U on a phone. Sections stay full bleed and pad to
   * --page-pad, so their backgrounds run to the edges and every left edge agrees.
   * Twelve columns with a 2 U gutter; the standard's six columns are every second
   * line, so its 3 + 3, 4 + 2 and 2 + 4 splits all land on this grid. */
  --page-max: calc(var(--u) * 70);
  --page-margin: clamp(var(--u), 4vw, calc(var(--u) * 3));
  --page-pad: max(var(--page-margin), calc((100vw - var(--page-max)) / 2));
  --grid-gap: calc(var(--u) * 2);
  --measure: 38rem;                          /* a column of running text */
  --measure-s: 24rem;                        /* a caption or a short note */

  /* ------------------------------------------------------------- type --- */
  --font-display: "Trade Gothic Extended", "IBM Plex Sans", sans-serif;
  --font-body: "IBM Plex Sans", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* Titles: Trade Gothic Extended, capitals, from 20 px up. */
  --size-title-xl: clamp(2.5rem, 1.1rem + 5.9vw, 7rem);    /* opens a page */
  --size-title-l: clamp(2rem, 1.2rem + 3.4vw, 4.5rem);      /* a chapter */
  --size-title-m: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);    /* a block inside a chapter */
  --size-title-s: clamp(1.25rem, 1.1rem + 0.6vw, 1.5rem);   /* a card, a name */
  --title-xl: 400 var(--size-title-xl)/1 var(--font-display);
  --title-l: 400 var(--size-title-l)/1 var(--font-display);
  --title-m: 400 var(--size-title-m)/1.1 var(--font-display);
  --title-s: 400 var(--size-title-s)/1.15 var(--font-display);
  /* The tagline SPACE SOUND APPLIANCES: always the display face, capitals, no
   * punctuation, and the one display line allowed under 20 px (Joris, 2026-09-15). */
  --tagline: 400 0.8125rem/1 var(--font-display);
  --track-title: -0.02em;       /* xl and l */
  --track-title-s: 0.02em;      /* m and s */

  /* Text: IBM Plex Sans. Nothing that is read is set under 1rem. */
  --text-lead: 400 clamp(1.375rem, 1.1rem + 1.1vw, 2rem)/1.3 var(--font-body);
  --text-l: 400 clamp(1.125rem, 1.05rem + 0.3vw, 1.25rem)/1.5 var(--font-body);
  --text: 400 1.0625rem/1.6 var(--font-body);
  --text-s: 400 1rem/1.6 var(--font-body);

  /* Labels, captions, data and controls: IBM Plex Mono. */
  --mono-data: 400 1rem/1.5 var(--font-mono);        /* values: an address, a spec */
  --mono-ui: 400 0.875rem/1.45 var(--font-mono);     /* eyebrows, links, nav, buttons */
  --mono-caption: 400 0.8125rem/1.5 var(--font-mono); /* under a figure, fine print */
  --mono-tag: 400 0.75rem/1.4 var(--font-mono);      /* tags and meta, in capitals */
  --track-caps: 0.08em;         /* every mono capital */
}

/* A dark section is marked data-nav-dark-bg for the bar already; the same mark
 * gives it the dark roles (the standard's plate). .theme-dark is for dark surfaces
 * that are not sections: the menu, the skip link. */
[data-nav-dark-bg], .theme-dark {
  --ground: var(--black);
  --paper: var(--off-black);
  --field: var(--anthracite);
  --line: var(--anthracite);      /* the standard darkens to Charcoal; Anthracite keeps
                                     dark rules as quiet as light ones */
  --control: var(--mid-grey);
  --ink: var(--off-white);
  --ink-2: var(--grey-tone);
  --ink-3: var(--mid-grey);
  --accent-text: var(--signal-red); /* Signal Red passes on black: 5.9:1 */
}
/* A grey band, one half step under the page. Captions and rules step darker so they
 * still read on it. */
.theme-field {
  --ground: var(--field-grey);
  --line: var(--grey-tone);
  --control: var(--charcoal);
  --ink-3: var(--charcoal);
}
:where([data-nav-dark-bg], .theme-dark, .theme-field) { background-color: var(--ground); color: var(--ink); }

@media (max-width: 991px) {
  :root { --section-y: calc(var(--u) * 5); --grid-gap: var(--u); }
}
@media (max-width: 767px) {
  :root { --section-y: calc(var(--u) * 4); --top-offset: calc(var(--u) * 5); }
}

/* ------------------------------------------------------------- base --- */
*, *::before, *::after { box-sizing: border-box; }
/* Lenis drives smooth scrolling (see Base.astro); native scroll-behavior must
 * stay auto or the two fight. The reserved gutter stops the layout shifting
 * by a scrollbar width when the menu or the lightbox locks the page. */
html { scroll-behavior: auto; scrollbar-gutter: stable; }
/* No sideways panning on phones, ever. `clip`, not `hidden`: it does not make
 * the root a scroll container, so position: sticky and Lenis are unaffected. */
html, body { overflow-x: clip; }
/* Safari reveals the document canvas during rubber-band scrolling. Match the
 * footer on pages that have one; the shell paints the content ground separately. */
html:has(.footer-wrap), body:has(.footer-wrap) { background: var(--black); }
:where(section, header, main, [id]) { scroll-margin-top: calc(var(--u) * 5); }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: var(--text);
  -webkit-font-smoothing: antialiased;
}
:where(input, select, textarea, button) { font: inherit; color: inherit; }

/* Titles. Anything in the display face is set in capitals (Brand Decisions Log
 * 2026-05-06); the source text stays sentence case for screen readers. Pages
 * pick a smaller step where a heading is not a chapter title. */
.display, h1, h2, h3 { font-family: var(--font-display); font-weight: 400; text-transform: uppercase; }
h1 { font: var(--title-xl); letter-spacing: var(--track-title); }
h2 { font: var(--title-l); letter-spacing: var(--track-title); }
h3 { font: var(--title-m); letter-spacing: var(--track-title-s); }

/* The eyebrow above a title: mono, sentence case, secondary ink. */
.eyebrow { font: var(--mono-ui); color: var(--ink-2); margin: 0 0 var(--space-small); }

img { max-width: 100%; height: auto; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------- buttons --- */
/* Pills stay a brand shape (the standard's square controls are not adopted) and keep
 * one look on every ground: the plain pill is black, the primary pill is light
 * (outlined on a light ground, filled on a dark one). Mono capitals, one size.
 * Hover on the plain pill is Signal Red with black type: white on orange fails. */
.button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-tiny);
  font: var(--mono-ui); letter-spacing: var(--track-caps); text-transform: uppercase;
  text-decoration: none; text-align: center;
  padding: calc(var(--u) * 0.75) calc(var(--u) * 1.5);
  border: 2px solid var(--black); border-radius: 50px;
  background: var(--black); color: var(--off-white);
  cursor: pointer;
  transition: border-color 0.2s, color 0.2s, background-color 0.2s;
}
.button:hover { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.button--primary { background: var(--off-white); border-color: var(--black); color: var(--black); }
:is([data-nav-dark-bg], .theme-dark) .button--primary { border-color: var(--off-white); }
.button--primary:hover { background: var(--black); border-color: var(--black); color: var(--off-white); }
:is([data-nav-dark-bg], .theme-dark) .button--primary:hover { border-color: var(--off-white); }
.button--arrow::after {
  content: "→";
  color: var(--accent);
  transition: transform 0.24s ease, color 0.2s;
}
.button--arrow:hover::after { color: var(--on-accent); transform: translateX(0.25rem); }
@media (max-width: 479px) {
  .button--primary { min-width: calc(var(--u) * 11); }
}

/* ------------------------------------------------- underline links --- */
/* The ONDSU link convention (locked 2026-04-28): every text link carries
 * data-underline-link. No value = quiet, sweeps in on hover. "alt" = visible at
 * rest, sweeps out then back in. Recovered verbatim from the live Webflow head
 * block. CSS only, no JavaScript. Block-level card links and filled pills must
 * NOT carry the attribute: the rule below sets inline-block, which collapses a
 * block link and kills a pill's flex centring. */
[data-underline-link] { display: inline-block; text-decoration: none; position: relative; }
[data-underline-link]::before,
[data-underline-link="alt"]::before,
[data-underline-link="alt"]::after {
  content: ""; position: absolute; bottom: -0.0625em; left: 0;
  width: 100%; height: 0.0625em; background-color: currentColor;
  transition: transform 0.735s cubic-bezier(0.625, 0.05, 0, 1);
  transform-origin: right; transform: scaleX(0) rotate(0.001deg);
}
[data-underline-link="alt"]::before { transform-origin: left; transform: scaleX(1) rotate(0.001deg); transition-delay: 0.3s; }
[data-underline-link="alt"]::after { transform-origin: right; transform: scaleX(0) rotate(0.001deg); transition-delay: 0s; }
@media (hover: hover) and (pointer: fine) {
  [data-hover]:hover [data-underline-link]::before,
  [data-underline-link]:hover::before { transform-origin: left; transform: scaleX(1) rotate(0.001deg); }
  [data-hover]:hover [data-underline-link="alt"]::before,
  [data-underline-link="alt"]:hover::before { transform-origin: right; transform: scaleX(0) rotate(0.001deg); transition-delay: 0s; }
  [data-hover]:hover [data-underline-link="alt"]::after,
  [data-underline-link="alt"]:hover::after { transform-origin: left; transform: scaleX(1) rotate(0.001deg); transition-delay: 0.3s; }
}
/* Pills that carry the attribute keep their own layout and no sweep line. */
.button[data-underline-link] { display: inline-flex; align-items: center; justify-content: center; }
.button[data-underline-link]::before, .button[data-underline-link]::after { content: none; }

/* Trade mark (Graphic Standards Rev 1.6, naming rule 27.8). Only PX-System
   carries it, once per page at the first mention in the content; never in
   the nav, footer, meta or alt text. In a Trade Gothic title the mark is set
   at 0.5294 of the name (ink = 0.30 of the cap) and raised so its ink top
   sits on the cap line. In Plex text it stays at the sentence size: plain ™. */
.tm { font-size: 0.5294em; letter-spacing: 0; position: relative; top: -0.646em; line-height: 0; }

/* Keyboard focus (Graphic Standards 26.2): a 2 px accent outline on every
   interactive element, site-wide. Pills stay; the focus ring is the standard's. */
:is(a, button, input, select, textarea, summary, [tabindex]):focus-visible { outline: 2px solid var(--accent); outline-offset: var(--space-tiny); }
