/* 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; }
.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;
}

/* 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; }

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

.plate {
  grid-area: stage;
  align-self: start;
  justify-self: start;
  z-index: 3;
  margin: 20px 0 0 22px;
  max-height: calc(100dvh - 40px);
  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 .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;
}

/* How much of the world is spoken for, on the plate. The figure is leaf ink,
   not amber: amber is the map's own word for a claimed square and is never
   borrowed for UI chrome. The bar underneath is the exception that was already
   here, and it is the one thing on the plate that IS the claims. */
.plate .claimed { margin-top: 13px; }

.plate .claimed-line {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.35;
  color: var(--text-dim);
}
.plate .claimed-line b {
  font-family: "Bodoni Moda", Georgia, serif;
  font-size: 21px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: .005em;
  margin-right: 3px;
  font-variant-numeric: tabular-nums;
}
.plate .claimed .gauge { margin-top: 9px; }
.plate .claimed-count {
  margin: 6px 0 0;
  font-size: 11.5px;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
}

/* What the person reading has bought the map. Sits under the share of the
   world claimed, because it is the same number told about them. */
.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. */
.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); }

.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; }

/* ------------------------------------------------------- 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 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;
  }

  /* 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; }
}

@media (max-width: 560px) {
  /* The clock drops under the wordmark and the links. There is not room for
     all three abreast at this width, and a countdown that wraps between a
     figure and its unit is worse than one on a line of its own. */
  .topbar .clockbar { order: 3; width: 100%; }

  /* 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 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; }

.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 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; }
}
