/* ============================================================
   STACKALITY — home
   Reads every color and radius from tokens.css.
   ============================================================ */
*{box-sizing:border-box}
html,body{margin:0;padding:0}
html{scroll-behavior:smooth}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  background:var(--far);
  color:var(--ink);
  font-family:var(--disp);
  font-size:15px;line-height:1.55;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
a{color:inherit}
button{background:none;border:0;cursor:pointer;font:inherit;color:inherit}
:focus-visible{outline:2px solid var(--signal);outline-offset:3px;border-radius:var(--r-s)}
::selection{background:var(--signal);color:#170F00}

.shell{max-width:var(--shell);margin:0 auto;padding:0 20px}
.eyebrow{
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--dimmer);
}

/* ============================================================
   HERO
   Not a banner. The graphic is a shape that occupies one side
   of the page with a wavy edge facing the copy, and the app
   windows cross that edge to break free of it.

   Desktop: shape on the right, wave running down its left edge.
   Mobile:  shape across the top, wave along its bottom edge,
            copy underneath on the page background.
   ============================================================ */
/* The hero box is what the graphic is measured against. The art is
   pinned to all four of its edges, so the shape's lower boundary
   always lands exactly where the hero content ends — no magic
   numbers to re-tune when the copy or the viewport changes. */
.hero{
  position:relative;
  /* Kept short on purpose: the shelves pane should start just below the
     CTA buttons. The characters provide the height, not empty space. */
  min-height:clamp(340px,44vh,470px);
}

.hero-art{
  position:absolute;z-index:0;
  /* Top stays welded to the divider. The other three edges bleed past
     the page so the pointer drift can never pull the shape off an edge
     — the bleed must exceed the largest drift in js/shell.js. */
  top:0;left:calc(-1 * var(--art-bleed));right:calc(-1 * var(--art-bleed));
  bottom:calc(-1 * var(--art-bleed));
  pointer-events:none;
  will-change:transform;
}
.hero-art svg{width:100%;height:100%;display:block}
.hero-art .wave-h{display:none}
@media(max-width:939px){
  .hero-art{bottom:auto;height:calc(clamp(280px,38vh,360px) + var(--art-bleed))}
  .hero-art .wave-v{display:none}
  .hero-art .wave-h{display:block}

  /* The bleed above is deliberate — it keeps the wave's edges off
     the screen while the pointer drifts it. On a phone there is no
     pointer to drift it with, and the bleed instead made the page
     20px wider than the viewport. A document wider than the screen
     pans sideways under a thumb, which is exactly the "everything
     moves around" symptom: nothing was mis-scaled, the whole page
     was sliding.

     overflow-x:clip rather than hidden, because hidden on one axis
     forces the other to scroll, and the characters are supposed to
     hang below the hero. clip leaves the vertical axis alone. */
  .hero{overflow-x:clip}
}

.hero-grid{
  position:relative;z-index:6;
  max-width:var(--shell);margin:0 auto;padding:30px 20px 0;
  display:grid;gap:26px;grid-template-columns:1fr;align-items:center;
}
@media(min-width:940px){
  .hero-grid{
    grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
    padding:76px 20px 0;gap:36px;
  }
}

/* on mobile the graphic leads, the words follow */
.hero-copy{order:2}
.breakout{order:1}
@media(min-width:940px){
  .hero-copy{order:1}
  .breakout{order:2}
}

.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;
}
.hero-copy{padding:24px 0 48px}
.hero-logo{
  display:block;width:100%;height:auto;
  max-width:min(100%,640px);
}
@media(max-width:939px){
  .hero-copy{padding:8px 0 24px}
  .hero-logo{max-width:520px;margin:0 auto}
}

.hero-copy .kicker{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--dim);
  display:inline-flex;align-items:center;gap:9px;
  border:1px solid var(--edge);
  border-radius:var(--r-pill);padding:6px 14px;
  background:var(--near);
}
.hero-copy .kicker i{
  width:6px;height:6px;border-radius:50%;background:var(--signal);font-style:normal;
  box-shadow:0 0 0 3px rgba(255,176,32,.2);
}
.hero-copy h1{
  font-family:var(--disp);font-weight:800;
  font-size:clamp(36px,5.6vw,64px);line-height:.95;letter-spacing:-.042em;
  margin:20px 0 0;color:var(--ink);
  text-wrap:balance;
}
.hero-copy h1 em{font-style:normal;color:var(--signal)}
.hero-copy p{
  margin:18px 0 0;max-width:44ch;font-size:16px;line-height:1.62;color:var(--dim);
}
.hero-cta{display:flex;flex-wrap:wrap;gap:10px;margin-top:28px}
.btn{
  display:inline-flex;align-items:center;gap:8px;
  font-family:var(--mono);font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  padding:12px 20px;border-radius:var(--r-pill);
  text-decoration:none;transition:transform .16s ease,background .16s ease,border-color .16s;
}
.btn.solid{background:var(--signal);color:#170F00;font-weight:600}
.btn.solid:hover{background:#FFC352;transform:translateY(-2px)}
.btn.ghost{border:1px solid var(--edge);color:var(--ink);background:var(--near)}
.btn.ghost:hover{border-color:var(--signal);background:var(--lift);transform:translateY(-2px)}

/* ============================================================
   THE BREAKOUT CLUSTER
   Three app windows on a shared vanishing point. They sit on the
   wavy shape and cross its edge — the sub-graphics that break
   free of the graphic. Each is a real Stackality surface.
   ============================================================ */
.breakout{
  position:relative;justify-self:center;
  width:min(440px,88vw);height:min(340px,42vh);
  perspective:1400px;perspective-origin:60% 40%;
  margin-bottom:-66px;          /* the overhang: this is the "off the page" */
  z-index:6;
}
/* ------------------------------------------------------------
   THE WINDOW STACK SITS BEHIND THE CHARACTERS

   It used to be pinned to the far right, level with the seated
   figure and clear of everything - which read as a fourth object
   in the composition rather than part of the scene, and left the
   middle of the plate empty.

   It now tucks UNDER both characters and slides left toward the
   crow, so the seated figure overlaps its near corner and the
   crow stands above it. That is deliberately against the usual
   rule of keeping decorative art clear of other art: the overlap
   is what turns three separate objects into one picture with
   depth in it.

   The z-index is the whole trick. Both characters are z-index 7;
   this drops to 4, BELOW them but still above the purple plate.
   ------------------------------------------------------------ */
@media(min-width:940px){
  .breakout{
    justify-self:end;
    /* pulled left and up, into the space under the crow */
    margin-right:clamp(40px, 9vw, 150px);
    margin-bottom:-4px;
    width:min(470px,42vw);height:min(310px,42vh);
    z-index:4;                  /* behind the characters, above the plate */
    perspective-origin:52% 44%;
  }
}
.win{
  position:absolute;border-radius:var(--r-l);overflow:hidden;
  background:var(--mid);
  border:1px solid rgba(255,255,255,.16);
  box-shadow:0 40px 70px -26px rgba(14,5,45,.9);
  transform-style:preserve-3d;
  transition:transform .5s cubic-bezier(.2,.8,.3,1);
}
.win .bar{
  height:26px;display:flex;align-items:center;gap:5px;padding:0 10px;
  background:var(--near);border-bottom:1px solid var(--edge-soft);
}
.win .bar i{width:7px;height:7px;border-radius:50%;background:var(--edge);font-style:normal}
.win .bar span{
  margin-left:6px;font-family:var(--mono);font-size:8.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dimmer);white-space:nowrap;overflow:hidden;
}
.win .body{padding:10px}

/* Cascade runs down-LEFT. Down-right put the front tile squarely under
   the reclining figure; this direction keeps all three readable. */
.win.w1{
  left:214px;top:0;width:222px;height:142px;
  transform:rotateX(9deg) rotateY(-20deg) rotateZ(-5deg);
}
.win.w2{
  left:112px;top:66px;width:228px;height:144px;
  transform:rotateX(9deg) rotateY(-20deg) rotateZ(-5deg) translateZ(46px);
}
.win.w3{
  left:10px;top:132px;width:232px;height:146px;
  transform:rotateX(9deg) rotateY(-20deg) rotateZ(-5deg) translateZ(92px);
}
.breakout:hover .win.w1{transform:rotateX(9deg) rotateY(-20deg) rotateZ(-5deg) translateZ(-14px)}
.breakout:hover .win.w2{transform:rotateX(9deg) rotateY(-20deg) rotateZ(-5deg) translateZ(60px)}
.breakout:hover .win.w3{transform:rotateX(9deg) rotateY(-20deg) rotateZ(-5deg) translateZ(116px)}
@media(prefers-reduced-motion:reduce){.win{transition:none}}
@media(max-width:520px){
  .win.w1{left:150px;width:180px;height:118px}
  .win.w2{left:78px;top:54px;width:186px;height:120px}
  .win.w3{left:6px;top:108px;width:190px;height:122px}
}

/* miniature of the Parallax depth track, drawn in CSS */
.mini{position:relative;height:96px;border-radius:var(--r-m);overflow:hidden;background:#1E1A31}
.mini .sky{position:absolute;inset:0;background:linear-gradient(180deg,#2A2350,#1A1631)}
.mini .ridge{position:absolute;left:0;right:0;bottom:18px;height:52px;background:#241E44;
  clip-path:polygon(0 60%,12% 40%,26% 56%,40% 30%,56% 52%,70% 36%,86% 54%,100% 40%,100% 100%,0 100%)}
.mini .ridge.two{bottom:13px;height:42px;background:#2E2752;
  clip-path:polygon(0 68%,14% 48%,28% 64%,44% 42%,60% 60%,76% 44%,92% 62%,100% 50%,100% 100%,0 100%)}
.mini .soil{position:absolute;left:0;right:0;bottom:0;height:13px;background:#3B3459}
.mini .soil::after{content:"";position:absolute;left:0;top:0;height:3px;width:58%;background:var(--signal)}
.mini .guy{position:absolute;bottom:13px;left:42%;width:7px;height:15px;border-radius:2px;
  background:var(--signal);box-shadow:0 0 16px rgba(255,176,32,.55)}
.mini .gate{position:absolute;bottom:13px;left:68%;width:3px;height:30px;background:var(--know);opacity:.75}

/* task rows for the dev tile */
.strip{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--edge-soft)}
.strip:last-child{border-bottom:0}
.strip .dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:var(--good)}
.strip .dot.amber{background:var(--signal)}
.strip .dot.ice{background:var(--know)}
.strip .ln{height:6px;border-radius:3px;background:var(--lift);flex:1}
.strip .ln.short{flex:0 0 34%}
.strip .tag{width:30px;height:8px;border-radius:4px;background:var(--edge)}

/* folder rows for the directory tile */
.dirrow{display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--edge-soft)}
.dirrow:last-child{border-bottom:0}
.dirrow .fold{width:11px;height:9px;border-radius:2px;flex:0 0 auto;background:var(--edge);position:relative}
.dirrow .fold::before{content:"";position:absolute;left:0;top:-3px;width:5px;height:3px;
  border-radius:1px 1px 0 0;background:var(--edge)}
.dirrow .fold.open,.dirrow .fold.open::before{background:var(--signal)}
.dirrow .ln{height:6px;border-radius:3px;background:var(--lift);flex:1}
.dirrow .ln.short{flex:0 0 52%}

/* ---- the little character (sword) ----
   Anchored to .hero-grid, NOT to the tile cluster. The cluster's own
   top moves with the height of the copy beside it, so an offset that
   cleared the header on the home page pushed him up behind it on the
   holding page, where the copy is much shorter. Measuring from the
   hero's top instead makes his position identical on every page.

   Horizontally he still lands 14px left of the cluster: the cluster's
   left edge sits (its width - 20px) in from the grid's right edge, so
   width - 6px puts his right edge exactly 14px clear of it. */
.hero-figure{
  position:absolute;z-index:7;
  right:calc(min(470px,42vw) - 6px);
  top:14px;
  width:clamp(150px,min(13.5vw,26vh),250px);
  height:auto;
  pointer-events:none;
  filter:drop-shadow(0 18px 26px rgba(12,4,40,.5));
}
@media(max-width:939px){
  /* stacked layout: the cluster is centered, so anchor him to the left */
  .hero-figure{right:auto;left:8px;top:10px;width:clamp(96px,22vw,150px)}
}
@media(max-width:520px){
  .hero-figure{left:4px;top:8px;width:clamp(84px,24vw,120px)}
}

/* ---- the main character (reclining) ----
   Lives inside .hero-grid, whose box is the shell. right:20px therefore
   lands his right edge exactly on the panes' right edge below, so he
   never widens the site's natural boundary. The negative bottom is what
   drops his feet over the first pane. */
.hero-keyart{
  position:absolute;z-index:7;
  right:20px;
  bottom:-104px;
  width:clamp(220px,min(23vw,40vh),400px);
  height:auto;
  pointer-events:none;
  filter:drop-shadow(0 26px 34px rgba(12,4,40,.5));
}
@media(max-width:939px){
  .hero-keyart{right:20px;bottom:-58px;width:clamp(180px,44vw,320px)}
}
@media(max-width:520px){
  .hero-keyart{bottom:-40px;width:clamp(150px,52vw,250px)}
}

/* On a phone he was anchored to the bottom of the hero, which is
   where the LEARN | STACK | CREATE lockup also is — so he sat on
   top of the wordmark and ate the last two letters. Scaling him
   down does not fix it, because the lockup is full-width at that
   size and there is nowhere along the bottom edge for him to go.

   So he moves up instead, onto the window cluster above, which is
   art rather than type and can carry him. The wordmark then gets
   the full width it needs to be read. */
@media(max-width:720px){
  .hero-keyart{
    bottom:auto;
    top:min(215px,26vh);
    right:4px;
    width:clamp(150px,40vw,230px);
  }
  .hero-logo{max-width:100%}
  .hero-copy{padding-top:28px}
}

/* ---- the plate's bottom edge, and the card that rides over it ---- */
.hero-cards{
  position:relative;z-index:1;
  max-width:var(--shell);margin:var(--stack-gap) auto 0;padding:0 20px;
}

/* ============================================================
   WINDOW IN A WINDOW
   Outer pane (radius R, padding = --frame) holds an inner panel
   at radius R - frame, so the two curves stay concentric.
   ============================================================ */
.pane{
  background:var(--near);
  border:1px solid var(--edge-soft);
  border-radius:var(--r-xl);
  padding:var(--frame);
  box-shadow:var(--shadow-card);
}
.panel{
  background:var(--mid);
  border:1px solid var(--edge-soft);
  border-radius:var(--r-inner);
  padding:clamp(20px,3vw,34px);
}
.panel.flush{padding:0;overflow:hidden}

.pane-head{
  display:flex;align-items:baseline;gap:14px;flex-wrap:wrap;
  padding:4px 12px 12px;
}
.pane-head h2{
  font-family:var(--disp);font-weight:800;font-size:clamp(22px,3vw,32px);
  letter-spacing:-.032em;margin:0;
}
.pane-head h2 em{font-style:normal;color:var(--signal)}
.pane-head .sub{color:var(--dim);font-size:14px;margin:0;flex:1;min-width:220px}

/* three inner windows side by side */
.trio{display:grid;gap:var(--frame);grid-template-columns:1fr}
@media(min-width:820px){.trio{grid-template-columns:repeat(3,1fr)}}
.card{
  background:var(--mid);
  border:1px solid var(--edge-soft);
  border-radius:var(--r-inner);
  padding:22px 22px 24px;
  position:relative;overflow:hidden;
  transition:transform .2s ease,border-color .2s ease,background .2s ease;
  text-decoration:none;color:inherit;display:block;
}
.card:hover{transform:translateY(-4px);border-color:var(--edge);background:var(--lift)}
.card .badge{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dimmer);display:flex;align-items:center;gap:7px;
}
.card .badge i{width:6px;height:6px;border-radius:50%;background:var(--know);font-style:normal}
.card .badge.live i{background:var(--good)}
.card .badge.wip i{background:var(--signal)}
.card h3{
  font-family:var(--disp);font-weight:700;font-size:19px;letter-spacing:-.022em;
  margin:12px 0 7px;
}
.card p{margin:0;color:var(--dim);font-size:13.5px;line-height:1.55}
.card .go{
  margin-top:16px;font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--signal);display:inline-flex;gap:6px;align-items:center;
}
.card.is-placeholder{
  cursor:default;
  border-style:dashed;
  background:transparent;
}
.card.is-placeholder:hover{transform:none;background:transparent;border-color:var(--edge-soft)}
.card.is-placeholder h3{color:var(--dim)}

.card .wash{
  position:absolute;right:-30px;top:-30px;width:120px;height:120px;border-radius:50%;
  background:radial-gradient(circle,rgba(139,75,240,.22),transparent 70%);
  pointer-events:none;
}

/* featured row: a wide inner window with its own inner window */
.feature{display:grid;gap:var(--frame);grid-template-columns:1fr}
@media(min-width:900px){.feature{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}}
.feature .shot{
  border-radius:var(--r-inner);overflow:hidden;
  background:linear-gradient(150deg,#241B45,#161029);
  border:1px solid var(--edge-soft);
  min-height:250px;position:relative;padding:16px;
}
.feature .shot .mini{position:absolute;inset:16px;height:auto}

.feature .why{padding:24px 24px 26px;background:var(--mid);border:1px solid var(--edge-soft);
  border-radius:var(--r-inner);display:flex;flex-direction:column}
.feature .why h3{font-family:var(--disp);font-weight:800;font-size:clamp(20px,2.6vw,27px);
  letter-spacing:-.03em;margin:10px 0 10px}
.feature .why p{color:var(--dim);font-size:14px;margin:0 0 16px}
.feature .why ul{margin:0 0 20px;padding-left:17px;color:var(--dim);font-size:13.5px}
.feature .why li{margin-bottom:6px}
.feature .why .btn{align-self:flex-start;margin-top:auto}
.btn.amber{background:var(--signal);color:#170F00;font-weight:600}
.btn.amber:hover{background:#FFC352;transform:translateY(-2px)}

/* writing rows */
.rows{border-radius:var(--r-inner);overflow:hidden;border:1px solid var(--edge-soft)}
.row{
  display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:baseline;
  padding:16px 20px;background:var(--mid);border-bottom:1px solid var(--edge-soft);
  text-decoration:none;color:inherit;transition:background .16s ease;
}
.row:last-child{border-bottom:0}
.row:hover{background:var(--lift)}
.row .when{font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--dimmer);white-space:nowrap}
.row .what{font-family:var(--disp);font-weight:600;font-size:15.5px;letter-spacing:-.015em}
.row .what small{display:block;font-family:var(--disp);font-weight:400;font-size:13px;
  color:var(--dim);letter-spacing:0;margin-top:3px}
.row .kind{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dimmer);white-space:nowrap}
@media(max-width:640px){
  .row{grid-template-columns:1fr auto}
  .row .when{display:none}
}

/* One gap value drives the spacing between every block, so the log,
   featured and footer all sit the same distance apart. */
section.band{padding:0;margin-top:var(--stack-gap)}
footer.foot{margin-top:var(--stack-gap)}

/* reveal */
[data-reveal]{opacity:0;transform:translateY(18px);transition:opacity .6s ease,transform .6s ease}
[data-reveal].in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){
  [data-reveal]{opacity:1;transform:none;transition:none}
}

/* footer */
footer.foot{
  border-top:1px solid var(--edge-soft);
  padding:34px 0 90px;
}
footer.foot .in{
  max-width:var(--shell);margin:0 auto;padding:0 20px;
  display:flex;flex-wrap:wrap;gap:18px;align-items:center;
}
footer.foot .in .sk-mark{opacity:.9}
footer.foot nav{display:flex;gap:16px;margin-left:auto;flex-wrap:wrap}
footer.foot nav a{
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--dimmer);text-decoration:none;
}
footer.foot nav a:hover{color:var(--ink)}
footer.foot .fine{
  width:100%;font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  color:var(--dimmer);
}

/* ============================================================
   THE LOG — horizontal post carousel
   Tiles scroll under a mask so the ones reaching the arrows fade out
   instead of being chopped at a hard edge. The arrows are thin, but
   their buttons are not: each has a wide invisible hit area so a click
   near one never lands on the article behind it.
   ============================================================ */
.stream{position:relative}

.stream-track{
  display:flex;gap:var(--frame);
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
  scrollbar-width:none;-ms-overflow-style:none;
  padding:2px 2px 6px;
  /* the soft landing at both edges */
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 78px,#000 calc(100% - 78px),transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 78px,#000 calc(100% - 78px),transparent 100%);
}
.stream-track::-webkit-scrollbar{display:none}

.post{flex:0 0 clamp(228px,25vw,300px);scroll-snap-align:start}
.post > a{
  display:flex;flex-direction:column;height:100%;
  text-decoration:none;color:inherit;
  background:var(--mid);
  border:1px solid var(--edge-soft);
  border-radius:var(--r-inner);
  overflow:hidden;
  transition:transform .2s ease,border-color .2s ease,background .2s ease;
}
.post > a:hover{transform:translateY(-4px);border-color:var(--edge);background:var(--lift)}
.post-shot{
  display:block;height:104px;
  background:linear-gradient(150deg,#2A2350,#1A1631);
  border-bottom:1px solid var(--edge-soft);
}
.post-shot.alt{background:linear-gradient(150deg,#2B2148,#191430)}
.post-date{
  display:block;padding:13px 16px 0;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer);
}
.post-title{
  display:block;padding:8px 16px 0;
  font-family:var(--disp);font-weight:600;font-size:15.5px;letter-spacing:-.018em;
}
.post-ex{
  display:block;padding:7px 16px 18px;
  font-size:13px;line-height:1.5;color:var(--dim);
}

/* ---- arrows ---- */
.stream-arrow{
  position:absolute;top:0;z-index:4;
  width:56px;height:112px;             /* the invisible hit area */
  display:grid;place-items:center;
  background:transparent;border:0;padding:0;
  cursor:pointer;
  opacity:.85;
  transition:opacity .2s ease,transform .2s ease;
  -webkit-tap-highlight-color:transparent;
}
.stream-arrow.prev{left:-6px;justify-items:start;padding-left:10px}
.stream-arrow.next{right:-6px;justify-items:end;padding-right:10px}
.stream-arrow svg{width:15px;height:26px;display:block;pointer-events:none;
  filter:drop-shadow(0 2px 6px rgba(8,3,24,.7))}
.stream-arrow:hover{opacity:1;transform:scale(1.08)}
.stream-arrow[disabled]{opacity:.18;cursor:default;transform:none}
@media(prefers-reduced-motion:reduce){.stream-arrow,.post > a{transition:none}}
@media(max-width:520px){
  .stream-arrow{width:44px}
  .stream-track{
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 52px,#000 calc(100% - 52px),transparent 100%);
            mask-image:linear-gradient(90deg,transparent 0,#000 52px,#000 calc(100% - 52px),transparent 100%);
  }
}

/* ============================================================
   SEARCH BOX — the parent bar's middle track
   The socials moved left to sit with the wordmark, and this took
   their place. One input, one arrow: click it or press Enter,
   both land on search.html.

   The purple stroke and the inset glow on press are the house
   input style; everything else here is plumbing to fit an arrow
   inside the field without the text ever running under it.
   ============================================================ */
/* The form, not the input, owns the width. An input sized by its own
   max-width inside a shrink-to-fit form leaves the arrow floating
   somewhere to the right of the field it belongs to. */
.sk-find{
  position:relative;justify-self:center;display:flex;align-items:center;
  width:min(100%,230px);
}

.input,
.sk-find input{
  color:#fff;
  border:2px solid #8707ff;
  border-radius:10px;
  padding:10px 25px;
  background:transparent;
  max-width:190px;
  font-family:var(--mono);
  font-size:12px;
  letter-spacing:.02em;
  width:100%;
  outline:none;
  transition:border-color .18s ease,box-shadow .18s ease,background .18s ease;
}
.input:active,
.sk-find input:active{box-shadow:2px 2px 15px #8707ff inset}

/* the arrow lives inside the field, so the text stops short of it */
.sk-find input{
  max-width:none;                       /* the form caps the width */
  padding-right:44px;height:36px;padding-top:0;padding-bottom:0;
}
.sk-find input::placeholder{color:var(--dimmer)}
.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)}

/* typeahead */
.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);font-weight:600;font-size:13px;
  color:var(--ink);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.sk-sugg li span{
  font-family:var(--mono);font-size:8.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--dimmer);flex:0 0 auto;
}
.sk-sugg li:hover,
.sk-sugg li[aria-selected="true"]{background:rgba(135,7,255,.24)}
.sk-sugg li[aria-selected="true"] span{color:#c79bff}

/* the bar's three tracks: mark + socials | search | nav */
.sk-parent-in{grid-template-columns:auto minmax(0,1fr) auto}
.sk-lead{display:flex;align-items:center;gap:14px;min-width:0}
.sk-lead .sk-social{justify-self:auto;margin-left:2px}

@media(max-width:900px){
  .sk-find{width:min(100%,180px)}
}
@media(max-width:720px){
  /* The socials go first, not the search box — they are one tap from
     the footer anyway, and a search field you cannot reach on a phone
     is the one thing worse than no search field. */
  .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-find input::placeholder{font-size:11px}
}
@media(max-width:430px){
  .sk-parent nav a:not([aria-current]):nth-last-child(-n+2){display:none}
}

/* ============================================================
   PICKER DIALOG — the Workshops and Tools cards open this
   instead of jumping straight into one workshop. Square tiles,
   each with its generated thumbnail, title and one line of
   description.

   A real <dialog>, so Escape closes it, focus is trapped, and
   the page behind it is inert without any of that in script.
   ============================================================ */
.sk-dialog{
  border:0;padding:0;background:transparent;
  /* Sized to one card plus its arrows, not to a grid of them. The
     deck keeps the height fixed however many workshops there are,
     which is the whole reason the close button now survives on a
     phone. */
  width:min(430px,calc(100vw - 24px));
  max-width:none;max-height:calc(100dvh - 32px);
  color:var(--ink);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);
  border:1px solid var(--edge);
  border-radius:var(--r-xl);
  box-shadow:var(--shadow-float);
  padding:var(--frame);
  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 12px 12px;
}
.sk-dialog .sheet-head h2{
  font-family:var(--disp);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)}
.sk-dialog .sheet-head p{margin:4px 0 0;color:var(--dim);font-size:12px;line-height:1.45}
.sk-dialog .sheet-close{
  margin-left:auto;flex:0 0 auto;
  width:34px;height:34px;border-radius:var(--r-s);
  display:grid;place-items:center;color:var(--dim);
  border:1px solid var(--edge-soft);background:var(--mid);
  transition:color .16s ease,background .16s ease,border-color .16s ease;
}
.sk-dialog .sheet-close:hover{color:var(--ink);background:var(--lift);border-color:var(--edge)}
.sk-dialog .sheet-close svg{width:15px;height:15px;display:block}

/* The deck manages its own overflow, so the sheet no longer
   scrolls. That is what guarantees the header — and the close
   button in it — stays on 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}
}

/* ============================================================
   SPONSORED — the ad band. Sized and labelled up front so the
   page does not jump when a unit fills, and so it never reads
   as site content.
   ============================================================ */
.adband .pane{padding:var(--frame)}
.ad-slot{
  border:1px dashed var(--edge);
  border-radius:var(--r-inner);
  background:var(--mid);
  min-height:280px;
  display:grid;place-items:center;
  padding:16px;overflow:hidden;
}
.ad-slot ins{display:block;width:100%}
.ad-slot .ad-empty{
  font-family:var(--mono);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--dimmer);text-align:center;
}
.ad-label{
  font-family:var(--mono);font-size:9px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--dimmer);
  display:block;margin:0 0 9px;
}
@media(max-width:640px){.ad-slot{min-height:250px}}

/* ============================================================
   SEARCH RESULTS — search.html
   In-site only. Every hit is a page on this domain, and each row
   says why it matched: the software it names, the sections and
   the lessons that carried the term.
   ============================================================ */
.searchhead{padding:36px 0 4px}
.searchhead .find-big{width:min(100%,640px);margin:18px 0 0;justify-self:start}
.searchhead .find-big input{font-size:14px;height:48px;padding-right:56px}
.searchhead .find-big .go-arrow{width:36px;height:36px;right:6px}
.searchhead .find-big .go-arrow svg{width:18px;height:18px}
.searchhead h1{
  font-family:var(--disp);font-weight:800;
  font-size:clamp(28px,4.6vw,46px);letter-spacing:-.04em;margin:14px 0 0;
}
.searchhead h1 em{font-style:normal;color:var(--signal)}
.searchhead .count{
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--dim);margin:12px 0 0;
}

.results{display:flex;flex-direction:column;gap:var(--frame);margin:0;padding:0;list-style:none}
.result{
  display:grid;gap:16px;
  grid-template-columns:96px minmax(0,1fr);
  align-items:start;
  background:var(--mid);
  border:1px solid var(--edge-soft);
  border-radius:var(--r-inner);
  padding:16px;
  transition:transform .18s ease,border-color .18s ease,background .18s ease;
}
.result:hover{transform:translateY(-3px);border-color:var(--edge);background:var(--lift)}
.result .rthumb{
  width:96px;aspect-ratio:1/1;border-radius:var(--r-m);overflow:hidden;
  border:1px solid var(--edge-soft);background:var(--far);
}
.result .rthumb svg{width:100%;height:100%;display:block}
.result h2{
  font-family:var(--disp);font-weight:700;font-size:19px;
  letter-spacing:-.024em;margin:0;
}
.result h2 a{text-decoration:none;color:inherit}
.result h2 a:hover{color:var(--signal)}
.result .rmeta{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--dimmer);
  margin:6px 0 0;display:flex;flex-wrap:wrap;gap:10px;align-items:center;
}
.result .rmeta .path{color:var(--know);text-transform:none;letter-spacing:.04em}
.result p.rblurb{margin:9px 0 0;color:var(--dim);font-size:13.5px;line-height:1.55}
.result .why{margin:12px 0 0;display:flex;flex-direction:column;gap:7px}
.result .why .row{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline}
.result .why .lbl{
  font-family:var(--mono);font-size:9px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--dimmer);flex:0 0 auto;
  min-width:74px;padding-top:3px;
}
.chip{
  font-family:var(--mono);font-size:10px;letter-spacing:.04em;
  padding:3px 9px;border-radius:var(--r-pill);
  background:var(--near);border:1px solid var(--edge-soft);color:var(--dim);
}
.chip.soft{color:var(--know);border-color:rgba(125,211,255,.32)}
.chip.les{color:var(--ink);letter-spacing:0;font-family:var(--disp);font-size:11.5px}
.chip mark{background:rgba(255,176,32,.26);color:var(--signal);border-radius:3px;padding:0 2px}

.result .wipnote{
  margin:11px 0 0;font-family:var(--mono);font-size:10px;line-height:1.55;
  color:var(--signal);background:rgba(255,176,32,.09);
  border:1px solid rgba(255,176,32,.24);border-radius:var(--r-s);
  padding:7px 10px;
}

.noresult{
  border:1px dashed var(--edge);border-radius:var(--r-inner);
  padding:28px 22px;text-align:center;color:var(--dim);
}
.noresult h2{font-family:var(--disp);font-weight:700;font-size:20px;color:var(--ink);margin:0 0 8px}
.noresult .tries{display:flex;flex-wrap:wrap;gap:7px;justify-content:center;margin:16px 0 0}
.noresult .tries a{text-decoration:none}
.noresult .tries a .chip{transition:color .16s,border-color .16s}
.noresult .tries a:hover .chip{color:var(--signal);border-color:var(--signal)}

@media(max-width:560px){
  .result{grid-template-columns:64px minmax(0,1fr);gap:12px;padding:13px}
  .result .rthumb{width:64px}
  .result .why .lbl{min-width:100%;padding-top:0}
}
@media(prefers-reduced-motion:reduce){.result{transition:none}}

/* the socials repeat in the footer — the bar drops them on narrow
   screens, and this is where people look for them anyway */
.foot-social{justify-self:auto;margin-left:auto}
footer.foot nav{margin-left:auto}
footer.foot nav + .foot-social{margin-left:12px}
@media(max-width:720px){
  footer.foot nav{margin-left:0;width:100%}
  .foot-social{margin-left:-6px}
}

/* A log tile carrying a real featured image. The placeholder is a
   gradient of fixed height; an image has to fill exactly that box
   or a mixed row would step up and down. */
.post-shot.has-img{position:relative;padding:0;overflow:hidden}
.post-shot.has-img img{
  position:absolute;inset:0;
  width:100%;height:100%;object-fit:cover;display:block;
}

/* A divider in the results list, between the static index and the
   posts fetched live from WordPress. The two are ranked by
   different measures and are labelled rather than interleaved. */
.result-group{
  display:flex;align-items:baseline;gap:12px;
  padding:22px 4px 2px;
}
.result-group span{
  font-family:var(--disp);font-weight:800;font-size:17px;
  letter-spacing:-.026em;color:var(--ink);
}
.result-group i{
  font-style:normal;font-family:var(--mono);font-size:9.5px;
  letter-spacing:.15em;text-transform:uppercase;color:var(--dimmer);
}
.result-group::after{
  content:"";flex:1;height:1px;background:var(--edge-soft);
}

/* ============================================================
   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.
   ============================================================ */

@media(max-width:860px){

  /* two tracks now: the wordmark, and the button hard right */
  .sk-parent-in{
    grid-template-columns:1fr auto;
    gap:10px;padding:0 14px;
  }
  .sk-parent-in > [data-sk-find],
  .sk-parent-in > nav{display:none}

  .sk-burger{
    display:grid;place-items:center;gap:4px;justify-self:end;
    /* align-content, not just place-items. Auto rows in a grid
       STRETCH to fill by default, which spread the three bars to a
       12px pitch — so the 6px translate that folds them into a
       cross landed each bar short and drew a broken chevron
       instead of an X. Centring the rows keeps the pitch at the
       6px the transform is written for. */
    align-content:center;
    width:40px;height:34px;padding:0;
    background:transparent;
    border:1px solid var(--edge, #3B3459);
    border-radius:var(--r-s, 8px);
    color:var(--ink, #F1EDFA);
    cursor:pointer;
    /* iOS gives buttons a rounded grey chrome of its own */
    -webkit-appearance:none;appearance:none;
  }
  .sk-burger span{
    display:block;width:17px;height:2px;border-radius:2px;
    background:currentColor;
    transition:transform .18s ease, opacity .14s ease;
  }
  /* the three bars fold into a cross */
  .sk-parent.menu-open .sk-burger{border-color:var(--signal, #FFB020)}
  .sk-parent.menu-open .sk-burger span:nth-child(1){transform:translateY(6px) rotate(45deg)}
  .sk-parent.menu-open .sk-burger span:nth-child(2){opacity:0}
  .sk-parent.menu-open .sk-burger span:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

  /* The panel hangs off the bar rather than the page, so it
     follows the bar when it sticks and needs no knowledge of how
     tall the bar happens to be. */
  .sk-menu{
    position:absolute;top:100%;left:0;right:0;
    background:var(--near, #26213C);
    border-bottom:1px solid var(--edge-soft, #2A2442);
    box-shadow:0 24px 40px -18px rgba(10,4,32,.85);
    padding:14px 14px 18px;
    display:grid;gap:4px;
    max-height:calc(100vh - var(--parent-h, 52px));
    overflow-y:auto;
    /* clears the iPhone home indicator when the menu is long */
    padding-bottom:max(18px, env(safe-area-inset-bottom));
  }
  .sk-menu[hidden]{display:none}

  .sk-menu [data-sk-find]{width:100%;margin:0 0 10px}
  .sk-menu .input{width:100%;max-width:none}

  /* The bar's own nav is a flex row pinned right (justify-self:end
     in tokens.css / chrome.css). A clone of it inside the panel
     inherited that and sat half-width against the right edge. The
     panel wants the opposite: full width, stacked, left. */
  .sk-menu nav{
    display:grid;gap:2px;
    justify-self:stretch;justify-items:stretch;
    overflow:visible;
  }
  .sk-menu nav a{width:100%}
  .sk-menu nav a{
    display:block;
    padding:12px 12px;          /* a 44px target, which is the size
                                   a thumb actually hits */
    font-family:var(--mono, ui-monospace, monospace);
    font-size:12px;letter-spacing:.14em;text-transform:uppercase;
    color:var(--dim, #9E96BC);text-decoration:none;
    border-radius:var(--r-s, 8px);
    border:1px solid transparent;
  }
  .sk-menu nav a:hover,
  .sk-menu nav a:focus{
    color:var(--ink, #F1EDFA);
    background:var(--mid, #1E1A31);
    text-decoration:none;
  }
  .sk-menu nav a[aria-current="page"]{
    color:var(--ink, #F1EDFA);
    background:var(--lift, #2E284A);
    border-color:var(--edge, #3B3459);
  }
}
