/* =========================================================
   Drone Lab — "Saturday-Morning Notebook" aesthetic
   ---------------------------------------------------------
   Warm paper, deep ink-navy, hand-drawn accents.
   Fraunces (display) + Lexend (body, kid-readable) + Caveat
   (handwritten asides). Custom Blockly theme is wired in
   theme.js — these styles handle the page chrome.
   ========================================================= */

:root {
  --paper:        #FBF3E0;
  --paper-deep:   #F2E7CC;
  --ink:          #1A2A40;
  --ink-soft:     #4A5870;
  --ink-faint:    #8C95A6;

  --flight:       #E76F51;   /* persimmon — movement blocks */
  --flight-soft:  #F3A487;
  --sensor:       #7FA877;   /* sage — sensor blocks */
  --logic:        #E9B44C;   /* marigold — logic blocks */
  --expression:   #C9486A;   /* rose — LED/sound blocks */

  --sky-1:        #DCE9F1;
  --sky-2:        #F1E2D0;
  --sky-3:        #BFD3E0;

  --go:           #2E7D5B;
  --go-hot:       #46A37A;
  --stop:         #D04543;
  --stop-hot:     #E76664;

  --shadow-paper: 0 2px 0 rgba(26,42,64,0.06),
                  0 14px 32px -18px rgba(26,42,64,0.35),
                  0 2px 4px rgba(26,42,64,0.05);

  --radius-card:  22px;
  --radius-tab:   14px;
  --radius-pill:  999px;

  --font-display: 'Fraunces', Georgia, serif;
  --font-body:    'Lexend', system-ui, -apple-system, sans-serif;
  --font-hand:    'Caveat', cursive;
}

/* -----------------------------------------------------------
   Base
   ----------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 380;
  color: var(--ink);
  background:
    radial-gradient(ellipse 80% 60% at 12% 8%, rgba(240,169,59,0.10), transparent 60%),
    radial-gradient(ellipse 60% 50% at 92% 88%, rgba(201,72,106,0.07), transparent 60%),
    radial-gradient(ellipse 50% 40% at 80% 10%, rgba(127,168,119,0.08), transparent 60%),
    var(--paper);
  background-attachment: fixed;
  overflow-x: hidden;
  min-height: 100vh;
}

/* paper grain — generated SVG, very subtle */
.grain {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  opacity: 0.32;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='240' height='240'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.10  0 0 0 0 0.16  0 0 0 0 0.25  0 0 0 0.10 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* -----------------------------------------------------------
   Background scribbles (decorative, very faint)
   ----------------------------------------------------------- */

.scribble {
  position: fixed;
  pointer-events: none;
  z-index: 0;
  color: var(--ink);
  opacity: 0.08;
}
.scribble--sun    { top: 56px;  right: 64px;  width: 110px; transform: rotate(-12deg); }
.scribble--cloud  { bottom: 90px; left: 40px;  width: 180px; transform: rotate(-6deg); }
.scribble--arrow  { top: 48%; left: 31%; width: 140px; transform: rotate(8deg); opacity: 0.10; }

/* -----------------------------------------------------------
   Masthead
   ----------------------------------------------------------- */

.masthead {
  position: relative;
  z-index: 4;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding: 32px 40px 14px;
  flex-wrap: wrap;
}

.masthead__title {
  display: flex;
  align-items: baseline;
  gap: 14px;
}

.masthead__icon {
  width: 48px;
  height: 48px;
  color: var(--ink);
  align-self: center;
  transform: rotate(-6deg);
  transition: transform 600ms cubic-bezier(.2,.7,.3,1.2);
}
.masthead__icon:hover { transform: rotate(8deg) translateY(-2px); }

.masthead h1 {
  font-family: var(--font-display);
  font-weight: 580;
  font-size: clamp(34px, 4vw, 52px);
  letter-spacing: -0.02em;
  line-height: 0.95;
  margin: 0;
  font-variation-settings: "opsz" 144, "SOFT" 60;
}

.masthead__tag {
  font-family: var(--font-hand);
  font-size: 26px;
  color: var(--flight);
  transform: rotate(-3deg) translateY(-4px);
  display: inline-block;
  margin-left: 4px;
}

/* -----------------------------------------------------------
   Mode toggle (sim / real)
   ----------------------------------------------------------- */

.masthead__controls {
  display: flex;
  align-items: center;
  gap: 14px;
}

.mode-toggle {
  position: relative;
  display: inline-flex;
  background: var(--paper-deep);
  border: 2px solid var(--ink);
  border-radius: var(--radius-pill);
  padding: 4px;
  box-shadow: var(--shadow-paper);
}
.mode-toggle__btn {
  font: inherit;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  background: transparent;
  border: 0;
  padding: 8px 16px 8px 14px;
  border-radius: var(--radius-pill);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  transition: color 200ms, background 200ms;
}
.mode-toggle__btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}
.mode-toggle__btn.is-active {
  background: var(--ink);
  color: var(--paper);
}
.mode-toggle__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.6;
}
.mode-toggle__btn.is-active .mode-toggle__dot {
  background: var(--go-hot);
  opacity: 1;
  box-shadow: 0 0 0 3px rgba(70,163,122,0.25);
}

/* -----------------------------------------------------------
   Buttons — chunky, candy-bar shaped, with offset shadow
   ----------------------------------------------------------- */

.btn {
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0.02em;
  font-size: 16px;
  border: 2px solid var(--ink);
  border-radius: 18px;
  padding: 10px 20px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  background: var(--paper);
  color: var(--ink);
  position: relative;
  box-shadow: 0 4px 0 var(--ink);
  transition: transform 120ms ease, box-shadow 120ms ease, background 200ms;
}
.btn svg { width: 18px; height: 18px; }
.btn:hover    { transform: translateY(-1px); box-shadow: 0 5px 0 var(--ink); }
.btn:active   { transform: translateY(3px);  box-shadow: 0 1px 0 var(--ink); }

.btn--go {
  background: var(--go);
  color: var(--paper);
}
.btn--go:hover { background: var(--go-hot); }

/* "fly!" button flips to "reset" after a pretend flight completes */
.btn--go.btn--reset { background: var(--logic); color: var(--ink); }
.btn--go.btn--reset:hover { background: #F1CF87; }

.btn--stop {
  background: var(--stop);
  color: var(--paper);
}
.btn--stop:hover { background: var(--stop-hot); }
.btn--stop svg rect { fill: var(--paper); }

.btn[disabled] {
  opacity: 0.42;
  cursor: not-allowed;
  background: var(--paper-deep);
  color: var(--ink-soft);
  box-shadow: 0 2px 0 rgba(26,42,64,0.4);
}
.btn[disabled]:hover {
  transform: none;
  box-shadow: 0 2px 0 rgba(26,42,64,0.4);
  background: var(--paper-deep);
}
.btn--stop[disabled] svg rect { fill: var(--ink-soft); }

/* small action button anchored to the top-right of a card */
.card__action {
  position: absolute;
  top: -14px;
  right: 22px;
  z-index: 3;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.01em;
  color: var(--ink-soft);
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 14px;
  padding: 5px 12px 5px 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--ink);
  transform: rotate(1.6deg);
  transition: transform 120ms ease, box-shadow 120ms ease, background 200ms, color 200ms;
}
.card__action svg { width: 14px; height: 14px; }
.card__action:hover {
  transform: rotate(1.6deg) translateY(-1px);
  box-shadow: 0 4px 0 var(--ink);
  background: #FBE9CF;
  color: var(--stop);
}
.card__action:active {
  transform: rotate(1.6deg) translateY(2px);
  box-shadow: 0 1px 0 var(--ink);
}

/* undo sits to the left of start-over, counter-rotated, and its hover
   stays ink (undo isn't destructive — no red) */
.card__action--undo {
  right: 138px;
  transform: rotate(-1.4deg);
}
.card__action--undo:hover {
  transform: rotate(-1.4deg) translateY(-1px);
  color: var(--ink);
}
.card__action--undo:active {
  transform: rotate(-1.4deg) translateY(2px);
}

/* -----------------------------------------------------------
   Main stage — three panels
   ----------------------------------------------------------- */

.stage {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 220px 1fr 1fr;
  grid-template-rows: minmax(460px, calc(100vh - 280px));
  gap: 22px;
  padding: 14px 40px 18px;
}

@media (max-width: 1180px) {
  .stage {
    grid-template-columns: 180px 1fr 1fr;
    grid-template-rows: minmax(420px, calc(100vh - 280px));
    gap: 16px;
    padding: 14px 24px 18px;
  }
}
@media (max-width: 860px) {
  /* Phone / narrow tablet — keep the three cards in ONE row and let the
     user swipe between them horizontally. Stacking them vertically meant
     the kid had to scroll past the blocks to see the canvas, which
     killed the "write code → watch it fly" loop. Landscape just fits
     more on screen with the same layout. */
  .stage {
    display: flex;
    flex-direction: row;
    /* Override the grid track defs from the base/1180px rules. */
    grid-template-columns: none;
    grid-template-rows: none;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior-x: contain;
    gap: 14px;
    padding: 12px 16px 16px;
    /* Definite height so children with height:100% don't collapse. */
    height: calc(100dvh - 200px);
    min-height: 380px;
    max-height: 760px;
  }
  .stage > .card {
    flex: 0 0 auto;
    scroll-snap-align: start;
    /* One card fills the portrait viewport with a small peek of the
       next card (signals scrollability). Two cards fit comfortably in
       landscape. */
    width: min(440px, 88vw);
    height: 100%;
    min-height: 0;
  }
  .stage > .card--palette {
    width: min(220px, 62vw);
  }
}

/* -----------------------------------------------------------
   Card (panel) — paper-on-paper with a torn tab
   ----------------------------------------------------------- */

.card {
  position: relative;
  background: #FFFBEE;
  border: 2px solid var(--ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-paper);
  padding: 38px 18px 18px;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.card--palette { transform: rotate(-0.6deg); padding: 38px 14px 14px; background: #FAF3DD; }
.card--blocks  { transform: rotate(-0.2deg); }
.card--sim     { transform: rotate(0.3deg); }

.card__tab {
  position: absolute;
  top: -16px;
  left: 22px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: var(--radius-tab);
  padding: 6px 16px 6px 8px;
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 0.02em;
  box-shadow: 0 3px 0 var(--ink);
  transform: rotate(-2deg);
}
.card--sim    .card__tab { left: 28px; transform: rotate(1.5deg); }
.card--code   .card__tab { left: 24px; transform: rotate(-1deg); }

.card__tab-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  background: var(--ink);
  color: var(--paper);
}
/* ---- Sim card caption + level tabs ------------------------------------ */

.sim-caption {
  position: absolute;
  top: 4px;                /* roughly horizontal with the "watch it fly" tab */
  left: 210px;             /* sits just to the right of the tab */
  right: 56px;             /* don't run under the level tabs */
  z-index: 2;
  margin: 0;
  font-family: var(--font-hand);
  font-size: 19px;
  line-height: 1.1;
  color: var(--ink);
  opacity: 0.85;
  pointer-events: none;
  text-align: left;
  transform: rotate(-0.8deg);
}

.level-tabs {
  position: absolute;
  top: 28px;
  bottom: 22px;
  right: -14px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.level-tab {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.02em;
  width: 36px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  color: var(--ink-soft);
  border: 2px solid var(--ink);
  border-radius: 0 12px 12px 0;
  border-left: 0;
  cursor: pointer;
  box-shadow: 2px 3px 0 rgba(26,42,64,0.4);
  transition: transform 120ms ease, background 200ms, color 200ms;
}
.level-tab:nth-child(odd)  { transform: rotate(1.5deg); }
.level-tab:nth-child(even) { transform: rotate(-1.2deg); }
.level-tab:hover { background: #FBE9CF; color: var(--ink); }
.level-tab.is-active {
  background: var(--ink);
  color: var(--paper);
}

/* Chapter tabs — always visible at the top of the column; selecting one
   shows that chapter's levels below (labelled 2.1, 2.2, …). Sage-tinted
   and squatter so they read as a different "kind" than the level tabs. */
.chapter-tab {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
  width: 44px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #E8EFE3;
  color: var(--ink-soft);
  border: 2px solid var(--ink);
  border-radius: 0 10px 10px 0;
  border-left: 0;
  cursor: pointer;
  box-shadow: 2px 3px 0 rgba(26,42,64,0.4);
  transition: transform 120ms ease, background 200ms, color 200ms;
}
.chapter-tab:nth-child(odd)  { transform: rotate(-1.3deg); }
.chapter-tab:nth-child(even) { transform: rotate(1.4deg); }
.chapter-tab:hover { background: #D7E4CF; color: var(--ink); }
.chapter-tab.is-active {
  background: var(--sensor);
  color: var(--paper);
}
/* accordion spacing: the expanded chapter's level tabs sit directly under
   their chapter tab, nudged right so they read as nested; the next
   chapter tab gets breathing room after the expanded list */
.level-tab:not(.level-tab--sandbox) { margin-left: 7px; }
.level-tab + .chapter-tab { margin-top: 10px; }

/* solved star — a marigold star pinned to the tab's top corner once the
   level is beaten (chapter tabs get one when ALL their levels are).
   Tabs need position for the pseudo-element to anchor to. */
.level-tab, .chapter-tab { position: relative; }
.level-tab.is-solved::after,
.chapter-tab.is-solved::after {
  content: '★';
  position: absolute;
  top: -15px;
  right: -6px;
  font-size: 23px;
  line-height: 1;
  color: var(--logic);
  text-shadow: 0 1px 0 rgba(26,42,64,0.6);
  transform: rotate(14deg);
}

/* "start fresh" — the one destructive control, parked just below the
   grown-ups drawer, right-aligned with its edge. Quiet dashed chip until
   hovered; asks for confirmation on click. */
.page-reset {
  display: block;
  margin: 0 40px 18px auto;   /* 40px matches the drawer's side margin */
  padding: 5px 12px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  background: none;
  border: 1.5px dashed rgba(26,42,64,0.3);
  border-radius: 10px;
  cursor: pointer;
  transition: color 160ms, border-color 160ms;
}
.page-reset:hover {
  color: var(--stop);
  border-color: var(--stop);
}

/* Sandbox tab — anchored to the bottom of the tab column (via
   margin-top:auto in the flex container) and marigold-tinted so it
   reads as "free play, not a challenge". */
.level-tab--sandbox {
  margin-top: auto;
  background: var(--logic);
  color: var(--ink);
  font-size: 18px;
}
.level-tab--sandbox:hover    { background: #F1CF87; }
.level-tab--sandbox.is-active {
  background: var(--ink);
  color: var(--logic);
}

.card--palette .card__tab-num { background: var(--logic); color: var(--ink); }
.card--blocks  .card__tab-num { background: var(--flight); }
.card--sim     .card__tab-num { background: var(--sensor); }
.card--palette .card__tab { left: 18px; transform: rotate(-2.5deg); }

.card__tab-label {
  font-family: var(--font-hand);
  font-size: 22px;
  line-height: 1;
  color: var(--ink);
}

/* -----------------------------------------------------------
   Blockly host
   ----------------------------------------------------------- */

.blockly-host {
  flex: 1;
  min-height: 0;
  border-radius: 14px;
  overflow: hidden;
  position: relative;
  border: 1.5px dashed rgba(26,42,64,0.25);
}

/* empty-state hint sitting in the workspace area; hidden once a block exists */
.workspace-hint {
  position: absolute;
  z-index: 1;
  pointer-events: none;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  width: min(70%, 240px);
  text-align: center;
  color: var(--ink-soft);
  opacity: 1;
  transition: opacity 220ms ease;
}
.workspace-hint__arrow {
  width: 110px;
  color: var(--flight);
  transform: rotate(-6deg) scaleX(-1);  /* point leftward toward the palette */
  margin: 0 auto 4px;
  display: block;
}
.workspace-hint__text {
  margin: 0;
  font-family: var(--font-hand);
  font-size: 22px;
  line-height: 1.05;
  color: var(--ink);
  transform: rotate(-1.5deg);
}
.workspace-hint__sub {
  margin: 8px 0 0;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.3;
  color: var(--ink-soft);
}
.blockly-host.has-blocks .workspace-hint { opacity: 0; }

/* Soft marigold glow on the "active" block — the anchor for the next click-insert */
.drone-active { filter: drop-shadow(0 0 8px rgba(240,169,59,0.85)); }

/* Peacock-teal halo on the block currently being executed during a
   pretend-mode flight. The glow is rendered on a CLONE of the block's
   SVG that lives at the end of the workspace canvas (see
   ensureHighlightOverlay in app.js), so the halo always sits on top
   of every other block — Blockly's DOM nesting would otherwise let
   later blocks in the chain clip the lower half of the glow. */
.drone-running-overlay { pointer-events: none; }
.drone-running-clone {
  filter: drop-shadow(0 0 6px rgba(31, 122, 122, 0.95))
          drop-shadow(0 0 14px rgba(31, 122, 122, 0.7));
}
/* When the flight ends in a failure, the block that was executing keeps
   its glow — switched to red, so "which block did it" is part of the
   feedback. Persists like the stamp; cleared on reset (endRunVisuals). */
.drone-running-overlay.is-culprit .drone-running-clone {
  filter: drop-shadow(0 0 6px rgba(208, 69, 67, 0.95))
          drop-shadow(0 0 14px rgba(208, 69, 67, 0.7));
}

/* ============================================================
   End-of-flight feedback "stamp"
   A hand-stamped note that thunks onto the canvas when a program
   finishes. Same physical language for both states (cream card,
   hard ink offset, slight rotation, overshoot entry) so repeated
   failures don't feel jarring — but WIN bursts with drawn sparkles
   and LOSE just shakes its head once. Built in app.js.
   ============================================================ */
.sim__feedback {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 8;
  pointer-events: none;   /* taps fall through to the canvas (pan + dismiss) */
}
.sim__feedback[data-state="win"],
.sim__feedback[data-state="lose"] { display: flex; }

.feedback-card {
  position: relative;
  min-width: 170px;
  max-width: 72%;
  padding: 17px 26px 15px;
  background: var(--paper);
  border: 2.5px solid var(--ink);
  border-radius: 18px;
  box-shadow: 0 5px 0 var(--ink);
  text-align: center;
  transform: rotate(-2deg);
  animation: feedback-thunk 380ms cubic-bezier(.34, 1.56, .64, 1) both;
}
/* accent hairline along the top of the card */
.feedback-card::before {
  content: "";
  position: absolute;
  left: 16px; right: 16px; top: 7px;
  height: 3px;
  border-radius: 3px;
  background: var(--feedback-accent, var(--logic));
}
/* lose: settle in, then shake the head twice */
.sim__feedback[data-state="lose"] .feedback-card {
  animation: feedback-thunk 380ms cubic-bezier(.34, 1.56, .64, 1) both,
             feedback-shake 190ms ease-in-out 380ms 2;
}

.feedback-card__title {
  font-family: var(--font-display);
  font-size: 27px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.05;
  margin: 2px 0 0;
}
.feedback-card__msg {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink);
  line-height: 1.25;
  margin: 6px 0 0;
}
.feedback-card__flourish {
  font-family: var(--font-hand);
  font-size: 19px;
  color: var(--feedback-accent, var(--logic));
  margin: 3px 0 0;
}

@keyframes feedback-thunk {
  0%   { transform: rotate(-2deg) scale(.7);  opacity: 0; }
  60%  { transform: rotate(-2deg) scale(1.04); opacity: 1; }
  100% { transform: rotate(-2deg) scale(1);   opacity: 1; }
}
@keyframes feedback-shake {
  0%, 100% { transform: rotate(-2deg); }
  25%      { transform: rotate(-5deg); }
  75%      { transform: rotate(1deg); }
}
.sim__feedback.is-leaving .feedback-card {
  animation: feedback-leave 280ms ease forwards;
}
@keyframes feedback-leave {
  to { transform: rotate(-2deg) translateY(-7px) scale(.96); opacity: 0; }
}

/* drawn sparkle particles (win only) — spawned from card centre */
.feedback-spark {
  position: absolute;
  left: 50%; top: 50%;
  width: var(--size, 14px);
  height: var(--size, 14px);
  margin-left: calc(var(--size, 14px) / -2);
  margin-top:  calc(var(--size, 14px) / -2);
  color: var(--spark-color, var(--logic));
  pointer-events: none;
  animation: feedback-spark-fly var(--dur, 700ms) ease-out var(--delay, 0ms) both;
}
.feedback-spark svg { width: 100%; height: 100%; display: block; }
@keyframes feedback-spark-fly {
  0%   { transform: translate(0, 0) scale(0) rotate(0deg); opacity: 0; }
  20%  { opacity: 1; }
  100% { transform: translate(var(--dx), var(--dy)) scale(1) rotate(var(--rot)); opacity: 0; }
}

/* Chunky, clearly-visible workspace scrollbars — the thin faint default
   is invisible to a kid. Only shown when the blocks overflow (the
   scroll-lock in app.js hides the container otherwise). */
.blocklyScrollbarHandle {
  fill: var(--flight) !important;   /* persimmon, matches the blocks */
  rx: 6px; ry: 6px;
}
.blocklyScrollbarVertical .blocklyScrollbarHandle,
.blocklyScrollbarHorizontal .blocklyScrollbarHandle {
  opacity: 0.7;
}

/* Floating per-block action toolbar (↑ ↓ ✕). Anchored to the active
   block in JS — see positionToolbar() in app.js. */
.block-toolbar {
  position: absolute;
  display: none;
  flex-direction: row;
  gap: 6px;
  z-index: 6;
  pointer-events: none;
}
.block-toolbar.is-visible { display: flex; pointer-events: auto; }
.block-tool {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: #FFFBEE;
  border: 2px solid var(--ink);
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 700;
  color: var(--ink);
  box-shadow: 0 2px 0 var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: transform 100ms ease, box-shadow 100ms ease, opacity 100ms ease;
}
.block-tool:hover  { transform: translateY(-1px); box-shadow: 0 3px 0 var(--ink); }
.block-tool:active { transform: translateY(2px);  box-shadow: 0 0 0 var(--ink); }
.block-tool.is-disabled {
  opacity: 0.25;
  cursor: not-allowed;
  pointer-events: none;
}
.block-tool--delete {
  background: #F5C9C0;
  color: #8B2A1C;
  border-color: #8B2A1C;
  box-shadow: 0 2px 0 #8B2A1C;
}
.block-tool--delete:hover  { box-shadow: 0 3px 0 #8B2A1C; }
.block-tool--delete:active { box-shadow: 0 0 0 #8B2A1C; }
/* Hide the toolbar entirely while the kid is dragging a block — otherwise
   it floats stale over the drag preview. JS toggles this class. */
.block-toolbar.is-hidden { display: none; }

/* Workspace drop-feedback when a palette tile is being dragged over */
.blockly-host.drag-over { box-shadow: inset 0 0 0 3px rgba(240,169,59,0.7); }
.blockly-host.drag-over::after {
  content: "drop here!";
  position: absolute;
  top: 14px; left: 50%;
  transform: translateX(-50%) rotate(-1.5deg);
  font-family: var(--font-hand);
  font-size: 22px;
  color: var(--ink);
  background: rgba(240,169,59,0.9);
  padding: 4px 14px;
  border: 1.5px solid var(--ink);
  border-radius: 999px;
  pointer-events: none;
  z-index: 4;
}

@keyframes hint-in {
  from { opacity: 0; transform: translateY(-46%); }
  to   { opacity: 1; transform: translateY(-50%); }
}

/* Override Blockly's default font via CSS (theme.js sets the theme font too) */
.blocklyText {
  font-family: var(--font-body) !important;
  font-weight: 500 !important;
}
.blocklyFlyoutBackground {
  fill: #FFFBEE !important;
  fill-opacity: 0.85 !important;
}
.blocklyMainBackground {
  stroke: none !important;
  fill: #FFFBEE !important;
}
.blocklyToolboxDiv {
  background: var(--paper-deep) !important;
  border-right: 1.5px dashed rgba(26,42,64,0.2) !important;
}
.blocklyTreeRow {
  border-radius: 10px !important;
  margin: 4px 6px !important;
  padding: 6px 10px !important;
}
.blocklyTreeLabel {
  font-family: var(--font-body) !important;
  font-weight: 500 !important;
  color: var(--ink) !important;
}
.blocklyTreeSelected {
  background: var(--ink) !important;
}
.blocklyTreeSelected .blocklyTreeLabel {
  color: var(--paper) !important;
}

/* -----------------------------------------------------------
   Simulator
   ----------------------------------------------------------- */

.sim {
  flex: 1;
  position: relative;
  min-height: 0;
  border-radius: 16px;
  overflow: hidden;
  border: 1.5px dashed rgba(26,42,64,0.25);
}
.sim__sky {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 70% 50% at 50% 0%, var(--sky-2) 0%, transparent 60%),
    linear-gradient(180deg, var(--sky-1) 0%, var(--sky-3) 100%);
}
#sim-canvas {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: block;
  cursor: grab;
  touch-action: none;        /* let pointermove drive pan instead of scrolling */
}
#sim-canvas.is-panning { cursor: grabbing; }

.sim__hud {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sim__chip {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  padding: 7px 12px 6px;
  border-radius: 14px;
  background: rgba(255, 251, 238, 0.85);
  border: 1.5px solid var(--ink);
  backdrop-filter: blur(4px);
  box-shadow: 0 2px 0 rgba(26,42,64,0.4);
  min-width: 80px;
}
.sim__chip-label {
  font-family: var(--font-hand);
  font-size: 16px;
  line-height: 1;
  color: var(--ink-soft);
  text-transform: lowercase;
}
.sim__chip-value {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 22px;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.sim__chip-unit {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 12px;
  margin-left: 2px;
  color: var(--ink-soft);
}

/* battery chip is meaningless in pretend mode (no actual battery to drain).
   Kept in the markup so we can surface a real reading from cflib once the
   bridge streams it. */
body[data-mode="sim"] .sim__chip--battery { display: none; }

/* sound on/off — a compact chip-shaped button under the height chip */
.sim__chip--sound {
  cursor: pointer;
  align-items: center;
  justify-content: center;
  align-self: flex-end;
  width: 44px;
  min-width: 0;
  padding: 7px 0 5px;
  font-size: 17px;
  line-height: 1;
}
.sim__chip--sound:hover { transform: translateY(-1px); }
.sim__chip--sound.is-muted { opacity: 0.55; }

.sim__status {
  /* Hidden: the end-of-flight feedback stamp now carries win/lose, and
     the drone animation conveys in-flight progress. `_setStatus` still
     writes here harmlessly (kept for potential real-drone use), it's
     just not shown. */
  display: none;
  position: absolute;
  bottom: 14px;
  left: 14px;
  z-index: 3;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border-radius: var(--radius-pill);
  background: rgba(255, 251, 238, 0.92);
  border: 1.5px solid var(--ink);
  box-shadow: 0 2px 0 rgba(26,42,64,0.4);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}
.sim__status-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--go-hot);
  box-shadow: 0 0 0 3px rgba(70,163,122,0.25);
  animation: pulse 1.6s ease-in-out infinite;
}

.sim__scale {
  position: absolute;
  bottom: 12px;
  right: 16px;
  z-index: 3;
  pointer-events: none;
  text-align: center;
  color: rgba(26,42,64,0.7);
}
.sim__scale-bar {
  /* 30 cm at the current canvas zoom — width tracks --canvas-zoom set
     from app.js whenever the kid hits +/-. Default 1.0 = 96 px. */
  width: calc(96px * var(--canvas-zoom, 1));
  height: 10px;
  position: relative;
  margin: 0 auto;
  border-left:  2px solid currentColor;
  border-right: 2px solid currentColor;
}
.sim__scale-bar::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  border-top: 2px solid currentColor;
  transform: translateY(-1px);
}
.sim__scale-label {
  display: block;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 11px;
  color: var(--ink-soft);
  margin-top: 2px;
}

/* Zoom controls — small map-style +/- in the top-left of the canvas */
.sim__zoom {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.sim__zoom-btn {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--ink);
  background: rgba(255,251,238,0.92);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 0 rgba(26,42,64,0.35);
  transition: transform 100ms ease, background 200ms;
}
.sim__zoom-btn:hover  { background: #FBE9CF; }
.sim__zoom-btn:active { transform: translateY(1px); box-shadow: 0 1px 0 rgba(26,42,64,0.35); }
.sim__zoom-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.sim__status.is-flying  .sim__status-dot { background: var(--flight); box-shadow: 0 0 0 3px rgba(231,111,81,0.25); }
.sim__status.is-stopped .sim__status-dot { background: var(--stop);   box-shadow: 0 0 0 3px rgba(208,69,67,0.25);  }

@keyframes pulse {
  0%, 100% { transform: scale(1);   opacity: 1; }
  50%      { transform: scale(1.2); opacity: 0.8; }
}

/* -----------------------------------------------------------
   Palette — click-to-insert tiles styled like the blocks
   ----------------------------------------------------------- */

.palette {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 4px 4px 8px;
}

.tile {
  --tile-bg:    #E76F51;
  --tile-edge:  #A14227;
  font: inherit;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.005em;
  color: #FFFBEE;
  background: var(--tile-bg);
  border: 2px solid var(--ink);
  border-radius: 14px;
  padding: 10px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  box-shadow: 0 4px 0 var(--ink);
  position: relative;
  text-align: left;
  transition: transform 110ms ease, box-shadow 110ms ease, background 160ms;
  width: 100%;
  white-space: nowrap;
}
.tile--logic {
  --tile-bg:    #E9B44C; /* marigold — matches the logic_blocks theme */
  --tile-edge:  #A0792C;
  /* Sit slightly apart from the flight tiles so it's visually clear that
     "repeat" is a different kind of block (it wraps the others). */
  margin-top: 18px;
}
.tile--logic::after {
  content: "";
  position: absolute;
  left: 8px;
  right: 8px;
  top: -10px;
  height: 0;
  border-top: 2px dashed rgba(26, 42, 64, 0.4);
}
.tile--sensor {
  --tile-bg:    #7FA877; /* sage — matches the sensor_blocks theme */
  --tile-edge:  #4F7148;
}
/* The first sensor tile gets the dashed divider — these PLUG INTO the
   "fly until" slot rather than stacking in the chain. */
.tile--sensor:not(.tile--sensor ~ .tile--sensor) { margin-top: 18px; }
.tile--sensor:not(.tile--sensor ~ .tile--sensor)::after {
  content: "";
  position: absolute;
  left: 8px;
  right: 8px;
  top: -10px;
  height: 0;
  border-top: 2px dashed rgba(26, 42, 64, 0.4);
}
.tile::before {
  /* the puzzle-piece "tab" on the right, like Blockly's stack hint */
  content: "";
  position: absolute;
  right: 14px;
  bottom: -6px;
  width: 22px;
  height: 8px;
  background: var(--tile-bg);
  border: 2px solid var(--ink);
  border-top: 0;
  border-radius: 0 0 9px 9px;
}
.tile:hover  { transform: translateY(-1px); box-shadow: 0 5px 0 var(--ink); }
.tile:active { transform: translateY(3px);  box-shadow: 0 1px 0 var(--ink); }

.tile__icon {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,0.15));
}
.tile__label { flex: 1; }

.tile__hint {
  font-family: var(--font-hand);
  font-size: 13px;
  font-weight: 500;
  color: rgba(255,251,238,0.82);
  margin-left: auto;
  padding-left: 6px;
  flex: 0 0 auto;
}

/* -----------------------------------------------------------
   Drawer — collapsible Python panel for grown-ups
   ----------------------------------------------------------- */

.drawer {
  position: relative;
  z-index: 2;
  margin: 0 40px 14px;
  border: 2px solid var(--ink);
  border-radius: 18px;
  background: #1D2D44;
  color: #F0E5C9;
  box-shadow: var(--shadow-paper);
  overflow: hidden;
}
.drawer__handle {
  font: inherit;
  font-family: var(--font-body);
  font-weight: 500;
  color: rgba(240,229,201,0.92);
  background: transparent;
  border: 0;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 18px;
  cursor: pointer;
  text-align: left;
  letter-spacing: 0.01em;
}
.drawer__handle:hover { background: rgba(240,229,201,0.05); }
.drawer__icon  { width: 18px; height: 18px; color: var(--logic); flex: 0 0 auto; }
.drawer__title { font-size: 14px; font-weight: 600; letter-spacing: 0.02em; }
.drawer__hint  {
  font-family: var(--font-hand);
  font-size: 16px;
  color: rgba(240,229,201,0.45);
  font-weight: 500;
  flex: 1;
}
.drawer__chevron {
  font-size: 14px;
  color: rgba(240,229,201,0.6);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1.05);
}
.drawer[data-state="open"] .drawer__chevron { transform: rotate(180deg); }

.drawer__body {
  max-height: 0;
  overflow: hidden;
  transition: max-height 340ms cubic-bezier(.2,.7,.3,1.05);
}
.drawer[data-state="open"] .drawer__body { max-height: 320px; }

.code__pre {
  margin: 0;
  padding: 14px 18px 18px;
  overflow: auto;
  font-family: 'Lexend', ui-monospace, SFMono-Regular, Menlo, monospace;
  font-weight: 380;
  font-size: 13.5px;
  line-height: 1.7;
  color: #F0E5C9;
  white-space: pre-wrap;
  word-break: break-word;
  letter-spacing: 0.01em;
  border-top: 1.5px dashed rgba(240,229,201,0.18);
  max-height: 280px;
}
.code__pre code .py-kw   { color: #E9B44C; font-weight: 600; }
.code__pre code .py-call { color: #F3A487; }
.code__pre code .py-num  { color: #BFD3E0; }
.code__pre code .py-cmt  { color: rgba(240,229,201,0.4); font-style: italic; }

/* -----------------------------------------------------------
   Footnote
   ----------------------------------------------------------- */

.footnote {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 0 24px;
  font-family: var(--font-hand);
  font-size: 18px;
  color: var(--ink-soft);
  opacity: 0.85;
}
.footnote__pin {
  color: var(--flight);
  font-size: 16px;
  transform: translateY(-1px);
}

/* -----------------------------------------------------------
   Tiny entrance flourish on first paint
   ----------------------------------------------------------- */

.card {
  animation: settle 700ms cubic-bezier(.2,.7,.3,1.05) both;
}
.card--palette { animation-delay: 60ms;  --enter-rot: -1.8deg; }
.card--blocks  { animation-delay: 140ms; --enter-rot: -0.8deg; }
.card--sim     { animation-delay: 220ms; --enter-rot: 1.2deg;  }

@keyframes settle {
  from {
    opacity: 0;
    transform: translateY(20px) rotate(var(--enter-rot, -1.4deg));
  }
}

.drawer {
  animation: settle 700ms 320ms cubic-bezier(.2,.7,.3,1.05) both;
  --enter-rot: 0deg;
}

.masthead h1,
.masthead__tag,
.masthead__icon {
  animation: settle 600ms cubic-bezier(.2,.7,.3,1.05) both;
}
.masthead h1   { animation-delay: 0ms;   }
.masthead__tag { animation-delay: 220ms; }
.masthead__icon{ animation-delay: 110ms; }
