/* Armadillo Bounce - interface.
   Wooden planks and warm amber on a twilight violet, so the furniture reads
   as part of the same forest the game is drawn in. */

:root {
  --ink: #1b0f2b;
  --ink2: #2a1740;
  --plank1: #43285c;
  --plank2: #2b1a41;
  --edge: #c99a5a;
  --edge-dim: rgba(201, 154, 90, 0.45);
  --amber: #ffd98a;
  --amber-hot: #ffb347;
  --cream: #fff6dc;
  --leaf: #7fd06a;
  --font: "Trebuchet MS", "Segoe UI", Verdana, system-ui, -apple-system, sans-serif;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: #120a20;
  color: var(--cream);
  font-family: var(--font);
  touch-action: none;
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
}

#app {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* ---------------------------------------------------------------- HUD */
#hud {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  background: linear-gradient(180deg, #3a2255, #241536 70%, #1d1030);
  /* the bar used to end on a two pixel rule across the whole width: it is a
     soft edge of light now, and a glow falling onto the field below */
  border-bottom: 0;
  box-shadow:
    0 1px 0 rgba(201, 154, 90, 0.30),
    0 6px 18px rgba(255, 190, 120, 0.10),
    0 5px 18px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 220, 160, 0.16);
  min-height: 46px;
}

.hud-group { display: flex; align-items: center; gap: 6px; }
/* The score is the one thing up here that must never be cut short, so it is
   the group around it that yields: whatever has to be lost is lost to the
   right of the number, and the little padding on the right leaves it to the
   combo chip to breathe when it swells. */
.hud-left { flex: 1 1 auto; min-width: 0; overflow: hidden; padding-right: 3px; }
.hud-mid { flex: 0 1 auto; min-width: 0; overflow: hidden; }
.hud-right { flex: 0 0 auto; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 12px;
  /* min-width:auto is the flexbox default and it means "never smaller
     than my text". The score is nowrap, so on a narrow phone the chip
     refused to shrink, spilled out of its own group and painted over the
     power-up timer beside it. */
  min-width: 0;
  overflow: hidden;
  background: linear-gradient(180deg, rgba(255, 236, 190, 0.14), rgba(255, 236, 190, 0.04));
  border: 1.5px solid var(--edge-dim);
  font-weight: 700;
  font-size: 14px;
  white-space: nowrap;
  color: var(--cream);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.35);
}
.chip.score { flex: 0 0 auto; }
.chip .k { font-size: 11px; opacity: 0.7; letter-spacing: 0.06em; text-transform: uppercase; }
.chip.combo {
  color: var(--amber);
  font-size: 16px;
  min-width: 44px;
  justify-content: center;
  transition: transform 0.22s cubic-bezier(0.22, 1.4, 0.42, 1), color 0.2s ease, background 0.2s ease;
}
.chip.combo.hot {
  color: #fff3c4;
  background: linear-gradient(180deg, rgba(255, 179, 71, 0.5), rgba(255, 120, 40, 0.25));
  border-color: rgba(255, 200, 120, 0.8);
  transform: scale(1.06);
}
.chip.level { font-size: 12.5px; opacity: 0.92; }

.lives { display: flex; gap: 1px; align-items: center; }

.powers { display: flex; gap: 5px; align-items: center; overflow: hidden; }
.pchip {
  position: relative;
  width: 30px; height: 30px;
  border-radius: 9px;
  background: linear-gradient(180deg, rgba(255, 230, 170, 0.22), rgba(255, 210, 140, 0.09));
  border: 1.5px solid var(--edge-dim);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  flex: 0 0 auto;
}
.pchip canvas { display: block; }
.pchip i {
  position: absolute;
  left: 2px; right: 2px; bottom: 2px;
  height: 4px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--amber-hot), var(--amber));
  transform-origin: left center;
  transition: transform 0.16s cubic-bezier(0.25, 0.8, 0.4, 1);
}
.pchip.low i { background: linear-gradient(90deg, #ff6b4a, #ffa04a); }

/* These are switches rather than buttons (see index.html), so they carry
   their own box model: a <button> is border-box by default and a <div> is
   not, and without this line each control in the bar is 3px wider than the
   one it replaced. */
.icon-btn {
  box-sizing: border-box;
  width: 36px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 11px;
  background: linear-gradient(180deg, rgba(255, 236, 190, 0.16), rgba(0, 0, 0, 0.16));
  border: 1.5px solid var(--edge-dim);
  cursor: pointer;
  padding: 0;
  user-select: none; -webkit-user-select: none;
  transition: transform 0.16s cubic-bezier(0.2, 0.9, 0.3, 1), background 0.22s ease;
}
.icon-btn:hover { background: rgba(255, 220, 150, 0.24); }
.icon-btn:active { transform: scale(0.94); }
/* reachable with Tab, so it has to say where the keyboard is */
.icon-btn:focus-visible { outline: 2px solid #ffd977; outline-offset: 2px; }

/* -------------------------------------------------------------- stage */
#stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background: #120a20;
}
#game {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  touch-action: none;
}
/* the field dims behind a panel instead of being switched off: the same
   transition also covers the moment a level starts and it comes back */
#stage #game { transition: filter 0.28s cubic-bezier(0.3, 0.9, 0.4, 1); }
#stage.dimmed #game { filter: saturate(0.85) brightness(0.62) blur(2px); }

/* ------------------------------------------------------------ screens */
.screen {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 12px;
  overflow: auto;
  z-index: 5;
}
.screen.show { display: flex; }

.panel {
  position: relative;
  width: min(560px, 100%);
  max-height: 100%;
  overflow: auto;
  padding: 18px 18px 20px;
  border-radius: 22px;
  background:
    radial-gradient(120% 80% at 20% 0%, rgba(255, 220, 160, 0.10), rgba(255, 220, 160, 0) 60%),
    linear-gradient(180deg, var(--plank1), var(--plank2) 78%, #221334);
  border: 3px solid var(--edge);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 226, 170, 0.22), inset 0 -14px 30px rgba(0, 0, 0, 0.35);
  text-align: center;
  animation: pop 0.30s cubic-bezier(0.2, 1.16, 0.42, 1);
}
.panel.wide { width: min(720px, 100%); }
.panel.small { width: min(420px, 100%); }

@keyframes pop {
  from { transform: scale(0.94) translateY(10px); opacity: 0; }
  60%  { opacity: 1; }
  to { transform: scale(1) translateY(0); opacity: 1; }
}

.panel::before, .panel::after {
  content: "";
  position: absolute;
  top: -8px;
  width: 44px; height: 22px;
  background: radial-gradient(60% 100% at 50% 100%, rgba(127, 208, 106, 0.85), rgba(63, 122, 53, 0));
  border-radius: 50% 50% 0 0;
  pointer-events: none;
}
.panel::before { left: 16px; transform: rotate(-12deg); }
.panel::after { right: 16px; transform: rotate(12deg); }

.panel-title {
  margin: 0 0 10px;
  font-size: clamp(20px, 5vw, 27px);
  letter-spacing: 0.01em;
  color: var(--cream);
  text-shadow: 0 3px 0 rgba(0, 0, 0, 0.35), 0 0 22px rgba(255, 200, 120, 0.28);
}

.logo {
  margin: 0 0 4px;
  display: flex;
  flex-direction: column;
  line-height: 0.96;
  font-size: clamp(30px, 9vw, 54px);
  letter-spacing: 0.01em;
}
.logo .l1 {
  color: #ffe1a6;
  text-shadow: 0 3px 0 #8a5527, 0 6px 0 #5c3418, 0 9px 18px rgba(0, 0, 0, 0.5);
}
.logo .l2 {
  color: #9fe07a;
  text-shadow: 0 3px 0 #2f6b28, 0 6px 0 #1d4a19, 0 9px 18px rgba(0, 0, 0, 0.5);
}

.tag {
  margin: 6px 0 0;
  font-size: 14px;
  line-height: 1.35;
  color: rgba(255, 246, 220, 0.78);
}
.subtitle { font-size: 13.5px; color: rgba(255, 246, 220, 0.75); margin: 6px 0 0; }
.scoreline { font-size: 20px; margin: 8px 0 0; color: rgba(255, 246, 220, 0.85); }
.scoreline b { color: var(--amber); font-size: 26px; }

.buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-top: 14px;
}

button {
  font-family: var(--font);
  font-weight: 700;
  font-size: 15px;
  color: #3a2110;
  padding: 10px 18px;
  border-radius: 14px;
  border: 2.5px solid #6f4420;
  background: linear-gradient(180deg, #ffd98a, #f0a83c);
  box-shadow: 0 4px 0 #7a4f28, 0 8px 16px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  transition: transform 0.16s cubic-bezier(0.2, 0.9, 0.3, 1), box-shadow 0.16s cubic-bezier(0.2, 0.9, 0.3, 1);
}
button:hover { transform: translateY(-1px); box-shadow: 0 5px 0 #7a4f28, 0 10px 18px rgba(0, 0, 0, 0.4); }
button:active { transform: translateY(2px); box-shadow: 0 2px 0 #7a4f28, 0 4px 10px rgba(0, 0, 0, 0.35); }
button.big { font-size: 17px; padding: 12px 26px; }
button:disabled { filter: grayscale(0.7) brightness(0.7); cursor: not-allowed; }

.toggles, .toggle-row { display: flex; gap: 8px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }
.tog {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px;
  padding: 7px 12px;
  border-radius: 12px;
  color: rgba(255, 246, 220, 0.55);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.06), rgba(0, 0, 0, 0.2));
  border: 2px solid rgba(201, 154, 90, 0.35);
  box-shadow: none;
  transition: color 0.22s ease, border-color 0.22s ease, background 0.22s ease;
}
.tog.on { color: var(--cream); border-color: var(--edge); background: linear-gradient(180deg, rgba(255, 216, 138, 0.22), rgba(255, 179, 71, 0.10)); }
.tog canvas { display: block; opacity: 0.95; }

/* how to play list */
.howto { list-style: none; margin: 10px 0 0; padding: 0; text-align: left; }
.howto li {
  display: grid;
  grid-template-columns: 76px 1fr;
  gap: 10px;
  padding: 7px 4px;
  border-bottom: 1px dashed rgba(201, 154, 90, 0.22);
  font-size: 13.5px;
  line-height: 1.4;
}
.howto li:last-child { border-bottom: 0; }
.howto b { color: var(--amber); font-size: 14px; }
.howto span { color: rgba(255, 246, 220, 0.82); }

/* level select */
.levels {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 9px;
  margin-top: 12px;
}
/* Thirty two levels rather than twelve. A phone cannot show thirty two
   plates the size of the old ones without turning the grid into a scroll
   with no end to it, so on a narrow screen the card keeps its picture and
   its name and gives up only its width: two or three across instead of
   one, and the whole chapter list is a couple of screens rather than
   seven. Nothing is hidden and nothing needs the phone turned sideways. */
@media (max-width: 760px) {
  .levels { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 7px; margin-top: 10px; }
  .level-btn { padding: 4px; border-radius: 12px; }
  .level-btn .lv-name { font-size: 10px; }
  .level-btn .lock { font-size: 9px; padding: 3px 4px; }
}
@media (max-width: 420px) {
  .levels { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 6px; }
  .level-btn .lv-name { font-size: 9.5px; }
}
.level-btn {
  padding: 5px;
  border-radius: 14px;
  border: 2.5px solid var(--edge);
  background: linear-gradient(180deg, #3d2456, #291741);
  box-shadow: 0 4px 0 #1b0f2b, 0 8px 14px rgba(0, 0, 0, 0.35);
  color: var(--cream);
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  position: relative;
  overflow: hidden;
  transition: transform 0.2s cubic-bezier(0.2, 0.9, 0.3, 1), box-shadow 0.2s ease;
}
.level-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 0 #1b0f2b, 0 12px 20px rgba(0, 0, 0, 0.4); }
/* !important for the same reason the HUD icons have it: these canvases are
   built at a fixed pixel size and carry that size as an inline style, which
   beats a plain rule. Without it the plate stays 150px wide inside a card
   that is 128px on a small phone, and `overflow: hidden` on the card cuts
   the right hand side of every level picture off. */
.level-btn canvas { display: block; width: 100% !important; height: auto !important; border-radius: 9px; }
.level-btn .lv-name {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--cream);
  text-align: center;
  line-height: 1.2;
  padding: 0 2px 2px;
}
.level-btn.locked { opacity: 0.72; }
/* the lock line is part of the card, not laid over it: sitting it on top of
   the level name made every locked card unreadable */
.level-btn .lock {
  display: block;
  width: 100%;
  font-size: 10px;
  padding: 4px 5px;
  border-radius: 8px;
  background: rgba(20, 10, 34, 0.72);
  color: rgba(255, 246, 220, 0.9);
  line-height: 1.2;
  text-align: center;
}

.stars { display: flex; justify-content: center; gap: 2px; margin: 6px 0 2px; }
/* the stars on the results card land one after another, on an ease-out
   with a little overshoot, rather than all three at once */
.stars canvas.award {
  opacity: 0;
  animation: award 0.42s cubic-bezier(0.22, 1.5, 0.44, 1) forwards;
}
.stars canvas.award.dim { animation-duration: 0.30s; }
@keyframes award {
  from { opacity: 0; transform: scale(0.35) rotate(-22deg); }
  to   { opacity: 1; transform: scale(1) rotate(0deg); }
}
.title-art, .final-art { display: flex; justify-content: center; margin: 8px 0 2px; }
.title-art canvas, .final-art canvas { max-width: 100%; height: auto; }
.best { min-height: 18px; font-size: 13px; color: var(--amber); margin: 10px 0 0; font-weight: 700; }

/* ------------------------------------------------------- small screens */
@media (max-width: 520px) {
  .chip { padding: 3px 8px; font-size: 13px; }
  .chip.level { display: none; }
  .hud-left { gap: 4px; }
  .hud-group { gap: 4px; }
}
/* The word SCORE is the first thing to go when there is no room for it:
   the number is what a player is reading anyway. */
@media (max-width: 430px) {
  .chip .k { display: none; }
  .chip.score { padding-left: 9px; padding-right: 9px; }
  /* The multiplier is never squeezed and never cut to a sliver: it takes the
     width its own digits need, and it is the score's padding and the timers
     beside it that give way instead. */
  .chip.combo { flex: 0 0 auto; padding: 3px 7px; font-size: clamp(13px, 3.9vw, 15px); }
  /* a button keeps its size whenever the bar has room to give and loses a
     little of it when it does not; the icon scales down with it */
  /* the right hand group yields too: with it nailed shut the whole squeeze
     landed on the score, which is the one thing that must not lose a digit */
  .hud-right { flex: 0 1 auto; min-width: 0; }
  .icon-btn { width: 32px; height: 32px; flex: 0 1 32px; min-width: 26px; padding: 4px; }
  /* !important because these canvases carry their size as an inline style,
     set from the pixel size the art was drawn at */
  .icon-btn canvas { width: 100% !important; height: 100% !important; }
  .lives canvas { width: 22px !important; height: 22px !important; }
  /* a running timer may lose a little width but never its place: with two
     going at once the pair is a squeeze, and the icon scales down inside the
     chip rather than the second timer being cut off at the edge */
  .pchip { flex: 0 1 30px; min-width: 18px; padding: 2px; box-sizing: border-box; }
  .pchip canvas { width: 100% !important; height: 100% !important; }
  .panel { padding: 14px 13px 16px; border-radius: 18px; }
  .howto li { grid-template-columns: 66px 1fr; font-size: 12.5px; }
  .levels { grid-template-columns: repeat(auto-fill, minmax(122px, 1fr)); }
  .logo { font-size: clamp(28px, 11vw, 40px); }
}

/* On the narrowest phones the bar has more in it than the width can hold, so
   it is the furniture that gives way rather than the number: everything in
   the row loses a little and the score keeps every digit it has. The score is
   the one thing up here a player is actually reading. */
@media (max-width: 380px) {
  #hud { padding: 5px 6px; gap: 4px; }
  .hud-group, .hud-left { gap: 3px; }
  /* the number sets its own size from the width it has, so a long score
     still fits rather than being cut off at the last digit */
  .chip { padding: 3px 6px; gap: 3px; font-size: clamp(10px, 3.4vw, 11.5px); }
  .chip.combo { padding: 3px 6px; font-size: 12.5px; }
  .icon-btn { width: 28px; height: 28px; flex-basis: 28px; padding: 3px; }
  /* Music is the one control in the bar that does not belong to playing, so
     it is the one that steps out when the bar runs out of room. It is still
     on the pause panel and on the title screen, both one tap away. */
  #btnMusic { display: none; }
  .pchip { width: 26px; height: 26px; flex-basis: 26px; }
  .lives canvas { width: 19px !important; height: 19px !important; }
  .powers { gap: 4px; }
}

@media (max-height: 520px) {
  #hud { min-height: 38px; padding: 3px 6px; }
  .pchip, .icon-btn { width: 28px; height: 26px; }
  .panel { padding: 10px 12px 12px; }
  .title-art, .final-art { display: none; }
  .logo { font-size: clamp(22px, 6vw, 34px); }
}

@media (prefers-reduced-motion: reduce) {
  .panel { animation: none; }
  .stars canvas.award { animation: none; opacity: 1; transform: none; }
  #stage #game { transition: none; }
}
