:root {
  /* courtyard neutrals: plaster for surfaces and lines, leaf shadow for text. no greys */
  --bg: #efe3df;
  --panel: #f9f6f3;
  --field: #fff;
  --chip: #f3eae7;
  --line: #e2d0cb;
  --line-strong: #d3bcb6;
  --muted: #6e6276;
  --ink: #2f2838;
  --ink-deep: #211b29;
  --ui: 'Atkinson Hyperlegible Next', system-ui, sans-serif;
  /* wisteria: one fixed accent for selected and active states. no thread swatch sits near it, so the UI never competes with the stitches */
  /* the card sits on an aubergine felt mat: the room around the work goes dark so every paper reads as an object */
  --felt: #3b3441;
  --felt-tex:
    radial-gradient(120% 90% at 30% 15%, rgba(255, 250, 240, 0.08), transparent 60%),
    radial-gradient(140% 120% at 50% 40%, transparent 55%, rgba(30, 20, 15, 0.18)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.4' numOctaves='2' seed='6' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .6 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='1' seed='12' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 .95 0 0 0 0 1 .18 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --felt-tex-soft:
    radial-gradient(120% 90% at 30% 15%, rgba(255, 250, 240, 0.07), transparent 60%),
    radial-gradient(140% 120% at 50% 40%, transparent 55%, rgba(30, 20, 15, 0.16)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.55' numOctaves='3' seed='6' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .32 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --accent: #6b4e8c;
  --on-accent: #fff;
  --error: #a8243a;
  --on-ink: #fff;
  --accent-soft: rgba(107, 78, 140, 0.25); /* focus halo, text selection */
  /* shadows on the panel and windows are the ink at four strengths; on the felt they are black, at two */
  --shade-1: rgba(47, 40, 56, 0.06);
  --shade-2: rgba(47, 40, 56, 0.18);
  --shade-3: rgba(47, 40, 56, 0.3);
  --shade-4: rgba(47, 40, 56, 0.5);
  --felt-shade: rgba(0, 0, 0, 0.3);
  --felt-shade-deep: rgba(0, 0, 0, 0.5);
  --on-felt-soft: rgba(249, 246, 243, 0.7); /* quiet text and outlines on the felt */
  /* type: five sizes. two exceptions live where they are used: the letter in a list thumbnail (24px, a glyph, not text)
     and text fields on touch screens (16px, below which iOS zooms the page) */
  /* corners: three sizes by how big the thing is. anything nested inside a rounded container takes the container's
     radius minus the gap between them (calc(var(--r) - var(--gap))), so the two curves stay parallel */
  --r-window: 16px; /* windows and sheets */
  --r-float: 12px; /* things that float: toolbars, the selection bar, the toast, option cards */
  --r-control: 8px; /* buttons, fields, tiles, rows */
  --r-tiny: 4px; /* key caps */
  --text-xs: 11px; /* tile captions, key caps */
  --text-sm: 12.5px; /* secondary: summaries, meta, stats, small notes */
  --text-md: 13.5px; /* body, labels, buttons, sub-headings */
  --text-lg: 14.5px; /* section headings */
  --text-xl: 17px; /* window titles, the text field, the big line in a window */
  /* phones: the card is pinned in the top half; settings live in a bottom sheet that rests at half height
   (card and settings visible together) and drags up to nearly full screen */
  --sheet-rest: 52dvh;
}
* {
  box-sizing: border-box;
}
/* phones: no gray tap flash, and quick taps never trigger double-tap zoom (pinch zoom still works) */
html {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
html,
body {
  margin: 0;
  height: 100%;
}
body {
  background: var(--bg);
  color: var(--ink);
  font: var(--text-md)/1.45 var(--ui);
  -webkit-font-smoothing: antialiased;
}
/* the tool is handled like an app: a long press or a drag never selects the page's text or calls up the phone's
   copy menu. text fields keep normal selection, and so do the windows (How to use, Print), which sit outside .app */
.app {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  display: grid;
  grid-template-columns: 340px 1fr;
  height: 100vh;
}
.panel {
  background: var(--panel);
  border-right: 1px solid var(--line);
  overflow-y: auto;
  padding: 0 20px 40px;
}
h1 {
  margin: 0;
  line-height: 0;
  color: var(--ink);
}
.wordmark {
  display: block;
  width: auto;
  height: 26px;
}
.top {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 -20px;
  padding: 16px 20px 14px;
  background: var(--panel);
  transition: box-shadow 0.2s ease;
}
.top.lifted {
  box-shadow:
    0 1px 0 var(--line),
    0 6px 12px -10px var(--shade-3);
}
.top h1 {
  margin: 0;
}
button.ghost {
  border-color: transparent;
  background: transparent;
  color: var(--muted);
  padding: 7px 9px;
}
.sum {
  margin-left: auto;
  color: var(--muted);
  font-size: var(--text-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 190px;
}
.blk {
  border-top: 1px solid var(--line);
  padding: 14px 2px 16px;
}
.top + .view > .blk:first-child {
  border-top: 0;
  padding-top: 4px;
}
.blk h2 {
  margin-bottom: 10px;
}
.hrow {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.blk > h2 {
  margin-bottom: 12px;
}
.addrow {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.addrow button {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 10px;
}
.addrow .i {
  width: 15px;
  height: 15px;
}
.addrow.filerow {
  margin-top: 2px;
}
.toast:has(button[hidden]) {
  padding: 10px 14px;
}
.sublabel {
  margin: 0 0 9px;
  color: var(--muted);
}
.row.gap {
  margin: 16px 0 0;
}
.row.gap label {
  flex: none;
  white-space: nowrap;
}
.layers {
  list-style: none;
  margin: 0 -8px;
  padding: 0;
  display: grid;
  gap: 1px;
}
.layer {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: 0;
  background: transparent;
  padding: 5px 8px;
  --r: var(--r-control);
  --gap: 5px;
  border-radius: var(--r);
  text-align: left;
  font-weight: 400;
}
.lthumb {
  width: 32px;
  height: 32px;
  border-radius: calc(var(--r) - var(--gap));
  background: var(--bg);
  border: 1px solid var(--line);
  display: grid;
  place-items: center;
  overflow: hidden;
  flex: none;
}
.lthumb img,
.lthumb canvas {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.ltext {
  font-size: 24px;
  line-height: 1;
  padding-top: 4px;
}
.lname {
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.lmeta {
  margin-left: auto;
  color: var(--muted);
  font-size: var(--text-sm);
  white-space: nowrap;
}
.layers .empty {
  color: var(--muted);
  padding: 4px 8px;
}
.layers li {
  position: relative;
}
.splitbtn {
  width: 100%;
  margin: -4px 0 14px;
}
.sw.custom {
  position: relative;
  overflow: hidden;
  background: conic-gradient(from 90deg, #e0473c, #e0b73c, #5fb85a, #3ca6e0, #8a5ad6, #e0473c);
}
.sw.custom input {
  position: absolute;
  inset: -6px;
  width: calc(100% + 12px);
  height: calc(100% + 12px);
  opacity: 0;
  cursor: pointer;
  padding: 0;
  border: 0;
}
.view.enter {
  animation: viewIn 0.24s cubic-bezier(0.2, 0.9, 0.3, 1);
}
@keyframes viewIn {
  from {
    opacity: 0;
    transform: translateX(10px);
  }
}
.vhead {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0 14px;
}
.back {
  border: 0;
  background: transparent;
  padding: 7px;
  margin-left: -7px;
  color: var(--muted);
  border-radius: var(--r-control);
}
.panel .ib {
  border: 0;
  background: transparent;
  border-radius: var(--r-control);
  padding: 7px;
  color: var(--ink);
}
.bigin {
  font: 500 var(--text-xl)/1.2 var(--ui) !important;
  padding: 10px 12px !important;
  margin: 0 0 14px;
}
h3.sub {
  font: 700 var(--text-md)/1.3 var(--ui);
  margin: 20px 0 10px;
}
.btns.two {
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-bottom: 14px;
}
/* a switch row: the label takes one line and the switch sits at the row's right edge, under the values and the Auto pill */
.row:has(.switch) label {
  flex: 1;
  white-space: nowrap;
}
.row:has(.switch) .ctl {
  flex: none;
}
.switch {
  -webkit-appearance: none;
  appearance: none;
  flex: none;
  border: 0;
  width: 34px;
  height: 20px;
  border-radius: 999px;
  background: var(--line);
  position: relative;
  cursor: pointer;
  transition: background 0.18s;
  margin: 0;
}
.switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--field);
  box-shadow: 0 1px 2px var(--shade-3);
  transition:
    transform 0.32s cubic-bezier(0.3, 1.6, 0.5, 1),
    width 0.15s;
}
.switch:checked {
  background: var(--accent);
}
.switch:checked::after {
  transform: translateX(14px);
}
.row label {
  line-height: 1.25;
  flex: 0 0 84px;
  color: var(--muted);
}
h2 {
  font: 700 var(--text-lg)/1.3 var(--ui);
  letter-spacing: 0;
  color: var(--ink);
  margin: 0;
}
button.grow {
  flex: 1;
}
.addfont {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.addfont button {
  flex: 1;
}
.err {
  color: var(--error);
  font-size: var(--text-sm);
  margin: 8px 0 0;
}
/* windows: the header (title + close) stays pinned while the body scrolls. on phones they're bottom sheets */
dialog {
  border: 0;
  border-radius: var(--r-window);
  padding: 0;
  max-width: 520px;
  width: calc(100% - 32px);
  max-height: min(84vh, 720px);
  color: var(--ink);
  background: var(--panel);
  box-shadow: 0 24px 60px -12px var(--shade-3);
  overflow: hidden;
}
dialog[open] {
  display: flex;
  flex-direction: column;
}
/* the entrance plays once (.settled), so dragging a sheet never replays it */
dialog[open]:not(.settled) {
  animation: winIn 0.26s cubic-bezier(0.2, 0.8, 0.2, 1);
}
dialog::backdrop {
  background: var(--shade-3);
  animation: fadeIn 0.26s ease;
}
dialog[open].closing {
  animation: winOut 0.16s ease-in forwards;
}
dialog.closing::backdrop {
  animation: fadeOut 0.16s ease-in forwards;
}
@keyframes winIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}
@keyframes winOut {
  to {
    opacity: 0;
    transform: translateY(6px);
  }
}
@keyframes fadeIn {
  from {
    opacity: 0;
  }
}
@keyframes fadeOut {
  to {
    opacity: 0;
  }
}
.dlg {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
  outline: none;
}
.dlg > header {
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 14px 12px 24px;
  transition: box-shadow 0.2s ease;
}
.dlg > header.lifted {
  box-shadow: 0 1px 0 var(--line);
}
.dlg .db {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 24px 22px;
}
.dlg h2 {
  font-size: var(--text-xl);
}
.dlg h3 {
  font: 700 var(--text-md)/1.3 var(--ui);
  margin: 18px 0 6px;
}
.dlg .lede {
  color: var(--ink);
  margin: 0;
}
.dlg .note {
  color: var(--ink);
  margin: 0 0 6px;
}
.dlg ul,
.dlg ol {
  padding-left: 18px;
  margin: 0;
  color: var(--ink);
}
.dlg li {
  margin-bottom: 6px;
}
.dlg .x {
  flex: none;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--chip);
  color: var(--ink);
}
.dlg .x .i {
  width: 16px;
  height: 16px;
  stroke-width: 2;
}
@media (hover: hover) {
  .dlg .x:hover {
    background: var(--line);
  }
}
.btns.end {
  justify-content: flex-end;
  margin-top: 18px;
}
kbd {
  font: 500 var(--text-xs)/1 var(--ui);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: var(--r-tiny);
  padding: 2px 5px;
  background: var(--field);
}
.font {
  position: relative;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: 0 0 6px;
  overflow: hidden;
  cursor: pointer;
  text-align: center;
  transition:
    transform 0.25s cubic-bezier(0.3, 1.6, 0.5, 1),
    border-color 0.15s,
    box-shadow 0.15s;
}
.font .rm {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 20px;
  height: 20px;
  padding: 0;
  border-radius: 50%;
  font-size: var(--text-md);
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s;
}
.font .rm:focus-visible {
  opacity: 1;
}
.row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
}
.row .ctl {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.val {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--ink);
  min-width: 44px;
  text-align: right;
}
select {
  -webkit-appearance: none;
  appearance: none;
  padding-right: 30px !important;
  cursor: pointer;
  background: var(--field)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236E6276' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E")
    no-repeat right 9px center !important;
}
select,
input[type='text'] {
  font: inherit;
  color: inherit;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: 6px 8px;
  width: 100%;
}
input[type='range'] {
  flex: 1;
  min-width: 0;
  /* sliders: a wisteria track filling to a white bead (--p is set by fillRange) */
  -webkit-appearance: none;
  appearance: none;
  height: 22px;
  background: transparent;
  cursor: pointer;
}
/* text fields: wisteria caret, highlight and focus, instead of the system's (which follows each person's OS accent) */
::selection {
  background: var(--accent-soft);
}
input[type='text'] {
  -webkit-user-select: text;
  user-select: text;
  caret-color: var(--accent);
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
input[type='text']:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
select:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
/* keyboard focus: one wisteria ring everywhere, instead of the system's (which follows each person's OS accent) */
button:focus-visible,
.font:focus-visible,
input[type='checkbox']:focus-visible,
.sw.custom:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.toolbar button:focus-visible {
  outline-offset: 1px;
}
.stage .printopen:focus-visible {
  outline-color: var(--panel);
}
/* on the felt, the ring flips light */
button {
  font: 500 var(--text-md)/1 var(--ui);
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--r-control);
  padding: 9px 12px;
  cursor: pointer;
  /* tactile: things press in when touched and spring back. buttons are crisp (no overshoot);
   swatches, the slider bead and the switch knob get a small spring */
  transition:
    background 0.15s,
    border-color 0.15s,
    box-shadow 0.12s,
    transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1);
}
button:active {
  transform: translateY(1px) scale(0.97);
  transition-duration: 0.06s;
}
.btns {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.fonts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}
.font.on {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}
.font canvas {
  width: 100%;
  height: auto;
  display: block;
  border-bottom: 1px solid var(--line);
}
/* the preview sits on the card's paper; a hairline makes its edge deliberate on every stock */
.font span {
  display: block;
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: 5px;
  padding: 0 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
[hidden] {
  display: none !important;
}
.toolbar .sep {
  width: 1px;
  background: var(--line);
  margin: 4px 3px;
}
.toolbar.sub {
  position: absolute;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  width: max-content;
  white-space: nowrap;
  animation: subIn 0.22s cubic-bezier(0.2, 0.9, 0.3, 1);
}
@keyframes subIn {
  from {
    opacity: 0;
    transform: translate(-50%, -6px);
  }
}
/* Add / Erase: one wisteria thumb that slides between the two */
.seg {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.seg::before {
  content: '';
  position: absolute;
  inset: 0 50% 0 0;
  border-radius: calc(var(--r) - var(--gap));
  background: var(--accent);
  transition: transform 0.3s cubic-bezier(0.3, 1.35, 0.5, 1);
}
.seg[data-pm='erase']::before {
  transform: translateX(100%);
}
.seg button {
  position: relative;
  transition:
    color 0.15s,
    transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.toolbar.sub .seg button.on {
  background: transparent;
}
.swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.sw {
  width: 27px;
  height: 27px;
  border-radius: 50%;
  border: 2px solid var(--panel);
  box-shadow: 0 0 0 1px var(--line);
  cursor: pointer;
  padding: 0;
  transition:
    transform 0.3s cubic-bezier(0.3, 1.7, 0.5, 1),
    box-shadow 0.15s;
}
.sw.on {
  box-shadow: 0 0 0 2px var(--ink);
  transform: scale(1.1);
}
.stage {
  background-color: var(--felt);
  background-image: var(--felt-tex);
  background-size:
    auto,
    auto,
    300px 300px,
    300px 300px;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  padding: 24px;
}
.stagebar {
  position: absolute;
  z-index: 3;
  top: 16px;
  left: 16px;
  right: 16px;
  display: flex;
  justify-content: center;
  align-items: center;
  pointer-events: none;
}
.stagebar > * {
  pointer-events: auto;
}
.printopen {
  position: absolute;
  right: 0;
  padding: 10px 18px;
}
.stage .printopen {
  background: var(--panel);
  color: var(--ink);
  border-color: var(--panel);
  font-weight: 600;
  box-shadow:
    0 1px 0 var(--felt-shade),
    0 4px 10px -4px var(--felt-shade-deep);
}
.toolbar {
  display: flex;
  background: var(--field);
  border: 1px solid var(--line);
  --r: var(--r-float);
  --gap: 4px;
  border-radius: var(--r);
  padding: 3px;
  gap: 2px;
  box-shadow:
    inset 0 -1px 0 var(--line),
    0 2px 6px -3px var(--shade-2);
}
.toolbar button {
  border: 0;
  background: transparent;
  padding: 8px 12px;
  border-radius: calc(var(--r) - var(--gap));
}
.toolbar button.on {
  background: var(--accent);
  color: var(--on-accent);
}
.toolbar .hb {
  padding: 8px 9px;
}
.toolbar.sub button.on {
  background: var(--accent);
  color: var(--on-accent);
}
.toolbar button:disabled {
  color: var(--line-strong);
  cursor: default;
  transform: none;
}
.toast {
  position: absolute;
  left: 50%;
  bottom: 48px;
  z-index: 6;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 7px 7px 14px;
  --r: var(--r-float);
  --gap: 7px;
  border-radius: var(--r);
  background: var(--panel);
  color: var(--ink);
  font-size: var(--text-md);
  line-height: 1.3;
  width: max-content;
  max-width: calc(100% - 32px);
  box-shadow: 0 10px 24px -8px var(--felt-shade-deep);
  opacity: 0;
  transform: translate(-50%, 8px);
  pointer-events: none;
  transition:
    opacity 0.18s ease,
    transform 0.26s cubic-bezier(0.2, 0.9, 0.3, 1.15);
}
.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
  pointer-events: auto;
}
.toast button {
  flex: none;
  border: 0;
  background: var(--chip);
  color: var(--ink);
  font-weight: 600;
  padding: 6px 10px;
  border-radius: calc(var(--r) - var(--gap));
}
#card {
  display: block;
  box-shadow:
    0 0 0 0.5px var(--felt-shade),
    0 1px 1.5px var(--felt-shade),
    0 3px 6px -3px var(--felt-shade);
  /* lying flat on the felt: a contact shadow, no lift */
  border-radius: 2px;
  touch-action: none;
  flex: none;
  will-change: transform;
}
#card.ease {
  transition: transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.stats {
  position: absolute;
  bottom: 16px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  gap: 18px;
  color: var(--on-felt-soft);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  flex-wrap: wrap;
  padding: 0 16px;
  z-index: 2;
  pointer-events: none;
}
.stats b {
  color: var(--panel);
  font-weight: 600;
}
.stage.zoomed .stats span {
  background: var(--felt);
  padding: 4px 9px;
  border-radius: var(--r-control);
  margin: -4px 0;
}
/* zoomed in, the card can sit under them */
/* zoom: − 1× + at the bottom right; the number resets the view */
.zoomer {
  position: absolute;
  z-index: 3;
  right: 16px;
  bottom: 12px;
}
.zoomer .zv {
  min-width: 44px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  padding: 8px 6px;
}
#print {
  display: none;
}
.selbar {
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  background: var(--field);
  border: 1px solid var(--line);
  --r: var(--r-float);
  --gap: 5px;
  border-radius: var(--r);
  box-shadow:
    0 1px 2px var(--shade-1),
    0 10px 24px -8px var(--shade-3);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(4px) scale(0.98);
  pointer-events: none;
  transition:
    opacity 0.16s ease,
    transform 0.22s cubic-bezier(0.2, 0.9, 0.3, 1.15);
}
.selbar.show {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.selbar.show.busy {
  opacity: 0;
  pointer-events: none;
  transition-duration: 0.08s;
}
.sb-sep {
  width: 1px;
  align-self: stretch;
  background: var(--line);
  margin: 4px 2px;
}
.sb-range {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 6px;
  color: var(--muted);
  font-size: var(--text-sm);
}
.sb-range input {
  width: 84px;
  flex: none;
}
.selbar .ib,
.selbar .tb {
  border: 0;
  background: transparent;
  border-radius: calc(var(--r) - var(--gap));
  padding: 7px;
  color: var(--ink);
}
.selbar .tb {
  padding: 7px 10px;
}
.selbar .tb.on {
  background: var(--accent);
  color: var(--on-accent);
}
.selbar .tb.strong {
  background: var(--ink);
  color: var(--on-ink);
}
.i {
  display: block;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}
.i * {
  vector-effect: non-scaling-stroke;
}
[data-icon] {
  display: contents;
}
#card.drop {
  outline: 2px dashed var(--on-felt-soft);
  outline-offset: 6px;
}
.popts {
  display: grid;
  gap: 8px;
  margin: 14px 0;
}
.popt {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  background: var(--field);
  border: 1px solid var(--line);
  border-radius: var(--r-float);
  padding: 12px 14px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.popt:has(input:checked) {
  border-color: var(--accent);
}
.popt input {
  margin: 2px 0 0;
  accent-color: var(--accent);
}
.popt b {
  display: block;
  font-weight: 600;
}
.popt small {
  display: block;
  color: var(--muted);
  font-size: var(--text-sm);
  margin-top: 2px;
}
.callout {
  background: var(--chip);
  border: 0;
  border-radius: var(--r-control);
  padding: 11px 14px;
  color: var(--ink);
  font-size: var(--text-md);
}
.callout b {
  display: block;
  color: var(--ink);
  margin-bottom: 2px;
}
.dlg .big {
  font: 700 var(--text-xl)/1.35 var(--ui);
  color: var(--ink);
  margin: 4px 0 6px;
}
.dlg p {
  color: var(--ink);
  margin: 0;
}
.measure {
  width: 96px;
  height: 96px;
  margin: 14px 0 0;
  position: relative;
  border-radius: var(--r-control);
  background: var(--field);
  border: 1px solid var(--line);
}
.measure span {
  position: absolute;
  inset: 18px;
  border: 2px solid var(--ink);
  border-radius: 1px;
}
.addrow button,
.btns button,
.popt,
.splitbtn,
.addfont button,
.printopen {
  box-shadow:
    0 1px 0 var(--line-strong),
    0 1px 2px var(--shade-1);
}
.addrow button:active,
.btns button:active,
.splitbtn:active,
.addfont button:active,
.printopen:active {
  box-shadow: 0 0 0 var(--line-strong);
}
/* after the lip rules above: a primary button carries its own, darker lip */
button.primary {
  background: var(--ink);
  color: var(--on-ink);
  border-color: var(--ink);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    0 1px 0 var(--ink-deep),
    0 3px 8px -3px var(--shade-4);
}
button.primary:active {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.1),
    0 0 0 var(--ink-deep),
    0 1px 3px -1px var(--shade-4);
}
.sw:active {
  transform: scale(0.88);
  transition-duration: 0.08s;
}
@media (hover: hover) {
  .sw:not(.on):hover {
    transform: translateY(-2px);
  }
}
.font:active {
  transform: scale(0.96);
  transition-duration: 0.06s;
}
input[type='range']::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 2px;
  background:
    linear-gradient(var(--accent), var(--accent)) 0 / var(--p, 50%) 100% no-repeat,
    var(--line);
}
input[type='range']::-moz-range-track {
  height: 4px;
  border-radius: 2px;
  background: var(--line);
}
input[type='range']::-moz-range-progress {
  height: 4px;
  border-radius: 2px;
  background: var(--accent);
}
input[type='range']::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin-top: -7px;
  border-radius: 50%;
  background: var(--field);
  border: 0;
  box-shadow:
    0 0 0 1.5px var(--accent),
    0 2px 4px var(--shade-3);
  transition: transform 0.22s cubic-bezier(0.3, 1.6, 0.5, 1);
}
input[type='range']::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--field);
  border: 0;
  box-shadow:
    0 0 0 1.5px var(--accent),
    0 2px 4px var(--shade-3);
  transition: transform 0.22s cubic-bezier(0.3, 1.6, 0.5, 1);
}
input[type='range']:active::-webkit-slider-thumb {
  transform: scale(1.2);
}
input[type='range']:active::-moz-range-thumb {
  transform: scale(1.2);
}
input[type='range']:focus-visible {
  outline: none;
}
input[type='range']:focus-visible::-webkit-slider-thumb {
  box-shadow:
    0 0 0 1.5px var(--accent),
    0 0 0 4px var(--accent-soft);
}
.switch:active::after {
  width: 20px;
}
.switch:checked:active::after {
  transform: translateX(10px);
}
@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
.measure span::after {
  content: '1″';
  position: absolute;
  bottom: -17px;
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--text-xs);
  color: var(--muted);
}
@media screen and (max-width: 820px) {
  /* screen only: a printed page is narrower than 820px, and these rules would clip the print to one page */
  html,
  body {
    overflow: hidden;
    overscroll-behavior: none;
  }
  /* the felt covers the whole screen behind the sheet, so wherever the sheet rests (Safari's toolbars move it) there's never a gap.
     the grain is softer and coarser here: at phone pixel density the desktop noise read as static */
  html {
    background-color: var(--felt);
    background-image: var(--felt-tex-soft);
    background-size:
      auto,
      auto,
      240px 240px;
  }
  body {
    background: transparent;
  }
  .stage {
    background: none;
    position: fixed;
    inset: 0 0 auto 0;
    height: calc(100dvh - var(--sheet-rest));
    padding: 72px 16px 10px;
    justify-content: flex-start;
  }
  .app {
    display: block;
    height: 100dvh;
  }
  .stats {
    position: relative;
    bottom: auto;
    margin-top: 10px;
  }
  /* bottom:auto: the desktop offset would lift it onto the card */
  /* phones zoom by pinching; the number shows only while zoomed, and tapping it goes back */
  .zoomer {
    right: 12px;
    bottom: auto;
    top: 66px;
  }
  .zoomer .hb {
    display: none;
  }
  .stage:not(.zoomed) .zoomer {
    display: none;
  }
  .stagebar {
    justify-content: space-between;
  }
  .printopen {
    position: relative;
  }
  .panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10;
    height: var(--sheet-h, var(--sheet-rest));
    border-right: 0;
    border-radius: var(--r-window) var(--r-window) 0 0;
    box-shadow:
      0 -1px 0 var(--line),
      0 -10px 30px -12px var(--shade-3);
    padding-bottom: calc(24px + env(safe-area-inset-bottom));
    transition: height 0.32s cubic-bezier(0.2, 0.9, 0.3, 1);
    overscroll-behavior: contain;
  }
  .panel.dragging {
    transition: none;
  }
  .top {
    border-radius: var(--r-window) var(--r-window) 0 0;
    padding-top: 22px;
    touch-action: none;
    cursor: grab;
  }
  /* inside a text, photo or selection view the view's own header is the top of the sheet; the wordmark stays on home */
  .panel:not([data-view='home']) .top h1,
  .panel:not([data-view='home']) #helpBtn {
    display: none;
  }
  .panel:not([data-view='home']) .top {
    padding-bottom: 0;
    min-height: 22px;
  }
  /* the selection bar docks where the stats sit, so it never covers the card */
  .stage.barup .stats {
    visibility: hidden;
  }
  .top::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 50%;
    width: 36px;
    height: 4px;
    margin-left: -18px;
    border-radius: 2px;
    background: var(--line-strong);
  }
  .toast {
    position: fixed;
    z-index: 11;
    bottom: calc(var(--sheet-h, var(--sheet-rest)) + 12px);
  }
  dialog {
    margin: auto 0 0;
    width: 100%;
    max-width: none;
    max-height: 90dvh;
    border-radius: var(--r-window) var(--r-window) 0 0;
    box-shadow: 0 -10px 30px -12px var(--shade-3);
  }
  dialog[open]:not(.settled) {
    animation: sheetIn 0.34s cubic-bezier(0.2, 0.9, 0.3, 1);
  }
  dialog[open].closing {
    animation: sheetOut 0.2s cubic-bezier(0.4, 0, 1, 1) forwards;
  }
  @keyframes sheetIn {
    from {
      transform: translateY(100%);
    }
  }
  @keyframes sheetOut {
    to {
      transform: translateY(100%);
    }
  }
  .dlg > header {
    padding: 24px 12px 12px 20px;
    touch-action: none;
  }
  .dlg > header::before {
    content: '';
    position: absolute;
    top: 8px;
    left: 50%;
    width: 36px;
    height: 4px;
    margin-left: -18px;
    border-radius: 2px;
    background: var(--line-strong);
  }
  .dlg .db {
    padding: 0 20px calc(22px + env(safe-area-inset-bottom));
  }
}
/* touch screens: controls keep their size; invisible hit zones extend each one toward ~44px
   without overlapping its neighbors (toolbar zones grow vertically only, since its buttons touch) */
@media (pointer: coarse) {
  button,
  .sw {
    position: relative;
  }
  .toolbar button::before,
  .printopen::before,
  .sw::before,
  .ib::before,
  .back::before,
  #helpBtn::before,
  .toast button::before,
  .dlg .x::before {
    content: '';
    position: absolute;
  }
  .toolbar button::before {
    inset: -6px 0;
  }
  .toolbar .hb {
    padding: 8px 12px;
  }
  .printopen::before {
    inset: -5px;
  }
  .sw {
    width: 30px;
    height: 30px;
  }
  .swatches {
    gap: 7px;
  }
  .sw::before {
    inset: -7px -3px;
  }
  .selbar {
    gap: 8px;
    padding: 5px 6px;
  }
  .selbar .ib,
  .panel .ib {
    padding: 8px;
  }
  .ib::before {
    inset: -8px -4px;
  }
  .back::before {
    inset: -7px -10px;
  }
  #helpBtn::before {
    inset: -8px -4px;
  }
  .toast button::before {
    inset: -10px -6px;
  }
  .dlg .x::before {
    inset: -6px;
  }
  input[type='range'] {
    height: 28px;
  }
  input[type='text'],
  select {
    font-size: 16px;
  }
  /* below 16px, iOS zooms the page when a field is focused */
  --gap: 6px;
}
@media print {
  dialog {
    display: none !important;
  }
  @page {
    size: letter;
    margin: 0.4in;
  }
  html,
  body {
    height: auto;
    overflow: visible;
    background: #fff;
  }
  .app {
    display: none;
  }
  #print {
    display: block;
    font: 10pt/1.4 var(--ui);
    color: #000;
  }
  .pg {
    page-break-after: always;
    break-after: page;
  }
  .pg:last-child {
    page-break-after: auto;
    break-after: auto;
  }
  .pg h3 {
    font: 700 11pt var(--ui);
    margin: 0 0 2pt;
  }
  .pg p {
    margin: 0 0 10pt;
    color: #444;
  }
  .pg svg,
  .pg img {
    display: block;
  }
}
/* hover styles only where a pointer can actually hover; on touch screens they stick after a tap */
@media (hover: hover) {
  button.ghost:hover {
    color: var(--ink);
    background: var(--field);
    border-color: var(--line);
  }
  .layer:hover {
    background: var(--field);
  }
  .back:hover {
    color: var(--ink);
    background: var(--field);
  }
  .panel .ib:hover {
    background: var(--field);
  }
  .font:hover .rm {
    opacity: 1;
  }
  button:hover {
    border-color: var(--line-strong);
  }
  .sw:hover {
    border-color: var(--panel);
  }
  /* swatches keep their panel-colored gap so the color reads true; hover is the lift alone */
  button.primary:hover {
    background: var(--ink-deep);
  }
  .stage .printopen:hover {
    background: var(--field);
    border-color: var(--field);
  }
  .font:not(.on):hover {
    border-color: var(--line-strong);
  }
  .toast button:hover {
    background: var(--line);
  }
  .selbar .ib:hover,
  .selbar .tb:not(.on):not(.strong):hover {
    background: var(--chip);
  }
  .ib[data-act='del']:hover {
    color: var(--error);
  }
  .popt:hover {
    border-color: var(--line-strong);
  }
}
@media (hover: none) {
  .font .rm {
    opacity: 1;
  }
}
.dlg:focus {
  outline: none;
}
