/* The composing stick loader: a steel composing stick and a brass galley seen from above and a little from the front,
   alone on a black page, with a line of words and the pills under it. The sorts, the roller, the platen and the sheet
   are made by script.js with these colours; the print is painted on a canvas. */
:root {
  --page: #000000;          /* the page */
  --text: #eef0f2;          /* the words */
  --muted: #8a9198;         /* the quiet words */
  --ok: #6fd39a;            /* invoice ready */
  --error: #ff6b4f;         /* the wrong sort, and the words when it goes wrong */
  --steel-hi: #e4e8ec;      /* the light on the steel of the stick */
  --steel: #8f979f;         /* the steel */
  --steel-lo: #3a4047;      /* the steel in shadow */
  --brass-hi: #f0cf8a;      /* the light on the brass galley */
  --brass: #b08544;         /* the brass */
  --brass-lo: #4e3818;      /* the brass in shadow */
  --lead-hi: #c9cfd5;       /* the face of a sort where the light falls */
  --lead: #8c949c;          /* the face of a sort */
  --lead-lo: #4a5159;       /* the side of a sort */
  --ink: #0b0a09;           /* the ink on the type */
  --roller: #17181a;        /* the inking roller */
  --platen: #23262a;        /* the platen of the press */
  --paper: #f1eadc;         /* the sheet */
  --print: #1a1512;         /* the ink on the sheet */
  --button: #f1eadc;        /* the main pill */
  --button-ink: #15120f;    /* its words */
  --line: #3a3f45;          /* the ring round the quiet pill */
  --focus: #e0b45e;         /* the keyboard's focus ring */
}

* {
  box-sizing: border-box;
}

/* a tap is a click at once: no wait for a double tap, no zoom */
html {
  touch-action: manipulation;
}

html,
body {
  margin: 0;
  overflow-x: clip;
}

body {
  min-height: 100svh;
  background: var(--page);
  color: var(--text);
  font-family: 'Instrument Sans Variable', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.stage {
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 56px 16px 40px;
}

/* ---------------------------------------------------------------- the press */
.press {
  display: grid;
  justify-items: center;
  width: min(380px, 100%);
}

/* the drawing is 360 by 226 pixels and scaled to the width it gets */
.press__scene {
  position: relative;
  width: min(360px, 100%);
  aspect-ratio: 360 / 226;
}

.press__fit {
  position: absolute;
  top: 0;
  left: 0;
  width: 360px;
  height: 226px;
  transform-origin: 0 0;
}

.press__box {
  position: absolute;
  inset: 0;
  perspective: 900px;
}

.press__box > div {
  position: absolute;
}

/* ---------------------------------------------------------------- the composing stick, steel */
.stick {
  left: 24px;
  top: 0;
  width: 314px;
  height: 56px;
}

.stick > div {
  position: absolute;
}

/* the back plate, standing up behind the type */
.stick__back {
  left: 2px;
  right: 2px;
  top: 3px;
  height: 14px;
  border-radius: 2px 2px 0 0;
  background: linear-gradient(180deg, var(--steel-hi) 0, var(--steel) 22%, var(--steel-lo) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

/* the bottom of the stick, seen where there is no type yet */
.stick__bed {
  left: 10px;
  right: 14px;
  top: 14px;
  height: 32px;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px 3px),
    linear-gradient(180deg, color-mix(in srgb, var(--steel-lo) 70%, #000) 0, var(--steel-lo) 40%, color-mix(in srgb, var(--steel) 55%, var(--steel-lo)) 100%);
  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.6);
}

/* the clamp that sets the measure, on the left */
.stick__clamp {
  left: 0;
  top: 6px;
  width: 12px;
  height: 44px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--steel-lo), var(--steel-hi) 35%, var(--steel) 70%, var(--steel-lo));
  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

/* the knee, the fixed end the first sort goes against */
.stick__knee {
  right: 0;
  top: 0;
  width: 16px;
  height: 52px;
  border-radius: 2px 2px 3px 3px;
  background: linear-gradient(90deg, var(--steel-lo), var(--steel-hi) 30%, var(--steel) 65%, color-mix(in srgb, var(--steel-lo) 60%, #000));
  box-shadow: -2px 2px 5px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

/* the front ledge, in front of the bottom of the type */
.stick__lip {
  left: 24px;
  top: 44px;
  width: 314px;
  height: 11px;
  z-index: 20;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(180deg, var(--steel-hi) 0, var(--steel) 30%, var(--steel-lo) 100%);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.7), inset 0 1px 0 rgba(255, 255, 255, 0.85);
}

/* ---------------------------------------------------------------- the galley, brass */
.galley {
  left: 22px;
  top: 68px;
  width: 316px;
  height: 156px;
}

.galley > div {
  position: absolute;
}

.galley__floor {
  inset: 0;
  border-radius: 3px;
  background:
    repeating-linear-gradient(90deg, rgba(255, 240, 200, 0.05) 0 1px, transparent 1px 4px),
    radial-gradient(120% 90% at 30% 10%, color-mix(in srgb, var(--brass) 85%, var(--brass-hi)) 0, var(--brass) 45%, var(--brass-lo) 100%);
  box-shadow: inset 0 0 0 1px rgba(255, 230, 170, 0.18), 0 10px 22px rgba(0, 0, 0, 0.6);
}

.galley__rim {
  background: linear-gradient(180deg, var(--brass-hi), var(--brass) 45%, var(--brass-lo));
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 245, 215, 0.8);
}

.galley__rim--top {
  left: 0;
  right: 0;
  top: 0;
  height: 9px;
  border-radius: 3px 3px 0 0;
}

.galley__rim--side {
  right: 0;
  top: 0;
  width: 16px;
  bottom: 0;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(90deg, var(--brass-lo), var(--brass-hi) 30%, var(--brass) 70%, var(--brass-lo));
}

.galley__rim--foot {
  left: 0;
  right: 0;
  bottom: 0;
  height: 9px;
  border-radius: 0 0 3px 3px;
  background: linear-gradient(180deg, var(--brass-hi), var(--brass) 40%, var(--brass-lo));
}

/* ---------------------------------------------------------------- the type */
.press__type,
.press__fly {
  inset: 0;
  pointer-events: none;
}

.press__fly {
  z-index: 60;
}

/* a line of type: its sorts stand on it; its lead (the strip that spaces the lines) shows once it is in the galley */
.line {
  position: absolute;
  left: 0;
  top: 14px;
  width: 360px;
  height: 32px;
}

.line__lead {
  position: absolute;
  top: -4px;
  height: 4px;
  border-radius: 1px;
  background: linear-gradient(180deg, #5d636a, #33383e);
  opacity: 0;
}

/* a sort: the face with its letter on top, the side (the body of the type) under it, seen a little from the front */
.sort {
  position: absolute;
  top: 0;
  height: 32px;
  --tint: 1;
}

.sort__face {
  position: absolute;
  inset: 0 0 10px;
  overflow: hidden;
  border-radius: 1px;
  background: linear-gradient(162deg, var(--lead-hi) 0, var(--lead) 55%, color-mix(in srgb, var(--lead) 70%, var(--lead-lo)) 100%);
  box-shadow: inset 0.5px 0.5px 0 rgba(255, 255, 255, 0.55), inset -0.5px -0.5px 0 rgba(0, 0, 0, 0.35);
  filter: brightness(var(--tint));
}

/* the glint that runs over the type when the line is tapped tight */
.sort__face::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, 0.75) 50%, transparent 65%);
  background-size: 300% 100%;
  background-position: var(--glint, 100%) 0;
  mix-blend-mode: soft-light;
}

/* the letter, raised and back to front */
.sort__glyph {
  position: absolute;
  inset: 0;
  display: block;
  font-family: 'Fraunces Variable', Georgia, serif;
  font-size: 19px;
  font-variation-settings: 'SOFT' 0, 'WONK' 0;
  line-height: 22px;
  text-align: center;
  white-space: pre;
  color: color-mix(in srgb, var(--lead-hi) 70%, #fff);
  text-shadow: 0.6px 0.8px 0 rgba(20, 24, 28, 0.75), -0.4px -0.5px 0 rgba(255, 255, 255, 0.55), 1px 1.6px 1.4px rgba(0, 0, 0, 0.35);
  transform: scaleX(-1);
  transition: color 0.18s ease, text-shadow 0.18s ease;
}

.sort.is-inked .sort__glyph {
  color: var(--ink);
  text-shadow: -0.4px -0.5px 0 rgba(255, 255, 255, 0.45), 0.5px 0.8px 0 rgba(0, 0, 0, 0.6), 1px 1.6px 1.4px rgba(0, 0, 0, 0.3);
}

.sort.is-wrong .sort__glyph {
  color: var(--error);
}

.sort.is-wrong .sort__face {
  box-shadow: inset 0 0 0 1px var(--error), inset 0.5px 0.5px 0 rgba(255, 255, 255, 0.55);
}

.sort__side {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 10px;
  border-radius: 0 0 1px 1px;
  background:
    linear-gradient(180deg, transparent 0 3px, rgba(0, 0, 0, 0.55) 3px 4px, rgba(255, 255, 255, 0.12) 4px 5px, transparent 5px),
    linear-gradient(180deg, var(--lead-lo), color-mix(in srgb, var(--lead-lo) 60%, #000));
  box-shadow: 1.5px 2px 3px rgba(0, 0, 0, 0.55);
  filter: brightness(var(--tint));
}

/* a space or a quad: lower than the type, so it has no letter and never prints */
.sort.is-blank .sort__face {
  top: 4px;
  background: linear-gradient(180deg, #2c3136, #444b52);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.6);
}

.sort.is-blank .sort__side {
  display: none;
}

/* ---------------------------------------------------------------- the roller, the platen and the sheet */
.roller {
  left: 14px;
  top: 0;
  width: 332px;
  height: 22px;
  z-index: 30;
  opacity: 0;
}

.roller::before,
.roller::after {
  content: '';
  position: absolute;
  top: 7px;
  width: 10px;
  height: 8px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--steel-hi), var(--steel) 50%, var(--steel-lo));
}

.roller::before {
  left: 0;
}

.roller::after {
  right: 0;
}

.roller__drum {
  position: absolute;
  left: 9px;
  right: 9px;
  top: 0;
  bottom: 0;
  border-radius: 11px;
  background:
    repeating-linear-gradient(180deg, rgba(255, 255, 255, 0.04) 0 2px, transparent 2px 6px),
    linear-gradient(180deg, color-mix(in srgb, var(--roller) 60%, #000) 0, color-mix(in srgb, var(--roller) 80%, #fff) 28%, var(--roller) 55%, #000 100%);
  background-position: 0 var(--turn, 0px), 0 0;
  box-shadow: 0 8px 12px rgba(0, 0, 0, 0.6), inset 0 -2px 3px rgba(0, 0, 0, 0.6);
}

.sheet__shadow {
  left: 26px;
  top: 70px;
  width: 308px;
  height: 136px;
  z-index: 38;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.75);
  filter: blur(8px);
  opacity: 0;
}

.sheet {
  left: 24px;
  top: 66px;
  width: 312px;
  height: 138px;
  z-index: 40;
  visibility: hidden;
  transform-style: preserve-3d;
}

.sheet__face {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 1.5px;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.sheet__face--front {
  transform: rotateY(180deg);
}

.platen {
  left: 14px;
  top: 58px;
  width: 332px;
  height: 158px;
  z-index: 50;
  opacity: 0;
  border-radius: 6px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent 8%, transparent 92%, rgba(0, 0, 0, 0.5)),
    linear-gradient(135deg, color-mix(in srgb, var(--platen) 70%, #fff) 0, var(--platen) 35%, color-mix(in srgb, var(--platen) 60%, #000) 100%);
  box-shadow: 0 18px 30px rgba(0, 0, 0, 0.75), inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.platen__ribs {
  position: absolute;
  inset: 16px 22px;
  border-radius: 4px;
  background: repeating-linear-gradient(180deg, rgba(255, 255, 255, 0.07) 0 1px, rgba(0, 0, 0, 0.35) 1px 3px, transparent 3px 14px);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.5), 0 1px 0 rgba(255, 255, 255, 0.06);
}

/* ---------------------------------------------------------------- the line of words */
.press__status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 22px;
  margin: 14px 0 0;
  max-width: 100%;
  font-size: 15px;
  font-weight: 600;
  font-stretch: 92%;
  line-height: 22px;
  letter-spacing: -0.005em;
  white-space: nowrap;
}

.press__swap {
  display: inline-block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.press[data-mode='idle'] .press__swap {
  color: var(--muted);
}

.press[data-mode='done'] .press__swap {
  color: var(--ok);
}

.press[data-mode='failed'] .press__swap {
  color: var(--error);
}

/* the percentage keeps its width while the figures change */
.press__pct {
  display: none;
  min-width: 3.2ch;
  color: var(--muted);
  font-weight: 700;
  font-stretch: 84%;
  font-variant-numeric: tabular-nums;
}

.press[data-mode='busy'] .press__pct {
  display: inline-block;
}

.press__tick,
.press__warn {
  display: none;
  flex: none;
  width: 19px;
  height: 19px;
  fill: none;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.press__tick {
  stroke: var(--ok);
  stroke-width: 2.4;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}

.press__warn {
  stroke: var(--error);
}

.press[data-mode='done'] .press__tick,
.press[data-mode='failed'] .press__warn {
  display: block;
}

/* ---------------------------------------------------------------- the pills */
.press__buttons {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 14px;
}

/* the fill is a layer of its own that swells past the edge with a bounce, and the words widen on the width axis of
   the font; pressed, a pill squashes a little */
.pill {
  position: relative;
  display: inline-grid;
  place-items: center;
  height: 44px;
  min-width: 44px;
  padding: 0 20px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--button-ink);
  font: inherit;
  font-size: 14.5px;
  font-weight: 620;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  isolation: isolate;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  user-select: none;
  -webkit-user-select: none;
  transition: color 0.25s ease;
}

.pill[hidden] {
  display: none;
}

.pill::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--button);
  transition: inset 0.6s cubic-bezier(0.34, 1.56, 0.64, 1), background-color 0.25s ease, box-shadow 0.25s ease;
}

.pill__label {
  display: inline-block;
  font-stretch: 88%;
  transition: font-stretch 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* the quiet pill: Generate again, and the main pill while it works */
.pill.is-quiet {
  color: var(--text);
}

.pill.is-quiet::before {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--line);
}

.pill[aria-disabled='true'] {
  color: var(--muted);
  cursor: default;
}

/* downloaded: the main pill turns green */
.pill.is-saved::before {
  background: var(--ok);
}

@media (hover: hover) and (pointer: fine) {
  .pill:not([aria-disabled='true']):hover::before {
    inset: -2px -6px;
  }

  .pill:not([aria-disabled='true']):hover .pill__label {
    font-stretch: 100%;
  }

  .pill.is-quiet:not([aria-disabled='true']):hover::before {
    background: color-mix(in srgb, var(--line) 45%, transparent);
  }
}

.pill:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .pill::before,
  .pill__label,
  .sort__glyph {
    transition: none;
  }
}
