/* ========================= It's Dinner Time — styles ======================= */

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

/* 100dvh is the *visible* viewport. Plain 100% includes the strip hiding behind
   a phone's address bar, which pushes the bottom of the game off the screen. */
html, body {
  margin: 0;
  height: 100%;
  height: 100dvh;
  overflow: hidden;
  font-family: "Baloo 2", system-ui, "Segoe UI", sans-serif;
  user-select: none;
  -webkit-user-select: none;
  /* The viewport meta says user-scalable=no, but phones have ignored that for
     years. touch-action is what actually stops double-tap-to-zoom. */
  touch-action: manipulation;
}

#game {
  position: fixed;
  inset: 0;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: radial-gradient(130% 90% at 50% 0%, #fff3dd 0%, #ffe1b8 45%, #ffd0a8 100%);
  transition: background 0.5s ease;
}

/* --------------------------------- HUD ----------------------------------- */

#hud {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  /* The 🚪 button used to hold the right-hand end with a margin-left:auto.
     With it gone the four chips spread across the bar themselves, so the
     timer still anchors the left and the level the right. */
  justify-content: space-between;
  gap: clamp(6px, 2.2vw, 20px);
  flex-wrap: wrap;
  padding:
    calc(clamp(6px, 2vw, 14px) + env(safe-area-inset-top, 0px))
    calc(clamp(8px, 2vw, 16px) + env(safe-area-inset-right, 0px))
    clamp(6px, 2vw, 14px)
    calc(clamp(8px, 2vw, 16px) + env(safe-area-inset-left, 0px));
}

.hud-item { flex: 0 0 auto; text-align: center; }

#timer-num {
  font-size: clamp(28px, 7vw, 46px);
  font-weight: 800;
  line-height: 1;
  color: #b8341f;
}

/* The last few seconds go red and pulse. */
#timer-num.low { color: #e10046; animation: pulse 0.6s ease-in-out infinite; }
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.18); }
}

/* A wrong guess just burned seconds — the whole timer flinches red. */
#timer.penalty { animation: penaltyFlash 0.5s ease; }
@keyframes penaltyFlash {
  0%, 100% { transform: translateX(0); filter: none; }
  25% { transform: translateX(-5px); filter: drop-shadow(0 0 6px #e10046); }
  50% { transform: translateX(5px); }
  75% { transform: translateX(-3px); }
}

.mini-bar {
  width: clamp(64px, 18vw, 110px);
  height: 10px;
  margin-top: 4px;
  border-radius: 99px;
  background: rgba(184, 52, 31, 0.2);
  overflow: hidden;
}

.mini-bar > div {
  width: 100%;
  height: 100%;
  border-radius: 99px;
  background: linear-gradient(90deg, #ffb347, #e0402f);
  transform-origin: left center;
  transition: transform 0.15s linear;
}

#timer-num.low ~ .mini-bar > div { background: #e10046; }

.stat-label {
  font-size: clamp(13px, 3.2vw, 19px);
  font-weight: 700;
  color: #6b3a24;
  white-space: nowrap;
}

.stat-label b { color: #b8341f; font-size: 1.15em; }

/* The level number pops on every clock, same as the score — this selector has
   to name both, or ui._bump() adds a class that matches no rule and the chip
   climbs in dead silence. */
#score-num.bump,
#level-num.bump { display: inline-block; animation: bump 0.3s ease; }
@keyframes bump {
  0% { transform: scale(1); }
  50% { transform: scale(1.6); color: #ff9500; }
  100% { transform: scale(1); }
}

/* -------------------------------- Stage ---------------------------------- */

/* min-height:0 is required, or the grid refuses to shrink inside the flex
   column and the answers get pushed off the bottom of a short screen. */
#stage {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  gap: clamp(4px, 1.5vw, 12px);
  padding:
    clamp(4px, 1.5vw, 12px)
    calc(clamp(8px, 2.5vw, 20px) + env(safe-area-inset-right, 0px))
    clamp(4px, 1.5vw, 10px)
    calc(clamp(8px, 2.5vw, 20px) + env(safe-area-inset-left, 0px));

  /* Portrait: the list sits across the top as two rows of three. */
  grid-template-columns: 1fr;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "list"
    "hint"
    "clock"
    "answers";
}

/* --------------------------- The list of six ------------------------------ */

#checklist-wrap { grid-area: list; min-width: 0; }

#list-title {
  font-size: clamp(12px, 3vw, 16px);
  font-weight: 800;
  color: #8a5a3a;
  margin-bottom: 4px;
  text-align: center;
}

#checklist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(4px, 1.2vw, 10px);
}

.chk {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  padding: clamp(3px, 0.9vw, 7px) clamp(4px, 1.2vw, 10px);
  background: rgba(255, 255, 255, 0.75);
  border: 2px solid #f0c98c;
  border-radius: 12px;
  animation: chkIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
}

@keyframes chkIn {
  from { transform: translateY(-14px) scale(0.7); opacity: 0; }
}

.chk-mark { font-size: clamp(11px, 2.8vw, 15px); line-height: 1; }

.chk-word {
  font-size: clamp(12px, 3.1vw, 17px);
  font-weight: 800;
  letter-spacing: 0.5px;
  color: #6b3a24;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The clock you're on right now. */
.chk.current {
  background: #fff6de;
  border-color: #ff9500;
  box-shadow: 0 0 0 3px rgba(255, 170, 40, 0.25);
}
.chk.current .chk-word { color: #b8341f; }

/* Read it! */
.chk.done { background: #eaffe9; border-color: #63c76e; }
.chk.done .chk-word { color: #2f9d4e; text-decoration: line-through; opacity: 0.8; }

/* ------------------------------- The hint -------------------------------- */

#hint {
  grid-area: hint;
  text-align: center;
  font-size: clamp(13px, 3.3vw, 19px);
  font-weight: 700;
  color: #8a4a2a;
  min-height: 1.2em;
  padding: 0 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* -------------------------------- The clock ------------------------------- */

#clock-wrap {
  grid-area: clock;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0;
  min-width: 0;
}

/* The viewBox keeps the drawing circular no matter what shape this element
   ends up — extra space just becomes margin around the dial. */
#clock {
  width: min(clamp(180px, 52vmin, 340px), 100%);
  height: 100%;
  max-height: clamp(180px, 52vmin, 340px);
}

#clock-wrap.pop-in #clock { animation: clockPop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); }
@keyframes clockPop {
  0% { transform: scale(0.55) rotate(-8deg); opacity: 0; }
  70% { transform: scale(1.06) rotate(2deg); opacity: 1; }
  100% { transform: scale(1) rotate(0deg); opacity: 1; }
}

/* The clock's parts, drawn by clock.js. The hour hand is warm red and chunky,
   the minute hand cool blue and slim — two more ways to tell them apart. */
.clock-rim { fill: #b5651d; stroke: #8a4a14; stroke-width: 2; }
.clock-face { fill: #fffdf4; }
.clock-tick { stroke: #c9a26e; stroke-width: 1.4; stroke-linecap: round; }
.clock-tick.major { stroke: #8a5a3a; stroke-width: 3.6; }

.clock-num {
  font-family: "Baloo 2", system-ui, "Segoe UI", sans-serif;
  font-size: 19px;
  font-weight: 800;
  fill: #6b3a24;
}

.hand { stroke-linecap: round; }
.hand.hour { stroke: #b8341f; stroke-width: 10; }
.hand.minute { stroke: #2f6bd8; stroke-width: 5.5; }
.clock-cap { fill: #6b3a24; }

/* ------------------------------ The answers ------------------------------- */

#qa {
  grid-area: answers;
  display: flex;
  justify-content: center;
  min-width: 0;
}

#answers {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(6px, 1.8vw, 14px);
  width: min(460px, 100%);
}

.answer-btn {
  font-family: inherit;
  font-size: clamp(20px, 5.5vw, 34px);
  font-weight: 800;
  /* Tabular-ish spacing so 3:05 and 11:55 fill their buttons alike. */
  font-variant-numeric: tabular-nums;
  color: #fff;
  background: linear-gradient(180deg, #ff9d5c, #e0722f);
  border: none;
  border-radius: 18px;
  padding: clamp(8px, 2.2vw, 16px);
  cursor: pointer;
  box-shadow: 0 6px 0 #b5531d, 0 8px 16px rgba(0, 0, 0, 0.2);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
  touch-action: manipulation;
}

.answer-btn:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 #b5531d, 0 4px 8px rgba(0, 0, 0, 0.2);
}

.answer-btn:disabled { opacity: 0.6; cursor: default; }

/* A wrong pick grays out and STAYS out — you can't tap it twice. */
.answer-btn.wrong {
  background: linear-gradient(180deg, #b0b8c0, #8a929c);
  box-shadow: 0 6px 0 #6a727c, 0 8px 16px rgba(0, 0, 0, 0.2);
}

/* The right one turns green so you can see what you got. */
.answer-btn.right {
  background: linear-gradient(180deg, #7be06a, #2f9d4e);
  box-shadow: 0 6px 0 #257a3c, 0 8px 16px rgba(0, 0, 0, 0.2);
  opacity: 1;
}

.answer-btn.shake { animation: shake 0.35s ease; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-8px); }
  40% { transform: translateX(8px); }
  60% { transform: translateX(-6px); }
  80% { transform: translateX(6px); }
}

/* ----------------------------- The dinner table ---------------------------- */

#table {
  flex: 0 0 auto;
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(8px, 3vw, 24px);
  height: clamp(52px, 11vh, 88px);
  padding-bottom: calc(4px + env(safe-area-inset-bottom, 0px));
  pointer-events: none;
}

/* #plate-wrap is in here for its font-size, not for a glyph of its own: the
   food sitting on the plate is sized in em, so the box around it has to be the
   one carrying the plate's size. */
#kid, #plate, #plate-wrap {
  font-size: clamp(34px, 9vw, 60px);
  line-height: 1;
  filter: drop-shadow(0 4px 4px rgba(0, 0, 0, 0.2));
}

/* The plate and whatever's been won onto it, stacked in one place so the food
   sits ON the plate instead of pushing it sideways. */
#plate-wrap { position: relative; filter: none; }

/* Food you've actually won, sitting there until the next round. It's pinned
   over the middle of the plate and can't catch taps. */
#plate-food {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* --slot is which piece of dinner this is, so the pie and the grapes sit beside
   each other rather than one hiding the other. */
.plate-item {
  position: absolute;
  left: 50%;
  top: 34%;
  font-size: 0.52em;
  line-height: 1;
  transform: translate(calc(-50% + (var(--slot, 0) - 0.5) * 0.62em), -50%);
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.28));
  animation: plateLand 0.34s cubic-bezier(0.34, 1.7, 0.64, 1);
}

@keyframes plateLand {
  0% { opacity: 0; transform: translate(calc(-50% + (var(--slot, 0) - 0.5) * 0.62em), -140%) scale(1.5); }
  100% { opacity: 1; }
}

#plate.plate-bump { animation: plateBump 0.4s cubic-bezier(0.34, 1.7, 0.64, 1); }
@keyframes plateBump {
  0% { transform: scale(1); }
  50% { transform: scale(1.28) rotate(-6deg); }
  100% { transform: scale(1); }
}

/* The goblin waits right off the edge of the screen — this is the title card
   and the dinner celebration, the only times he isn't part of the game. */
#goblin-box {
  position: absolute;
  right: clamp(4px, 2vw, 24px);
  bottom: calc(2px + env(safe-area-inset-bottom, 0px));
  transform: translateX(140%);
  transition: transform 0.5s cubic-bezier(0.34, 1.3, 0.64, 1);
}

/* While a clock is up he's on the table, and --creep says how far in: 0 leaves
   a sliver of him at the edge, 1 puts him on the plate. The game sets it from
   the timer every frame, so the slow springy slide above would lag behind by
   half a second — under .lurking it's the short linear one the timer bar uses. */
#goblin-box.lurking {
  transform: translateX(calc(78% * (1 - var(--creep, 0))));
  transition: transform 0.12s linear;
}

/* Declared after .lurking on purpose: same specificity, so source order is what
   makes him arrive properly at game over instead of staying wherever he crept. */
#goblin-box.arrive {
  transform: translateX(0);
  transition: transform 0.5s cubic-bezier(0.34, 1.3, 0.64, 1);
}

/* --grow is his whole body's scale — every gobbled mouthful raises it. */
#goblin {
  position: relative;
  font-size: clamp(44px, 12vw, 80px);
  line-height: 1;
  transform: scale(var(--grow, 1));
  transform-origin: bottom center;
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
  filter: drop-shadow(0 6px 6px rgba(0, 0, 0, 0.3));
}

/* Rocking side to side while dinner flies in. */
#goblin.gobbling { animation: goblinChomp 0.5s ease-in-out infinite; }
@keyframes goblinChomp {
  0%, 100% { transform: scale(var(--grow, 1)) rotate(0deg); }
  25% { transform: scale(calc(var(--grow, 1) * 1.05)) rotate(-8deg); }
  75% { transform: scale(calc(var(--grow, 1) * 1.05)) rotate(8deg); }
}

/* The pop of an actual mouthful going down. Declared after .gobbling so it
   wins while both classes are on. */
#goblin.nom { animation: goblinNom 0.3s ease; }
@keyframes goblinNom {
  50% { transform: scale(calc(var(--grow, 1) * 1.18)) translateY(3px); }
}

/* The invisible box the gross food flies into — roughly his mouth. */
#goblin-mouth {
  position: absolute;
  left: 25%;
  bottom: 18%;
  width: 50%;
  height: 30%;
}

/* Food (good or gross) in mid-air on its way to a mouth or a plate. The
   duration comes from the game's timings, set inline. */
.flier {
  position: fixed;
  z-index: 50;
  font-size: clamp(34px, 9vw, 60px);
  transform: translate(0, 0);
  transition-property: transform, opacity;
  transition-timing-function: cubic-bezier(0.5, -0.2, 0.7, 1), ease;
  pointer-events: none;
  margin-left: -0.5em;
  margin-top: -0.5em;
  filter: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.25));
}

/* ------------------------------ The banner ------------------------------- */

#banner {
  position: fixed;
  left: 50%;
  top: 22%;
  z-index: 50;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.4);
  padding: clamp(10px, 2.6vw, 18px) clamp(16px, 5vw, 34px);
  max-width: 92vw;
  text-align: center;
  font-size: clamp(17px, 4.6vw, 30px);
  font-weight: 800;
  color: #fff;
  background: linear-gradient(180deg, #ff7a4a, #e0402f);
  border: 4px solid #fff;
  border-radius: 22px;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
}

#banner.show {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
  animation: bannerIn 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

#banner.show.win { background: linear-gradient(180deg, #7be06a, #2f9d4e); }
#banner.show.lose { background: linear-gradient(180deg, #8a6a52, #5a3a28); }
/* "It just got harder" — the same purple Spaghetti Words uses for its speed-up,
   so the two sibling games agree on what that news looks like. */
#banner.show.level { background: linear-gradient(180deg, #c77dff, #6a1fb0); }

@keyframes bannerIn {
  0% { transform: translate(-50%, -50%) scale(0.3) rotate(-6deg); opacity: 0; }
  60% { transform: translate(-50%, -50%) scale(1.12) rotate(2deg); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1) rotate(0deg); opacity: 1; }
}

/* ------------------------------- FX canvas -------------------------------- */

#fx {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 40;
}

/* -------------------------------- Overlays -------------------------------- */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(70, 30, 20, 0.45);
  backdrop-filter: blur(3px);
  overflow-y: auto;
}

.overlay.show { display: flex; }

.card-box {
  background: #fff;
  border-radius: 28px;
  border: 6px solid #f0a93c;
  box-shadow: 0 16px 0 rgba(190, 120, 40, 0.28), 0 24px 40px rgba(0, 0, 0, 0.3);
  padding: clamp(20px, 5vw, 40px);
  max-width: 470px;
  width: 100%;
  text-align: center;
  animation: cardIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes cardIn {
  from { transform: scale(0.6) translateY(30px); opacity: 0; }
}

.card-emoji {
  font-size: clamp(46px, 12vw, 72px);
  line-height: 1;
  margin-bottom: 6px;
}

.card-box h1 {
  margin: 6px 0 12px;
  font-size: clamp(28px, 7.5vw, 46px);
  font-weight: 800;
  color: #e0402f;
  letter-spacing: 1px;
}

.overlay.lose .card-box h1 { color: #7a4a2a; }

.card-box p {
  margin: 8px 0;
  font-size: clamp(15px, 3.6vw, 19px);
  font-weight: 500;
  color: #5a3a2a;
}

.card-box p.small { font-size: clamp(13px, 3vw, 16px); color: #8a7060; }

.card-box .new-best {
  font-weight: 800;
  color: #ff9500;
  font-size: clamp(17px, 4.2vw, 22px);
}

.big-btn {
  margin-top: 18px;
  font-family: inherit;
  font-size: clamp(19px, 4.8vw, 27px);
  font-weight: 800;
  color: #fff;
  background: linear-gradient(180deg, #ff7a4a, #e0402f);
  border: none;
  border-radius: 99px;
  padding: 14px 32px;
  cursor: pointer;
  box-shadow: 0 6px 0 #a82a1c, 0 10px 18px rgba(0, 0, 0, 0.25);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
  touch-action: manipulation;
}

.big-btn:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 #a82a1c, 0 4px 10px rgba(0, 0, 0, 0.25);
}

/* ============================ Wide screens ================================ */

/* Landscape phones, tablets and desktop: the list becomes a rail down the left
   as six stacked rows, and the clock gets the whole rest of the screen.
   min-aspect-ratio rather than orientation, so a squarish window keeps the
   safer stacked layout. */
@media (min-aspect-ratio: 1 / 1) {
  #stage {
    grid-template-columns: clamp(96px, 22vw, 200px) 1fr;
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "list hint"
      "list clock"
      "list answers";
    column-gap: clamp(8px, 2vw, 20px);
  }

  #checklist { grid-template-columns: minmax(0, 1fr); }
  #list-title { text-align: left; }
  .chk { justify-content: flex-start; }
}

/* ============================== Small phones ============================== */

@media (max-width: 430px) {
  #hud { gap: 5px; }
  #timer-num { font-size: clamp(24px, 6.5vw, 34px); }
  .mini-bar { width: clamp(52px, 15vw, 78px); height: 8px; }
  .stat-label { font-size: 11px; }
  /* Three stats is still a lot of phone. The level chip loses its word and
     keeps its number — 🔥 12 says everything it needs to. */
  .level-word { display: none; }
  .chk-word { font-size: 12px; letter-spacing: 0.3px; }
  #hint { font-size: 13px; }
  .answer-btn { font-size: clamp(18px, 5vw, 26px); border-radius: 14px; }
}

/* Phone held sideways: there's plenty of width and almost no height, so the
   clock has to be sized by height instead, and the furniture gives way. */
@media (max-height: 560px) {
  #hud {
    padding-top: calc(4px + env(safe-area-inset-top, 0px));
    padding-bottom: 4px;
    gap: 8px;
  }
  #timer-num { font-size: 26px; }
  .mini-bar { height: 7px; margin-top: 2px; }
  .level-word { display: none; }
  /* The round-and-rung line is the one thing there's no height for. The HUD
     level chip and the level-up banner still carry it here. */
  #list-title { display: none; }
  .chk { padding: 2px 6px; border-width: 2px; border-radius: 9px; }
  .chk-word { font-size: 12px; }
  #hint { font-size: 12px; }
  #clock { max-height: clamp(120px, 44vh, 240px); }
  .answer-btn { font-size: clamp(16px, 4.5vh, 24px); padding: 6px; border-radius: 12px; }
  #table { height: clamp(40px, 10vh, 60px); }
  #kid, #plate, #plate-wrap { font-size: clamp(26px, 8vh, 44px); }
  #goblin { font-size: clamp(34px, 11vh, 60px); }
}

/* ========================= Gentler on the eyes ============================ */

@media (prefers-reduced-motion: reduce) {
  #timer-num.low,
  #timer.penalty,
  .chk,
  .answer-btn.shake,
  #clock-wrap.pop-in #clock,
  #plate.plate-bump,
  #goblin.gobbling,
  #goblin.nom,
  #banner.show,
  .plate-item,
  .card-box { animation: none; }
  .mini-bar > div { transition: none; }
  .flier { transition: none; }
  #goblin-box { transition: none; }

  /* A goblin who slid in smoothly was one thing; a goblin who jumps a notch
     every frame is another. Here he just sits at the table where you can see
     him, and the timer does its own warning. This has to override the transform
     rather than --creep, because --creep is set inline and inline always wins. */
  #goblin-box.lurking { transform: translateX(40%); }
}
