/* Shared design for every page: sign in, staff, admin, public.
   Direction: a printed order of ceremony made live. Type from the university's own lettering
   (a Garamond for names and the clock), hairline rules and tables for structure, no cards-in-cards.
   Red appears only for what is live or late. Gold is one hairline, as in the logo's divider.
   Fonts are self-hosted so the page loads on bad venue WiFi. */
@import url('/fonts/fonts.css');

:root {
  --paper: #f2f3f5; --surface: #ffffff; --ink: #0d0e10; --ink-2: #4a4f59; --ink-3: #6b717d;
  --rule: #d8dbe1; --rule-strong: #b6bbc5;
  --red: #c8352a; --blue: #2c5f9e; --gold: #b08a2e; --gold-ink: #7a5c10; --ok: #1f7a4d;
  --serif: 'EB Garamond', 'Iowan Old Style', Georgia, serif;
  --sans: 'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --r: 16px; --r-sm: 10px;
  --sh-1: 0 1px 2px rgba(15, 20, 35, .05), 0 8px 24px -8px rgba(15, 20, 35, .10);
  --sh-2: 0 2px 4px rgba(15, 20, 35, .05), 0 24px 56px -16px rgba(15, 20, 35, .22);
  --logo-pos: block; --logo-neg: none;
  color-scheme: light;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #0d0f13; --surface: #14171d; --ink: #f1f2f4; --ink-2: #aeb3be; --ink-3: #8a909d;
    --rule: #272b34; --rule-strong: #3a404c; --red: #ff6e61; --blue: #8db8f0; --gold: #d9a92f; --gold-ink: #e3bb62; --ok: #52c98d;
    --sh-1: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -8px rgba(0, 0, 0, .5);
    --sh-2: 0 2px 4px rgba(0, 0, 0, .4), 0 24px 56px -16px rgba(0, 0, 0, .7);
    --logo-pos: none; --logo-neg: block; color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --paper: #0d0f13; --surface: #14171d; --ink: #f1f2f4; --ink-2: #aeb3be; --ink-3: #8a909d;
  --rule: #272b34; --rule-strong: #3a404c; --red: #ff6e61; --blue: #8db8f0; --gold: #d9a92f; --gold-ink: #e3bb62; --ok: #52c98d;
  --sh-1: 0 1px 2px rgba(0, 0, 0, .4), 0 8px 24px -8px rgba(0, 0, 0, .5);
  --sh-2: 0 2px 4px rgba(0, 0, 0, .4), 0 24px 56px -16px rgba(0, 0, 0, .7);
  --logo-pos: none; --logo-neg: block; color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--paper); color: var(--ink); font: 15px/1.55 var(--sans); -webkit-font-smoothing: antialiased; }
[hidden] { display: none !important; }
button { font: inherit; color: inherit; cursor: pointer; background: none; border: 0; padding: 0; }
input, textarea, select { font: inherit; color: inherit; }
h1, h2, h3, h4, p { margin: 0; }
h1, h2, h3 { font-family: var(--serif); font-weight: 500; text-wrap: balance; }
:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.n { font-variant-numeric: tabular-nums lining-nums; }
.mute { color: var(--ink-3); }
.dim { color: var(--ink-2); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* logo that swaps with the theme */
.logo { display: block; }
.logo img { height: 38px; width: auto; max-width: 100%; }
.logo .pos { display: var(--logo-pos); }
.logo .neg { display: var(--logo-neg); }

/* buttons and fields */
.btn {
  border: 1px solid var(--rule); border-radius: var(--r-sm); padding: 9px 14px; font-weight: 600; font-size: 14px;
  background: var(--surface); box-shadow: 0 1px 1px rgba(15, 20, 35, .04);
  transition: transform .15s, background-color .2s, border-color .2s, box-shadow .2s;
}
.btn:hover { border-color: var(--rule-strong); transform: translateY(-1px); box-shadow: var(--sh-1); }
.btn:active { transform: scale(.97); }
.btn.main { background: var(--ink); color: var(--paper); border-color: var(--ink); box-shadow: 0 6px 16px -6px rgba(15, 20, 35, .45); }
.btn.sm { padding: 5px 10px; font-size: 13px; }
.btn.danger { color: var(--red); }
.btn.alert { background: var(--red); border-color: var(--red); color: #fff; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .btn.alert { color: #1a0604; } }
:root[data-theme="dark"] .btn.alert { color: #1a0604; }
.btn:disabled { opacity: .4; cursor: default; transform: none; box-shadow: none; }

.field { display: flex; flex-direction: column; gap: 6px; }
.field label, .lbl { font-size: 13px; font-weight: 600; color: var(--ink-2); }
.in {
  width: 100%; border: 1px solid var(--rule-strong); border-radius: var(--r-sm); padding: 10px 12px; background: var(--paper);
  transition: border-color .2s, box-shadow .2s;
}
.in:focus { border-color: var(--blue); outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 22%, transparent); }
textarea.in { min-height: 92px; resize: vertical; }

.seg { display: inline-flex; border: 1px solid var(--rule); border-radius: var(--r-sm); padding: 2px; gap: 2px; background: var(--surface); }
.seg button { padding: 5px 12px; font-size: 13px; font-weight: 600; color: var(--ink-2); border-radius: 8px; }
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

.tag { display: inline-block; font-size: 12px; font-weight: 700; border: 1px solid var(--rule-strong); padding: 3px 11px; border-radius: 99px; color: var(--ink-2); }

/* the live dot: green = connected, red = live item, grey = offline */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--ok); margin-right: 7px; }
.dot.red { background: var(--red); }
.dot.off { background: var(--ink-3); }

/* the clock: set large in the serif, like a name on a programme */
.big {
  font-family: var(--serif); font-weight: 500; font-size: clamp(76px, 11vw, 132px); line-height: .95; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums lining-nums; margin-top: 14px;
}
.big small { font-size: .22em; letter-spacing: 0; color: var(--ink-3); font-weight: 400; margin-left: .4em; }
.big.over { color: var(--red); }
.state { margin-top: 12px; color: var(--ink-2); max-width: 58ch; }
.state b { color: var(--ink); font-weight: 600; }
.state.late b { color: var(--red); }

/* timeline strip: one segment per item, filled as time passes */
.track { display: flex; gap: 3px; height: 12px; }
.track i { display: block; border: 1px solid var(--rule-strong); border-radius: 99px; position: relative; overflow: hidden; min-width: 5px; }
.track i.done { background: var(--ink); border-color: var(--ink); }
.track i.cur::after { content: ""; position: absolute; inset: 0; background: var(--ink); transform-origin: left; transform: scaleX(var(--p, 0)); }
.ticks { display: flex; gap: 3px; margin-top: 6px; font-size: 11px; color: var(--ink-3); }
.ticks span { overflow: hidden; white-space: nowrap; min-width: 5px; }
.ticks span.cur { color: var(--ink); font-weight: 600; }

/* messages from admins */
.pm { border-radius: 14px; background: var(--paper); padding: 12px 14px 12px 16px; position: relative; font-size: 14px; }
.pm::before { content: ""; position: absolute; left: 0; top: 12px; bottom: 12px; width: 3px; border-radius: 99px; background: var(--gold); }
.pm.u { background: color-mix(in srgb, var(--red) 8%, var(--surface)); }
.pm.u::before { background: var(--red); }
.pm small { display: block; color: var(--ink-3); font-size: 12px; margin-bottom: 2px; }

/* hairline tables */
table.rule { width: 100%; border-collapse: collapse; font-size: 14px; }
table.rule th { font-weight: 600; font-size: 12px; color: var(--ink-3); text-align: left; padding: 0 8px 8px 0; border-bottom: 1px solid var(--rule-strong); }
table.rule td { padding: 11px 8px 11px 0; border-bottom: 1px solid var(--rule); vertical-align: top; }

.toast {
  position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom, 0px)); transform: translate(-50%, 140%); z-index: 50;
  background: var(--ink); color: var(--paper); border-radius: 14px; padding: 11px 16px; font-size: 14px; box-shadow: var(--sh-2);
  max-width: min(92vw, 420px); transition: transform .3s;
}
.toast.show { transform: translate(-50%, 0); }
.toast.err { background: var(--red); color: #fff; }

@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } html { scroll-behavior: auto; } }


/* ---- graduation theme: the crest's colours, a sash, and a soft background ---- */
:root { --go: #1f7a4d; --warn: #b26a00; --wait: #2c5f9e; --crest-red: #cf3a2c; --crest-blue: #4a86c5; --crest-gold: #d9a92f; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --go: #52c98d; --warn: #f0b44c; --wait: #8db8f0; } }
:root[data-theme="dark"] { --go: #52c98d; --warn: #f0b44c; --wait: #8db8f0; }

body { position: relative; min-height: 100vh; border-top: 4px solid; border-image: linear-gradient(90deg, var(--crest-red) 0 42%, var(--crest-blue) 42% 84%, var(--crest-gold) 84% 100%) 1; }
body::before {
  content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(52rem 34rem at 92% -8%, color-mix(in srgb, var(--crest-blue) 22%, transparent), transparent 62%),
    radial-gradient(44rem 30rem at -8% 108%, color-mix(in srgb, var(--crest-red) 15%, transparent), transparent 62%),
    radial-gradient(34rem 24rem at 55% 118%, color-mix(in srgb, var(--crest-gold) 18%, transparent), transparent 62%),
    var(--paper);
}
body::after {
  content: ""; position: fixed; right: -40px; bottom: -30px; width: 250px; height: 306px; z-index: -1; pointer-events: none;
  background: url('/brand/crest.png') no-repeat center / contain; opacity: .045;
}
@media (max-width: 600px) { body::after { width: 170px; height: 208px; right: -30px; bottom: -20px; } }

/* a colour-coded clock: green while there is plenty, amber when it is getting short, red when it is nearly out or over */
.tone-go { color: var(--go); }
.tone-warn { color: var(--warn); }
.tone-alert, .big.over.tone-alert { color: var(--red); }
.tone-wait { color: var(--wait); }
.tone-pause { color: var(--gold-ink); }
.tone-done { color: var(--ink-3); }
.track[data-tone="go"] i.cur::after { background: var(--go); }
.track[data-tone="warn"] i.cur::after { background: var(--warn); }
.track[data-tone="alert"] i.cur::after { background: var(--red); }
.track[data-tone="pause"] i.cur::after { background: var(--gold); }
.tone-key { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12px; color: var(--ink-3); margin-top: 10px; }
.tone-key span { display: inline-flex; align-items: center; gap: 6px; }
.tone-key i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }

/* a gold rule with a mortarboard in the middle, used to close a section */
.mortar { display: block; width: 28px; height: 28px; color: var(--gold); }
.flourish { display: flex; align-items: center; gap: 14px; color: var(--gold); }
.flourish::before, .flourish::after { content: ""; flex: 1; height: 1px; background: linear-gradient(90deg, transparent, var(--gold)); }
.flourish::after { background: linear-gradient(270deg, transparent, var(--gold)); }

canvas.confetti { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 60; }


/* ---- certificate feel: a fine gold rosette pattern and a double-ruled frame, like a diploma ---- */
body::before {
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='88' viewBox='0 0 88 88' fill='none' stroke='%23c9a23a' stroke-opacity='.15' stroke-width='.7'%3E%3Ccircle cx='44' cy='44' r='42'/%3E%3Ccircle cx='44' cy='44' r='32'/%3E%3Ccircle cx='44' cy='44' r='22'/%3E%3Ccircle cx='0' cy='0' r='44'/%3E%3Ccircle cx='88' cy='0' r='44'/%3E%3Ccircle cx='0' cy='88' r='44'/%3E%3Ccircle cx='88' cy='88' r='44'/%3E%3C/svg%3E"),
    radial-gradient(52rem 34rem at 92% -8%, color-mix(in srgb, var(--crest-blue) 22%, transparent), transparent 62%),
    radial-gradient(44rem 30rem at -8% 108%, color-mix(in srgb, var(--crest-red) 15%, transparent), transparent 62%),
    radial-gradient(34rem 24rem at 55% 118%, color-mix(in srgb, var(--crest-gold) 18%, transparent), transparent 62%),
    var(--paper);
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,.55), #000 40%, #000 70%, rgba(0,0,0,.7));
  mask-image: linear-gradient(180deg, rgba(0,0,0,.55), #000 40%, #000 70%, rgba(0,0,0,.7));
}
html::after {
  content: ""; position: fixed; inset: 8px; z-index: 70; pointer-events: none; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--crest-gold) 55%, transparent);
  outline: 1px solid color-mix(in srgb, var(--crest-gold) 28%, transparent); outline-offset: 4px;
}
@media (max-width: 600px) { html::after { inset: 5px; border-radius: 12px; outline-offset: 3px; } }

/* academic hood colours: one per ceremony */
.hood::before { content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 8px; background: var(--hood, var(--crest-gold)); }
.hood0 { --hood: var(--crest-red); } .hood1 { --hood: var(--crest-blue); } .hood2 { --hood: var(--crest-gold); }

/* a framed card, like a diploma */
.diploma {
  position: relative; padding: 22px 20px 20px; border-radius: 20px;
  background: color-mix(in srgb, var(--surface) 78%, transparent);
  box-shadow: inset 0 0 0 5px color-mix(in srgb, var(--surface) 78%, transparent), inset 0 0 0 6px color-mix(in srgb, var(--crest-gold) 55%, transparent), var(--sh-1);
  border: 1px solid color-mix(in srgb, var(--crest-gold) 40%, var(--rule));
}
