/* Maze game (/play/maze, maze.js): the maze itself. The frame (bar, win card, confetti, How to play) is game.css. */
.mz-stage{position:relative}
/* "Slide me" bubble next to Cubi at the start (placed by maze.js), gone after the first move */
/* a speech bubble up and to the right of Cubi: Mini's yellow like the tray, no outline, a soft shadow (drop-shadow, so
   the tail gets it too), tail down to Cubi */
.mz-hint{position:absolute;z-index:2;transform:translate(6px,calc(-100% - 4px));transform-origin:15px calc(100% + 14px);background:#feda62;color:var(--ink);filter:drop-shadow(0 1px 1px #2024281f) drop-shadow(0 4px 8px #20242826);font:600 14px/1.25 Rubik,sans-serif;padding:11px 16px;border-radius:18px;width:max-content;pointer-events:none;animation:mz-pop .45s var(--ease-pop) .35s both,mz-talk 2.6s ease-in-out 1.2s infinite;transition:opacity .3s}
/* the tail: a yellow triangle under the bubble (svg added by maze.js), its top tucked 1 px into the bubble */
.mz-tail{position:absolute;left:10px;bottom:-14px;width:22px;height:15px;overflow:visible}
/* the bubble pops out of its tail, then gives a little "talking" bounce every few seconds (scaled from the tail tip) */
@keyframes mz-pop{from{opacity:0;transform:translate(6px,calc(-100% - 4px)) scale(.2)}}
@keyframes mz-talk{0%,78%,100%{transform:translate(6px,calc(-100% - 4px)) scale(1)}86%{transform:translate(6px,calc(-100% - 4px)) scale(1.07)}93%{transform:translate(6px,calc(-100% - 4px)) scale(.98)}}
.mz-ico{width:18px;height:18px;vertical-align:-4px;margin:0 1px}
.mz-keys{width:27px;height:19px;vertical-align:-5px;margin-left:2px}
.mz-hint.is-gone{opacity:0}
/* New maze pluses: on hover they twinkle one after another (a quarter turn and a little pop); on a click all three
   spin and the small ones jump out from the big one and back (maze.js adds .is-burst) */
.mg-new .mg-ico path,.mg-again .mg-ico path{transform-box:fill-box;transform-origin:center}
.mg-new:hover .mg-ico path,.mg-again:hover .mg-ico path{animation:mz-twinkle .5s var(--ease-pop) both}
.mg-new:hover .mg-ico path:nth-of-type(2),.mg-again:hover .mg-ico path:nth-of-type(2){animation-delay:.08s}
.mg-new:hover .mg-ico path:nth-of-type(3),.mg-again:hover .mg-ico path:nth-of-type(3){animation-delay:.16s}
@keyframes mz-twinkle{50%{transform:scale(1.35) rotate(45deg)}100%{transform:rotate(90deg)}}
.is-burst .mg-ico path{animation:mz-spin .6s var(--ease-pop) both!important}
.is-burst .mg-ico path:nth-of-type(2){animation-name:mz-out-lo!important}
.is-burst .mg-ico path:nth-of-type(3){animation-name:mz-out-hi!important}
@keyframes mz-spin{40%{transform:scale(.7) rotate(-90deg)}100%{transform:rotate(180deg)}}
@keyframes mz-out-lo{45%{transform:translate(3px,3px) scale(1.4) rotate(90deg)}100%{transform:rotate(180deg)}}
@keyframes mz-out-hi{45%{transform:translate(3px,-3px) scale(1.4) rotate(90deg)}100%{transform:rotate(180deg)}}
/* win: Cubi dances (frames from her animation), Mini dances along (CSS, the same beat: the dance loops every 3 s) */
.mz-duo{display:flex;align-items:flex-end;justify-content:center;margin:0 auto -6px}
.mz-duo .mg-dance{width:min(190px,42vw);margin:0}
.mz-duo-mini{width:min(92px,21vw);height:auto;margin:0 0 14px -18px;transform-origin:50% 100%;animation:mz-mini-dance .75s ease-in-out infinite alternate}
@keyframes mz-mini-dance{0%{transform:translateY(0) rotate(-8deg)}50%{transform:translateY(-12px) rotate(0)}100%{transform:translateY(0) rotate(8deg)}}
/* the maze keeps its shape (--ar from maze.js) and is never taller than the screen minus menu and bar */
.mz-box{--budget:328px;position:relative;display:block;margin:0 auto;width:min(100%,calc((100svh - var(--budget)) * var(--ar,1.3)));border-radius:18px;touch-action:none;user-select:none;-webkit-user-select:none;cursor:pointer}
.mz-box:focus-visible{outline:3px solid #7254c4;outline-offset:6px}
.mz-svg{display:block;width:100%;height:auto;overflow:visible}
.mz-walls{fill:none;stroke:var(--ink);stroke-width:.11;stroke-linecap:round;stroke-linejoin:round}
.mz-trail{fill:none;stroke:#ff85d5;stroke-width:.3;stroke-linecap:round;stroke-linejoin:round;opacity:.9}
.mz-cubi{transition:transform .09s linear;filter:drop-shadow(0 .04px .06px #20242840)}
.mz-box.is-new .mz-svg{animation:mg-deal .45s var(--ease-pop) both}

/* "Print this maze": a quiet link in the bottom right corner of the field */
.mz-print-btn{position:absolute;right:16px;bottom:12px;z-index:2;display:inline-flex;align-items:center;gap:6px;border:0;background:none;border-radius:20px;padding:7px 12px 7px 10px;font-weight:600;font-size:13px;color:#45484b;transition:background .2s,color .2s}
.mz-print-btn .mg-ico{width:18px;height:18px}
.mz-print-btn:hover{background:#fff0bf;color:var(--ink)}

/* the printed sheet: hidden on screen; on paper only the sheet shows, the maze fills an A4 page */
.mz-sheet{display:none}
@media print{
  @page{size:A4 portrait;margin:14mm}
  body>*:not(.mz-sheet){display:none!important}
  html,body{background:#fff!important}
  .mz-sheet{display:flex;flex-direction:column;align-items:center;gap:3mm;width:100%;height:265mm;color:#202428;font-family:'DM Sans',sans-serif;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .mz-sheet-logo{height:9mm;width:auto}
  .mz-sheet-title{margin:3mm 0 0;font:700 26pt/1.1 Rubik,sans-serif;letter-spacing:-.03em}
  .mz-sheet-level{margin:0;display:flex;align-items:center;gap:2mm;font:600 11pt Rubik,sans-serif;color:#45484b}
  .mz-sheet-level .mg-dots{display:inline-flex;gap:1mm}.mz-sheet-level .mg-dots u{width:2.2mm;height:2.2mm;border-radius:50%;background:#d8d8d8}.mz-sheet-level .mg-dots u.on{background:#202428}
  .mz-sheet-maze{flex:1;min-height:0;width:100%;display:flex;align-items:center;justify-content:center;margin-top:4mm}
  .mz-sheet-maze svg{width:100%;height:100%;max-height:205mm;overflow:visible}
  .mz-sheet-maze .mz-walls{stroke:#202428;stroke-width:.13}
  .mz-sheet-foot{margin:0;font-size:9pt;color:#626466}
}

/* tablets (touch, wider than a phone): the steady height from game.js (--screen) and less taken for the slimmer frame
   (the menu, the way back above the tray, the tray and field, plus the bar's own height from game.js, --bar: it can wrap into two rows) */
@media(pointer:coarse) and (min-width:761px){
  .mz-box{--budget:calc(var(--bar,48px) + 256px);width:min(100%,calc((var(--screen,100svh) - var(--budget)) * var(--ar,1.3)))}
}
/* full screen (game.css .mg-game.is-full): the maze is sized to the whole screen (its height --fh, game.js), minus the bar (--bar) and the slim frame */
.mg-game.is-full .mz-box{--budget:calc(var(--bar,48px) + 110px);width:min(100%,calc((var(--fh,100vh) - var(--budget)) * var(--ar,1.3)))}
/* a tray too narrow for the bar in one row (tablets upright; French needs about 760 px): New maze becomes a round
   button, and if that is not enough the time hides as on phones (it shows on the win card). Phones have their own bar */
@media(min-width:761px){
  @container tray (max-width:800px){.mg-new span{display:none}.mg-new{padding:0}}
  @container tray (max-width:690px){.mg-stats{display:none}}
}
@media(max-width:760px){
  /* phones: just the printer, a small round button in the bottom right corner of the field (Cubi starts on the left) */
  .mz-print-btn{right:8px;bottom:8px;width:38px;height:38px;padding:0;justify-content:center;background:#fffcf3;box-shadow:0 2px 8px -3px #20242840}
  .mz-print-btn span{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .mz-box{--budget:260px;border-radius:12px;width:min(100%,calc((var(--screen,100svh) - var(--budget)) * var(--ar,1.3)))}
  .mz-hint{font-size:13px;padding:7px 11px;border-radius:15px}
  /* phone bar: levels + sound + new maze in one row, the time shows on the win card */
  .mg-stats{display:none}
}
@media(prefers-reduced-motion:reduce){
  .mz-cubi{transition:none}
  .mz-hint,.mz-duo-mini,.mg-ico path{animation:none!important}
  .mz-box.is-new .mz-svg{animation:none}
}
