/* ============================================================================
   course.css — self-contained stylesheet for the republished Python courses.

   Replaces O'Reilly School of Technology's original Lab.css. No external
   dependencies, no web fonts, no JavaScript. It styles the lesson markup
   vocabulary inherited from the OST exports:

     .lesson  .title  .heading/.headingText  .subheading/.subheadingText
     listingBox  ("CODE TO TYPE"    — type this into a file)
     interactiveBox ("INTERACTIVE SESSION" — a terminal / REPL transcript)
     observeBox  ("OBSERVE"          — read and absorb, don't type)
     noteBox     (Note / Tip / WARNING callouts)
     ins / del   (code to add / code to remove)
     inline colour spans used for manual code highlighting

   The OST page chrome (font-resize "A A HC" widget, analytics, survey iframe)
   is removed during conversion rather than styled here.
   ========================================================================== */

/* ---- Design tokens --------------------------------------------------------*/
:root {
  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
               Arial, sans-serif;
  --font-mono: "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas,
               "Liberation Mono", monospace;

  --ink:        #1a1a1a;   /* body text                       */
  --ink-soft:   #4a4a4a;   /* secondary text                  */
  --rule:       #e2e2dd;   /* hairlines / borders             */
  --bg:         #ffffff;
  --bg-page:    #f7f6f2;   /* page surround                   */

  --accent:     #15568b;   /* headings, links — calm blue     */
  --accent-2:   #0a7d3e;   /* "type this" green               */

  --measure:    44rem;     /* comfortable reading width       */
  --radius:     6px;
}

/* ---- Reset-ish & page frame ----------------------------------------------*/
*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg-page);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-text-size-adjust: 100%;
}

/* The whole lesson lives in a centred, card-like column. Conversion wraps the
   body content in <main class="lesson">; legacy files without it still read
   fine because body styling carries the defaults. */
.lesson,
main.lesson {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 3rem 2.5rem 4rem;
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(0,0,0,.04);
}

@media (max-width: 48rem) {
  .lesson, main.lesson { padding: 1.75rem 1.25rem 3rem; border-radius: 0; }
  body { font-size: 16px; }
}

/* ---- Lesson title & headings ---------------------------------------------*/
.title {
  font-size: 2.1rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 1.5rem;
  padding-bottom: 1rem;
  border-bottom: 3px solid var(--accent);
}

.heading {
  font-size: 1.5rem;
  font-weight: 650;
  color: var(--accent);
  margin: 2.75rem 0 0;
  scroll-margin-top: 1rem;
}
.headingText { margin: 0.75rem 0 0; }

.subheading {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--ink);
  margin: 2rem 0 0;
}
.subheadingText { margin: 0.5rem 0 0; }

p { margin: 0 0 1rem; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-color: var(--accent-2); }

/* Generic content block wrapper inherited from the source. */
.c, .para { margin: 0 0 1rem; }
.c:last-child, .para:last-child { margin-bottom: 0; }

/* ---- Lists ----------------------------------------------------------------*/
ul, ol { margin: 0 0 1rem; padding-left: 1.5rem; }
li { margin: 0.25rem 0; }
.itemList, .headingList, .subheadingList { margin: 0.25rem 0 1rem; }

/* ============================================================================
   Code boxes
   Each box is: a titled bar + a <pre> body. Three flavours share a skeleton.
   ========================================================================== */
.listingBox, .interactiveBox, .observeBox {
  margin: 1.5rem 0;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--rule);
}

.listingTitle, .interactiveTitle, .observeTitle {
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.45rem 0.9rem;
  color: #fff;
}

.listing, .interactive, .observe { margin: 0; }

.listing pre, .interactive pre, .observe pre,
pre {
  margin: 0;
  padding: 0.9rem 1.1rem;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  line-height: 1.5;
  tab-size: 4;
  overflow-x: auto;
  white-space: pre;
}

/* CODE TO TYPE — the active "type this into your editor" box. White body,
   green header to signal "you do this". */
.listingBox  { border-color: #cfe6d6; }
.listingTitle { background: var(--accent-2); }
.listing      { background: #fcfdfc; color: var(--ink); }

/* INTERACTIVE SESSION — a terminal/REPL transcript. Dark, terminal-like. */
.interactiveBox  { border-color: #2b3a44; }
.interactiveTitle { background: #2b3a44; }
.interactive      { background: #1e2a32; }
.interactive pre  { color: #e7edf0; }

/* OBSERVE — read-only. Muted grey, signals "don't type, just read". */
.observeBox  { border-color: var(--rule); }
.observeTitle { background: #6b6f76; }
.observe      { background: #f4f4f1; color: var(--ink); }

/* ---- ins / del : code to add or remove -----------------------------------*/
ins {
  text-decoration: none;
  background: rgba(10,125,62,.16);
  box-shadow: inset 2px 0 0 var(--accent-2);
  padding: 0 .15em;
}
del {
  text-decoration: line-through;
  text-decoration-color: #b00020;
  background: rgba(176,0,32,.12);
  padding: 0 .15em;
}
/* Inside the dark interactive box, the user-typed code (ins) is shown in a pale
   blue (and bold) so it stands out clearly from the output; deletions keep a
   light tint. */
.interactive ins { background: transparent; box-shadow: none; color: #a8d1ff; font-weight: bold; padding: 0; }
.interactive del { background: rgba(255,120,140,.18); text-decoration-color: #ff8da0; }

/* ============================================================================
   Manual code highlighting — colour spans from the original source.
   Tuned for AA contrast on the light code backgrounds.
   ========================================================================== */
.darkgreen { color: #0a7d3e; }
.green     { color: #1a8f47; }
.darkred   { color: #b00020; }
.red       { color: #cf2a2a; }
.darkblue  { color: #1456b8; }
.blue      { color: #1769c4; }
.purple    { color: #7b1fa2; }
.orange    { color: #b85c00; }

/* Same palette, brightened for the dark interactive box. */
.interactive .darkgreen { color: #5ed684; }
.interactive .green     { color: #7ee29a; }
.interactive .darkred   { color: #ff8da0; }
.interactive .red       { color: #ff9b8a; }
.interactive .darkblue  { color: #79b8ff; }
.interactive .blue      { color: #8cc6ff; }
.interactive .purple    { color: #d6a2ff; }
.interactive .orange    { color: #ffb86b; }

/* Inline code in prose. */
code, .code {
  font-family: var(--font-mono);
  font-size: 0.88em;
  background: #f2f1ec;
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 0.05em 0.35em;
}
pre code { background: none; border: 0; padding: 0; font-size: inherit; }

/* ============================================================================
   Note / Tip / WARNING callouts  (source renders these as <table class="noteBox">)
   ========================================================================== */
.noteBox {
  width: 100%;
  margin: 1.5rem 0;
  border-collapse: collapse;
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  background: #f3f7fb;
  overflow: hidden;
}
.noteBox td { padding: 0.85rem 1rem; vertical-align: top; }
.noteTitle {
  white-space: nowrap;
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent);
  width: 1%;
}
.note { color: var(--ink); }
.note p:last-child { margin-bottom: 0; }

/* Tip — green; Warning — amber. Toggled by a modifier class added during
   conversion (.is-tip / .is-warning) so the colour matches the label. */
.noteBox.is-tip      { border-left-color: var(--accent-2); background: #f1f8f3; }
.noteBox.is-tip      .noteTitle { color: var(--accent-2); }
.noteBox.is-warning  { border-left-color: #c77700; background: #fdf6ec; }
.noteBox.is-warning  .noteTitle { color: #a85a00; }

/* ---- Data tables ----------------------------------------------------------*/
.tbl {
  border-collapse: collapse;
  margin: 1rem 0;
  width: 100%;
  font-size: 0.95rem;
}
.tbl th, .tbl td {
  border: 1px solid var(--rule);
  padding: 0.45rem 0.7rem;
  text-align: left;
}
.tbl th { background: #f2f1ec; font-weight: 650; }
.tbl tr:nth-child(even) td { background: #faf9f6; }

/* ---- Images ---------------------------------------------------------------*/
img { max-width: 100%; height: auto; }

/* ---- Footer / licence -----------------------------------------------------*/
.footer {
  max-width: var(--measure);
  margin: 1.5rem auto 0;
  padding: 1.25rem 2.5rem 0;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--ink-soft);
  text-align: center;
}
.footer img { vertical-align: middle; }

/* ---- Inter-lesson navigation (added during conversion) --------------------*/
.lesson-nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: baseline;
  gap: 0.5rem 1rem;
  margin: 2.5rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.95rem;
}
.lesson-nav a { font-weight: 600; }
.lesson-nav .prev { grid-column: 1; justify-self: start; }
.lesson-nav .contents { grid-column: 2; justify-self: center; white-space: nowrap; }
.lesson-nav .next { grid-column: 3; justify-self: end; text-align: right; }
.lesson-nav .prev::before { content: "← "; }
.lesson-nav .next::after  { content: " →"; }

/* ============================================================================
   Interactive diff viewer — added by course.js to "Code" boxes with <ins>/<del>
   ========================================================================== */

/* Three-way switch lives in the Code box's title bar. */
.listingBox .listingTitle { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.diff-tabs { display: flex; gap: 5px; }
.diff-tab {
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: none;     /* keep the labels lower-case, not upper */
  letter-spacing: 0;
  line-height: 1.4;
  padding: 2px 9px;
  border-radius: 5px;
  border: 1px solid rgba(255,255,255,.55);
  background: transparent;
  color: #fff;
  cursor: pointer;
  transition: background-color .15s, color .15s;
}
.diff-tab:hover:not(:disabled) { background: rgba(255,255,255,.18); }
.diff-tab[aria-pressed="true"] { background: #fff; color: var(--accent-2); border-color: #fff; font-weight: 700; }
.diff-tab:disabled { opacity: .4; cursor: default; }

/* Each source line becomes a block so a removed line can collapse to zero
   height (font-size 0 + unitless line-height) without leaving a blank line. */
.diff-pre .cl { display: block; overflow: hidden; transition: font-size 2s linear, opacity 2s linear; }
.diff-pre ins, .diff-pre del {
  font-size: 1em;
  transition: font-size 2s linear, opacity 2s linear;   /* only size/opacity animate; the */
}                                                        /* add/remove styling is kept, then dropped at settle */

/* prior: hide additions; deletions collapse keeping their styling until settled. */
.diff-pre.is-prior .cl[data-diff="ins"] { font-size: 0; opacity: 0; }
.diff-pre.is-prior ins { font-size: 0; opacity: 0; }

/* updated: hide deletions; insertions stay, keeping their styling until settled. */
.diff-pre.is-updated .cl[data-diff="del"] { font-size: 0; opacity: 0; }
.diff-pre.is-updated del { font-size: 0; opacity: 0; }

/* Strip the add/remove markings only once the transition has settled, and only
   for the plain before/after views — the marked (everything) view keeps them. */
.diff-pre.is-prior.is-settled del { background: transparent; box-shadow: none; text-decoration: none; }
.diff-pre.is-updated.is-settled ins { background: transparent; box-shadow: none; text-decoration: none; }

@media (prefers-reduced-motion: reduce) {
  .diff-pre .cl, .diff-pre ins, .diff-pre del { transition: none; }
}

/* ============================================================================
   Per-statement copy buttons — added by course.js to "Code and output" boxes
   ========================================================================== */
.repl-pre .cl { display: block; }
.repl-piece { display: block; position: relative; }
.repl-copy {
  position: absolute;
  top: 0;
  right: 6px;
  opacity: 0;
  transition: opacity .12s linear;
  font-family: var(--font-body);
  font-size: 0.62rem;
  line-height: 1.4;
  letter-spacing: 0.03em;
  padding: 1px 7px;
  border-radius: 4px;
  cursor: pointer;
  background: rgba(255,255,255,.10);
  color: #cdd6db;
  border: 1px solid rgba(255,255,255,.28);
}
.repl-piece:hover .repl-copy,
.repl-copy:focus-visible { opacity: 1; }
.repl-copy:hover { background: rgba(255,255,255,.20); color: #fff; }
.repl-copy.copied { opacity: 1; color: #5ed684; border-color: #5ed684; background: rgba(94,214,132,.12); }

@media (prefers-reduced-motion: reduce) { .repl-copy { transition: none; } }

/* ============================================================================
   Course contents pages (index.html)
   ========================================================================== */
.toc-meta {
  margin: -0.5rem 0 0.5rem;
  color: var(--ink-soft);
  font-size: 0.95rem;
}
.toc-meta b { color: var(--accent); font-weight: 650; }

.toc {
  list-style: none;
  margin: 1.5rem 0 0;
  padding: 0;
  counter-reset: lesson;
}
.toc li { counter-increment: lesson; }
.toc li a {
  display: flex;
  align-items: baseline;
  gap: 0.8rem;
  padding: 0.6rem 0.5rem;
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: var(--ink);
}
.toc li:first-child a { border-top: 1px solid var(--rule); }
.toc li a::before {
  content: counter(lesson);
  flex: 0 0 1.8rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 650;
  color: var(--accent);
}
.toc li a:hover { background: #f5f8fb; }
.toc li a:hover .toc-title { text-decoration: underline; text-decoration-color: var(--accent-2); text-underline-offset: 2px; }

/* ============================================================================
   Progress, resume & completion — added by course.js (stored in localStorage)
   ========================================================================== */
.progress {
  display: flex; align-items: center; gap: 0.85rem;
  margin: 0.75rem 0 0.5rem; flex-wrap: wrap;
}
.progress-bar {
  flex: 1 1 10rem; min-width: 8rem; height: 8px;
  background: var(--rule); border-radius: 5px; overflow: hidden;
}
.progress-bar span { display: block; height: 100%; background: var(--accent-2); border-radius: 5px; transition: width .3s; }
.progress-text { font-size: 0.9rem; color: var(--ink-soft); white-space: nowrap; }
.resume-btn {
  font-size: 0.88rem; font-weight: 600; color: #fff; background: var(--accent-2);
  padding: 0.3rem 0.85rem; border-radius: 6px; text-decoration: none; white-space: nowrap;
}
.resume-btn:hover { background: #0a6e36; }
.progress-reset {
  font-family: var(--font-body); font-size: 0.72rem; color: var(--ink-soft);
  background: none; border: 0; cursor: pointer; text-decoration: underline;
}

/* ✓ on completed lessons in the contents list */
.toc li.done a::after { content: "✓"; margin-left: auto; color: var(--accent-2); font-weight: 700; }
.toc li.done a .toc-title { color: var(--ink-soft); }

/* Lesson-page strip: position + reading estimate, and a "Mark complete" toggle.
   Sits just above the prev/next nav (whose top border it absorbs). */
.lesson-progress {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  margin: 2.5rem 0 0; padding-top: 1.5rem; border-top: 1px solid var(--rule);
  font-size: 0.9rem; color: var(--ink-soft);
}
.lesson-progress + .lesson-nav { border-top: 0; margin-top: 1.1rem; padding-top: 0; }
.done-toggle {
  font-family: var(--font-body); font-size: 0.82rem; font-weight: 600;
  padding: 0.32rem 0.85rem; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--accent-2); background: transparent; color: var(--accent-2);
  transition: background-color .15s, color .15s;
}
.done-toggle:hover { background: rgba(10,125,62,.10); }
.done-toggle.is-done { background: var(--accent-2); color: #fff; }

/* Inter-course navigation: the four courses form a sequence. */
.course-series {
  margin: 2.5rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
  font-size: 0.92rem;
}
.course-series .label { color: var(--ink-soft); margin: 0 0 0.5rem; }
.course-series ol { list-style: none; margin: 0; padding: 0; counter-reset: course; }
.course-series li { counter-increment: course; margin: 0.15rem 0; }
.course-series li::before {
  content: counter(course) ".";
  color: var(--accent);
  font-weight: 650;
  margin-right: 0.5rem;
}
.course-series li.current { color: var(--ink-soft); }
.course-series li.current::after { content: " — you are here"; font-style: italic; color: var(--ink-soft); }

/* Connective-prose slots — rendered (optionally) from
   content/<course>/connective.yaml. Empty by default, so nothing shows until the
   slot is filled. Neutral spacing only; style further to taste. */
.lesson-intro { margin-bottom: 1.25rem; }
.lesson-signoff { margin-top: 1.75rem; }

/* Optional header sketches — starter styles for the commented markup in
   site.html.j2 (site_header) and course.html.j2 (course_header). Uncomment this
   block alongside the template markup, then restyle to taste. Inert until then.
.site-header {
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
  margin: 0 0 1.5rem; padding-bottom: 0.6rem; border-bottom: 1px solid var(--rule);
}
.site-header .site-title { font-weight: 700; font-size: 1.05rem; text-decoration: none; color: var(--accent); }
.site-header .site-nav { display: flex; gap: 0.9rem; flex-wrap: wrap; font-size: 0.9rem; }
.course-header { margin: 0 0 0.35rem; }
.course-header .course-kicker { display: block; font-size: 0.78rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-soft); }
.course-header .course-name { font-weight: 650; text-decoration: none; color: var(--accent); }
*/

/* ============================================================================
   Placeholder site chrome — rendered by base.html.j2 when the host site has
   NOT supplied its own base. Deliberately loud: if this is visible in a
   deployed page, the real chrome was never wired in. Disappears as soon as
   base.html.j2 is replaced or site_chrome_header is overridden.
   ========================================================================== */
.placeholder-chrome {
  background: repeating-linear-gradient(135deg, #ffe9a8, #ffe9a8 12px, #ffdf85 12px, #ffdf85 24px);
  border-bottom: 2px solid #c77700;
  color: #6a4a00;
  font-family: var(--font-body);
  font-size: 0.85rem;
  line-height: 1.45;
  padding: 0.6rem 1.1rem;
  text-align: center;
}
.placeholder-chrome code {
  background: rgba(0,0,0,.10);
  padding: 0.05em 0.35em;
  border-radius: 3px;
}

/* ============================================================================
   Landing page (out/index.html) — the site root listing the four courses.
   Echoes the holdenweb.com home-page structure: pageheader + tagline, a
   content area, and the shared licence footer from base.html.j2.
   ========================================================================== */
main.landing {
  max-width: var(--measure, 46rem);
  margin: 0 auto;
  padding: 0 1.2rem;
}
.landing .pageheader {
  margin: 2.2rem 0 1.4rem;
  padding-bottom: 0.9rem;
  border-bottom: 2px solid var(--accent);
}
.landing .pageheader h1 {
  margin: 0;
  font-size: 2.1rem;
  line-height: 1.15;
  color: var(--ink);
}
.landing .tagline {
  margin-top: 0.35rem;
  font-size: 1.05rem;
  color: var(--ink-soft);
}
.landing-intro { color: var(--ink-soft); margin-bottom: 1.6rem; }

.course-cards {
  list-style: none;
  margin: 0 0 2.5rem;
  padding: 0;
  display: grid;
  gap: 0.9rem;
}
.course-card { margin: 0; }
.course-card-link {
  display: block;
  padding: 1rem 1.15rem;
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius);
  background: #fff;
  text-decoration: none;
  color: inherit;
  transition: border-color .12s ease, box-shadow .12s ease, transform .12s ease;
}
.course-card-link:hover {
  border-color: var(--accent-2);
  border-left-color: var(--accent-2);
  box-shadow: 0 2px 10px rgba(0,0,0,.07);
}
.course-card-kicker {
  display: block;
  font-size: 0.74rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.course-card-title {
  display: block;
  margin: 0.15rem 0 0.3rem;
  font-size: 1.18rem;
  font-weight: 650;
  color: var(--accent);
}
.course-card-blurb { display: block; color: var(--ink); }

/* ============================================================================
   Result annotations — hover/tap commentary on a single transcript line.
   build.py wraps the line in <span class="noted" data-note="ID"> and emits the
   prose once as <span class="note-body" id="ID">; course.js wires the reveal
   and shows it in the floating .note-pop (appended to <body>, so the box's
   overflow:hidden never clips it).
   ========================================================================== */
.noted {
  cursor: help;
  border-bottom: 1px dotted currentColor;
  border-radius: 1px;
}
.noted::after {                       /* discoverability cue: a small superscript ⓘ */
  content: "\24D8";
  font-family: var(--font-body);
  font-size: 0.72em;
  vertical-align: super;
  margin-left: 0.15em;
  opacity: 0.75;
}
.noted:hover, .noted:focus, .noted.is-open { outline: none; }
.interactive .noted { border-bottom-color: rgba(168,209,255,.55); }
.interactive .noted::after { color: #8cc6ff; }
.interactive .noted:hover, .interactive .noted.is-open { background: rgba(121,184,255,.16); }

.note-pop {
  position: absolute;
  z-index: 60;
  max-width: min(340px, 88vw);
  background: #16222c;
  color: #e7edf0;
  border: 1px solid #35505f;
  border-radius: 8px;
  padding: 0.6rem 0.75rem;
  font-family: var(--font-body);
  font-size: 0.9rem;
  line-height: 1.45;
  box-shadow: 0 8px 28px rgba(0,0,0,.34);
}
.note-pop p { margin: 0; }
.note-pop p + p { margin-top: 0.5rem; }
.note-pop code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: rgba(255,255,255,.10);
  padding: 0.05em 0.3em;
  border-radius: 3px;
}
.note-pop em { color: #9fb2c0; }      /* the [placeholder] marker reads as an aside */
.note-pop::after {                    /* little pointer toward the annotated line */
  content: "";
  position: absolute;
  left: var(--note-arrow, 1.5rem);
  border: 7px solid transparent;
}
.note-pop:not(.below)::after { top: 100%;  border-top-color: #16222c; }
.note-pop.below::after      { bottom: 100%; border-bottom-color: #16222c; }

@media (prefers-reduced-motion: no-preference) {
  .note-pop { transition: opacity .12s ease; }
}
