/* Roboto sets the interface text; the characters themselves are always Amiri,
   loaded from ./fonts so its coverage can be read exactly. */
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
/* The type specimens use the font files in ./fonts - see SPECIMEN_FONTS in
   script.js - so no webfonts are loaded for them. */

/* Reset */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Variables */
:root {
  --bg-color: rgb(255, 255, 255);
  --text-color: rgb(20, 20, 20);
  --border-color: rgb(0, 0, 255); /* Blue border */
  --accent-color: rgb(0, 0, 255); /* Blue accent */
  --input-bg: rgb(255, 255, 255);
  --input-border: rgb(0, 0, 255); /* Blue input border */
  --title: rgb(20, 20, 20);
  --hover: rgb(210, 220, 255);
  --link: rgb(0, 0, 255);
  --muted: rgb(120, 120, 120);
  --map-land: rgb(238, 238, 238);
  --map-edge: rgb(255, 255, 255);
  --map-used: rgba(0, 0, 255, 0.4);
  --map-hot: rgb(0, 0, 255);
  /* Interface text */
  --font-main: 'Roboto', Arial, sans-serif;
  /* The characters. Amiri only: where it has no glyph the page draws a missing
     box rather than letting the browser substitute another face. */
  --font-glyph: 'Amiri', serif;
  border: 15px solid blue;
}

body.dark {
  --bg-color: rgb(20, 20, 20);
  --text-color: rgb(180, 180, 180);
  --border-color: rgb(255, 255, 255);
  --accent-color: rgb(255, 255, 255);
  --input-bg: rgb(20, 20, 20);
  --input-border: rgb(255, 255, 255);
  --title: rgb(255, 255, 255);
  --hover: rgb(0, 0, 255);
  --link: rgb(255, 255, 255);
  --muted: rgb(130, 130, 130);
  --map-land: rgb(45, 45, 45);
  --map-edge: rgb(20, 20, 20);
  --map-used: rgba(90, 120, 255, 0.55);
  --map-hot: rgb(140, 165, 255);
}

body {
  font-family: var(--font-main);
  background: var(--bg-color);
  color: var(--text-color);
  min-height: 100vh;
}

/* Container */
.container {
  width: 100%;
  margin: auto;
  padding: 20px;
}

.sitetitle {
  width: 100%;
  white-space: normal;
  word-wrap: break-word;
  overflow-wrap: break-word;
}

/* Heading */
h1 {
  float: left;
  text-align: left;
  font-weight: 600;
  color: var(--accent-color);
}

h2 {
  text-align: left;
  margin-bottom: 3px;
  font-weight: 400;
  color: var(--text-color);
  display: inline-block;
  vertical-align: baseline;
}

h3 {
  text-align: left;
  margin-bottom: 10px;
  font-weight: 400;
  color: var(--text-color);
  display: inline-block;
  vertical-align: baseline;
}

p {
  clear: both;
}

/* Dark Mode Toggle Button */
.toggle-btn {
  background: blue;
  color: white;
  border: none;
  padding: 8px 12px 6px 12px;
  font-size: 18px;
  cursor: pointer;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.3s ease, color 0.3s ease;
}

body.dark .toggle-btn {
  background: blue;
  color: white;
}

/* Top bar with toggle and about buttons */
.top-bar {
  display: flex;
  align-items: right;
  gap: 10px;
  margin-bottom: 5px;
  justify-content: flex-end;
}

/* About Toggle Button */
.about-toggle {
  background: blue;
  color: white;
  border: none;
  height: 40px;
  padding: 8px 12px;
  font-size: 18px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  margin-left: auto;
}

body.dark .about-toggle {
  background: blue;
  color: white;
}

/* Full-width About Panel */
.about-panel {
  padding-left: 40px;
  padding-right: 40px;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 0;
  overflow: hidden;
  background: blue;
  color: white;
  z-index: 1000;
  transition: height 0.4s ease, padding 0.5s ease;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.about-panel.show {
  height: 65vh;
  overflow-y: scroll;
  padding: 40px 40px;
}

.aboutLink {
  color: rgb(180, 180, 180);
  text-decoration: underline;
}

.about-inner {
  float: left;
  margin: 0 auto;
  max-width: 748px;
  padding-right: 20px;
}

.about-inner h2 {
  font-size: 24px;
  margin-bottom: 10px;
  color: white;
}

.about-inner p {
  font-size: 16px;
  line-height: 1.6;
}

.about-credit {
  font-size: 0.85em !important;
  color: rgb(180, 180, 180);
}

/* Close Button */
#about-close {
  position: absolute;
  top: 27px;
  right: 40px;
  font-size: 40px;
  padding: 0;
  background: none;
  border: none;
  color: white;
  cursor: pointer;
}

/* Filter bar: the same columns and gutter as the character grid, each control
   five columns wide */
.filter-bar {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 6px;
  margin: 10px 0;
}

.filter-bar input[type="text"],
.filter-bar select {
  grid-column: span 5;
  min-width: 0;
  padding: 6px 8px;
  font-family: inherit;
  font-size: 14px;
  border: 1px solid var(--input-border);
  background: var(--input-bg);
  color: var(--text-color);
  outline: none;
  appearance: none;
  border-radius: 0;
  padding-right: 25px;
}

.filter-bar input::placeholder {
  color: var(--text-color);
  opacity: 1;
}

.filter-bar select {
  cursor: pointer;
  background-color: var(--input-bg);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-color) 50%),
    linear-gradient(135deg, var(--text-color) 50%, transparent 50%);
  background-position:
    calc(100% - 15px) calc(50% - 3px),
    calc(100% - 10px) calc(50% - 3px);
  background-repeat: no-repeat;
  background-size: 5px 5px;
}

/* A filter that is narrowing the list looks chosen, like a selected character
   or contextual form. An empty search box and "All …" keep the plain box. */
.filter-bar input[type="text"].chosen,
.filter-bar select.chosen {
  background-color: rgb(0, 0, 255);
  border-color: rgb(0, 0, 255);
  color: rgb(255, 255, 255);
}

.filter-bar select.chosen {
  background-image:
    linear-gradient(45deg, transparent 50%, rgb(255, 255, 255) 50%),
    linear-gradient(135deg, rgb(255, 255, 255) 50%, transparent 50%);
}

.filter-bar input[type="text"].chosen::placeholder {
  color: rgb(255, 255, 255);
}

/* The dropdown itself is drawn by the system, so keep its rows readable */
.filter-bar select.chosen option {
  background-color: var(--input-bg);
  color: var(--text-color);
}

/* Ask the font for a contextual shape directly, rather than putting the letter
   next to a joiner - see formPresentation() in script.js */
.shape-init {
  -webkit-font-feature-settings: "init" 1;
  font-feature-settings: "init" 1;
}

.shape-medi {
  -webkit-font-feature-settings: "medi" 1;
  font-feature-settings: "medi" 1;
}

.shape-fina {
  -webkit-font-feature-settings: "fina" 1;
  font-feature-settings: "fina" 1;
}

/* A shape read straight out of the font, for the engines that will not produce
   a contextual form on request - positioned by placeOutlines() */
.glyph-outline {
  position: absolute;
  display: block;
  overflow: visible;
}

/* Every box that shows a character: always Amiri */
.glyph-font {
  font-family: var(--font-glyph);
}

/* Amiri has no glyph for this character - the conventional empty box with a
   cross, rather than a silent substitution from another typeface */
.glyph-missing {
  display: inline-block;
  width: 0.5em;
  height: 0.72em;
  border: 0.05em solid currentColor;
  position: relative;
  opacity: 0.55;
  vertical-align: baseline;
}

.glyph-missing::before,
.glyph-missing::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top right,
    transparent calc(50% - 0.4px),
    currentColor calc(50% - 0.4px),
    currentColor calc(50% + 0.4px),
    transparent calc(50% + 0.4px)
  );
}

.glyph-missing::after {
  transform: scaleX(-1);
}

.status-line {
  font-size: 14px;
  color: var(--muted);
  padding: 10px 0;
}

/* Character grid */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 6px;
  align-items: start;
}

.cell {
  aspect-ratio: 1 / 1;
  border: 1px solid var(--border-color);
  background: var(--bg-color);
  color: var(--text-color);
  font-size: 30px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 2px;
  overflow: hidden;
  transition: background-color 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
  .cell:hover {
    background-color: var(--hover);
  }

  body.dark .cell:hover {
    background: rgb(0, 0, 255);
    color: rgb(255, 255, 255);
  }
}

.cell.active {
  background: var(--accent-color);
  color: var(--bg-color);
}

/* Characters with no visible shape: show the bare code point instead */
/* A character that draws nothing: shown the way the Unicode code charts show
   one, as its abbreviation in a dashed box */
.cell.blank {
  font-family: var(--font-main);
  font-size: 10px;
  color: var(--text-color);
  letter-spacing: 0.04em;
}

.invisible-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed currentColor;
  padding: 0.35em 0.45em;
  line-height: 1;
  font-family: var(--font-main);
  white-space: nowrap;
}

.cell.active.blank {
  color: var(--bg-color);
}

/* Expanded record, occupies a full grid row under the character clicked */
/* ------------------------------------------------------------------ record

   The record is a grid item spanning the whole character grid, and it borrows
   that grid's columns with `subgrid`. Every edge inside it - the divider, the
   glyph box, the form and specimen boxes - therefore lands on the same column
   lines as the squares above. A container spanning N of those columns can use
   repeat(N, 1fr) with the same 6px gap and reproduce them exactly, which is how
   the inner rows below stay on the grid without nesting subgrids everywhere. */

.detail {
  grid-column: 1 / -1;
  display: grid;
  /* Fallback for browsers without subgrid: the same tracks as the grid above */
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  column-gap: 6px;
  position: relative;
  border: 1px solid var(--border-color);
  margin: 0 0 4px 0;
  align-items: stretch;
}

@supports (grid-template-columns: subgrid) {
  .detail {
    grid-template-columns: subgrid;
  }
}

.detail-close {
  position: absolute;
  top: 10px;
  right: 14px;
  z-index: 3;
  font-size: 28px;
  line-height: 1;
  background: none;
  border: none;
  color: var(--accent-color);
  cursor: pointer;
}

/* Ten columns for the character, the rest for the map and the lists */
.detail-left {
  grid-column: 1 / 11;
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  column-gap: 6px;
  row-gap: 14px;
  align-content: start;
  padding: 22px 0;
  border-right: 1px solid var(--border-color);
}

/* One column of air on either side, instead of padding that would fall
   between the grid lines */
.detail-left > * {
  grid-column: 2 / 10;
  min-width: 0;
}

.detail-right {
  grid-column: 11 / -1;
  min-width: 0;
  padding: 20px;
}

@supports (grid-template-columns: subgrid) {
  .detail-right {
    display: grid;
    grid-template-columns: subgrid;
    /* The map takes whatever height the left column leaves, the lists sit
       under it */
    grid-template-rows: 1fr auto;
    align-content: stretch;
    padding: 0;
  }

  .detail-map {
    grid-column: 1 / -1;
  }

  .detail-meta {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: subgrid;
  }

  .detail-meta > * {
    grid-column: 2 / -2;
  }
}

/* Head: the name on its own line above, then the glyph box with the code and
   counts beside it. The name sets its own width, so however many lines it runs
   to it cannot push the composition around. */
.detail-head {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  column-gap: 6px;
  align-items: stretch;
}

.detail-glyph-box {
  grid-column: span 3;
  border: 1px solid var(--border-color);
  position: relative;
  overflow: hidden;
}

/* A square made from its own width. `aspect-ratio` on a grid item is resolved
   at different points by different engines, which left the box collapsed and
   the glyph spilling out of it in Safari. */
.detail-glyph-box::before {
  content: "";
  display: block;
  padding-top: 100%;
}

.detail-glyph-box .detail-glyph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.detail-id {
  grid-column: 4 / -1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Sits on the bottom edge of the glyph box beside it */
.detail-id .copy-btn {
  margin-top: auto;
  align-self: flex-start;
}

.detail-glyph {
  font-size: 116px;
  line-height: 1.1;
  color: var(--text-color);
}

.detail-glyph.blank {
  font-size: 22px;
  color: var(--text-color);
  text-align: center;
  padding: 0 8px;
}

.detail-name {
  font-size: 20px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--accent-color);
}

.detail-code {
  font-size: 17px;
  font-weight: 700;
  color: var(--text-color);
}

.detail-counts {
  font-size: 17px;
  line-height: 1.4;
  color: var(--text-color);
  margin-top: 10px;
}

/* A count and its noun stay on one line */
.detail-counts div {
  white-space: nowrap;
}

/* Small grey caption above a row of boxes */
.detail-label {
  font-size: 15px;
  color: var(--muted);
  margin-bottom: -6px;
}

.detail-traits {
  font-size: 15px;
  font-weight: 700;
  line-height: 1.4;
}

.detail-links {
  font-size: 15px;
  margin-top: -8px;
}

.detail-links a {
  color: var(--link);
  text-decoration: underline;
}

.detail-row {
  font-size: 15px;
  line-height: 1.45;
  text-align: justify;
  hyphens: auto;
  overflow-wrap: anywhere;
}

/* Labels are the bold part of a line, as in the layout */
.detail-row .label {
  font-weight: 700;
  color: var(--text-color);
}

.detail-row a {
  color: var(--link);
  text-decoration: none;
}

.detail-row a:hover {
  text-decoration: underline;
}

/* ---- contextual forms: four boxes, each two columns wide ---- */
.forms {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 6px;
  /* Natural height, so a box whose code point wraps to two lines cannot
     stretch the row and shift the glyph boxes out of line */
  align-items: start;
}

.form-box {
  text-align: center;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
  color: inherit;
  min-width: 0;
}

/* A button centres its own content, which would drop the glyph box a few
   pixels in whichever box has the shorter caption */
button.form-box {
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
}

@media (hover: hover) and (pointer: fine) {
  button.form-box:hover .form-glyph {
    background: var(--hover);
  }
}

.form-box.chosen .form-glyph {
  background: var(--accent-color);
  color: var(--bg-color);
}

.form-box.chosen .form-glyph::after {
  border-top-color: var(--bg-color);
}

/* A box with a baseline drawn across it, the glyph sitting on the line.
   ::before is a zero-width strut - an empty flex item takes its baseline from
   its bottom edge, so it pins the baseline at a fixed height no matter which
   font, or which glyph, is being shown. */
.form-glyph {
  position: relative;
  height: 104px;
  border: 1px solid var(--border-color);
  display: flex;
  align-items: baseline;
  justify-content: center;
  font-size: 48px;
  line-height: 1;
  overflow: hidden;
}

.form-glyph::before {
  content: "";
  display: block;
  width: 0;
  height: 70px;
}

.form-glyph::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 70px;
  border-top: 1px solid var(--border-color);
}

.form-glyph.na {
  color: var(--muted);
  font-size: 13px;
}

.form-label {
  font-size: 13px;
  color: var(--muted);
  margin-top: 5px;
}

.form-code {
  font-size: 12px;
  color: var(--muted);
}

/* ---- specimens: bare boxes, the font named on hover ---- */
.specimen-slot {
  position: relative;
}

.specimens {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}

.specimen {
  min-width: 0;
}

.specimen-glyph {
  position: relative;
  height: 96px;
  border: 1px solid var(--border-color);
  display: flex;
  align-items: baseline;
  justify-content: center;
  font-size: 46px;
  line-height: 1;
  overflow: hidden;
}

.specimen-glyph::before {
  content: "";
  display: block;
  width: 0;
  height: 64px;
}

.specimen-glyph::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 64px;
  border-top: 1px solid var(--border-color);
}

@media (hover: hover) and (pointer: fine) {
  .specimen:hover .specimen-glyph {
    background: var(--hover);
  }
}

/* Touch has no hover, so a tapped box gets the same highlight */
.specimen.tapped .specimen-glyph {
  background: var(--hover);
}

/* ---- dark mode: the characters read white, the baseline recedes ---- */
body.dark .cell {
  color: rgb(255, 255, 255);
}

body.dark .cell.blank,
body.dark .detail-glyph.blank {
  color: rgb(255, 255, 255);
}

body.dark .cell.active {
  background: rgb(0, 0, 255);
  color: rgb(255, 255, 255);
}

body.dark .detail-glyph,
body.dark .form-glyph,
body.dark .specimen-glyph {
  color: rgb(255, 255, 255);
}

body.dark .form-glyph::after,
body.dark .specimen-glyph::after {
  border-top-color: rgb(120, 120, 120);
}

/* Picked or pointed at, a box is blue with white on it - in both modes */
body.dark .form-box.chosen .form-glyph,
body.dark .specimen.tapped .specimen-glyph {
  background: rgb(0, 0, 255);
  color: rgb(255, 255, 255);
}

body.dark .form-box.chosen .form-glyph::after,
body.dark .specimen.tapped .specimen-glyph::after {
  border-top-color: rgb(255, 255, 255);
}

@media (hover: hover) and (pointer: fine) {
  body.dark button.form-box:hover .form-glyph,
  body.dark .specimen:hover .specimen-glyph {
    background: rgb(0, 0, 255);
    color: rgb(255, 255, 255);
  }

  body.dark button.form-box:hover .form-glyph::after,
  body.dark .specimen:hover .specimen-glyph::after {
    border-top-color: rgb(255, 255, 255);
  }
}

.specimen-tip,
.map-tip {
  position: absolute;
  pointer-events: none;
  background: var(--accent-color);
  color: var(--bg-color);
  font-size: 12px;
  line-height: 1;
  padding: 4px 6px;
  white-space: nowrap;
  z-index: 2;
}

.specimen-tip[hidden],
.map-tip[hidden] {
  display: none;
}

.specimen-note {
  font-size: 14px;
  color: var(--muted);
}

.copy-btn {
  background: blue;
  color: white;
  border: none;
  height: 34px;
  padding: 0 14px;
  font-family: inherit;
  font-size: 15px;
  cursor: pointer;
  margin-top: 16px;
  white-space: nowrap;
}

.empty-state {
  font-size: 14px;
  padding: 20px 0;
}

/* ---- countries: the list and the map highlight each other on hover ---- */
.country {
  cursor: default;
}

/* Colour only: bolding here would reflow the whole list on every hover. */
.country.hot {
  color: var(--map-hot);
}

.detail-map {
  /* Pulled left over the column gap so the map, and the rule below it, reach
     the divider between the two halves of the record */
  margin-left: -6px;
  min-height: 260px;
  min-width: 0;
}

.detail-meta {
  margin-left: -6px;
  border-top: 1px solid var(--border-color);
  padding: 18px 0;
  display: grid;
  row-gap: 14px;
}

.map-frame {
  position: relative;
  height: 100%;
  overflow: hidden;
  touch-action: none; /* we handle drag and pinch ourselves */
}

.world {
  width: 100%;
  height: 100%;
  display: block;
  cursor: grab;
}

.map-frame.zoomed .world {
  cursor: move;
}

.world:active {
  cursor: grabbing;
}

/* Zoom controls, tucked into the top left corner */
.map-zoom {
  position: absolute;
  top: 8px;
  left: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.map-btn {
  width: 26px;
  height: 26px;
  background: var(--bg-color);
  border: 1px solid var(--border-color);
  color: var(--accent-color);
  font-family: inherit;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}

@media (hover: hover) and (pointer: fine) {
  .map-btn:hover {
    background: var(--accent-color);
    color: var(--bg-color);
  }
}

.world .land {
  fill: var(--map-land);
  stroke: var(--map-edge);
  stroke-width: 1;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.world .used {
  fill: var(--map-used);
  cursor: pointer;
}

.world .used.hot {
  fill: var(--map-hot);
}

/* ---- narrow screens: one column, map under the description, lists last ---- */
@media (max-width: 1100px) {
  .detail-left,
  .detail-right {
    grid-column: 1 / -1;
  }

  .detail-left {
    display: block;
    padding: 20px;
    border-right: none;
    border-bottom: 1px solid var(--border-color);
  }

  .detail-left > * {
    margin-bottom: 14px;
  }

  .detail-right {
    display: block;
    padding: 0;
  }

  /* The subgrid placement above only makes sense while the parent is a grid */
  .detail-meta {
    display: block;
  }

  .detail-meta > * {
    grid-column: auto;
  }

  .detail-meta .detail-row + .detail-row {
    margin-top: 14px;
  }

  .detail-head {
    grid-template-columns: repeat(8, 1fr);
  }

  /* Stacked, the close button sits over the name rather than over the map */
  .detail-id {
    padding-right: 30px;
  }

  /* Edge to edge, so the rule under the map meets the panel's own borders */
  .detail-map {
    margin-left: 0;
    height: 280px;
    min-height: 0;
  }

  .detail-meta {
    margin-left: 0;
    padding: 18px 20px 20px;
  }

  .forms,
  .specimens {
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: 6px;
  }
}

@media (max-width: 748px) {
  .filter-bar input[type="text"],
  .filter-bar select {
    width: 100%;
  }

  .grid {
    grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
  }

  .cell {
    font-size: 22px;
  }

  /* Only the left half is padded: the map and the rule under it run to the
     panel's own borders */
  .detail-left {
    padding: 15px;
  }

  .detail-meta {
    padding: 15px;
  }

  .detail-head {
    grid-template-columns: repeat(6, 1fr);
  }

  .detail-glyph-box {
    grid-column: span 3;
  }

  .detail-glyph {
    font-size: 54px;
  }

  /* The counts never wrap, so on a narrow column they set the type size */
  .detail-code {
    font-size: 15px;
  }

  .detail-counts {
    font-size: 14px;
  }

  .copy-btn {
    font-size: 14px;
    height: 30px;
    padding: 0 10px;
    margin-top: 12px;
  }

  .forms,
  .specimens {
    grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  }
}
