/* ============================================================
   STACKALITY — subsite chrome
   The parent bar, the search box, the picker dialogs and the
   footer, for the five workshops. Injected by js/chrome.js.

   WHY THIS DUPLICATES PARTS OF site.css
   -------------------------------------
   The obvious move is to have the workshops load css/site.css and
   share the rules. They cannot. site.css is the home page's whole
   layout — it restyles body, sets a font stack and a background,
   and owns generic names like .card, .pane and .band that the
   workshops already use for their own things. Loading it into a
   workshop would rewrite that workshop.

   So the shared chrome is duplicated here instead, deliberately:
   about 120 lines of search box and dialog that also exist in
   site.css. If you restyle one, restyle the other. That cost buys
   five large, self-contained pages that cannot be broken by an
   edit to the home page's stylesheet.

   Everything here is namespaced .sk-* for the same reason.

   PALETTE
   -------
   The workshops all define the site palette in their own inline
   :root, so the tokens resolve. The var() chains carry literal
   fallbacks anyway, so this file also renders correctly on a page
   that defines nothing.
   ============================================================ */

:root{
  /* The one number the rest of the geometry hangs off. Matches
     --parent-h on the home page: one bar height across the site. */
  --sk-bar:52px;
}


/* ============================================================
   THE PARENT BAR
   Sticks at the very top, above each workshop's own bar. z-index
   70 puts it over that bar (60) and under every workshop's
   drawers, lightboxes and toasts (90 and up) — a modal should
   cover the site chrome, not fight it.
   ============================================================ */
.sk-parent{
  position:sticky;top:0;z-index:70;
  height:var(--sk-bar);
  background:rgba(15,12,26,.92);
  backdrop-filter:blur(16px);
  -webkit-backdrop-filter:blur(16px);
  border-bottom:1px solid var(--edge-soft,#2F2949);
}
.sk-parent-in{
  max-width:var(--shell,1360px);margin:0 auto;height:100%;
  padding:0 20px;gap:16px;
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;
}

.sk-lead{display:flex;align-items:center;gap:14px;min-width:0}

.sk-mark{
  display:flex;align-items:center;gap:8px;text-decoration:none;
  flex:0 0 auto;color:var(--ink,#F1EDFA);
}
.sk-mark .glyph{
  width:20px;height:20px;flex:0 0 auto;border-radius:5px;
  background:linear-gradient(140deg,#8B4BF0,#3D6FE8);
  position:relative;
}
.sk-mark .glyph::before,
.sk-mark .glyph::after{
  content:"";position:absolute;left:3px;right:3px;height:2px;border-radius:2px;
  background:rgba(255,255,255,.85);
}
.sk-mark .glyph::before{top:6px;opacity:.55}
.sk-mark .glyph::after{top:11px}
.sk-mark b{
  font-family:var(--disp),sans-serif;font-weight:800;font-size:15px;letter-spacing:-.03em;
}
.sk-mark b i{font-style:normal;color:var(--signal,#FFB020)}

.sk-social{display:flex;align-items:center;gap:4px}
.sk-social .soc{
  display:grid;place-items:center;
  width:30px;height:30px;border-radius:var(--r-s,6px);
  color:var(--dim,#9E96BC);text-decoration:none;
  transition:color .16s ease,background .16s ease;
}
.sk-social .soc svg{width:17px;height:17px;display:block;fill:currentColor}
.sk-social .soc:hover{color:var(--ink,#F1EDFA);background:var(--near,#26213C)}

/* Direct child of .sk-parent-in ONLY. As a descendant selector
   this also caught js/menu.js's tree - which lives in a panel
   inside .sk-parent - and laid a stacked menu out as a horizontal
   strip. tokens.css carries the same rules for root pages and had
   to be scoped too; fixing one and not the other is why the menu
   was still wrong on the workshop pages. */
.sk-parent-in > nav{
  display:flex;gap:2px;justify-self:end;align-items:center;
  overflow-x:auto;scrollbar-width:none;
}
.sk-parent-in > nav::-webkit-scrollbar{display:none}
.sk-parent-in > nav a{
  font-family:var(--mono),monospace;font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--dim,#9E96BC);text-decoration:none;padding:7px 11px;
  border-radius:var(--r-s,6px);white-space:nowrap;
  transition:color .15s,background .15s;
}
.sk-parent-in > nav a:hover{color:var(--ink,#F1EDFA);background:var(--near,#26213C)}
.sk-parent-in > nav a[aria-current="page"]{color:var(--ink,#F1EDFA);background:var(--lift,#2E284A)}

.sk-sr{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}


/* ============================================================
   SEARCH BOX  (mirrors the block in css/site.css — see the note
   at the top of this file before editing one without the other)
   ============================================================ */
.sk-find{
  position:relative;justify-self:center;display:flex;align-items:center;
  width:min(100%,230px);
}
.sk-find input{
  color:#fff;
  border:2px solid #8707ff;
  border-radius:10px;
  background:transparent;
  font-family:var(--mono),monospace;
  font-size:12px;letter-spacing:.02em;
  width:100%;max-width:none;outline:none;
  height:36px;padding:0 44px 0 25px;
  transition:border-color .18s ease,box-shadow .18s ease,background .18s ease;
}
.sk-find input:active{box-shadow:2px 2px 15px #8707ff inset}
.sk-find input::placeholder{color:var(--dimmer,#6F6790)}
.sk-find input:hover{border-color:#9d3bff}
.sk-find input:focus{
  border-color:#a04dff;
  box-shadow:0 0 0 3px rgba(135,7,255,.22), 2px 2px 15px rgba(135,7,255,.35) inset;
  background:rgba(135,7,255,.06);
}
.sk-find .go-arrow{
  position:absolute;right:5px;top:50%;transform:translateY(-50%);
  width:28px;height:28px;border-radius:7px;
  display:grid;place-items:center;
  color:#c79bff;background:transparent;border:0;cursor:pointer;padding:0;
  transition:color .16s ease,background .16s ease,transform .16s ease;
}
.sk-find .go-arrow svg{width:15px;height:15px;display:block;pointer-events:none}
.sk-find .go-arrow:hover{color:#fff;background:rgba(135,7,255,.28)}
.sk-find .go-arrow:active{transform:translateY(-50%) scale(.9)}

.sk-sugg{
  position:absolute;top:calc(100% + 7px);left:0;right:0;z-index:90;
  margin:0;padding:5px;list-style:none;
  background:rgba(22,17,40,.98);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  border:1px solid #4b1a86;border-radius:12px;
  box-shadow:0 24px 48px -20px rgba(0,0,0,.9);
  max-height:min(58vh,340px);overflow:auto;
}
.sk-sugg[hidden]{display:none}
.sk-sugg li{
  display:flex;align-items:baseline;gap:9px;
  padding:8px 11px;border-radius:8px;cursor:pointer;
}
.sk-sugg li b{
  font-family:var(--disp),sans-serif;font-weight:600;font-size:13px;
  color:var(--ink,#F1EDFA);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.sk-sugg li span{
  font-family:var(--mono),monospace;font-size:8.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer,#6F6790);flex:0 0 auto;
}
.sk-sugg li:hover,
.sk-sugg li[aria-selected="true"]{background:rgba(135,7,255,.24)}


/* ============================================================
   PICKER DIALOGS  (mirrors css/site.css — same note applies)
   ============================================================ */
.sk-dialog{
  border:0;padding:0;background:transparent;
  /* one card plus arrows, not a grid of them */
  width:min(430px,calc(100vw - 24px));
  max-width:none;max-height:calc(100dvh - 32px);
  color:var(--ink,#F1EDFA);overflow:visible;
}
.sk-dialog::backdrop{
  background:rgba(8,5,20,.74);
  backdrop-filter:blur(5px);-webkit-backdrop-filter:blur(5px);
}
.sk-dialog .sheet{
  background:var(--near,#26213C);
  border:1px solid var(--edge,#3B3459);
  border-radius:28px;
  box-shadow:0 30px 70px -24px rgba(0,0,0,.9);
  padding:10px;
  max-height:calc(100dvh - 32px);
  display:flex;flex-direction:column;overflow:hidden;
}
.sk-dialog .sheet-head{display:flex;align-items:flex-start;gap:14px;padding:12px}
.sk-dialog .sheet-head h2{
  font-family:var(--disp),sans-serif;font-weight:800;
  font-size:clamp(18px,4vw,23px);letter-spacing:-.03em;margin:0;
}
.sk-dialog .sheet-head h2 em{font-style:normal;color:var(--signal,#FFB020)}
.sk-dialog .sheet-head p{margin:4px 0 0;color:var(--dim,#9E96BC);font-size:12px;line-height:1.45}
.sk-dialog .sheet-close{
  margin-left:auto;flex:0 0 auto;
  width:34px;height:34px;border-radius:6px;
  display:grid;place-items:center;color:var(--dim,#9E96BC);
  border:1px solid var(--edge-soft,#2F2949);background:var(--mid,#1E1A31);
  cursor:pointer;
  transition:color .16s ease,background .16s ease,border-color .16s ease;
}
.sk-dialog .sheet-close:hover{
  color:var(--ink,#F1EDFA);background:var(--lift,#2E284A);border-color:var(--edge,#3B3459);
}
.sk-dialog .sheet-close svg{width:15px;height:15px;display:block}
/* the deck owns its overflow; the sheet never scrolls, so the
   close button cannot leave the screen */
.sk-dialog .sheet-body{overflow:visible;padding:0}

/* ============================================================
   THE DECK
   The pickers used to be a responsive grid, which meant the
   dialog's height grew with the number of workshops — five cards
   in two rows pushed the close button off a phone screen entirely.

   A deck fixes the height at exactly one card no matter how many
   there are. One card faces you, its neighbours peek out on either
   side and slightly behind, and scrolling, dragging or arrowing
   moves the deck along one card at a time. It wraps, so there is
   no dead end in either direction.

   Deliberately flat — no perspective, no rotation. Depth is carried
   by scale, opacity and z-order alone, which reads as a stack of
   cards rather than a carousel on a cylinder, and costs nothing to
   composite.

   Every colour carries a literal fallback so this block is
   byte-identical in css/site.css and css/chrome.css. If you edit
   one, edit the other.
   ============================================================ */
.deck{
  position:relative;
  /* The card drives everything below it. Bounded by vh as well as
     vw so a landscape phone shrinks the card instead of clipping
     the dialog's chrome. */
  --dcard-w:clamp(178px, min(58vw, 30vh), 236px);
  --dcard-h:calc(var(--dcard-w) + 118px);
  height:var(--dcard-h);
  margin:2px 0 4px;
  overflow:hidden;
  touch-action:pan-y;
  user-select:none;
  -webkit-user-select:none;
}

.deck-stage{
  position:absolute;inset:0;
  display:grid;
  place-items:center;
}

/* Each card is centred on the stage and then pushed left or right
   by the controller. Centring first is what makes the transform a
   pure offset — no width arithmetic in the JS. */
.deck .pick{
  position:absolute;
  grid-area:1 / 1;
  width:var(--dcard-w);
  display:flex;flex-direction:column;
  text-decoration:none;color:inherit;
  background:var(--mid,#1E1A31);
  border:1px solid var(--edge-soft,#2F2949);
  border-radius:var(--r-inner,18px);
  overflow:hidden;
  box-shadow:0 18px 38px -22px rgba(0,0,0,.9);
  transition:transform .42s cubic-bezier(.22,.68,.28,1),
             opacity .42s ease,
             border-color .2s ease;
  will-change:transform;
}

/* The one facing you. Only this card is clickable — the others are
   targets for the deck, not for navigation, which is what stops a
   half-hidden card from stealing a click. */
.deck .pick[data-live="1"]{
  border-color:var(--edge,#3B3459);
  box-shadow:0 26px 54px -20px rgba(0,0,0,.95);
}
.deck .pick[data-live="1"]:hover{border-color:var(--signal,#FFB020)}
.deck .pick[data-live="0"]{cursor:pointer}

.pick-thumb{
  position:relative;
  aspect-ratio:1 / 1;
  background:var(--far,#171426);
  border-bottom:1px solid var(--edge-soft,#2F2949);
  overflow:hidden;
}
.pick-thumb svg{width:100%;height:100%;display:block}

.pick-body{padding:11px 13px 13px;display:flex;flex-direction:column;gap:3px;flex:1}
.pick-kind{
  font-family:var(--mono),monospace;font-size:8.5px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--dimmer,#6F6790);
}
.pick-body h3{
  font-family:var(--disp),sans-serif;font-weight:700;font-size:15.5px;
  letter-spacing:-.022em;margin:0;
}
.pick-body p{
  margin:1px 0 0;font-size:11.5px;line-height:1.45;color:var(--dim,#9E96BC);
  /* two lines, then trim — the blurbs vary in length and a ragged
     card height would break the deck's alignment */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;
}
.pick-go{
  margin-top:auto;padding-top:9px;
  font-family:var(--mono),monospace;font-size:9px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--signal,#FFB020);
  display:inline-flex;align-items:center;gap:5px;
}

.pick-flag{
  position:absolute;left:8px;top:8px;z-index:2;
  font-family:var(--mono),monospace;font-size:8px;letter-spacing:.13em;
  text-transform:uppercase;padding:3px 7px;border-radius:999px;
  background:rgba(12,8,26,.88);border:1px solid var(--edge,#3B3459);
  display:inline-flex;align-items:center;gap:5px;
}
.pick-flag i{width:4px;height:4px;border-radius:50%;font-style:normal;background:var(--signal,#FFB020)}
.pick-flag.wip{color:var(--signal,#FFB020);border-color:rgba(255,176,32,.45)}
.pick-flag.tab{color:var(--know,#7DD3FF);right:8px;left:auto}
.pick-flag.tab i{background:var(--know,#7DD3FF)}

.pick-note{
  margin:0;padding:7px 11px;
  background:rgba(255,176,32,.09);
  border-top:1px solid rgba(255,176,32,.24);
  font-family:var(--mono),monospace;font-size:8.5px;line-height:1.45;
  letter-spacing:.02em;color:var(--signal,#FFB020);
}

/* ---- the arrows ----
   Outside the cards, vertically centred, with a hit area far bigger
   than the glyph so they are usable with a thumb. */
.deck-nav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:60;
  width:38px;height:64px;
  display:grid;place-items:center;
  background:transparent;border:0;padding:0;cursor:pointer;
  color:var(--dim,#9E96BC);
  transition:color .16s ease,transform .16s ease;
  -webkit-tap-highlight-color:transparent;
}
.deck-nav:hover{color:var(--signal,#FFB020)}
.deck-nav.prev{left:2px}
.deck-nav.next{right:2px}
.deck-nav:hover.prev{transform:translateY(-50%) translateX(-2px)}
.deck-nav:hover.next{transform:translateY(-50%) translateX(2px)}
.deck-nav svg{width:15px;height:26px;display:block;pointer-events:none;
  filter:drop-shadow(0 2px 7px rgba(8,3,24,.85))}

/* ---- position readout ---- */
.deck-dots{
  display:flex;align-items:center;justify-content:center;gap:7px;
  padding:2px 0 8px;
}
.deck-dots button{
  width:7px;height:7px;padding:0;border:0;border-radius:50%;
  background:var(--edge,#3B3459);cursor:pointer;
  transition:background .2s ease,transform .2s ease,width .2s ease;
}
.deck-dots button[aria-current="true"]{
  background:var(--signal,#FFB020);width:18px;border-radius:999px;
}
.deck-count{
  font-family:var(--mono),monospace;font-size:9px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer,#6F6790);
  text-align:center;padding:0 0 10px;
}

@media(prefers-reduced-motion:reduce){
  .deck .pick{transition:none}
  .deck-nav{transition:none}
}


/* ============================================================
   NO UNDERLINES ON CHROME LINKS
   Albedo — and only Albedo — carries a bare
   `a:hover{text-decoration:underline}` in its own stylesheet, a
   sensible default for a page full of prose links. It leaked onto
   the injected bar, footer and picker cards.

   The reason is specificity arithmetic that is easy to get wrong:
   :hover counts as a class-level component, so

       a:hover        = (0,1,1)   one pseudo-class, one element
       .sk-mark       = (0,1,0)   one class          -> LOSES
       .pick          = (0,1,0)   one class          -> LOSES
       .sk-parent nav a = (0,1,2)                    -> wins
       .sk-social .soc  = (0,2,0)                    -> wins

   which is exactly why the wordmark and the workshop cards
   underlined while the nav and the socials did not. Setting
   text-decoration:none on `.pick` was never going to hold; it had
   to be stated on a hover state of its own.

   Each selector below carries two class-level components, so it
   outranks any host page's `a:hover` no matter which stylesheet
   loads first. Written for every chrome surface rather than the
   two that happened to break, so the next workshop with an
   opinion about links cannot reach in here either.
   ============================================================ */
.sk-parent a:hover,  .sk-parent a:focus,  .sk-parent a:active,
.sk-foot a:hover,    .sk-foot a:focus,    .sk-foot a:active,
.sk-dialog a:hover,  .sk-dialog a:focus,  .sk-dialog a:active,
.sk-sugg a:hover,
a.pick:hover,        a.pick:focus,        a.pick:active{
  text-decoration:none;
}


/* ============================================================
   THE FOOTER
   Deliberately quieter than the home page's: a workshop ends in
   its own content, and this is a way back out, not a second
   navigation surface.
   ============================================================ */
.sk-foot{
  border-top:1px solid var(--edge-soft,#2F2949);
  background:var(--far,#171426);
  margin-top:48px;padding:30px 0 44px;
  position:relative;z-index:2;
}
.sk-foot .in{
  max-width:var(--shell,1360px);margin:0 auto;padding:0 20px;
  display:flex;flex-wrap:wrap;gap:16px;align-items:center;
}
.sk-foot nav{display:flex;gap:16px;margin-left:auto;flex-wrap:wrap}
.sk-foot nav a{
  font-family:var(--mono),monospace;font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dimmer,#6F6790);text-decoration:none;
}
.sk-foot nav a:hover{color:var(--ink,#F1EDFA)}
.sk-foot .foot-social{margin-left:12px}
.sk-foot .fine{
  width:100%;font-family:var(--mono),monospace;font-size:10px;
  letter-spacing:.1em;color:var(--dimmer,#6F6790);
}


/* ============================================================
   BACK TO TOP
   shell.js injects the button on any page that loads it; these
   are the styles it needs, since the workshops do not load
   css/tokens.css. z-index 75 sits above the two bars and below
   every workshop's drawer and lightbox.
   ============================================================ */
.sk-top{
  position:fixed;z-index:75;
  right:max(18px, env(safe-area-inset-right));
  bottom:max(18px, env(safe-area-inset-bottom));
  width:48px;height:48px;border-radius:999px;
  display:grid;place-items:center;
  background:var(--lift,#2E284A);
  border:1px solid var(--edge,#3B3459);
  color:var(--ink,#F1EDFA);
  box-shadow:0 30px 70px -24px rgba(0,0,0,.9);
  cursor:pointer;
  opacity:0;visibility:hidden;transform:translateY(12px) scale(.9);
  transition:opacity .22s ease,transform .22s ease,visibility .22s,
             background .16s ease,border-color .16s ease;
}
.sk-top.on{opacity:1;visibility:visible;transform:none}
.sk-top:hover{background:var(--signal,#FFB020);border-color:var(--signal,#FFB020);color:#170F00}
.sk-top svg{width:20px;height:20px;display:block}


/* ============================================================
   RE-ANCHORING EACH WORKSHOP'S OWN BAR
   ------------------------------------
   Every workshop has a second sticky bar of its own, and each one
   was written against a different parent: Albedo assumed 33px,
   VISTA its own --bar, Throughline a bar that scrolled away, and
   Parallax and Hitstop had no parent at all and stuck at 0.

   One bar height now, so all of them are re-anchored to
   --sk-bar. The `html` prefix is what makes these win: the page's
   own `.top{top:0}` is a class selector in an inline <style> that
   loads after this file, so matching its specificity would not be
   enough — `html .top` outranks it regardless of order.

   The sticky rails inside the Learn views are offset the same
   way, and their max-height loses the bar as well, or the last
   lesson in a long rail ends up under the fold.

   Each page is addressed by the data-sk-page attribute that
   build/apply-seo.js writes onto its <html>. That scoping is not
   decoration: the five pages measure their sticky stacks in three
   incompatible ways, and a rule written for one of them silently
   moves the rails on the other four.
   ============================================================ */

/* The workshop's own bar drops below the shared one. True of all
   five, and the only rule here that is. */
html header.top{top:var(--sk-bar)}

/* VISTA drives its whole layout off --bar: the offset of its own
   bar, the height of the WebGL world, and the rail in its Guide
   view. Redefining that one variable re-anchors all three at once,
   which is why VISTA needs nothing else. html[...] outranks the
   page's own :root, which loads after this file. */
html[data-sk-page="vista"]{--bar:var(--sk-bar)}

/* Blendspace calls its own bar .sitebar rather than header.top, so
   the shared rule above does not reach it. Same job: drop it below
   the Stackality bar. */
html[data-sk-page="blendspace"] .sitebar{top:var(--sk-bar)}

/* Parallax, Hitstop and Throughline all hard-coded a 78px rail
   offset against a page that had no parent bar at all. */
html[data-sk-page="parallax"] .rail,
html[data-sk-page="hitstop"] .rail,
html[data-sk-page="throughline"] .rail{
  top:calc(78px + var(--sk-bar));
  max-height:calc(100vh - 100px - var(--sk-bar));
}

/* Albedo measures its sticky stack with --topH: 33px of the parent
   bar it used to have, plus 71px of its own. Only the first number
   changes. Its .rail and .pin both read --topH, so neither needs
   touching once the variable is right. */
/* Affordance is built on Albedo's stylesheet, so it measures its
   sticky stack the same way and takes the same correction. Its
   exhibit column is sticky against --topH as well, which is why
   getting this one variable right settles the whole page. */
html[data-sk-page="albedo"],
html[data-sk-page="affordance"]{--topH:calc(71px + var(--sk-bar))}
@media(max-width:760px){
  html[data-sk-page="albedo"],
  html[data-sk-page="affordance"]{--topH:calc(63px + var(--sk-bar))}
}


/* ============================================================
   NARROW SCREENS
   The socials go before the search box does — they are in the
   footer too, and a search field you cannot reach on a phone is
   worse than no search field.
   ============================================================ */
@media(max-width:900px){
  .sk-find{width:min(100%,180px)}
}
@media(max-width:720px){
  .sk-lead .sk-social{display:none}
  .sk-parent-in{gap:10px;padding:0 14px}
  .sk-find{width:100%}
  .sk-find input{padding-left:14px;padding-right:38px;font-size:11.5px}
  .sk-find .go-arrow{width:26px;height:26px;right:4px}
  .sk-foot nav{margin-left:0;width:100%}
  .sk-foot .foot-social{margin-left:-6px}
}
@media(max-width:430px){
  .sk-parent-in > nav a:not([aria-current]):nth-last-child(-n+2){display:none}
}

@media(prefers-reduced-motion:reduce){
  .pick,.sk-top,.sk-find input{transition:none}
}

/* ============================================================
   MOBILE NAVIGATION
   The button is built by js/shell.js — see mobileNav() there for
   why it is not written into the six files that carry the bar.

   Below 860px the three-track bar cannot hold the wordmark, a
   search box and six links. It used not to admit that: the tracks
   held their widths, the nav slid left over the wordmark, and the
   search input was squeezed to about 56px. Here the search and
   the links leave the bar entirely and move into a panel.
   ============================================================ */
/* ============================================================
   THE MENU  -  one button, one panel, every width

   Built by js/menu.js. It replaced the row of nav links AND the
   two picker dialogs; see that file's header for why.

   The button carries the word MENU on desktop and drops to the
   icon alone when the bar gets tight. The search box stays out in
   the open on desktop and moves inside the panel on narrow
   screens, because search is the one thing worth a permanent slot
   and the one thing most annoying to go hunting for.
   ============================================================ */
.sk-burger{
  display:inline-flex;align-items:center;gap:9px;
  background:var(--near, #26213C);
  border:1px solid var(--edge, #3B3459);
  border-radius:var(--r-s, 6px);
  padding:7px 12px;cursor:pointer;
  color:var(--dim, #9E96BC);
  justify-self:end;
  transition:color .15s,border-color .15s,background .15s;
}
.sk-burger:hover{color:var(--ink, #F1EDFA);border-color:var(--signal, #FFB020)}
.sk-burger-bars{display:grid;gap:3px;width:15px}
.sk-burger-bars i{
  display:block;height:2px;border-radius:2px;background:currentColor;
  transition:transform .2s ease,opacity .2s ease;
}
.sk-burger-word{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;
}
.sk-parent.menu-open .sk-burger{
  color:var(--ink, #F1EDFA);border-color:var(--signal, #FFB020);
}
.sk-parent.menu-open .sk-burger-bars i:nth-child(1){transform:translateY(5px) rotate(45deg)}
.sk-parent.menu-open .sk-burger-bars i:nth-child(2){opacity:0}
.sk-parent.menu-open .sk-burger-bars i:nth-child(3){transform:translateY(-5px) rotate(-45deg)}

/* ---------- the panel ---------- */
.sk-menu{
  position:absolute;top:100%;right:max(14px, calc((100vw - var(--shell, 1360px))/2 + 20px));
  z-index:80;width:min(340px, calc(100vw - 28px));
  background:rgba(20,17,34,.97);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  border:1px solid var(--edge, #3B3459);
  border-radius:var(--r-l, 20px);
  box-shadow:var(--shadow-float, 0 30px 70px -24px rgba(0,0,0,.9));
  padding:10px;
  max-height:calc(100vh - var(--parent-h, 52px) - 20px);
  overflow-y:auto;
}
.sk-menu[hidden]{display:none}
/* The panel's copy of the search box, hidden on desktop where the
   bar already has one.

   SCOPED TO .sk-menu ON PURPOSE. The clone carries both classes -
   "sk-find sk-menu-find" - so a bare .sk-menu-find ties on
   specificity with .sk-find{display:flex} and only source ORDER
   decides. That order is not the same on every page: workshops
   load chrome.css alone, where the hide comes later and wins;
   root pages load tokens.css then site.css, where .sk-find comes
   later and the box appeared in BOTH places at once.

   One extra class settles it everywhere, whatever loads when. */
.sk-menu .sk-menu-find{display:none}

/* ---------- rows ---------- */
.sk-tree{display:block}
.sk-row{
  display:block;text-decoration:none;
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim, #9E96BC);
  padding:11px 12px;border-radius:var(--r-s, 6px);
  transition:color .14s,background .14s;
}
a.sk-row:hover{color:var(--ink, #F1EDFA);background:var(--near, #26213C)}
a.sk-row[aria-current="page"]{color:var(--ink, #F1EDFA);background:var(--lift, #2E284A)}

/* a parent is a link PLUS a chevron - two controls, because touch
   has no hover and one control cannot mean two things */
/* The parent row's layout and the chevron are defined once, below,
   under "CHEVRON FIRST". An earlier copy lived here with the arrow
   38px wide on the right and rotating 90deg - it was superseded
   rather than deleted, which left two .sk-chev rules disagreeing
   and only order deciding. Gone now; there is one of each. */
.sk-row-name{
  text-decoration:none;
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim, #9E96BC);
  padding:11px 12px;border-radius:var(--r-s, 6px);
  transition:color .14s,background .14s;
}
.sk-row-name:hover{color:var(--ink, #F1EDFA);background:var(--near, #26213C)}
.sk-chev svg{transition:transform .18s ease}
.sk-branch.is-open > .sk-parent-row .sk-row-name{color:var(--ink, #F1EDFA)}

/* ---------- the submenu ----------
   Offset, so it reads as a branch rather than a continuation. */
.sk-sub-list{
  display:block;margin:2px 0 6px 10px;padding-left:10px;
  border-left:1px solid var(--edge-soft, #2F2949);
}
.sk-sub-list[hidden]{display:none}
.sk-sub-row{
  display:block;text-decoration:none;color:inherit;
  padding:9px 10px;border-radius:var(--r-s, 6px);
  transition:background .14s;
}
.sk-sub-row:hover{background:var(--near, #26213C)}
.sk-sub-row[aria-current="page"]{background:var(--lift, #2E284A)}
.sk-sub-row b{
  display:block;font-family:var(--disp);font-weight:700;font-size:14px;
  letter-spacing:-.01em;color:var(--ink, #F1EDFA);
}
.sk-sub-cat{
  display:inline-block;margin:2px 0 0;
  font-family:var(--mono);font-size:9px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--know, #7DD3FF);
}
.sk-sub-row small{
  display:block;margin:2px 0 0;
  font-family:var(--serif);font-size:12.5px;line-height:1.4;
  color:var(--dim, #9E96BC);
}



/* ------------------------------------------------------------
   CHEVRON FIRST, EVERYTHING ALIGNED

   The arrow sits BEFORE the word and points left, which is the
   direction the list actually appears. It used to sit hard right
   while pointing left, which said two things at once.

   Every row is indented by the arrow's width so the words line up
   in one column whether the row has an arrow or not. --sk-arrow
   is the single number that keeps them in step.
   ------------------------------------------------------------ */
.sk-tree{--sk-arrow:26px}

/* rows with no branch: indent past where the arrow would be */
a.sk-row{padding-left:calc(12px + var(--sk-arrow))}

.sk-parent-row{display:flex;align-items:stretch;gap:0;padding:0}
.sk-chev{
  flex:0 0 var(--sk-arrow);
  width:var(--sk-arrow);
  order:-1;                       /* belt and braces if markup moves */
  display:grid;place-items:center;
  margin-left:12px;
  background:none;border:0;cursor:pointer;
  color:var(--dimmer, #6F6790);
  border-radius:var(--r-s, 6px);
  transition:color .14s,transform .18s ease;
}
.sk-chev:hover{color:var(--signal, #FFB020);background:none}
.sk-chev svg{width:14px;height:14px;display:block;transform:none}
.sk-branch.is-open .sk-chev{color:var(--signal, #FFB020)}
.sk-branch.is-open .sk-chev svg{transform:translateX(-2px)}

.sk-row-name{
  flex:1 1 auto;
  padding-left:0;                 /* the arrow already supplies it */
}

/* ------------------------------------------------------------
   THE SUBMENU IS A FLYOUT, NOT AN ACCORDION

   The first version expanded the list INLINE, inside the panel.
   That is fatal for a hover menu and the reason it was unusable:
   opening Workshops pushed Tools seven rows down the page, so
   moving the mouse toward Tools meant leaving the branch - the
   list collapsed, every row snapped back up, and the cursor was
   suddenly over empty space with the menu closing underneath it.
   The target moved out from under the pointer that was chasing
   it.

   A flyout fixes it at the root: the parent rows NEVER MOVE. The
   list appears beside them, so Workshops stays exactly where it
   was while its contents are on screen, and travelling down to
   Tools crosses nothing but stationary rows.

   IT OPENS TO THE LEFT. The panel is pinned to the right edge of
   the window; a submenu opening rightward would go off-screen.

   NO GAP. There is an 8px visual offset between panel and flyout,
   and if that gap were real the pointer would cross dead space
   and the menu would close mid-travel. The flyout carries
   transparent padding of the same width instead, so the hover
   region is continuous even though the ink is not.
   ------------------------------------------------------------ */
@media(min-width:861px){
  /* the panel must not clip its own flyout */
  .sk-menu{overflow:visible}
  .sk-branch{position:relative}

  .sk-sub-list{
    position:absolute;
    right:100%;                 /* leftward: the panel hugs the right edge */
    top:-10px;
    width:min(330px, 42vw);
    margin:0;
    padding:10px 8px 10px 0;    /* the 8px is the hover bridge, not a gap */
    border-left:0;

    background:transparent;     /* the card is the inner box, below */
  }
  /* the visible card, inset by the bridge padding */
  .sk-sub-list::before{
    content:"";position:absolute;inset:0 8px 0 0;
    background:rgba(20,17,34,.97);
    backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
    border:1px solid var(--edge, #3B3459);
    border-radius:var(--r-l, 20px);
    box-shadow:var(--shadow-float, 0 30px 70px -24px rgba(0,0,0,.9));
    pointer-events:none;
  }
  .sk-sub-list > *{position:relative;z-index:1}
  .sk-sub-row{margin:0 14px}

}

/* ---------- narrow ---------- */
@media(max-width:860px){
  .sk-burger-word{display:none}         /* icon alone */
  .sk-burger{padding:8px 10px}
  .sk-parent-in > [data-sk-find]{display:none}   /* moves into the panel */

  /* The bar is a three-track grid (1fr auto 1fr) and the search box
     is the middle track. Hiding it leaves two children in three
     columns, which parks the button mid-bar with dead space to its
     right. Two tracks, and it sits hard right where it belongs. */
  .sk-parent-in{grid-template-columns:1fr auto}
  .sk-menu .sk-menu-find{display:block;margin:0 0 8px}
  .sk-menu{
    right:14px;left:14px;width:auto;
  }
}


/* ============================================================
   KEEP YOUR PROGRESS
   The bar js/keep.js raises when there is unsaved workshop
   progress. See that file for why it exists.

   Bottom LEFT deliberately: .sk-top owns the bottom right, and a
   panel that covers the back-to-top button would be its own small
   insult. On a phone it goes full width and sits above it.

   Fallback values on every var(): the workshops load chrome.css
   and scrollbars.css but NOT tokens.css, so nothing here may
   depend on a token being defined.
   ============================================================ */
.sk-keep{
  position:fixed;z-index:74;
  left:max(18px, env(safe-area-inset-left));
  bottom:max(18px, env(safe-area-inset-bottom));
  width:min(360px, calc(100vw - 36px));
  background:var(--near, #26213C);
  border:1px solid var(--edge, #3B3459);
  border-left:3px solid var(--signal, #FFB020);
  border-radius:12px;
  box-shadow:0 26px 48px -18px rgba(8,3,26,.9);
  animation:sk-keep-in .26s cubic-bezier(.2,.8,.3,1);
}
@media(prefers-reduced-motion:reduce){
  .sk-keep{animation:none}
}
@keyframes sk-keep-in{
  from{opacity:0;transform:translateY(10px)}
  to  {opacity:1;transform:none}
}

.sk-keep-in{padding:15px 17px 14px}

.sk-keep-t{
  margin:0;
  font-family:var(--disp, system-ui, sans-serif);
  font-size:14px;font-weight:700;letter-spacing:-.01em;
  color:var(--ink, #F1EDFA);
}
.sk-keep-b{
  margin:7px 0 0;
  font-size:13px;line-height:1.5;
  color:var(--dim, #9E96BC);
}

.sk-keep-do{display:flex;gap:8px;margin-top:13px}

.sk-keep-go,
.sk-keep-no{
  font-family:var(--mono, ui-monospace, monospace);
  font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;
  padding:9px 14px;border-radius:999px;
  border:1px solid transparent;cursor:pointer;
  transition:background .15s ease,border-color .15s ease,color .15s ease;
  -webkit-appearance:none;appearance:none;
}
.sk-keep-go{
  background:var(--signal, #FFB020);
  color:#170F00;font-weight:600;
}
.sk-keep-go:hover{background:#FFC352}
.sk-keep-no{
  background:transparent;
  border-color:var(--edge, #3B3459);
  color:var(--dim, #9E96BC);
}
.sk-keep-no:hover{
  color:var(--ink, #F1EDFA);
  border-color:var(--dim, #9E96BC);
}

@media(max-width:560px){
  .sk-keep{
    left:12px;right:12px;width:auto;
    /* clear of the back-to-top button, which is 44px there */
    bottom:calc(max(12px, env(safe-area-inset-bottom)) + 56px);
  }
}
