/**
 * New York City Scholars — Design System
 * Reference: docs/design-system.md
 * Source: https://brand.northeastern.edu/design-and-experiences/digital/
 *
 * This file loads before css/style.css (see functions.php). It defines the
 * token layer plus a small set of net-new component classes. It does not
 * override existing style.css rules directly — those are normalised in
 * place in style.css itself so the two layers never fight the cascade.
 */

/**
 * Button standard — confirmed against four live northeastern.edu reference
 * screenshots: a dark-hero pill pair ("Find your event" / "Watch
 * livestreams", default = outline/white), the same pair on hover (solid
 * red fill), and a light-background pill pair ("Read more coverage" /
 * "Get NGN in your inbox", default = solid black). .c-btn-primary is
 * context-aware as a result — see style.css for the full rule set:
 *
 *   .c-btn-primary                    Light-bg default: solid black fill,
 *                                      white text (21:1 — comfortably AA).
 *   .c-btn-primary.c-btn-color-alt     Dark-bg default: solid white fill,
 *                                      black text. Use on any panel that
 *                                      sits on --nu-cool-black or similar
 *                                      (e.g. .block-ls-hero's primary CTA).
 *   .c-btn-primary.c-btn-color-normal  Escape hatch — forces the original
 *                                      always-red look. Markup for the five
 *                                      pre-existing .c-btn-primary usages
 *                                      already carried this class before
 *                                      the context-aware default existed,
 *                                      so their appearance is unchanged.
 *   :hover (all three)                 Fills solid --color-brand-red, text
 *                                      flips to white for contrast — this
 *                                      is the one accent moment per spec
 *                                      §3.1 ("red... to highlight important
 *                                      elements — e.g. button highlights").
 *                                      .c-btn-color-normal:hover keeps the
 *                                      original --color-brand-red-dark to
 *                                      match its pre-existing behavior.
 *   Animation                          The trailing arrow (.c-btn-icon >
 *                                      .icon-arrow-right) nudges right 4px
 *                                      on hover — generalised from
 *                                      .c-btn-tertiary-only to every .c-btn
 *                                      variant via `.c-btn:hover .c-btn-icon`.
 *   Shape/height                       Pill (--radius-pill), min-height
 *                                      ~5.9rem — measured against a live
 *                                      .wp-block-button.is-style-black-button
 *                                      (228.95×58.8px). An earlier pass
 *                                      briefly normalised to a rounded
 *                                      rectangle against a single "Apply
 *                                      Now" reference — reverted; pill is
 *                                      correct.
 *   Weight                             var(--weight-medium) (500) — scaled
 *                                      down from bold (700). 500 is one of
 *                                      the two weights ff-real-headline-pro
 *                                      actually ships (see docs/next_steps.txt
 *                                      ISSUE-45), so this avoids browser
 *                                      faux-bold/light synthesis.
 *
 * .c-btn-secondary is unchanged by this pass — still red-bordered by
 * default, .c-btn-color-alt for white-on-dark, hover fills
 * --color-brand-red-dark (not yet aligned to the plain-red hover above;
 * flagged as a follow-up if full consistency is wanted later).
 */
:root {
  /* Brand */
  --color-brand-red: #C8102E;
  --color-brand-red-dark: #A50E26;
  --color-brand-red-visited: #6B0000;
  --color-brand-black: #000000;
  --color-brand-white: #FFFFFF;

  /* Supporting (spec §3.1.2) — prefer over pure white/black in the redesign */
  --nu-canvas: #F6F6F4;
  --nu-cool-black: #1E2028;

  /* Digital neutral ramp (spec §3.1.3) */
  --color-grey-900: #17191F;
  --color-grey-800: #1E2028;
  --color-grey-700: #49494D;
  --color-grey-300: #E0E0E0;
  --color-grey-200: #EBEBEB;
  --color-grey-100: #F5F5F5;

  /* Retained AA-safe mid grey (min 4.5:1 on white — used by existing style.css) */
  --color-grey-500: #767676;

  /* Status */
  --color-success: #2D7D32;
  --color-warning: #E65100;
  --color-error: #B71C1C;

  /* Typography */
  --font-display: "FF Real Head", "ff-real-headline-pro", "Lato", Arial, sans-serif;
  --font-body: "FF Real Head", "ff-real-headline-pro", "Lato", Arial, sans-serif;
  --font-mono: "Courier New", Courier, monospace;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 1.875rem;
  --text-4xl: 2.25rem;
  --text-5xl: 3rem;

  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.625;

  --weight-light: 300;
  --weight-medium: 500;
  --weight-bold: 700;

  /* Spacing (4px base grid).
     Declared in px, not rem: style.css:703 sets html { font-size: 62.5% }, so
     1rem is 10px here and the previous rem values rendered at 62.5% of their
     names -- --space-4 was 10px, not 16px, and --space-1 was a 2.5px subpixel.
     px also keeps this scale correct if the 62.5% declaration ever changes. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;

  /* Shape */
  --radius-input: 4px;
  /* Pill IS correct for .c-btn-primary/.c-btn-secondary — confirmed against
     two live northeastern.edu reference screenshots (a pill "Find your
     event / Watch livestreams" pair, and a measured
     div.wp-block-button.is-style-black-button at 228.95×58.8px). An earlier
     pass in this file briefly normalised .c-btn to a rounded-rectangle
     (--radius-button: 8px) against a different single reference image
     ("Apply Now") — that was wrong and has been reverted. The canonical
     NEU button is: pill shape, trailing arrow icon (.c-btn-has-icon +
     .c-btn-icon > .icon-arrow-right, both already in style.css), min-height
     ~5.9rem (the 58.8px measured value). */
  --radius-pill: 999px;
  --radius-modal: 10px;
  --radius-image: 0; /* spec §3.6 — images have squared corners */

  /* Focus */
  --focus-ring: 2px solid var(--color-brand-red);
  --focus-ring-offset: 2px;

  /* Motion.
     ---------------------------------------------------------------------
     This block is the single source of truth for motion, for CSS *and* for
     JS. js/anim.js reads these tokens once at boot with a single
     getComputedStyle(document.documentElement) call and parses the beziers
     into arrays for Motion; it no longer keeps its own copy of the numbers.
     Retuning the whole site is therefore an edit to this block alone.

     (An earlier revision duplicated the values as constants in anim.js, on
     the grounds that reading them would cost "a layout read per element".
     That was true of a per-element read; it is not true of one read at
     init, before any observer exists and with nothing to invalidate. Each
     constant still carries a literal fallback in anim.js so a missing or
     unparseable token degrades to the previous behaviour rather than NaN.)

     Declared in ms, not the rem scale, so unlike --space-* these are not
     affected by style.css:703's html{font-size:62.5%}. */

  /* Micro-states. Unchanged — 160ms and 240ms are the two values style.css
     already hard-codes most often, so these remain a rename, not a
     retiming. */
  --duration-fast: 160ms; /* hover fill, colour shifts */
  --duration-base: 240ms; /* expand/collapse, panel fades */
  --duration-slow: 400ms; /* drawer and overlay movement */

  /* Reveals. 520ms at 16px sat below the perception threshold: present but
     unnoticeable, which is what made the reveal layer read as generic. */
  --duration-reveal: 720ms; /* scroll reveals */
  --duration-reveal-lg: 980ms; /* rise, clip-up, lines — the big moves */
  --duration-hover-media: 640ms; /* card image zoom; see anim.css */

  /* Asymmetric easings only — linear and ease-in-out read as mechanical.

     --ease-out is expo-out. It is kept for micro-states, where the short
     duration is exactly what makes expo work, but it is deliberately NOT
     used for reveals any more: over 720ms it covers 95% of its travel in
     the first ~250ms and then sits visually motionless for the remaining
     470ms, which reads as a stall rather than as a settle. --ease-reveal
     is quartOut, which keeps a perceptible tail across the full duration. */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-reveal: cubic-bezier(0.25, 1, 0.5, 1);

  /* Reveal geometry. The suffix on a directional preset (fade-up,
     fade-left…) is the direction of TRAVEL, not the side of origin —
     fade-up starts below and moves upward. */
  --anim-distance: 28px; /* the default travel */
  --anim-distance-sm: 16px; /* secondary/nested elements, fade-down */
  --anim-distance-lg: 42px; /* rise — full-bleed panels only */
  --anim-stagger: 90ms;
  --anim-stagger-tight: 50ms;

  /* Elevation. Two layers on purpose: a single large-blur shadow reads as a
     glow, whereas a tight contact shadow under a wider ambient one reads as
     an object above a surface. Consumed by the card hover in anim.css. */
  --shadow-0: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-1: 0 2px 6px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-2: 0 10px 28px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.05);
}

/* ---------------------------------------------------------------------------
   Components
   --------------------------------------------------------------------------- */

/* TextLink.

   The underline is drawn as a ::after rule rather than with
   text-decoration, because text-decoration cannot be animated. The
   transform-origin flips between the rest and hover states so the rule
   wipes in from the left and back out to the right, passing through the
   link, instead of retracting the way it came. That asymmetry is most of
   what separates this from a plain underline, and it costs one
   compositor-only scaleX. */
.c-link {
  position: relative;
  color: var(--color-brand-red);
  text-decoration: none;
}

.c-link::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--duration-base) var(--ease-out);
}

.c-link:hover,
.c-link:focus-visible {
  color: var(--color-brand-red-dark);
}

.c-link:hover::after,
.c-link:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

.c-link:visited {
  color: var(--color-brand-red-visited);
}

.c-link:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-ring-offset);
}

/* In forced-colors mode the ::after background is stripped, so the link
   would lose its affordance entirely — the one case where a real
   text-decoration has to come back. */
@media (forced-colors: active) {
  .c-link:hover,
  .c-link:focus-visible {
    text-decoration: underline;
  }

  .c-link::after {
    display: none;
  }
}

/* Input / Select — net-new utilities. The existing .search-form__input is an
   intentional large-format display search field and is exempt from this
   generic spec (see docs/design-system.md). */
.c-input,
.c-select {
  height: 44px;
  padding: 0 var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-base);
  color: var(--color-grey-900);
  border: 1px solid var(--color-grey-300);
  border-radius: var(--radius-input);
  background: var(--color-brand-white);
}

.c-input:focus,
.c-select:focus {
  border: 2px solid var(--color-brand-red);
  outline: none;
}

.c-input[aria-invalid="true"],
.c-select[aria-invalid="true"] {
  border-color: var(--color-error);
}

/* Eyebrow — all-caps kicker above a headline. Spec §3.4: sentence case is
   required for headlines; all-caps is reserved for eyebrows only. Markup
   stays sentence case so screen readers don't spell it out; this class
   applies the visual transform. */
.c-eyebrow {
  display: block;
  font-family: var(--font-body);
  font-weight: var(--weight-bold);
  /* NOTE: the --text-* scale is declared in rem assuming a 16px root and is
     not corrected for style.css:703's html{font-size:62.5%} (1rem=10px) —
     the same discrepancy the --space-* comment above documents for spacing.
     Sized in rem directly here (10px base) to match every other rem value
     in style.css (e.g. h1 at 6rem) instead of inheriting that mismatch. */
  font-size: 1.4rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Hero — applied to .search-hero (parts/search/hero.php) and .block-ls-hero
   (parts/elements/hero-split.php) only. Other hero variants (.hero-staff,
   .hero-news, .block-hero-programs) are out of scope for this phase; see
   docs/design-system.md "Follow-up phases". */
.search-hero {
  position: relative;
  padding: var(--space-16) 0;
  background-color: var(--color-grey-100);
}

@media (max-width: 767px) {
  .search-hero {
    padding: var(--space-10) 0;
  }
}
