/* ==========================================================================
   10-BASE.CSS — reset, base typography, accessibility primitives.
   Depends on 00-tokens.css. Contains no literal design values.
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* 1rem = 16px. Never overridden: body copy must not shrink. */
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Sticky header offset for in-page anchors. */
  scroll-padding-top: calc(var(--header-height-sticky) + var(--space-md));
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background-color: var(--color-background);
  color: var(--color-text-secondary);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  font-weight: var(--font-weight-regular);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Guards against any child overflowing and creating a horizontal scrollbar
     without hiding it globally, which would break position: sticky. */
  overflow-wrap: break-word;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
  color: var(--color-text-primary);
  /* --font-heading exists ONLY so the Design tab's "editorial" preset can give
     headings a serif without touching body copy. It is unset by default, so this
     resolves to --font-sans and an untouched install renders identically. */
  font-family: var(--font-heading, var(--font-sans));
  font-weight: var(--font-weight-bold);
  line-height: var(--leading-heading);
  text-wrap: balance;
}

h1 {
  font-size: var(--text-h1);
  letter-spacing: var(--tracking-display);
}

h2 {
  font-size: var(--text-h2);
}

h3 {
  font-size: var(--text-h3);
  font-weight: var(--font-weight-semibold);
}

p,
ul,
ol,
dl,
figure,
blockquote {
  margin: 0;
}

/* Body prose keeps a readable measure wherever it appears. */
.u-prose {
  max-width: var(--measure-body);
}

.u-prose > * + * {
  margin-top: var(--space-md);
}

a {
  color: var(--color-primary-500);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--transition-base);
}

a:hover {
  color: var(--color-primary-700);
}

img,
picture,
svg,
video,
iframe {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Every image frame declares a ratio, so layout shift is structurally
   impossible regardless of when the file loads. */
.c-media {
  position: relative;
  overflow: hidden;
  margin: 0;
  border-radius: var(--radius-md);
  background-color: var(--color-surface-alt);
}

.c-media--hero { aspect-ratio: var(--ratio-hero); }
.c-media--wide { aspect-ratio: var(--ratio-wide); }
.c-media--faculty { aspect-ratio: var(--ratio-faculty); }
.c-media--faculty-portrait { aspect-ratio: var(--ratio-faculty-portrait); }
.c-media--faculty-card { aspect-ratio: var(--ratio-faculty-card); }
.c-media--portrait { aspect-ratio: var(--ratio-portrait); }
.c-media--map { aspect-ratio: var(--ratio-map); }

.c-media__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Natural variant: no ratio is imposed, so the frame takes the photograph's own
   proportions and nothing is cropped. For images where the composition is the
   content — a group of people, where the edges are not padding, or a portrait
   whose subject fills the frame — a uniform frame is the wrong trade.

   Two photographs use it, both for the same reason:
     About      1080x705 (1.53:1). Forcing 21:9 kept 65.7% of the height and cut
                people out of the top and bottom edges.
     Principal  724x779 (0.93:1). The 'tdc-principal' size is a 600x750 hard
                crop, so requesting it trimmed the frame in the file itself.

   Height is auto here, so the frame is whatever the image is. */
.c-media--natural {
  aspect-ratio: auto;
}

.c-media--natural .c-media__img {
  width: 100%;
  height: auto;
  /* contain, never cover: if any future rule constrains this frame's height,
     the image must letterbox inside it rather than crop to fill it. */
  object-fit: contain;
}

/* Faculty portraits: never crop the head. This targets the LANDSCAPE 3:2 frame,
   which the gallery strip uses. The faculty card's own portrait frame sets its
   own object-fit/object-position pair — see .c-faculty__photo. */
.c-media--faculty .c-media__img {
  object-position: top center;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* --------------------------------------------------------------- focus ---
   A visible ring on everything focusable. :focus-visible for pointer users,
   with a :focus fallback for older engines. outline is never removed without
   an equally visible replacement. */
:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-sm);
}

/* Dark bands need the gold ring to stay visible against navy. */
.is-on-dark :focus-visible,
.c-utility :focus-visible,
.c-header__bar :focus-visible,
.c-hero :focus-visible,
.c-cta :focus-visible,
.c-footer :focus-visible {
  outline-color: var(--focus-color-on-dark);
}

/* Focus rings inside overflow-hidden image frames are inset so they are not
   clipped by the frame. */
.c-media :focus-visible {
  outline-offset: calc(var(--focus-offset) * -1);
}

/* --------------------------------------------------------- skip link ---
   First focusable element on the page. */
.c-skip-link {
  position: absolute;
  left: var(--space-md);
  top: var(--space-md);
  z-index: var(--z-overlay);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  background-color: var(--color-primary-700);
  color: var(--color-text-on-dark);
  font-size: var(--text-ui);
  font-weight: var(--font-weight-semibold);
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--transition-base);
}

.c-skip-link:focus {
  transform: translateY(0);
  color: var(--color-text-on-dark);
}

/* Visually hidden but available to assistive technology. */
.u-visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Minimum touch target, applied wherever a control could otherwise be small. */
.u-tap-target {
  min-width: var(--tap-target);
  min-height: var(--tap-target);
}

/* Centre a block's inline content. Available for any block that needs it; the
   homepage faculty "view all" link no longer uses it — it is left-aligned with
   the cards above it, for the reason recorded on .c-faculty-showcase__more. */
.u-text-center {
  text-align: center;
}

/* Standard gap above a block that follows another. Replaces one-off inline
   margin declarations in templates. */
.u-mt-md {
  margin-block-start: var(--space-md);
}

.u-mt-lg {
  margin-block-start: var(--space-lg);
}

.u-mt-xs {
  margin-block-start: var(--space-xs);
}

/* Small, de-emphasised metadata line (post dates, counts). */
.u-meta {
  font-size: var(--text-xs);
  color: var(--color-text-muted);
}

[hidden] {
  display: none !important;
}

/* Reduced motion: durations are already neutralised in 00-tokens.css. This
   removes any remaining declarative animation while leaving all content
   visible and every control operable. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
}
