/* ==========================================================================
   Speculative Decoding: Accelerating Large Language Model Inference
   CSoNet 2026 Tutorial

   A plain academic layout, no framework. The whole visual system is a short
   list of values: Noto Sans, #4a4a4a body text, #363636 headings, #485fc7
   links, a 960px container, and horizontal rules instead of boxes.
   ========================================================================== */

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: #fff;
  color: #4a4a4a;
  font-family: "Noto Sans", -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: #485fc7; text-decoration: none; }
a:hover { color: #363636; text-decoration: underline; }

sup { font-size: .7em; }

.container {
  max-width: 960px;
  margin-inline: auto;
  padding-inline: 1.5rem;
}
.has-text-centered  { text-align: center; }
.has-text-justified { text-align: justify; }

.section { padding: 3rem 0; }

.title {
  color: #363636;
  font-weight: 600;
  line-height: 1.125;
  margin: 0 0 1.5rem;
}
.title.is-2 { font-size: 2.5rem; }
.title.is-3 { font-size: 2rem; }
.title.is-5 { font-size: 1.25rem; margin-bottom: .6rem; }

p { margin: 0 0 1em; }

.content { margin-bottom: 2rem; }
.content p { margin-bottom: 1em; }
.content ul {
  list-style: disc outside;
  margin: .25em 0 1em 2em;
  padding: 0;
}
.content li + li { margin-top: .25em; }
.content ul:last-child { margin-bottom: 0; }

/* ==========================================================================
   TITLE BLOCK
   ========================================================================== */
.hero { padding: 3rem 0 1rem; }

.publication-title { margin-bottom: 1.6rem; }

/* "CSoNet 2026 Tutorial" above the title — the conference name links to the
   programme, in the same blue as the author links just below it */
.publication-conf { font-size: 80%; }
.publication-conf a { color: hsl(204, 86%, 53%); }
.publication-conf a:hover { text-decoration: underline; }

.publication-authors { font-size: 1.1rem; margin-bottom: .4rem; }
.publication-authors table {
  margin: 0 auto;
  border-collapse: collapse;
}
.publication-authors td {
  width: 33.33%;
  text-align: center;
  padding: 3px 10px;
  vertical-align: top;
}
.publication-authors a { color: hsl(204, 86%, 53%); }
.publication-authors a:hover { text-decoration: underline; }

.avatar {
  position: relative;
  width: 150px; height: 150px;
  max-width: 100%;
  margin: 0 auto;
  border-radius: 50%;
  overflow: hidden;
  background: #f5f5f5;
  display: grid;
  place-items: center;
}
.avatar__mono {
  font-size: 2.6rem; font-weight: 600; color: #b5b5b5;
  user-select: none;
}
.avatar img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

.publication-affil { font-size: .95rem; margin-bottom: 1.4rem; }

.publication-venue { color: #555; font-weight: bold; margin-bottom: 1rem; }

.publication-links { font-size: .95rem; color: #7a7a7a; }

/* ==========================================================================
   DEMONSTRATION — standard vs speculative decoding

   Both rows run on one 11s clock so the difference in finishing time is
   visible: the top row commits one token per target-model call (last token
   at 5.6s), the bottom row drafts a whole block and verifies it in one call
   (committed by 2.6s, with a second call for the tail after the correction).
   ========================================================================== */
.demo {
  margin: 2.4rem auto .5rem;
  max-width: 46rem;
}

.demo__row + .demo__row { margin-top: 1.6rem; }

.demo__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap;
  font-size: .8rem; color: #7a7a7a;
  margin-bottom: .5rem;
}
.demo__name  { font-weight: 600; color: #4a4a4a; }
.demo__calls { white-space: nowrap; }
.demo__calls--win { color: #485fc7; font-weight: 600; }

.demo__strip { display: flex; flex-wrap: wrap; gap: .3rem; }

/* shared token chrome; look and timing come from the per-state animations */
.w, .t {
  font-family: monospace; font-size: .82rem;
  padding: .28rem .5rem; border-radius: 3px;
  border: 1px solid #dbdbdb;
  white-space: nowrap;
}

/* --- top row: one token per call, arriving 0.8s apart --- */
.w { animation: autoreg 11s calc(var(--i) * .8s) infinite both; }

/* --- bottom row: whole block drafted at once, then verified --- */
.t         { animation: specOk   11s calc(var(--i) * .05s) infinite both; }
.t--fix    { animation-name: specFix; position: relative; }
.t--late   { animation-name: specLate; }

/* the corrected token: the wrong guess is swapped for the target's token
   in place — both words are 6 monospace characters, so nothing shifts */
.t--fix s { position: absolute; left: .5rem; top: .28rem; text-decoration: none;
            animation: fixOut 11s calc(var(--i) * .05s) infinite both; }
.t--fix b { font-weight: 400;
            animation: fixIn  11s calc(var(--i) * .05s) infinite both; }

/*  DRAFT = white / dashed grey      COMMITTED = blue      CORRECTED = red  */
@keyframes autoreg {
  0%, 1%    { opacity: 0; background: #eef0fb; border-color: #485fc7; color: #485fc7; }
  3%, 88%   { opacity: 1; background: #eef0fb; border-color: #485fc7; color: #485fc7; }
  95%, 100% { opacity: 0; background: #eef0fb; border-color: #485fc7; color: #485fc7; }
}
@keyframes specOk {
  0%, 1%    { opacity: 0; background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  3%, 13%   { opacity: 1; background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  14%, 88%  { opacity: 1; background: #eef0fb; border-color: #485fc7; border-style: solid;  color: #485fc7; }
  95%, 100% { opacity: 0; background: #eef0fb; border-color: #485fc7; border-style: solid;  color: #485fc7; }
}
/* holds the draft look until 13.5%, so the colour only starts moving towards
   red after the word has already been swapped (see fixOut/fixIn below) */
@keyframes specFix {
  0%, 1%    { opacity: 0; background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  3%, 13.5% { opacity: 1; background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  14%, 88%  { opacity: 1; background: #feecf0; border-color: #cc0f35; border-style: solid;  color: #cc0f35; }
  95%, 100% { opacity: 0; background: #feecf0; border-color: #cc0f35; border-style: solid;  color: #cc0f35; }
}
/* drafted, thrown away after the correction, re-drafted, then committed */
@keyframes specLate {
  0%, 1%    { opacity: 0;  background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  3%, 13%   { opacity: 1;  background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  14%, 17%  { opacity: .22; background: #fff;   border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  18%, 23%  { opacity: 1;  background: #fff;    border-color: #b5b5b5; border-style: dashed; color: #b5b5b5; }
  24%, 88%  { opacity: 1;  background: #eef0fb; border-color: #485fc7; border-style: solid;  color: #485fc7; }
  95%, 100% { opacity: 0;  background: #eef0fb; border-color: #485fc7; border-style: solid;  color: #485fc7; }
}
/* The word swaps at 12.5%, a full 1% before specFix begins interpolating
   towards red at 13.5%. CSS interpolates colour across the whole gap between
   keyframes, so the swap must finish before that gap opens — otherwise the
   rejected word is briefly visible already tinted as a "correction". */
@keyframes fixOut { 0%, 12.4% { opacity: 1; } 12.5%, 100% { opacity: 0; } }
@keyframes fixIn  { 0%, 12.4% { opacity: 0; } 12.5%, 88% { opacity: 1; } 95%, 100% { opacity: 0; } }

.demo figcaption {
  margin-top: 1.4rem;
  font-size: .85rem; color: #7a7a7a; line-height: 1.6;
}
/* inline colour keys in the caption */
.k { font-weight: 600; }
.k--draft { color: #8c8c8c; }
.k--ok    { color: #485fc7; }
.k--fix   { color: #cc0f35; }

/* ==========================================================================
   SCHEDULE TABLE

   The reference page uses the tables-generator default: a 1px black grid in
   Arial. Horizontal rules only, in the page's own type, reads better and is
   the usual convention for a printed programme.
   ========================================================================== */
.sched {
  width: 100%;
  border-collapse: collapse;
  margin: 1.2rem 0 0;
  font-size: .95rem;
}

.sched thead th {
  text-align: left;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #7a7a7a;
  padding: 0 1rem .5rem 0;
  border-bottom: 2px solid #363636;
}
.sched thead th:last-child { text-align: right; padding-right: 0; }

.sched td {
  padding: .72rem 1rem .72rem 0;
  vertical-align: baseline;
  border-bottom: 1px solid #ededed;
}
.sched tbody tr:last-child td { border-bottom: 2px solid #363636; }

/* time — placeholder for now; fixed width so the column stays aligned */
.sched .sc-time {
  width: 6.5rem;
  white-space: nowrap;
  color: #9a9a9a;
}

.sched .sc-sec b { font-weight: 600; color: #363636; }

/* one-line summary under each part title, so the schedule doubles as the outline */
.sched .sc-desc {
  display: block;
  margin-top: .3rem;
  max-width: 46rem;
  font-size: .855rem;
  color: #7a7a7a;
  line-height: 1.5;
}
.sched .sc-desc i { font-style: italic; }

/* presenter — right-aligned so names hang off the same edge */
.sched .sc-who {
  text-align: right;
  padding-right: 0;
  white-space: nowrap;
  color: #4a4a4a;
}

/* breaks and Q&A are not tutorial content — de-emphasise them */
.sched .brk td { color: #9a9a9a; }
.sched .brk .sc-sec { font-style: italic; }

/* stack into labelled blocks rather than scrolling sideways on a phone */
@media (max-width: 620px) {
  .sched thead { display: none; }
  .sched, .sched tbody, .sched tr, .sched td { display: block; width: auto; }
  .sched tr { padding: .8rem 0; border-bottom: 1px solid #ededed; }
  .sched tbody tr:last-child { border-bottom: 2px solid #363636; }
  .sched td { border: 0; padding: 0; }
  .sched .sc-time { color: #9a9a9a; font-size: .85rem; }
  .sched .sc-sec { margin-top: .1rem; }
  .sched .sc-who { text-align: left; margin-top: .25rem; font-size: .85rem; color: #7a7a7a; }
  .sched .sc-who::before { content: attr(data-l) ": "; }
  .sched .brk .sc-who { display: none; }        /* no presenter for a break */
}

/* ---------- reading list sub-headings ---------- */
.sub {
  font-weight: 600;
  color: #4a4a4a;
  margin: 1em 0 .1em;
}

/* ==========================================================================
   BIBTEX
   ========================================================================== */
pre {
  background: #f5f5f5;
  color: #4a4a4a;
  font-size: .875em;
  padding: 1.25rem 1.5rem;
  overflow-x: auto;
  white-space: pre;
  word-wrap: normal;
  margin: 0;
}
code { font-family: monospace; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
.footer {
  background: #fafafa;
  padding: 3rem 0 4rem;
  font-size: .9rem;
  color: #7a7a7a;
}
.footer p { margin-bottom: .8em; }

/* ==========================================================================
   SMALL SCREENS
   ========================================================================== */
@media (max-width: 700px) {
  .title.is-2 { font-size: 1.8rem; }
  .title.is-3 { font-size: 1.5rem; }
  .publication-authors { font-size: 1rem; }
  .publication-authors td { padding: 3px 4px; }
  .avatar { width: 90px; height: 90px; }
  .avatar__mono { font-size: 1.6rem; }
  .has-text-justified { text-align: left; }
}

/* No animation: show the settled end state — every token committed, the
   correction already applied, so the figure still reads correctly. */
@media (prefers-reduced-motion: reduce), print {
  .w, .t, .t--fix b { animation: none; opacity: 1; }
  .w, .t { background: #eef0fb; border-color: #485fc7; color: #485fc7; }
  .t--fix { background: #feecf0; border-color: #cc0f35; color: #cc0f35; }
  .t--fix s { display: none; }
}

@media print {
  body { font-size: 10.5pt; }
  a { color: #000; }
}
