/* micropolisJS. Adapted by Graeme McCutcheon from Micropolis.
 *
 * This code is released under the GNU GPL v3, with some additional terms.
 * Please see the files LICENSE and COPYING for details. Alternatively,
 * consult http://micropolisjs.graememcc.co.uk/LICENSE and
 * http://micropolisjs.graememcc.co.uk/COPYING
 *
 * The name/term "MICROPOLIS" is a registered trademark of Micropolis (https://www.micropolis.com) GmbH
 * (Micropolis Corporation, the "licensor") and is licensed here to the authors/publishers of the "Micropolis"
 * city simulation game and its source code (the project or "licensee(s)") as a courtesy of the owner.
 *
 */

@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,300,600,300italic,400italic);

* {
  padding: 0;
  margin: 0;
}

@font-face {
  font-family: 'Chunk';
  font-style: normal;
  font-weight: 400;
  src: local('ChunkFive'), url(chunk.woff) format('woff');
}

body {
  background-image: url('../images/dirtbg.png');
}

button, input[type="submit"] {
  width: 140px;
  height: 19px;
  border-radius: 3px;
  cursor: pointer;
  border: none;
  font-family: sans-serif;
}

footer {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0px;
  height: 5em;
  background-color: darkslategray;
}

/* ---------------------------------------------------------------------------
   The HUD bar (v0.89.6)

   This was the fork's banner: 35px of darkslategray under a 45-degree white
   stripe, carrying the Chunk slab-serif title and nothing else. The stripe is
   gone -- it was decoration on the one strip of the page that had no room for
   any -- and the bar now carries the readouts a player actually watches.

   That is what let Town Info and the Demand panel leave the left-hand column,
   which is a layout with several paragraphs of source comments about being
   short of vertical space (panel.js's shrinkColumnToFit, the SHORT_BREAKPOINT
   work). The title keeps the Chunk face; everything else in here is sans, since
   a slab serif at 11px is unreadable.
   --------------------------------------------------------------------------- */
header {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 38px;
  padding: 0 10px;
  box-sizing: border-box;
  background-color: darkslategray;
  font-family: sans-serif;
}

#hudBrand {
  flex: 0 0 auto;
}

header h1 {
  margin: 0;
  font-family: 'Chunk', serif;
  font-size: 19px;
  font-weight: normal;
  line-height: 1;
  white-space: nowrap;
}

/* The readouts. A row of label-over-value pairs -- the label is what it is, the value
   is what it says -- so the eye can find "funds" without reading the number first. */
/* :not(.initialHidden) on all three of the HUD's game-time sections, for the reason
   this file documents at #mobileDrawerToggles: an ID selector outranks .initialHidden's
   class selector whatever the source order, so a bare "display: flex" here would show
   an empty readout over the splash screen before a city exists. */
#hudStats:not(.initialHidden) {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  overflow: hidden;
}

.hudStat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.25;
  white-space: nowrap;
}

.hudLabel {
  color: rgba(255, 255, 255, 0.55);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.hudValue {
  color: white;
  font-size: 13px;
}

/* The city's own name, which is the one thing here that is a name rather than a
   number -- set on one line at readout size rather than as a label/value pair. */
.hudCity {
  justify-content: center;
  padding-right: 4px;
  border-right: 1px solid rgba(255, 255, 255, 0.22);
  color: mintcream;
  font-size: 14px;
  font-weight: bold;
}

#hudDemand:not(.initialHidden) {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}

/* Pushed to the right-hand end, so the controls are together and the readouts are
   together rather than interleaved. */
#hudSpeed:not(.initialHidden) {
  flex: 0 0 auto;
  display: flex;
  gap: 3px;
  margin-left: auto;
}

/* Zoom, on the map. Bottom-left, which keeps it clear of the Tools panel on the right,
   the notification bar along the bottom centre and the FPS readout in the corner. */
#mapControls:not(.initialHidden) {
  position: absolute;
  left: 8px;
  bottom: 8px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

#mapControls button {
  width: 26px;
  height: 26px;
  padding: 0;
  background-color: rgba(47, 79, 79, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 3px;
  color: white;
  font-family: sans-serif;
  font-size: 15px;
  line-height: 1;
}

#mapControls button:hover {
  background-color: darkslategray;
}

/* Plain labels rather than the collapsible headers the Tools panel has: the Menu
   panel's eleven items fit at once in three groups, so there is nothing to collapse. */
.menuGroupHeader {
  width: 140px;
  margin-top: 6px;
  padding-bottom: 2px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.18);
  color: darkslategray;
  font-family: sans-serif;
  font-size: 10px;
  text-align: left;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex: 0 0 auto;
}

.menuGroupHeader:first-child {
  margin-top: 0;
}

/* :not(.initialHidden) rather than the shared .inlineblock class -- .inlineblock is
   declared later in this file than .initialHidden, so at equal specificity it would
   silently win and defeat the hiding before the game reveals this element */
#mobileDrawerToggles:not(.initialHidden) {
  display: inline-block;
  vertical-align: middle;
}

.mobileDrawerToggle {
  display: none;
  width: auto;
  height: auto;
  padding: 6px 10px;
  margin-left: 10px;
  background-color: darkslategray;
  color: white;
  border: 1px solid white;
  font-family: sans-serif;
  font-size: 13px;
}

#cancelToolToggle {
  background-color: darkred;
}

body.showInfoDrawer #infoDrawerToggle, body.showToolsDrawer #toolsDrawerToggle {
  background-color: cadetblue;
}

main {
  position: absolute;
  top: 0;
  bottom: 26px;
  width: 100%;
  overflow: hidden;
}

#MicropolisCanvas {
  /* One-finger drag pans the map (see inputStatus.js) -- without this the browser's own
     touch scroll/zoom gestures fight with it */
  touch-action: none;
}

nav a, nav a:link, nav a:visited, nav a:hover, footer a, footer a:link, footer a:visited, footer a:hover,
#aboutHeader a, #aboutHeader a:link, #aboutHeader a:visited, #aboutHeader a:hover,
#licenseHeader a, #licenseHeader a:link, #licenseHeader a:visited, #licenseHeader a:hover {
  text-decoration: none;
  color: white;
}

footer a, footer a:link, footer a:visited, footer a:hover {
  text-decoration: underline;
  margin-left: 5px;
}

nav li {
  display: inline;
}

.alignCenter {
  text-align: center;
}

.awaitGeneration, .hidden, .initialHidden, .imageData {
  display: none;
}

.bad {
  background-color: red;
  color: yellow;
}

.block {
  display: block;
}

.bold {
  font-weight: bold;
}

.border-bottom {
  border-bottom: 1px solid black;
}

.budgetRight {
   margin-left: 7px
}

.cancel, #debugRequest, #pauseRequest {
  background-color: darkslategray;
  color: white;
}

.centred, #tooSmallInner {
  position: absolute;
  top: 50%;
  left: 50%;
  border: 1px solid black;
  width: 400px;
  transform: translate(-50%, -50%);
}

.chunk {
  font-family: 'Chunk', serif;
  font-weight: normal;
}

.dialogOK {
  color: white;
  background-color: green;
}

.difficulty {
  margin-left: 10px;
}

.elided {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fontlarge {
  font-size: 36px;
}

.good {
  background-color: LightGreen;
  color: black;
}

.helpPointer {
  cursor: help;
}

.inline {
  display: inline;
}

.inlineblock {
  display: inline-block;
}

.left {
  float: left;
}

.leftedge {
  left: 50px;
}

.loadSave, .saveHeader {
  background-color: cadetblue;
  color: white;
}

.loadSave:disabled {
  background-color: darkgray;
  color: silver;
  cursor: not-allowed;
}

.margin10 {
  margin: 10px 0;
}

.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  border: 1px solid black;
  transform: translate(-50%, -50%);
  z-index: 20;
  background-color: white;
  width: 500px;
}

.modal header {
  height: 18px;
  /* panel.js grabs any window's <header> as its drag handle -- these already needed
     one for the title bar, so this is the only CSS change needed to make every
     .modal window draggable alongside it. */
  cursor: move;
  user-select: none;
}

.mintcream, .neutral {
  background-color: mintcream;
}

.neutral {
  color: black;
}

.open {
  font-family: 'Open Sans', sans-serif;
}

.opinion, .statistics {
  font-size: 12px;
}

.opinionList dd {
  font-style: italic;
}

.padding10 {
  padding: 10px;
}

.panelHeader {
  height: 18px;
  padding: 4px 6px;
  background-color: darkslategray;
  color: white;
  font-family: sans-serif;
  font-size: 12px;
  cursor: move;
  user-select: none;
}

/* Bottom-right resize grip, added by panel.js for any Panel constructed with
   opts.resizable -- a striped square in the style of a native textarea resize
   handle. Positioned relative to the panel itself, which is always position:
   fixed while floated (desktop-only, same as dragging -- see MOBILE_BREAKPOINT
   in panel.js) or position:relative below as a fallback so it's never left
   positioning against some unrelated ancestor. */
.panelResizeHandle {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  background-image: linear-gradient(135deg,
    transparent 0 40%, rgba(0, 0, 0, 0.35) 40% 50%,
    transparent 50% 60%, rgba(0, 0, 0, 0.35) 60% 70%,
    transparent 70% 80%, rgba(0, 0, 0, 0.35) 80% 90%,
    transparent 90% 100%);
}

.pointer {
  cursor: pointer;
}

.queryItem, .statisticsItem {
  display: inline-block;
  width: 200px;
}

.queryList dt {
  font-weight: 600;
}

.right {
  float: right;
}

.rightedge {
  right: 50px;
}

.row button {
  display: inline-block;
}

/* Load/Export/Delete on the save lists: three to a row now, so the global 140px
   button would run the Load Game dialog well past its 500px. */
.saveRowButton {
  width: 70px;
}

.selected {
  font-weight: bold;
  border: 1px solid black;
}

/* .selected above would otherwise reset border-left-width to 1px and take the tool's
   colour stripe off the one button where it matters most -- the one you have in hand.
   The stripe stays; the selected state is carried by the fill and the outline instead. */
.toolButton.selected {
  border: 1px solid black;
  border-left-width: 3px;
  background-color: darkslategray;
  color: white;
}

.toolButton.selected .toolCost,
.toolButton.selected .toolKey {
  color: #c9d6d2;
}

.toolButton.selected .toolGlyph {
  color: white;
}

.semibold {
  font-weight: 600px;
}

/* Scenario mode's objective/deadline readout, appended inside Town Info (see
   index.html and scenarioController.js). Ruled off and slightly smaller so it reads
   as a second section rather than more of the city stats above it -- those describe
   the city, these describe what's being asked of it. Only ever visible when a
   scenario is actually running; scenarioController.js unhides it. */
#scenarioInfo {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px solid rgba(0, 0, 0, 0.25);
  font-size: 11px;
  line-height: 1.35;
}

#scenarioName {
  font-size: 12px;
}

#scenarioDeadline {
  opacity: 0.75;
}

.shadow, .controlShadow {
  -ms-box-shadow: 10px 0px 35px 0px rgba(31,28,31, 0.8);
  -webkit-box-shadow: 10px 0px 35px 0px rgba(31,28,31, 0.8);
  -moz-box-shadow: 10px 0px 35px 0px rgba(31,28,31, 0.8);
  box-shadow: 10px 0px 35px 0px rgba(31,28,31, 0.8);
}

.statisticsItem {
  display: inline-block;
  width: 200px;
}

.statisticsRight {
  display: inline-block;
  width: 150px;
}

/* The Main Menu button at the foot of the Menu panel. Ruled off and set apart from
   the buttons above it because it is the only one that throws the city away -- the
   rest of that list opens a window or nudges the view. Deliberately not red: this
   is a normal thing to want to do, and it asks for confirmation before it acts. */
.quitButton {
  margin-top: 8px;
  border-top: 1px solid rgba(0, 0, 0, 0.25);
  padding-top: 8px;
  height: auto;
  background-color: darkslategray;
  color: white;
}

/* flex: 0 0 auto on both button classes so a squeezed panel scrolls its buttons
   rather than crushing them -- Tools and Menu are both flex columns whose body the
   column layout is allowed to shrink (see shrinkColumnToFit in panel.js). */
.miscButton {
  flex: 0 0 auto;
}

/* The line under the Tools panel header: the tool currently in hand, or why the last
   click did nothing (see game.js's handleTool). */
#toolInfo {
  flex: 0 0 auto;
  padding: 3px 6px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  color: darkslategray;
  font-family: sans-serif;
  font-size: 11px;
}

/* ---------------------------------------------------------------------------
   Tool buttons (v0.89.6)

   Until this version every tool button was filled with its own data-colour, which
   is the colour of the placement outline (mouseBox.js) and was never meant to be a
   background. Thirty-four of them in one column read as a paint chart, and the
   colour carried no information a player could use -- Police is darkblue and Port
   is dodgerblue for no reason either of them could tell you.

   The colour is now a 3px stripe down the left edge: still present, still the
   outline colour it matches, no longer the first thing you see. The row reads
   icon / label / cost instead, which is what you are actually scanning for.
   --------------------------------------------------------------------------- */
.toolButton {
  width: 100%;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 5px;
  box-sizing: border-box;
  color: black;
  background-color: white;
  font-size: 12px;
  text-align: left;
  border: 1px solid transparent;
  border-left-width: 3px;
  border-radius: 2px;
}

.toolButton:hover:not(.selected) {
  background-color: #eef4f2;
  border-color: rgba(0, 0, 0, 0.35);
}

/* The tile the building is actually made of, cropped straight out of images/tiles.png
   with background-position (see toolbar.js). Deliberately not routed through TileSet,
   which turns every tile into its own Image via canvas.toDataURL at ~5ms each -- the
   reason startup takes as long as it does. This costs nothing: the sheet is already
   being downloaded for the map. */
.toolIcon {
  flex: 0 0 auto;
  width: 16px;
  height: 16px;
  background-image: url('../images/tiles.png');
  background-repeat: no-repeat;
  image-rendering: pixelated;
}

/* Query and Bulldoze have no tile of their own -- they are not things you place. */
.toolGlyph {
  background-image: none;
  font-size: 13px;
  line-height: 16px;
  text-align: center;
  color: darkslategray;
}

.toolLabel {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.toolCost {
  flex: 0 0 auto;
  color: #5a6a66;
  font-size: 11px;
}

/* The keyboard shortcut, for the nine tools that have one. */
.toolKey {
  flex: 0 0 auto;
  min-width: 13px;
  padding: 0 2px;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 2px;
  font-size: 9px;
  line-height: 12px;
  text-align: center;
  color: #5a6a66;
}

/* Priced out. Left clickable on purpose -- the tool itself says "insufficient funds"
   in the notification bar, which tells a player *why* nothing happened; a disabled
   button would just swallow the click. */
.toolButton.unaffordable {
  opacity: 0.4;
}

.toolButton.unaffordable .toolCost {
  color: darkred;
}

/* Query and Bulldoze, above the groups and outside them: verbs rather than buildings,
   reached for between placing things rather than instead of placing them. Two across,
   since neither needs a cost column. */
.toolPinned {
  display: flex;
  gap: 4px;
  width: 100%;
  margin-bottom: 6px;
}

.toolPinned .toolButton {
  width: auto;
  flex: 1 1 0;
  min-width: 0;
}

/* Two buttons sharing one panel width is tight, and neither cost is worth the room it
   takes: Query is free and Bulldoze is $1. Without this both labels ellipsise to
   "Q..." and "B." and the pinned row stops naming its own tools. */
.toolPinned .toolCost {
  display: none;
}

.toolGroup {
  width: 100%;
}

.toolGroupHeader {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  height: 20px;
  padding: 0 4px;
  box-sizing: border-box;
  background-color: transparent;
  border: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.18);
  border-radius: 0;
  color: darkslategray;
  font-family: sans-serif;
  font-size: 11px;
  text-align: left;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.toolGroupHeader:hover {
  background-color: rgba(0, 0, 0, 0.06);
}

.toolGroupArrow {
  flex: 0 0 auto;
  font-size: 9px;
}

.toolGroupLabel {
  flex: 1 1 auto;
}

.toolGroupCount {
  flex: 0 0 auto;
  opacity: 0.55;
}

.toolGroupBody {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 3px 0 7px;
}

/* .hidden is also a single class, and it is declared earlier in this file than the rule
   above -- so at equal specificity display:flex wins and collapsing a group sets the
   class without hiding anything. Same trap #mobileDrawerToggles documents at the top of
   the file; two classes beat one. */
.toolGroupBody.hidden {
  display: none;
}

/* Hover help, built in toolbar.js. Thirty-four buildings whose entire difference from
   one another is a number in customBuildings.js need somewhere to say what that number
   is -- before this, nothing in the game told a player what any building did. Appended
   to <body> rather than inside the panel so it can hang outside the panel's own
   scrolling box. */
#toolTooltip {
  position: fixed;
  z-index: 40;
  display: none;
  width: 190px;
  padding: 7px 9px;
  box-sizing: border-box;
  background-color: mintcream;
  border: 1px solid darkslategray;
  border-radius: 3px;
  font-family: sans-serif;
  font-size: 11px;
  line-height: 1.45;
  pointer-events: none;
}

#toolTooltip.open {
  display: block;
}

.toolTipTitle {
  font-weight: bold;
  font-size: 12px;
}

.toolTipFacts {
  color: #5a6a66;
  margin-bottom: 4px;
}

.unselected {
  font-weight: normal;
}

.white {
  color: white;
}

.width140 {
  width: 140px;
}

.z1 {
  z-index: 1;
}

.nameLicense {
  margin-top: 1em;
  margin-bottom: 0.5em;
  font-size: 10px;
  opacity: 0.55;
}

/* The OK/Cancel row, which wants the full width rather than the 230px column the
   rule below gives every other div in the form. Was `> div:nth-child(9)`, i.e. "the
   ninth thing in the form, whatever that turns out to be" -- which stopped being the
   button row the moment the Ordinances and Power contracts lines were added above it,
   and would have gone wrong again on any later addition. Addressed by its own id now. */
#budgetForm > #budgetButtons {
  align: center;
  width: 100%;
}

#budgetForm > div, #budgetForm > fieldset {
  display: inline-block;
  width: 230px;
}

#budgetForm input[type="range"] {
  max-width: 210px;
  padding: 5px;
}

#budgetReset {
  color: white;
  background-color: dodgerblue;
}

/* City ordinances (src/ordinanceWindow.js) and the neighbouring cities
   (src/neighbourWindow.js). Both windows build their own rows at open time, so there
   is nothing in index.html for these to hang off but the two list containers -- every
   class below is applied in JS. Both lists scroll rather than growing the dialog: eight
   ordinances already make a tall window, and the modal has to keep its OK button
   reachable on a short screen. */
#ordinanceList, #neighbourList {
  max-height: 340px;
  overflow-y: auto;
  margin: 6px 0;
}

.ordinanceRow, .neighbourRow {
  padding: 6px 4px;
  border-bottom: 1px solid #ddd;
  font-size: 12px;
}

.ordinanceRow:last-child, .neighbourRow:last-child {
  border-bottom: none;
}

.ordinanceLabel {
  font-weight: bold;
  margin-left: 4px;
  cursor: pointer;
}

.ordinanceCost, .neighbourRowCost {
  float: right;
  font-size: 11px;
  opacity: 0.8;
}

.ordinanceBlurb, .neighbourBlurb, .neighbourRates {
  margin: 2px 0 0 22px;
  font-size: 11px;
  font-style: italic;
  opacity: 0.75;
}

/* An ordinance that cannot be enacted right now keeps its row, greyed, with the reason
   in place of the blurb -- a policy that silently vanished from the list would be a
   worse mystery than one that says why it is unavailable. */
.ordinanceBlocked {
  opacity: 0.5;
}

#ordinanceTotal, #neighbourPower {
  padding: 6px;
  font-weight: bold;
  font-size: 12px;
  background-color: #f2f2f2;
  border-radius: 3px;
}

/* Empty except in the one situation it warns about, so it takes no room the rest of
   the time -- :empty rather than a class toggled from JS, since "is there any text in
   here" is exactly the condition. */
#neighbourWarning {
  margin-top: 4px;
  padding: 6px;
  font-size: 11px;
  color: #7a3b00;
  background-color: #fdf0d5;
  border-radius: 3px;
}

#neighbourWarning:empty {
  display: none;
}

.neighbourName {
  font-weight: bold;
}

.neighbourRelations {
  float: right;
  font-size: 11px;
  opacity: 0.8;
}

.neighbourRates {
  margin-left: 0;
}

.neighbourControls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}

.neighbourControls select {
  flex: 0 0 auto;
}

.neighbourControls input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
}

.neighbourReadout {
  font-size: 11px;
  opacity: 0.85;
}

.neighbourCooloff {
  opacity: 0.5;
}

#congratsHeader {
  background-color: limegreen;
}

/* The scrolling body shared by the two button panels: Tools (#buttons) and Menu
   (#menuButtons). Both hold a single column of fixed-width buttons that can run
   taller than the panel, so both need the same flex:1/min-height:0/overflow-y
   combination to scroll internally rather than overflowing their panel. */
#buttons, #menuButtons {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 8px;
  box-sizing: border-box;
}

/* Tools stretches its children where Menu centres its fixed-width ones: since v0.89.6
   the tool rows are full-bleed (icon left, cost right), and the group headers rule off
   the whole panel width rather than floating in the middle of it. No gap either -- the
   groups carry their own spacing, so a flex gap here would only double it. */
#buttons {
  align-items: stretch;
  gap: 0;
  padding: 8px 6px;
}

/* Sizing/position/flex-direction apply on both breakpoints -- the mobile
   drawer uses this exact box too (see body.showToolsDrawer below), just
   toggled via display instead of floated. flex-direction is meaningless
   until something actually sets display:flex, so it's harmless to declare
   here even though display itself has to stay conditionally gated below. */
#controls {
  position: absolute;
  top: 40px;
  /* 198px, up from the 172px this was when every button was a 140px-wide block of
     colour. A tool row now carries an icon, a label, a cost and sometimes a hotkey
     hint, and at 172px the longest names ("Recycling Centre", "Amusement Park")
     ellipsised -- which defeats the point of naming them. Measured against the
     longest label in customBuildings.js; check this if a longer one is ever added. */
  width: 198px;
  /* Every build tool at once still runs taller than most viewports even in groups --
     #buttons above scrolls internally past this cap rather than letting the
     panel (or the resize handle on its bottom-right corner) run off-screen. */
  max-height: calc(100vh - 80px);
  flex-direction: column;
}

/* Sized and structured to match #controls above, for the same reason: a single
   column of 140px-wide buttons (see the global "button" rule) needs 156px of
   content box, which .width140 + .padding10 never gave it -- every button used
   to sit 10px proud of this panel. 172px is #controls' own width, so the two
   button panels now read as a matched pair. Sizing/flex-direction apply on both
   breakpoints; only display is gated below. */
#miscButtons {
  width: 172px;
  max-height: calc(100vh - 80px);
  flex-direction: column;
}

/* The objective panel (was Town Info) sits directly above Menu in the same column --
   matched to its width so the stack has one edge rather than two. It has no
   fixed-width content of its own (just wrapping text), so this is purely cosmetic. */
#infobar {
  width: 172px;
}

/* Only the flex switch needs :not(.initialHidden) and breakpoint-gating: an ID
   selector outranks .initialHidden's class selector whatever the source order, so a
   bare display:flex would defeat the hiding before the game starts -- and would also
   outrank the max-width:768px drawer rules once .initialHidden is gone, even on a
   phone. Nothing else above competes with either, so it applies unconditionally. */
@media (min-width: 769px) and (min-height: 601px) {
  #controls:not(.initialHidden),
  #miscButtons:not(.initialHidden) {
    display: flex;
  }
}

/* The frame-rate readout. This was #debug: a 280px box parked at a hard-coded
   top: 580px, outside the Panel system, holding both this and the button that opened
   the cheat menu -- which is how a frame counter came to be a sub-feature of a cheat
   menu. The button is in the Menu panel now (as "Sandbox") and this is what is left:
   pinned to the bottom-right of the map, still only shown when the sandbox is switched
   on in Settings. */
#fps {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: 2;
  padding: 2px 6px;
  background-color: rgba(47, 79, 79, 0.75);
  color: white;
  font-family: sans-serif;
  font-size: 11px;
  border-radius: 3px;
  pointer-events: none;
}

#difficultyLabel {
  margin-right: 5px;
}

#disasterLabel {
  display: block;
}

#evalContainer {
  font-size: 14px;
}

#flagsTable {
  text-align: center;
  padding: 5px;
  margin: 0 auto;
  border: 1px solid black;
}

#flagsTable td, #flagsTable th {
  padding: 0 5px;
}

/* Shared flow container for the #infobar/#miscButtons stack -- each panel's
   position derives from the flex column instead of hand-copied top offsets,
   so only this rule (and its media-query overrides below) needs to change if
   the stack's height budget changes. The demand graph was a third panel in this
   flow until v0.89.6 and is part of the HUD bar now, which is most of why this
   column stopped being short of room. */
#leftStack {
  position: absolute;
  top: 40px;
  display: flex;
  flex-direction: column;
  gap: 40px;
}

#loadingBanner[data-hasscript=false] {
  display: none;
}

/* The city history graph (src/graphWindow.js). Same construction as #mapWindow below --
   read that block first; everything here follows the same reasoning, including the
   inline-style hiding in index.html. Wider than the map window and shorter, because a
   time series wants width where a 120x100 map wants square. */
#graphWindow {
  width: 470px;
  height: 430px;
  min-width: 300px;
  min-height: 280px;
  display: flex;
  flex-direction: column;
}

#graphContainer {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: 8px;
}

#graphRange {
  flex: 0 0 auto;
}

.graphRangeButton {
  width: auto;
  padding: 2px 12px;
  margin: 0 3px;
  font-size: 12px;
}

.graphRangeSelected {
  background-color: darkslateblue;
  color: white;
}

/* The one row that grows. min-height:0 for the same reason #mapCanvasContainer needs
   it: a flex item defaults to min-height:auto and would otherwise refuse to shrink,
   pushing the legend and OK button out of the bottom of a resized window. */
#graphCanvasContainer {
  flex: 1 1 auto;
  min-height: 0;
  background-color: white;
  border: 1px solid #555;
}

#graphCanvas {
  display: block;
}

/* The legend is also the series toggles -- one list, not two to keep in step. */
#graphLegend {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  font-size: 11px;
}

.graphLegendItem {
  display: flex;
  align-items: center;
  gap: 3px;
  cursor: pointer;
  user-select: none;
}

.graphLegendItem input {
  margin: 0;
}

.graphSwatch {
  width: 10px;
  height: 10px;
  border: 1px solid rgba(0, 0, 0, 0.3);
  flex: 0 0 auto;
}

.graphSeriesValue {
  font-weight: 600;
}

#graphAxisNote {
  flex: 0 0 auto;
  margin: 0;
  font-size: 10px;
  font-style: italic;
  color: #555;
}

#graphButtons {
  flex: 0 0 auto;
}

/* The speed control. Lived in the Menu panel until v0.89.6, where changing speed meant
   scrolling past a list of windows to reach it; it sits in the HUD bar now, beside the
   clock it governs. Settings carried a second, three-way copy of this that could not
   pause and never stayed in sync with it -- that one is gone. */
.speedButton {
  width: auto;
  min-width: 26px;
  height: 20px;
  padding: 0 5px;
  background-color: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 3px;
  color: white;
  font-family: sans-serif;
  font-size: 11px;
  line-height: 1;
}

.speedButton:hover {
  background-color: rgba(255, 255, 255, 0.26);
}

.speedSelected {
  background-color: mintcream;
  border-color: mintcream;
  color: darkslategray;
  font-weight: bold;
}

/* The city data map (src/mapWindow.js). Overrides .modal's shared 500px width with a
   size derived from the map instead: 120x100 tiles at 3px a tile is 360x300, which is
   the smallest the overlays are actually readable at, plus room for the chrome around
   it. Resizable from there -- see the Panel entry in game.js -- so the whole thing is a
   flex column with exactly one growable row (#mapCanvasContainer below).

   Unconditionally display:flex, with the hiding done by an inline style in index.html
   instead of the .hidden class -- see the comment on the element there for why that
   swap is required rather than cosmetic. */
#mapWindow {
  width: 400px;
  height: 500px;
  min-width: 260px;
  min-height: 320px;
  display: flex;
  flex-direction: column;
}

#mapContainer {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: 8px;
}

#mapControls {
  flex: 0 0 auto;
}

#mapOverlaySelect {
  margin-left: 6px;
  max-width: 220px;
}

/* The one row that grows and shrinks with the window. min-height:0 because a flex item
   defaults to min-height:auto, which refuses to shrink below its content and would let
   the canvas push the legend and OK button out of the bottom of a shrunk window. */
#mapCanvasContainer {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #101014;
  border: 1px solid #555;
}

/* pixelated for the same reason mapWindow.js disables imageSmoothingEnabled: the map is
   a grid of samples blitted up from one pixel per tile, and interpolating it invents
   gradients between blocks that the simulation never computed. Both are needed -- the
   canvas is scaled by its own backing-store size AND, on a fractional scale, by the
   browser's layout of it. */
#mapCanvas {
  display: block;
  image-rendering: pixelated;
  cursor: pointer;
}

#mapLegend {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
}

#mapLegendBar {
  flex: 1 1 auto;
  height: 10px;
  border: 1px solid #555;
}

#mapDescription {
  flex: 0 0 auto;
  margin: 0;
  font-size: 11px;
  font-style: italic;
  min-height: 28px;
}

#mapButtons {
  flex: 0 0 auto;
}

/* The disaster camera. Was .rightedge (right: 50px) at top: 364px, which put it
   directly on top of the Tools panel -- the two have always collided, and widening
   #controls to 198px in v0.89.6 made it obvious. Moved to the left instead, under the
   Menu panel's column and clear of both the notification bar (bottom centre) and the
   zoom buttons (bottom left). It is not a Panel: it has no <header> to drag by, and
   giving it one is a bigger change than this pass wants. */
#monstertv {
  position: absolute;
  left: 50px;
  top: 364px;
  width: 200px;
  background-color: red;
}

#monsterTVForm {
  margin-top: 5px;
}

#nameForm {
  font-size: 18px;
  width: 150px;
}

#notifications {
  position: absolute;
  bottom: 65px;
  left: 50%;
  border: 1px solid black;
  width: 400px;
  height: 19px;
  transform: translateX(-50%);
}

#opaque {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  opacity: .70;
  filter: Alpha(Opacity=70);
  background-color: gray;
  z-index: 10;
}

#playit {
  background-color: green;
  color: white;
  font-size: 18px;
  height: 24px;
}

/* #rciPanel -- the demand graph's own floating, draggable, resizable panel, third in
   the left-hand column -- is gone as of v0.89.6, along with the media query that
   revealed it. The graph is in the HUD bar; see #RCIContainer just below, and the
   rewritten src/rci.js. */

/* The demand graph's container: a fixed slot in the HUD bar now, rather than the body
   of a panel. rci.js measures this box on every draw and sizes its canvas to match, so
   the graph's shape is decided here and nowhere else. 58x26 fits three 7px bars with
   5px gaps between them, plus the row of R/C/I letters underneath. */
#RCIContainer {
  width: 58px;
  height: 26px;
}

#screenshotLink, #screenshotLink:link, #screenshotLink:visited, #screenshotLink:hover {
  text-decoration: none;
  color: dodgerblue;
}

#splash {
  position: absolute;
  width: 540px;
  height: 380px;
}

#splashButton {
  margin-bottom: 10px;
}

#splashButtons {
  position: absolute;
  left: 10px;
  top: 105px;
}

#splashButtonContainer {
  position: absolute;
  top: 90px;
  left: 390px;
}

#splashContainer {
  position: absolute;
  top: 90px;
  left: 20px;
}

#splashGenerate {
  background-color: dodgerBlue;
  color: white
}

#splashPlay {
  background-color: lightgreen;
}

#start {
  display: none;
  text-align: center;
  font-size: 18px;
}

#loadList {
  display: none;
  width: 500px;
  text-align: center;
}

#scenarioList {
  display: none;
  width: 500px;
  text-align: center;
}

#fullScenarioList {
  display: none;
  width: 700px;
  text-align: center;
}

#fullScenarioTableEl .scenarioBlurb {
  text-align: left;
  font-size: 13px;
}

#fullScenarioTableEl .scenarioYear {
  font-weight: normal;
  color: dimgray;
}

#statisticsList, .queryList {
  width: 400px;
  margin: 0 auto;
  padding: 0 110px;
}

#tooSmall {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: none;
  z-index: 200;
}

#tooSmallInner {
  max-width: 90vw;
  box-sizing: border-box;
}

/* Desktop mouse users don't need this -- shown only at mobile widths, see the
   max-width:768px override below */
#touchNotice {
  display: none;
  font-size: 13px;
  font-style: italic;
  color: dimgray;
}

#tvContainer {
  width: 177px;
  height: 128px;
  margin: 0 auto;
}

/* Clears the header, which is a sibling rather than an ancestor, so this has to be a
   length rather than something that follows automatically. It used to be a hardcoded
   guess per breakpoint, and every guess was wrong somewhere: the header's real height
   moves with the breakpoint, with whether the mobile drawer toggles are showing, and
   with whether the title row wraps. At phone width the guess was ~24px short, so the
   game canvas was painted over the bottom half of the Menu/Tools buttons -- and a tap
   there landed on the map, placing a building instead of opening the drawer.
   --headerHeight is the header's actual measured height, republished on resize and
   after webfonts land (see syncHeaderHeight in src/micropolis.js); the fallback is
   only for the instant before that first runs. */
#wrapper {
  position: absolute;
  top: var(--headerHeight, 55px);
  left: 0px;
  right: 0px;
  bottom: 0px;
}


/* Miscellaneous buttons */

#budgetRequest, #budgetHeader {
  background-color: dodgerblue;
  color: white;
}

#disasterRequest, #disasterHeader {
  background-color: red;
  color: yellow;
}

#evalRequest, #evalHeader {
  background-color: forestgreen;
  color: white;
}

#mapRequest, #mapHeader {
  background-color: darkcyan;
  color: white;
}

#graphRequest, #graphHeader {
  background-color: darkslateblue;
  color: white;
}

.screenshotHeader, #screenshotRequest {
  background-color: tomato;
  color: white;
}

#settingsHeader, #settingsRequest {
  background-color: #663399;
  color: white;
}

#ordinanceHeader, #ordinanceRequest {
  background-color: #8b5a2b;
  color: white;
}

#neighbourHeader, #neighbourRequest {
  background-color: #2f6f6f;
  color: white;
}

/* The sixteen per-ID tool-button colour rules that used to live here are gone as of
   v0.89.6 -- #residentialButton { background-color: lime } and its fifteen siblings.
   Every tool's colour now comes from one place, src/toolRegistry.js (and, for the
   custom buildings, customBuildings.js), and is applied by src/toolbar.js as the
   button's left stripe. See the "Tool buttons" block earlier in this file.

   #queryHeader survives them: that is the Query *window's* title bar, which has always
   shared the Query tool's cyan and still should. It only sat in that rule because the
   two happened to want the same colour. */
#queryHeader {
  background-color: cyan;
}

@media (max-height: 742px) {
  /* `header { height: 15px }` used to live here, squeezing the old banner down to a
     sliver on a short window -- which it could afford to be, holding nothing but a
     title. It cannot now: the bar carries the funds, the date, the population and the
     speed control, and at 15px all of that was clipped to slivers of text. The bar
     sizes to its own contents at every height and #wrapper follows its measured height
     (see syncHeaderHeight in micropolis.js), so there is nothing to override here. */

  .border-bottom {
    border: none;
  }

  .fontlarge {
      font-size: 16px;
  }

  #author {
    display: none;
  }

  #notifications {
    bottom: unset;
    border: none;
    top: 593px;
  }

  /* The #wrapper override that used to live here (top: 35px, to match this block's
     shorter header) is gone: #wrapper now clears the header's real measured height,
     which already accounts for this. */
}

@media (max-height: 702px) {
  #controls {
    top: 30px;
  }

  #leftStack {
    top: 30px;
    gap: 30px;
  }

  #monstertv {
    top: 324px;
  }

  #notifications {
    top: 563px;
  }
}

@media (max-height: 672px) {
  #controls {
    top: 20px;
  }

  #leftStack {
    top: 20px;
    gap: 20px;
  }

  #monstertv {
    top: 304px;
  }

  #notifications {
    top: 533px;
  }
}

@media (max-height: 642px) {
  .controlShadow {
    -ms-box-shadow: unset;
    -webkit-box-shadow: unset;
    -moz-box-shadow: unset;
    box-shadow: unset;
  }

  #controls {
    top: 10px;
  }

  #leftStack {
    top: 10px;
    gap: 10px;
  }

  #monstertv {
    top: 274px;
  }

  #notifications {
    top: 503px;
  }
}

@media (max-height: 612px) {
  #controls {
    top: 0px;
  }

  #leftStack {
    top: 0px;
    gap: 0px;
  }

  #monstertv {
    top: 220px;
  }

  #notifications {
    top: 473px;
  }
}

@media (max-height: 400px) {
  #tooSmall[data-hasscript=true] {
    display: block;
  }
}

/* THE COMPACT (DRAWER) LAYOUT.

   A comma in a media query is OR, so this fires when the viewport is small in EITHER
   dimension. It must stay the exact complement of the "(min-width: 769px) and
   (min-height: 601px)" queries above and of roomyMediaQuery in panel.js -- negating
   an OR needs AND, which is why those two are and-joined. If the three ever drift,
   there is a band of viewport sizes where both layouts apply at once, or neither.

   Width was the only test until 2026-09-09. A phone in landscape (~932x430) clears
   768px easily and then has nowhere near the ~609px of height the left-hand column
   needs, so it took the floating-panel path and stacked three panels on top of each
   other -- see the measurements in panel.js. #tooSmall did not catch it either; that
   only appears below 400px.

   Only the rules that decide WHICH LAYOUT runs live in here. The width-driven
   cosmetics (header trimming, 94vw dialog caps, the splash reflow) stay in the
   max-width block further down, because a 932px-wide landscape phone doesn't need a
   header trimmed to fit 375px. */
@media (max-width: 768px), (max-height: 600px) {
  /* The left (info/menu) and right (tools) panel stacks no longer fit next to each
     other and the canvas -- they become toggleable overlay drawers instead of
     always-on. #monstertv and the FPS readout aren't included: both already manage their own
     show/hide independently of game start (inline style via jQuery .show()/.hide()), so
     folding them into the drawer classes here would just fight that. */
  #infobar, #miscButtons, #controls {
    display: none;
  }

  /* :not(.hidden) since v0.89.6 -- #infobar is the scenario objective now and is
     hidden outright in a freeform city, so opening the drawer must not conjure an
     empty panel above the menu. */
  body.showInfoDrawer #infobar:not(.hidden) {
    display: block;
  }

  /* #controls is a flex column (header + a growable/scrollable body) so its resizable
     desktop layout also works as a drawer -- display: block here would silently drop
     that flex context and let the content collapse or overflow unpredictably. */
  body.showInfoDrawer #miscButtons {
    display: flex;
  }

  body.showToolsDrawer #controls {
    display: flex;
  }

  /* The left stack used to be Town Info + Menu + Demand, ~634px, taller than a
     landscape phone's whole viewport (430px) -- so without bounding it to the room it
     actually has, the bottom simply sat below the fold with nothing to scroll. It is
     down to the Menu panel (plus the objective in a scenario) since v0.89.6, so this
     matters far less than it did, but it still has to hold for a scenario in landscape.
     #controls needs no equivalent: it already caps itself at calc(100vh - 80px) and
     scrolls #buttons.

     Scoped to the drawer actually being open, not to #leftStack generally: with its
     children display:none the closed container collapses to zero width and height,
     and giving it bottom:0 unconditionally would leave a full-height invisible box
     down the left edge of the map, swallowing clicks meant for the tiles under it. */
  body.showInfoDrawer #leftStack {
    bottom: 0;
    overflow-y: auto;
  }

  /* Dragging and resizing only happen on a roomy viewport (see isRoomy in panel.js)
     -- the grip has nothing to do once a panel is a static drawer. */
  .panelResizeHandle {
    display: none;
  }

  /* The toggles that open those drawers. The #mobileDrawerToggles container is
     always inline-block once the game reveals it; these are the buttons inside it,
     which are display:none by default, so this rule is what actually makes the
     drawers reachable -- it has to move with the layout rules above, or a landscape
     phone gets hidden panels and no way to open them. */
  .mobileDrawerToggle {
    display: inline-block;
  }
}

/* Dialogs are a height problem as much as a width one, and this half was previously
   trapped in the width-only block below. A .modal is 500px wide and can be taller
   than a 430px landscape viewport, which puts its own OK/Cancel buttons off-screen
   with no way to reach them. dvh over vh because mobile browsers slide their address
   bar in and out of the viewport, which vh does not track. */
@media (max-height: 600px) {
  .centred, #tooSmallInner, .modal {
    max-height: 90vh;
    max-height: 90dvh;
    overflow-y: auto;
  }
}

/* WIDTH-ONLY COSMETICS. Everything below is about fitting ~375-412px of real phone
   width -- not about which layout runs, which the compact query above decides. */
@media (max-width: 768px) {

  /* Trimmed from the desktop defaults (10px/20px padding, 10px margin) -- the title
     plus the 3 toggle buttons (Menu/Tools/the cancel-tool button) need to fit in
     ~375-412px of real phone width. The About/GitHub links used to live here too and
     were the reason this row didn't fit even trimmed -- they've since moved down to
     the footer, next to the b0r3d.org link (see #footerLinks), which is what actually
     fixed the wrapping rather than this trimming alone. */
  .mobileDrawerToggle {
    padding: 4px 6px;
    margin-left: 4px;
    font-size: 12px;
  }

  #title {
    font-size: 16px;
    margin-left: 6px;
  }

  /* The HUD bar wraps rather than being given a phone layout of its own: the readouts
     are the same readouts, there are just more rows of them. #wrapper tracks the
     header's measured height (see syncHeaderHeight in micropolis.js, and the
     ResizeObserver there that catches the bar growing a row when a city starts), so the
     bar is free to be as tall as its contents need. */
  header {
    height: auto;
    min-height: 35px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 10px;
    padding: 5px 8px;
  }

  /* The one thing in the bar that is decoration rather than information, and the
     biggest single item in it. A player on a phone knows what they opened. */
  #hudBrand {
    display: none;
  }

  /* Second row, full width, so the readouts are not competing with the drawer
     toggles for the same line on a 375px screen. */
  #hudStats:not(.initialHidden) {
    order: 2;
    flex: 1 0 100%;
    gap: 12px;
  }

  #hudDemand:not(.initialHidden) {
    order: 3;
  }

  #hudSpeed:not(.initialHidden) {
    order: 3;
    margin-left: auto;
  }

  header .left {
    float: none;
  }

  /* No #wrapper override here any more either. This was the guess that actually bit:
     40px of clearance for a header that really measures ~64px once the drawer toggle
     buttons are in it, leaving the canvas covering their bottom halves. #wrapper
     tracks the header's measured height now, so the header is free to be as tall as
     its contents need -- including wrapping to a second row on a very narrow phone,
     which the fixed value could never have survived. */

  /* All the pre-game/dialog boxes below (.centred, .modal and their fixed-width
     variants) were sized for desktop and simply run off the edges of a phone-width
     screen -- #tooSmallInner was the one place that already used the vw-relative,
     border-box pattern that fixes this; extended here to the rest. max-height +
     overflow-y matters just as much as max-width: Budget/Settings/High Scores all
     stack their content into a single column at this width (see #budgetForm below),
     which makes them taller, not just narrower -- without a height cap a tall enough
     one pushes its own OK/Cancel buttons off-screen with no way to reach them. The
     dvh line is a progressive enhancement over vh for browsers that support it --
     real mobile browsers resize their address bar in and out of the viewport, which
     vh doesn't track but dvh does, so a dialog sized against vh can still end up
     taller than the actually-visible area. */
  .centred, #tooSmallInner, .modal {
    max-width: 94vw;
    max-height: 90vh;
    max-height: 90dvh;
    overflow-y: auto;
    box-sizing: border-box;
  }

  #statisticsList, .queryList {
    max-width: 100%;
    padding: 0 10px;
    box-sizing: border-box;
  }

  /* #splash alone has a two-column layout (map preview + buttons) built from fixed
     pixel offsets tuned for its 540px desktop width, so capping its own width isn't
     enough -- those children need to become normal flow so they actually reflow
     into the narrower box instead of sitting at their old absolute offsets. */
  #splash {
    width: 94vw;
    max-width: 94vw;
    height: auto;
    max-height: 90vh;
    overflow-y: auto;
    box-sizing: border-box;
  }

  #splashContainer {
    position: static;
    margin-top: 10px;
  }

  #splashContainer canvas {
    max-width: 100%;
    height: auto;
    display: block;
    margin: 0 auto;
  }

  #splashButtonContainer, #splashButtons {
    position: static;
  }

  #splashButtonContainer {
    margin-top: 10px;
  }

  #touchNotice {
    display: block;
  }

  #start {
    max-width: 94vw;
    box-sizing: border-box;
  }

  #loadList, #scenarioList, #fullScenarioList {
    width: 94vw;
    max-width: 94vw;
    box-sizing: border-box;
  }

  /* The Load Game and High Score tables' columns/buttons keep their desktop sizing
     rather than being redesigned to stack -- if they don't fit, the table scrolls
     horizontally inside the dialog instead of clipping. */
  #loadTableEl, #highScoreTableEl {
    max-width: 100%;
    overflow-x: auto;
    display: block;
    white-space: nowrap;
  }

  /* Fixed desktop width, same overflow problem as the dialogs above -- this is often
     the very first thing shown once a game starts (the welcome notification), so it
     matters as much as any dialog. */
  #notifications {
    max-width: 94vw;
    box-sizing: border-box;
  }
}

@media (max-width: 850px) {
  .leftedge {
    left: 20px;
  }

  .rightedge {
    right: 20px;
  }

  #notifications {
    bottom: 40px;
    left: unset;
    right: 0;
    transform: unset;
  }
}

@media (max-width: 750px) {
  .leftedge {
    left: 10px;
  }

  .rightedge {
    right: 10px;
  }
}

@media (max-width: 650px) {
  .leftedge {
    left: 0px;
  }

  .rightedge {
    right: 0px;
  }
}

@media (max-width: 320px) {
  #tooSmall[data-hasscript=true] {
    display: block;
  }
}

/* About/nag page styles */

#aboutMain, #licenseMain {
  position: relative;
  top: 50px;
  margin-bottom: 100px;
}

#aboutContainer, #licenseContainer {
  position: relative;
  left: 50%;
  border: 1px solid black;
  width: 75%;
  line-height: 1.7em;
  text-align: justify;
  transform: translate(-50%);
}

#aboutContainer p, #aboutContainer li, #aboutContainer h3, #licenseContainer p, #licenseContainer li, #licenseContainer h3 {
  margin: 10px;
}

#aboutContainer h3, #licenseContainer h3 {
  margin-top: 20px;
}

#aboutContainer ul {
  margin-left: 50px;
}

#aboutFooter, #licenseFooter {
  position: relative;
}

#appeal {
  border: 1px dotted grey;
  font-size: 12px;
  width: 50%;
  margin: auto;
  line-height: 1.5em;
  background-color: lightyellow;
}

#aboutMain a, #aboutMain a:link, #aboutMain a:visited, #aboutMain a:hover,
#licenseMain a, #licenseMain a:link, #licenseMain a:visited, #licenseMain a:hover,
#nagContainer a, #nagContainer a:link, #nagContainer a:visited, #nagContainer a:hover {
  text-decoration: none;
  color: dodgerblue;
}

#licenseContainer ol {
  margin-left: 3em;
  margin-right: 3em;
}

/* Pre refactoring below */

.info {
  width: 20%;
  text-align: centre;
}

#build {
  position: absolute;
  left: 5px;
  bottom: 5px;
}

#footer {
  height: 26px;
  box-sizing: border-box;
}

#footer #build {
  font-size: 11px;
}

#footerLinks {
  position: absolute;
  right: 5px;
  bottom: 5px;
  font-size: 11px;
}
