/*
 * TurtleLab: styles.
 * Copyright (C) 2026 Eric Brown. Licensed under the GNU AGPL-3.0 or later.
 * See COPYING in the folder above this one.
 */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  display: flex;
  flex-direction: column;
  background: #e9edf1;
  color: #1b1f23;
  font-family: Roboto, system-ui, sans-serif;
  /* Dragging on the page should never scroll or zoom it. */
  overscroll-behavior: none;
}

/* ---- Toolbar ---- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  padding: 0.35rem 0.75rem;
  background: #4da6ff;
  color: #fff;
}

.toolbar h1 {
  margin: 0 0.75rem 0 0;
  font-size: 1.2rem;
}

.toolbar label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

.icon-button {
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
}

.icon-button img {
  display: block;
  width: 100%;
  height: 100%;
}

.toolbar-link,
.embed-link {
  color: #fff;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.toolbar-link:first-of-type {
  margin-left: auto; /* push Guide and About to the right edge */
}

.toolbar-gap {
  width: 0.75rem;
}

/* On a narrower window, squeeze the gaps so the whole toolbar, links and menu included, stays on one row. */
@media (max-width: 1100px) {
  .toolbar { gap: 0.1rem; }
  .toolbar-gap { width: 0.4rem; }
  .icon-button { width: 2.25rem; height: 2.25rem; }
}

/* And a little more on a window as narrow as an iPad held sideways or a small laptop, where the Full screen button made it one icon too many. */
@media (max-width: 1060px) {
  .icon-button { width: 2rem; height: 2rem; }
}

.icon-button:disabled {
  opacity: 0.4;
  cursor: default;
}

/* ---- Inside a lesson page (?embed=1, set on the page by js/embed-flag.js) ----
   A slim toolbar: Run, Stop, Undo, Redo, Start over and Open full size. The palettes, the can, the boxes readout and the message line stay. */
.embed-only { display: none; }
.embedded .embed-only { display: inline-flex; }
.embedded .toolbar > :not(#run):not(#stop):not(#undo):not(#redo):not(.embed-only) { display: none; }
.embedded .toolbar { padding: 0.2rem 0.5rem; }
.embedded #embed-open { margin-left: auto; }
.embed-button {
  align-items: center;
  height: 2rem;
  padding: 0 0.8rem;
  border: 2px solid rgba(255, 255, 255, 0.9);
  border-radius: 999px;
  background: transparent;
  color: #fff;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}
.embed-button:hover { background: rgba(255, 255, 255, 0.25); }
.embedded .score-badge { display: none; }
.embedded .boxes-readout { right: 0.75rem; } /* the badge that it made room for is not there */

.icon-button[aria-pressed='true'] {
  background: rgba(255, 255, 255, 0.45);
}

/* ---- The stage: paper, turtle, blocks ---- */

.stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  touch-action: none; /* dragging empty space slides the blocks, it never scrolls the page */
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* The box is sized by script to fit the stage while keeping the paper's shape. */
.paper-box {
  position: relative;
  background: #fff;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
  touch-action: none;
}

.paper {
  display: block;
  width: 100%;
  height: 100%;
}

/* The grid lies over the paper but is not part of it: it is not in a saved picture, and clicks go through it. */
.paper-grid {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.paper-grid[hidden] { display: none; }

/* How the paper looks on the screen (js/ui/canvas-view.js setPaper): never in a saved picture. The paper the turtle draws on stays white; a dark one
   turns the picture light-on-dark here (black becomes white like chalk, red stays red), and a layer over it, blended in, gives the board its color and
   prints the lines (graph and blueprint). The turtle and the grid lie over all of it. */
.paper-style {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.paper-style[hidden] { display: none; }
.paper-box.paper-graph .paper-style,
.paper-box.paper-whiteboard .paper-style { mix-blend-mode: multiply; }
.paper-box.paper-blueprint .paper { filter: invert(1) hue-rotate(180deg); }
.paper-box.paper-chalkboard .paper-style,
.paper-box.paper-blueprint .paper-style { mix-blend-mode: lighten; }

/* The hand drawn papers (the whiteboard and the chalkboard): a sketch canvas, the same drawing wobbled (core/hand.js, painted by canvas-view.js), takes the
   paper canvas's place on the screen. The paper canvas stays underneath, hidden and untouched: it is the real picture, what Save and the PDF read. The
   sketch starts see-through, so the box shows through it: white for the whiteboard, and the board's own color (set by script) for the chalkboard. */
.paper-sketch {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.paper-sketch[hidden] { display: none; }
.paper-box.paper-hand .paper { visibility: hidden; }
/* Chalk is light on dark like the other dark papers; its grain (a mask that lets the board show through) is put on by script. */
.paper-box.paper-chalkboard .paper-sketch { filter: invert(1) hue-rotate(180deg); }

/* A preview of a tapped palette block: grey lines over the paper that fade out. Clicks go through it. */
.paper-peek {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0.85;
}
.paper-peek[hidden] { display: none; }
.paper-peek.fading { opacity: 0; transition: opacity 0.9s ease-out; }
/* While a preview plays the turtle glides to the far end and back. */
.turtle-sprite.peeking { transition: transform 0.5s ease-in-out; }
@media (prefers-reduced-motion: reduce) {
  .turtle-sprite.peeking { transition: none; }
  .paper-peek.fading { transition-duration: 0.3s; }
}

.turtle-sprite {
  position: absolute;
  left: 0;
  top: 0;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}

.turtle-sprite svg {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.turtle-sprite.dragging { cursor: grabbing; }
/* While a program runs the turtle cannot be dragged, so it lets a press go through to the paper: a program that listens for clicks (the turtle often sits right on what is to be clicked) hears them. */
.turtle-sprite.locked { cursor: default; pointer-events: none; }

/* The shell is the color of the pen (the page sets --shell and --scute from it), and its markings a shade of it. */
.turtle-sprite .shell { fill: var(--shell, #6cc600); transition: fill-opacity 0.18s ease-out; }
.turtle-sprite .scutes path { fill: var(--scute, #037700); }

/* With the pen up the turtle hovers: a little bigger, a shadow underneath, and a paler shell, as if the pen were lifted off the paper.
   (scale and rotate here are the separate properties, so they never fight the sprite's own place and heading.) */
.turtle-sprite svg {
  transition: scale 0.18s ease-out, filter 0.18s ease-out;
}
.turtle-sprite.pen-up svg {
  scale: 1.14;
  filter: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.38));
}
.turtle-sprite.pen-up .shell { fill-opacity: 0.4; }

/* Picked up, it squirms: it wriggles from side to side for as long as you hold it. */
.turtle-sprite.dragging svg {
  animation: turtle-squirm 0.3s ease-in-out infinite alternate;
}
@keyframes turtle-squirm {
  from { rotate: -8deg; translate: -1px 0; }
  to { rotate: 8deg; translate: 1px -1px; }
}
/* After half a minute alone the turtle breathes: the color of its shell (the pen's color, and the markings on it) slowly goes lighter and then comes back to its
   full depth, over and over, like a breath or a heartbeat, until somebody does something (js/ui/idle.js starts and stops it). It is a change of color, never of
   see-through: the page works out the lighter shade from the pen's color (--shell-breath, --scute-breath, see turtle-look.js). Only the colored top changes: the
   head, flippers and outline stay as they are, and nothing moves (no scale or other transform, which would also shift the sprite from its place). It goes on whatever
   else the turtle is doing. A breath takes --breath (4 seconds). The keyframes name only the lighter moment, so each breath starts from, and returns to, the
   shell's own color. */
.turtle-sprite.breathing-color .shell {
  animation: turtle-breath-shell var(--breath, 4s) ease-in-out infinite;
}
.turtle-sprite.breathing-color .scutes path {
  animation: turtle-breath-scute var(--breath, 4s) ease-in-out infinite;
}
@keyframes turtle-breath-shell {
  50% { fill: var(--shell-breath, #ff8080); }
}
@keyframes turtle-breath-scute {
  50% { fill: var(--scute-breath, #ff8080); }
}

/* While a wait block waits the turtle yawns: it sways slowly, and a Zzz floats up from it (the page keeps the Zzz at the turtle). */
.turtle-sprite.yawning svg {
  animation: turtle-yawn 1.6s ease-in-out infinite alternate;
}
@keyframes turtle-yawn {
  from { rotate: -5deg; translate: 0 0; }
  to { rotate: 5deg; translate: 0 1px; }
}
.turtle-zzz {
  position: absolute;
  left: 0;
  top: 0;
  width: 2rem;
  height: 2.2rem;
  pointer-events: none;
  font-weight: 700;
  color: #5b7fa6;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff;
}
.turtle-zzz[hidden] { display: none; }
/* Each z rises all the way off the top of the window (--rise is how far, --rise-time how long, --times how often, all set from where the
   turtle is), one after another, swaying as it goes. */
.turtle-zzz span {
  position: absolute;
  left: 0;
  bottom: 0;
  opacity: 0;
  animation-name: turtle-zzz;
  animation-duration: var(--rise-time, 2.1s);
  animation-timing-function: linear;
  animation-iteration-count: var(--times, infinite);
  animation-fill-mode: backwards;
}
.turtle-zzz span:nth-child(1) { font-size: 0.8rem; animation-delay: 0s; }
.turtle-zzz span:nth-child(2) { font-size: 1.05rem; animation-delay: calc(var(--rise-time, 2.1s) * 0.28); }
.turtle-zzz span:nth-child(3) { font-size: 1.35rem; animation-delay: calc(var(--rise-time, 2.1s) * 0.56); }
@keyframes turtle-zzz {
  0% { opacity: 0; transform: translate(0, 4px) rotate(-8deg); }
  6% { opacity: 1; }
  25% { transform: translate(9px, calc(var(--rise, 26px) * -0.25)) rotate(8deg); }
  50% { transform: translate(-5px, calc(var(--rise, 26px) * -0.5)) rotate(-8deg); }
  75% { transform: translate(9px, calc(var(--rise, 26px) * -0.75)) rotate(8deg); }
  100% { opacity: 1; transform: translate(0, calc(var(--rise, 26px) * -1)) rotate(-4deg); }
}

/* When a program finishes the turtle waves: the front flipper on its right swings out and back, twice. */
.turtle-sprite.waving .wave-flipper {
  transform-box: fill-box;
  transform-origin: 0% 100%;
  animation: turtle-wave 0.6s ease-in-out 2;
}
@keyframes turtle-wave {
  0%, 100% { transform: rotate(0deg); }
  30% { transform: rotate(-38deg); }
  70% { transform: rotate(22deg); }
}

/* The idle antics (js/ui/antics.js), for when the turtle has been left alone a while. */

/* Dance: a few hops and sways, then a full spin. It runs twice. */
.turtle-sprite.pose-dance svg {
  animation: turtle-dance 1.7s ease-in-out 2;
}
@keyframes turtle-dance {
  0% { rotate: 0deg; translate: 0 0; }
  12% { rotate: -14deg; translate: -2px -5px; }
  25% { rotate: 14deg; translate: 2px 0; }
  37% { rotate: -14deg; translate: -2px -5px; }
  50% { rotate: 14deg; translate: 2px 0; }
  60% { rotate: 0deg; translate: 0 0; }
  100% { rotate: 360deg; translate: 0 0; }
}

/* Scratch its head: the front left flipper comes up to the head and rubs back and forth, while the turtle leans into it. */
.turtle-sprite.pose-scratch svg {
  animation: turtle-lean 2.6s ease-in-out 1;
}
@keyframes turtle-lean {
  0%, 100% { rotate: 0deg; }
  15%, 85% { rotate: -5deg; }
}
.turtle-sprite.pose-scratch .scratch-flipper {
  transform-box: fill-box;
  transform-origin: 100% 100%;
  animation: turtle-scratch 0.22s ease-in-out 11 alternate;
}
@keyframes turtle-scratch {
  from { transform: rotate(36deg); }
  to { transform: rotate(64deg); }
}

/* Blow bubbles, as if breathing under water: little bubbles wobble up from the nose, one after another. */
.turtle-bubbles {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}
.turtle-bubbles[hidden] { display: none; }
.turtle-bubbles span {
  position: absolute;
  left: 0;
  top: 0;
  border: 1.5px solid #6c98c4;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #fff, rgba(255, 255, 255, 0.35));
  opacity: 0;
  animation-name: turtle-bubble;
  animation-duration: var(--rise-time, 2.2s);
  animation-timing-function: linear;
  animation-iteration-count: var(--times, infinite);
  animation-fill-mode: backwards;
}
.turtle-bubbles span:nth-child(1) { width: 0.4rem; height: 0.4rem; margin-left: -0.2rem; animation-delay: 0s; }
.turtle-bubbles span:nth-child(2) { width: 0.65rem; height: 0.65rem; margin-left: 0.15rem; animation-delay: calc(var(--rise-time, 2.2s) * 0.2); }
.turtle-bubbles span:nth-child(3) { width: 0.5rem; height: 0.5rem; margin-left: -0.35rem; animation-delay: calc(var(--rise-time, 2.2s) * 0.4); }
.turtle-bubbles span:nth-child(4) { width: 0.8rem; height: 0.8rem; margin-left: 0.05rem; animation-delay: calc(var(--rise-time, 2.2s) * 0.6); }
/* Each bubble wobbles from side to side as it rises, all the way off the top of the window, and swells a little as it goes. */
@keyframes turtle-bubble {
  0% { opacity: 0; transform: translate(0, 0) scale(0.5); }
  5% { opacity: 1; }
  25% { transform: translate(8px, calc(var(--rise, 3rem) * -0.25)) scale(0.75); }
  50% { transform: translate(-7px, calc(var(--rise, 3rem) * -0.5)) scale(0.95); }
  75% { transform: translate(8px, calc(var(--rise, 3rem) * -0.75)) scale(1.1); }
  100% { opacity: 1; transform: translate(-5px, calc(var(--rise, 3rem) * -1)) scale(1.25); }
}

/* And, rarely, what turtles do: a little pile drops from the tail, falls, bounces once and fades. */
.turtle-poop {
  position: absolute;
  left: 0;
  top: 0;
  width: 1.5rem;
  height: 1.5rem;
  margin: -0.75rem 0 0 -0.75rem;
  pointer-events: none;
}
.turtle-poop svg {
  display: block;
  width: 100%;
  height: 100%;
  animation: turtle-poop var(--fall-time, 1.2s) ease-in forwards;
}
/* It drops from the tail and falls all the way off the bottom of the window (--fall is how far, --fall-time how long), tumbling as it goes. */
@keyframes turtle-poop {
  0% { opacity: 0; transform: translateY(0) scale(0.4) rotate(0deg); }
  5% { opacity: 1; transform: translateY(calc(var(--fall, 4rem) * 0.01)) scale(1) rotate(0deg); }
  100% { opacity: 1; transform: translateY(var(--fall, 4rem)) scale(1) rotate(200deg); }
}

/* The ring that opens where a click landed (CanvasView.ring). It has a white edge inside and out so it shows on every paper. */
.click-ring {
  position: absolute;
  width: 2.6rem;
  height: 2.6rem;
  margin: -1.3rem 0 0 -1.3rem;
  box-sizing: border-box;
  border: 3px solid #ff2c76;
  border-radius: 50%;
  box-shadow: 0 0 0 2px #ffffff, inset 0 0 0 2px #ffffff;
  pointer-events: none;
  animation: click-ring 0.5s ease-out forwards;
}
@keyframes click-ring {
  from { transform: scale(0.2); opacity: 1; }
  to { transform: scale(1.1); opacity: 0; }
}
@keyframes click-ring-calm {
  from { opacity: 1; }
  to { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .click-ring { animation-name: click-ring-calm; }
  .turtle-sprite svg { transition: none; }
  .turtle-sprite.dragging svg,
  .turtle-sprite.yawning svg,
  .turtle-sprite.pose-dance svg,
  .turtle-sprite.pose-scratch svg { animation: none; }
  .turtle-sprite.breathing-color .shell,
  .turtle-sprite.breathing-color .scutes path { animation: none; }
  .turtle-zzz,
  .turtle-bubbles,
  .turtle-poop { display: none; }
  .turtle-sprite.waving .wave-flipper,
  .turtle-sprite.pose-scratch .scratch-flipper { animation: none; }
}

/* The layer above everything, for what floats off the top of the window or falls off the bottom (js/ui/sky.js). */
.sky {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  z-index: 60;
  overflow: hidden;
}

/* ---- Blocks ---- */

/* The workspace covers the paper but lets clicks through, except on blocks. */
.workspace {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  touch-action: none;
}

.workspace .node {
  pointer-events: auto;
  cursor: grab;
}

.workspace .node.literal,
.workspace .node.nameslot { cursor: text; }
.workspace .node.fontslot,
.workspace .node.keyslot,
.workspace .node.colorslot { cursor: pointer; }

.block-text {
  font-family: Roboto, system-ui, sans-serif;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

.workspace .carried { opacity: 0.9; }
.workspace .carried .node { cursor: grabbing; }

/* The block that just ran, and the block that caused an error. */
.workspace .running path { stroke: #fff; stroke-width: 3px; }
.workspace .error path { stroke: #e60000; stroke-width: 3px; }

.snap-ring {
  fill: rgba(255, 255, 255, 0.55);
  stroke: #ffb300;
  stroke-width: 3;
  pointer-events: none;
}

.hint {
  position: absolute;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  margin: 0;
  padding: 0.4rem 0.9rem;
  border-radius: 1rem;
  background: rgba(255, 255, 255, 0.85);
  color: #444;
  pointer-events: none;
}

.stage.blocks-hidden .workspace,
.stage.blocks-hidden .palettes,
.stage.blocks-hidden .flyout,
.stage.blocks-hidden .python-box,
.stage.blocks-hidden .logo-box,
.stage.blocks-hidden .hint {
  display: none;
}

.number-input {
  position: absolute;
  z-index: 6;
  padding: 0 0.4rem;
  font: 16px Roboto, system-ui, sans-serif; /* 16px so phones don't zoom in */
  border: 2px solid #ff2c76;
  border-radius: 0.3rem;
  background: #fff;
}

/* The question box that an ask block shows (js/ui/ask-box.js): at the top of the page, clear of the drawing. */
.ask-box {
  position: absolute;
  z-index: 30;
  top: 0.6rem;
  left: 50%;
  transform: translateX(-50%);
  width: 22rem;
  max-width: calc(100% - 8px);
  box-sizing: border-box;
  padding: 0.7rem 0.8rem 0.6rem;
  color: #1b1f23;
  background: #fff;
  border: 2px solid #f3a600;
  border-radius: 0.6rem;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  touch-action: manipulation;
}
.ask-question { margin: 0 0 0.5rem; font-size: 1.05rem; font-weight: 600; overflow-wrap: anywhere; }
.ask-row { display: flex; gap: 0.4rem; }
.ask-input {
  flex: 1 1 auto;
  min-width: 0;
  box-sizing: border-box;
  min-height: 2.3rem;
  padding: 0 0.5rem;
  font: 16px Roboto, system-ui, sans-serif; /* 16px so phones don't zoom in */
  border: 2px solid #8a8a8a;
  border-radius: 0.35rem;
}
.ask-ok,
.ask-cancel {
  min-height: 2.3rem;
  padding: 0 0.8rem;
  font: 600 0.95rem Roboto, system-ui, sans-serif;
  border: 2px solid #8a8a8a;
  border-radius: 0.35rem;
  background: #fff;
  cursor: pointer;
}
.ask-ok { color: #fff; background: #1f6fd0; border-color: #1f6fd0; }
.ask-input:focus-visible,
.ask-ok:focus-visible,
.ask-cancel:focus-visible { outline: 3px solid #3a7bd5; outline-offset: 1px; }
.ask-problem { min-height: 1.2rem; margin: 0.3rem 0 0; font-size: 0.9rem; color: #b00020; }

/* ---- Palettes ---- */

.palettes {
  position: absolute;
  left: 0.5rem;
  top: 0.5rem;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.5rem;
  border-radius: 1.8rem;
  background: rgba(255, 255, 255, 0.85);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

/* The icons are drawn for a light background, so each button is white with a
   ring in its palette's color. */
.palette-button {
  width: 3rem;
  height: 3rem;
  padding: 0.3rem;
  border: 4px solid var(--palette-color);
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
}

.palette-button img {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.palette-button.selected {
  outline: 3px solid #1b1f23;
  outline-offset: 2px;
}

.flyout {
  position: absolute;
  left: 5.6rem;
  top: 0.5rem;
  bottom: 0.5rem;
  z-index: 3;
  overflow-y: auto;
  border-radius: 0.8rem;
  background: rgba(240, 240, 240, 0.96);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
}

.flyout[hidden] { display: none; }

.flyout-svg {
  display: block;
  /* Up and down scrolls the flyout. Sideways drags a block out of it. */
  touch-action: pan-y;
}

.flyout-svg .stack { cursor: grab; }

/* While a block is held over the palette, it turns red: drop to delete. */
.palettes.trash,
.flyout.trash {
  background: rgba(255, 190, 190, 0.95);
}

/* The delete zone, shown while a block is held over it: the whole left column. */
.trash-band {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  display: none;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 1rem;
  background: rgba(255, 150, 150, 0.35);
  border-right: 3px dashed rgba(190, 40, 40, 0.55);
  pointer-events: none;
}

.trash-band.active { display: flex; }

/* The trash can at the bottom of the left side, and its shark. Which state it is in
   is a class on .trash-can: hungry (a block is held over the side) or eating (one was
   just dropped). The shark sinks behind the front of the can, which is what hides it. */
.trash-can {
  position: absolute;
  left: 0.5rem;
  bottom: 0.5rem;
  width: 5rem;
  pointer-events: none; /* and it sits under the blocks, so a stack held over it is on top */
}

/* On a short window the column of palette buttons runs close to the can, so it shrinks. */
@media (max-height: 700px) {
  .trash-can { width: 4rem; }
}

.stage.blocks-hidden .trash-can { display: none; }

.trash-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.trash-can .shark {
  transform: translateY(84px);
  transition: transform 0.22s cubic-bezier(0.3, 1.6, 0.5, 1);
}

.trash-can .jaw {
  transform: translateY(0);
  transition: transform 0.18s ease-out;
}

.trash-can .lid {
  transform-origin: 24px 73px;
  transition: transform 0.2s ease-out;
}

/* A fish is swimming by: the shark's head comes up over the lid, just its eyes and fin, and the pupils follow the fish (--look-x and --look-y).
   Dozing off (dreaming) is the same pose with the eyes shut. */
.trash-can.peek .shark,
.trash-can.dreaming .shark { transform: translateY(12px); }
.trash-can .eyes-shut { opacity: 0; }
.trash-can.dreaming .eyes-shut { opacity: 1; }
.trash-can.dreaming .eye,
.trash-can.dreaming .pupil { opacity: 0; }
.trash-can .pupil {
  transform: translate(var(--look-x, 0px), var(--look-y, 0px));
  transition: transform 0.12s ease-out;
}

.trash-can.hungry .shark,
.trash-can.eating .shark,
.trash-can.spitting .shark,
.trash-can.hunting .shark { transform: translateY(-40px); }

.trash-can.hungry .jaw,
.trash-can.eating .jaw,
.trash-can.spitting .jaw,
.trash-can.hunting .jaw { transform: translateY(26px); }

.trash-can.hungry .lid,
.trash-can.eating .lid,
.trash-can.spitting .lid,
.trash-can.hunting .lid { transform: translate(-34px, -4px) rotate(-62deg); }

/* A fish or the boat was clicked: the shark comes up, then a copy of its head (in the layer above everything) swims out to it, chomps and swims home
   (Trash.hunt). While the copy is out the real shark is hidden and the open can sits empty. */
.trash-can.swimming-out .shark { visibility: hidden; }
.shark-swimmer {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  will-change: transform;
}
.shark-swimmer .shark { transform: translateY(-40px); }
.shark-swimmer .jaw { transform: translateY(26px); }
.shark-swimmer .pupil { transform: translate(var(--look-x, 0px), 0); }
.shark-swimmer.chomp .jaw { animation: chomp 0.8s ease-in-out; }
/* Swimming, it wags from side to side (the separate rotate property, so it never fights the place the page gives it). */
.shark-swimmer.swimming .trash-svg {
  transform-origin: 50% 32%;
  animation: swimmer-wag 0.28s ease-in-out infinite alternate;
}
@keyframes swimmer-wag {
  from { rotate: -7deg; }
  to { rotate: 7deg; }
}

/* The shark's dream of turtle stew: a thought bubble above the can, with a pot of stew in it, steam rising, and a few z's coming off the shark. */
.dream {
  position: absolute;
  left: 3.4rem;
  top: -6.4rem;
  width: 9.5rem;
  pointer-events: none;
  animation: dream-float 8.5s ease-in-out forwards;
}
.dream-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
@keyframes dream-float {
  0% { opacity: 0; transform: translateY(8px) scale(0.85); }
  8% { opacity: 1; transform: translateY(0) scale(1); }
  50% { transform: translateY(-4px) scale(1.02); }
  92% { opacity: 1; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(-6px) scale(0.95); }
}
.dream .steam { animation: dream-steam 1.8s ease-in-out infinite; }
.dream .steam-2 { animation-delay: 0.6s; }
.dream .steam-3 { animation-delay: 1.2s; }
@keyframes dream-steam {
  0%, 100% { opacity: 0.15; transform: translateY(2px); }
  50% { opacity: 0.9; transform: translateY(-3px); }
}
/* The fishing boat that comes now and then to try to harpoon the shark (js/ui/boat.js). It and its harpoon float in the layer above everything.
   The boat takes clicks (the shark comes up and eats it); its harpoon and rope do not. */
.boat {
  position: absolute;
  left: 0;
  top: 0;
  width: 5.8rem;
  pointer-events: auto;
  cursor: pointer;
  touch-action: none;
  will-change: transform;
}
.boat-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.boat-lines {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.boat-lines .rope {
  stroke: #8a6a3a;
  stroke-width: 1.7;
  stroke-linecap: round;
}

/* The score: a sticker on the can's front for each thing the shark has eaten, less a point for each harpoon that hit. It is not there at nothing. */
.can-score { display: none; transform-box: fill-box; transform-origin: 50% 50%; }
.trash-can.has-score .can-score { display: inline; }
.can-score-text { font-family: Roboto, system-ui, sans-serif; user-select: none; }
.can-score.bump { animation: can-score-bump 0.5s ease-out; }
.can-score.ouch { animation: can-score-ouch 0.5s ease-out; }
.can-score.ouch circle { fill: #ffb3a7; }
@keyframes can-score-bump {
  0% { transform: scale(1); }
  30% { transform: scale(1.45) rotate(-8deg); }
  60% { transform: scale(0.92); }
  100% { transform: scale(1); }
}
@keyframes can-score-ouch {
  0% { transform: translateX(0); }
  15% { transform: translateX(-5px); }
  35% { transform: translateX(5px); }
  55% { transform: translateX(-3px); }
  100% { transform: translateX(0); }
}

/* Poking the can: the body of the can can be clicked (the can itself ignores the mouse), it squashes a little, and a bubble says how many pokes are left. */
.trash-hit {
  position: absolute;
  left: 22%;
  width: 56%;
  top: 62%;
  bottom: 0;
  pointer-events: auto;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.trash-can.poked .trash-svg { transform-origin: 50% 100%; animation: can-poked 0.3s ease-out; }
@keyframes can-poked {
  0% { transform: scale(1, 1); }
  35% { transform: scale(1.06, 0.92); }
  70% { transform: scale(0.98, 1.03); }
  100% { transform: scale(1, 1); }
}
.poke-left {
  position: absolute;
  left: 100%;
  bottom: 30%;
  margin-left: 0.25rem;
  padding: 0.1rem 0.55rem;
  border: 1.5px solid #6c98c4;
  border-radius: 999px;
  background: #fff;
  color: #3b6385;
  font-size: 0.8rem;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
}

/* The harpoon hits the can: it rings (a shake), and a "clang!" pops up. */
.trash-can.clang {
  transform-origin: 50% 100%;
  animation: can-clang 0.55s ease-out;
}
@keyframes can-clang {
  0% { rotate: 0deg; }
  14% { rotate: -6deg; }
  32% { rotate: 5deg; }
  50% { rotate: -3deg; }
  70% { rotate: 1.5deg; }
  100% { rotate: 0deg; }
}
.clang-word {
  position: absolute;
  left: 50%;
  top: 14%;
  white-space: nowrap;
  font-weight: 800;
  font-size: 1rem;
  color: #c0392b;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff;
  pointer-events: none;
  animation: clang-pop 0.9s ease-out forwards;
}
@keyframes clang-pop {
  0% { opacity: 0; transform: translate(-50%, 0) scale(0.3) rotate(-8deg); }
  18% { opacity: 1; transform: translate(-50%, -0.2rem) scale(1.3) rotate(-6deg); }
  100% { opacity: 0; transform: translate(-50%, -1.6rem) scale(1) rotate(-4deg); }
}

/* The shark is sick (Trash.spew): the can shakes and the shark goes green while it brings things up, and says "blech!". What it brings up (js/ui/spew.js) is in the layer
   above everything: each thing flies out in an arc, lands, and fades to nothing. */
.trash-can.heaving .trash-svg { transform-origin: 50% 100%; animation: can-queasy 0.26s ease-in-out infinite alternate; }
.trash-can.heaving .shark { filter: sepia(1) hue-rotate(28deg) saturate(2.6); } /* all of the shark one sickly green (turning the hue only would make the red inside of its mouth blue) */
@keyframes can-queasy {
  from { transform: rotate(-2.5deg) translateX(-1.5px); }
  to { transform: rotate(2.5deg) translateX(1.5px); }
}
.spew-word {
  position: absolute;
  left: 50%;
  top: 8%;
  white-space: nowrap;
  font-weight: 800;
  font-size: 1rem;
  color: #4f7f12;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff;
  pointer-events: none;
  animation: spew-pop 1.1s ease-out forwards;
}
@keyframes spew-pop {
  0% { opacity: 0; transform: translate(-50%, 0) scale(0.3) rotate(6deg); }
  20% { opacity: 1; transform: translate(-50%, -0.3rem) scale(1.25) rotate(5deg); }
  100% { opacity: 0; transform: translate(-50%, -1.8rem) scale(1) rotate(3deg); }
}
.spew-piece {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  will-change: transform, opacity;
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.3));
}
.spew-piece svg { display: block; overflow: visible; }
.spew-chip { border-radius: 6px; border: 2px solid rgba(0, 0, 0, 0.22); }

/* Now and then, after a meal, a bubble with a "burp" in it floats up out of the shark's mouth. */
.burp {
  position: absolute;
  left: 50%;
  top: 36%;
  width: 0;
  height: 0;
  pointer-events: none;
}
.burp-dot,
.burp-word {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  animation: burp-rise 1.6s ease-out forwards;
}
.burp-dot {
  width: 0.45rem;
  height: 0.45rem;
  border: 1.5px solid #6c98c4;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.6);
}
.burp-dot-1 { margin-left: -1.1rem; animation-delay: 0.05s; }
.burp-dot-2 { width: 0.7rem; height: 0.7rem; margin-left: 0.9rem; animation-delay: 0.15s; }
.burp-word {
  margin: -0.5rem 0 0 -1.2rem;
  padding: 0.12rem 0.55rem;
  border: 1.5px solid #6c98c4;
  border-radius: 999px;
  background: #fff;
  color: #3b6385;
  font-size: 0.78rem;
  font-weight: 700;
  animation-delay: 0.2s;
}
@keyframes burp-rise {
  0% { opacity: 0; transform: translateY(0) scale(0.4); }
  18% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-4.2rem) scale(1.05); }
}

.trash-can.chomp .jaw { animation: chomp 0.8s ease-in-out; }

@keyframes chomp {
  0% { transform: translateY(26px); }
  20% { transform: translateY(0); }
  40% { transform: translateY(22px); }
  60% { transform: translateY(0); }
  80% { transform: translateY(14px); }
  100% { transform: translateY(0); }
}

/* A copy of a deleted stack on its way into the shark: it is only for looking at. */
.workspace .ghost,
.workspace .ghost * { pointer-events: none !important; }

/* The occasional fish (js/ui/fish.js). It swims in the layer above everything, which is given its place with a transform, and it is the one thing in
   that layer that takes clicks: click it and the shark eats it. The invisible border makes it an easier thing to catch. */
.fish {
  position: absolute;
  left: 0;
  top: 0;
  width: 2.6rem;
  pointer-events: auto;
  cursor: pointer;
  touch-action: none;
  will-change: transform;
}
.fish::before {
  content: '';
  position: absolute;
  inset: -0.9rem;
}
.fish-svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.fish-tail {
  transform-origin: 9px 14px;
  animation: fish-wag 0.32s ease-in-out infinite alternate;
}
@keyframes fish-wag {
  from { transform: rotate(-16deg); }
  to { transform: rotate(16deg); }
}
/* What the shark is eating (a fish or the boat): it spins and shrinks under the shark's jaws, and cannot be clicked again. */
.fish.eaten,
.boat.eaten { pointer-events: none; }
.fish.eaten .fish-svg,
.boat.eaten .boat-svg {
  transform-origin: 50% 50%;
  animation: visitor-eaten 0.48s ease-in forwards;
}
@keyframes visitor-eaten {
  from { rotate: 0deg; scale: 1; opacity: 1; }
  to { rotate: 200deg; scale: 0.15; opacity: 0.4; }
}

@media (prefers-reduced-motion: reduce) {
  .fish-tail { animation: none; }
  .fish,
  .shark-swimmer,
  .burp,
  .spew-word,
  .spew-piece,
  .dream,
  .boat,
  .boat-lines,
  .clang-word { display: none; }
  .trash-can.clang { animation: none; }
  .can-score.bump, .can-score.ouch, .trash-can.poked .trash-svg, .trash-can.heaving .trash-svg { animation: none; }
  .trash-can.heaving .shark { filter: none; }
  .trash-can .pupil { transition: none; }
  .trash-can .shark,
  .trash-can .jaw,
  .trash-can .lid { transition: none; }
  .trash-can.chomp .jaw { animation: none; }
}

/* ---- Messages ---- */

.message {
  margin: 0;
  min-height: 1.6rem;
  padding: 0.25rem 0.75rem;
  background: #fff8e8;
  color: #7a5b00;
}

.message:empty { visibility: hidden; }

/* ---- The badge: blocks, complexity, elegance, efficiency ---- */

/* A small card in the bottom right corner, the one place no palette, flyout or delete zone reaches (they fill the left side: a badge there covered the last
   blocks of the open Flow palette). The details open upward from it. The boxes readout moves left to make room, and the code boxes sit above both. */
.score-badge {
  position: absolute;
  right: 0.75rem;
  bottom: 0.75rem;
  z-index: 5;
}

.score-pill {
  display: flex;
  align-items: stretch;
  gap: 0.15rem;
  padding: 0.3rem 0.4rem;
  font: inherit;
  color: #3b2a6b;
  background: rgba(244, 238, 255, 0.96);
  border: 2px solid #9b7fe0;
  border-radius: 0.8rem;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}

.score-pill:hover { background: #fff; }
.score-pill:focus-visible { outline: 3px solid #3a7bd5; outline-offset: 2px; }

.score-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-width: 4.3rem;
  padding: 0 0.3rem;
  line-height: 1.15;
}
.score-cell + .score-cell { border-left: 1px solid #d6cdf0; }
.score-label { font-size: 0.68rem; color: #6a5a9a; }
.score-value { font-size: 1.1rem; font-weight: 700; }
.score-bar { display: block; width: 100%; height: 0.25rem; margin-top: 0.1rem; background: #e3dcf6; border-radius: 0.15rem; overflow: hidden; }
.score-bar[hidden] { display: none; }
.score-bar i { display: block; height: 100%; background: #7c5cd6; border-radius: 0.15rem; }
.score-elegance .score-bar i { background: #1d9a6c; }
.score-efficiency .score-bar i { background: #e08a00; }
.score-cell.score-none .score-value { font-size: 0.78rem; font-weight: 500; color: #8a7fb0; }
.score-blocks .score-value { color: #3b2a6b; }

/* "+0.1 elegance" floats up from the card when building has made a number go up. */
.score-gain {
  position: absolute;
  right: 0.6rem;
  bottom: 100%;
  white-space: pre;
  font-weight: 700;
  color: #1d7a3a;
  text-shadow: 0 0 3px #fff, 0 0 3px #fff, 0 0 3px #fff;
  pointer-events: none;
}
.score-gain[hidden] { display: none; }
.score-gain.score-gain-go { animation: score-gain-float 1.8s ease-out forwards; }

@keyframes score-gain-float {
  0% { transform: translateY(0.4rem) scale(0.8); opacity: 0; }
  15% { transform: translateY(-0.2rem) scale(1.15); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translateY(-1.6rem) scale(1); opacity: 0; }
}

.score-panel {
  position: absolute;
  right: 0;
  bottom: calc(100% + 0.45rem);
  width: min(23rem, 80vw);
  max-height: 72vh;
  overflow-y: auto;
  box-sizing: border-box;
  padding: 0.7rem 0.9rem 0.8rem;
  color: #1b1f23;
  background: rgba(255, 255, 255, 0.98);
  border: 1px solid #b8c2cc;
  border-radius: 0.5rem;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
.score-panel[hidden] { display: none; }
.score-panel p { margin: 0; }
.score-head { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 0.2rem; }
.score-big { font-size: 1.6rem; line-height: 1.1; color: #5b3fb5; }
.score-level { font-weight: 700; color: #3b2a6b; }

.score-cols { display: grid; grid-template-columns: 1fr; gap: 0 1.2rem; }
.score-section { margin-top: 0.7rem; padding-top: 0.6rem; border-top: 1px solid #e0e4ea; }
/* On a wide window: complexity on the left, elegance and efficiency on the right, so the reasons for all three show without scrolling. */
@media (min-width: 820px) {
  .score-panel { width: min(45rem, 72vw); }
  .score-cols { grid-template-columns: 1fr 1fr; }
  .score-col:first-child .score-section:first-child,
  .score-col:last-child .score-section:first-child { margin-top: 0.3rem; padding-top: 0.3rem; border-top: 0; }
}
.score-title { display: flex; align-items: baseline; gap: 0.5rem; margin: 0; font-size: 1rem; }
.score-title-name { font-weight: 700; }
.score-title-value { font-size: 1.15rem; font-weight: 700; color: #5b3fb5; font-variant-numeric: tabular-nums; }
.score-section-elegance .score-title-value { color: #167a55; }
.score-section-efficiency .score-title-value { color: #b86e00; }
.score-meter { height: 0.4rem; margin: 0.25rem 0 0.35rem; background: #ece8f7; border-radius: 0.25rem; overflow: hidden; }
.score-meter i { display: block; height: 100%; background: #7c5cd6; border-radius: 0.25rem; }
.score-section-elegance .score-meter i { background: #1d9a6c; }
.score-section-efficiency .score-meter i { background: #e08a00; }
.score-what { font-size: 0.82rem; color: #555; }
.score-next { margin-top: 0.35rem; font-size: 0.85rem; color: #444; }

.score-scale { margin-top: 0.2rem; font-size: 0.78rem; color: #666; }
.score-table { width: 100%; margin: 0.35rem 0; border-collapse: collapse; }
.score-table td { padding: 0.16rem 0; border-top: 1px solid #e6e9ee; vertical-align: top; }
.score-colhead { padding: 0.1rem 0; font-size: 0.72rem; font-weight: 600; text-align: left; color: #777; }
.score-colhead.score-colnum { text-align: right; }
.score-count { width: 3rem; padding-right: 0.7rem; text-align: right; font-variant-numeric: tabular-nums; }
.score-zero .score-count { color: #999; }
.score-table tfoot td { border-top: 2px solid #cfd5dc; font-weight: 700; }
.score-table tfoot .score-points { color: #1b1f23; }
.score-part-name { display: block; }
.score-part-detail { display: block; font-size: 0.78rem; color: #666; }
.score-points { width: 3.2rem; text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; color: #1d7a3a; }
.score-zero .score-part-name { color: #777; }
.score-zero .score-points { color: #999; font-weight: 400; }

.score-reasons { margin: 0.4rem 0 0; padding: 0; list-style: none; }
.score-reason { position: relative; margin-top: 0.25rem; padding: 0.3rem 0.5rem 0.3rem 1.5rem; border-radius: 0.35rem; font-size: 0.88rem; }
.score-reason::before { position: absolute; left: 0.5rem; top: 0.3rem; font-weight: 700; }
.score-reason.score-good { background: #eef7e8; }
.score-reason.score-good::before { content: '\2713'; color: #1d7a3a; }
.score-reason.score-tip { background: #fff4df; }
.score-reason.score-tip::before { content: '\2192'; color: #b86e00; }
.score-tip.score-reason { color: #1b1f23; }
.score-section-complexity > .score-tip { margin-top: 0.4rem; padding: 0.45rem 0.6rem; background: #eef7e8; border-radius: 0.4rem; font-size: 0.9rem; }
.score-fine { margin-top: 0.7rem; font-size: 0.75rem; color: #666; }

.stage.blocks-hidden .score-badge { display: none; }

@media (prefers-reduced-motion: reduce) {
  .score-gain.score-gain-go { animation: score-gain-fade 1.8s linear forwards; }
  @keyframes score-gain-fade { 0% { opacity: 0; } 10% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }
}

/* ---- Help bubble ---- */

.bubble {
  position: absolute;
  z-index: 7;
  max-width: 16rem;
  padding: 0.6rem 0.8rem;
  border-radius: 0.7rem;
  background: #fffbe6;
  border: 2px solid #b98900;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  color: #1b1f23;
}

.bubble[hidden] { display: none; }

.bubble p {
  margin: 0;
  line-height: 1.35;
}

.bubble button {
  margin-top: 0.5rem;
  min-height: 2.25rem;
  padding: 0 0.9rem;
  font: inherit;
  border: 0;
  border-radius: 0.4rem;
  background: #4da6ff;
  color: #fff;
  cursor: pointer;
}

.bubble button[hidden] { display: none; }

/* ---- Boxes readout ---- */

.boxes-readout {
  position: absolute;
  right: 22rem; /* to the left of the badge (blocks, complexity, elegance, efficiency), which has the corner */
  bottom: 0.75rem;
  z-index: 4;
  margin: 0;
  padding: 0.3rem 0.9rem;
  border: 2px solid #daaf30;
  border-radius: 1rem;
  background: rgba(255, 251, 230, 0.95);
  font-variant-numeric: tabular-nums;
  white-space: pre;
  pointer-events: none;
}

.boxes-readout[hidden] { display: none; }

/* The Python box: small on purpose, it is for reading beside the blocks. */
.python-box {
  position: absolute;
  right: 0.75rem;
  bottom: 3.6rem; /* above the boxes readout */
  z-index: 4;
  display: flex;
  flex-direction: column;
  width: min(27rem, 46vw);
  max-height: 55%;
  background: rgba(255, 255, 255, 0.97);
  border: 1px solid #b8c2cc;
  border-radius: 0.5rem;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
}

.python-box[hidden] { display: none; }

.python-box header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.25rem 0.5rem;
  background: #e9f1f9;
  border-bottom: 1px solid #b8c2cc;
  border-radius: 0.5rem 0.5rem 0 0;
  font-size: 0.8rem;
}

.python-copy {
  padding: 0.1rem 0.6rem;
  font: inherit;
  border: 1px solid #8aa3bb;
  border-radius: 0.3rem;
  background: #fff;
  cursor: pointer;
}

.python-code {
  margin: 0;
  padding: 0.4rem 0.6rem;
  overflow: auto;
  touch-action: pan-x pan-y; /* the page around it does not scroll, but this does */
  user-select: text;
  -webkit-user-select: text;
  font: 11px/1.45 ui-monospace, Menlo, Consolas, monospace;
  color: #1b1f23;
  tab-size: 4;
}

/* The Logo box: you can type in it, so it is bigger than the Python box. */
.logo-box {
  position: absolute;
  right: 0.75rem;
  bottom: 3.6rem;
  z-index: 4;
  display: flex;
  flex-direction: column;
  width: min(30rem, 52vw);
  max-height: 62%;
  background: rgba(255, 255, 255, 0.97);
  border: 1px solid #b8c2cc;
  border-radius: 0.5rem;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.25);
}

.logo-box[hidden] { display: none; }

.logo-box header {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 0.6rem;
  padding: 0.25rem 2rem 0.25rem 0.5rem; /* room on the right for the X */
  background: #e9f1f9;
  border-bottom: 1px solid #b8c2cc;
  border-radius: 0.5rem 0.5rem 0 0;
  font-size: 0.8rem;
}

/* The X in the top right corner of the box. */
.logo-box .logo-close {
  position: absolute;
  top: 0.2rem;
  right: 0.3rem;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  font: 700 1.2rem/1 sans-serif;
  color: #3d4a57;
  background: transparent;
  border: 0;
  border-radius: 0.3rem;
  cursor: pointer;
}

.logo-box .logo-close:hover,
.logo-box .logo-close:focus-visible { background: rgba(0, 0, 0, 0.12); }

.logo-short { display: flex; align-items: center; gap: 0.2rem; cursor: pointer; }
.logo-actions { display: flex; gap: 0.3rem; margin-left: auto; }

.logo-actions button {
  padding: 0.1rem 0.6rem;
  font: inherit;
  border: 1px solid #8aa3bb;
  border-radius: 0.3rem;
  background: #fff;
  cursor: pointer;
}

.logo-actions .logo-run { background: #2b8a3e; border-color: #1f6b2e; color: #fff; font-weight: 700; }

.logo-code {
  box-sizing: border-box;
  width: 100%;
  min-height: 10rem;
  flex: 1;
  margin: 0;
  padding: 0.4rem 0.6rem;
  border: 0;
  resize: none;
  font: 12px/1.45 ui-monospace, Menlo, Consolas, monospace;
  color: #1b1f23;
  tab-size: 2;
  white-space: pre;
  overflow: auto;
  user-select: text;
  -webkit-user-select: text;
}

.logo-status {
  margin: 0;
  padding: 0.25rem 0.6rem;
  border-top: 1px solid #d8dee4;
  font-size: 0.75rem;
  color: #4b5560;
}

.logo-status.problem { color: #a40e26; font-weight: 700; }

/* ---- Print output ---- */

.output {
  position: absolute;
  right: 0.75rem;
  top: 0.75rem;
  z-index: 4;
  max-width: 16rem;
  margin: 0;
  padding: 0.4rem 0.9rem;
  border: 2px solid #ff2c76;
  border-radius: 0.7rem;
  background: rgba(255, 255, 255, 0.95);
  font-variant-numeric: tabular-nums;
  white-space: pre;
  overflow: hidden;
  pointer-events: none;
}

.output::before {
  content: 'Output';
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  color: #ff2c76;
}

.output[hidden] { display: none; }

/* ---- Dropping a saved picture on the page ---- */

.stage.drop-target {
  outline: 4px dashed #ff2c76;
  outline-offset: -10px;
}

/* ---- Sticky notes ---- */

.note-input {
  position: absolute;
  z-index: 6;
  padding: 10px 12px;
  font: 14px/18px Roboto, system-ui, sans-serif;
  color: #4a4100;
  background: #fff8c4;
  border: 2px solid #c9b037;
  border-radius: 4px;
  resize: none;
}

/* ---- The list of ways to save (right-click Save) ---- */

.export-menu {
  position: fixed;
  z-index: 30;
  display: flex;
  flex-direction: column;
  width: min(22rem, calc(100vw - 16px));
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  padding: 0.3rem;
  border-radius: 0.6rem;
  background: #fff;
  color: #222;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35);
}

.export-menu[hidden] { display: none; }

.export-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  padding: 0.45rem 0.6rem;
  border: 0;
  border-radius: 0.4rem;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.export-item:hover,
.export-item:focus-visible {
  background: #e6f2ff;
  outline: none;
}

.export-label { font-weight: 700; }
.export-hint { font-size: 0.85rem; color: #555; }

/* The grid button's menu has headings over its groups, and a check mark on the line that is chosen. */
.export-heading {
  padding: 0.5rem 0.6rem 0.15rem;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #4a6a8a;
}
.export-heading:not(:first-child) { margin-top: 0.2rem; border-top: 1px solid #dde5ee; }
.export-radio { position: relative; padding-left: 1.9rem; }
.export-radio[aria-checked="true"]::before {
  content: '\2713';
  position: absolute;
  left: 0.6rem;
  top: 0.4rem;
  font-weight: 700;
  color: #1a6fc4;
}
.export-radio[aria-checked="true"] .export-label { color: #14558f; }

/* ---- The list of fonts that opens from a write block ---- */

.font-menu {
  position: absolute;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 4px;
  background: #fff;
  border: 1px solid #8a8a8a;
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  touch-action: manipulation;
}

/* The list of keys that opens from a when [key] pressed block: the named keys wide, the letters and digits small, wrapping. */
.key-menu {
  position: absolute;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  width: 17.5rem;
  max-width: calc(100% - 8px);
  box-sizing: border-box;
  padding: 6px;
  background: #fff;
  border: 1px solid #8a8a8a;
  border-radius: 8px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  touch-action: manipulation;
}

.key-option {
  flex: 0 0 auto;
  min-width: 2rem;
  height: 2rem;
  padding: 0 0.4rem;
  border: 1px solid #c9c9c9;
  border-radius: 6px;
  background: #fafafa;
  color: #222;
  font: inherit;
  text-align: center;
  cursor: pointer;
}

.key-option.key-named {
  padding: 0 0.6rem;
}

.key-option:hover,
.key-option:focus-visible {
  background: #e3efff;
  outline: none;
}

.key-option[aria-selected='true'] {
  background: #cfe3ff;
  font-weight: 700;
}

/* The color picker that opens from the color box on a set color or fill screen block (js/ui/color-picker.js). */
.color-picker {
  position: absolute;
  z-index: 30;
  width: 26rem;
  max-width: calc(100% - 8px);
  box-sizing: border-box;
  padding: 0.65rem 0.75rem 0.7rem;
  color: #1b1f23;
  background: #fff;
  border: 1px solid #8a8a8a;
  border-radius: 0.6rem;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  font-size: 0.9rem;
  touch-action: manipulation;
}

.cp-top { display: flex; align-items: center; gap: 0.65rem; margin-bottom: 0.55rem; }
.cp-native { width: 3.2rem; height: 2.5rem; padding: 0; border: 2px solid #8a8a8a; border-radius: 0.4rem; background: none; cursor: pointer; }
.cp-hex-label { display: flex; align-items: center; gap: 0.45rem; font-weight: 600; }

.cp-hex,
.cp-number,
.cp-chex,
.cp-bin {
  box-sizing: border-box;
  min-height: 2.1rem;
  padding: 0.15rem 0.3rem;
  font: 600 0.95rem ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  text-align: center;
  color: #1b1f23;
  background: #fff;
  border: 1px solid #aab4be;
  border-radius: 0.35rem;
}
.cp-hex { width: 7.6rem; font-size: 1.05rem; letter-spacing: 0.04em; text-transform: uppercase; }
.cp-chex { text-transform: uppercase; }
.cp-hex:focus-visible,
.cp-number:focus-visible,
.cp-chex:focus-visible,
.cp-bin:focus-visible,
.cp-slider:focus-visible,
.cp-native:focus-visible,
.cp-done:focus-visible { outline: 3px solid #3a7bd5; outline-offset: 1px; }

/* The number box would hide its digits behind little arrows; the slider and the keyboard do that job. */
.cp-number { -moz-appearance: textfield; appearance: textfield; }
.cp-number::-webkit-outer-spin-button,
.cp-number::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.cp-heads,
.cp-row { display: grid; grid-template-columns: 3rem 1fr 3.2rem 2.7rem 6.6rem; gap: 0.35rem; align-items: center; }
.cp-heads span { font-size: 0.7rem; text-align: center; color: #666; }
.cp-row { margin: 0.25rem 0; }
.cp-name { font-weight: 700; }
.cp-red .cp-name { color: #c62828; }
.cp-green .cp-name { color: #2e7d32; }
.cp-blue .cp-name { color: #1565c0; }
.cp-slider { width: 100%; min-width: 0; margin: 0; }
.cp-red .cp-slider { accent-color: #e53935; }
.cp-green .cp-slider { accent-color: #43a047; }
.cp-blue .cp-slider { accent-color: #1e88e5; }

.cp-bits { margin: 0.55rem 0 0.15rem; font: 0.8rem ui-monospace, 'SF Mono', Menlo, Consolas, monospace; color: #333; }
.cp-note { margin: 0.2rem 0 0.55rem; font-size: 0.78rem; color: #666; }
.cp-done {
  min-height: 2.25rem;
  padding: 0 1rem;
  font: inherit;
  color: #fff;
  background: #4da6ff;
  border: 0;
  border-radius: 0.4rem;
  cursor: pointer;
}

.font-option {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  min-height: 2.5rem;
  padding: 0.1rem 0.6rem;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: #222;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.font-option:hover,
.font-option:focus-visible {
  background: #e3efff;
  outline: none;
}

.font-option[aria-selected='true'] {
  background: #cfe3ff;
  font-weight: 700;
}

.font-name {
  min-width: 4.2rem;
}

.font-preview {
  display: block;
}
