/* Knock Down — the field, the strip beside it, and the help rows.

   Everything that is not specific to this game — the bars, the buttons, the
   readout, the stage, the dialogs, the seven colours — is in
   css/games/arcade.css, which Bubble Pop and Stack Up load too. If a rule in
   here would also be right for one of those, it is in the wrong file. */

/* The Balls box in the top bar. Three digits and the arrows, where the run
   number beside it wants seven. */
.kd-balls { width: 5rem; font-variant-numeric: tabular-nums; }

/* The board and the strip beside it.

   The field is 240 units across and 320 tall — three by four, portrait, which
   is the shape this game has had since 1976 and the shape it has to be. A wide
   field makes the paddle a formality. So on a wide window there is room going
   spare at the sides, and the strip goes there rather than eating the height
   the board wants. On a narrow one it drops underneath. */
/* The page is exactly the window, not at least the window.
   
   arcade.css gives .Master min-height:100dvh, which lets it GROW when a
   child wants more room. That was fine while the tallest thing in this row
   was the board. It stopped being fine when the score moved into the rail:
   the rail's content got taller than the board, a stretch row takes the
   height of its tallest item, and with nothing capping the column the whole
   page grew and pushed the footer off the bottom -- 679 pixels of page in a
   640 pixel window.

   A fixed height caps it. The shell is then exactly what is left over,
   .kd-play may shrink because its min-height is 0, and the rail scrolls
   inside itself because it already says overflow-y:auto -- which never had
   anything to do, because its height was never constrained. */
.knock-down-page .Master {
  height: 100dvh;
}

.kd-play {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 10px;
  align-items: stretch;
}

/* The board, and only as wide as a three-by-four board needs to be.

   arcade.css pins the canvas to all four sides of its stage, which is right
   for Bubble Pop and Stack Up. Here it is not: the field is 240 by 320 and
   Stage letterboxes it into whatever it is given, so on a laptop the canvas
   was 1034 pixels wide to draw a board 440 wide, and the other 600 were empty
   stage. The board was fine. It was just marooned.

   So the canvas is taken out of that pinning and given the field's own shape.
   As a flex item it is stretched to the full height, aspect-ratio works the
   width back out from that, and justify-content puts it in the middle. The
   canvas is then almost exactly the size of the board, which is also a real
   saving: it is a third of the pixels to clear and repaint, sixty times a
   second, on the oldest machine anybody plays this on.

   max-width is the other half of it. On a window that is wider than it is
   tall the height wins; on a narrow one the width has to, or the board is
   drawn off the side. */
/* The frame goes on the board, not on the room it sits in.

   .ar-stage draws the border, the rounded corners and the background, which is
   right when the canvas fills it. Now that the canvas is only as wide as the
   board, that border was a big empty box with a small board floating in the
   middle of it. Handing the frame to the canvas turns the same pixels into
   something that looks like a cabinet. */
.kd-stage {
  flex: 1;
  min-width: 0;
  border-color: transparent;
  background: none;
}

.kd-stage canvas {
  border: 1px solid var(--rule-strong);
  border-radius: 12px;
  background: var(--ground);
}

.kd-stage canvas {
  /* As wide as a three-by-four board needs to be, and no wider.

     arcade.css pins the canvas to all four sides of its stage, which is right
     for Bubble Pop and Stack Up. Here it was not: the field is 240 by 320, so
     Stage letterboxed it into a canvas 1034 pixels wide to draw a board 443
     wide, and the other 590 were empty stage either side. The board was fine.
     It was marooned.

     So the height is taken from the stage and the width is worked back from
     the field's own shape. The percentage is the part worth explaining,
     because the top of arcade.css says in as many words that height:100% on
     this canvas quietly does nothing — and it is right, for the case it is
     describing. A percentage height resolves against the parent's height
     PROPERTY, and .ar-stage is a flex item whose height property stays auto.
     An absolutely positioned child is the exception: its percentages resolve
     against the containing block's padding BOX, which is a real measured
     height whatever the property says. Hence position:absolute here, and hence
     this working where the same line in the shared file would not.

     Two other ways of writing this both loop, and loop invisibly. A canvas's
     intrinsic width is its width ATTRIBUTE, and Stage writes that attribute
     from the width the browser just gave it — so anything that lets the canvas
     be sized by its own content feeds last frame's answer back in. Laying it
     out as a flex item does that. So does leaving the width to shrink-to-fit
     with only `left` set, which is how this was written second: it came out
     1034 by 1379 and pushed the paddle off the bottom of the page.

     max-width is for a window wider than it is tall. It wins over the aspect
     ratio, and since the height is pinned the canvas simply ends up shorter
     than three by four — at which point Stage letterboxes the board inside it
     exactly as it always did, and the picture is still right. */
  position: absolute;
  top: 0;
  left: 50%;
  right: auto;
  bottom: auto;
  transform: translateX(-50%);
  width: auto;
  height: 100%;
  max-width: 100%;
  aspect-ratio: 3 / 4;
}

.kd-side {
  flex: 0 0 12.5rem;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 10px 12px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--surface);
  overflow-y: auto;
}

.kd-side__title {
  margin: 8px 0 0;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.kd-side__level {
  margin: 2px 0 6px;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--accent);
}

.kd-side__hint {
  margin: 10px 0 0;
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--ink-muted);
}

/* ------------------------------------------------------------ what is in hand

   One chip per paddle power, with the seconds left on it. The colour is set
   from powers.js by main.js, so a capsule and the chip it turned into are
   always the same colour without the two lists having to be kept in step by
   hand. */

.kd-powers {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 2px 0 0;
}

.kd-power {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  border: 1px solid var(--kd-power-colour, var(--rule-strong));
  border-left: 5px solid var(--kd-power-colour, var(--rule-strong));
  border-radius: 7px;
  background: var(--surface-alt, var(--surface));
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* The bad one is the only one that is allowed to shout, and it shouts in
   italics as well as in colour — the whole argument for that is at the top of
   js/games/knockDown/powers.js. */
.kd-power--bad {
  font-style: italic;
  font-weight: 700;
}


/* ----------------------------------------------------------- the help rows

   A small canvas of the real brick, drawn by the game's own drawBrick, beside
   what it does. bubblePop.html builds its specials list the same way and for
   the same reason: a screenshot of a brick is out of date the first time
   anybody changes a brick. */

.kd-help {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 10px 0 0;
}

.kd-help__row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--rule);
}

.kd-help__row canvas {
  flex: 0 0 auto;
  /* Nudged down to sit on the first line of text rather than above it. */
  margin-top: 2px;
}

.kd-help__row b {
  display: block;
  color: var(--ink);
}

.kd-help__row span {
  display: block;
  font-size: 0.9rem;
  line-height: 1.4;
  color: var(--ink-muted);
}

/* The help dialog carries two of these lists and a fair amount of prose, so it
   is allowed to be wider than the shared 34rem and to scroll inside itself
   rather than growing past the bottom of a laptop screen. */
.knock-down-page #help-dialog {
  width: min(40rem, calc(100vw - 32px));
  max-height: min(46rem, calc(100vh - 48px));
  overflow-y: auto;
}


/* ------------------------------------------------------------ narrow windows

   Below this the strip has nowhere sensible to be beside the board, so it goes
   under it and lies down: the level name and the powers on one line, the hints
   gone entirely. They are hints, and a hint is the first thing that can be
   spared when the board is the thing somebody came for. */

@media (max-width: 720px) {
  /* Reverse, so the numbers end up ABOVE the board. A sliver of score
     across the top is what a phone game looks like, and it is also the
     only place it can go: under the board on a tall screen it sits below
     the fold with the paddle. The markup is left alone -- the board is
     what the page is for, and it stays first for a screen reader and for
     the tab order. */
  .kd-play {
    flex-direction: column-reverse;
  }

  .kd-side {
    flex: 0 0 auto;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 12px;
    overflow: visible;
  }

  /* The In hand block is its own box on a wide window; lying down it has to
     become part of the same line as everything else, or the chips wrap under
     a heading that is no longer above them. */
  #powers-block {
    display: flex;
    align-items: baseline;
    gap: 4px 10px;
  }

  .kd-side__title { margin: 0; }
  .kd-side__level { margin: 0; }
  .kd-side__hint { display: none; }
}

/* A short window has already lost its bars to the shared stylesheet; the strip
   is the next thing that has to go, because the board has a floor of 19rem and
   below that the page starts to scroll. */
@media (max-height: 560px) {
  .kd-side__hint { display: none; }
  .kd-side { flex-basis: 10rem; }
}


/* ======================================================================
   THE NUMBERS, IN THE RAIL

   .ar-readout is a wrapping row everywhere else on the site. In the rail it
   is a column, because the rail is 12.5rem wide and a row would wrap into a
   ragged two-and-a-bit lines that shift every time the score gains a digit.
   ====================================================================== */

.kd-side .ar-readout {
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  padding: 0;
  margin-bottom: 2px;
}

.kd-side .ar-readout__item {
  justify-content: space-between;
  width: 100%;
}

/* Coins are not part of this run the way the score is -- they carry over --
   so they sit a little apart from the numbers that reset. */
.kd-coins {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px solid var(--rule);
}

.kd-coins b { color: var(--warn); }


/* ---------------------------------------------------------- the shop, shut */

.kd-shop__purse b { color: var(--warn); font-size: 1.1rem; }


/* ==================================================================
   A NARROW WINDOW KEEPS THE BOARD AND DROPS THE REST

   This is the rule the whole thing was built for. The field is three by
   four and takes its WIDTH from its height, so on a narrow window every
   row of chrome above the board costs width as well -- roughly three
   quarters of a pixel across for every pixel down. Two rows of controls
   is not a tidiness problem there. It is why the board came out three
   inches wide on a Chromebook.

   So the setup bar goes. Everything on it -- the version, the balls, the
   run number -- is either on the front door or reachable from More, and
   a phone has no room to carry a second copy of a thing you touch once
   a run. Change the version is in the More menu for exactly this.
   ================================================================== */

@media (max-width: 720px) {
  .ar-bar--setup { display: none; }

  /* The arrow keys on screen are for a trackpad somebody cannot get on
     with. A touch screen drags the paddle, so they are two more targets
     in the way of the one that matters. */
  .ar-bar--play #move-left,
  .ar-bar--play #move-right { display: none; }

  /* What is left is one row, and it stops looking like a panel. */
  .ar-bar--play {
    border: 0;
    padding: 0;
    background: none;
    gap: 6px;
  }

  .ar-bar--play button {
    padding: 6px 10px;
    font-size: 0.85rem;
  }

  /* Full Screen is the one button on this row a phone actually wants, so
     it stops being the afterthought pushed to the right and sits with
     the others. */
  .ar-fs { margin-left: 0; }

  .arcade-page .Master > section.ar-shell {
    gap: 6px;
    padding: 6px 8px 8px;
  }
}


/* The rail lies down as a sliver on a narrow window, so the numbers that
   stack in a column beside the board read across the top instead. */
@media (max-width: 720px) {
  .kd-side .ar-readout {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 2px 12px;
  }

  .kd-side .ar-readout__item { width: auto; }

  .kd-coins {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }
}


/* ======================================================================
   THE WALL EDITOR

   knockDown-editor.html. Kept in this stylesheet rather than its own
   because it is Knock Down's own tool and shares the brick colours, the
   rail and the hint type with the game itself.
   ====================================================================== */

.kd-ed {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.kd-ed__board {
  flex: 1;
  min-width: 0;
  display: flex;
  justify-content: center;
  padding: 14px;
  border: 1px solid var(--rule-strong);
  border-radius: 12px;
  background: var(--ground);
  overflow: auto;
}

/* The wall, at fifteen across. The column count is written by the script
   from WALL.cols, because that is what the game deals -- a number typed
   here would be a second opinion about the width of the board. */
.kd-ed__grid {
  display: grid;
  gap: 1px;
}

/* A div, not a button. Holding a button down and dragging across a row of
   them is a gesture the browser reads as a dozen half-presses; the grid owns
   the pointer instead and works out which cell it is over. */
.kd-ed__cell {
  display: block;
  cursor: crosshair;
  line-height: 0;
  outline-offset: -1px;
  /* Or the pointer gets captured by a cell mid-stroke and the grid stops
     hearing about it. */
  touch-action: none;
}

.kd-ed__cell:hover { outline: 1px solid var(--accent); }

/* An empty cell still has to be a target you can hit, so it keeps the box
   a brick would have had and shows it faintly. */
.kd-ed__cell canvas {
  display: block;
  background: color-mix(in srgb, var(--rule) 25%, transparent);
}


/* ------------------------------------------------------------- the paint box */

.kd-ed__palette {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.kd-ed__paint {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 5px;
  border: 1px solid var(--rule);
  border-radius: 7px;
  background: var(--ground);
  color: var(--ink-muted);
  font-size: 0.72rem;
  cursor: pointer;
  line-height: 1;
}

.kd-ed__paint canvas { display: block; }

.kd-ed__paint[aria-pressed="true"] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  color: var(--ink);
}


/* ------------------------------------------------------------------ the rail */

.kd-ed__side {
  flex: 0 0 21rem;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--surface);
  max-height: 100%;
  overflow-y: auto;
}

.kd-ed__star {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 5px;
}

.kd-ed__star select { flex: 1; min-width: 0; }
.kd-ed__value { width: 6rem; }

.kd-ed__suffix {
  font-size: 0.75rem;
  color: var(--ink-faint);
}

.kd-ed__save {
  display: flex;
  gap: 6px;
  margin-bottom: 4px;
}

.kd-ed__save button { flex: 1; padding: 7px 10px; }

.kd-ed__out {
  width: 100%;
  height: 11rem;
  margin: 4px 0 6px;
  padding: 7px 9px;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--ground);
  color: var(--ink-muted);
  font-family: Consolas, 'Courier New', monospace;
  font-size: 0.72rem;
  line-height: 1.35;
  resize: vertical;
}


/* --------------------------------------------------------------- what it says

   Four voices, and they are not the same thing. `bad` is a level that
   cannot work. `warn` is one that might not. `ok` is a count. `gate` is the
   thing this tool cannot answer and is handing to the checker. */

.kd-ed__note {
  margin: 0 0 4px;
  padding-left: 9px;
  border-left: 3px solid var(--rule);
  font-size: 0.8rem;
  line-height: 1.35;
  color: var(--ink-muted);
}

.kd-ed__note.is-bad { border-left-color: var(--danger); color: var(--danger); }
.kd-ed__note.is-warn { border-left-color: var(--warn); }
.kd-ed__note.is-ok { border-left-color: var(--ok); }

.kd-ed__note.is-gate {
  border-left-color: var(--accent);
  color: var(--ink);
  font-weight: 600;
}


@media (max-width: 900px) {
  .kd-ed { flex-direction: column; }
  .kd-ed__side { flex: 0 0 auto; width: 100%; max-height: none; }
}


/* ======================================================================
   HANDHELD MODE

   css/games/handheld.css lays the shell out; these are Knock Down's own
   parts of it. The numbers live in the rail, not in a line over the board,
   so the rail is not marked .hh-side (which a phone takes away altogether):
   on a phone it is already lying down over the board (the narrow-window
   rules above), and handheld.css turns its numbers into the one line.
   ====================================================================== */

/* Out of the way while a screen before play is up, like everything else. */
.hh-app:has(.ar-screen:not([hidden])) .kd-side { display: none; }

/* The parked paddle buttons (knockDown.html says why). If they come back,
   they join the dock as three more of its buttons. */
.hh-dock .kd-moves:not([hidden]) { display: contents; }

/* A phone: the numbers are one line. The level's name is on its card and
   flashes across the wall as it starts; the coins are on the first screen and
   the tally. Both cost the line a row. What is in hand stays -- it is the
   game. */
@media (pointer: coarse) and (max-width: 720px) {
  .hh-app .kd-side {
    padding: 4px 6px;
    gap: 4px 10px;
  }

  .hh-app .kd-side__title,
  .hh-app .kd-side__level,
  .hh-app .kd-coins { display: none; }

  .hh-app .kd-side .ar-readout { width: 100%; }
  .hh-app .kd-side .ar-readout__item { width: auto; }
}

/* The board's frame is the board's own shape, as big as it fits and in the
   middle. The rule at the top of this file takes the canvas's height from the
   stage and works the width back from three by four, which is right on a
   window that is wider than the board -- every computer. On a phone held
   upright the WIDTH runs out first, max-width clips the canvas, and the frame
   came out far taller than the board, which floated half way down a tall
   empty box. Measuring the stage as a container gives the canvas both
   answers at once: as wide as either the stage's width or three quarters of
   its height allows, whichever is less, and the height from the shape. The
   width is stated, never left to the canvas, so nothing Stage writes back can
   feed into it -- the loop the note at the top warns about. */
.hh-app .kd-stage { container-type: size; }

.hh-app .kd-stage canvas {
  top: 50%;
  width: min(100cqw, 75cqh);
  height: auto;
  max-width: none;
  transform: translate(-50%, -50%);
}
