/* Slides feature — styles (loaded by crimreview.html as /slides.css).
   EVERY selector in this file is scoped to #slides — checked mechanically, zero rules
   escape the screen — so nothing here can reach any other screen.
   Visual language is copied from lectures.css so Slides and Lectures read as
   the same feature family; the class prefix is sl- (not lec-) so the two never share
   a rule and one can be restyled without touching the other. */

/* Screen padding: #slides carries .shelled, which has no padding of its own, so
   without this the header sits flush against the side panel. The value is the one
   the approved 2026-07-27 "subject-card unification (draft v5)" gave Lectures /
   Upload / Question Bank, so Slides lines up with them pixel-for-pixel. */
#slides{padding:26px 30px 60px}

#slides .sl-phdr{margin-bottom:20px}
#slides .sl-title{font-family:'Syne',sans-serif;font-size:22px;font-weight:800}
#slides .sl-sub{font-size:12.5px;color:var(--mut);margin-top:4px;max-width:660px;line-height:1.55}
#slides .sl-load,#slides .sl-empty{font-size:13px;color:var(--mut);padding:16px 2px}

/* action bar above the accordions */
#slides .sl-bar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:18px}
#slides .sl-new{display:inline-flex;align-items:center;gap:8px;background:rgba(var(--gG),.09);border:1px solid rgba(var(--gG),.4);color:var(--acc);border-radius:9px;padding:9px 16px;font-size:13px;font-weight:600;cursor:pointer;font-family:inherit}
#slides .sl-new:hover{background:rgba(var(--gG),.16)}
#slides .sl-new:disabled{opacity:.5;cursor:default}
#slides .sl-new svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

/* Subject accordion. Geometry is the POST-unification Lectures geometry (radius 12,
   margin 10, head padding 15/16, chevron 12px) — i.e. lectures.css's base values with
   the 2026-07-27 draft-v5 overrides already folded in, so nothing here needs a second
   rule to win a cascade fight with itself. */
#slides .sl-grp{background:var(--sur);border:1px solid var(--bdr);border-radius:12px;margin-bottom:10px;overflow:hidden}
#slides .sl-ghead{display:flex;align-items:center;gap:12px;padding:15px 16px;cursor:pointer;user-select:none}
#slides .sl-gic{width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;font-size:17px;flex:none;background:rgba(255,255,255,.05);border:1px solid var(--bdr);filter:grayscale(1);opacity:.85}
#slides .sl-gnm{font-weight:700;font-size:15px}
#slides .sl-gcount{font-size:11px;font-weight:600;padding:3px 9px;border-radius:20px;margin-left:10px;background:var(--sur2);color:var(--mut);white-space:nowrap}
#slides .sl-gcount.has{background:rgba(var(--gG),.15);color:var(--grn)}
#slides .sl-chev{margin-left:auto;color:var(--mut);transition:transform .18s;font-size:12px}
#slides .sl-grp.open .sl-chev{transform:rotate(90deg)}
#slides .sl-gbody{display:none;padding:2px 18px 18px}
#slides .sl-grp.open .sl-gbody{display:block}
#slides .sl-gempty{font-size:12px;color:var(--mut);padding:8px 2px 4px}

/* one deck row */
#slides .sl-row{display:flex;align-items:center;gap:12px;background:var(--sur2);border:1px solid var(--bdr);border-radius:12px;padding:12px 14px;margin-bottom:10px;flex-wrap:wrap}
#slides .sl-rtitle{font-weight:700;font-size:14px}
#slides .sl-rmeta{font-size:11px;color:var(--mut);margin-top:3px}
#slides .sl-spacer{flex:1}
#slides .sl-badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:20px;border:1px solid var(--bdr);color:var(--mut);white-space:nowrap}
#slides .sl-badge.pub{color:var(--acc);border-color:rgba(var(--gG),.4);background:rgba(var(--gG),.08)}
#slides .sl-badge.edited{color:var(--flg);border-color:rgba(245,158,11,.45);background:rgba(245,158,11,.10)}
#slides .sl-btn{background:transparent;border:1px solid var(--bdr);color:var(--txt);border-radius:8px;padding:7px 12px;font-size:12px;cursor:pointer;font-family:inherit}
#slides .sl-btn:hover{border-color:var(--acc);color:var(--acc)}
#slides .sl-btn.danger:hover{border-color:#ff3b3b;color:#ff3b3b}

/* Mobile ≤720px — mirrors PART B of the same approved unification. */
@media(max-width:720px){
  #slides{padding:16px 12px 60px}
  #slides .sl-title{font-size:18px}
  #slides .sl-sub{font-size:11.5px}
  #slides .sl-new{font-size:12px;padding:7px 12px}
  #slides .sl-ghead{padding:12px;gap:10px}
  #slides .sl-gnm{font-size:13.5px}
  #slides .sl-gic{width:28px;height:28px;font-size:14px;border-radius:8px}
  #slides .sl-gcount{font-size:10px;padding:2px 8px;margin-left:6px}
  #slides .sl-gbody{padding:2px 12px 12px}
}
@media(max-width:520px){
  #slides .sl-row{align-items:flex-start}
  #slides .sl-spacer{flex-basis:100%;height:0}
}


/* ══════════════════════════════════════════════════════════════════════════
   S3 · EDITOR + VIEWER  (approved draft stylesheet, every rule scoped to #slides)
   ══════════════════════════════════════════════════════════════════════════ */
#slides button,#slides input,#slides select,#slides textarea{font-family:inherit}
#slides .topbar{height:var(--topbar);flex:none;display:flex;align-items:center;gap:10px;
  padding:0 12px;background:var(--sur);border-bottom:1px solid var(--bdr)}
#slides #deckTitle{background:var(--sur2);border:1px solid var(--bdr);color:var(--txt);
  font-size:13.5px;font-weight:700;padding:7px 11px;border-radius:9px;width:100%;min-width:0}
#slides #deckTitle::placeholder{color:var(--mut);font-weight:500}
#slides #deckTitle:hover{border-color:var(--bdr2)}
#slides #deckTitle:focus{outline:none;border-color:rgba(var(--gG),.55);background:var(--sur3);box-shadow:0 0 0 3px rgba(var(--gG),.08)}
#slides .tspace{flex:1}
#slides .chip{font-size:10.5px;color:var(--mut);padding:4px 9px;border-radius:20px;
  border:1px solid var(--bdr);background:var(--sur2);white-space:nowrap;flex:none}
#slides .chip.live{color:var(--acc);border-color:rgba(var(--gG),.35)}
#slides .chip.dirty{color:#ffb454;border-color:rgba(255,180,84,.35)}
/* buttons */
#slides .b{display:inline-flex;align-items:center;justify-content:center;gap:7px;
  background:transparent;border:1px solid var(--bdr);color:var(--txt);
  border-radius:9px;padding:7px 12px;font-size:12px;font-weight:600;cursor:pointer;
  transition:border-color .15s,background .15s,color .15s;white-space:nowrap;flex:none}
#slides .b:hover:not(:disabled){border-color:rgba(var(--gG),.5);background:rgba(var(--gG),.06)}
#slides .b:disabled{opacity:.32;cursor:not-allowed}
#slides .b.pri{background:var(--acc);color:#000;border-color:var(--acc);font-weight:700}
#slides .b.pri:hover:not(:disabled){background:#4dff2e;border-color:#4dff2e}
#slides .b.sm{padding:5px 9px;font-size:11px;border-radius:8px}
#slides .b svg{width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.9;flex:none}
#slides .b.ico{padding:7px;width:34px}
#slides .b.ico svg{width:17px;height:17px}
/* ── toolbar ───────────────────────────────────────────────────────────── */
/* Wraps rather than scrolling: with the table and typography controls added, a
   horizontal scroller hid Background / Delete / Clear ink off the right edge on
   a normal laptop, which is worse than one extra row. */
#slides .toolbar{min-height:var(--toolbar);flex:none;display:flex;align-items:center;gap:6px;
  padding:7px 10px;background:var(--sur2);border-bottom:1px solid var(--bdr);
  flex-wrap:wrap;row-gap:7px}
#slides .tool{width:36px;height:36px;flex:none;display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid transparent;border-radius:9px;color:var(--mut);cursor:pointer;
  transition:all .15s;position:relative}
#slides .tool:hover{background:var(--sur3);color:var(--txt)}
#slides .tool.on{background:rgba(var(--gG),.12);border-color:rgba(var(--gG),.45);color:var(--acc)}
#slides .tool svg{width:19px;height:19px;stroke:currentColor;fill:none;stroke-width:1.8;pointer-events:none}
#slides .tool.on svg{filter:drop-shadow(0 0 5px rgba(var(--gG),calc(.5*var(--go))))}
#slides .sep{width:1px;height:24px;background:var(--bdr);flex:none;margin:0 4px}
#slides .sep2{width:1px;height:18px;background:var(--bdr);flex:none;margin:0 2px}
#slides .tool.sq{width:30px;height:30px;border-radius:7px;color:var(--txt)}
#slides .tool.sq svg{width:16px;height:16px}
#slides .tool.sq:disabled{opacity:.3;cursor:not-allowed}
#slides .num-out{width:26px;text-align:right;font-variant-numeric:tabular-nums}
#slides .tgrp{display:flex;align-items:center;gap:5px;flex:none}
#slides .tlbl{font-size:10px;color:var(--mut);text-transform:uppercase;letter-spacing:.08em;font-weight:700;flex:none}
/* colour swatches */
#slides .sw{width:22px;height:22px;border-radius:6px;border:2px solid rgba(255,255,255,.22);cursor:pointer;flex:none;padding:0}
#slides .sw.on{border-color:var(--acc);box-shadow:0 0 0 1px #000 inset}
#slides input[type=color]{width:28px;height:26px;padding:0;border:1px solid var(--bdr);border-radius:6px;
  background:var(--sur3);cursor:pointer;flex:none}
#slides input[type=range]{width:88px;accent-color:var(--acc);flex:none}
#slides .num{width:52px;background:var(--sur3);border:1px solid var(--bdr);color:var(--txt);
  border-radius:7px;padding:5px 7px;font-size:11.5px;flex:none}
/* ── body: stage + rail ────────────────────────────────────────────────── */
#slides .body{flex:1;display:flex;min-height:0;position:relative}
#slides .stagewrap{flex:1;min-width:0;position:relative;display:flex;align-items:center;justify-content:center;
  padding:16px;background:
    radial-gradient(ellipse at 50% 0%,rgba(var(--gG),.045),transparent 62%),
    #08080b;
  overflow:hidden}
#slides .stage{position:relative;box-shadow:0 18px 60px rgba(0,0,0,.7),0 0 0 1px var(--bdr);
  border-radius:4px;overflow:hidden;touch-action:none}
#slides #canvas{display:block;width:100%;height:100%;touch-action:none;cursor:crosshair}
/* renamed from .sel: that name is also the <select> skin below, and its
   max-width was collapsing the canvas. */
#slides #canvas.picking{cursor:default}
/* transparent lid: swallows long-press "save image", drag-out and right-click in
   student mode. Instructor mode leaves it off so drawing works. */
#slides #lid{position:absolute;inset:0;display:none;background:transparent;touch-action:pan-y;
  -webkit-touch-callout:none;user-select:none}
#slides #lid.on{display:block}
/* No background and no border-box: the canvas copy of this element is hidden
   while the editor is open, so what you see IS the textarea. An outline is used
   instead of a border because a border would shift the text by its own width. */
#slides #txed{position:absolute;display:none;background:transparent;border:0;
  outline:1px dashed rgba(var(--gG),.85);outline-offset:2px;
  resize:none;overflow:hidden;padding:0;margin:0;white-space:pre-wrap;
  /* Must match wrapText()/breakAt() in slides.js: break inside a word only
     when the word cannot fit a line of its own. overflow-wrap:break-word is
     exactly that rule, so the box you type in and the text that gets drawn
     wrap at the same characters. word-break:break-all would NOT match — it
     breaks eagerly, mid-word, even when the word would have fitted. */
  overflow-wrap:break-word;word-wrap:break-word}

/* ── slide rail (right) ────────────────────────────────────────────────── */
#slides .rail{width:var(--rail);flex:none;display:flex;flex-direction:column;
  background:var(--sur);border-left:1px solid var(--bdr)}
#slides .railhd{display:flex;align-items:center;gap:6px;padding:9px 10px;
  border-bottom:1px solid var(--bdr);flex:none}
#slides .railhd .t{font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--mut)}
#slides .raillist{flex:1;overflow-y:auto;overflow-x:hidden;padding:9px;display:flex;flex-direction:column;gap:9px}
#slides .raillist::-webkit-scrollbar{width:5px}
#slides .raillist::-webkit-scrollbar-thumb{background:var(--bdr2);border-radius:3px}
#slides .thumb{position:relative;border:2px solid var(--bdr);border-radius:7px;overflow:hidden;cursor:pointer;
  background:#2b2e33;flex:none;transition:border-color .15s;touch-action:none}
#slides .thumb:hover{border-color:var(--bdr2)}
#slides .thumb.on{border-color:var(--acc);box-shadow:0 0 0 1px rgba(var(--gG),.35),0 0 14px rgba(var(--gG),calc(.22*var(--go)))}
/* Reordering has to LOOK like it is happening: the grabbed slide lifts and
   follows the pointer, the rest dims, and a neon bar marks the landing spot. */
#slides .thumb.drag{border-color:var(--acc);box-shadow:0 16px 34px rgba(0,0,0,.65),0 0 0 2px rgba(var(--gG),.5);
  z-index:20;position:relative;cursor:grabbing;transition:none}
#slides .raillist.reordering .thumb:not(.drag){opacity:.42;filter:saturate(.5)}
#slides .raillist{position:relative}
#slides .dropbar{position:absolute;left:9px;right:9px;height:4px;border-radius:3px;display:none;
  background:var(--acc);box-shadow:0 0 12px rgba(var(--gG),.85);pointer-events:none;z-index:15}
#slides .thumb .grip{position:absolute;left:4px;top:2px;color:rgba(255,255,255,.75);font-size:13px;line-height:1;
  letter-spacing:-1px;text-shadow:0 1px 3px rgba(0,0,0,.9);cursor:grab;opacity:0;transition:opacity .15s}
#slides .thumb:hover .grip{opacity:1}
#slides .thumb canvas{display:block;width:100%;height:auto}
#slides .thumb .n{position:absolute;left:4px;bottom:3px;background:rgba(0,0,0,.72);color:#fff;
  font-size:9.5px;font-weight:700;padding:1px 5px;border-radius:4px;min-width:17px;text-align:center}
#slides .thumb .del{position:absolute;right:3px;top:3px;width:19px;height:19px;border-radius:5px;
  background:rgba(0,0,0,.7);border:1px solid var(--bdr2);color:#ff7b7b;
  font-size:13px;line-height:1;display:none;align-items:center;justify-content:center;cursor:pointer;padding:0}
#slides .thumb:hover .del{display:flex}
#slides .railft{padding:9px;border-top:1px solid var(--bdr);display:flex;gap:6px;flex:none}
#slides .railft .b{flex:1;padding:7px 6px;font-size:11px}
/* rail as a right drawer on phones */
#slides #railToggle{display:none}
#slides .scrim{display:none;position:absolute;inset:0;background:rgba(0,0,0,.55);z-index:38}
#slides .scrim.on{display:block}
/* ── student viewer ────────────────────────────────────────────────────── */
#slides .vwbar{height:var(--topbar);flex:none;display:flex;align-items:center;gap:9px;padding:0 12px;
  background:var(--sur);border-bottom:1px solid var(--bdr)}
#slides .vwcount{font-size:11.5px;color:var(--mut);font-variant-numeric:tabular-nums;white-space:nowrap;flex:none}
/* The exam's own ghost / neon chevrons, sitting on the slide edges */
#slides .chev{flex:none;background:none;border:0;padding:0;cursor:pointer;z-index:6;
  width:58px;height:82px;display:flex;align-items:center;justify-content:center;
  transition:opacity .15s,transform .15s;opacity:.9}
#slides .chev svg{width:40px;height:56px;display:block;overflow:visible;
  filter:drop-shadow(0 3px 10px rgba(0,0,0,.65))}
#slides .chev.right svg{filter:drop-shadow(0 0 12px rgba(var(--gG),calc(.45*var(--go))))}
#slides .chev:hover:not(:disabled){opacity:1;transform:scale(1.1)}
#slides .chev:disabled{opacity:.18;cursor:default}
#slides .vwtitle{font-weight:700;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:38vw}
#slides .dots{display:flex;gap:5px;justify-content:center;padding:9px;flex:none;flex-wrap:wrap}
#slides .dot{width:6px;height:6px;border-radius:50%;background:var(--bdr2);cursor:pointer;transition:all .15s;border:0;padding:0}
#slides .dot.on{background:var(--acc);width:17px;border-radius:3px}
#slides .gate{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:11px;text-align:center;padding:34px 20px;color:var(--mut)}
#slides .gate .big{font-size:15px;font-weight:800;color:var(--txt)}
#slides .gate svg{width:38px;height:38px;stroke:var(--mut);fill:none;stroke-width:1.5;opacity:.55}
/* ── panels / modals ───────────────────────────────────────────────────── */
#slides .ovl{position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.68);
  display:none;align-items:center;justify-content:center;padding:18px}
#slides .ovl.on{display:flex}
#slides .card{background:var(--sur2);border:1px solid var(--bdr);border-radius:15px;
  padding:20px;width:100%;max-width:460px;max-height:88vh;
  display:flex;flex-direction:column;overflow:hidden}
/* the picker scrolls; the heading and the Apply/Close row never leave the screen */
#slides .card .scroll{overflow:auto;flex:1;min-height:0;margin:0 -6px;padding:0 6px}
#slides .card h3{font-size:15px;font-weight:800;margin-bottom:4px}
#slides .card .sub{font-size:11.5px;color:var(--mut);margin-bottom:15px;line-height:1.55}
#slides .card .row{display:flex;gap:9px;justify-content:flex-end;margin-top:16px;padding-top:14px;
  border-top:1px solid var(--bdr);flex:none;align-items:center;flex-wrap:wrap}
#slides .opt{display:flex;align-items:center;gap:10px;padding:10px 11px;border:1px solid var(--bdr);
  border-radius:10px;cursor:pointer;margin-bottom:7px;transition:all .15s;background:var(--sur)}
#slides .opt:hover{border-color:var(--bdr2)}
#slides .opt.on{border-color:rgba(var(--gG),.55);background:rgba(var(--gG),.06)}
#slides .opt input{accent-color:var(--acc);width:15px;height:15px;flex:none}
#slides .opt .nm{font-size:12.5px;font-weight:600;display:block}
#slides .opt .ds{font-size:10.5px;color:var(--mut);display:block}
#slides .card.wide{max-width:min(940px,96vw)}
#slides .bggrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px}
#slides .bgopt{border:2px solid var(--bdr);border-radius:9px;overflow:hidden;cursor:pointer;
  background:none;padding:0;transition:border-color .15s}
#slides .bgopt:hover{border-color:var(--bdr2)}
#slides .bgopt.on{border-color:var(--acc)}
#slides .bgopt canvas{display:block;width:100%;height:auto}
#slides .bgopt .nm{font-size:11px;padding:5px 4px;color:var(--mut);text-align:center;background:var(--sur);font-weight:600}
#slides .bgopt.on .nm{color:var(--acc)}
#slides .tplgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px}
#slides .sel{background:var(--sur3);border:1px solid var(--bdr);color:var(--txt);border-radius:8px;
  padding:7px 9px;font-size:12px;cursor:pointer;flex:none;max-width:170px}
#slides .sel.wide{max-width:none;width:100%;font-size:13px;padding:9px 11px}
#slides .chipwrap{display:flex;flex-wrap:wrap;gap:7px;margin-top:10px;padding-top:10px;border-top:1px solid var(--bdr)}
#slides .chiplbl{width:100%;font-size:11px;color:var(--mut);margin-bottom:2px}
#slides .bchip{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--txt);
  background:var(--sur);border:1px solid var(--bdr);border-radius:8px;padding:6px 10px;cursor:pointer}
#slides .bchip.on{border-color:rgba(var(--gG),.55);background:rgba(var(--gG),.07)}
#slides .bchip input{accent-color:var(--acc)}
#slides .hidden{display:none!important}
/* ── responsive ────────────────────────────────────────────────────────── */
@media(max-width:820px){
  #slides #railToggle{display:flex}
  #slides .rail{position:absolute;right:0;top:0;bottom:0;width:176px;z-index:40;
    transform:translateX(100%);transition:transform .22s ease;box-shadow:-14px 0 34px rgba(0,0,0,.55)}
  #slides .rail.open{transform:translateX(0)}
  #slides #deckTitle{font-size:12.5px;max-width:120px}
  #slides .stagewrap{padding:9px 4px}
  #slides .toolbar{padding:6px 8px;gap:5px}
  #slides .tool{width:34px;height:34px}
  #slides .chev{width:34px;height:60px}
  #slides .chev svg{width:24px;height:36px}
  #slides .bggrid{grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}
  #slides .tplgrid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
}
@media(max-width:520px){
  #slides .b span.lbl{display:none}
  #slides .b{padding:7px 9px}
  #slides .chip.opt2{display:none}
}
/* ══ S3 · editor shell, top-bar controls and the gated publish modal ══════════
   Values are lifted verbatim from the two approved drafts (slides-integration-draft
   and slides-lifecycle-draft), so what ships is what was signed off. Everything is
   scoped to #slides like the rest of this file. */

/* Tokens the editor needs on top of the app's own. --sur3 is deliberately
   re-declared here: the app's global --sur3 is #2a2a3a, the editor's panels were
   drawn against #16171d. Scoping it to #slides leaves every other screen alone. */
#slides{--sur3:#16171d;--amb:#ffb454;--rail:190px;--topbar:52px;--toolbar:50px}

/* The list and the editor are siblings; exactly one is shown. .slFull pins the
   screen to the viewport the same way the exam screens do (crimreview.html drops
   body.crnx-app before painting #exam), so there is no panel, rail or padding. */
#slides #sldUI{display:none}
#slides.slFull{position:fixed;inset:0;z-index:60;padding:0;min-height:0;overflow:hidden;background:var(--bg)}
#slides.slFull #sldListWrap{display:none}
#slides.slFull #sldUI{display:flex;flex:1;min-height:0;flex-direction:column}
#slides #shell{flex:1;display:flex;flex-direction:column;min-height:0}
#slides .topbar{position:relative}

/* subject selector */
#slides .subjsel{display:flex;align-items:center;gap:7px;background:var(--sur2);border:1px solid var(--bdr);border-radius:9px;padding:7px 10px;flex:none;font-size:12.5px;font-weight:600;max-width:190px;cursor:pointer;color:var(--txt);font-family:inherit}
#slides .subjsel:hover{border-color:var(--bdr2)}
#slides .subjsel .ic{filter:grayscale(1);opacity:.85;font-size:14px}
#slides .subjsel .nm2{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#slides .subjsel .cv{color:var(--mut);font-size:11px}

/* deck switcher */
#slides .picker{display:flex;align-items:center;gap:9px;background:var(--sur2);border:1px solid var(--bdr);border-radius:9px;padding:7px 11px;flex:1;max-width:340px;min-width:0;cursor:pointer;color:var(--txt);font-family:inherit;text-align:left}
#slides .picker:hover{border-color:var(--bdr2)}
#slides .picker .nm{font-weight:700;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#slides .picker .cv{margin-left:auto;color:var(--mut);font-size:11px}

/* the dropdown both controls share */
#slides .drop{position:absolute;top:calc(100% + 2px);min-width:250px;max-width:430px;max-height:min(60vh,420px);overflow:auto;background:var(--sur2);border:1px solid var(--bdr2);border-radius:13px;box-shadow:0 22px 60px rgba(0,0,0,.8);z-index:30;display:none}
#slides .drop.on{display:block}
#slides .drop .hd{font-size:10px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--mut);padding:12px 15px 7px}
#slides .drop .it{display:flex;align-items:center;gap:11px;padding:10px 15px;border-top:1px solid var(--bdr);cursor:pointer;width:100%;background:transparent;border-left:0;border-right:0;border-bottom:0;color:var(--txt);font-family:inherit;text-align:left}
#slides .drop .it:hover{background:rgba(255,255,255,.04)}
#slides .drop .it.on{background:rgba(var(--gG),.07)}
#slides .drop .it .tt{flex:1;min-width:0}
#slides .drop .it .n1{font-weight:700;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#slides .drop .it .n2{font-size:11px;color:var(--mut)}
#slides .drop .ft{border-top:1px solid var(--bdr);padding:10px 15px;color:var(--acc);font-weight:700;font-size:12.5px;cursor:pointer;width:100%;background:transparent;border-left:0;border-right:0;border-bottom:0;font-family:inherit;text-align:left}
#slides .drop .ft:hover{background:rgba(var(--gG),.07)}

/* status pills — the same three states the deck list shows */
#slides .st{font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:3px 8px;border-radius:20px;border:1px solid var(--bdr2);color:var(--mut);white-space:nowrap;flex:none;background:rgba(8,8,11,.86)}
#slides .st.draft{border-color:var(--bdr2);color:#d3d8df}
#slides .st.pub{border-color:rgba(var(--gG),.55);color:var(--acc)}
#slides .st.edited{border-color:rgba(255,180,84,.6);color:var(--amb)}

/* Save goes amber the moment there is unsaved work */
#slides .b.warn{border-color:rgba(255,180,84,.6);color:var(--amb)}
#slides .chip.dirty{color:var(--amb);border-color:rgba(255,180,84,.35)}

/* in-place rename field (shown when the picker title is clicked) */
#slides #deckTitle{flex:1;max-width:340px}

/* required-field markers in the publish modal */
#slides .req{display:flex;flex-direction:column;gap:5px;margin-bottom:13px}
#slides .req .lb{font-size:11px;font-weight:700;color:var(--mut);display:flex;align-items:center;gap:6px}
#slides .req .lb i{font-style:normal;color:var(--amb);font-weight:800}
#slides .req .er{font-size:11px;color:var(--amb);font-weight:600;display:none}
#slides .req.bad .er{display:block}
#slides .req.bad .sel,#slides .req.bad .tin{border-color:rgba(255,180,84,.7)}
#slides .tin{background:var(--sur3);border:1px solid var(--bdr);border-radius:9px;color:var(--txt);padding:9px 11px;font-size:13px;width:100%;font-family:inherit}
#slides .tin:focus{outline:none;border-color:rgba(var(--gG),.55)}
#slides .b.pri:disabled{background:var(--sur2);color:var(--mut);border-color:var(--bdr)}

/* ── narrow screens ────────────────────────────────────────────────────────
   The approved top bar carries Back, subject, picker, status, chip and five
   buttons. At 390px that is far more than one 52px row can hold — measured, the
   buttons fell off the right edge entirely — so the bar wraps to two rows and the
   spacer becomes the line break instead of a gap. */
@media(max-width:820px){
  #slides .topbar{height:auto;min-height:var(--topbar);flex-wrap:wrap;row-gap:7px;padding:7px 8px}
  #slides .tspace{flex:0 0 100%;height:0}
  #slides .picker{max-width:none;flex:1 1 130px}
  #slides .subjsel{max-width:132px}
  #slides .drop{left:8px;right:8px;min-width:0;max-width:none}
  #slides .crnxBack{padding:7px 11px 7px 8px;font-size:12px}
}
@media(max-width:520px){
  #slides .subjsel .nm2{display:none}     /* the icon still says which subject */
  #slides .subjsel{max-width:none;flex:none}
}

/* The app's Xris button is fixed bottom-right at z-index 9999 and landed exactly on
   top of the rail's Duplicate button (measured: FAB 1324–1417 × 828–882, Duplicate
   1344–1427 × 861–891 at 1440×900). The footer is lifted clear of its default
   footprint rather than hiding an app-wide control this feature was not asked to
   touch — the button stays draggable and stays reachable. */
#slides .railft{padding-bottom:78px}

/* ── toolbar overlap fix (2026-08-04, reported) ────────────────────────────
   With a TABLE selected the toolbar shows the typography group and the table
   group at once, and "Insert table" was painting on top of the font-size
   slider. Root cause, measured: #fontFam is a <select> with max-width:170px and
   no width, so its USED width was 170px but its intrinsic (max-content)
   contribution was only ~72px. Its parent .tgrp therefore had its box computed
   98px narrower than its own children, and they spilled out over the next
   group — #grpText was 452px wide holding 550px of controls.
   Fix 1: give the select an explicit width so intrinsic == used (104px fits
   Sans/Serif/Mono with room; measured scrollWidth 102, no clipping).
   Fix 2: let a group wrap internally, so if any future control ever exceeds its
   group's box it drops to a second row instead of overlapping a neighbour. */
#slides #fontFam{width:104px;max-width:none}
/* flex-wrap alone was not enough: a flex item defaults to min-width:auto, which
   refuses to shrink below its contents, so the group overflowed the toolbar
   instead of wrapping inside it. Measured on a 430px-wide phone, BEFORE any of
   today's changes: the font-size slider ran to x=435 and the number box to x=492
   against a toolbar that ended at 425 — both simply unreachable. min-width:0 lets
   the group shrink, at which point its own flex-wrap puts the overflow on a
   second line. */
#slides .tgrp{flex-wrap:wrap;min-width:0;flex-shrink:1}

/* ── "students are on an older version" banner (2026-08-04) ─────────────────
   Same shape as the unsaved-changes strip in Create > Credentials, which is the
   pattern the instructor already recognises. Amber, because it is a state to
   resolve, not an error. Shown only when the deck is published AND has saved
   edits that were never pushed; paintDeckChrome() is the only thing that
   toggles it. */
#slides .pendbar{display:flex;align-items:center;gap:11px;flex:none;
  padding:9px 14px;background:rgba(255,180,84,.10);border-bottom:1px solid rgba(255,180,84,.32)}
#slides .pendbar svg{width:17px;height:17px;flex:none;stroke:var(--amb);fill:none;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
#slides .pendbar .pt{font-size:12.5px;color:var(--amb);font-weight:600;line-height:1.45}
#slides .pendbar .b{margin-left:auto}
@media(max-width:520px){
  #slides .pendbar{gap:8px;padding:8px 10px;flex-wrap:wrap}
  #slides .pendbar .pt{font-size:11.5px;flex:1 1 100%;order:2}
  #slides .pendbar .b{margin-left:auto;order:1}
}

/* ── the size control's target (2026-08-04) ────────────────────────────────
   With a table selected the size control changes the table's row height; with
   cells picked it changes their text. Same slider, two jobs, so the label next
   to it says which. It lights up when cells are picked, matching the neon the
   canvas uses for the same picked cells. */
#slides .szgrp{display:inline-flex;align-items:center;gap:5px;flex:none}
#slides .szwhat{min-width:52px;text-align:right}
#slides .szwhat.on{color:var(--acc)}

/* ── live annotations (2026-08-04) ─────────────────────────────────────────
   The keep/discard bar. Same shape as the published-edits bar above it so the
   two read as one family, but neon rather than amber: this is a choice waiting
   to be made, not a warning about what students can see. */
#slides .annbar{display:flex;align-items:center;gap:11px;flex:none;
  padding:9px 14px;background:rgba(var(--gG),.08);border-bottom:1px solid rgba(var(--gG),.30)}
#slides .annbar svg{width:17px;height:17px;flex:none;stroke:var(--acc);fill:none;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
#slides .annbar .pt{font-size:12.5px;color:var(--acc);font-weight:600;line-height:1.45}
#slides .annbar #annDrop{margin-left:auto}
@media(max-width:520px){
  #slides .annbar{gap:8px;padding:8px 10px;flex-wrap:wrap}
  #slides .annbar .pt{font-size:11.5px;flex:1 1 100%;order:2}
  #slides .annbar #annDrop{margin-left:auto;order:1}
  #slides .annbar #annKeep{order:1}
}
/* Annotate is a MODE. It has to look held-down, not just hovered, or you cannot
   tell at a glance whether the next stroke edits the deck or marks over it. */
#slides #btnAnnot.on{border-color:rgba(var(--gG),.65);background:rgba(var(--gG),.13);color:var(--acc)}
#slides #btnAnnot.on svg{stroke:var(--acc)}
/* A slide three back in the rail is otherwise silent about marks still waiting
   to be kept or discarded. */
#slides .thumb .annmark{position:absolute;right:4px;bottom:4px;width:9px;height:9px;border-radius:50%;
  background:var(--acc);box-shadow:0 0 8px rgba(var(--gG),.85),0 0 0 2px rgba(0,0,0,.55)}

/* ── deck footer modal ─────────────────────────────────────────────────── */
#slides .ftprev{margin-top:4px;padding:11px 13px;border:1px dashed var(--bdr2);border-radius:9px;
  background:var(--sur3);color:var(--mut);font-size:11.5px;white-space:pre-wrap;line-height:1.5}
#slides .ftprev.off{opacity:.55;font-style:italic}

/* ── zoom (2026-08-04) ─────────────────────────────────────────────────────
   The slide area only becomes scrollable while there is something to scroll to,
   so at fit it behaves exactly as it did before zoom existed.

   margin:auto rather than justify/align-content:center: a centred flex item that
   overflows its container puts the overflow past the START edge, where no amount
   of scrolling can reach it. auto margins centre when the slide is smaller and
   simply stop when it is bigger. */
#slides .stagewrap.zoomed{overflow:auto;justify-content:flex-start;align-items:flex-start;
  scrollbar-width:thin;scrollbar-color:var(--bdr2) transparent}
#slides .stagewrap.zoomed > .stage{margin:auto;flex:none}
#slides .stagewrap.zoomed::-webkit-scrollbar{width:9px;height:9px}
#slides .stagewrap.zoomed::-webkit-scrollbar-thumb{background:var(--bdr2);border-radius:5px}
#slides #grpZoom .num-out{min-width:42px;text-align:center}

/* ── preview (2026-08-04) ──────────────────────────────────────────────────
   Hide the rail and the app's Xris button, keep the top bar and every tool. The
   rail is not removed — it becomes the same overlay drawer it already is on a
   phone, so the mechanism behind the edge tab is one that is already tested. */
/* The drawer is parked by translating it out to the right. The editor body can be a
   few pixels narrower than the window (measured: 1435 inside 1440), which would
   leave a sliver of the parked rail showing at the very edge, so the body clips it. */
#slides.previewing .body{overflow:hidden}
#slides.previewing .rail{position:absolute;right:0;top:0;bottom:0;width:190px;z-index:40;
  transform:translateX(100%);transition:transform .22s ease;box-shadow:-14px 0 34px rgba(0,0,0,.55)}
#slides.previewing .rail.open{transform:translateX(0)}
#slides.previewing #btnPrev{border-color:rgba(var(--gG),.6);background:rgba(var(--gG),.12);color:var(--acc)}
#slides.previewing #btnPrev svg{stroke:var(--acc)}
/* The way back to the rail: a slim tab against the right edge of the slide area. */
#slides .railedge{position:absolute;right:0;top:50%;transform:translateY(-50%);z-index:39;
  width:22px;height:74px;padding:0;border:1px solid var(--bdr);border-right:0;
  border-radius:9px 0 0 9px;background:var(--sur);color:var(--mut);cursor:pointer;
  display:flex;align-items:center;justify-content:center}
#slides .railedge:hover{color:var(--txt);border-color:var(--bdr2);background:var(--sur2)}
#slides .railedge svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
/* The ONLY other rule in this stylesheet outside #slides, and it does exactly what
   the app already does to its own floating button when a drawer opens
   (body.crnx-drawer-open #crnxXrisFab). crimreview.html is not touched. */
body.crnx-slides-preview #crnxXrisFab{display:none}

/* ── the top bar can no longer push a control off its own edge ─────────────
   Measured 2026-08-04: on a 900px window the Unpublish button sat past the right
   edge of the bar and could not be reached at all — that was true BEFORE any of
   today's changes — and adding Preview did the same at 1100. The bar had a fixed
   height, so it could never wrap and overflow was the only thing left for it to do.
   It now wraps the way the toolbar already does, so a control can always be reached
   even if it costs a second row; the fixed height becomes a minimum. */
#slides .topbar{height:auto;min-height:var(--topbar);flex-wrap:wrap;padding-top:6px;padding-bottom:6px}

/* ══ LANDSCAPE / SHORT-SCREEN ADAPTATION (2026-08-07, approved draft) ═══════════
   The problem this fixes: every breakpoint in this file stops at `max-width`, so a
   phone held sideways — 844x390 on a modern handset — is WIDER than the 820px
   mobile ceiling and is therefore served the full DESKTOP layout: a single-row top
   bar, both toolbar rows, and a rail that cannot be closed, all inside 390px of
   height. Measured on the shipped build: ~133px of chrome (34% of the screen)
   leaving a 476x268 canvas, barely larger than portrait on a screen with twice the
   width.

   Every rule below is keyed on max-height, because height is the scarce resource
   when a phone is turned sideways — width never is. Nothing here can fire on a
   portrait phone or a tablet, so those layouts are byte-for-byte unchanged. */
@media (max-height:520px) and (orientation:landscape){
  /* 1 · The shell becomes a 2x2 grid so the toolbar can sit BESIDE the stage
     instead of stacked above it. The DOM order (topbar, toolbar, body) is not
     touched — only where each child lands. */
  #slides #shell{
    display:grid;
    /* `auto` rather than a fixed 48px: the strip is allowed to wrap into a second
       column instead of scrolling. Measured, a single 48px column fits about nine
       of the ~15 controls, which buried Background/Footer/Annotate below a scroll.
       This costs the canvas nothing — at 844x390 the canvas is limited by HEIGHT
       (349px -> 620px wide), and 620 fits comfortably in the width left even after
       the strip doubles, so the drawing area is identical either way. */
    grid-template-columns:112px minmax(0,1fr);
    /* Four rows, not two (2026-08-13). #shell has FIVE children — topbar,
       toolbar, pendbar, annbar, body — and naming only three areas left the two
       bars to be AUTO-PLACED, which drops them into column 1: the 112px tool
       strip. Measured at 918x412 the annotation bar came out 112px wide beside a
       746px stage, and at 112px its sentence collapses to min-content, i.e. one
       word per line. That is the "mangled in landscape" report — the bar was in
       the wrong column, not badly wrapped. The two bars get a row each rather
       than sharing one named area because both can be up at once (a published
       deck with unsaved edits AND live marks); sharing would stack them. While
       hidden they are display:none, so their `auto` rows resolve to 0 and the
       stage is exactly as tall as before. */
    grid-template-rows:auto auto auto minmax(0,1fr);
    grid-template-areas:"top  top"
                        "pend pend"
                        "ann  ann"
                        "tool body";
    /* The 1fr row needs a DEFINITE height to resolve against. In the flex layout
       above, #shell's height is content-driven, which is harmless while the toolbar
       is a short horizontal bar — but once it becomes a vertical strip of six
       groups it drives #shell to ~650px inside a 390px viewport, and
       #slides.slFull's overflow:hidden silently clips the bottom instead of
       scrolling. Measured before this line was added. Pinning the chain to the
       viewport makes the grid deterministic; both rules are inside this media
       query, so no other layout sees them. */
    height:100%;min-height:0;
  }
  #slides.slFull #sldUI{height:100%;min-height:0}
  #slides .topbar{grid-area:top;height:auto;min-height:0;flex-wrap:nowrap;
    row-gap:0;padding:4px 7px;gap:5px;overflow-x:auto;overflow-y:hidden}
  /* The full-width spacer exists to force the top bar onto two rows at <=820px.
     Here there is no vertical room for a second row, so it is removed and the bar
     scrolls sideways instead — every control stays reachable. */
  #slides .tspace{display:none}
  /* Icon-only, exactly the way the existing max-width:520px rule already does it —
     same class, same mechanism, nothing new invented. Every button keeps its icon
     and its title/aria-label, so nothing becomes unreachable or unreadable to a
     screen reader; only the visible word is dropped. This is what lets the top bar
     fit on one row instead of scrolling, and it also narrows the vertical tool
     strip, since Background/Footer/Annotate live there in landscape. */
  #slides .b span.lbl{display:none}
  #slides .body{grid-area:body}
  #slides .pendbar{grid-area:pend}
  #slides .annbar{grid-area:ann}
  /* One line, always: there is no vertical room here for the wrapped two-row
     shape the <=520px portrait rule uses. min-width:0 is the load-bearing
     declaration — a flex item refuses to shrink below min-content without it,
     which is the same trap that produced the one-word-per-line column above.
     With it the sentence ellipsises and the buttons keep their natural width. */
  #slides .pendbar,#slides .annbar{padding:6px 10px;gap:8px;flex-wrap:nowrap}
  #slides .pendbar .pt,#slides .annbar .pt{font-size:11.5px;min-width:0;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* 2 · The toolbar becomes a vertical strip down the left edge. */
  /* nowrap, deliberately. flex-wrap in a COLUMN spills into extra columns, and
     max-width does not constrain that — it just clips them: measured, the last
     group (Insert table / Front / Back / Delete / Clear ink / Fit) ran to 218px
     inside a 132px strip and was cut off. A single scrolling column is honest
     about it. It also beats the alternative of a horizontal scrolling bar, which
     would cost ~44px of height and shrink the canvas from 620x349 to 542x305. */
  #slides .toolbar{grid-area:tool;flex-direction:column;flex-wrap:nowrap;
    align-items:center;justify-content:flex-start;
    /* 132px, not 96px. Most of this toolbar is NOT icon buttons: btnTable
       ("⊞ Insert table"), btnClearInk, Front/Back/Delete, +Row/−Row/+Col/−Col,
       Keep/Discard and zoomFit are bare TEXT with no icon behind them, and four of
       them carry no title attribute either — so hiding their text would leave blank
       squares with no accessible name. They keep their words, and the strip is
       sized to hold them. This is close to free: at 844x390 the canvas is limited
       by HEIGHT (349px -> 620px wide) and 620 still fits in the 732px left over. */
    min-height:0;max-height:100%;overflow-y:auto;overflow-x:hidden;
    /* A rotated phone puts its notch on one side, and the tool strip is pinned to
       exactly that edge. max() leaves the normal padding on devices with no inset. */
    gap:4px;padding:6px 5px 6px max(5px, env(safe-area-inset-left));
    border-right:1px solid var(--bdr);border-bottom:0}
  #slides .toolbar .tgrp{flex-direction:column;gap:4px;flex:none}
  /* Captions ("Colour", "Pen", "Zoom") cost a line each and the controls under them
     are self-evident; the title attributes still carry the full names. */
  #slides .toolbar .tlbl{display:none}
  #slides .tool{width:34px;height:34px}
  /* The colour group has no wrapper element — it is a run of .sw buttons plus the
     custom-colour input — so it is selected by what it contains. Left as a column
     it would be six swatches tall; wrapping two-up keeps it short. */
  #slides .toolbar .tgrp:has(> .sw){flex-direction:row;flex-wrap:wrap;
    width:38px;gap:4px;justify-content:center}
  #slides .toolbar .sw{width:15px;height:15px}
  #slides .toolbar #colPick{width:34px;height:20px}
  /* Group dividers are drawn as a 1px vertical rule; in a vertical strip they have
     to lie down or they collapse to nothing. */
  #slides .toolbar .sep{width:28px;height:1px;margin:2px 0}
  /* The two slider groups are the only controls that do not stack naturally. */
  #slides #grpStroke,#slides #grpZoom{flex-direction:column;gap:3px;align-items:center}
  #slides #grpStroke input[type=range]{width:34px}
  #slides #grpZoom{font-size:10px}

  /* 3 · The rail becomes a slide-over drawer, exactly as it already does at
     <=820px. Without this it stays pinned open and eats 190px of a 844px screen. */
  #slides #railToggle{display:flex}
  #slides .rail{position:absolute;right:0;top:0;bottom:0;width:190px;z-index:40;
    transform:translateX(100%);transition:transform .22s ease;
    box-shadow:-14px 0 34px rgba(0,0,0,.55)}
  #slides .rail.open{transform:translateX(0)}

  /* 4 · Give the canvas the room the chrome just gave back. */
  #slides .stagewrap{padding:5px 4px}
  #slides .chev{width:30px;height:52px}
  #slides .chev svg{width:20px;height:32px}
  #slides #deckTitle{font-size:12px;max-width:112px}
  #slides .crnxBack{padding:5px 9px 5px 7px;font-size:11.5px}
}

/* NOT DONE — the tablet "fold the second toolbar row onto the first" tweak.
   The draft costed it as a free ~30px back to the canvas. Built and measured, it is
   not free and not a gain: forcing flex-wrap:nowrap with overflow-x:auto makes the
   row scrollable, and the horizontal scrollbar is itself taller than the row it
   saves. Measured at 1180x820 the toolbar went 79px -> 103px, i.e. 24px WORSE, and
   at 1440x900 it also silently changed the desktop editor, which was never in
   scope. Tablet landscape already had the correct layout, so the honest outcome is
   to leave it exactly as it was rather than ship a regression for a rounding error.
   Kept as a note so the idea is not re-attempted without the measurement. */

/* One of only TWO rules in this file outside #slides (the other is the
   body.crnx-slides-preview rule just above, which hides the app's floating Xris
   button while preview is on, exactly as the app hides it for its own drawer).
   While the full-bleed editor or
   viewer is up, the page behind it must not scroll and touch must not chain to
   it. The class is set exclusively by crnxSlidesFull() in slides.js and removed
   again the moment the screen is left, so no other screen can ever inherit it. */
body.crnx-slides-full{overflow:hidden;overscroll-behavior:none}
