/* Buy The World — the sheet and the album leaf.
   Squares are stamps: printed on gummed paper, punched with perforations, sold
   at a face value, mounted on dark album card. The rail is a sheet; each panel
   is a pane separated by gutters; status lives in the selvedge marginalia the
   way a printer's registration marks and plate numbers do. */

:root {
  /* Album card — warm near-black, the leaf a collection is mounted on. */
  --leaf:        #16120e;
  --leaf-2:      #1e1813;
  --leaf-3:      #272019;

  /* Gummed paper — the stamp face itself. */
  --gum:         #f3ecdd;
  --gum-2:       #e6dcc7;
  --gum-ink:     #17130d;

  /* Ink on the leaf. */
  --text:        #ece4d5;
  --text-dim:    #b3a692;
  --text-faint:  #7d7263;

  /* Signal: carmine, the classic definitive ink. Carries every primary action. */
  --carmine:     #d0405a;
  --carmine-lit: #e65b74;
  --carmine-ink: #2a0a11;
  --carmine-dim: #4a1a24;

  /* Information: ultramarine, the airmail overprint. */
  --marine:      #5b8fd4;
  --marine-dim:  #23334c;

  /* Brand, unchanged: the globe's own language. */
  --amber:       #e8a13c;
  --amber-dim:   #4a3717;
  --land:        #7cb56d;

  --rule:        #33291f;
  --rule-lit:    #4a3c2c;

  --perf:        7px;    /* perforation hole diameter */
  --perf-gap:    12px;   /* pitch between holes */
  --r:           2px;

  --shadow-leaf: 0 1px 2px rgba(0, 0, 0, .5), 0 10px 28px -14px rgba(0, 0, 0, .9);
  --shadow-lift: 0 2px 4px rgba(0, 0, 0, .5), 0 18px 40px -18px rgba(0, 0, 0, .95);

  color-scheme: dark;
}

* { box-sizing: border-box; }

/* Every display rule below would otherwise outrank the hidden attribute, and a
   panel that hides itself by setting .hidden would stay on screen. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--leaf);
  color: var(--text);
  font-family: "Familjen Grotesk", "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

button, input, select, textarea { font: inherit; }

a { color: var(--marine); text-underline-offset: 2px; }
a:hover { color: #82abe0; }

.mono {
  font-family: "Azeret Mono", ui-monospace, Menlo, Consolas, monospace;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* Perforation: punched out of the panel edge, not drawn on it. Two masks —
   one keeps the panel body, the other bites the holes out along an edge. */
.perf-top,
.perf-bottom { position: relative; }

.perf-top::before,
.perf-bottom::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: var(--perf);
  background: var(--leaf);
  -webkit-mask-image: radial-gradient(circle at var(--perf-gap) 50%,
                #000 calc(var(--perf) / 2), transparent calc(var(--perf) / 2 + .5px));
  mask-image: radial-gradient(circle at var(--perf-gap) 50%,
                #000 calc(var(--perf) / 2), transparent calc(var(--perf) / 2 + .5px));
  -webkit-mask-size: calc(var(--perf-gap) * 2) 100%;
  mask-size: calc(var(--perf-gap) * 2) 100%;
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  pointer-events: none;
}
.perf-top::before { top: calc(var(--perf) / -2); }
.perf-bottom::after { bottom: calc(var(--perf) / -2); }

/* ---------------------------------------------------------------- layout */

/* The stage and the sheet are the two named areas; the wordmark and the account
   links are laid into the stage's own area rather than positioned absolutely
   inside it. That is what makes the stacked layout possible further down - a
   grid item can be moved to a row of its own, and an absolutely positioned
   overlay cannot. It is also what stops the wordmark outgrowing the stage: on a
   phone the plate stood 370px tall in a 260px stage and hung over the sheet. */
.app {
  display: grid;
  grid-template-columns: 1fr 372px;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "brand sheet"
    "stage sheet";
  height: 100dvh;
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/* The bar. One row across the top at every width, holding the three things that
   are about the site rather than about a square: whose it is, how long it has
   left, and the way into an account.

   A real grid row rather than a third overlay floating in the stage. Two
   overlays sharing a corner is the mistake this file already records once; a
   row cannot collide with anything, and the map simply starts under it. */
.topbar {
  grid-area: brand;
  display: flex;
  align-items: baseline;
  gap: 18px;
  padding: 13px 20px 12px;
  background: var(--leaf);
  border-bottom: 1px solid var(--rule);
  min-width: 0;
}
.topbar h1 {
  margin: 0;
  font-family: "Bodoni Moda", Georgia, serif;
  font-size: 25px;
  font-weight: 600;
  letter-spacing: .005em;
  line-height: 1.05;
  white-space: nowrap;
}
/* The links go to the far end, so the clock ends up beside the wordmark rather
   than adrift in the middle: the two things that are about the site read as one
   group, and the way into an account stays where an account link belongs. */
.topbar .ledger { margin-left: auto; }

/* The countdown, in the one place on the page that is always in view. Short
   units because a bar has no room for a sentence - the long form is behind the
   plate's fold, and the aria-label on the element carries it besides.
   Carmine for the figures, as everywhere: it is the definitive ink and this is
   the most definitive thing on the page. Never amber, which is the globe's. */
.clockbar {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 9px;
  min-width: 0;
}
.clockbar .tick { white-space: nowrap; }
/* The label the figures answer to. Selvedge mono caps, so it reads as the
   caption on a plate rather than a second headline competing with the
   wordmark, and it drops out when the clock has run out - "this site will live
   for: no time left" is not a sentence anybody should have to parse. */
.clockbar .lede {
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: 9.5px;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--text-faint);
  white-space: nowrap;
}
.clockbar.out .lede { display: none; }
.clockbar b {
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: 17px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--carmine-lit);
  letter-spacing: -.01em;
}
.clockbar i {
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-style: normal;
  font-size: 11px;
  color: var(--text-faint);
  margin-left: 1px;
}
.clockbar.last-day b { color: var(--carmine); }
.clockbar.out b, .clockbar.out { color: var(--carmine); font-size: 13px; }

.stage { grid-area: stage; position: relative; background: #0d1a24; min-width: 0; }
#map { position: absolute; inset: 0; }

/* Outside the globe the map's canvas is transparent, so the stage's night blue
   is what space is made of. The stars are painted under the map and brought up
   by globe.js as the globe pulls back - close in, there is no space to see. */
#stars {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
}

/* The atmosphere: a ring of light sitting just outside the globe's edge, drawn
   under the map so the globe itself covers all of it but the rim. Its box is
   set by globe.js, which has to measure where that edge actually is - see
   `limbRadius`. Over the stars rather than under them, because that is the
   order the real ones are in. */
#halo {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  border-radius: 50%;
  background: radial-gradient(closest-side circle at 50% 50%,
              rgba(143, 200, 234, 0) 0 74%,
              rgba(143, 200, 234, .18) 78%,
              rgba(143, 200, 234, .07) 86%,
              rgba(143, 200, 234, 0) 100%);
}

/* MapLibre ships white chrome; bring it onto the leaf. */
.maplibregl-ctrl-attrib {
  font-family: "Azeret Mono", monospace !important;
  font-size: 9.5px !important;
  background: color-mix(in srgb, var(--leaf) 86%, transparent) !important;
  color: var(--text-faint) !important;
  border-radius: var(--r) 0 0 0 !important;
  padding: 3px 7px !important;
}
.maplibregl-ctrl-attrib a { color: var(--text-dim) !important; }
.maplibregl-ctrl-attrib-button { filter: invert(1) opacity(.55); }

.maplibregl-ctrl-group {
  background: color-mix(in srgb, var(--leaf) 88%, transparent) !important;
  border: 1px solid var(--rule) !important;
  border-radius: var(--r) !important;
  box-shadow: var(--shadow-leaf) !important;
  overflow: hidden;
}
.maplibregl-ctrl-group button + button { border-top: 1px solid var(--rule) !important; }
.maplibregl-ctrl-group button { background: transparent !important; width: 30px !important; height: 30px !important; }
.maplibregl-ctrl-group button:hover { background: var(--leaf-3) !important; }
.maplibregl-ctrl-group button:focus-visible { outline: 2px solid var(--marine) !important; outline-offset: -2px; }
.maplibregl-ctrl-group button .maplibregl-ctrl-icon { filter: invert(1) opacity(.62); }
.maplibregl-ctrl-group button:hover .maplibregl-ctrl-icon { filter: invert(1) opacity(.92); }

/* Marking, offered beside the zoom pair - where a hand already is while
   somebody is looking around, and the one place on the map that is already
   chrome rather than world. It is deliberately quiet: an icon the size of a
   zoom button, and a number only once something is marked. Nothing here asks
   anybody to buy more.

   Marine when engaged, which is this interface's ink for a mode being held
   open - never amber or green, which belong to the map itself. */
.maplibregl-ctrl-group button.mark-ctrl {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: auto !important;
  min-width: 30px;
  padding: 0 6px;
  color: var(--text-dim);
}
.mark-ctrl svg { width: 15px; height: 15px; flex: none; }
.mark-ctrl:hover { color: var(--text); }
.mark-ctrl.on { color: var(--marine); background: color-mix(in srgb, var(--marine) 16%, transparent) !important; }
.mark-ctrl .n {
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.mark-ctrl .n:empty { display: none; }

/* ---------------------------------------------------------- opening soon */
/* The page somebody early gets. An album leaf and the wordmark, and the
   countdown set in the same carmine mono as the doomsday clock - it is the same
   kind of fact, and this is the first thing anybody will ever have seen of this
   site, so it should already look like the site. */
.launching {
  max-width: 34rem;
  margin: 0 auto;
  padding: clamp(48px, 14vh, 120px) 22px 60px;
  text-align: left;
}
.launching h1 {
  margin: 0 0 30px;
  font-family: "Bodoni Moda", Georgia, serif;
  font-size: clamp(30px, 7vw, 44px);
  font-weight: 600;
  line-height: 1.05;
  color: var(--text);
}
.launching .lede {
  margin: 0 0 10px;
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.launching .dial {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 14px;
  row-gap: 5px;
}
.launching .dial .tick { white-space: nowrap; }
.launching .dial b {
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: clamp(30px, 9vw, 44px);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--carmine-lit);
  letter-spacing: -.02em;
}
.launching .dial i {
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-style: normal;
  font-size: 11px;
  color: var(--text-faint);
  margin-left: 5px;
}
.launching .dial.out b { color: var(--carmine); }
.launching .blurb {
  margin: 26px 0 0;
  font-size: 15px;
  line-height: 1.62;
  color: var(--text-dim);
}
.launching .notice { margin-top: 18px; font-size: 12.5px; color: var(--text-faint); }
.launching .notice a { color: var(--marine); }

/* ------------------------------------------------------------ the welcome */
/* The one modal on the site, shown once to somebody who has never been here.
   An album-leaf panel like the plate rather than gummed paper: gum is for a
   square's own facts, and this is about the site. It is deliberately not a
   stamp - nothing is being bought here, so it carries no perforation and no
   denomination. */
.welcome {
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100dvh - 48px);
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: auto;
  padding: 26px 30px 24px;
  border: 1px solid var(--rule-lit);
  border-radius: var(--r);
  background: var(--leaf-2);
  color: var(--text-dim);
  box-shadow: 0 18px 60px rgba(0, 0, 0, .55);
}
.welcome::backdrop {
  background: rgba(8, 6, 4, .62);
  backdrop-filter: blur(3px);
}
.welcome h2 {
  margin: 0 34px 4px 0;
  font-family: "Bodoni Moda", Georgia, serif;
  font-size: 27px;
  font-weight: 600;
  line-height: 1.1;
  color: var(--text);
}
.welcome p { font-size: 14px; line-height: 1.62; margin: 12px 0 0; }
.welcome .thesis { color: var(--text); }
.welcome .whatitis b { color: var(--text); font-weight: 600; }
.welcome .acts { margin-top: 20px; }
/* The phone's fold. Same component as the plate's, so it keeps the rule above
   and only its spacing changes: a dialog holds more air around its prose than
   a panel does, and the rule it draws should read as a break in the text
   rather than the lid of the button below it. */
.welcome .unfold { margin-top: 16px; }
.welcome .unfold + .acts { margin-top: 14px; }
.welcome .notice { font-size: 11.5px; color: var(--text-faint); margin-top: 12px; }

/* The cross. Its own form so it submits the dialog closed with no script, and
   in the corner at a size a thumb can hit - a modal has to be easier to leave
   than to read. */
.welcome-shut { float: right; margin: -8px -10px 0 0; }
.welcome .x {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: var(--r);
  background: none;
  color: var(--text-faint);
  cursor: pointer;
}
.welcome .x svg { width: 15px; height: 15px; }
.welcome .x:hover { color: var(--text); background: var(--leaf-3); }
.welcome .x:focus-visible { outline: 2px solid var(--marine); outline-offset: 2px; }

/* A dialog that is open without showModal - no <dialog> support - is a plain
   block in the flow rather than a centred overlay. Put it back over the page.

   Keyed on a class the script adds, not on `:not(:modal)`. A browser old enough
   to lack <dialog> lacks `:modal` too, which makes that selector invalid there
   and throws the whole rule away - in exactly the browser it was written for. */
.welcome.plain[open] {
  position: fixed;
  inset: 20px auto auto 50%;
  transform: translateX(-50%);
  z-index: 20;
}

@media (prefers-reduced-motion: no-preference) {
  .welcome[open] { animation: settle .34s cubic-bezier(.16, 1, .3, 1); }
}

@media (max-width: 560px) {
  .welcome { padding: 20px 18px 18px; }
  .welcome h2 { font-size: 24px; }
  .welcome p { font-size: 13.5px; }
}

/* ---------------------------------------------------------- the wordmark */

.plate {
  grid-area: stage;
  align-self: start;
  justify-self: start;
  z-index: 3;
  margin: 20px 0 0 22px;
  /* Against the stage row, not the viewport. It was `100dvh - 40px`, which was
     right while the plate started at the top of the window and 49px too tall
     the moment a bar appeared above it. */
  max-height: calc(100% - 40px);
  /* A column so the fold can be the part that gives. `max-height` alone left
     the panel capped and its content `overflow: visible`, so on any window
     under about 850px tall the welcome printed straight out through the bottom
     of the plate onto the map - no background behind it, and no way to reach
     the end of it. That was harmless while the fold was shut by default and
     became a live defect the moment it opened for every first visit. */
  display: flex;
  flex-direction: column;
  min-height: 0;
  pointer-events: none;
  max-width: min(44ch, 60%);
  background: color-mix(in srgb, var(--leaf) 88%, transparent);
  backdrop-filter: blur(7px);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 13px 17px 14px;
  box-shadow: var(--shadow-leaf);
}

/* The plate is click-through so the globe can be dragged behind it, and every
   descendant inherits that - which was fine while the plate held nothing but
   prose. The search box was added inside it and was simply not clickable on any
   screen wide enough for the overlay layout: the press went through to the map
   canvas. Only the parts meant to be pressed get it back, so dragging the globe
   across the wordmark and the folded copy still works.

   Anything interactive added to the plate has to be named here, or it will look
   right and do nothing. */
.plate .find,
.plate .find-list,
.plate .acts,
.plate .more,
.plate .unfold { pointer-events: auto; }

/* The mark control sits directly under the search: the two ways in, together,
   before the clock. Tighter to the search than a pane's action row would be,
   because they are one group rather than two things that happen to follow. */
.plate .plate-acts { margin-top: 8px; }

.plate p {
  margin: 7px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-dim);
  max-width: 40ch;
}

/* What the person reading has bought the map. Their own squares, which is the
   one count this site does tell: no total is published anywhere. */
.plate .contributed {
  margin: 11px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--text-dim);
}
.plate .contributed b {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* The selvedge strip: a printer's colour bar, doubling as the live counter. */
.selvedge {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 11px;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
  font-family: "Azeret Mono", monospace;
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* A sheet printed for reference rather than for postage is overprinted
   SPECIMEN. Shown only while Stripe is in test mode. */
.specimen {
  border: 1px solid var(--carmine);
  color: var(--carmine);
  border-radius: 1px;
  padding: 1px 5px;
  letter-spacing: .18em;
  font-size: 9px;
}

.bars { display: flex; gap: 3px; }
.bars i {
  width: 9px;
  height: 9px;
  border-radius: 1px;
  display: block;
}
.bars i:nth-child(1) { background: var(--carmine); }
.bars i:nth-child(2) { background: var(--marine); }
.bars i:nth-child(3) { background: var(--amber); }
.bars i:nth-child(4) { background: var(--land); }

/* -------------------------------------------------------------- top bar */

.ledger {
  display: flex;
  gap: 6px;
  align-items: center;
  flex: none;
}

.ledger a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--text);
  text-decoration: none;
  background: color-mix(in srgb, var(--leaf) 88%, transparent);
  backdrop-filter: blur(7px);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 7px 12px;
  font-size: 12.5px;
  transition: border-color .14s ease, background .14s ease;
}
.ledger a:hover { border-color: var(--rule-lit); background: var(--leaf-2); color: var(--text); }
.ledger .who {
  color: var(--text-faint);
  padding: 8px;
  font-family: "Azeret Mono", monospace;
  font-size: 11px;
}

/* ------------------------------------------------------------- the sheet */

.sheet {
  grid-area: sheet;
  background: var(--leaf-2);
  border-left: 1px solid var(--rule);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-lit) transparent;
}

/* Panes are separated by gutters, the way panes on a sheet are. */
/* One square or several. Two tabs sharing a rule with the pane below, so the
   sheet reads as a thing with two faces rather than as a panel with a widget on
   top of it. Carmine on the selected one - it is the definitive ink and this is
   the most definitive choice on the sheet: it decides what a click does. */
.modes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: 1px solid var(--rule);
}
.mode {
  appearance: none;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  padding: 13px 10px 11px;
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--text-faint);
  cursor: pointer;
}
.mode + .mode { border-left: 1px solid var(--rule); }
.mode:hover { color: var(--text-dim); }
.mode[aria-selected="true"] {
  color: var(--carmine-lit);
  border-bottom-color: var(--carmine);
  background: color-mix(in srgb, var(--carmine) 7%, transparent);
}
.mode:focus-visible { outline: 2px solid var(--marine); outline-offset: -2px; }
.mode .val { color: var(--text-dim); letter-spacing: .06em; }
.mode[aria-selected="true"] .val { color: var(--carmine-lit); }

/* The two screens carry no chrome of their own - the panes inside them already
   have it, and a border here would double every rule on the sheet. */
#screenOne, #screenMany { display: contents; }

.pane { padding: 18px 20px 20px; border-bottom: 1px solid var(--rule); }
.pane:last-child { border-bottom: 0; }

.pane > h2 {
  margin: 0 0 14px;
  font-family: "Azeret Mono", monospace;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--text-faint);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}
.pane > h2 .val { color: var(--text-dim); letter-spacing: .06em; }

/* --------------------------------------------------------- the stamp itself */

.stamp {
  background: var(--gum);
  color: var(--gum-ink);
  border-radius: var(--r);
  padding: 15px 16px 16px;
  box-shadow: var(--shadow-leaf);
  --perf: 8px;
  --perf-gap: 11px;
}

.stamp .denom {
  float: right;
  font-family: "Bodoni Moda", Georgia, serif;
  font-size: 26px;
  font-weight: 600;
  line-height: 1;
  color: var(--carmine);
  margin: -2px 0 0 12px;
}

.stamp .catalogue {
  font-family: "Azeret Mono", monospace;
  font-size: 23px;
  font-weight: 500;
  letter-spacing: -.02em;
  line-height: 1.1;
  word-break: break-all;
}
.stamp .catalogue.empty { font-size: 14px; color: #6d6455; letter-spacing: 0; }

.stamp .inscription {
  font-family: "Azeret Mono", monospace;
  font-size: 10.5px;
  letter-spacing: .05em;
  color: #6d6455;
  margin-top: 4px;
  word-break: break-all;
}

.facts { display: grid; gap: 6px; margin-top: 13px; }
.fact { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.fact .k { font-size: 12px; color: #6d6455; }
.fact .v {
  font-family: "Azeret Mono", monospace;
  font-size: 12px;
  text-align: right;
  color: var(--gum-ink);
}
.fact .v.off { color: #9a8f7c; }

/* The image sits in the stamp's vignette, perforated on both edges. */
.vignette {
  margin-top: 14px;
  width: 100%;
  aspect-ratio: 1;
  background: var(--gum-2) center / cover no-repeat;
  border-radius: 1px;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 18px;
  font-family: "Azeret Mono", monospace;
  font-size: 10px;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: #8a7f6c;
  box-shadow: inset 0 0 0 1px rgba(23, 19, 13, .1);
}
.vignette.filled { color: transparent; }

/* --------------------------------------------------------------- controls */

.acts { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 13px; }
.acts:not(:has(> *:not([hidden]))) { display: none; }

.btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  background: var(--leaf-3);
  color: var(--text);
  border: 1px solid var(--rule-lit);
  border-radius: var(--r);
  padding: 9px 13px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.btn:hover:not(:disabled) { background: #33291f; border-color: #5c4b37; }
.btn:focus-visible { outline: 2px solid var(--marine); outline-offset: 2px; }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn[hidden] { display: none; }
.btn svg { width: 14px; height: 14px; flex: none; }

.btn.primary {
  background: var(--carmine);
  border-color: var(--carmine);
  color: #fff;
  font-weight: 600;
}
.btn.primary:hover:not(:disabled) { background: var(--carmine-lit); border-color: var(--carmine-lit); }
.btn.primary:disabled { background: var(--carmine-dim); border-color: var(--carmine-dim); color: #a88790; opacity: 1; }

.btn.on { background: var(--marine-dim); border-color: var(--marine); color: #bcd4f2; }
.btn.slim { flex: 0 0 auto; }

/* On the gum, buttons are printed rather than lit. */
.stamp .btn { background: transparent; border-color: rgba(23, 19, 13, .28); color: var(--gum-ink); }
.stamp .btn:hover:not(:disabled) { background: rgba(23, 19, 13, .07); border-color: rgba(23, 19, 13, .5); }
.stamp .btn.primary { background: var(--carmine); border-color: var(--carmine); color: #fff; }
.stamp .btn.primary:hover:not(:disabled) { background: #b83450; border-color: #b83450; }
.stamp .btn.primary:disabled { background: #d9b3bb; border-color: #d9b3bb; color: #7d5a62; }

/* ----------------------------------------------------------------- fields */

.field { display: grid; gap: 5px; margin-top: 12px; }
.field label { font-size: 11.5px; color: #6d6455; }
.field input,
.field select,
.field textarea {
  width: 100%;
  background: rgba(23, 19, 13, .05);
  border: 1px solid rgba(23, 19, 13, .22);
  border-radius: var(--r);
  color: var(--gum-ink);
  padding: 8px 10px;
  font-size: 13px;
}
.field input::placeholder { color: #9a8f7c; }
.field input:focus,
.field select:focus,
.field textarea:focus { outline: none; border-color: var(--carmine); }
.field textarea { resize: vertical; min-height: 62px; }

/* Fields on the leaf rather than on the gum. */
.pane > .field input,
.pane > .field select,
.pane > .field textarea,
.onleaf input, .onleaf select, .onleaf textarea {
  background: var(--leaf);
  border-color: var(--rule-lit);
  color: var(--text);
}
.onleaf label { color: var(--text-faint); }

/* A .field dropped straight on a leafpage is on the dark leaf whether or not
   anybody remembered to write onleaf, and the gum ink it would otherwise take
   is #17130d on a #16120e ground: typed text invisible. The claim-code field on
   checkout_success was exactly that. Cards are gum, so they opt back out. */
.leafpage .field input,
.leafpage .field select,
.leafpage .field textarea {
  background: var(--leaf);
  border-color: var(--rule-lit);
  color: var(--text);
}
.leafpage .field label { color: var(--text-faint); }
.leafpage .field input::placeholder { color: var(--text-faint); }
.leafpage .card .field input,
.leafpage .card .field select,
.leafpage .card .field textarea {
  background: rgba(23, 19, 13, .05);
  border-color: rgba(23, 19, 13, .22);
  color: var(--gum-ink);
}
.leafpage .card .field label { color: #6d6455; }
.leafpage .card .field input::placeholder { color: #9a8f7c; }

.consent {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin-top: 12px;
  font-size: 11.5px;
  line-height: 1.5;
  color: #6d6455;
}
.consent input { margin-top: 2px; accent-color: var(--carmine); flex: none; }
.consent a { color: #8a5a66; }

/* ------------------------------------------------------------- the notice */

.notice {
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-dim);
  margin: 13px 0 0;
}
.stamp .notice { color: #6d6455; }
.stamp #testNote {
  background: rgba(208, 64, 90, .07);
  border: 1px solid rgba(208, 64, 90, .28);
  border-radius: var(--r);
  padding: 9px 11px;
  color: #7d3a47;
}
.stamp #testNote b { color: var(--carmine); font-weight: 600; }
.stamp #testNote .mono { color: #4a4237; font-size: .95em; }
.notice b { color: var(--text); font-weight: 500; }

/* ------------------------------------------------- why it is not live yet */
/* A printed slip on the gum, the same ink as the test-mode note, with a caret
   punched through its bottom edge at the button below. Both halves of the
   caret are mixed from the same two tokens as the slip itself, so the fill
   cannot drift from the paper it sits on when either one is retuned. */

.hint {
  position: relative;
  margin-top: 13px;
  padding: 9px 11px;
  border: 1px solid rgba(208, 64, 90, .28);
  border-radius: var(--r);
  background: color-mix(in srgb, var(--carmine) 7%, var(--gum));
}
.hint .ask {
  margin: 0;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--carmine);
}
.hint .why {
  margin: 5px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: #7d3a47;
}
.hint .why b { color: var(--gum-ink); font-weight: 600; }
.hint::before,
.hint::after {
  content: "";
  position: absolute;
  left: 17px;
  width: 0;
  height: 0;
  border: 7px solid transparent;
  border-bottom: 0;
}
.hint::before { bottom: -7px; border-top-color: rgba(208, 64, 90, .28); }
.hint::after { bottom: -6px; border-top-color: color-mix(in srgb, var(--carmine) 7%, var(--gum)); }
/* The row the caret is aimed at, pulled up under it. */
.hint + .acts { margin-top: 10px; }

/* ------------------------------------------------------- owner's caption */

.byline {
  margin-top: 13px;
  padding: 11px 12px;
  background: rgba(23, 19, 13, .05);
  border: 1px solid rgba(23, 19, 13, .14);
  border-radius: var(--r);
  font-size: 12.5px;
}
.byline .who {
  display: block;
  font-family: "Azeret Mono", monospace;
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--carmine);
  margin-bottom: 5px;
}
.byline .cap { color: #4a4237; line-height: 1.5; }
.byline a { display: inline-block; margin-top: 7px; font-size: 12px; word-break: break-all; color: #2f5fb0; }

/* ------------------------------------------------------------ the counter */

.gauge {
  height: 3px;
  background: var(--leaf);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 12px;
}
.gauge i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--amber);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .5s cubic-bezier(.16, 1, .3, 1);
}
@media (prefers-reduced-motion: reduce) { .gauge i { transition: none; } }

/* ------------------------------------------------------------------ chips */

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 11px; }
.chip {
  font-family: "Azeret Mono", monospace;
  font-size: 11.5px;
  background: var(--leaf);
  border: 1px solid var(--rule-lit);
  border-radius: var(--r);
  color: var(--text-dim);
  padding: 5px 9px;
  cursor: pointer;
  transition: border-color .14s ease, color .14s ease;
}
.chip:hover { border-color: var(--amber); color: var(--amber); }
.chip:focus-visible { outline: 2px solid var(--marine); outline-offset: 2px; }

/* ------------------------------------------------- the newest squares, rolling */

/* A grid item laid into the stage's area, exactly as the plate is - never
   `position: absolute` against the stage. That is the whole reason it can
   become a card at the top of the map on a phone instead of covering it: a
   grid item can be moved, an absolutely positioned overlay cannot.

   The plate takes the top of that area (`align-self: start`) and this takes the
   bottom, so on any screen wide enough to show both they cannot meet. Under the
   plate in the stack regardless: if a very short window ever does bring them
   together, the panel with the controls on it is the one that must win. */
.roll {
  grid-area: stage;
  align-self: end;
  justify-self: start;
  z-index: 2;
  margin: 0 0 20px 22px;
  width: min(318px, 42%);
  /* Click-through, like the plate and for the same reason: the globe has to be
     draggable across it. Only the rows take a press - see `.rollrow`. */
  pointer-events: none;
  background: color-mix(in srgb, var(--leaf) 88%, transparent);
  backdrop-filter: blur(7px);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: 10px 12px 11px;
  box-shadow: var(--shadow-leaf);
}

.roll-title {
  margin: 0 0 8px 7px;
  font-family: "Azeret Mono", monospace;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--text-faint);
}

/* What the roll happens behind. The row coming in is put at the head and the
   column is carried up by its own height before it is let down again, so the
   arriving row is never seen outside the frame and the leaving one is never
   seen to vanish - it goes under this edge. */
.roll-clip { overflow: hidden; }
.roll-list { display: flex; flex-direction: column; }

/* One square at a time, and the two of them share a cell so the change is a
   change rather than a gap. Stacking them in one grid area is what makes the
   outgoing and the incoming overlap. */
.roll.one .roll-list { display: grid; }
.roll.one .roll-list > * { grid-area: 1 / 1; }

.rollrow {
  /* The one thing in here that takes a press. Everything else is click-through
     so the globe keeps turning behind it. */
  pointer-events: auto;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  background: transparent;
  border: 0;
  border-left: 2px solid transparent;
  padding: 6px 7px;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: background-color .14s ease, border-color .14s ease;
}
.rollrow:hover { background: var(--leaf-2); border-left-color: var(--amber); }
.rollrow:focus-visible { outline: 2px solid var(--marine); outline-offset: -2px; }

/* The gum, at 32px. Square, because a square is what was bought. */
.rollface {
  flex: none;
  width: 32px;
  height: 32px;
  border-radius: 1px;
  background: var(--gum-2) center / cover no-repeat;
  box-shadow: inset 0 0 0 1px rgba(23, 19, 13, .12);
}
/* Bought, nothing printed on it: the dashed amber outline the map draws for
   the same cell, so the two say the same thing in the same colour. */
.rollface.blank {
  background: transparent;
  border: 1.5px dashed var(--amber);
  box-shadow: none;
}

.rolltext { min-width: 0; display: grid; gap: 1px; flex: 1 1 auto; }

.rolltop { display: flex; align-items: baseline; gap: 8px; }
.rolltop b {
  font-weight: 500;
  font-size: 12.5px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Two lines and always two: a column that rolls by a row's height cannot
   measure a height that changes per row, and a phone's single card would grow
   and shrink under the bar as it cycled. So this is the caption when there is
   one and where the square is when there is not - a stranger's words in the
   reading hand, coordinates in the one the stamp's own facts are set in. */
.rollsecond {
  font-family: "Azeret Mono", monospace;
  font-size: 10px;
  color: var(--text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rollsecond.said {
  font-family: inherit;
  font-size: 11.5px;
  color: var(--text-dim);
}

/* The phone's change: the one standing fades out at once and the next rises in
   behind it, overlapping through the middle. The delay on the incoming used to
   be long enough to clear the outgoing completely, which left the card holding
   nothing but its heading for a quarter of a second every five seconds - and an
   empty box reads as a fault, not as a pause. Written as a delay rather than as
   a second timer in script, so a browser that has been asked for less motion
   can take the whole thing away in one rule below. */
.roll.one .rollrow {
  transition: opacity 680ms ease 140ms,
              transform 680ms cubic-bezier(.16, 1, .3, 1) 140ms;
}
.roll.one .rollrow.coming { opacity: 0; transform: translateY(9px); }
.roll.one .rollrow.going {
  opacity: 0;
  transform: translateY(-7px);
  transition: opacity 420ms ease, transform 420ms ease;
  pointer-events: none;
}

/* Asked for less motion: it stops rolling in script, and nothing here moves
   either - a row that is put in place still arrives instantly rather than
   sliding. */
@media (prefers-reduced-motion: reduce) {
  .roll-list { transition: none !important; }
  .roll.one .rollrow,
  .roll.one .rollrow.going { transition: none; }
}

/* ------------------------------------------------------------- the legend */

.legend { display: grid; gap: 9px; }
.key { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--text-dim); }
.key .sw { width: 16px; height: 10px; border-radius: 1px; flex: none; }
/* Bought and blank: the outline the map draws, at legend size. */
.key .sw.ring {
  background: transparent;
  border: 1.5px dashed var(--amber);
  box-sizing: border-box;
}
.key .sw.hatch {
  background-image: repeating-linear-gradient(45deg,
    var(--marine) 0 2px, transparent 2px 4px);
  background-color: var(--marine-dim);
}

/* --------------------------------------------------------------- the boot */

#boot {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: grid;
  place-items: center;
  background: var(--leaf);
  font-family: "Azeret Mono", monospace;
  font-size: 12px;
  color: var(--text-dim);
  letter-spacing: .09em;
  text-align: center;
  padding: 32px;
  line-height: 2;
}

/* One authored moment: the sheet arrives as if laid onto the leaf. */
@media (prefers-reduced-motion: no-preference) {
  .sheet > .pane {
    animation: settle .5s cubic-bezier(.16, 1, .3, 1) backwards;
  }
  .sheet > .pane:nth-child(1) { animation-delay: .02s; }
  .sheet > .pane:nth-child(2) { animation-delay: .06s; }
  .sheet > .pane:nth-child(3) { animation-delay: .1s; }
  .sheet > .pane:nth-child(4) { animation-delay: .14s; }
  .sheet > .pane:nth-child(5) { animation-delay: .18s; }
  .plate { animation: settle .6s cubic-bezier(.16, 1, .3, 1) backwards .1s; }
}

@keyframes settle {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ plain pages */

.leafpage {
  max-width: 72ch;
  margin: 0 auto;
  padding: 52px 26px 96px;
  height: 100dvh;
  overflow-y: auto;
}
.leafpage h1 {
  font-family: "Bodoni Moda", Georgia, serif;
  font-size: 34px;
  font-weight: 600;
  letter-spacing: -.005em;
  margin: 0 0 10px;
  text-wrap: balance;
}
.leafpage h2 {
  font-family: "Azeret Mono", monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--carmine);
  margin: 36px 0 10px;
}
.leafpage p, .leafpage li { color: var(--text-dim); font-size: 15px; line-height: 1.68; }
.leafpage .lede { color: var(--text); font-size: 16.5px; }
.leafpage .back {
  font-family: "Azeret Mono", monospace;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--text-faint);
}
.leafpage .back:hover { color: var(--text); }
.leafpage code {
  font-family: "Azeret Mono", monospace;
  font-size: .86em;
  background: var(--leaf-2);
  border: 1px solid var(--rule);
  border-radius: var(--r);
  padding: .1em .35em;
}

.collection { display: grid; grid-template-columns: repeat(auto-fill, minmax(154px, 1fr)); gap: 14px; margin-top: 26px; }
.mounted {
  background: var(--gum);
  border-radius: var(--r);
  overflow: hidden;
  text-decoration: none;
  display: block;
  box-shadow: var(--shadow-leaf);
  transition: transform .16s cubic-bezier(.16, 1, .3, 1), box-shadow .16s ease;
}
.mounted:hover { transform: translateY(-2px); box-shadow: var(--shadow-lift); }
.mounted .img {
  aspect-ratio: 1;
  background: var(--gum-2) center / cover no-repeat;
  display: grid;
  place-items: center;
  font-family: "Azeret Mono", monospace;
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #8a7f6c;
}
.mounted .meta { padding: 9px 11px 11px; }
.mounted .meta b {
  display: block;
  font-family: "Azeret Mono", monospace;
  color: var(--gum-ink);
  font-size: 13px;
  letter-spacing: -.01em;
}
.mounted .meta span { font-size: 11.5px; color: #6d6455; }

.card {
  max-width: 400px;
  margin: 0 auto;
  background: var(--gum);
  color: var(--gum-ink);
  border-radius: var(--r);
  padding: 30px 28px;
  box-shadow: var(--shadow-leaf);
  --perf: 8px;
  --perf-gap: 11px;
}
.card h1 { font-size: 24px; margin: 0 0 14px; color: var(--gum-ink); }
.card p { color: #4a4237; font-size: 13.5px; }
.card a { color: #2f5fb0; }
.card label { display: block; font-size: 12px; color: #6d6455; margin-top: 12px; }
.card form input {
  width: 100%;
  background: rgba(23, 19, 13, .05);
  border: 1px solid rgba(23, 19, 13, .22);
  border-radius: var(--r);
  color: var(--gum-ink);
  padding: 9px 11px;
  font-size: 14px;
  margin: 5px 0 4px;
}
.card form input:focus { outline: none; border-color: var(--carmine); }
.card .errorlist { list-style: none; padding: 0; margin: 8px 0 0; color: #a32b3f; font-size: 12.5px; }
.card .btn { width: 100%; margin-top: 18px; }

.flash {
  background: rgba(23, 19, 13, .05);
  border: 1px solid rgba(23, 19, 13, .16);
  border-radius: var(--r);
  padding: 10px 12px;
  font-size: 13px;
  margin-bottom: 16px;
  color: #4a4237;
}

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

/* ---------------------------------------------------------------- stacked

   Below 940px, and in any window too short to hold a floating masthead over a
   map, the whole layout stops being an app shell and becomes one scrolling
   document: a bar, the globe, the argument, then the sheet.

   The overlay was the whole bug. A masthead pinned over the stage is fine at
   1440px, where it covers a third of a 900px-tall map. On a 375x812 phone the
   stage was 373px and the plate 370px, so it covered the globe entirely and
   still hung 10px over the sheet; at 320px it overflowed by 153px and buried
   the top of the selected-square stamp, and in landscape by 233px. The account
   links sat in the same 14px-top row as the wordmark on a higher z-index, so
   "My squares" printed straight across "Buy The World" and clipped it mid-word.

   Both come from the same mistake - two absolutely positioned overlays sharing
   a corner they only fit in when the corner is big. Placed in the grid they
   cannot collide and cannot overflow, because the rows size to them. */
@media (max-width: 940px), (max-height: 620px) {
  /* One scroller, not three. Two nested scroll areas plus the map's own gesture
     handling is what makes a phone feel like it is fighting back. */
  body { overflow: auto; }
  html, body { height: auto; }

  .app {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "brand"
      "stage"
      "argument"
      "sheet";
    height: auto;
    min-height: 100dvh;
  }

  /* The bar is already a row; it only has to be allowed to wrap. It keeps all
     three abreast for as long as they fit - a landscape phone is short rather
     than narrow, and giving the clock a row of its own across 1400px would be
     a stripe of empty bar. Below 560px it stacks; see that block. */
  .topbar {
    flex-wrap: wrap;
    align-items: center;
    column-gap: 12px;
    row-gap: 6px;
    padding: calc(11px + env(safe-area-inset-top)) 16px 11px;
  }
  .topbar h1 {
    /* DESIGN.md puts a 24px floor under Bodoni. */
    font-size: clamp(24px, 6.6vw, 27px);
    white-space: normal;
    text-wrap: balance;
  }

  /* The plate stops being an overlay and joins the flow under the map. */
  .plate {
    grid-area: argument;
    align-self: stretch;
    justify-self: stretch;
    pointer-events: auto;
    max-width: none;
    max-height: none;
    margin: 0;
    border: 0;
    border-top: 1px solid var(--rule);
    border-radius: 0;
    background: var(--leaf);
    backdrop-filter: none;
    box-shadow: none;
    padding: 15px 16px 17px;
  }

  /* No column to put a list in, so it stops being one. It goes to the top of
     the map - where the plate was before it joined the flow, so nothing else
     wants that corner - and shows one square at a time, each fading out before
     the next rises in. Stretched rather than pinned to a side: a card floating
     at one edge of a 375px map reads as something gone wrong. */
  .roll {
    align-self: start;
    justify-self: stretch;
    width: auto;
    margin: 10px 12px 0;
    padding: 8px 10px 9px;
  }
  .roll-title { margin: 0 0 5px 7px; font-size: 9px; }

  /* The name is the first thing to go: the links have to fit beside a wordmark
     that is already wrapping, and "Ada" is decoration next to a way in. */
  .ledger .who { display: none; }

  /* The map is the interface, so it gets a real amount of the screen and a
     floor in pixels - 58dvh of a landscape phone is 220px, which is not a
     globe you can turn. */
  .stage { height: clamp(300px, 58dvh, 620px); }

  .plate .thesis { font-size: .89rem; line-height: 1.5; margin-bottom: .5rem; }

  .sheet {
    border-left: 0;
    border-top: 1px solid var(--rule);
    max-height: none;
    overflow: visible;
    padding-bottom: env(safe-area-inset-bottom);
  }

  .leafpage { height: auto; overflow: visible; padding: 34px 18px calc(72px + env(safe-area-inset-bottom)); }
  .leafpage h1 { font-size: 27px; }
  .leafpage .lede { font-size: 15.5px; }
}

@media (prefers-reduced-motion: no-preference) and (max-width: 940px),
       (prefers-reduced-motion: no-preference) and (max-height: 620px) {
  .topbar { animation: settle .5s cubic-bezier(.16, 1, .3, 1) backwards; }
  .plate { animation: settle .5s cubic-bezier(.16, 1, .3, 1) .08s backwards; }
}

/* The clock drops under the wordmark and the links. Three abreast wants about
   700px once the caption is counted, and what gives way when they do not fit
   is the account links, which is the wrong thing to send down a line: the two
   items about the site should stay together. Wider than the 560px the rest of
   the phone layout uses, because it is the caption and not the viewport that
   runs out of room. */
@media (max-width: 760px) {
  .topbar .clockbar { order: 3; width: 100%; }
}

@media (max-width: 560px) {
  /* Two columns of thumbnails, not one wide one and a gap. */
  .collection { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .mounted .meta { padding: 7px 9px 9px; }
  .mounted .meta b { font-size: 12px; }
  .mounted .meta span { font-size: 10.5px; }
  .leafpage h1 { font-size: 24px; }
  .prefs .consent { padding: 6px 0; }
  .prefs .btn, .leafpage .btn { width: 100%; text-align: center; }

  /* A primary action takes the row. The slim pair - Share and Report - splits
     it, because one full-width button each for two afterthoughts pushes the
     buy action off the screen. */
  .acts .btn { width: 100%; }
  .acts .btn.slim { width: auto; flex: 1 1 calc(50% - 4px); }
}

@media (max-width: 420px) {
  .plate { padding: 13px 14px 15px; }
  .plate .thesis { font-size: .84rem; line-height: 1.45; }
  .topbar { padding-left: 14px; padding-right: 14px; }
  .ledger { gap: 4px; }
  .ledger a { padding-left: 10px; padding-right: 10px; }
  .pane { padding: 16px 14px 18px; }
  /* Two columns all the way down. One column of square tiles puts a single
     thumbnail across half the screen, and a collection you have to scroll
     through one at a time is not a collection you can look at. */
  .collection { gap: 8px; }
}

/* ------------------------------------------------------------------ touch

   Screen size is not input method: a touch laptop needs these and a 900px
   browser window on a desktop does not. Keyed on the pointer, not the width. */
@media (pointer: coarse) {
  /* Under 16px, iOS Safari zooms the whole page the moment a field is focused,
     and the layout the visitor was reading jumps sideways under their thumb. */
  .field input, .field select, .field textarea,
  .card form input { font-size: 16px; }

  .btn { min-height: 44px; }
  .chip { min-height: 44px; display: inline-flex; align-items: center; }
  .ledger a { min-height: 44px; }
  .maplibregl-ctrl-group button { width: 44px !important; height: 44px !important; }

  /* The footer's three legal links are navigation on their own line, not words
     in a sentence. Padding an inline box grows the hit area without moving the
     line it sits on. Deliberately not applied to .notice links generally: the
     terms link inside a consent label would then swallow taps meant to tick
     the box it sits in. */
  .notice.legal a { padding: 11px 3px; }

  /* A 13px-tall link is the only way back to the globe from every paper page. */
  .leafpage .back { display: inline-block; padding: 11px 0; }
  .consent { padding: 4px 0; }
  .consent input[type="checkbox"] { width: 22px; height: 22px; }
}


/* The masthead now argues before it instructs. The thesis carries the weight;
   the how-to steps back so it does not read as another line of the same voice. */
.plate .thesis {
  font-size: .93rem;
  line-height: 1.55;
  color: var(--text);
  margin-bottom: .55rem;
}
/* ---------- finding a place ----------------------------------------------
   The search box on the plate. It is the first thing a visitor who came to
   buy somewhere in particular needs, so it reads as the plate's own control
   rather than as a field on a form: marine, which is the ink for a mode being
   engaged, and carmine on focus like every other input on gum. */
.find {
  display: flex;
  gap: 6px;
  margin: 0 0 .5rem;
}
.find input {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--leaf-3);
  border: 1px solid var(--rule-lit);
  color: var(--text);
  font: inherit;
  font-size: .84rem;
  padding: 7px 9px;
  border-radius: 2px;
  /* Safari draws a search field as a rounded capsule with its own inset
     shadow and ignores most of the above without this. */
  -webkit-appearance: none;
  appearance: none;
}
.find input::placeholder { color: var(--text-faint); }
.find input:focus {
  outline: 2px solid var(--marine);
  outline-offset: 2px;
  border-color: var(--marine);
}
.find input::-webkit-search-cancel-button { filter: invert(1) opacity(.45); }
/* The disclosure. A tracked mono caps line rather than a button, because it is
   not an action: it is the same kind of label as a section heading, and giving
   it carmine would put the plate's loudest ink on the least important control.
   Marine on hover and focus, which is the ink for a mode being engaged. */
.unfold {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  margin: 11px 0 0;
  padding: 7px 0 0;
  border: 0;
  border-top: 1px solid var(--rule);
  background: none;
  color: var(--text-faint);
  font-family: "Azeret Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: .17em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}
.unfold:hover { color: var(--marine); }
.unfold:focus-visible {
  outline: 2px solid var(--marine);
  outline-offset: 2px;
  color: var(--marine);
}
.unfold svg {
  width: 13px;
  height: 13px;
  flex: none;
  transition: transform .14s ease;
}
.unfold[aria-expanded="true"] svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .unfold svg { transition: none; }
}

/* The fold is what shrinks, so the two controls and the disclosure stay put and
   only the prose scrolls. `min-height: 0` is what lets a flex child be smaller
   than its content at all; without it the panel grows past its own cap and the
   text spills out of the bottom. Pointer events come back here because a panel
   nobody can reach is a panel nobody can scroll. */
.plate .argument {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.plate .more {
  min-height: 0;
  overflow-y: auto;
  /* The map is behind this. Scrolling to the end of the welcome must not then
     start turning the globe. */
  overscroll-behavior: contain;
}
/* The first paragraph of the fold sits straight under the control, so it does
   not also carry .plate p's top margin on top of the button's padding. */
.plate .more > :first-child { margin-top: 9px; }

/* The way back to the welcome. A line rather than a button, because it opens
   something to read rather than doing anything to the map - marine, which is
   this interface's ink for a link. */
.plate .again { margin-top: 12px; }
.plate .again button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  color: var(--marine);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.plate .again button:hover { color: var(--text); }
.plate .again button:focus-visible { outline: 2px solid var(--marine); outline-offset: 2px; }

.find-note {
  font-size: .78rem;
  color: var(--text-faint);
  margin: -.25rem 0 .5rem;
}
.find-note:empty { display: none; }
.find-list {
  list-style: none;
  margin: -.25rem 0 .6rem;
  padding: 0;
  background: var(--leaf-2);
  border: 1px solid var(--rule-lit);
  /* Eight results at most, and a phone in landscape has no room for eight.
     It scrolls rather than pushing the globe off the page. */
  max-height: 232px;
  overflow-y: auto;
}
.find-list li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1px 10px;
  padding: 7px 9px;
  cursor: pointer;
  border-top: 1px solid var(--rule);
}
.find-list li:first-child { border-top: 0; }
.find-list li:hover,
.find-list li[aria-selected="true"] { background: var(--leaf-3); }
.find-list li b {
  font-weight: 500;
  font-size: .82rem;
  color: var(--text);
}
.find-list li .where {
  grid-column: 1;
  font-size: .74rem;
  color: var(--text-faint);
}
.find-list li .cell {
  grid-row: 1 / span 2;
  grid-column: 2;
  align-self: center;
  font-family: "Azeret Mono", monospace;
  font-size: .68rem;
  letter-spacing: .04em;
  color: var(--marine);
  white-space: nowrap;
}
/* A label that exists for a screen reader and not for the eye. The box's own
   placeholder is the visible label. */
.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.plate .howto,
.plate .howto-touch,
.plate .howto-both,
.plate .howto-price {
  font-size: .82rem;
  color: var(--text-faint);
  margin-top: 0;
}
/* The price breakdown is the one of these a visitor is owed rather than
   offered, so it sits closer to the sum it explains and is not faded as far
   as the pointer instructions beside it. */
.plate .howto-price {
  color: var(--text-dim);
  margin-top: .45rem;
  margin-bottom: .55rem;
}
/* The one line of the three that is not about the pointer, so it is the one
   that shows on every device. */
.plate .howto-both { margin-top: .35rem; }
/* "Scroll to come closer" is not an instruction a thumb can follow. */
.plate .howto-touch { display: none; }
@media (pointer: coarse) {
  .plate .howto { display: none; }
  .plate .howto-touch { display: block; }
}


/* Notification switches on the collection page. The consent label style already
   exists for the checkout box; this only gives the stack some room. */
.prefs { margin-top: 16px; }
.prefs .consent { display: flex; gap: 10px; margin-bottom: 10px; align-items: flex-start; }
.prefs .flash, .leafpage .flash { color: var(--moss, #4a6141); }
.prefs .flash.error, .leafpage .flash.error { color: var(--carmine); }


/* A <pre> is the one element that will push a phone page sideways on its own.
   The form has to stay monospaced to read as a form, so it scrolls in its own
   box instead of taking the document with it. */


/* Links on the paper pages had no colour of their own, so they came out as
   browser blue on a cream sheet - the one colour nothing else here uses. */
.leafpage a:not(.btn):not(.back) {
  color: var(--carmine);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.leafpage a:not(.btn):not(.back):hover { text-decoration-thickness: 2px; }


/* The one revision, said in the panel rather than only in an error after the
   fact. It is the whole shape of what somebody is buying, so it reads as part
   of the form and not as a warning bolted on. */
/* ---------- giving it away -----------------------------------------------
   The gift inputs sit on gum inside the stamp, so they inherit .field. What
   they need of their own is a rule separating them from the square's facts:
   this is the one block on the panel that is about a person rather than a
   place. */
#giftBox {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid #c9bda3;
}
#giftBox .field:first-child { margin-top: 0; }

/* Handing over a square that already exists. Same treatment as the gift block
   above because it is the same kind of thing - a block about a person, on a
   panel otherwise about a place - and deliberately not the same block: one
   decides who a purchase is for, the other moves something somebody owns. */
#giveBox {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid #c9bda3;
}
#giveBox .field:first-child { margin-top: 0; }

.metanote {
  margin: 6px 0 2px;
  font-size: .78rem;
  line-height: 1.45;
  color: var(--ink-3, #6b6257);
}
.metanote:empty { display: none; }

/* The case for a gift, above the three fields that take one. Prose weight, not
   metanote weight: it is the argument rather than a footnote about how the
   argument works, and at .78rem in --ink-3 it read as small print nobody was
   meant to finish. The rule down the left is the only mark on it - a tinted
   panel here would put a second box inside a panel that is already a box. */
.gift-lede {
  margin: 2px 0 14px;
  padding: 1px 0 1px 12px;
  border-left: 2px solid rgba(23, 19, 13, .18);
  font-size: .86rem;
  line-height: 1.55;
  /* Gum ink, not --text-dim. This block sits inside .stamp, which is the
     gummed paper - the leaf's own tokens are written for the dark ground and
     put a near-white bold on a cream panel, which is where the first sentence
     went when this was first written: invisible, and it is the sentence the
     whole block is for. Anything added in here takes its colour from --gum-ink
     the way .hint .why does. */
  color: rgba(23, 19, 13, .78);
}
.gift-lede b { color: var(--gum-ink); font-weight: 600; }


/* The clock. Carmine because it is the definitive mark and this is the most
   definitive thing on the page - not amber, which belongs to the globe. The bar
   drains rather than fills, so it reads as something being used up. */
.doom {
  height: 6px;
  background: var(--carmine-dim);
  overflow: hidden;
  margin: 2px 0 10px;
}
.doom i {
  display: block;
  height: 100%;
  background: var(--carmine);
  transform-origin: left center;
  transform: scaleX(1);
  transition: transform .6s ease-out;
}
.doom i.low { background: var(--carmine-lit); }
#clockDays { font-variant-numeric: tabular-nums; }
#clockDays.out { color: var(--carmine-lit); }


/* ---------- the clock ----------
   The second thing you read, after the thesis. A sentence rather than a digital
   dial: the units cascade down as the time runs out, so it gets more urgent on
   its own without anything changing colour.

   Carmine for the figures because it is the definitive ink and this is the most
   definitive thing on the page. Never amber - that belongs to the globe. */
.doomsday {
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px solid var(--rule);
}
.doomsday .lede-clock {
  margin: 0 0 6px;
  font-family: var(--mono, "Azeret Mono", ui-monospace, monospace);
  font-size: 10px;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--text-faint);
}
/* A wrapping row of number-and-unit pairs. It used to be inline spans joined
   with no whitespace at all and `font-size: 0` on top of that, which left the
   line with no break opportunity anywhere - so when the figures grew wide
   enough (three digits of days, or a narrower window) the clock did not wrap,
   it ran out through the side of the plate.
   Flex gives the row its break points back, and `.tick` is what keeps a number
   from ever being parted from its own unit. */
.doomsday .dial {
  margin: 0;
  line-height: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: 14px;
  row-gap: 5px;
}
.doomsday .dial .tick { white-space: nowrap; }
.doomsday .dial .n {
  font-family: var(--mono, "Azeret Mono", ui-monospace, monospace);
  font-size: 40px;
  line-height: 1.02;
  font-variant-numeric: tabular-nums;
  color: var(--carmine-lit);
  letter-spacing: -.02em;
}
.doomsday .dial .u {
  font-family: var(--ui, "Familjen Grotesk", sans-serif);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-left: 5px;
  vertical-align: 6px;
}
.doomsday .bought {
  margin: 9px 0 0;
  font-size: .78rem;
  line-height: 1.45;
  color: var(--text-dim);
}
.doomsday .bought b { color: var(--text); font-weight: 600; }
/* Under a day left, the figures stop being a fact and start being a warning. */
.doomsday.last-day .dial .n { color: var(--carmine); }
.doomsday.out .dial .n { font-size: 27px; color: var(--carmine); }

@media (max-width: 940px) {
  .doomsday .dial { column-gap: 11px; }
  .doomsday .dial .n { font-size: 32px; }
  .doomsday .dial .u { font-size: 11px; }
}
@media (max-width: 560px) {
  .doomsday { margin-top: 11px; padding-top: 10px; }
  .doomsday .dial { column-gap: 9px; }
  .doomsday .dial .n { font-size: 27px; }
  .doomsday .dial .u { font-size: 10px; margin-left: 4px; vertical-align: 4px; }
  .doomsday .bought { font-size: .74rem; }
}
