/*
 * base.css
 * CLEAR-AUD — PeerView Repository Site
 *
 * Shared design token foundation for the whole site.
 * Contains ONLY: color primitives, typography primitives, spacing/size
 * tokens, utility classes, and the responsive container/animation system.
 * Do NOT add component or layout styles here — those belong in clear-aud.css.
 *
 * Brand is PeerView (Sofia Pro, blue/navy) — deliberately independent from
 * PeerVoice's shared assets.peervoice.com token set (DM Sans, teal). See
 * CLAUDE.md "Architecture" for why this site does not consume that file.
 *
 * Version : 1.3
 * Updated : 2026-09-30
 */

/* Sofia Pro — loaded via a <link rel="stylesheet"> in index.html's <head>
   (kit id kkn4bvf, 2026-09-28), not an @import here. Switched from
   courses.peerview.com's shared kit (zxt7ugs) to CLEAR-AUD's own
   dedicated kit, per direct instruction — Adobe Fonts kits are still
   domain-restricted regardless of kit id, so clear-aud.org's allowed-
   domains configuration should be verified for kkn4bvf specifically
   before production launch (see CLAUDE.md "Open items"). Poppins here is
   still the graceful-degradation fallback if the kit ever fails to load,
   so type never falls all the way to serif. */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');

/* ============================================================
   COLOR PRIMITIVES
   Pulled directly from the Figma file's published variables
   (node 161:615) — exact values, not eyeballed from screenshots.
   ============================================================ */
:root {
  /* Brand blues */
  --color-brand:              #0077BE; /* surface/surface-brand */
  --color-link:                #009FE3; /* text/hyperlink, border/border-hyperlink */
  --color-link-hover:           #064B69;
  --color-link-active:          #161A2E;
  --color-navy:                #161A2E; /* surface/surface-invert */
  --color-light-blue:           #E5F1F8; /* surface/surface-light-blue */
  --color-mid-blue:             #BFDDEF; /* surface/surface-mid-blue, border-secondary */
  --color-hero-wordmark:         #4280A5; /* one-off, direct spec (2026-09-30) — not in the Figma palette above, used only by .ca-hero__wordmark */

  /* Neutrals */
  --color-surface-primary:      #FAFAFA;
  --color-surface-secondary:    #FFFFFF;
  --color-surface-positive:     #DBEBE5;
  --color-text-primary:         #000000;
  --color-text-secondary:       #6E6E6E;
  --color-text-light:           #CECECE;
  --color-text-invert:          #FFFFFF;
  --color-border-midgray:       #CECECE;
  --color-negative:             #B6415A; /* text/text-negative — promo badge red */

  /* Buttons */
  --color-button-primary:       #009FE3;
  --color-button-ghost:         #FFFFFF;
}

/* ============================================================
   TYPOGRAPHY PRIMITIVES
   Font families, a linear size scale, and weight aliases.
   ============================================================ */
:root {
  --typography-family-title: "sofia-pro", "Poppins", sans-serif;
  --typography-family-body:  "sofia-pro", "Poppins", sans-serif;

  --typography-scale-xs:  12px;
  --typography-scale-sm:  14px;
  --typography-scale-base:16px;
  --typography-scale-md:  18px;
  --typography-scale-lg:  20px;
  --typography-scale-xl:  30px;

  --typography-weight-regular:  400;
  --typography-weight-semibold: 600;
  --typography-weight-bold:     700;
}

/* ============================================================
   SIZE & SPACING PRIMITIVES
   ============================================================ */
:root {
  --size-space-0:   0px;
  --size-space-2xs: 8px;
  --size-space-xs:  12px;
  --size-space-sm:  16px;
  --size-space-md:  24px;
  --size-space-lg:  40px;
  --size-space-2xl: 80px;

  --size-radius-minimal: 4px;
  --size-radius-rounded: 16px;
  --size-radius-full:    40px;

  --transition-fast: 150ms ease;
  --transition-base:  250ms ease;
  --transition-slow:  400ms ease;
  --transition-carousel: 350ms cubic-bezier(0.4, 0, 0.2, 1);
  --carousel-gap: 16px;
}

/* ============================================================
   RESET
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--typography-family-body);
  font-size: var(--typography-scale-base);
  font-weight: var(--typography-weight-regular);
  color: var(--color-text-primary);
  background: var(--color-surface-secondary);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img { max-width: 100%; display: block; }
button { font-family: inherit; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, h5, h6 { margin: 0; font-family: var(--typography-family-title); }
/* p was missing from this reset — every <p> site-wide was carrying the
   browser default ~1em top+bottom margin unless a component rule
   happened to override both sides explicitly. Most looked fine only by
   accident (block spacing elsewhere masked it); it became visibly wrong
   in the hero carousel slide, where several stacked <p>s (date,
   subtitle, location) compounded into a large, uneven gap instead of the
   tight flex `gap` the component CSS actually specifies. */
p { margin: 0; }
/* Standard "safe" sup/sub reset — the browser default (vertical-align:
   super/sub) inflates the whole line's height to fit the raised glyph on
   top of the normal line, which visibly drops a link's baseline out of
   alignment with sibling links that don't contain one (this showed up in
   the sub-nav's "Project ECHO®" vs. its neighbors). line-height:0 removes
   the sup/sub from the line-height calculation entirely; position:relative
   + top does the visual raise/drop instead of vertical-align. */
sup, sub { font-size: 0.7em; line-height: 0; position: relative; vertical-align: baseline; }
sup { top: -0.5em; }
sub { top: 0.3em; }

/* ============================================================
   TEXT UTILITY CLASSES
   Apply directly via class="" — never write raw font-size/family/weight
   in clear-aud.css component rules (see docs pattern in Hub_Curriculum).
   ============================================================ */
.TitleXLarge   { font-family: var(--typography-family-title); font-size: var(--typography-scale-xl);   font-weight: var(--typography-weight-semibold); line-height: 1.2; }
.TitleLarge    { font-family: var(--typography-family-title); font-size: var(--typography-scale-lg);   font-weight: var(--typography-weight-semibold); line-height: 1.2; }
.TitleMedium   { font-family: var(--typography-family-title); font-size: var(--typography-scale-md);   font-weight: var(--typography-weight-semibold); line-height: 1.2; }
.TitleSmall    { font-family: var(--typography-family-title); font-size: var(--typography-scale-sm);   font-weight: var(--typography-weight-semibold); line-height: 1.4; }
.TitleBase     { font-family: var(--typography-family-title); font-size: var(--typography-scale-base); font-weight: var(--typography-weight-semibold); line-height: 1.4; }

.BodyBase      { font-family: var(--typography-family-body); font-size: var(--typography-scale-base); font-weight: var(--typography-weight-regular);  line-height: 1.4; }
.BodyBaseMedium{ font-family: var(--typography-family-body); font-size: var(--typography-scale-base); font-weight: var(--typography-weight-semibold); line-height: 1.4; }
.BodySmall     { font-family: var(--typography-family-body); font-size: var(--typography-scale-sm);   font-weight: var(--typography-weight-regular);  line-height: 1.4; }
.BodySmallMedium{ font-family: var(--typography-family-body); font-size: var(--typography-scale-sm);  font-weight: var(--typography-weight-semibold); line-height: 1.4; }
.BodyXSmall    { font-family: var(--typography-family-body); font-size: var(--typography-scale-xs);   font-weight: var(--typography-weight-regular);  line-height: 1.4; }
.BodyXSmallMedium{ font-family: var(--typography-family-body); font-size: var(--typography-scale-xs); font-weight: var(--typography-weight-semibold); line-height: 1.4; }

.SingleLine { line-height: 1; }

/* ============================================================
   CONTAINER + RESPONSIVE PADDING
   ============================================================ */
/* max-width is 1440 (the Figma frame width), not 1280 (the content
   width) — box-sizing:border-box means padding-inline eats into
   max-width, so 1440 - 2*80px padding = 1280px actual content width,
   matching the mockup exactly. Setting max-width to 1280 directly (an
   earlier bug) instead left only 1120px of content, visibly narrower
   than the mockup at desktop widths. */
.container {
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: var(--size-space-2xl); /* 80px, xl */
}
@media (max-width: 1279px) { .container { padding-inline: var(--size-space-lg); } }    /* 40px, lg — see responsive.md note; tuned during polish pass */
@media (max-width: 767px)  { .container { padding-inline: var(--size-space-md); } }    /* 24px, md/sm */
@media (max-width: 479px)  { .container { padding-inline: var(--size-space-sm); } }    /* 16px, sm */

/* ============================================================
   ENTRY ANIMATIONS (load-on-scroll)
   Driven by IntersectionObserver in ca-animations.js. Ported 2026-09-28
   from AnswersInCME's Get In Touch page (per direct request — ported into
   demo/ first, not yet the real site) — ca-animations.js used to add
   `is-visible` once and never remove it; now it toggles both ways, so
   scrolling back up and back down replays the reveal instead of leaving
   everything sitting fully visible after the first pass. That's why this
   uses `transition` (which animates cleanly in both directions off a
   class toggle), not the old `animation: ... both` keyframe approach
   (which only plays forward and just snaps back to the base opacity:0
   state the instant the class is removed — fine for a one-shot reveal,
   wrong for a replay).
   ============================================================ */
.animate-on-enter {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.animate-on-enter.is-visible {
  opacity: 1;
  transform: translateY(0);
}
.animate-on-enter--fade {
  transform: none;
}
.animate-on-enter--fade.is-visible {
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .animate-on-enter {
    transition: none;
    opacity: 1;
    transform: none;
  }
}

/* Heading letter glide-in (ca-animations.js's initHeadingFlyIn()) — every
   character of a flagged heading swims in from the right, one after
   another left to right (a trailing school-of-fish motion, not letters
   converging from opposite sides). The slight overshoot easing on
   .fly-letter is what reads as a swim rather than a mechanical slide.
   Opt-in via [data-fly-in] on the heading element, not automatic on every
   heading — see CLAUDE.md for which ones use it. */
.fly-word {
  display: inline-block;
  white-space: nowrap;
}
.fly-letter {
  display: inline-block;
  opacity: 0;
  transform: translateX(30px);
  transition: opacity 0.5s ease, transform 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}
.fly-letter.is-visible {
  opacity: 1;
  transform: translateX(0);
}
@media (prefers-reduced-motion: reduce) {
  .fly-letter {
    transition: none;
    opacity: 1;
    transform: none;
  }
}

/* ============================================================
   PAGE LOADER
   Covers the page until content renders — avoids the empty-skeleton
   flash between first paint and ca:ready. See ca-loader.js.
   ============================================================ */
.page-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: var(--color-navy);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--size-space-sm);
  transition: opacity var(--transition-slow), visibility var(--transition-slow);
}
.page-loader__logo { width: 160px; }
.page-loader__spinner {
  width: 32px;
  height: 32px;
  border: 3px solid var(--color-mid-blue);
  border-top-color: var(--color-link);
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.page-loader.is-done {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .page-loader__spinner { animation-duration: 1600ms; }
}

/* ============================================================
   ACCESSIBILITY — FOCUS RINGS
   ============================================================ */
.hs-focus-ring:focus-visible,
a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--color-link);
  outline-offset: 2px;
}
.ca-focus-ring--on-dark:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
}

/* Visually-hidden but screen-reader accessible */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
