:root {
  --primary-gold: #ffd369;
  --gold-glow: rgba(255, 211, 105, 0.4);
  --dream-purple: #9d65ff;
  --sky-dark: #0f0a20;
  --card-bg: rgba(18, 12, 38, 0.88);
  --card-border: rgba(255, 211, 105, 0.35);
  --glass-glow: rgba(255, 255, 255, 0.08);
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  user-select: none;
}

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #090514;
  color: #fff;
  font-family: 'Outfit', sans-serif;
}

#game-shell {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #090514;
}

#pixi-host,
#pixi-host canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

.hidden {
  display: none !important;
}

/* =========================================================
   HUD STYLING
========================================================= */
#hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 15;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 16px 24px;
}

.hud-top {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}

/* Left-packed, NOT space-between. With space-between the row's contents jump to
   the far right the moment a second panel becomes visible, and the candy/score
   panel slid underneath the controls overlay as soon as the wand meter
   appeared. Packing left keeps every panel's position stable no matter how many
   meters happen to be on. */
.hud-bottom {
  display: flex;
  justify-content: flex-start;
  align-items: flex-end;
  gap: 12px;
}

/* Candy stays leftmost, where it has always been, so a meter switching on never
   moves it. */
.hud-candy { order: -1; }

.glass {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 12px;
  backdrop-filter: blur(10px);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), inset 0 0 12px var(--glass-glow);
  padding: 10px 18px;
  color: #fff;
}

.hud-label {
  display: block;
  font-family: 'Cinzel', serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.25em;
  color: #b5a5db;
  text-transform: uppercase;
  margin-bottom: 4px;
}

.health-pips {
  display: flex;
  gap: 6px;
  font-size: 20px;
}

.health-pip {
  color: #ff5c8a;
  text-shadow: 0 0 10px rgba(255, 92, 138, 0.6);
  transition: transform 0.2s;
}

.health-pip.lost {
  color: #4a2d3b;
  text-shadow: none;
  opacity: 0.4;
}

.hud-stage {
  text-align: center;
  min-width: 280px;
}

.stage-roman {
  display: block;
  font-family: 'Cinzel', serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.3em;
  color: var(--primary-gold);
  text-shadow: 0 0 8px var(--gold-glow);
}

.stage-name {
  display: block;
  font-family: 'Cinzel', serif;
  font-size: 17px;
  font-weight: 900;
  letter-spacing: 0.12em;
  color: #ffffff;
  margin: 2px 0 6px;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.8);
}

.keys-tracker {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 700;
  color: #ffeaa7;
  letter-spacing: 0.08em;
}

.hud-form {
  text-align: right;
  min-width: 170px;
}

.form-badge {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin-bottom: 2px;
}

.form-icon {
  font-size: 18px;
}

.form-name {
  font-family: 'Cinzel', serif;
  font-size: 15px;
  font-weight: 700;
  color: #e2d9fc;
  letter-spacing: 0.1em;
}

.form-desc {
  display: block;
  font-size: 11px;
  color: #a395cf;
  font-style: italic;
}

.hud-candy {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
  font-weight: 700;
  color: #ff9ed2;
  text-shadow: 0 0 10px rgba(255, 158, 210, 0.5);
}

.hud-meter {
  min-width: 160px;
}

.meter-label {
  font-family: 'Cinzel', serif;
  font-size: 9px;
  letter-spacing: 0.2em;
  color: #c7b5ff;
  display: block;
  margin-bottom: 4px;
}

.meter-bar {
  width: 100%;
  height: 8px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.meter-fill {
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, #9d65ff, #00d2d3);
  box-shadow: 0 0 8px rgba(0, 210, 211, 0.8);
  transition: width 0.1s linear;
}

/* Wand XP reads gold rather than the flutter meter's cyan, so a glance tells
   the two meters apart without reading either label. */
.wand-fill {
  background: linear-gradient(90deg, #b46a00, #ffd166);
  box-shadow: 0 0 8px rgba(255, 209, 102, 0.85);
}

.meter-label b {
  color: var(--primary-gold, #ffd166);
  font-weight: 700;
  letter-spacing: 0.1em;
}

/* ---- Dialogue box ------------------------------------------------------- */
.dialogue {
  position: absolute;
  left: 50%;
  bottom: 84px;
  transform: translateX(-50%);
  width: min(760px, calc(100% - 64px));
  display: flex;
  gap: 16px;
  padding: 16px 18px;
  background: rgba(15, 10, 30, 0.95);
  border: 2px solid var(--primary-gold, #ffd166);
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.6);
  z-index: 40;
}

.dialogue.hidden { display: none; }

.dialogue-portrait {
  flex: 0 0 84px;
  width: 84px;
  height: 84px;
  border: 2px solid rgba(255, 209, 102, 0.55);
  border-radius: 10px;
  background: rgba(60, 40, 100, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Portraits are generated from the game's own vector art, so they are small and
   must not be smoothed into mush when scaled up to fill the frame. */
.dialogue-portrait img {
  max-width: 100%;
  max-height: 100%;
  image-rendering: -webkit-optimize-contrast;
}

.dialogue-body { flex: 1 1 auto; min-width: 0; }

.dialogue-name {
  display: block;
  font-family: 'Cinzel', serif;
  font-size: 12px;
  letter-spacing: 0.22em;
  color: var(--primary-gold, #ffd166);
  margin-bottom: 6px;
}

.dialogue-text {
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
  color: #efe6ff;
}

.dialogue-more {
  display: block;
  margin-top: 8px;
  text-align: right;
  font-size: 10px;
  letter-spacing: 0.18em;
  color: #c7b5ff;
  animation: dialogue-blink 1.1s steps(2, end) infinite;
}

@keyframes dialogue-blink { 0%, 60% { opacity: 1; } 61%, 100% { opacity: 0.25; } }

.toast {
  position: absolute;
  top: 110px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(15, 10, 30, 0.92);
  border: 1px solid var(--primary-gold);
  border-radius: 30px;
  padding: 10px 24px;
  font-family: 'Crimson Pro', serif;
  font-style: italic;
  font-size: 19px;
  color: #fff4d1;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.7), 0 0 15px var(--gold-glow);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s, transform 0.3s;
  white-space: nowrap;
}

.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

.controls-overlay {
  position: absolute;
  right: 24px;
  bottom: 16px;
  display: grid;
  gap: 3px;
  width: 248px;
  padding: 10px 14px;
  border: 1px solid rgba(255, 211, 105, 0.42);
  border-radius: 10px;
  background: rgba(12, 8, 26, 0.88);
  color: #cfc2f0;
  font-size: 11px;
  line-height: 1.25;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.55);
}

.controls-overlay strong {
  color: var(--primary-gold);
  font-family: 'Cinzel', serif;
  font-size: 10px;
  letter-spacing: 0.18em;
  margin-bottom: 2px;
}

/* =========================================================
   TOUCH CONTROLS

   Shown only when game.js puts .touch-input on <body>, which it does only
   when the device reports touch. Never on desktop.

   Sizing is in vmin, not px and not the stage's 1280x720: the canvas is
   letterboxed and its scale has nothing to do with how big a child's thumb
   is. clamp() floors the target at 60 px, which is about a 9 mm tap area on
   a typical mid-range Android — above the 7 mm everyone quotes, because the
   audience is seven.
========================================================= */
.touch-controls {
  /* Four buttons plus their gaps have to fit across the narrowest phone still
     in use, so the size is capped against viewport WIDTH as well as vmin: vmin
     alone is the short edge, which in portrait is the one that does NOT
     constrain a row of buttons. Measured at 320/390/412/667/828 CSS px — the
     jump button's right edge stays inside the viewport at all of them. */
  --tb: clamp(54px, min(17vmin, 19vw), 92px);
  --tb-sm: calc(var(--tb) * 0.74);
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  /* Above the dialogue box (40) AND above the map sheet (55), so the two
     buttons that dismiss them — action and MAP — are never buried under the
     thing they dismiss. Both of those are soft locks on a phone, and the map
     one shipped for about ten minutes before elementFromPoint caught it.
     Still inside #hud's stacking context, so the screens at 25 cover it. */
  z-index: 60;
  display: none;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  padding: 0 clamp(4px, 2vw, 22px)
             calc(clamp(6px, 2vh, 18px) + env(safe-area-inset-bottom, 0px));
  pointer-events: none;
  touch-action: none;
}

body.touch-input .touch-controls { display: flex; }

/* The keyboard legend is noise on a device with no keyboard. */
body.touch-input .controls-overlay { display: none; }

/* The title card carries both control legends and shows exactly one. Written
   with two class selectors on purpose: `.controls-guide` sets `display: grid`
   further down this file, and at equal specificity the later rule wins — a
   single-class `.touch-guide { display: none }` here loses to it and the phone
   legend appears on desktop. */
.controls-guide.touch-guide { display: none; }
body.touch-input .controls-guide.touch-guide { display: grid; }
body.touch-input .controls-guide.keyboard-guide { display: none; }

.touch-pad,
.touch-actions {
  display: grid;
  gap: clamp(8px, 2vmin, 14px);
  grid-template-columns: var(--tb) var(--tb);
  pointer-events: auto;
}

/* Down sits centred under the pair rather than beside them: it is a modal
   verb (drop through cloud, dig down), not a direction you steer with, and
   putting it in the row would invite mis-taps against left/right. */
.touch-pad .touch-down {
  grid-column: 1 / -1;
  justify-self: center;
  width: var(--tb-sm);
  height: var(--tb-sm);
}

/* Two small pills on top, two thumb buttons below. The pills are deliberately
   quiet: MAP and dismount are things you choose, not things you press mid-jump,
   and making them the same size as jump would invite mis-taps that cost you a
   mount. */
.touch-actions { justify-items: center; align-items: end; }
.touch-actions .touch-map,
.touch-actions .touch-dismount {
  width: var(--tb-sm);
  height: calc(var(--tb-sm) * 0.6);
  border-radius: 999px;
  font-size: clamp(10px, 2.4vmin, 14px);
  letter-spacing: 0.1em;
  opacity: 0.8;
}
.touch-actions .touch-map       { grid-area: 1 / 1 / 2 / 2; }
.touch-actions .touch-dismount  { grid-area: 1 / 2 / 2 / 3; }
.touch-actions .touch-action    { grid-area: 2 / 1 / 3 / 2; }
.touch-actions .touch-jump      { grid-area: 2 / 2 / 3 / 3; }

.touch-btn {
  width: var(--tb);
  height: var(--tb);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 2px solid rgba(255, 211, 105, 0.55);
  border-radius: 50%;
  background: rgba(18, 12, 38, 0.62);
  color: #ffe9b0;
  font-family: 'Outfit', sans-serif;
  font-size: clamp(20px, 5vmin, 30px);
  font-weight: 700;
  line-height: 1;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);
  cursor: pointer;
  /* touch-action:none is what stops the page scrolling and pinch-zooming
     under the thumb; the tap highlight is what stops Android painting a grey
     box over the button on every press. */
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
}

/* Pressed state is a class, not :active: the press is tracked by hit-testing
   the live touch list, so a finger that slides off must un-light the button
   even though it is still touching the screen. */
.touch-btn.on {
  background: rgba(255, 211, 105, 0.34);
  border-color: var(--primary-gold);
  color: #fff8e2;
  transform: scale(0.94);
}

.touch-jump {
  border-color: rgba(157, 101, 255, 0.75);
  background: rgba(52, 30, 96, 0.66);
  color: #e6d8ff;
}
.touch-jump.on { background: rgba(157, 101, 255, 0.46); }

/* Landscape on a phone leaves ~360 px of height; two rows of 92 px buttons
   would eat half the dream. */
@media (max-height: 430px) {
  .touch-controls { --tb: clamp(52px, 15vh, 72px); }
}

/* =========================================================
   THE ATLAS — the map overlay (M)

   Above the dialogue and the touch pad, because it is modal and it pauses
   the world. Still inside #hud's stacking context, so the title, game-over
   and victory screens cover it.
========================================================= */
.map-overlay {
  position: absolute;
  inset: 0;
  /* BELOW the touch pad (60), above the dialogue (40).
     This was 60 — above the pad — and that is a soft lock on a phone: the map
     covered the very MAP button that closes it, so a child could open the Atlas
     and never get out of it. Found with elementFromPoint in a real browser;
     no harness models z-order. */
  z-index: 55;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 20px;
  background: rgba(9, 5, 20, 0.96);
  pointer-events: auto;
  cursor: pointer;   /* the whole sheet closes it — see the click handler */
}

.map-head {
  font-family: 'Cinzel', serif;
  font-size: clamp(14px, 2.4vw, 22px);
  font-weight: 900;
  letter-spacing: 0.28em;
  color: var(--primary-gold);
  text-align: center;
}

/* Wraps rather than scrolls: five pages fit in a row on a laptop and in two
   rows on a phone, and a map you have to scroll is a map you have to read. */
.map-shelf {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: clamp(8px, 1.4vw, 16px);
  max-width: 1100px;
}

.map-page {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: clamp(150px, 19vw, 200px);
  padding: 14px 16px;
  border: 1px solid rgba(255, 211, 105, 0.4);
  border-radius: 10px;
  background: rgba(24, 16, 48, 0.9);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
}

/* A dream you have never entered is not a greyed-out entry — it is a page
   somebody tore out. Dashed edge, no colour, no name. */
.map-torn {
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(16, 11, 32, 0.6);
  color: #6b6188;
}

.map-here {
  border-color: var(--primary-gold);
  box-shadow: 0 0 26px rgba(255, 211, 105, 0.35), 0 10px 26px rgba(0, 0, 0, 0.5);
}

.map-roman {
  font-family: 'Cinzel', serif;
  font-size: 10px;
  letter-spacing: 0.22em;
  color: var(--primary-gold);
}
.map-torn .map-roman { color: #6b6188; }

.map-title {
  font-family: 'Cinzel', serif;
  font-size: 13px;
  line-height: 1.3;
  color: #f2e9ff;
}
.map-torn .map-title { color: #6b6188; letter-spacing: 0.3em; }

.map-rows {
  display: grid;
  gap: 3px;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: #cfc2f0;
}

.map-open { color: #8ce99a; }
.map-shut { color: #b8879a; }

.map-you {
  margin-top: 2px;
  font-size: 9px;
  letter-spacing: 0.16em;
  color: var(--primary-gold);
}

.map-foot {
  font-family: 'Outfit', sans-serif;
  font-size: 10px;
  letter-spacing: 0.18em;
  color: #9c8fc4;
  text-align: center;
}

/* =========================================================
   OVERLAY SCREENS (Title, Transition, Game Over, Win)
========================================================= */
.screen {
  position: absolute;
  inset: 0;
  z-index: 25;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(10, 6, 22, 0.85);
  backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity 0.5s ease;
}

.screen.active {
  display: flex;
  opacity: 1;
}

.title-card,
.transition-card,
.ending-card {
  width: min(720px, 92vw);
  background: linear-gradient(145deg, rgba(26, 17, 52, 0.95), rgba(12, 8, 26, 0.98));
  border: 1px solid var(--card-border);
  border-radius: 20px;
  padding: 44px 50px;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8), inset 0 0 30px var(--glass-glow);
  position: relative;
}

.eyebrow {
  font-family: 'Cinzel', serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.35em;
  color: var(--primary-gold);
  text-transform: uppercase;
  margin-bottom: 8px;
}

.glow-title {
  font-family: 'Cinzel', serif;
  font-size: clamp(38px, 6vw, 68px);
  font-weight: 900;
  letter-spacing: 0.12em;
  color: #ffffff;
  text-shadow: 0 0 20px rgba(255, 211, 105, 0.7), 0 0 50px rgba(157, 101, 255, 0.5);
  margin-bottom: 4px;
}

.subtitle {
  font-family: 'Crimson Pro', serif;
  font-size: clamp(20px, 3vw, 28px);
  font-style: italic;
  font-weight: 400;
  color: #cfc2f0;
  margin-bottom: 22px;
}

.lore {
  font-size: 16px;
  line-height: 1.6;
  color: #bbb0d6;
  margin-bottom: 28px;
  max-width: 580px;
  margin-left: auto;
  margin-right: auto;
}

.controls-guide {
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 16px 20px;
  margin-bottom: 30px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 16px;
  text-align: left;
  font-size: 13px;
}

.ctrl-row {
  display: flex;
  justify-content: space-between;
  color: #9f91c9;
}

.ctrl-row strong {
  color: #fff;
  font-weight: 600;
}

.btn-dream {
  font-family: 'Cinzel', serif;
  font-size: 15px;
  font-weight: 900;
  letter-spacing: 0.2em;
  color: #0d0820;
  background: linear-gradient(135deg, #ffd369, #ffa502);
  border: none;
  border-radius: 50px;
  padding: 16px 42px;
  cursor: pointer;
  box-shadow: 0 0 30px rgba(255, 211, 105, 0.6), inset 0 2px 4px rgba(255, 255, 255, 0.5);
  transition: transform 0.2s, box-shadow 0.2s;
}

.btn-dream:hover {
  transform: scale(1.05);
  box-shadow: 0 0 45px rgba(255, 211, 105, 0.9), inset 0 2px 4px rgba(255, 255, 255, 0.8);
}

.btn-dream:active {
  transform: scale(0.98);
}

/* CONTINUE sits above ENTER THE DREAM and is the calmer of the two on purpose:
   it is the button a returning player is looking for, but the gold gradient is
   the game's "begin" gesture and should stay attached to beginning. Cool violet
   reads as "the dream you left", and the two are never confusable at a glance —
   which matters when the person tapping is seven and about to overwrite an hour
   of play with the wrong one. */
.btn-continue {
  /* block + auto margins, not inline: the sub-label under the word CONTINUE
     needs its own line, and an inline-block would sit on the card's text
     baseline and refuse to centre against the gold button below it. */
  display: block;
  margin: 0 auto 14px;
  color: #f3ecff;
  background: linear-gradient(135deg, #7b4dd8, #4a2a9c);
  box-shadow: 0 0 30px rgba(157, 101, 255, 0.5), inset 0 2px 4px rgba(255, 255, 255, 0.25);
}

.btn-continue:hover {
  box-shadow: 0 0 45px rgba(157, 101, 255, 0.85), inset 0 2px 4px rgba(255, 255, 255, 0.4);
}

.btn-sub {
  display: block;
  margin-top: 5px;
  font-family: 'Outfit', sans-serif;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: rgba(243, 236, 255, 0.75);
}

/* Transition Screen */
.transition-screen {
  background: rgba(7, 4, 18, 0.95);
}

.transition-roman {
  font-family: 'Cinzel', serif;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.4em;
  color: var(--primary-gold);
  display: block;
  margin-bottom: 12px;
}

.transition-heading {
  font-family: 'Cinzel', serif;
  font-size: clamp(32px, 5vw, 54px);
  font-weight: 900;
  letter-spacing: 0.1em;
  color: #fff;
  text-shadow: 0 0 30px rgba(157, 101, 255, 0.8);
  margin-bottom: 16px;
}

.transition-quote {
  font-family: 'Crimson Pro', serif;
  font-size: 22px;
  font-style: italic;
  color: #a99cd1;
}

/* Victory & Gameover Titles */
.victory-title {
  font-family: 'Cinzel', serif;
  font-size: 42px;
  color: var(--primary-gold);
  text-shadow: 0 0 30px var(--gold-glow);
  margin-bottom: 24px;
}

.gameover-title {
  font-family: 'Cinzel', serif;
  font-size: 42px;
  color: #ff5c8a;
  text-shadow: 0 0 30px rgba(255, 92, 138, 0.6);
  margin-bottom: 16px;
}

.ending-story {
  font-family: 'Crimson Pro', serif;
  font-size: 22px;
  font-style: italic;
  color: #d1c7eb;
  line-height: 1.8;
  margin-bottom: 32px;
}

.gold-text {
  color: var(--primary-gold);
  font-weight: 700;
  font-size: 26px;
  margin-top: 10px;
}

/* =========================================================
   CRT & POST-PROCESSING OVERLAYS
========================================================= */
.crt-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  opacity: 0.08;
  background: repeating-linear-gradient(
    0deg,
    rgba(0, 0, 0, 0.5) 0px,
    rgba(0, 0, 0, 0.5) 1px,
    transparent 1px,
    transparent 3px
  );
}

.vignette-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 51;
  box-shadow: inset 0 0 120px 40px rgba(0, 0, 0, 0.7);
}

@media (max-width: 768px) {
  #hud {
    padding: 10px 14px;
  }
  .hud-stage {
    min-width: auto;
  }
  .stage-name {
    font-size: 14px;
  }
  .title-card {
    padding: 28px 24px;
  }
  .controls-guide {
    grid-template-columns: 1fr;
    gap: 6px;
  }
}
