/* Bundled, so that text wraps alike everywhere, each face of its own, as made-up ones would not. */
@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url("fonts/Inter-Regular.woff2") format("woff2");
}

@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url("fonts/Inter-Bold.woff2") format("woff2");
}

@font-face {
  font-family: Inter;
  font-style: italic;
  font-weight: 400;
  font-display: block;
  src: url("fonts/Inter-Italic.woff2") format("woff2");
}

@font-face {
  font-family: Inter;
  font-style: italic;
  font-weight: 700;
  font-display: block;
  src: url("fonts/Inter-BoldItalic.woff2") format("woff2");
}

/* Also for what draws in the light theme's colours, whatever the theme. */
:root,
.light {
  color-scheme: light;
  font:
    14px/1.4 system-ui,
    sans-serif;
  --board: #f1f1f3;
  --surface: #ffffff;
  --text: #1d1d22;
  --ink: #1d1d22;
  --muted: #6e6e78;
  --line: rgb(0 0 0 / 10%);
  --hover: rgb(0 0 0 / 5%);
  --accent: #c0173e;
  --accent-soft: #fde7ec;
  --shadow: 0 1px 2px rgb(0 0 0 / 8%), 0 4px 16px rgb(0 0 0 / 10%);
  /* Of its own, as engines draw the system's highlight pale and see-through. */
  --selected: #0b5fff;
  /* The palette elements are drawn in, besides the ink. */
  --red: #d42f2f;
  --orange: #c45a00;
  --green: #2b8a3e;
  --blue: #1c6ed6;
  --violet: #6f42dc;
  /* As a highlighter draws the palette, bright under its own translucency, in either theme. */
  --highlight-yellow: #ffe100;
  --highlight-red: #ff4d6d;
  --highlight-orange: #ff9500;
  --highlight-green: #2fe05a;
  --highlight-blue: #19b5ff;
  --highlight-violet: #a259ff;
  /* Sticky notes keep their papers and their ink in either theme, pale in the highlighters' hues. */
  --paper-yellow: #feeb85;
  --paper-pink: #ffd1d3;
  --paper-orange: #ffd5b0;
  --paper-green: #c1ebc3;
  --paper-blue: #bce4ff;
  --paper-lilac: #e3d6ff;
  --sticky-ink: #1d1d22;
  /* A comment's pin, how wide its text may grow, and how far from the pin it shows. */
  --pin: 28px;
  --bubble: 240px;
  --pin-gap: 4px;
}

/* As theme.ts sets it, which follows the system unless told otherwise. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --board: #121215;
  --surface: #232329;
  --text: #ececf1;
  --ink: #ececf1;
  --muted: #9d9da8;
  --line: rgb(255 255 255 / 10%);
  --hover: rgb(255 255 255 / 6%);
  --accent: #ff8fa8;
  --accent-soft: rgb(255 143 168 / 18%);
  --shadow: 0 1px 2px rgb(0 0 0 / 40%), 0 4px 16px rgb(0 0 0 / 40%);
  --selected: #5aa9ff;
  --red: #ff8a85;
  --orange: #ffad66;
  --green: #7bd88f;
  --blue: #7fb5ff;
  --violet: #b49bff;
}

:root[data-contrast="high"],
[data-contrast="high"] .light {
  --board: #ffffff;
  --surface: #ffffff;
  --text: #000000;
  --ink: #000000;
  --muted: #45454d;
  --line: #000000;
  --hover: rgb(0 0 0 / 12%);
  --accent: #a30027;
  --accent-soft: #f5ccd6;
  --shadow: none;
  --selected: var(--accent);
  /* How many times stronger than the renderer's own the grid shows. */
  --grid-strength: 3;
  --red: #b00020;
  --orange: #a34800;
  --green: #1b6e2d;
  --blue: #0b4fb3;
  --violet: #5523c0;
  --highlight-yellow: #ffd000;
  --highlight-red: #ff1f4b;
  --highlight-orange: #ff7a00;
  --highlight-green: #00c43a;
  --highlight-blue: #0091ff;
  --highlight-violet: #8a2eff;
}

:root[data-theme="dark"][data-contrast="high"] {
  --board: #000000;
  --surface: #000000;
  --text: #ffffff;
  --ink: #ffffff;
  --muted: #d0d0d8;
  --line: #ffffff;
  --hover: rgb(255 255 255 / 16%);
  --accent: #ffc2d0;
  --accent-soft: #5c2f3a;
  --red: #ffa8a3;
  --orange: #ffc285;
  --green: #9be8ad;
  --blue: #a6ccff;
  --violet: #cbb8ff;
  --highlight-yellow: #fff04d;
  --highlight-red: #ff7a92;
  --highlight-orange: #ffb04d;
  --highlight-green: #6cff8f;
  --highlight-blue: #6fd0ff;
  --highlight-violet: #c49aff;
}

/* Its ink as its text colour, which `paint.ts` reads, and which forced colours would not keep. */
.light {
  color: var(--ink);
  forced-color-adjust: none;
}

[hidden] {
  display: none !important;
}

html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  color: var(--text);
  background: var(--board);
}

/* The renderer reads its colour as the ink. Clipped, as a focused pin would scroll what hides. */
#viewport {
  position: fixed;
  inset: 0;
  color: var(--ink);
  overflow: clip;
  touch-action: none;
}

/* Before the tools', which take the press instead. */
#viewport.over-handle {
  cursor: var(--handle-cursor);
}

/* Before the hand's, which pans over a tool to draw. */
#viewport.drawing {
  cursor: crosshair;
}

/* About as wide as the eraser reaches, and white to show over any image. */
#viewport.erasing {
  cursor:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5' fill='white' stroke='black' stroke-width='1.5'/%3E%3C/svg%3E")
      8 8,
    crosshair;
}

#viewport.hand {
  cursor: grab;
}

#viewport.panning {
  cursor: grabbing;
}

#viewport > * {
  position: absolute;
  top: 0;
  left: 0;
}

/* Over the renderer's canvas, which each board opened adds after it. */
#viewport > svg {
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* The pins, placed as the board shows, keep their text readable. */
#viewport.mirrored > canvas,
#viewport.mirrored > svg {
  transform: scaleX(-1);
}

/* Over the board and its selection, where only the pins take the pointer. */
#viewport > .pins {
  z-index: 2;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

#viewport.unannotated > .pins {
  display: none;
}

/* Placed at its comment's point, which its pin's centre sits on. */
.comment {
  position: absolute;
  top: 0;
  left: 0;
}

/* Over the board and its selection, under the pins. */
#viewport > .titles {
  z-index: 2;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.group-title {
  position: absolute;
  top: 0;
  left: 0;
  translate: 0 calc(-100% - 4px);
  overflow: hidden;
  font:
    500 12px/16px system-ui,
    sans-serif;
  color: var(--muted);
  white-space: nowrap;
  text-overflow: ellipsis;
  pointer-events: auto;
  user-select: none;
}

.group-title:hover {
  color: var(--ink);
}

.group-title.selected {
  color: var(--selected);
}

.group-title.offered {
  border-bottom: 1px dashed currentColor;
  opacity: 0.8;
  cursor: text;
}

/* Clicks go through it, as through its group. */
.group-title.locked {
  pointer-events: none;
}

.group-title.writing {
  overflow: visible;
  max-width: none !important;
}

.group-title input {
  margin: -2px -4px;
  padding: 1px 3px;
  border: 1px solid var(--selected);
  border-radius: 4px;
  outline: none;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
}

/* A thumbtack's head, ringed to stand apart from any image. */
.pin {
  position: absolute;
  top: calc(var(--pin) / -2);
  left: calc(var(--pin) / -2);
  box-sizing: border-box;
  display: block;
  width: var(--pin);
  height: var(--pin);
  padding: 0;
  border: 2px solid var(--surface);
  border-radius: 50%;
  background:
    radial-gradient(circle at 35% 30%, rgb(255 255 255 / 65%) 0 2px, transparent 3px),
    radial-gradient(
      circle at 40% 35%,
      color-mix(in srgb, var(--accent), white 20%),
      var(--accent) 60%
    );
  box-shadow: 1px 2px 3px rgb(0 0 0 / 35%);
  cursor: pointer;
  pointer-events: auto;
}

.comment .text,
.writer.bubble {
  box-sizing: border-box;
  padding: 6px 12px 7px;
  border-radius: 10px;
  font:
    14px/1.4 system-ui,
    sans-serif;
  color: var(--text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* In flow, so that the comment is as tall as it for the bridge, and hidden once faded, as it would
   otherwise still take the pointer. */
.comment .text {
  position: relative;
  top: calc(var(--pin) / -2);
  left: calc(var(--pin) / 2 + var(--pin-gap));
  display: block;
  width: max-content;
  max-width: var(--bubble);
  max-height: 50vh;
  overflow: hidden;
  pointer-events: auto;
  visibility: hidden;
  opacity: 0;
  transition:
    opacity 100ms ease-out,
    visibility 0s 100ms;
}

/* From the pin's right half to the text's edge, past its corners and down to its last line, so that
   the pointer keeps the text shown on its way. Clear of the left half, as it would otherwise cover
   most of a pin planted just below. */
.comment::before {
  content: "";
  position: absolute;
  top: calc(var(--pin) / -2);
  bottom: calc(var(--pin) / 2);
  left: 0;
  width: calc(var(--pin) / 2 + var(--pin-gap) + 10px);
  clip-path: polygon(0 0, 100% 0, 100% 100%, calc(100% - 10px) 100%, 0 var(--pin));
}

/* Over the pins planted later, which would otherwise cover its text. */
.pins:not(.quiet) .comment:not(.writing, .blank):is(:hover, :has(.pin:focus-visible)) {
  z-index: 1;
}

.pins:not(.quiet) .comment:not(.writing, .blank):is(:hover, :has(.pin:focus-visible)) .text {
  visibility: visible;
  opacity: 1;
  transition-delay: 0s;
}

.pins:not(.quiet) .comment:not(.writing, .blank):is(:hover, :has(.pin:focus-visible))::before {
  pointer-events: auto;
}

.comment.selected .pin {
  outline: 2px solid var(--selected);
  outline-offset: 1px;
}

/* After the selection's, which it would otherwise lose to. */
.comment .pin:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Where the selection takes the accent too. */
[data-contrast="high"] .comment .pin:focus-visible {
  outline-color: var(--text);
}

/* Flat, as everything is in high contrast. */
[data-contrast="high"] .pin {
  background: var(--accent);
  box-shadow: none;
}

/* Where the text shows, as wide as it may grow, so that it wraps alike. */
.writer.bubble {
  width: var(--bubble);
  caret-color: var(--accent);
  transform: translate(calc(var(--pin) / 2 + var(--pin-gap)), calc(var(--pin) / -2));
}

@media (prefers-reduced-motion: reduce) {
  .comment .text,
  .selection {
    transition: none;
  }
}

/* Out of the way while the style card is used, as it would hide the strokes the card changes. */
.selection {
  transition: opacity 0.15s;
}

:root:has(.style-card:hover, .style-card:focus-within, .style-card :active) .selection {
  opacity: 0;
}

.selection > *,
.preview > *,
.start,
.pivot,
.marquee,
.entered {
  fill: none;
  stroke: var(--selected);
  stroke-width: 1.5px;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.preview > * {
  stroke-width: 1px;
}

.preview.locked > * {
  stroke-dasharray: 2 4;
}

.marquee {
  fill: color-mix(in srgb, var(--selected) 15%, transparent);
  stroke-width: 1px;
}

.entered,
.start {
  stroke-width: 1px;
  stroke-dasharray: 4 4;
}

/* Thin as a preview, and dashed where they bridge, as they only come and go with a gesture. */
.lineup > * {
  fill: none;
  stroke: var(--selected);
  stroke-width: 1px;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.lineup .bridges {
  stroke-dasharray: 4 3;
  stroke-linecap: butt;
}

/* Wide and faint, so that it does not read as selected. */
.targets > * {
  fill: none;
  stroke: var(--selected);
  stroke-opacity: 0.5;
  stroke-width: 6px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.handles > * {
  fill: Canvas;
  stroke: var(--selected);
  stroke-width: 1.5px;
  vector-effect: non-scaling-stroke;
}

.handles .grabbed {
  fill: var(--selected);
  stroke: Canvas;
}

.handles .side,
.handles .turn {
  fill: none;
  stroke-linecap: round;
}

.handles .side {
  stroke-width: 3.5px;
}

.crop-shade {
  fill: rgb(0 0 0 / 0.5);
  fill-rule: evenodd;
}

.crop-frame {
  fill: none;
  stroke: var(--selected);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
}

.crop-guides {
  fill: none;
  vector-effect: non-scaling-stroke;
}

.crop-guides.halo {
  stroke: rgb(0 0 0 / 0.35);
  stroke-width: 3px;
}

.crop-guides.line {
  stroke: rgb(255 255 255 / 0.85);
  stroke-width: 1px;
}

[data-contrast="high"] .selection > *,
[data-contrast="high"] .crop-frame {
  stroke-width: 3px;
}

[data-contrast="high"] .preview > *,
[data-contrast="high"] .start,
[data-contrast="high"] .pivot,
[data-contrast="high"] .marquee,
[data-contrast="high"] .entered,
[data-contrast="high"] .handles > *,
[data-contrast="high"] .lineup > * {
  stroke-width: 2px;
}

[data-contrast="high"] .handles .side {
  stroke-width: 5px;
}

/* Over the board, where the renderer leaves out the text written in it. */
.writer {
  position: fixed;
  z-index: 1;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  resize: none;
  overflow: hidden;
  color: var(--ink);
  background: none;
  font-weight: 400;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  transform-origin: center;
}

/* Only the bar and the message take the pointer, so the board stays reachable around them. */
#toolbar {
  position: fixed;
  left: 50%;
  bottom: 16px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  /* Its own width, as the half of the window right of `left` would otherwise wrap the hint. */
  width: max-content;
  max-width: calc(100vw - 32px);
  transform: translateX(-50%);
  pointer-events: none;
}

.bar,
#message,
#measurements,
.menu,
.finder,
.comment .text,
.writer.bubble {
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}

/* No wider than the window, where its row scrolls. */
.bar {
  --edge: 32px;
  position: relative;
  box-sizing: border-box;
  max-width: 100%;
  padding: 4px;
  border-radius: 12px;
  pointer-events: auto;
}

/* Keys moving the focus bring its button out from under the edges. */
.bar .row {
  display: flex;
  align-items: center;
  gap: 4px;
  overflow-x: auto;
  /* Swiping on past an end would go back a page. */
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  scroll-behavior: smooth;
  scroll-padding-inline: var(--edge);
}

/* Where WebKit does not take `scrollbar-width` yet. */
.bar .row::-webkit-scrollbar {
  display: none;
}

.bar .row > * {
  flex-shrink: 0;
}

/* Over each end that hides more, where the buttons fade out under a chevron. */
.bar .edge {
  position: absolute;
  top: 4px;
  bottom: 4px;
  display: flex;
  align-items: center;
  width: var(--edge);
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms ease-out;
}

.bar .edge:hover {
  color: var(--text);
}

.bar .edge.before {
  left: 4px;
  justify-content: flex-start;
  background: linear-gradient(to right, var(--surface) 50%, transparent);
}

.bar .edge.after {
  right: 4px;
  justify-content: flex-end;
  background: linear-gradient(to left, var(--surface) 50%, transparent);
}

.bar.before .edge.before,
.bar.after .edge.after {
  opacity: 1;
  pointer-events: auto;
}

/* Swiped through on a touch screen, as a swipe from them would scroll nothing. */
@media (pointer: coarse) {
  .bar.before .edge.before,
  .bar.after .edge.after {
    pointer-events: none;
  }
}

.bar .edge svg {
  width: 14px;
  height: 14px;
}

.bar .edge.before svg {
  transform: rotate(90deg);
}

.bar .edge.after svg {
  transform: rotate(-90deg);
}

@media (prefers-reduced-motion: reduce) {
  .bar .row {
    scroll-behavior: auto;
  }

  .bar .edge {
    transition: none;
  }
}

.bar button,
.style-card button,
.style-card .custom {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--button, 36px);
  height: var(--button, 36px);
  padding: 0;
  border: 0;
  border-radius: 8px;
  color: inherit;
  background: none;
  cursor: pointer;
}

.bar button:hover,
.style-card button:hover,
.style-card .custom:hover {
  background: var(--hover);
}

.bar button[aria-pressed="true"],
.style-card button[aria-pressed="true"] {
  color: var(--accent);
  background: var(--accent-soft);
}

.bar button[aria-disabled="true"] {
  opacity: 0.4;
  cursor: default;
}

.bar button:focus-visible,
.style-card button:focus-visible,
.style-card .custom:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.bar svg,
.style-card svg {
  width: var(--icon, 20px);
  height: var(--icon, 20px);
}

/* Close to the button whose tools it lists, and still as wide as a pointer needs. */
.bar .chevron {
  width: 24px;
  margin-left: -4px;
  color: var(--muted);
}

.bar .chevron svg {
  width: 14px;
  height: 14px;
}

.bar .zoom {
  display: flex;
  gap: 2px;
  width: auto;
  padding: 0 6px 0 8px;
  font: inherit;
  font-variant-numeric: tabular-nums;
}

/* Wide enough for four digits, so that the bar stays put as the zoom changes. */
.bar .zoom span {
  min-width: 5.5ch;
  text-align: center;
}

.bar .zoom svg {
  width: 14px;
  height: 14px;
  color: var(--muted);
}

.bar button[aria-expanded="true"] {
  background: var(--hover);
}

.bar .key {
  position: absolute;
  right: 3px;
  bottom: 2px;
  font-size: 10px;
  line-height: 1;
  color: var(--muted);
}

.bar .separator,
.style-card .separator {
  width: 1px;
  height: 20px;
  margin: 0 4px;
  background: var(--line);
}

/* Under the selection. */
.style-chip,
.style-card,
.readout {
  position: fixed;
  z-index: 2;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}

.readout {
  display: flex;
  align-items: center;
  height: 22px;
  box-sizing: border-box;
  padding: 0 10px;
  border-radius: 11px;
  font:
    11px/1 ui-monospace,
    monospace;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
}

/* Bold too, so that colour is not all that tells it. */
.readout.snapped {
  border-color: var(--selected);
  font-weight: 600;
}

.style-chip {
  display: grid;
  place-items: center;
  width: 34px;
  height: 22px;
  padding: 0;
  border-radius: 11px;
  color: var(--muted);
  cursor: pointer;
}

.style-chip:hover {
  color: var(--text);
}

.style-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

.style-chip svg {
  width: 18px;
  height: 18px;
}

/* Out of the way in compact mode, where the context menu still opens the card. */
:root[data-compact] .style-chip {
  display: none;
}

.style-card {
  --button: 32px;
  --icon: 18px;
  display: flex;
  flex-direction: column;
  padding: 4px;
  border-radius: 12px;
}

.style-card .row {
  display: flex;
  align-items: center;
  gap: 2px;
}

/* The palette, the colours picked lately under it, then the pipette over a colour of one's own,
   spread over a wider card so that the pipette ends the row. */
.style-card .colours {
  display: grid;
  grid-template-columns: repeat(6, var(--button)) auto var(--button);
  justify-content: space-between;
  align-items: center;
  gap: 2px;
}

.style-card .separator {
  margin: 0 2px;
}

.style-card .colours .separator {
  height: 14px;
}

.style-card .rule {
  height: 1px;
  margin: 3px 4px;
  background: var(--line);
}

.style-card .letters {
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
}

.style-card .slider {
  --checks: repeating-conic-gradient(var(--line) 0 25%, transparent 0 50%) 0 0 / 6px 6px;
  display: flex;
  flex: 1;
  align-items: center;
  gap: 10px;
  height: var(--button);
  padding: 0 4px 0 9px;
}

.style-card .slider .track {
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
}

.style-card .slider input {
  flex: 1;
  height: 20px;
  margin: 0;
  background: none;
  appearance: none;
  cursor: pointer;
}

.style-card .slider input::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(to right, transparent, var(--tint)), var(--checks);
  box-shadow: inset 0 0 0 1px var(--line);
}

.style-card .slider input::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(to right, transparent, var(--tint)), var(--checks);
  box-shadow: inset 0 0 0 1px var(--line);
}

/* Centred on the track, which WebKit lays it at the top of. */
.style-card .slider input::-webkit-slider-thumb {
  width: 14px;
  height: 14px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow:
    0 0 0 2px var(--text),
    0 1px 3px rgb(0 0 0 / 30%);
  appearance: none;
}

.style-card .slider input::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: 0;
  border-radius: 50%;
  background: var(--surface);
  box-shadow:
    0 0 0 2px var(--text),
    0 1px 3px rgb(0 0 0 / 30%);
}

.style-card .slider.mixed input::-webkit-slider-thumb {
  opacity: 0;
}

.style-card .slider.mixed input::-moz-range-thumb {
  opacity: 0;
}

.style-card .slider input:focus-visible {
  border-radius: 4px;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Under the thumb's centre at each step, which travels a thumb less than the track. */
.style-card .slider .tick {
  position: absolute;
  top: calc(50% + 7px);
  left: calc(7px + (100% - 14px) * var(--at));
  width: 2px;
  height: 2px;
  margin-left: -1px;
  border-radius: 1px;
  background: var(--muted);
  pointer-events: none;
}

.style-card .slider .value {
  min-width: 40px;
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.style-card .facts {
  margin: 0;
  padding: 2px 4px;
  overflow: hidden;
  color: var(--muted);
  font-size: 12px;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Wider than the rows under it, so that the card keeps its width as they change. */
.style-card .scrub {
  position: relative;
  display: flex;
  flex: 1;
  align-items: center;
  min-width: 196px;
  height: var(--button);
  margin: 0 4px 0 6px;
}

.style-card .scrub .rail,
.style-card .scrub .kept {
  position: absolute;
  top: calc(50% - 3px);
  height: 6px;
  border-radius: 3px;
  pointer-events: none;
}

.style-card .scrub .rail {
  left: 0;
  right: 0;
  background: var(--line);
}

.style-card .scrub:is(.trimmed, .trimming) .rail {
  background: repeating-linear-gradient(-45deg, var(--line) 0 2px, transparent 2px 4px);
  box-shadow: inset 0 0 0 1px var(--line);
}

.style-card .scrub:is(.trimmed, .trimming) .kept {
  background: color-mix(in srgb, var(--text) 26%, transparent);
}

.style-card .scrub input {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 20px;
  margin: 0;
  background: none;
  appearance: none;
  cursor: pointer;
}

.style-card .scrub input::-webkit-slider-runnable-track {
  height: 6px;
  background: none;
}

.style-card .scrub input::-moz-range-track {
  height: 6px;
  background: none;
}

.style-card .scrub input::-webkit-slider-thumb {
  width: 14px;
  height: 14px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow:
    0 0 0 2px var(--text),
    0 1px 3px rgb(0 0 0 / 30%);
  appearance: none;
}

.style-card .scrub input::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: 0;
  border-radius: 50%;
  background: var(--surface);
  box-shadow:
    0 0 0 2px var(--text),
    0 1px 3px rgb(0 0 0 / 30%);
}

.style-card .scrub input:focus-visible {
  border-radius: 4px;
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* As wide as a pointer needs. */
.style-card .scrub .handle {
  position: absolute;
  z-index: 1;
  top: calc(50% - 10px);
  width: 12px;
  height: 20px;
  margin-left: -6px;
  border-radius: 3px;
  cursor: ew-resize;
  touch-action: none;
}

.style-card .scrub .handle:hover {
  background: none;
}

.style-card .scrub .handle::before {
  content: "";
  width: 4px;
  height: 16px;
  border-radius: 2px;
  background: var(--text);
}

.style-card .scrub .handle:hover::before {
  background: var(--accent);
}

.style-card .count,
.style-card .note {
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Wide enough for four digits a side, so that the track stays put as it plays. */
.style-card .count {
  min-width: 9ch;
  padding-right: 4px;
  text-align: right;
}

/* As wide as minutes and seconds to the hundredth. */
.style-card .count.clock {
  min-width: 7ch;
}

.style-card .note {
  flex: 1;
  padding: 0 6px;
}

.style-card button.wide {
  width: auto;
  min-width: var(--button);
  padding: 0 8px;
}

.style-card button.push {
  margin-left: auto;
}

/* As wide as its widest speed, so that the buttons around it stay put as it changes. */
.style-card button.speed {
  width: 52px;
}

/* As wide as its widest count, so that the button after it stays put as it changes. */
.style-card .tally {
  min-width: 10ch;
  text-align: center;
}

.style-card button[aria-disabled="true"] {
  opacity: 0.4;
  cursor: default;
}

.style-card button[aria-disabled="true"]:hover {
  background: none;
}

.style-card .custom input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.swatch {
  display: block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--swatch);
  box-shadow: inset 0 0 0 1px var(--line);
  /* A colour to choose, which forced colours would hide. */
  forced-color-adjust: none;
}

/* Square ones are no theme's, picked or a sticky note's paper. */
.swatch.own {
  border-radius: 5px;
}

.swatch.paper {
  border-radius: 4px;
}

/* In its own colour, as the accent would read as one more to choose. */
.style-card button[aria-pressed="true"]:has(> .swatch) {
  background: color-mix(in srgb, var(--swatch) 24%, transparent);
}

/* Towards the text, as pale ones alone would not show around their swatch. */
.style-card button[aria-pressed="true"] .swatch {
  outline: 1.5px solid color-mix(in srgb, var(--swatch) 55%, var(--text));
  outline-offset: 2px;
}

.export-card button {
  display: flex;
  width: auto;
  padding: 0 9px;
}

.export-card .letters {
  display: flex;
  align-items: center;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}

.export-card .swatch {
  width: 14px;
  height: 14px;
}

.swatch.board {
  --swatch: var(--board);
}

.swatch.white {
  --swatch: #ffffff;
}

.swatch.transparent {
  background: repeating-conic-gradient(var(--line) 0 25%, var(--surface) 0 50%) 0 0 / 6px 6px;
}

.export-card .facts {
  margin-left: auto;
  padding-left: 12px;
  font-variant-numeric: tabular-nums;
}

.export-card .actions button {
  flex: 1;
  justify-content: center;
}

.style-card button.primary {
  width: auto;
  padding: 0 9px;
  color: var(--accent);
  background: var(--accent-soft);
}

.style-card button.primary .letters {
  display: flex;
  align-items: center;
  gap: 6px;
}

.style-card kbd {
  font: inherit;
  font-weight: 400;
  color: var(--muted);
}

#viewport.sampling {
  cursor: crosshair;
}

.loupe {
  position: fixed;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  pointer-events: none;
}

.loupe .lens {
  position: relative;
  overflow: hidden;
  border: 3px solid var(--surface);
  border-radius: 50%;
  box-shadow: var(--shadow);
}

.loupe canvas {
  display: block;
  image-rendering: pixelated;
}

/* As the board shows, which the pixels it reads are not. */
:root:has(#viewport.mirrored) .loupe canvas {
  transform: scaleX(-1);
}

.loupe .lens::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7px;
  height: 7px;
  translate: -50% -50%;
  outline: 1px solid var(--surface);
  box-shadow: 0 0 0 2px var(--text);
}

.loupe span {
  padding: 2px 6px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font:
    11px/1.4 ui-monospace,
    monospace;
  background: var(--surface);
}

.loupe span:empty {
  display: none;
}

.menu-button.unsaved::after {
  content: "";
  position: absolute;
  top: 6px;
  right: 6px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

/* On a plain surface, as the images under it would leave it unreadable. */
.hint {
  margin: 0;
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 12px;
  color: var(--muted);
  background: var(--surface);
  text-align: center;
}

.hint:empty {
  display: none;
}

#message {
  max-width: 40rem;
  margin: 0;
  padding: 6px 12px;
  border-radius: 8px;
  text-align: center;
  overflow-wrap: anywhere;
  pointer-events: auto;
}

/* Hidden from sight only, where screen readers keep listening to it. */
#message:empty {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
}

.menu {
  position: fixed;
  z-index: 3;
  display: flex;
  flex-direction: column;
  min-width: 13rem;
  padding: 4px;
  border-radius: 10px;
}

.menu button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 6px 10px;
  border: 0;
  border-radius: 6px;
  font: inherit;
  text-align: left;
  color: inherit;
  background: none;
  cursor: pointer;
}

.menu .name,
.finder .name {
  display: flex;
  align-items: center;
  gap: 10px;
}

.menu svg {
  width: 18px;
  height: 18px;
}

.menu [role="menuitemradio"][aria-checked="true"] .name {
  color: var(--accent);
  font-weight: 600;
}

.menu .end,
.finder .end {
  display: flex;
  align-items: center;
  gap: 8px;
}

.menu .opens {
  width: 14px;
  height: 14px;
  color: var(--muted);
  transform: rotate(-90deg);
}

.menu .tick,
.finder .tick {
  color: var(--accent);
}

/* The tick takes the shortcut's place, which the toolbar's button shows already. */
.menu [aria-checked="false"] .tick,
.finder [aria-checked="false"] .tick,
.menu [role="menuitemradio"][aria-checked="true"] kbd {
  display: none;
}

/* Outlined while off, so that it shows in every theme. */
.menu .switch,
.finder .switch {
  position: relative;
  box-sizing: border-box;
  width: 26px;
  height: 16px;
  border: 1px solid var(--muted);
  border-radius: 8px;
}

.menu .switch::after,
.finder .switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted);
}

.menu [aria-checked="true"] .switch,
.finder [aria-checked="true"] .switch {
  border-color: var(--accent);
  background: var(--accent);
}

.menu [aria-checked="true"] .switch::after,
.finder [aria-checked="true"] .switch::after {
  left: 12px;
  background: var(--surface);
}

/* Hovering moves the focus, so the tint marks both. */
.menu button:focus {
  outline: none;
  background: var(--accent-soft);
}

.menu button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.menu button[aria-disabled="true"] {
  opacity: 0.45;
  cursor: default;
}

.menu kbd,
.finder kbd {
  font: inherit;
  color: var(--muted);
}

.menu [role="separator"] {
  height: 1px;
  margin: 4px 6px;
  background: var(--line);
}

/* High in the window, where the eye goes first, and short enough for a small one. */
.finder {
  position: fixed;
  top: min(15vh, 96px);
  left: 50%;
  z-index: 3;
  display: flex;
  flex-direction: column;
  width: min(32rem, calc(100vw - 16px));
  max-height: min(28rem, calc(100vh - 2 * min(15vh, 96px)));
  padding: 4px;
  border-radius: 10px;
  transform: translateX(-50%);
}

.finder input {
  margin: 0 0 4px;
  padding: 8px 10px;
  border: 0;
  border-bottom: 1px solid var(--line);
  outline: none;
  color: inherit;
  background: none;
  font: inherit;
}

.finder [role="listbox"] {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.finder [role="option"] {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
}

.finder [aria-selected="true"] {
  background: var(--accent-soft);
}

.finder [aria-disabled="true"] {
  opacity: 0.45;
  cursor: default;
}

.finder .within {
  color: var(--muted);
}

.finder .why {
  margin: 4px 10px 2px;
  color: var(--muted);
  font-size: 12px;
}

.finder .why:empty {
  display: none;
}

/* Forced colours drop backgrounds unless in system colours. */
@media (forced-colors: active) {
  /* Theirs for the selection and one colour for everything drawn, as forced colours would have it, whatever the theme. */
  :root,
  :root[data-theme="dark"],
  :root[data-contrast="high"],
  :root[data-theme="dark"][data-contrast="high"] {
    /* As the page's own background, which a picture on the board's colour takes. */
    --board: Canvas;
    --selected: Highlight;
    --ink: CanvasText;
    --red: CanvasText;
    --orange: CanvasText;
    --green: CanvasText;
    --blue: CanvasText;
    --violet: CanvasText;
    --highlight-yellow: CanvasText;
    --highlight-red: CanvasText;
    --highlight-orange: CanvasText;
    --highlight-green: CanvasText;
    --highlight-blue: CanvasText;
    --highlight-violet: CanvasText;
  }

  .bar button[aria-pressed="true"] {
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }

  /* Solid, as forced colours drop gradients. */
  .bar .edge.before,
  .bar .edge.after {
    background: Canvas;
  }

  .bar .separator,
  .menu [role="separator"] {
    background: CanvasText;
  }

  /* Outlined, as forced colours drop the track's gradient and the thumb's shadow. */
  .style-card .slider input::-webkit-slider-runnable-track {
    border: 1px solid CanvasText;
  }

  .style-card .slider input::-moz-range-track {
    border: 1px solid CanvasText;
  }

  .style-card .slider input::-webkit-slider-thumb {
    box-sizing: border-box;
    border: 2px solid CanvasText;
  }

  .style-card .slider input::-moz-range-thumb {
    box-sizing: border-box;
    border: 2px solid CanvasText;
  }

  .style-card .slider .tick {
    background: CanvasText;
  }

  .style-card .scrub .rail {
    border: 1px solid CanvasText;
  }

  .style-card .scrub input::-webkit-slider-thumb {
    box-sizing: border-box;
    border: 2px solid CanvasText;
  }

  .style-card .scrub input::-moz-range-thumb {
    box-sizing: border-box;
    border: 2px solid CanvasText;
  }

  .style-card .scrub .kept,
  .style-card .scrub .handle::before {
    background: CanvasText;
  }

  .menu-button.unsaved::after {
    background: Highlight;
  }

  .menu button:focus,
  .finder [aria-selected="true"] {
    color: HighlightText;
    background: Highlight;
  }

  .menu .switch,
  .finder .switch {
    border-color: CanvasText;
  }

  .menu .switch::after,
  .finder .switch::after {
    background: CanvasText;
  }

  .menu [aria-checked="true"] .switch,
  .finder [aria-checked="true"] .switch {
    border-color: CanvasText;
    background: CanvasText;
  }

  .menu [aria-checked="true"] .switch::after,
  .finder [aria-checked="true"] .switch::after {
    background: Canvas;
  }

  .menu button:focus .switch,
  .finder [aria-selected="true"] .switch {
    border-color: HighlightText;
  }

  .menu button:focus .switch::after,
  .finder [aria-selected="true"] .switch::after {
    background: HighlightText;
  }

  .menu [aria-checked="true"]:focus .switch,
  .finder [aria-checked="true"][aria-selected="true"] .switch {
    background: HighlightText;
  }

  .menu [aria-checked="true"]:focus .switch::after,
  .finder [aria-checked="true"][aria-selected="true"] .switch::after {
    background: Highlight;
  }

  /* As the renderer draws it, which forced colours leave alone. */
  .writer {
    forced-color-adjust: none;
    color: CanvasText;
    background: none;
  }

  .comment .text,
  .writer.bubble {
    border-color: CanvasText;
    color: CanvasText;
    background: Canvas;
  }

  /* Solid, as forced colours drop the head's gradients, high contrast's flat one included. */
  .pin,
  [data-contrast="high"] .pin {
    border-color: Canvas;
    background: CanvasText;
  }
}

#measurements {
  position: fixed;
  top: 12px;
  right: 12px;
  z-index: 2;
  max-height: calc(100vh - 140px);
  overflow: auto;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 12px;
}

:root[data-compact] .bar,
:root[data-compact] .hint,
:root[data-compact] #measurements {
  display: none;
}

/* Clear but for its grip, to cover little of a small window. Under the text being written. */
#handle {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  display: none;
  align-items: center;
  justify-content: flex-end;
  height: 24px;
  padding: 0 4px;
  border-bottom: 1px solid transparent;
  cursor: grab;
  transition:
    background-color 150ms,
    border-color 150ms;
}

:root[data-compact] #handle {
  display: flex;
}

/* Always there, as macOS tells the page nothing of the pointer while its window is behind. */
#handle::before {
  content: "";
  position: absolute;
  top: 10px;
  left: calc(50% - 16px);
  width: 32px;
  height: 4px;
  border-radius: 2px;
  background: var(--muted);
  box-shadow: 0 0 0 1px var(--surface);
}

#handle:hover,
#handle:focus-within {
  border-bottom-color: var(--line);
  background: var(--surface);
}

#handle button {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 0;
  border-radius: 4px;
  color: inherit;
  background: none;
  opacity: 0;
  cursor: pointer;
  transition: opacity 150ms;
}

#handle:hover button,
#handle:focus-within button {
  opacity: 1;
}

#handle button:hover {
  background: var(--hover);
}

#handle button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

#handle svg {
  width: 16px;
  height: 16px;
}

@media (prefers-reduced-motion: reduce) {
  #handle,
  #handle button {
    transition: none;
  }
}

/* Apart from the other forced colours, as it must come after the grip's own. */
@media (forced-colors: active) {
  #handle::before {
    background: CanvasText;
  }
}

dl {
  display: grid;
  grid-template-columns: auto auto;
  gap: 0.25rem 1rem;
  margin: 0;
  font-variant-numeric: tabular-nums;
}

dt {
  color: var(--muted);
}

dd {
  margin: 0;
}
