/* ------------------------------------------------------------------ *
 *  Curriculum, shared styles.
 *
 *  Palette and type are taken from the pitch deck, with three rules
 *  that the deck does not have to care about and this tool does:
 *
 *  1. The blue gradient never sits behind text in white. Measured end
 *     to end it runs 1.66:1 against white and 4.72:1 at its darkest
 *     against charcoal, so anything written on it is written in ink.
 *  2. The heavy display weight is for headings and course codes. Body
 *     text, table cells and form labels stay at a normal weight, where
 *     they stay legible at 200% zoom and under increased letter spacing.
 *  3. Dark surfaces are for the header band and the sign-in page. The
 *     catalog and the board are read for an hour at a time, and dark
 *     text on light is the better polarity for that.
 * ------------------------------------------------------------------ */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/archivo-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("/fonts/archivo-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --ink: #24282B;        /* 11.2:1 on page, 14.9:1 on card */
  --mut: #4E555E;        /* 5.7:1 on page, 7.5:1 on card   */
  --shell: #2F3335;      /* header band, white text 12.8:1 */
  --shell-2: #3A3F42;
  --page: #D9E0E9;
  --card: #FFFFFF;
  --line: #A4AFBE;       /* card outlines: decorative grouping */
  --ctrl: #767F8C;       /* control borders: 4.1:1 on card  */
  --blue: #1F5FAE;       /* action, white on it 6.4:1       */
  --blue-hov: #174B8C;
  --g1: #A9CCF6;         /* gradient, ink only, never white */
  --g2: #5B93DE;
  --focus: #0B2E5C;
  --warm: #FBEBD6; --warm-ink: #8A4B00;
  --ok: #E3EFE5;   --ok-ink: #14532D;
  --err: #FFF4F3;  --err-ink: #B42318;
  --r: 18px;             /* the deck's generous corner */
  --r-sm: 10px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 15px/1.6 "Archivo", "Avenir Next", "Segoe UI", Helvetica, Arial, sans-serif;
  font-synthesis-weight: none;
}

/* Display type. Tight, but not so tight that increased letter spacing breaks it. */
h1, h2, .display {
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.12;
  color: var(--ink);
  margin: 0;
}
h1 { font-size: clamp(20px, 2.4vw, 27px); }
h2 { font-size: 16px; letter-spacing: -0.01em; }

/* ------------------------------ shell ----------------------------- */
header {
  background: var(--shell);
  color: #fff;
  padding: 14px 22px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px 24px;
  flex-wrap: wrap;
  border-bottom: 3px solid transparent;
  border-image: linear-gradient(90deg, var(--g1), var(--g2)) 1;
}
header h1 { color: #fff; }
header .brand { display: flex; align-items: center; gap: 13px; min-width: 0; }
header .seal { width: 40px; height: 40px; flex: none; border-radius: 50%; }
header p { margin: 3px 0 0; font-size: 13px; color: #D3D8DC; }
header nav { display: flex; gap: 18px; flex-wrap: wrap; }
header a { color: #fff; font-size: 13.5px; text-decoration: underline; text-underline-offset: 3px; }
header a:hover { color: var(--g1); }
.headright { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }

/* who is signed in, in the header band */
#who { display: flex; align-items: center; gap: 10px; font-size: 13px; flex-wrap: wrap; }
#who .whoami { color: #fff; display: inline-flex; align-items: center; gap: 7px; }
#who .role {
  background: rgba(255, 255, 255, .14);
  border: 1px solid rgba(255, 255, 255, .42);
  border-radius: 999px; padding: 1px 10px; font-size: 11.5px; color: #E8EBEE;
}
#who .signout {
  background: none; border: 1px solid rgba(255, 255, 255, .55); color: #fff;
  border-radius: var(--r-sm); padding: 5px 12px; font-size: 12.5px;
  font-weight: 600; min-height: 28px;
}
#who .signout:hover { background: rgba(255, 255, 255, .16); border-color: #fff; }
#who .signin { color: #fff; font-weight: 700; font-size: 13.5px; }

main { padding: 22px 22px 56px; max-width: 1500px; margin: 0 auto; }

/* ------------------------------ focus ----------------------------- */
/* 2.4.13: thick, high contrast, and never clipped by a sticky header. */
:is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
  scroll-margin-top: 80px;
  scroll-margin-bottom: 24px;
}
header :is(a, button):focus-visible,
.dark :is(a, button, input):focus-visible { outline-color: #fff; }

.skip {
  position: absolute; left: 8px; top: -60px; z-index: 50;
  background: var(--card); color: var(--blue); font-weight: 700;
  padding: 10px 16px; border-radius: var(--r-sm); border: 2px solid var(--blue);
  transition: top .12s;
}
.skip:focus { top: 8px; }

/* ------------------------------ cards ----------------------------- */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px 18px;
}
.card > h2 { margin: 0 0 4px; }
.card > .sub { margin: 0 0 14px; font-size: 13.5px; color: var(--mut); }

/* The deck's outlined container: no fill, just the line. */
.outline {
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px 18px;
}

/* ------------------------- numbered stages ------------------------ */
/* Order lives in the text, not only in the left-to-right position, so it
   survives wrapping, narrow screens and a screen reader. */
.stagenum {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 38px;
  padding: 3px 10px;
  border-radius: 999px;
  background: linear-gradient(100deg, var(--g1), var(--g2));
  color: var(--ink);            /* never white: see note at the top */
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.01em;
  border: 1px solid rgba(0, 0, 0, .14);
}
.stagenum.flat { background: var(--page); border-color: var(--line); }

/* -------------------------- chips and tags ------------------------ */
.chip {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  border: 1px solid var(--line);
  background: var(--page);
  color: var(--ink);
}
.chip.accent { background: linear-gradient(100deg, var(--g1), var(--g2)); border-color: rgba(0,0,0,.14); }
.chip.warn { background: var(--warm); border-color: #E2C89E; color: var(--warm-ink); }
.chip.ok { background: var(--ok); border-color: #B2D2BA; color: var(--ok-ink); }

/* ------------------------------ buttons --------------------------- */
button, .btn {
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  border-radius: var(--r-sm);
  padding: 9px 15px;
  min-height: 34px;          /* 2.5.8 target size */
  border: 1px solid var(--blue);
  background: var(--blue);
  color: #fff;
}
button:hover, .btn:hover { background: var(--blue-hov); border-color: var(--blue-hov); }
button.ghost, .btn.ghost { background: var(--card); color: var(--blue); }
button.ghost:hover, .btn.ghost:hover { background: #EAF1FA; }
button.warn { background: var(--card); color: var(--warm-ink); border-color: #A9711F; }
button.warn:hover { background: var(--warm); }
button:disabled { opacity: .55; cursor: not-allowed; }
button:disabled:hover { background: var(--blue); border-color: var(--blue); }
button.ghost:disabled:hover { background: var(--card); }

/* A text button in a table row is still a target: 2.5.8 wants 24px, and the
   line box alone gives 22. The padding is what buys the last two pixels. */
button.link {
  background: none; border: none; padding: 3px 0; min-height: 24px;
  font: inherit; color: var(--blue); text-decoration: underline;
  text-underline-offset: 2px; font-weight: 600; text-align: left;
}
button.link:hover { background: none; color: var(--blue-hov); }

/* ------------------------------ forms ----------------------------- */
label { font-size: 12px; font-weight: 700; color: var(--mut); text-transform: uppercase; letter-spacing: .05em; }
input, select, textarea {
  font: inherit;
  max-width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--ctrl);   /* 4.1:1, meets 1.4.11 */
  border-radius: var(--r-sm);
  background: var(--card);
  color: var(--ink);
}
input:disabled, select:disabled, textarea:disabled { background: #F1F3F6; color: #5A6069; }
textarea { line-height: 1.55; }
.fld { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.fld > input, .fld > select, .fld > textarea { width: 100%; min-width: 0; }

/* A row of fields. Grid, not flex: a grid track cannot be overrun by a child
   that refuses to shrink, which is how the search box ended up sitting on top
   of the department menu. */
.fieldrow {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  align-items: end;
}

/* ------------------------------ tables ---------------------------- */
td.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
table { width: 100%; border-collapse: collapse; background: var(--card); }
th, td { text-align: left; padding: 9px 11px; border-bottom: 1px solid #DCE2EA; font-size: 13.5px; vertical-align: top; }
th {
  background: #EDF1F6; color: var(--ink); font-size: 12px;
  text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
  position: sticky; top: 0; z-index: 2;
  box-shadow: inset 0 -1px 0 var(--line);
}
tbody tr:hover { background: #F4F7FB; }
tbody tr:last-child td { border-bottom: none; }
/* 1.4.10 lets a data table keep its two-dimensional layout, but the table has
   to scroll inside its own frame rather than scrolling the whole page, and the
   frame has to be focusable so it can be scrolled from the keyboard.
   The frame scrolls on both axes so the column headings can actually pin: a
   sticky heading sticks to its nearest scrolling ancestor, which means a table
   wrapped in a clipping box has a heading that only looks sticky.
   `contain: paint` is what stops the clipped width from being added to the
   document's own scroll width, which is what makes the page scroll sideways. */
.tablewrap {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--card);
  overflow: auto;
  contain: paint;
  max-height: calc(100vh - 150px);
  min-height: 220px;
}
.tablewrap:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.tablewrap table { min-width: 760px; }

/* ----------------------------- timeline --------------------------- */
/* The deck's dashed timeline, turned vertical. A proposal step carries an
   email, a date and sometimes a sentence, which a horizontal track cannot
   hold without wrapping into nonsense. Built as an ordered list so the
   sequence is announced in order rather than inferred from the dashes. */
ol.timeline { list-style: none; margin: 0; padding: 0; }
ol.timeline li { position: relative; padding: 0 0 18px 26px; }
ol.timeline li:last-child { padding-bottom: 0; }
/* the connector, drawn from each pill down to the next */
ol.timeline li::before {
  content: "";
  position: absolute;
  left: 7px; top: 22px; bottom: 4px;
  border-left: 2px dashed var(--ctrl);
}
ol.timeline li:last-child::before { display: none; }
/* the node on the rail */
ol.timeline li::after {
  content: "";
  position: absolute;
  left: 0; top: 6px;
  width: 16px; height: 16px; border-radius: 50%;
  background: linear-gradient(130deg, var(--g1), var(--g2));
  border: 1px solid rgba(0, 0, 0, .18);
}
ol.timeline li:last-child::after { background: var(--ok-ink); border-color: var(--ok-ink); }
ol.timeline .stepname {
  display: inline-block; padding: 3px 13px; border-radius: 999px;
  background: linear-gradient(100deg, var(--g1), var(--g2));
  color: var(--ink);             /* never white: see note at the top */
  font-weight: 800; font-size: 12.5px;
  border: 1px solid rgba(0, 0, 0, .14);
}
ol.timeline li:last-child .stepname { background: var(--ok); border-color: #B2D2BA; color: var(--ok-ink); }
ol.timeline .who { display: block; margin: 6px 0 0; font-size: 12.5px; color: var(--mut); }
ol.timeline .said {
  display: block; margin: 6px 0 0; padding: 8px 11px;
  background: var(--page); border-radius: var(--r-sm);
  font-size: 12.5px; color: var(--ink);
}

/* --------------------------- status notes ------------------------- */
.note { margin: 0 0 14px; padding: 11px 14px; border-radius: var(--r-sm); font-size: 14px; }
.note:empty { display: none; margin: 0; padding: 0; }
.note.warn { background: var(--warm); border: 1px solid #E2C89E; color: var(--warm-ink); font-weight: 600; }
.note.ok { background: var(--ok); border: 1px solid #B2D2BA; color: var(--ok-ink); }
.note.err { background: var(--err); border: 1px solid #F0B9B3; color: var(--err-ink); }

.ro { margin: 0 0 15px; padding: 11px 14px; border-radius: var(--r-sm); font-size: 14px;
     background: var(--warm); border: 1px solid #E2C89E; color: var(--warm-ink); font-weight: 600; }
.muted { color: var(--mut); }
.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* --------------------------- dark surfaces ------------------------ */
/* Only the sign-in page, where there are forty words rather than 468 rows. */
.dark {
  background: var(--shell);
  color: #E8EBEE;
  position: relative;
  overflow: hidden;
}
/* The deck's soft colour bloom. Decorative, behind nothing but itself. */
.dark::before, .dark::after {
  content: ""; position: fixed; border-radius: 50%; filter: blur(90px);
  pointer-events: none; z-index: 0;
}
.dark::before { width: 46vw; height: 46vw; left: -12vw; bottom: -18vw; background: rgba(91, 147, 222, .34); }
.dark::after { width: 34vw; height: 34vw; right: -8vw; top: -12vw; background: rgba(169, 204, 246, .20); }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

@media (max-width: 640px) {
  main { padding: 16px 16px 48px; }
  header { padding: 12px 16px; }
}
