/* ==========================================================================
   THE FRENCH REVOLUTION · LESSON SLIDES — shared stylesheet
   Loaded once by index.html and used by every deck. Nothing here is
   deck-specific; slide CONTENT lives in decks/*.js.

   Same engine as the 91233 lesson site, re-skinned to the palette of
   frenchrev.mrhart.org: parchment page, cream cards, navy ink, revolution
   red, gold. Hairline rules, 2px corners, no shadows.
   Sized for a 65" screen at the front of a classroom — everything scales
   from ONE base font size, so it stays readable from the back row.

   SIZING NOTE. Slides used to size themselves from the viewport (vw/vh).
   Now that a sidebar shares the screen they size from the STAGE instead,
   using container units (cqw/cqh) against #frame. In Present mode the
   stage fills the window, so cq units and viewport units coincide and the
   projected slide is identical to what it always was.

   TO CHANGE COLOURS: edit :root.
   TO CHANGE CONTENT: edit the deck files in decks/.
   ========================================================================== */

/* --------------------------------------------------------------------------
   THE PALETTE. These are the frenchrev.mrhart.org tokens.

   One inversion worth knowing about: on the course site the PAGE is the
   darker parchment and the CARDS are the lighter cream, which is the
   opposite way round to the 91233 skin. --paper-2 is therefore LIGHTER
   than --paper here, so note cards lift off the page instead of sinking
   into it. --paper-3 goes the other way and is used for the demoted
   "talk, don't write" card and for empty progress track.

   CONTRAST. Every accent below is used three ways: as small-caps label text
   on cream, as a 10px card border, and as a chip with white text on it. So
   each one has to clear 4.5:1 against #F7F0DE AND against white. The bright
   gold #C9975A does not (2.3:1 on white), so it is kept for decoration only
   and --answer-bg carries a deeper bronze that passes both.
   -------------------------------------------------------------------------- */
:root{
  --paper:#EBE1CB;                       /* parchment — the page   */
  --paper-2:#F7F0DE;                     /* cream — cards lift     */
  --paper-3:#E1D5B9;                     /* sunk well, talk cards  */
  --ink:#2A2415;
  --ink-2:#4E432C;
  --ink-3:#6E6046;
  --rule:#D6C7A6;
  --rule-2:#C3B18B;

  --signal:#A02B2B;                      /* revolution red         */
  --signal-ink:#8E2222;                  /* 6.4:1 on cream         */
  --signal-soft:#F4E3D9;
  --pulse:#15223A;                       /* navy                   */
  --pulse-ink:#1D3157;
  --pulse-soft:#DFE4EE;

  /* interactive feedback — the one green in the system, because right/wrong
     needs universal classroom semantics that red cannot carry */
  --ok:#1F5C3A;
  --ok-soft:#DCEADF;
  --bad:#7D2020;

  /* task banners */
  --copy-bg:#15223A;                     /* navy   — copy this down      */
  --answer-bg:#8A6224;                   /* bronze — answer in your book */
  --discuss-bg:#5A5140;                  /* stone  — talk, don't write   */
  --on-accent:#FFFDF7;

  --gold:#C9975A;                        /* decoration only — see note   */

  --serif:"Playfair Display",Georgia,"Times New Roman",serif;
  --sans:"Spectral",Georgia,"Times New Roman",serif;
  --mono:"Space Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --radius:2px;
}

*{box-sizing:border-box}
/* kill default UA margins — in a flex column they don't collapse, so a stray
   1em top+bottom on every <p> silently eats ~2em of vertical space per block */
p,figure,figcaption,h1,h2,h3,h4{margin:0}
html,body{height:100%}
body{
  margin:0;background:var(--paper);color:var(--ink);
  font-family:var(--sans);overflow:hidden;
}

/* ---- the deck ---------------------------------------------------------- */
#deck{position:absolute;inset:0}

.slide{
  position:absolute;inset:0;
  display:none;flex-direction:column;
  padding:1.5em 1.9em 1.1em;
  /* SINGLE SCALING KNOB — ~33px on a 1920×1080 stage.
     Nudge this up or down if the back row still struggles. */
  font-size:calc(1.1cqw + 1.1cqh);
  animation:rise .18s ease-out;
}
.slide.is-live{display:flex}
@keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ---- slide furniture --------------------------------------------------- */
.slide__head{
  display:flex;align-items:baseline;gap:1em;
  border-bottom:1px solid var(--rule);padding-bottom:.4em;margin-bottom:.6em;flex:0 0 auto;
}
.kicker{
  font-family:var(--mono);font-size:.58em;letter-spacing:.16em;text-transform:uppercase;
  color:var(--signal-ink);white-space:nowrap;
}
.kicker--muted{color:var(--ink-3);margin-left:auto}

/* ---- THE CAUSAL THREAD MARKER ------------------------------------------
   Flags a slide as evidence for one of the essay arguments on the Excellence
   Atlas. Students should see the case accumulating as they go, not have to
   reassemble it in October.
   ------------------------------------------------------------------------ */
.thread{
  font-family:var(--mono);font-size:.5em;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--on-accent);background:var(--signal-ink);
  padding:.34em .6em;border-radius:var(--radius);white-space:nowrap;
}

h1.slide__title{
  font-family:var(--serif);font-weight:500;letter-spacing:-.02em;
  font-size:2em;line-height:1.06;margin:0;
}

/* auto rather than hidden: if a slide is ever over-filled it scrolls
   instead of silently cutting the last line off in front of a class.

   `safe center` balances a short slide in the space under the title instead
   of stranding it at the top. The `safe` keyword is the important half: when
   content DOES fill the slide it falls back to flex-start, so nothing is ever
   centred out of reach above the scroll origin. */
.slide__body{flex:1 1 auto;display:flex;flex-direction:column;gap:.6em;min-height:0;
  overflow:auto;justify-content:safe center}

/* ---- text blocks ------------------------------------------------------- */
.lead{font-family:var(--serif);font-size:1.5em;line-height:1.3}
p.body{font-size:1.12em;line-height:1.38;max-width:68ch}
p.body.wide{max-width:none}
.dim{color:var(--ink-2)}
strong{font-weight:600}
em.term{font-style:normal;font-weight:600;color:var(--signal-ink)}

ul.points{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.38em}
ul.points li{
  font-size:1.12em;line-height:1.32;padding-left:1.4em;position:relative;
}
ul.points li::before{
  content:"";position:absolute;left:.3em;top:.6em;
  width:.4em;height:1px;background:var(--rule-2);
}

/* ---- source box -------------------------------------------------------- */
.source{
  border:1px solid var(--rule-2);border-left:5px solid var(--signal);
  background:var(--paper-2);border-radius:var(--radius);
  padding:.7em .95em;display:flex;flex-direction:column;gap:.38em;
}
.source__tag{
  font-family:var(--mono);font-size:.58em;letter-spacing:.16em;text-transform:uppercase;
  color:var(--signal-ink);
}
.source__text{font-family:var(--serif);font-size:1.3em;line-height:1.32}
.source__text::before{content:"\201C"}
.source__text::after{content:"\201D"}
.source__attr{font-family:var(--mono);font-size:.56em;line-height:1.45;color:var(--ink-3)}

/* ---- questions --------------------------------------------------------- */
ol.qs{margin:0;padding:0;list-style:none;counter-reset:q;display:flex;flex-direction:column;gap:.34em}
ol.qs li{
  counter-increment:q;position:relative;padding-left:1.95em;
  font-size:1.12em;line-height:1.32;
}
ol.qs li::before{
  content:counter(q);position:absolute;left:0;top:.05em;
  width:1.4em;height:1.4em;display:grid;place-items:center;
  font-family:var(--mono);font-size:.7em;font-weight:600;
  color:var(--ink-2);border:1px solid var(--rule-2);border-radius:var(--radius);
  background:var(--paper);
}

/* ---- THE NOTE CARD -----------------------------------------------------
   The single most important object on a slide. If it is in the box, it goes
   in the book. Deliberately the loudest thing on screen.
   ------------------------------------------------------------------------ */
.note{
  border:1px solid var(--rule-2);border-left:10px solid var(--copy-bg);
  border-radius:var(--radius);background:var(--paper-2);
  padding:.7em 1.1em;display:flex;flex-direction:column;gap:.45em;
}
.note__label{
  font-family:var(--mono);font-size:.62em;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--copy-bg);
}
.note__body{font-size:1.24em;line-height:1.34}
.note ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.34em}
.note ul li{font-size:1.24em;line-height:1.3;padding-left:1.15em;position:relative}
.note ul li::before{content:"";position:absolute;left:0;top:.58em;width:.55em;height:2px;background:var(--copy-bg)}
.note ol{margin:0;padding:0;list-style:none;counter-reset:n;display:flex;flex-direction:column;gap:.34em}
.note ol li{counter-increment:n;font-size:1.18em;line-height:1.3;padding-left:1.6em;position:relative}
.note ol li::before{
  content:counter(n);position:absolute;left:0;top:.02em;width:1.15em;height:1.15em;
  display:grid;place-items:center;font-family:var(--mono);font-size:.72em;font-weight:600;
  color:var(--on-accent);background:var(--copy-bg);border-radius:var(--radius);
}
/* amber = answer, not copy */
.note--task{border-left-color:var(--answer-bg)}
.note--task .note__label{color:var(--answer-bg)}
.note--task ul li::before{background:var(--answer-bg)}
.note--task ol li::before{background:var(--answer-bg)}
/* grey = talk, don't write */
.note--talk{border-left-color:var(--discuss-bg);background:var(--paper-3)}
.note--talk .note__label{color:var(--discuss-bg)}
.note--talk ul li::before{background:var(--discuss-bg)}
.note--talk ol li::before{background:var(--discuss-bg)}
/* red = essay ammunition. THESE RULES MUST STAY BELOW .note — they used to sit
   further up the file, where .note's `border-left` shorthand overrode them and
   every argument card rendered as an ordinary blue copy card. The one card that
   most needed to look different looked identical. */
.note--argument{border-left-color:var(--signal);background:var(--signal-soft)}
.note--argument .note__label{color:var(--signal-ink)}
.note--argument ul li::before{background:var(--signal)}
.note--argument ol li::before{background:var(--signal)}

/* ---- pull quote — evidence without the wall of text -------------------- */
.pull{border-left:5px solid var(--signal);padding:.1em 0 .1em .95em;
  display:flex;flex-direction:column;gap:.35em}
.pull__text{font-family:var(--serif);font-size:1.62em;line-height:1.26}
.pull__text::before{content:"\201C"}
.pull__text::after{content:"\201D"}
.pull__attr{font-family:var(--mono);font-size:.56em;line-height:1.4;color:var(--ink-3)}

/* ---- MODEL PARAGRAPH — what the grade looks like on the page -----------
   Serif body, because it is prose to be read as prose rather than notes to
   copy. Merit is amber like a task card; Excellence is vermilion like the
   argument bank, so the colour already says which shelf it belongs on.
   ------------------------------------------------------------------------ */
.exem{
  border:1px solid var(--rule-2);border-left:10px solid var(--answer-bg);
  border-radius:var(--radius);background:var(--paper-2);
  padding:.7em 1.1em;display:flex;flex-direction:column;gap:.45em;
}
.exem__label{
  font-family:var(--mono);font-size:.62em;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--answer-bg);
}
.exem__text{font-family:var(--serif);font-size:1.12em;line-height:1.36}
.exem__moves{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.3em}
.exem__moves li{
  font-size:.92em;line-height:1.3;color:var(--ink-2);
  padding-left:1.15em;position:relative;
}
.exem__moves li::before{
  content:"";position:absolute;left:0;top:.52em;width:.55em;height:2px;background:var(--answer-bg);
}
/* Excellence variant — keep BELOW .exem, same trap as .note--argument */
.exem--e{border-left-color:var(--signal);background:var(--signal-soft)}
.exem--e .exem__label{color:var(--signal-ink)}
.exem--e .exem__moves li::before{background:var(--signal)}

/* ---- teacher talking point — Mr Hart's cue, not a student instruction -- */
.teach{
  display:none;   /* hidden from the class — press T to reveal */
  flex:0 0 auto;margin-top:.65em;border-radius:var(--radius);
  background:var(--signal-soft);border-left:6px solid var(--signal);
  padding:.55em .95em;align-items:baseline;gap:.9em;
}
body.show-teach .teach{display:flex}
.teach__label{
  font-family:var(--mono);font-size:.64em;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--signal-ink);white-space:nowrap;
}
.teach__text{font-size:1.02em;line-height:1.26;color:var(--ink)}

/* ---- figures and split layouts ----------------------------------------- */
.figure{display:flex;flex-direction:column;gap:.3em;min-width:0}
/* width AND height auto, with both maxima set, lets the browser fit the image
   inside the box on whichever axis binds first — no letterboxing, no overflow.

   align-self:start is load-bearing, not tidying. .figure is a flex column, so
   the default align-items:stretch stretches the <img> to the container's full
   width and silently overrides width:auto — which distorted every image whose
   shape didn't happen to match its box. The Ottoman sanjaks map (portrait) was
   being squashed 41% and shown to the class geographically wrong. */
.figure img{
  align-self:start;
  max-width:100%;max-height:40cqh;width:auto;height:auto;
  border:1px solid var(--rule);border-radius:var(--radius);background:var(--paper-2);
}
/* Portrait maps: height binds first, so the default cap squeezes the width to
   nothing. The 1947 partition plan is 0.37 aspect and unreadable at 40cqh.
   56 and not more: this cap is in cqh, so it does NOT shrink when auto-fit
   reduces the type — the caption and attribution underneath still have to fit
   in what is left, and at 66cqh they were clipped by the frame. */
.figure--tall img{max-height:56cqh}
.figure__cap{font-size:.88em;line-height:1.25;color:var(--ink-2)}
.figure__attr{font-family:var(--mono);font-size:.54em;line-height:1.4;color:var(--ink-3)}

/* image beside text — grid-template-columns is set per slide */
.split{display:grid;gap:1.15em;align-items:start;min-height:0}
.split__side{display:flex;flex-direction:column;gap:.6em;min-width:0}

/* ---- two columns ------------------------------------------------------- */
.cols{display:grid;grid-template-columns:1fr 1fr;gap:.9em}
.col{border:1px solid var(--rule);border-radius:var(--radius);padding:.65em .8em;background:var(--paper-2)}
.col h3{font-family:var(--sans);font-size:.76em;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-3);margin:0 0 .55em;font-weight:600}
.col--a{border-top:4px solid var(--signal)}
.col--b{border-top:4px solid var(--pulse)}
.col ul.points li{font-size:1.02em}

/* ---- stat strip -------------------------------------------------------- */
.stats{display:flex;gap:1.5em;flex-wrap:wrap;margin-top:.15em}
.stat{border-left:3px solid var(--signal);padding-left:.65em}
.stat b{display:block;font-family:var(--serif);font-size:2.3em;line-height:1;font-weight:600}
.stat span{font-family:var(--mono);font-size:.62em;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-3)}
/* figures beside an image have less room — shrink so a row of four still fits */
.split .stats{gap:.95em}
.split .stat b{font-size:1.8em}
.split .stat span{font-size:.55em;letter-spacing:.06em}

/* ---- timeline ---------------------------------------------------------- */
/* the marker dots sit ON the rule, so the timeline needs a left margin —
   without it the dots poke outside .slide__body and get clipped by its overflow */
.tl{display:flex;flex-direction:column;gap:.26em;border-left:2px solid var(--rule-2);
  margin-left:.8em;padding-left:1.3em}
.tl__row{display:grid;grid-template-columns:6.6em 1fr;gap:.9em;align-items:baseline;position:relative}
.tl__row::before{
  content:"";position:absolute;left:-1.67em;top:.4em;width:.55em;height:.55em;
  border-radius:50%;background:var(--paper);border:3px solid var(--signal);
}
.tl__when{font-family:var(--mono);font-size:.8em;font-weight:600;color:var(--signal-ink);letter-spacing:.01em}
.tl__what{font-size:1.06em;line-height:1.26}

/* ---- the banner -------------------------------------------------------- */
.banner{
  flex:0 0 auto;margin-top:.7em;border-radius:var(--radius);
  display:flex;align-items:center;gap:.95em;padding:.58em .95em;color:var(--on-accent);
}
.banner__label{
  font-family:var(--mono);font-weight:600;font-size:.82em;letter-spacing:.13em;
  text-transform:uppercase;white-space:nowrap;
  border-right:1px solid rgba(255,255,255,.45);padding-right:.95em;
}
.banner__text{font-size:1.06em;line-height:1.24;font-weight:500}
.banner--copy{background:var(--copy-bg)}
.banner--answer{background:var(--answer-bg)}
.banner--discuss{background:var(--discuss-bg)}

/* ---- title slides ------------------------------------------------------ */
.slide--title{justify-content:center;padding:2em 2.4em}
.slide--title .slide__head{border:0;margin-bottom:1em;padding:0}
.slide--title h1.slide__title{font-size:3.4em;max-width:20ch}
.slide--title .lead{max-width:32ch;color:var(--ink-2);margin-top:.5em}
.title__meta{
  margin-top:1.4em;display:flex;gap:2em;flex-wrap:wrap;
  font-family:var(--mono);font-size:.72em;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);
}
.title__meta b{color:var(--ink);font-weight:600}

/* ---- chrome ------------------------------------------------------------ */
#bar{
  position:absolute;left:0;right:0;bottom:0;height:.22em;background:var(--paper-3);z-index:40;
  font-size:calc(0.9cqw + 0.9cqh);
}
#bar i{display:block;height:100%;background:var(--signal);transition:width .2s ease}

/* The HUD sits over the banner, so it fades out while you teach and comes
   back on any mouse movement. Keyboard navigation is unaffected. */
#hud{
  position:absolute;right:.9em;bottom:.9em;z-index:50;display:flex;align-items:center;gap:.55em;
  font-size:calc(0.9cqw + 0.9cqh);
  background:var(--paper);border-radius:var(--radius);padding:.25em .3em;
  opacity:0;pointer-events:none;transition:opacity .25s ease;
}
#hud.is-awake{opacity:1;pointer-events:auto}
#hud button{
  font-family:var(--mono);font-size:.6em;letter-spacing:.08em;
  background:var(--paper);color:var(--ink-2);border:1px solid var(--rule-2);
  border-radius:var(--radius);padding:.42em .7em;cursor:pointer;line-height:1;
}
#hud button:hover{border-color:var(--signal);color:var(--signal-ink)}
#count{font-family:var(--mono);font-size:.6em;color:var(--ink-3);letter-spacing:.08em}

/* click zones for advancing without a clicker */
.zone{position:absolute;top:0;bottom:2.6em;width:14cqw;z-index:10;cursor:pointer;background:transparent}
.zone--prev{left:0}
.zone--next{right:0}

/* ---- overview (press O) ------------------------------------------------ */
#ov{
  position:absolute;inset:0;background:var(--paper);z-index:60;display:none;
  overflow-y:auto;padding:2.4em;
  font-size:calc(0.85cqw + 0.85cqh);   /* scales with the stage, like the slides */
}
#ov.is-open{display:block}
#ov h2{font-family:var(--serif);font-weight:500;font-size:1.7em;margin:0 0 1.2em}
.ov__lesson{font-family:var(--mono);font-size:.72em;letter-spacing:.16em;text-transform:uppercase;
  color:var(--signal-ink);margin:1.6em 0 .6em;border-top:1px solid var(--rule);padding-top:.8em}
.ov__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(11em,1fr));gap:.6em}
.ov__card{
  text-align:left;border:1px solid var(--rule);border-radius:var(--radius);background:var(--paper-2);
  padding:.7em .8em;cursor:pointer;font-family:var(--sans);color:var(--ink);
  display:flex;flex-direction:column;gap:.35em;font-size:.85em;line-height:1.3;
}
.ov__card:hover{border-color:var(--signal)}
.ov__card.is-cur{border-color:var(--signal);background:var(--signal-soft)}
.ov__n{font-family:var(--mono);font-size:.66em;color:var(--ink-3)}
.ov__dot{width:100%;height:3px;border-radius:2px;margin-top:.2em}

/* ==========================================================================
   INTERACTIVE BLOCKS — quiz, order, reveal, timer, three
   Behaviour in deck-fx.js. A slide containing any .ia block gets the edge
   click-zones switched off (see #frame.has-ia below) so its buttons own
   their clicks; navigation stays on the keyboard and the HUD.
   ========================================================================== */

@keyframes ia-pop{50%{transform:scale(1.05)}}
@keyframes ia-shake{25%{transform:translateX(-.28em)}75%{transform:translateX(.28em)}}
.shake{animation:ia-shake .22s}

#frame.has-ia .zone{display:none}

/* BUTTONS DO NOT INHERIT font-size — the UA sets 13.33px on them outright, and
   inheritance never gets a look in. Every em inside a control therefore
   resolves against 13.33px instead of the slide's size. This is not cosmetic:
   with the slide auto-fitted to 76px, the chronology chips were rendering at
   about a sixth of the intended size — unreadable from the back row, and it
   looked like an auto-fit fault rather than a one-line CSS omission.
   Any control added here needs an explicit font-size or this line. */
.order__chip,.reveal__card{font-size:inherit}

/* ---- quiz -------------------------------------------------------------- */
.quiz{
  border:1px solid var(--rule-2);border-left:10px solid var(--pulse);
  border-radius:var(--radius);background:var(--paper-2);
  padding:.7em 1.1em;display:flex;flex-direction:column;gap:.55em;
}
.quiz__head{display:flex;align-items:baseline;gap:1.2em}
.quiz__label{
  font-family:var(--mono);font-size:.62em;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--pulse-ink);
}
.quiz__count{font-family:var(--mono);font-size:.62em;color:var(--ink-3);margin-left:auto}
.quiz__score{font-family:var(--mono);font-size:.62em;color:var(--ok)}
.quiz__q{font-size:1.24em;line-height:1.32}
.quiz__opts{display:grid;grid-template-columns:1fr 1fr;gap:.45em}
.quiz__opt{
  display:flex;gap:.65em;align-items:center;text-align:left;cursor:pointer;
  font-family:var(--sans);font-size:1.02em;line-height:1.26;color:var(--ink);
  background:var(--paper);border:1px solid var(--rule-2);border-radius:var(--radius);
  padding:.5em .7em;
}
.quiz__opt:hover:not(:disabled){border-color:var(--pulse)}
.quiz__opt:disabled{cursor:default}
.quiz__key{
  flex:0 0 auto;width:1.55em;height:1.55em;display:grid;place-items:center;
  font-family:var(--mono);font-size:.72em;font-weight:600;color:var(--ink-2);
  border:1px solid var(--rule-2);border-radius:var(--radius);background:var(--paper-2);
}
.quiz__opt.is-right{border-color:var(--ok);background:var(--ok-soft);animation:ia-pop .3s}
.quiz__opt.is-right .quiz__key{background:var(--ok);border-color:var(--ok);color:var(--on-accent)}
.quiz__opt.is-wrong{border-color:var(--signal);background:var(--signal-soft);opacity:.55}
/* the why-line reserves its height from the start, so revealing it cannot
   change the size the slide was auto-fitted to */
.quiz__why{
  visibility:hidden;min-height:1.4em;
  font-size:.98em;line-height:1.32;color:var(--ink-2);
  border-left:4px solid var(--ok);padding-left:.7em;
}
.quiz__why.is-shown{visibility:visible}

/* ---- order (chronology game) ------------------------------------------- */
.order{display:flex;flex-direction:column;gap:.55em}
.order__label{
  font-family:var(--mono);font-size:.62em;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--pulse-ink);
}
/* Sized deliberately large. A sparse slide stops growing at the 1.5× fit cap,
   so a game built from small chips ends up as postage stamps in the middle of
   a 65" screen. The chips carry their own weight instead. */
.order__grid{display:grid;grid-template-columns:1fr 1fr;gap:.55em}
.order__chip{
  display:grid;grid-template-columns:1.9em 1fr;grid-template-rows:auto auto;
  column-gap:.75em;align-items:center;text-align:left;cursor:pointer;
  font-family:var(--sans);color:var(--ink);
  background:var(--paper);border:1px solid var(--rule-2);border-radius:var(--radius);
  padding:.62em .85em;
}
.order__chip:hover:not(.is-locked){border-color:var(--pulse)}
.order__n{
  grid-row:1/3;width:1.75em;height:1.75em;display:grid;place-items:center;
  font-family:var(--mono);font-size:.86em;font-weight:600;color:var(--on-accent);
  background:var(--rule-2);border-radius:50%;
}
.order__t{font-size:1.16em;line-height:1.26}
/* dates are the answer key — space reserved, revealed only when locked in */
.order__when{
  grid-column:2;visibility:hidden;
  font-family:var(--mono);font-size:.66em;letter-spacing:.08em;color:var(--signal-ink);
}
.order__chip.is-locked{border-color:var(--ok);background:var(--ok-soft);cursor:default;animation:ia-pop .3s}
.order__chip.is-locked .order__n{background:var(--ok)}
.order__chip.is-locked .order__when{visibility:visible}

/* ---- reveal (flip cards) ------------------------------------------------ */
.reveal{display:flex;flex-direction:column;gap:.55em}
.reveal__label{
  font-family:var(--mono);font-size:.62em;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--pulse-ink);
}
.reveal__grid{display:grid;gap:.5em}
.reveal__card{
  perspective:900px;background:none;border:0;padding:0;cursor:pointer;
  height:6.6em;font-family:var(--sans);color:var(--ink);
}
.reveal__inner{
  position:relative;display:block;width:100%;height:100%;
  transition:transform .45s;transform-style:preserve-3d;
}
.reveal__card.is-flipped .reveal__inner{transform:rotateY(180deg)}
.reveal__front,.reveal__back{
  position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  display:grid;place-items:center;padding:.4em .8em;text-align:center;
  border:1px solid var(--rule-2);border-left:6px solid var(--pulse);border-radius:var(--radius);
}
.reveal__front{background:var(--paper-2);font-family:var(--serif);font-size:1.3em}
.reveal__back{background:var(--pulse-soft);transform:rotateY(180deg);font-size:.92em;line-height:1.3}

/* ---- timer strip -------------------------------------------------------- */
.qtimer{
  display:flex;align-items:center;gap:.8em;
  border:1px solid var(--rule-2);border-radius:var(--radius);background:var(--paper-2);
  padding:.4em .8em;
}
.qtimer__label{
  font-family:var(--mono);font-size:.62em;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--pulse-ink);white-space:nowrap;
}
.qtimer__digits{
  font-family:var(--mono);font-size:1.5em;font-weight:600;
  min-width:3em;text-align:center;font-variant-numeric:tabular-nums;
}
.qtimer.is-final .qtimer__digits{color:var(--signal-ink);animation:ia-pop .5s infinite}
.qtimer.is-done .qtimer__digits{color:var(--signal-ink)}
.qtimer__bar{flex:1 1 auto;height:.42em;background:var(--paper-3);border-radius:2px;overflow:hidden}
.qtimer__fill{display:block;height:100%;background:var(--pulse);transition:width .25s linear}
.qtimer.is-final .qtimer__fill,.qtimer.is-done .qtimer__fill{background:var(--signal)}
.qtimer__btn{
  font-family:var(--mono);font-size:.6em;letter-spacing:.08em;text-transform:uppercase;
  background:var(--paper);color:var(--ink-2);border:1px solid var(--rule-2);
  border-radius:var(--radius);padding:.45em .8em;cursor:pointer;line-height:1;
}
.qtimer__btn:hover{border-color:var(--pulse);color:var(--pulse-ink)}

/* ---- three (3D scene panel) --------------------------------------------- */
/* Deliberately the one dark object in the design system — a change of
   register, so the room looks up. Colours inside the scene are the same
   palette translated to the dark ground. */
.three{
  position:relative;border:1px solid var(--rule-2);border-radius:var(--radius);
  background:oklch(0.21 0.02 265);overflow:hidden;
}
.three canvas{position:absolute;inset:0;display:block;width:100%!important;height:100%!important}
.three__fallback{
  display:none;position:absolute;inset:0;place-items:center;
  font-family:var(--mono);font-size:.66em;color:oklch(0.8 0.01 265);
}
/* the caption sits over the scene, so it carries its own scrim — without one
   it was competing with the globe for the same pixels */
.three__cap{
  position:absolute;left:0;right:0;bottom:0;z-index:2;
  padding:1.6em 1.1em .8em;
  font-size:.88em;line-height:1.3;color:oklch(0.93 0.005 265);
  background:linear-gradient(to top, oklch(0.21 0.02 265) 42%, transparent);
}
.three__cap b{color:oklch(0.8 0.12 40)}

@media print{
  body{overflow:visible}
  #rail,#hud,#bar,.zone,#ov{display:none!important}
  #stage{padding:0;background:#fff}
  #frame{aspect-ratio:auto;max-width:none;max-height:none;border:0;container-type:normal}
  #deck{position:static}
  /* !important because auto-fit writes an inline font-size on every slide */
  .slide{display:flex!important;position:relative;page-break-after:always;height:100vh;font-size:16px!important}
}
/* ==========================================================================
   THE SHELL — lesson rail on the left, stage on the right
   ==========================================================================
   Two modes:
     BROWSE  (default)  rail visible, stage letterboxed to 16:9 so the
                        preview is exactly what the class will see.
     PRESENT (F, or the PRESENT button) rail gone, stage fills the window,
                        fullscreen requested. Escape or F comes back.
   ========================================================================== */

#shell{display:flex;height:100%;overflow:hidden}

/* ---- the rail ----------------------------------------------------------- */
#rail{
  flex:0 0 20rem;width:20rem;
  border-right:1px solid var(--rule);background:var(--paper-2);
  display:flex;flex-direction:column;overflow:hidden;
}
body.present #rail{display:none}

#rail__head{
  flex:0 0 auto;padding:1.15rem 1.15rem .85rem;border-bottom:1px solid var(--rule);
}
#rail__head h1{
  font-family:var(--serif);font-weight:500;font-size:1.24rem;line-height:1.15;
  letter-spacing:-.01em;margin:0 0 .3rem;
}
#rail__head p{
  font-family:var(--mono);font-size:.62rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-3);margin:0;
}

#rail__body{flex:1 1 auto;overflow-y:auto;padding:.5rem 0 1.2rem;
  scrollbar-width:thin;scrollbar-color:var(--rule-2) transparent}

.unit{
  font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-3);
  padding:1.1rem 1.15rem .45rem;display:flex;align-items:baseline;gap:.5rem;
}
.unit::after{content:"";flex:1 1 auto;height:1px;background:var(--rule)}
.unit--soon{color:var(--rule-2)}

/* ---- a lesson row ------------------------------------------------------- */
.lrow{
  display:block;width:100%;text-align:left;cursor:pointer;
  font-family:var(--sans);color:var(--ink);background:transparent;
  border:0;border-left:3px solid transparent;
  padding:.5rem 1.15rem .55rem 1.05rem;line-height:1.25;
}
.lrow:hover{background:var(--paper-3)}
.lrow.is-cur{border-left-color:var(--signal);background:var(--paper)}
.lrow__n{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.13em;text-transform:uppercase;
  color:var(--ink-3);display:block;margin-bottom:.16rem;
}
.lrow.is-cur .lrow__n{color:var(--signal-ink)}
.lrow__t{font-size:.86rem;display:block}
.lrow.is-cur .lrow__t{font-weight:500}
.lrow__meta{
  font-family:var(--mono);font-size:.58rem;color:var(--ink-3);
  display:block;margin-top:.2rem;
}

/* planned but not built — visible so the shape of the course is obvious */
.lrow--soon{cursor:default;color:var(--rule-2)}
.lrow--soon:hover{background:transparent}
.lrow--soon .lrow__n,.lrow--soon .lrow__meta{color:var(--rule-2)}

/* ---- slide list under the open lesson ----------------------------------- */
.slist{display:none;padding:.1rem 0 .5rem;background:var(--paper);
  border-left:3px solid var(--signal)}
.lrow.is-cur + .slist{display:block}
.srow{
  display:flex;gap:.55rem;width:100%;text-align:left;cursor:pointer;
  font-family:var(--sans);font-size:.76rem;line-height:1.24;color:var(--ink-2);
  background:transparent;border:0;padding:.26rem 1.15rem .26rem 1.5rem;
}
.srow:hover{color:var(--ink);background:var(--paper-3)}
.srow.is-cur{color:var(--signal-ink);font-weight:500}
.srow__n{font-family:var(--mono);font-size:.62rem;color:var(--ink-3);flex:0 0 1.5rem}
.srow.is-cur .srow__n{color:var(--signal-ink)}
.srow__d{flex:0 0 3px;border-radius:2px;background:var(--rule)}

#rail__foot{
  flex:0 0 auto;border-top:1px solid var(--rule);padding:.7rem 1.15rem;
  display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
}
#rail__foot a,#rail__foot button{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink-2);text-decoration:none;background:var(--paper);
  border:1px solid var(--rule-2);border-radius:var(--radius);padding:.4rem .6rem;
  cursor:pointer;line-height:1;
}
#rail__foot a:hover,#rail__foot button:hover{border-color:var(--signal);color:var(--signal-ink)}
#rail__foot .go{background:var(--signal);border-color:var(--signal);color:var(--on-accent)}
#rail__foot .go:hover{color:var(--on-accent);filter:brightness(1.07)}

/* ---- the stage ---------------------------------------------------------- */
#stage{
  flex:1 1 auto;min-width:0;display:grid;place-items:center;
  padding:1.1rem;background:var(--paper-3);
}
#frame{
  position:relative;overflow:hidden;background:var(--paper);
  border:1px solid var(--rule-2);border-radius:var(--radius);
  /* container-type:size is what makes cqw/cqh in the slide CSS work */
  container-type:size;
  aspect-ratio:16/9;width:100%;max-width:100%;max-height:100%;
}
body.present #stage{padding:0;background:var(--paper)}
body.present #frame{aspect-ratio:auto;width:100%;height:100%;max-width:none;border:0;border-radius:0}

/* keyboard hint, shown only in browse mode */
#hint{
  position:absolute;left:.9em;bottom:.9em;z-index:45;
  font-family:var(--mono);font-size:calc(0.55cqw + 0.55cqh);color:var(--ink-3);
  opacity:0;transition:opacity .25s ease;pointer-events:none;letter-spacing:.06em;
}
#hint.is-awake{opacity:.75}
body.present #hint{display:none}

/* ---- narrow screens: rail becomes a top strip --------------------------- */
@media (max-width:820px){
  #shell{flex-direction:column}
  #rail{flex:0 0 auto;width:100%;max-height:45vh;border-right:0;border-bottom:1px solid var(--rule)}
  #stage{padding:.6rem}
}

/* ==========================================================================
   FRENCH REVOLUTION SKIN — additions on top of the shared engine
   Everything above this line is the 91233 renderer's stylesheet, re-coloured
   in :root. Everything below is specific to this course.
   ========================================================================== */

/* ---- the tricolour ------------------------------------------------------
   Three flat bands, in the order they appear on the cockade Lafayette handed
   the king on 17 July 1789: blue and red are the colours of Paris, white is
   the colour of the Bourbons. It reads as decoration; it is also the first
   thing on the first slide of Lesson 7, so it is worth being right about.
   ------------------------------------------------------------------------ */
.tricolore{display:flex;height:3px;width:100%;border-radius:1px;overflow:hidden}
.tricolore i{flex:1 1 0}
.tricolore i:nth-child(1){background:#1E3A6E}
.tricolore i:nth-child(2){background:#FFFCF2}
.tricolore i:nth-child(3){background:var(--signal)}

#rail__head{position:relative}
#rail__head .tricolore{position:absolute;left:0;right:0;bottom:-1px;height:2px}

/* Title slides get the band under the rule, at slide scale. */
.slide--title .slide__head{
  border-bottom:0;
  position:relative;padding-bottom:.7em;
}
.slide--title .slide__head::after{
  content:"";position:absolute;left:0;bottom:0;width:7em;height:3px;
  background:linear-gradient(to right,#1E3A6E 0 33.3%,#FFFCF2 33.3% 66.6%,var(--signal) 66.6% 100%);
}

/* ---- Playfair runs large and light; Spectral runs small ----------------
   Two corrections measured against the 91233 original at 1920×1080, not
   guessed. Playfair's caps are taller than Newsreader's at the same size, so
   the 3.4em title slide overflowed 20ch; Spectral's x-height is smaller than
   Space Grotesk's, so note-card body text lost about a step of apparent size.
   ------------------------------------------------------------------------ */
.slide--title h1.slide__title{font-size:3.05em;max-width:19ch}
h1.slide__title{font-weight:600}
.note__body,.note ul li{font-size:1.28em}
.note ol li{font-size:1.22em}
ul.points li,ol.qs li,p.body{font-size:1.16em}

/* Spectral has real italics and small caps; the term marker uses them
   instead of colour alone, so it survives being photocopied in greyscale
   and does not depend on colour vision. */
em.term{font-style:italic;font-weight:600;color:var(--signal-ink)}

/* ---- KEY WORD chip ------------------------------------------------------
   {vocab:[{word, gloss}]} — the UDL vocabulary strip. Every lesson that
   introduces a technical term puts it here as well as in the prose, so a
   student who missed the sentence still meets the definition.
   ------------------------------------------------------------------------ */
.vocab{
  display:flex;flex-wrap:wrap;gap:.5em;
  border-top:1px solid var(--rule);padding-top:.55em;
}
.vocab__item{
  flex:1 1 14em;border:1px solid var(--rule-2);border-radius:var(--radius);
  background:var(--paper-2);padding:.45em .7em;
  border-left:4px solid var(--gold);
}
.vocab__word{
  font-family:var(--mono);font-size:.62em;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-2);display:block;margin-bottom:.15em;
}
.vocab__gloss{font-size:.95em;line-height:1.25;color:var(--ink)}

/* ---- STANDALONE FIGURES -------------------------------------------------
   A {figure:…} that is not inside a {split:…} is the whole point of its
   slide, so it should own the slide. Without this it inherits the flex
   column's start alignment, and a landscape painting sat in the top-left
   third of a 1920px screen with two-thirds of the slide empty beside it.

   The caps stay in cqh for the reason given above .figure--tall: auto-fit
   scales the TYPE, not these, so the caption and attribution underneath
   must still fit in what is left. 56/64 is measured, not guessed.
   ------------------------------------------------------------------------ */
.slide__body > .figure{align-items:center;text-align:center}
.slide__body > .figure img{align-self:center;max-height:46cqh}
.slide__body > .figure--tall img{max-height:54cqh}
/* Nothing else on the slide? Then the picture gets the slide. */
.slide__body > .figure:only-child img{max-height:60cqh}
.slide__body > .figure--tall:only-child img{max-height:68cqh}
.slide__body > .figure .figure__cap,
.slide__body > .figure .figure__attr{max-width:80ch;margin-inline:auto}
