:root {
  --pixel-font: 'Press Start 2P', monospace;
  --bg-dark: #1a1a2e;
  --accent-gold: #ffb020;
  --accent-red: #e94f4f;
  --accent-green: #4fe985;
  --ui-bg: rgba(10, 10, 20, 0.7);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100vh;
  height: var(--app-height, 100vh);
  background: #000;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
  font-family: var(--pixel-font);
  color: #fff;
  -webkit-user-select: none;
  user-select: none;
}

/* --app-height is set by a tiny script in index.html's <head>, from
   window.visualViewport.height. Mobile browsers resize their own address
   bar/toolbar on top of the page instead of shrinking the layout viewport,
   so plain 100vh (and even 100svh on some older/WebView browsers) can end
   up taller than what's actually visible, pushing the controls panel below
   the fold. visualViewport always reflects the real visible area. */
#game-wrap {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: var(--app-height, 100vh);
  display: flex;
  flex-direction: column;
  background: var(--bg-dark);
  touch-action: none;
}

/* The screen's own area - on desktop/keyboard play this is the whole
   #game-wrap (no controls panel below eats into it). On touch devices the
   controls panel (see touch-controls.css) takes a fixed slice at the
   bottom, and #screen is sized in game.js's resize() against whatever
   space is left here - never the full window - so the panel never has to
   overlap the canvas or HUD to fit. */
#viewport-area {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* container-type: size makes cqw/cqh below always mean "% of #screen's own
   rendered width/height" - since #screen is always exactly CANVAS_W x
   CANVAS_H scaled up by the same factor (set in game.js's resize()), this
   keeps the HUD proportional to the game world at any size: huge on a
   desktop window, tiny on a letterboxed phone screen, without ever needing
   to know the actual scale factor in CSS. */
#screen {
  position: relative;
  container-type: size;
  box-shadow: 0 0 0 4px #000, 0 0 40px rgba(0,0,0,0.6);
}

#game-canvas {
  display: block;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
  background: #6ec6ff;
}

.hidden {
  display: none !important;
}

/* HUD - sizes in cqw/cqh (see the container-type note on #screen above),
   tuned so they read the same as before on a normal desktop window (roughly
   4x the canvas' native 384x216) but now shrink together with the screen on
   a small letterboxed phone view instead of staying fixed-size and
   swallowing the whole visible game area. */
#hud {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  padding: 1.15cqh 0.91cqw;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

#hud-top {
  display: flex;
  align-items: flex-start;
  gap: 0.9cqw;
  font-size: 2.2cqh;
  text-shadow: 0.2cqh 0.2cqh 0 #000;
}

#hud-health-wrap {
  background: var(--ui-bg);
  padding: 0.46cqh 0.52cqw;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.13cqw;
}

#hud-health {
  /* Exactly 5 columns - a 6th+ steak (earned past BASE_MAX_HEALTH, see
     updateHud) wraps onto a second row underneath instead of widening the
     box sideways forever. */
  display: grid;
  grid-template-columns: repeat(5, auto);
  gap: 0.13cqw;
  font-size: 7.4cqh;
  filter: drop-shadow(0.2cqh 0.2cqh 0 #000);
}

/* Once a second row exists, shrink the icons a bit so 10 of them still
   read as one tidy block instead of ballooning the whole HUD chip. */
#hud-health.many {
  font-size: 4.6cqh;
}

/* Each steak is two overlapping copies of the same emoji - see updateHud in
   game.js. .bg sits in normal flow (its size is what the grid cell/wrap
   actually sizes around) dim and gray; .fg is absolutely stacked on top,
   full color, clipped from the right down to whatever quarter-fraction of
   that steak's health remains - clipping to 0% at full health shows all of
   it, clipping more as it takes hits reveals more of the dim .bg
   underneath, reading as the steak being eaten into rather than the whole
   icon just fading. */
#hud-health .picanha-icon-wrap {
  position: relative;
  display: inline-block;
  line-height: 1;
}

#hud-health .picanha-icon {
  display: block;
}

#hud-health .picanha-icon.bg {
  opacity: 0.25;
  filter: grayscale(1);
}

#hud-health .picanha-icon.fg {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 1;
  filter: none;
}

#hud-hp-label {
  font-size: 3.05cqh;
  color: var(--accent-green);
  white-space: nowrap;
  text-align: center;
}

#hud-lives {
  font-size: 2.6cqh;
  background: var(--ui-bg);
  padding: 0.46cqh 0.52cqw;
  border-radius: 4px;
}

#hud-score {
  background: var(--ui-bg);
  padding: 0.69cqh 0.65cqw;
  border-radius: 4px;
  color: var(--accent-gold);
  font-size: 3.5cqh;
  white-space: nowrap;
  margin-left: auto;
}

/* While the boss bar is visible, it has its own margin:0 auto centering
   the gap between the health chip and the score - if #hud-score keeps its
   own margin-left:auto too, the two auto-margins split the leftover space
   three ways instead of two, pulling the bar off-center toward the left. */
#hud-top:has(#boss-bar-wrap:not(.hidden)) #hud-score {
  margin-left: 0;
}

#hud-bottom {
  display: flex;
  justify-content: flex-start;
}

#hud-weapon {
  background: var(--ui-bg);
  padding: 0.46cqh 0.52cqw;
  border-radius: 4px;
  font-size: 1.95cqh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.26cqw;
  color: #fff;
}

#weapon-switch-hint {
  text-align: center;
  color: var(--accent-gold);
}

#weapon-icon {
  image-rendering: pixelated;
  height: 23.9cqh;
  width: auto;
}

#weapon-name {
  color: var(--accent-green);
}

/* Sits in the normal #hud-top flex flow, between the lives count and the
   score (not absolutely centered over everything - that was wide enough to
   run into both the health chip and the score at once). flex:1 lets it
   soak up exactly whatever room is left between its neighbors instead of
   claiming a fixed 60% of the screen. */
#boss-bar-wrap {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 26cqw;
  /* flex:1 reserves the whole gap between the health/lives chips and the
     score, but max-width caps how wide the bar itself gets inside that
     gap - without this auto margin the leftover room past the cap just
     sat on the right (before the score), reading as left-aligned instead
     of centered between the two. */
  margin: 0 auto;
  align-self: center;
  text-align: center;
  pointer-events: none;
}

#boss-label {
  font-size: 1.5cqh;
  font-weight: normal;
  color: var(--accent-red);
  text-shadow: 0.15cqh 0.15cqh 0 #000;
  margin-bottom: 0.3cqh;
  letter-spacing: 0.1em;
}

#boss-bar-bg {
  width: 100%;
  /* Border(1px*2) + padding(1px*2) = 4px is baked into this height under the
     global box-sizing:border-box - on a short mobile #screen (portrait, the
     on-screen controls panel eating vertical space below it) 1.4cqh alone
     can shrink under that 4px floor, leaving zero (or negative, clamped to
     0) room for #boss-bar-fill to actually render any color - the whole bar
     then reads as just its own white border, looking permanently empty
     regardless of the boss's real hp. The 10px floor guarantees room for
     the fill on every screen size; harmless on desktop where 1.4cqh is
     already comfortably above it. */
  height: max(1.4cqh, 10px);
  background: rgba(0, 0, 0, 0.65);
  border: 1px solid rgba(255, 255, 255, 0.85);
  border-radius: 3px;
  box-shadow: inset 0 0.15cqh 0.3cqh rgba(0, 0, 0, 0.6);
  overflow: hidden;
  padding: 1px;
}

#boss-bar-fill {
  height: 100%;
  width: 100%;
  border-radius: 2px;
  background: linear-gradient(180deg, #ff8f7a 0%, var(--accent-red) 45%, #a52d2d 100%);
  box-shadow: 0 0 0.4cqh rgba(233, 79, 79, 0.7);
  transition: width 0.15s linear;
}

/* Overlays */
.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  background: rgba(10, 10, 20, 0.88);
  text-align: center;
  padding: 20px;
}

/* Cutscene - full-bleed video (see #cutscene-screen in index.html), not an
   .overlay since there's no dimmed canvas to center content over here, just
   the video itself filling the whole screen. object-fit: contain instead of
   cover so a video whose aspect doesn't exactly match #screen's still shows
   letterboxed instead of cropped. #boss-special-screen/-video (a mid-fight
   boss special-attack cutscene, e.g. TAXAD's - see BOSS_SPECIAL_BY_PHASE in
   game.js) share this exact look, just a separate screen/video element so
   the two can't ever collide mid-transition. */
#cutscene-screen, #boss-special-screen {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #000;
  overflow: hidden;
}

#cutscene-video, #boss-special-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.cutscene-skip-hint {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  padding: 1.3cqh 0;
  text-align: center;
  font-size: 1.7cqh;
  /* Same gold as the video's own burned-in subtitles (sampled off the
     actual caption pixels, ~#ffdc03) instead of plain white, and no
     .blink animation - static like those captions, not flashing. */
  color: #ffdc03;
  background: linear-gradient(rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0));
  text-shadow: 0.15cqh 0.15cqh 0 #000;
}

#title-screen {
  /* assets/title_banner.png fills the whole title screen, dimmed just
     enough to keep the text/logo readable over it - see assets/README.md
     for the size to make it. Nothing shows here (the flat dark background
     from .overlay above still applies) until that file actually exists. */
  background:
    linear-gradient(rgba(10, 10, 20, 0.55), rgba(10, 10, 20, 0.75)),
    url('assets/title_banner.png') center / cover no-repeat,
    rgba(10, 10, 20, 0.88);
}

.logo {
  font-size: clamp(16px, 4vw, 30px);
  color: var(--accent-gold);
  text-shadow: 4px 4px 0 #7a3b00;
  letter-spacing: 2px;
}

.logo-img {
  width: min(80%, 320px);
  image-rendering: pixelated;
  image-rendering: -moz-crisp-edges;
  image-rendering: crisp-edges;
}

/* body.touch is added by touch-controls.js only on real touch hardware
   (see its isTouchDevice() check) - the reliable "is this the mobile
   version" signal already used elsewhere in this project, not a screen-
   width media query (a resized desktop window shouldn't get this). Mobile
   only, smaller than the logo's own native width (320px), on purpose -
   leaves more of assets/title_banner.png (the puppet-master scene behind
   it) visible; on a narrow phone 80% nearly filled the whole width edge to
   edge. */
body.touch .logo-img {
  width: min(55%, 220px);
}

.image-slot {
  position: relative;
  width: min(80%, 300px);
  height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.image-slot-label {
  font-size: 9px;
  color: #888;
  letter-spacing: 1px;
}

.image-slot img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
}

/* Dialogue - SNES-RPG style: a bordered portrait box, then a bordered
   textbox below it (see startDialogue() in game.js), both using the same
   gold-trim/dark-panel look as the rest of the UI chrome. Unlike every
   other .overlay (title/gameover/stageclear/phaseN), which paints an almost
   opaque background over the canvas, a boss's pre-fight dialogue plays
   with their own arena visible behind it (the canvas is left frozen on
   that frame the moment state becomes 'dialogue' - see the BOSS_TRIGGER_X
   branch in updatePlayer()) - so this only needs a lighter dark tint on
   top for the text to stay readable, not a near-solid cover. */
.dialogue-overlay {
  background: rgba(0, 0, 0, 0.55);
  /* Tighter than .overlay's default 18px - portrait and textbox read as one
     compact unit instead of two things floating apart on the screen. */
  gap: 8px;
}

.dialogue-portrait {
  width: min(42vw, 200px);
  height: min(42vw, 200px);
  border: 3px solid var(--accent-gold);
  border-radius: 4px;
  background: var(--bg-dark);
}

#dialogue-box {
  width: min(88vw, 540px);
  min-height: 80px;
  border: 3px solid var(--accent-gold);
  border-radius: 4px;
  background: var(--bg-dark);
  padding: 10px 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  text-align: center;
}

#dialogue-name {
  color: var(--accent-gold);
  font-size: clamp(13px, 3vw, 18px);
  letter-spacing: 1px;
}

#dialogue-text {
  color: #fff;
  font-size: clamp(12px, 2.6vw, 17px);
  line-height: 1.6;
  /* Reserves room for ~3 lines so the box doesn't resize as text reveals. */
  min-height: 3.2em;
  white-space: pre-wrap;
}

#dialogue-continue {
  align-self: center;
  color: var(--accent-gold);
  font-size: clamp(12px, 2.4vw, 18px);
}

.subtitle {
  font-size: clamp(8px, 1.6vw, 12px);
  color: #fff;
  letter-spacing: 1px;
}

.prompt {
  font-size: clamp(9px, 1.8vw, 13px);
  color: var(--accent-green);
}


.version {
  position: absolute;
  bottom: 14px;
  right: 18px;
  font-size: 8px;
  color: #666;
}

.title-text {
  font-size: clamp(14px, 3vw, 24px);
  letter-spacing: 2px;
}

.title-text.danger {
  color: var(--accent-red);
}

.title-text.success {
  color: var(--accent-green);
}

/* A phase-specific stageclear message (see STAGECLEAR_MESSAGE_BY_PHASE) is
   real sentences, not a short title - smaller, wraps, and keeps the \n
   line break the JS puts between them instead of collapsing it. */
.title-text.long-message {
  font-size: clamp(13px, 2.6vw, 21px);
  line-height: 1.8;
  letter-spacing: 0.5px;
  white-space: pre-line;
  max-width: 78%;
  text-align: center;
}

.final-score {
  font-size: clamp(10px, 2vw, 14px);
  color: var(--accent-gold);
}

.love-won {
  font-size: clamp(11px, 2.2vw, 16px);
  color: #ff6b9d;
  text-shadow: 2px 2px 0 #7a1f3d;
  letter-spacing: 1px;
}

.love-won .heart {
  display: inline-block;
  animation: heartbeat 0.9s ease-in-out infinite;
}

@keyframes heartbeat {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.25); }
}

.blink {
  animation: blink 1s steps(1) infinite;
}

@keyframes blink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

.pixel-btn {
  font-family: var(--pixel-font);
  font-size: 11px;
  background: #2b2b45;
  color: #fff;
  border: 3px solid #fff;
  padding: 10px 18px;
  cursor: pointer;
  pointer-events: auto;
}

.pixel-btn:hover {
  background: var(--accent-gold);
  color: #000;
}

/* Controls screen (see #controls-screen in index.html) - one row per key,
   a small pixel-bordered badge (same visual language as .pixel-btn) on the
   left naming the key, the action spelled out to its right. */
.controls-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.controls-row {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: clamp(9px, 1.8vw, 13px);
  color: #fff;
}

.key-badge {
  flex: 0 0 auto;
  min-width: 28px;
  font-family: var(--pixel-font);
  font-size: clamp(9px, 1.8vw, 12px);
  background: #2b2b45;
  color: var(--accent-gold);
  border: 2px solid #fff;
  border-radius: 3px;
  padding: 6px 8px;
  text-align: center;
}
