/* The clock board's stylesheet, loaded by the two places that draw one: the
 * board's own page, which asks for it in its head, and the calculator, which
 * asks for it the first time an answer converts a time and never otherwise.
 *
 * A second file rather than part of calc.css, for the reason sun.css is one.
 * Folded in, everything below would ride along on every visit from everybody
 * who only ever converts a currency. Left inline in the page, it would be
 * dropped on the floor: there is no 'unsafe-inline' in the style-src of the
 * policy in public/_headers, and a <style> block would be refused.
 *
 * What is not here is everything calc.css already says. The tokens, the body
 * rule, .wrap, .sr, .nav and .foot are the sheet next door's, and two copies
 * of a token is one token that will be changed in one place.
 *
 * It is in three parts: what a cell looks like, which is the same in both
 * layouts; the frame and the two grids, which are where they differ; and the
 * marks laid over them. The two grids are the only rules in this file that
 * know which way the board is turned, and they know it from one attribute.
 */

/* ===== THE RAMP =====
 *
 * Four shades saying what hour a cell holds: the small hours, the hour or two
 * before work, the working day, the evening. src/26-board.js decides which
 * band a cell is in and this decides what that looks like, so the boundaries
 * live in one place and the colours in another and neither can drift into
 * being an opinion about the other.
 *
 * Every pair below was measured rather than eyeballed. The weakest is the
 * night cell in light mode at 6.7:1 against its white numerals, and the rest
 * run from 8.7 to 16.6, so every reading on the board clears AA for body text
 * with room to spare. That matters more here than on most pages: the numbers
 * sitting on these shades are the entire content, and a 3am that cannot be
 * read is a board that has not answered.
 *
 * The scale runs pale for the working day and deep for the night, which is
 * the direction both of the widgets this one is modelled on run and the one
 * that needs no key: a dark block reads as "do not ring them" without being
 * told, and the reader supplies the rest. The shading says the hour and only
 * the hour. Shading "a good time to call" would be a judgement about somebody
 * else's Tuesday, and it would be wrong for shift work, for Friday afternoon,
 * and for every country whose weekend is not Saturday.
 */
:root {
  --board-work-bg: #f8fafc;
  --board-work-fg: #1a1a1a;
  --board-early-bg: #dbeafe;
  --board-early-fg: #1a1a1a;
  --board-evening-bg: #93c5fd;
  --board-evening-fg: #10243d;
  --board-night-bg: #1d4ed8;
  --board-night-fg: #ffffff;

  /* The two marks that are not cells. `now` is where the clock actually
     stands, and `pick` is where the reader has put the handle. They have to
     be told apart at a glance, so one is a warm line and the other takes the
     page's own accent: two blues on a board of blues would be one mark. */
  --board-now: #f97316;
  --board-pick: #111827;
  --board-sel-fill: rgba(17, 24, 39, 0.14);
  --board-edge: rgba(15, 23, 42, 0.14);
  /* The knob stands on a cell rather than beside one, so it is a wash and not
     a block: the hour underneath is the hour the reader is pointing at, and a
     control that covered its own reading would be answering with its back. */
  --board-knob-fill: rgba(17, 24, 39, 0.28);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --board-work-bg: #1e2530;
    --board-work-fg: #f3f4f6;
    --board-early-bg: #1b2a44;
    --board-early-fg: #dbeafe;
    --board-evening-bg: #1a3a63;
    --board-evening-fg: #dbeafe;
    --board-night-bg: #0d1e3a;
    --board-night-fg: #93c5fd;

    --board-now: #fb923c;
    --board-pick: #f3f4f6;
    --board-sel-fill: rgba(243, 244, 246, 0.18);
    --board-edge: rgba(226, 232, 240, 0.16);
    --board-knob-fill: rgba(243, 244, 246, 0.26);
  }
}

:root[data-theme="dark"] {
  --board-work-bg: #1e2530;
  --board-work-fg: #f3f4f6;
  --board-early-bg: #1b2a44;
  --board-early-fg: #dbeafe;
  --board-evening-bg: #1a3a63;
  --board-evening-fg: #dbeafe;
  --board-night-bg: #0d1e3a;
  --board-night-fg: #93c5fd;
  --board-now: #fb923c;
  --board-pick: #f3f4f6;
  --board-sel-fill: rgba(243, 244, 246, 0.18);
  --board-edge: rgba(226, 232, 240, 0.16);
  --board-knob-fill: rgba(243, 244, 246, 0.26);
}

/* ===== A CELL ===== */

.cell {
  background: var(--board-work-bg);
  color: var(--board-work-fg);
  font-variant-numeric: tabular-nums;
  /* Tabular figures throughout, because the whole picture is a column of
     numbers that has to line up. Proportional digits put a 1 in less room
     than a 0 and the column visibly wanders. */
  line-height: 1.15;
  text-align: center;
}

.cell[data-band="early"] { background: var(--board-early-bg); color: var(--board-early-fg); }
.cell[data-band="evening"] { background: var(--board-evening-bg); color: var(--board-evening-fg); }
.cell[data-band="night"] { background: var(--board-night-bg); color: var(--board-night-fg); }

/* The am or pm under the hour. Smaller and quieter, because it is the half of
   the reading nobody scans for: a column of hours is read by its numbers and
   the meridiem is checked once. It is hidden rather than removed on the
   24-hour face, down at the end of this file, so the cell keeps its size. */
.cell__meridiem {
  display: block;
  font-size: 0.68em;
  opacity: 0.72;
}

/* A cell in a zone that is half or three quarters past carries four
   characters where the others carry two. It shrinks rather than overflowing,
   because the alternative is a column sized for the exception: every board
   with a Kolkata on it would set every other cell twice as wide as it needs. */
.cell[data-min="yes"] .cell__h { font-size: 0.86em; }

/* ===== THE DAY TURNING =====
 *
 * The cell where a place's date changes carries the date instead of the hour,
 * which is how both of the boards this is modelled on say it and is the right
 * way round: the hour at a day boundary is always midnight and says nothing,
 * while the date is the fact the reader came for. The weekday rides above it
 * in the vertical layout and beside it in the horizontal one, so both are
 * drawn here and the layouts decide which to show.
 */
.cell[data-starts] { font-weight: 600; }

.cell__day {
  display: block;
  font-size: 0.62em;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  opacity: 0.8;
}

.cell__date {
  display: block;
  font-size: 0.82em;
}

/* ===== THE CLOCK MOVING =====
 *
 * Twice a year a row is not 24 cells long and the board should say why rather
 * than let it read as a bug. The cell after a spring forward is the one whose
 * hour is missing from the sequence, and the second of the two identical
 * cells after a fall back is the one that looks like a repeat because it is
 * one. Both get a rule down the leading edge and a title the reader can hover.
 */
.cell[data-shift] { box-shadow: inset 2px 0 0 var(--board-now); }

/* Home. The row the whole board is read against, so it is marked on the name
   rather than on its cells: shading home's own hours differently would break
   the one rule the ramp has, which is that a shade means an hour. */
.place[data-home] .place__name { font-weight: 600; }

.place__badge {
  font-size: 0.72em;
  letter-spacing: 0.04em;
  padding: 0.1em 0.4em;
  border: 1px solid var(--board-edge);
  border-radius: 0.25em;
  color: var(--muted);
}

.place__region {
  font-size: 0.8em;
  color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The hours between here and there, which is the number people actually quote
   to each other. Home carries none: the row is already marked as home, and a
   "+0" beside it is a number to read and discard. */
.place__from {
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}

/* ===== THE FRAME ===== */

.board { position: relative; }

/* How wide the board is allowed to be, which is a different answer for the
   two layouts because they are asking different questions of the space.

   Hours down the page needs no more than the column every other page here
   gets: one 720px .wrap less 1.5rem of padding each side, so 672px. Four or
   five places fit across it and a taller board is only more scrolling, which
   is what a page is for.

   Hours across is the opposite. Its long axis is the one the hours run along,
   and 672px of it shows eight of them beside a name column, which is a day
   seen through a letterbox. So it steps outside the column, up to 1250px,
   centred by a negative margin against the 672px it was given. No transform:
   a transformed ancestor is a containing block, and the name column of this
   layout is position: sticky inside it. */
.board[data-layout="horizontal"] {
  --wide: min(1250px, calc(100vw - 3rem));
  width: var(--wide);
  margin-left: calc((100% - var(--wide)) / 2);
}

/* One width for everything that is not the picture, whichever way the picture
   is turned. The board itself is 672px down the page and up to 1250px across
   it, and anything sharing that width moved half a screen sideways every time
   the layout switch was thrown, which is the one control guaranteed to be
   under the pointer when it happens. So the bar and the line underneath are
   pinned, and the picture moves between them.

   Centred against whatever the parent gives by the same negative margin the
   wide board uses, so they hold still whether that parent is 672 or 1250. */
.board { --bar: min(750px, calc(100vw - 3rem)); }
/* Folded into an answer the picture steps out exactly as it does on its own
   page, and everything that is not the picture stays in the column.

   It was held to the column to begin with, on the reasoning that a figure
   under an answer belongs inside the type it is a figure for. What that
   reasoning cost is the whole point of this layout: the column is 672px, the
   two step chevrons take their share of it, and what is left shows eight
   hours of a day whose length is the thing the reader came to see. On its own
   page the same board shows twenty.

   Nothing above it moves when it does, which is the part that had to be true.
   The picture is centred against the column by a negative margin, so it grows
   sideways out of a box that keeps its own width, and the answer, the bar,
   the line underneath and the history list all stand where they stood.

   The bar cannot use the wide board's own width here, since --bar is read
   inside .board and .board is now 1250px. It takes the column instead, which
   is one .wrap of 720px less 1.5rem of padding each side. */
.clocks--inline .board { --bar: min(672px, calc(100vw - 3rem)); }
.clocks--inline .board { margin-top: 1.25rem; }
/* Shorter, too. A compact board is an illustration under a number, and thirty
   hours of it down a phone is a picture that pushes the history list off the
   end of the page. */
.clocks--inline .board[data-layout="vertical"] .board__scroll { max-height: 22rem; }

/* The bar, and the compact form under an answer keeps it.
   It was folded away to begin with, on the reasoning that an answer is not a
   place to put three controls. What that reasoning missed is which three.
   Every one of them is about how the picture is drawn and none of them is
   about which board this is: the face is 12 or 24, the layout is hours down
   or hours across, and the range is how long the selection runs. A reader who
   throws any of them is looking at the same instant in the same places, which
   is what makes them safe to leave under an answer, and the day walk and the
   picker below are not and stay folded.

   Sending somebody to /time to read the board in 24-hour was sending them
   away from their answer to change the type on it. */
.board__bar {
  width: var(--bar);
  margin-left: calc((100% - var(--bar)) / 2);

  display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem;
  justify-content: space-between; align-items: center;
  margin-bottom: 0.75rem;
}
/* Smaller under an answer, where the bar is a caption's worth of controls
   rather than the top of a page. One number, everything about the switch being
   sized off --h, and the words beside it were the smaller size already. */
.clocks--inline .tgl { --h: 22px; }

.board__group { display: inline-flex; align-items: center; gap: 0.6rem; }

/* ===== THE SWITCH =====
   Two of them, one per pair of words, and both are the site's switch, which is
   drawn in calc.css. What is here is only what the board's two switches say
   inside the knob: the glyph is what makes a pair readable once the bar wraps
   and the words fall away from the switch they belong to.

   Everything is still sized off the switch's own --h, so the two cannot drift
   apart and a third would need one number. */

/* Which way the hours run: three bars that turn a quarter turn as they travel,
   so the glyph is doing to itself what the switch does to the board. */
.tgl--turn .tgl__knob svg {
  width: calc(var(--dot) * 0.5); height: calc(var(--dot) * 0.5);
  color: var(--tgl-glyph-off); transform-origin: 50% 50%;
  transition: transform 0.34s var(--ease), color 0.3s var(--ease);
}
.tgl--turn input:checked ~ .tgl__knob svg {
  transform: rotate(90deg); color: var(--tgl-glyph-on);
}

/* The clock face: the digits turn over, 24 on the front and 12 on the back.
   They ride the shared card, so all that is theirs is how a number is set. */
.tgl__digits {
  font: inherit; font-size: calc(var(--dot) * 0.43); font-weight: 700;
  letter-spacing: -0.04em; font-variant-numeric: tabular-nums; line-height: 1;
}

@media (prefers-reduced-motion: reduce) {
  .tgl--turn .tgl__knob svg { transition: none; }
}

/* The words either side, which are also the control: clicking one is how you
   pick that side without having to work out which way the switch is currently
   lying. Which one is showing is said on the word itself, by it taking the
   page's ink while the other keeps the muted grey. */
.pair-label {
  font: inherit; font-size: 0.8125rem; font-weight: 500;
  background: none; border: 0; padding: 0.25rem 0.1rem; margin: 0;
  color: var(--faint); cursor: pointer; white-space: nowrap;
  border-radius: 0.4rem;
  transition: color 0.2s ease;
}
.pair-label:hover { color: var(--muted); }
.pair-label[aria-pressed="true"] { color: var(--text); }
.pair-label:focus-visible { outline: 2px solid var(--tgl-on); outline-offset: 2px; }

/* ===== WALKING THE DAYS =====
   Chevrons either side of the day the board is standing on, and a box that
   takes a date said in words. Pinned to the same width as the bar for the same
   reason: it is a control, and the picture underneath is what moves. */
.board__days {
  width: var(--bar);
  margin-left: calc((100% - var(--bar)) / 2);
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 0.5rem 1rem;
  margin-bottom: 0.75rem;
}
.clocks--inline .board__days { display: none; }

.board__walk { display: inline-flex; align-items: center; gap: 0.15rem; }

.board__chev {
  display: inline-flex; align-items: center; justify-content: center;
  font: inherit; padding: 0.25rem;
  color: var(--faint); background: none; border: 0; cursor: pointer;
}
.board__chev:hover { color: var(--text); }

/* The day, and the way back to today. Wide enough for the longest of the three
   words it says, so the chevrons either side of it hold still: a control whose
   buttons move when the label changes is a control you have to re-aim at
   between presses. */
.board__today {
  font: inherit; font-size: 0.8125rem; font-weight: 600;
  min-width: 7.5rem; padding: 0.25rem 0.5rem;
  color: var(--text); background: none;
  border: 0; border-radius: 0.4rem; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.board__today:hover:not(:disabled) { background: var(--chip); }
/* On today there is nowhere to go back to. Kept at full strength rather than
   greyed: it is the label as much as the button, and a greyed label reads as
   a board that is not working. */
.board__today:disabled { cursor: default; }

.board__jump { display: inline-flex; align-items: center; gap: 0.35rem; }
.board__jump input { width: 12rem; max-width: 40vw; }
.board__jump[data-bad] input { border-color: var(--board-now); }

/* ===== ADDING A PLACE =====
   The box and the list under it, which is where the widget does the one thing
   a typed answer cannot: offer the choices for a country that keeps several
   clocks, rather than refusing with "name a city". */
.board__add {
  width: var(--bar);
  margin-left: calc((100% - var(--bar)) / 2);
  display: flex; align-items: flex-start; gap: 0.5rem;
  margin-top: 0.75rem;
}
.clocks--inline .board__add,
.clocks--inline .board__cap { display: none; }

/* The list is positioned against this rather than against the page, so it
   opens under the box wherever the box happens to be. */
.board__addbox { position: relative; flex: 1 1 auto; min-width: 0; }
.board__addbox input { width: 100%; }

.board__found {
  position: absolute; z-index: 6; left: 0; right: 0; top: calc(100% + 0.25rem);
  max-height: 17rem; overflow-y: auto;
  margin: 0; padding: 0.25rem; list-style: none;
  background: var(--bg);
  border: 1px solid var(--line); border-radius: 0.6rem;
  box-shadow: 0 6px 20px rgba(16, 26, 38, 0.12);
}

.found__row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem;
  padding: 0.3rem 0.5rem; border-radius: 0.4rem; cursor: pointer;
}
.found__row:hover,
.found__row[aria-selected="true"] { background: var(--chip); }
.found__line { display: flex; align-items: baseline; gap: 0.4rem; min-width: 0; }
.found__name { font-size: 0.875rem; white-space: nowrap; }
.found__where {
  font-size: 0.75rem; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.found__clock {
  font-size: 0.75rem; color: var(--muted); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* The country line above a list of its clocks, and the line where there is
   nothing to show. Neither is an option, so neither is styled like one. */
.found__head,
.found__none {
  padding: 0.35rem 0.5rem;
  font-size: 0.75rem; color: var(--muted);
}
.found__head { border-bottom: 1px solid var(--line); margin-bottom: 0.25rem; }

.board__sort { flex: none; }

.board__cap {
  width: var(--bar);
  margin-left: calc((100% - var(--bar)) / 2);
  margin-top: 0.5rem;
  font-size: 0.8125rem; color: var(--board-now);
}

/* The layout switch is the browser's alone. On a phone the horizontal board
   does not fit, and a control offering something broken is worse than no
   control: the phone gets the vertical layout and nothing to change it to. */
@media (max-width: 719px) {
  .board__group--layout { display: none; }
}

/* Nothing in the picture is text to be selected. Every drag across it used to
   leave a trail of highlighted hours behind the bar, and a double click on a
   cell picked the number out of it as though somebody meant to copy "11".
   The line worth copying is the summary under the board, which is outside
   this box and stays selectable. */
.board__frame {
  display: flex; align-items: center; gap: 0.35rem;
  -webkit-user-select: none; user-select: none;
}

.board__step {
  font: inherit; display: inline-flex; align-items: center; justify-content: center;
  flex: none; padding: 0.3rem;
  color: var(--faint); background: none; border: 0; cursor: pointer;
}
.board__step:hover { color: var(--text); }

.board__scroll {
  flex: 1; min-width: 0;
  overflow: auto;
  border: 1px solid var(--line);
  /* The strip of hours runs out where it runs out, and the page behind it does
     not take over. A swipe that reaches the last hour used to hand what was
     left of itself up to the document, which slid the whole page sideways and
     bounced it back: the reader was scrolling the board and the site moved.
     `contain` is the half of overscroll-behavior that is about the handover,
     and this box keeps its own bounce, which is the one that says the hours
     have run out. */
  overscroll-behavior: contain;
  /* A stacking context of its own, so the three z-indexes inside it are about
     the picture and not about the page. Written out at the selection below,
     with what went wrong without it. */
  isolation: isolate;
}

/* What the selection is positioned against. It has to be exactly the grid's
   size and not the scroll container's: in the horizontal layout the grid is
   wider than what is on screen, and a selection measured against the visible
   part would drift further out of place the further the board was scrolled.
   min-content shrink-wraps it to the grid, min-width keeps it filling when
   there is room to spare. */
.board__stage { position: relative; width: min-content; min-width: 100%; }

.board__grid {
  display: grid;
  position: relative;
  background: var(--bg);
  font-size: 0.8125rem;
}

/* One wrapper per row of the picture, laid out by the grid two levels up.
   Without it the grid works and a screen reader is handed three hundred cells
   in a heap with nothing saying where one row ends. */
.board__row { display: contents; }

/* ===== HOURS DOWN THE PAGE =====
   Places across the top, hours running down. The phone's only layout and one
   of the browser's two.

   The columns are locked to each other by the grid, which is the whole point
   of the picture: row k is the same instant in every column, so a finger run
   across it is one moment in five cities. A gap between the columns and none
   between the rows makes each place read as one continuous band, which is how
   the eye finds a run of working hours without counting.

   Past four or so places the board scrolls sideways rather than refusing the
   fifth. The reader asked for those places; the header is pinned so they stay
   named while it scrolls, which is the thing that would otherwise be lost. */
.board[data-layout="vertical"] .board__frame { flex-direction: column; align-items: stretch; }
.board[data-layout="vertical"] .board__step { width: 100%; }
.board[data-layout="vertical"] .board__scroll { max-height: 70vh; }

.board[data-layout="vertical"] .board__grid {
  /* A firm floor rather than an even share. Five places squeezed into a phone
     gave each 73px and every name came out as two letters and an ellipsis, so
     the board fitted and could not be read. At this floor four fit a phone and
     a fifth scrolls, which is the trade written up beside the layout: the
     reader asked for those places, and the pinned header keeps them named. */
  grid-template-columns: repeat(var(--places, 3), minmax(5.5rem, 1fr));
  column-gap: 2px;
}
.board[data-layout="vertical"] .place {
  /* Above the selection, not under it. The pinned header is the thing that
     says which column is which, and it was being painted over: drag the bar up
     to the top of the band and the grey of the selection and its dark border
     lay across the place names, so the one part of the picture that must stay
     readable while the rest scrolls was the part that stopped being readable.
     See the stacking order written out at the selection. */
  position: sticky; top: 0; z-index: 5;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  padding: 0.5rem 0.4rem;
  text-align: left;
}
/* The four tools run along the top of a column header here rather than down
   the side of a row. Four stacked glyphs in a header this narrow would be
   taller than the name they belong to. */
.board[data-layout="vertical"] .place__tools {
  flex-direction: row; gap: 0.05rem; margin-bottom: 0.1rem;
}

.board[data-layout="vertical"] .cell { padding: 0.35rem 0.2rem; }
.board[data-layout="vertical"] .board__mark i { left: 0; right: 0; height: 2px; }

/* ===== HOURS ACROSS THE PAGE =====
   Places down the side, hours running across. The browser's default.

   Every row scrolls together because there is one scroll container and one
   grid: rows that scrolled independently would put two places on two
   different hours and the board would be saying something untrue. The name
   column is pinned to the left edge so a row stays identified while its hours
   run past.

   The rows stay aligned on the instant, which is the fault a grid of hour
   cells invites: a place at +5:30 reads half past all the way along and is
   drawn half past, not rounded into step with its neighbours. Nothing here
   does that rounding because nothing here does arithmetic. */
.board[data-layout="horizontal"] .board__grid {
  /* The name column, sized for the column this board actually lives in.
     Every page here is one 720px .wrap with 1.5rem of padding, so the widest
     the board is ever drawn is 672px, and a name column of 20rem was taking
     half of it and leaving eight hours on screen. At this width the meta
     stacks instead of running along one line, and the band keeps two thirds
     of the board. */
  --meta: 13rem;
  grid-template-columns: var(--meta) repeat(var(--hours, 24), minmax(2.5rem, 1fr));
  row-gap: 4px;
}
/* How tall the knob is, and therefore where the grips start. Said once, on the
   layout that has a cap, because the two numbers cannot be allowed to drift:
   a gap between them is a band of the bar that does nothing, and an overlap
   is the bug this was written to fix. */
.board[data-layout="horizontal"] { --board-knob: 39px; }
.board[data-layout="horizontal"] .place {
  /* Above the selection here too, and this is the layout where it showed:
     the name column is pinned to the left edge and the bar is dragged across
     it constantly, so every drag past the start of the band put the selection
     over the city names and their clocks. */
  position: sticky; left: 0; z-index: 5;
  display: grid;
  grid-template-columns: auto 2.5rem minmax(0, 1fr);
  grid-template-areas:
    "tools from named"
    "tools from at";
  align-items: center; gap: 0.1rem 0.4rem;
  padding: 0.35rem 0.5rem;
  background: var(--bg);
  border-right: 1px solid var(--line);
}
.board[data-layout="horizontal"] .place__tools { grid-area: tools; }
.board[data-layout="horizontal"] .place__from { grid-area: from; text-align: right; }
.board[data-layout="horizontal"] .place__named { grid-area: named; }
.board[data-layout="horizontal"] .place__at { grid-area: at; text-align: left; }
/* The region stays, now that this layout has room to step outside the column.
   It came off when the name column had 11.5rem to work in and something had to. */

.board[data-layout="horizontal"] .cell { padding: 0.3rem 0.15rem; }
.board[data-layout="horizontal"] .board__mark i { top: 0; bottom: 0; width: 2px; }
.board[data-layout="horizontal"] .board__step svg { transform: rotate(-90deg); }

/* The four controls on a row. Drawn small and quiet: they are used when a
   board is set up and hardly again, and at full weight they would compete with
   the name beside them every time the board is read. */
.place__tools { display: flex; flex-direction: column; gap: 0.15rem; }
.place__x,
.place__pin,
.place__step {
  width: 1.1rem; height: 1.1rem; padding: 0;
  font: inherit; line-height: 1;
  color: var(--faint); background: none; border: 0; cursor: pointer;
}
.place__x::before { content: "\00d7"; }
.place__pin::before { content: "\2302"; }
/* One pair of glyphs, turned by the layout. The places run down the side of
   the horizontal board and across the top of the vertical one, so the same
   instruction is a row moving up in one picture and a column moving left in
   the other, and an arrow that pointed the same way in both would be pointing
   the wrong way in one of them. */
.place__step--back::before { content: "\2039"; }
.place__step--on::before { content: "\203a"; }
.board[data-layout="horizontal"] .place__step--back::before { content: "\2039"; }
.board[data-layout="horizontal"] .place__step { transform: rotate(90deg); }
.place__x:hover, .place__pin:hover, .place__step:hover { color: var(--text); }
.place__x:disabled { opacity: 0.3; cursor: default; }
.place__x:disabled:hover { color: var(--faint); }
.place[data-home] .place__pin { color: var(--text); }

/* Picked up, and the row it would land on. Both are the drag saying what it is
   about to do, which a drag that showed nothing would leave the reader to find
   out by letting go. */
.place[data-carrying] { opacity: 0.4; }
.place[data-place][data-over] { box-shadow: inset 0 0 0 1px var(--board-pick); }
.place { cursor: grab; }
.place__x, .place__pin, .place__step { cursor: pointer; }
/* ...and nothing to grab under an answer, where the rows do not move. */
.clocks--inline .place { cursor: default; }

.place__named { min-width: 0; }
.place__line { display: flex; align-items: baseline; gap: 0.35rem; min-width: 0; }
.place__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place__at { text-align: right; }
.place__clock { font-variant-numeric: tabular-nums; }
.place__day { font-size: 0.8em; color: var(--muted); white-space: nowrap; }

/* ===== THE MARKS =====
   A grid item stretched over the cell it belongs in, with the line inside it
   at a percentage of that cell. Percentages inside a stretched item resolve
   against the item's own box, so the quarter-past mark lands a quarter of the
   way down the 10pm cell without anything knowing how tall a cell is. Nothing
   to remeasure when the window changes, and nothing to get wrong when it does. */
.board__mark { position: relative; pointer-events: none; z-index: 3; }
.board__mark i { position: absolute; display: block; }
.board__mark--now i { background: var(--board-now); }
.board__mark--pick i { background: var(--board-pick); }

/* ===== THE SELECTION =====
   Laid over the grid rather than placed in it, for two reasons that both come
   down to the same thing: it has to stand between two cells, which a grid item
   cannot do, and it has to move without the grid being touched, because it
   moves sixty times a second under a finger.

   Its position is written in pixels by paint(), off two numbers measured once
   per build. The `now` marker above is placed by the grid instead, since it
   moves once a minute and can afford to land on a cell. */
/* The stacking order on the board, top to bottom, and it is the whole of what
   decides which of two overlapping things wins:

     6  the picker's suggestion list, which opens over everything
     5  the pinned place headers, which never stop being readable
     4  the selection
     3  the now marker
     0  the cells

   The pair that matters is 5 over 4: the headers are pinned so they stay
   legible while the rest scrolls, and a selection dragged over them defeated
   the only reason they are pinned.

   Three, four and five are sealed inside .board__scroll and the sixth is not,
   which is the difference between content and an overlay and is why the seal
   is on that box rather than on .board. The prose pages hold their footer at
   the foot of the window, opaque and sticky, and the board scrolls under it
   like everything else on the page -- except that these numbers were being
   read against the whole document, so the now marker and the selection came
   out on top of it: an orange rule across the footer, under a board that had
   ended an inch above. Sealed, they are numbers about the picture and the
   picture goes under the footer whole. The suggestion list stays outside the
   seal on purpose: it opens downward out of a box near the bottom of the page
   and it is the one thing here that really does belong over the footer. */
.board__sel {
  position: absolute;
  z-index: 4;
  cursor: grab;
  touch-action: none;   /* or a phone scrolls the page instead of dragging it */
  display: flex;
  background: var(--board-sel-fill);
  border: 1px solid var(--board-pick);
  border-radius: 6px;
}
/* Focus, and where it can be drawn depends on which way the board is turned.

   Hours down, the bar is the width of the board and carries a reading per
   place, so a ring around it is a ring around something. Hours across, the
   bar is two pixels: a 2px outline held 2px off it is three parallel lines
   down the whole picture, and a reader met them the moment they moved the
   thing, since a drag focuses the handle. So that layout rings the knob
   instead, which is the part of the bar a pointer was aiming at anyway. */
.board__sel:focus-visible { outline: 2px solid var(--board-pick); outline-offset: 2px; }
.board[data-layout="horizontal"] .board__sel:focus-visible { outline: none; }
.board[data-layout="horizontal"] .board__sel:focus-visible .board__knob {
  outline: 2px solid var(--board-pick); outline-offset: 2px;
}
/* And no ring at all for the reader who arrived by pointer, which is the
   other half of the same fault. A ring says where the keyboard is. Chrome
   hands :focus-visible to anything focused from script, and picking the bar
   up focuses it from script, so every drag ended in a ring nobody had asked
   for. The pointer says so on the way in and this leaves the ring off while
   it does, which is what :focus-visible would have done unaided if the focus
   had come from the pointer rather than from the line of code the pointer
   ran. The same for the picker below, a <select> being the other control the
   browser rings on a plain click. */
.board__sel[data-by="pointer"]:focus-visible,
.board[data-layout="horizontal"] .board__sel[data-by="pointer"]:focus-visible .board__knob,
.board__span select[data-by="pointer"]:focus-visible {
  outline: none;
}
body.ui-drag .board__sel { cursor: grabbing; }

/* Hours down: a bar the width of the board, its top edge the selected instant,
   carrying a reading per place. A moment gets the bar's own height, which is
   what it needs to hold the readings; a range grows downwards from there. */
.board[data-layout="vertical"] .board__sel {
  left: 0; right: 0;
  min-height: 2.1rem;
  align-items: center;
  transform: translateY(-50%);
  background: var(--bg);
  padding: 0.15rem 0.4rem;
  box-shadow: 0 1px 8px rgb(0 0 0 / 0.16);
}
.board[data-layout="vertical"] .board__sel[data-span="range"] {
  transform: none;
  align-items: flex-start;
  background: var(--board-sel-fill);
}

/* Hours across: a box from start to end, which for a moment is a hairline.
   The readings are not in here because each row already prints its own. */
.board[data-layout="horizontal"] .board__sel {
  top: 0; bottom: 0;
  transform: translateX(-1px);
}
.board[data-layout="horizontal"] .board__read,
.board[data-layout="horizontal"] .board__clear { display: none; }

/* The edges, which resize rather than move. Wider than they look, because a
   two-pixel target is a target nobody hits: the hit area is a third of an
   inch and the ink inside it is a line. */
.board__grip { position: absolute; }
.board__grip::after {
  content: ""; position: absolute; border-radius: 999px;
  background: var(--board-pick);
}
.board[data-layout="vertical"] .board__grip {
  left: 0; right: 0; height: 14px; cursor: ns-resize;
}
.board[data-layout="vertical"] .board__grip--start { top: -7px; }
.board[data-layout="vertical"] .board__grip--end { bottom: -7px; }
.board[data-layout="vertical"] .board__grip::after {
  left: 50%; top: 50%; width: 28px; height: 3px; margin: -1.5px 0 0 -14px;
}
/* Below the cap, and this is the whole fix.

   Hours across draws a moment two pixels wide and a half hour twenty-seven,
   and these grips are fourteen each. They straddled the edges, so on anything
   shorter than an hour they covered the bar from side to side: every drag
   resized the selection and none of them moved it. Two targets in the same
   pixels are one target, and the one that won was not the one a hairline
   needs. So the top of the bar is the knob's and the rest is theirs. */
.board[data-layout="horizontal"] .board__grip {
  top: var(--board-knob); bottom: 0; width: 14px; cursor: ew-resize;
}
.board[data-layout="horizontal"] .board__grip--start { left: -7px; }
.board[data-layout="horizontal"] .board__grip--end { right: -7px; }
.board[data-layout="horizontal"] .board__grip::after {
  top: 50%; left: 50%; width: 3px; height: 28px; margin: -14px 0 0 -1.5px;
}
/* A moment has no length, so its two edges are in the same place and only one
   of them can be grabbed. The trailing one is the one that means anything:
   pulling it is how a moment becomes a meeting. */
.board__sel[data-span="moment"] .board__grip--start { display: none; }

/* ===== THE KNOB =====
   What a two-pixel bar is moved by.

   Hours down needs nothing like it: the bar there is the width of the board
   and carries a reading per place, so there is always something to take hold
   of. Hours across is the layout where the selection can be a hairline, and a
   hairline is not a handle.

   It stands on the top of the bar rather than in a strip above the board,
   because this layout has no strip: the rows are places and the first of them
   starts at the top of the grid. So it is drawn as a wash with an outline
   rather than as a block, and the cell it stands on is read through it.

   Wide enough to hit at any span, and the same size whether the selection is
   an instant or four hours, which is the point of it: the thing that moves
   the selection stops changing size with the selection. */
.board__knob { display: none; }
.board[data-layout="horizontal"] .board__knob {
  display: block; position: absolute;
  top: 0; left: 50%; width: 54px; margin-left: -27px;
  height: var(--board-knob);
  background: var(--board-knob-fill);
  border: 1px solid var(--board-pick);
  /* Rounded at the head and square at the foot, so it reads as sitting on the
     bar rather than floating over the board. */
  border-radius: 9px 9px 2px 2px;
  /* A light ring outside the dark outline, because the ground under this
     changes: half the cells on a board are the night band, which is nearly
     the colour of the outline. One line each way and it reads on both. */
  box-shadow: 0 0 0 1px var(--bg);
  cursor: grab;
}
body.ui-drag .board__knob { cursor: grabbing; }
/* Three strokes, because a wash with a line under it could be a highlight
   somebody left on the hours. Strokes say it is a thing to take hold of. */
.board[data-layout="horizontal"] .board__knob::after {
  content: ""; position: absolute;
  top: 50%; left: 50%; width: 2px; height: 11px; margin: -5.5px 0 0 -1px;
  border-radius: 999px; background: var(--board-pick);
  /* One stroke drawn and two copied, and then the same three again a pixel
     wider in the page's own colour. Shadows paint behind the box and in the
     order they are written, so the wide pale ones come out as an outline
     round the narrow dark ones, which is what keeps all three legible over a
     midnight cell and over an empty afternoon alike. */
  box-shadow:
    5px 0 0 var(--board-pick), -5px 0 0 var(--board-pick),
    0 0 0 1px var(--bg), 5px 0 0 1px var(--bg), -5px 0 0 1px var(--bg);
}
/* A fingertip is not a pointer, and this is the target that has to be hit
   first. The grips widen with it, since they start where it ends. */
@media (pointer: coarse) {
  /* The height goes through the variable and not through this rule, or the
     grips would still start where the smaller knob ended and the two would
     overlap by half a centimetre. */
  .board[data-layout="horizontal"] { --board-knob: 44px; }
  .board[data-layout="horizontal"] .board__knob { width: 66px; margin-left: -33px; }
  .board[data-layout="horizontal"] .board__grip { width: 22px; }
  .board[data-layout="horizontal"] .board__grip--start { left: -11px; }
  .board[data-layout="horizontal"] .board__grip--end { right: -11px; }
}

/* The readings inside the bar, one per place, on the same track widths the
   columns use so each sits under the place it belongs to. */
.board__read {
  flex: 1; min-width: 0;
  display: grid;
  grid-template-columns: repeat(var(--places, 3), minmax(5.5rem, 1fr));
  font-size: 0.8125rem;
}
.board__reading {
  display: flex; align-items: baseline; justify-content: center; gap: 0.3rem;
  min-width: 0; font-variant-numeric: tabular-nums;
}
.board__reading-day { font-size: 0.72em; color: var(--muted); }
.board__reading-clock { font-weight: 500; }
.board[data-layout="vertical"] .board__sel[data-span="range"] .board__read { display: none; }

.board__clear {
  flex: none; display: inline-flex; align-items: center; padding: 0.2rem;
  color: var(--faint); background: none; border: 0; cursor: pointer;
}
.board__clear:hover { color: var(--text); }

/* How long the selection runs. A native select, so it is keyboard operable,
   screen-reader operable and translated into the reader's own language
   without a line of code here. */
.board__span select { padding-block: 0.2rem; }

/* A row whose own clock disagrees with how long the selection is, which
   happens on the two mornings a year a clock moves inside it. Marked rather
   than corrected: six hours of elapsed time really does run to a wall reading
   seven hours later, and the honest number is the elapsed one. */
.place__at[data-shifted] .place__clock { text-decoration: underline dotted; }
.place__at[data-over] .place__day { color: var(--board-now); }

/* ===== THE 24-HOUR FACE =====
   The meridiem is hidden rather than left out, so it keeps its space and the
   band does not reflow when the switch is thrown. A board that jumped an
   eighth of an inch every time somebody changed the face would make the
   switch feel like a mistake. */
.board[data-face="24"] .cell__meridiem { visibility: hidden; }

/* ===== THE LINE UNDERNEATH =====
   The deliverable of the whole thing: a converted time is looked up in order
   to be sent to somebody. */
/* ===== TAKING IT AWAY =====
   The line, and the four ways of getting it out of the page. Under an answer
   too, which is a reversal: the row was folded away there on the grounds that
   the answer above is already the copyable thing.

   True of the line and of nothing else in the row. Nobody types a time
   conversion in order to read it; they type it to put the meeting in a
   calendar, and the calculator's answer to "3pm tokyo in london" was a number
   and a full stop. The four here are the difference between reading the answer
   and acting on it, and the nearest one was a page away.

   Two of them mean something slightly different in this form and both are
   handled next door in clocks.js: the link points at /time, since the
   calculator keeps its own query in the fragment and cannot be sent a board in
   it, and it always names the instant, since the instant came from the
   question rather than from a reader who moved off now. */
.board__outs {
  width: var(--bar);
  margin-left: calc((100% - var(--bar)) / 2);
  margin-top: 0.5rem;
  display: flex; flex-wrap: wrap; gap: 0.4rem;
}

/* The four tools on each row go too, and they are the least obvious of the
   things that go. They are not chrome: dropping a place or moving home changes
   which board this is, and the board under an answer is the board that answer
   is about. A reader who pinned home to London here would be left with a
   picture measured from London under a headline measured from Tokyo, and the
   only way back would be to retype the question. display:none rather than a
   disabled state, so they leave the tab order with it. */
.clocks--inline .place__tools { display: none; }

/* The anchor among the buttons. .pill is written for a button, so the two
   things an anchor brings of its own have to come back off. */
.board__outs a.pill { text-decoration: none; }
.board__outs a.pill:hover { text-decoration: none; }

.board__summary {
  /* Pinned to the bar's width for the same reason the bar is: this is a line
     of prose about the picture, not part of it, and left at the wide board's
     width it started half a screen to the left of every other line of type on
     the page. */
  width: var(--bar);
  margin-left: calc((100% - var(--bar)) / 2);
  margin-top: 0.75rem;
  font-size: 0.875rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
