/* ==========================================================================
   taylordwyer.com — design system
   Tokens first, then primitives, then components. Nothing here is generated;
   edit this file directly. Token rules and contrast notes: DESIGN-SYSTEM.md
   ========================================================================== */

/* --- Tokens: color ------------------------------------------------------ */
:root {
  /* Brand (from the approved 5-color Notion palette) */
  --c-steel: #3e5c76;     /* primary — headings, nav, dark sections   7.0:1 on white */
  --c-steel-800: #2e4659; /* pressed / darker steel                             */
  --c-steel-050: #eef2f6; /* tinted section background                          */

  --c-ember: #c05a2e;     /* brand accent — DECOR ONLY (rules, marks, borders)
                             4.43:1 on white, so it must never carry text       */
  --c-ember-600: #ba5429; /* accent TEXT + button fill        4.79:1 — AA pass  */
  --c-ember-800: #8f4220; /* hover / pressed                  7.3:1             */
  --c-ember-050: #fbf1eb; /* accent wash                                        */

  --c-ink: #111111;       /* body copy                                          */
  --c-ink-600: #4a5158;   /* muted copy                      7.4:1 on white     */

  --c-silver: #b0bec5;    /* decorative only — never text on white              */
  --c-silver-050: #f5f7f9;/* page alt background                                */
  --c-rule: #dde3e8;      /* hairlines, input borders                           */

  --c-paper: #ffffff;

  /* Semantic aliases — components reference these, not raw brand names.
     This indirection is what makes the dark theme at the bottom of this file
     a token swap instead of a rewrite. Adding a raw hex to a component
     defeats it. */
  color-scheme: light dark;

  --bg: var(--c-paper);
  --bg-alt: var(--c-silver-050);
  --bg-tint: var(--c-steel-050);
  --bg-invert: var(--c-steel);
  --surface: var(--c-paper);          /* cards, inputs — sits on --bg      */
  --header-bg: rgba(255, 255, 255, 0.94);
  --footer-bg: var(--c-steel-800);
  --callout-bg: var(--c-ember-050);
  --input-border: var(--c-silver);

  --text: var(--c-ink);
  --text-muted: var(--c-ink-600);
  --text-invert: #f2f6f9;
  --heading: var(--c-steel);
  --on-accent: #ffffff;               /* text on an accent-filled button   */

  --accent: var(--c-ember-600);
  --accent-hover: var(--c-ember-800);
  --accent-decor: var(--c-ember);
  --accent-on-dark: #f4c6ae;          /* accent text inside dark sections  */
  --rule: var(--c-rule);
  --focus: var(--c-ember-800);

  --danger: #b3261e;
  --danger-bg: #fdecea;
}

/* --- Tokens: type ------------------------------------------------------- */
:root {
  /* No webfonts: zero network cost, no CLS, no third-party request.
     Serif display reads "educator"; sans body reads "clear". */
  --font-display: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
    Georgia, "Times New Roman", serif;
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;

  /* Fluid scale, ~1.25 ratio at both ends */
  --t-xs: 0.8125rem;
  --t-sm: 0.9375rem;
  --t-base: 1.0625rem;
  --t-md: clamp(1.125rem, 0.3vw + 1.06rem, 1.25rem);
  --t-lg: clamp(1.35rem, 0.7vw + 1.2rem, 1.65rem);
  --t-xl: clamp(1.7rem, 1.4vw + 1.4rem, 2.25rem);
  --t-2xl: clamp(2.1rem, 2.4vw + 1.6rem, 3rem);
  --t-3xl: clamp(2.5rem, 3.6vw + 1.7rem, 4rem);

  --lh-tight: 1.15;
  --lh-snug: 1.3;
  --lh-body: 1.65;

  --w-normal: 400;
  --w-medium: 500;
  --w-bold: 700;

  --track-caps: 0.09em;
}

/* --- Tokens: space, shape, motion --------------------------------------- */
:root {
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;

  --measure: 68ch;          /* max line length for prose */
  --width-page: 1120px;
  --width-narrow: 760px;
  --gutter: clamp(1.25rem, 5vw, 3rem);

  --r-sm: 3px;
  --r-md: 6px;
  --r-lg: 12px;

  --shadow-1: 0 1px 2px rgba(17, 17, 17, 0.06), 0 2px 8px rgba(17, 17, 17, 0.05);
  --shadow-2: 0 2px 6px rgba(17, 17, 17, 0.07), 0 12px 28px rgba(17, 17, 17, 0.08);

  --dur-fast: 120ms;
  --dur-base: 200ms;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);
}

/* --- Reset -------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--w-normal) var(--t-base) / var(--lh-body) var(--font-body);
  text-rendering: optimizeLegibility;
}
img, svg, video { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--w-bold);
  line-height: var(--lh-tight);
  color: var(--heading);
  margin: 0 0 var(--s-4);
  text-wrap: balance;
}
h1 { font-size: var(--t-3xl); letter-spacing: -0.015em; }
h2 { font-size: var(--t-2xl); letter-spacing: -0.01em; }
h3 { font-size: var(--t-lg); }
h4 { font-size: var(--t-md); }
p, ul, ol { margin: 0 0 var(--s-4); }
p { max-width: var(--measure); }
a { color: var(--accent); text-underline-offset: 0.18em; }
a:hover { color: var(--text); }
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
hr { border: 0; border-top: 1px solid var(--rule); margin: var(--s-7) 0; }

/* --- Layout primitives -------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--width-page);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: var(--width-narrow); }
.section { padding-block: clamp(var(--s-7), 7vw, var(--s-9)); }
.section--tight { padding-block: var(--s-7); }
.section--alt { background: var(--bg-alt); }
.section--tint { background: var(--bg-tint); }
.section--invert { background: var(--bg-invert); color: var(--text-invert); }
.section--invert h1,
.section--invert h2,
.section--invert h3 { color: #ffffff; }
.section--invert a { color: var(--accent-on-dark); }

.grid { display: grid; gap: var(--s-6); }
@media (min-width: 720px) {
  .grid--2 { grid-template-columns: repeat(2, 1fr); }
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}
.stack > * + * { margin-top: var(--s-4); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center; }

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: var(--w-bold);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 var(--s-3);
}
.lede { font-size: var(--t-md); color: var(--text-muted); }
/* A run of names read as a list without the bullets and vertical cost of one. */
.namelist {
  font-family: var(--font-display);
  font-size: var(--t-lg);
  line-height: var(--lh-snug);
  color: var(--heading);
  max-width: 40ch;
  margin-bottom: var(--s-5);
}
.muted { color: var(--text-muted); }

/* --- Component: credits (program, role, years) --------------------------- */
/* Denser than a card grid and more informative than a bare list of names:
   every row carries a program, a role, and a span of time. */
.credits {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-5);
  border-top: 1px solid var(--rule);
  max-width: var(--measure);
}
.credits li {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-5);
  align-items: baseline;
  justify-content: space-between;
  padding-block: var(--s-3);
  border-bottom: 1px solid var(--rule);
}
.credits__what { flex: 1 1 20rem; }
.credits__what strong { color: var(--heading); }
.credits__role { display: block; font-size: var(--t-sm); color: var(--text-muted); }
.credits__year {
  font-size: var(--t-sm);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
.skip-link {
  position: absolute; left: var(--s-4); top: -4rem; z-index: 100;
  background: var(--bg-invert); color: #fff; padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md); transition: top var(--dur-base) var(--ease);
}
.skip-link:focus { top: var(--s-4); color: #fff; }

/* --- Component: button -------------------------------------------------- */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--on-accent);
  --btn-bd: transparent;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 44px;                    /* touch target */
  padding: var(--s-3) var(--s-5);
  border: 1px solid var(--btn-bd);
  border-radius: var(--r-md);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font: var(--w-bold) var(--t-sm) / 1.2 var(--font-body);
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.btn:hover { --btn-bg: var(--accent-hover); color: var(--btn-fg); box-shadow: var(--shadow-1); }
.btn:active { transform: translateY(1px); box-shadow: none; }
.btn[aria-disabled="true"], .btn:disabled {
  --btn-bg: var(--c-silver); cursor: not-allowed; box-shadow: none; opacity: 0.85;
}
.btn--secondary {
  --btn-bg: transparent; --btn-fg: var(--heading); --btn-bd: var(--heading);
}
.btn--secondary:hover { --btn-bg: var(--heading); --btn-fg: var(--bg); }
.btn--ghost {
  --btn-bg: transparent; --btn-fg: var(--accent); --btn-bd: transparent;
  padding-inline: var(--s-2);
}
.btn--ghost:hover { --btn-bg: var(--callout-bg); --btn-fg: var(--accent); }
.btn--on-dark {
  --btn-bg: #ffffff; --btn-fg: var(--c-steel-800); --btn-bd: transparent;
}
.btn--on-dark:hover { --btn-bg: #e9eff4; --btn-fg: var(--c-steel-800); }

/* --- Component: card ---------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}
.card > :last-child { margin-bottom: 0; }
/* Pin a trailing CTA to the bottom so buttons line up across a row of cards.
   Scoped to links only — on a card ending in a list, `margin-top: auto` shoves
   the list to the bottom and leaves a hole under the heading. */
.card > a:last-child { margin-top: auto; padding-top: var(--s-2); }
.card h3 { margin-bottom: 0; }
.card p { max-width: none; }
.card--accent { border-top: 3px solid var(--accent-decor); }
.card ul { padding-left: 1.1em; color: var(--text-muted); font-size: var(--t-sm); }
.card li { margin-bottom: var(--s-1); }

/* --- Component: stat row ------------------------------------------------ */
.stats { display: grid; gap: var(--s-5); }
@media (min-width: 640px) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat__value {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  font-weight: var(--w-bold);
  line-height: 1;
  color: #ffffff;
}
.stat__label {
  font-size: var(--t-sm);
  color: rgba(255, 255, 255, 0.82);
  margin: var(--s-2) 0 0;
  max-width: none;
}

/* --- Component: site header / nav --------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--header-bg);
  backdrop-filter: saturate(160%) blur(8px);
  border-bottom: 1px solid var(--rule);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
  min-height: 68px;
}
.brand {
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: var(--w-bold);
  color: var(--heading);
  text-decoration: none;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.brand span { color: var(--accent-decor); }
.nav { display: flex; align-items: center; gap: var(--s-2); }
.nav a {
  color: var(--text);
  text-decoration: none;
  font-size: var(--t-sm);
  font-weight: var(--w-medium);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--accent); }
.nav a[aria-current="page"] {
  color: var(--heading);
  border-bottom-color: var(--accent-decor);
}
/* `.nav a` (0,1,1) outranks `.btn` (0,1,0), so without this the CTA inherits
   body text colour onto the accent fill — 3.9:1 in light, 2.8:1 in dark. */
.nav .btn { margin-left: var(--s-2); border-bottom: 0; color: var(--btn-fg); }
.nav .btn:hover { color: var(--btn-fg); }
@media (max-width: 719px) {
  /* Five items wrap to two rows here, which makes the bar ~158px tall — too
     much of a phone screen to give up permanently, so it scrolls away. */
  .site-header { position: static; }
  .site-header__inner { flex-wrap: wrap; padding-block: var(--s-3); }
  .nav { width: 100%; justify-content: flex-start; gap: 0; flex-wrap: wrap; }
  .nav .btn { margin-left: auto; }
}

/* --- Component: hero ---------------------------------------------------- */
.hero { padding-block: clamp(var(--s-7), 9vw, var(--s-9)); background: var(--bg-tint); }
.hero h1 { margin-bottom: var(--s-5); }
.hero .lede { max-width: 56ch; margin-bottom: var(--s-6); }
.hero__rule {
  width: 64px; height: 4px; background: var(--accent-decor);
  border-radius: 2px; margin-bottom: var(--s-5);
}

/* --- Component: portrait ------------------------------------------------ */
/* A photo of a person. Always give width/height so the layout never shifts. */
.portrait {
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  object-fit: cover;
  width: 100%;
}
.portrait--headshot { max-width: 22rem; aspect-ratio: 4 / 5; }
.portrait--wide { aspect-ratio: 3 / 2; }
/* Hero photo: 4:5 fills the narrower hero column far better than a landscape
   crop, and matches the portrait orientation these photos are shot in. */
.portrait--hero { aspect-ratio: 4 / 5; max-width: 30rem; margin-inline: auto; }
.portrait--float {
  float: right;
  max-width: 16rem;
  margin: 0 0 var(--s-5) var(--s-6);
}
@media (max-width: 719px) {
  .portrait--float { float: none; max-width: 100%; margin: 0 0 var(--s-5); }
}

/* --- Component: figure (wide inline image) ------------------------------- */
.figure { margin: 0; }
.figure img {
  width: 100%;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
}

/* --- Component: split hero (copy + photo) -------------------------------- */
/* Used when there is a real photo. Without one, use the plain .hero. */
.hero--split .hero__grid { display: grid; gap: var(--s-6); align-items: center; }
@media (min-width: 860px) {
  .hero--split .hero__grid { grid-template-columns: 1.15fr 0.85fr; gap: var(--s-8); }
}
/* On phones the copy comes first. A 4:5 photo at full column width eats the
   entire first screen, which would push the headline and CTA below the fold. */
@media (max-width: 859px) {
  .hero--split .hero__media { max-width: 20rem; margin-inline: auto; }
}

/* --- Component: form ---------------------------------------------------- */
.field { display: block; margin-bottom: var(--s-5); max-width: 34rem; }
.field__label {
  display: block;
  font-size: var(--t-sm);
  font-weight: var(--w-bold);
  color: var(--heading);
  margin-bottom: var(--s-2);
}
.field__hint { display: block; font-size: var(--t-xs); color: var(--text-muted); margin-top: var(--s-2); }
.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 44px;
  padding: var(--s-3);
  border: 1px solid var(--input-border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--text);
  font: var(--w-normal) var(--t-base) / 1.4 var(--font-body);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.field textarea { min-height: 9rem; resize: vertical; }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--heading); }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--heading);
  box-shadow: 0 0 0 3px rgba(62, 92, 118, 0.28);
  outline: none;
}
.field [aria-invalid="true"] { border-color: var(--danger); }
.field__error { display: block; font-size: var(--t-sm); color: var(--danger); margin-top: var(--s-2); }
.field--honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status { margin-top: var(--s-5); padding: var(--s-4); border-radius: var(--r-md); max-width: 34rem; }
.form-status[data-state="ok"] { background: var(--bg-tint); border: 1px solid var(--heading); }
.form-status[data-state="error"] { background: var(--danger-bg); border: 1px solid var(--danger); }
.form-status:empty { display: none; }

/* --- Component: definition list (policies, details) --------------------- */
.deflist { border-top: 1px solid var(--rule); margin: 0 0 var(--s-6); }
.deflist > div {
  display: grid;
  gap: var(--s-2) var(--s-5);
  padding-block: var(--s-4);
  border-bottom: 1px solid var(--rule);
}
@media (min-width: 720px) { .deflist > div { grid-template-columns: 14rem 1fr; } }
.deflist dt { font-weight: var(--w-bold); color: var(--heading); margin: 0; }
.deflist dd { margin: 0; color: var(--text-muted); }
.deflist dd > :last-child { margin-bottom: 0; }

/* --- Component: callout ------------------------------------------------- */
.callout {
  border-left: 3px solid var(--accent-decor);
  background: var(--callout-bg);
  padding: var(--s-4) var(--s-5);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  margin-block: var(--s-5);
}
.callout > :last-child { margin-bottom: 0; }

/* --- Component: prose (long-form pages) --------------------------------- */
.prose h2 { margin-top: var(--s-7); }
.prose h3 { margin-top: var(--s-6); }
.prose > :first-child { margin-top: 0; }
.prose ul, .prose ol { max-width: var(--measure); padding-left: 1.25em; }
.prose li { margin-bottom: var(--s-2); }

/* --- Component: site footer --------------------------------------------- */
.site-footer {
  background: var(--footer-bg);
  color: rgba(255, 255, 255, 0.85);
  padding-block: var(--s-7) var(--s-5);
  font-size: var(--t-sm);
  margin-top: auto;
}
.site-footer h2 { font-size: var(--t-md); color: #fff; margin-bottom: var(--s-3); }
.site-footer__cols { display: grid; gap: var(--s-6); }
@media (min-width: 720px) { .site-footer__cols { grid-template-columns: 2fr 1fr 1fr; } }
.site-footer p { max-width: 34ch; }
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { margin-bottom: var(--s-2); }
.site-footer a { color: rgba(255, 255, 255, 0.9); text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.site-footer__bar {
  margin-top: var(--s-6);
  padding-top: var(--s-4);
  border-top: 1px solid rgba(255, 255, 255, 0.18);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
  align-items: center;
  justify-content: space-between;
  color: rgba(255, 255, 255, 0.7);
  font-size: var(--t-xs);
}
.site-footer__label {
  font-size: var(--t-xs);
  font-weight: var(--w-bold);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: var(--s-3);
}

/* --- Page shell --------------------------------------------------------- */
body { display: flex; flex-direction: column; min-height: 100vh; }
main { flex: 1 0 auto; }

/* --- Dark theme ---------------------------------------------------------- *
 * Follows the visitor's OS setting. Light stays the default, because a lot of
 * this site is read on school computers under fluorescent light — but anyone
 * whose device is set to dark gets a real dark version rather than an inverted
 * one. Only the semantic aliases change; no component rules are duplicated.
 *
 * Two things are deliberately NOT a straight inversion:
 *   - --bg-invert gets LIGHTER than the page. On the light theme the stats band
 *     is a dark punctuation mark; in dark it has to lift instead of sink, or
 *     the page loses its rhythm.
 *   - the accent lightens to #d9713f and buttons take dark text. The light
 *     theme's #ba5429 only manages 3.9:1 on this background — below AA.
 * ------------------------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #131a22;            /* deep, cool, blue-leaning — not neutral black */
    --bg-alt: #182029;
    --bg-tint: #1b2530;
    --bg-invert: #24313d;     /* raised panel, not a sunken one              */
    --surface: #1b242e;
    --header-bg: rgba(19, 26, 34, 0.92);
    --footer-bg: #0e141a;     /* below --bg, so it anchors the page bottom   */
    --callout-bg: #2a1d15;
    --input-border: #3a4854;

    --text: #e6ecf1;          /* 14.8:1 on --bg                             */
    --text-muted: #a8b6c2;    /*  8.5:1                                     */
    --text-invert: #f2f6f9;
    --heading: #cfe0ee;       /* 14.2:1 — light steel, keeps the blue cast  */
    --on-accent: #131a22;     /* dark text on the orange fill,  5.3:1       */

    --accent: #d9713f;        /*  5.3:1 on --bg                             */
    --accent-hover: #e88a5c;
    --accent-decor: #d9713f;
    --accent-on-dark: #f0b48f;
    --rule: #2a3742;
    --focus: #e88a5c;

    --danger: #ff8a80;
    --danger-bg: #3a1c1a;

    /* Black shadows vanish on a dark page; these carry the elevation. */
    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 8px rgba(0, 0, 0, 0.3);
    --shadow-2: 0 2px 6px rgba(0, 0, 0, 0.45), 0 12px 28px rgba(0, 0, 0, 0.4);
  }

  /* The one place white is hard-coded: headings inside the raised panel. */
  .section--invert h1,
  .section--invert h2,
  .section--invert h3 { color: #ffffff; }

  /* A pure-white photo edge glares against a dark page. */
  .portrait,
  .figure img { filter: brightness(0.94); }
}

/* --- Print -------------------------------------------------------------- */
@media print {
  .site-header, .site-footer, .btn { display: none !important; }
  body { color: #000; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; }
}
