/* ───────────────────────── typefaces ─────────────────────────
   Atkinson Hyperlegible for the interface, its mono cut for anything numeric,
   Righteous for the wordmark. All vendored in vendor/fonts so the page looks
   the same on every machine and still works with the network switched off. */
@font-face {
  font-family: 'Atkinson';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url('../vendor/fonts/atkinson-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson';
  font-style: normal; font-weight: 700; font-display: swap;
  src: url('../vendor/fonts/atkinson-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson';
  font-style: italic; font-weight: 400; font-display: swap;
  src: url('../vendor/fonts/atkinson-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Mono';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url('../vendor/fonts/atkinson-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Mono';
  font-style: normal; font-weight: 700; font-display: swap;
  src: url('../vendor/fonts/atkinson-mono-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Righteous';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url('../vendor/fonts/righteous-400.woff2') format('woff2');
}

/* ───────────────────────── tokens ─────────────────────────
   Light is the warm paper of startipsum.org. Dark is the deep space of
   hamsterdome.com. Same bones, two moods. */
:root {
  --bg: #fff8ec;
  --bg-2: #fffdf8;
  --bg-3: #fdf0dc;
  --panel: #fffdf8;
  --line: #e7dcc6;
  --line-soft: #f2e8d6;
  --ink: #231f1a;
  --ink-2: #5e5850;
  --ink-3: #8a8176;

  --accent: #0e7c74;           /* teal, for active and interactive things */
  --accent-soft: #d9efec;
  --solid: #1f1f1c;            /* primary buttons are near-black pills */
  --solid-ink: #fffdf8;

  --danger: #b3305f;
  --warn: #9a5200;
  --warn-bg: #fff4c2;
  --warn-line: #efd98a;
  --ok: #4a7a1c;
  --violet: #6246c0;
  --page: #ffffff;             /* the paper a PDF page is drawn on */
  --stars: none;

  --radius: 12px;
  --radius-lg: 18px;
  --pill: 999px;
  --shadow: 0 6px 20px rgba(67, 50, 24, .10);
  --shadow-lg: 0 14px 40px rgba(67, 50, 24, .16);
  --glow: none;

  --sans: 'Atkinson', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'Atkinson Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --display: 'Righteous', 'Trebuchet MS', var(--sans);

  --text-xs: 12px;
  --text-sm: 14px;
  --text-ui: 15px;
  --text-base: 16px;
  --text-lg: 19px;
  --text-xl: 26px;
}

:root[data-theme="dark"] {
  --bg: #070318;
  --bg-2: #120826;
  --bg-3: #1d1142;
  --panel: #0e0624;
  --line: #352a7a;
  --line-soft: #241760;
  --ink: #ece6ff;
  --ink-2: #b3a6e0;
  --ink-3: #8b7dc4;

  --accent: #4af0f7;
  --accent-soft: #22124a;
  --solid: #7b4dff;
  --solid-ink: #ffffff;

  --danger: #ff6b81;
  --warn: #ffeaa0;
  --warn-bg: #2a2208;
  --warn-line: #6a5a12;
  --ok: #5dff6a;
  --violet: #c9a8ff;
  --page: #ffffff;

  --shadow: 0 6px 20px rgba(0, 0, 0, .45);
  --shadow-lg: 0 16px 44px rgba(0, 0, 0, .6);
  --glow: 0 0 14px rgba(108, 182, 255, .45);

  /* a quiet star field, tiled */
  --stars:
    radial-gradient(1.4px 1.4px at 18px 24px, rgba(201, 168, 255, .55), transparent 100%),
    radial-gradient(1.1px 1.1px at 92px 68px, rgba(74, 240, 247, .45), transparent 100%),
    radial-gradient(1px 1px at 151px 19px, rgba(255, 255, 255, .42), transparent 100%),
    radial-gradient(1.5px 1.5px at 47px 133px, rgba(255, 234, 160, .4), transparent 100%),
    radial-gradient(1px 1px at 191px 108px, rgba(255, 255, 255, .3), transparent 100%),
    radial-gradient(1.2px 1.2px at 124px 152px, rgba(108, 182, 255, .45), transparent 100%);
}

* { box-sizing: border-box; }
/* Author `display` rules outrank the user-agent's [hidden] rule, so panels with
   a display of their own would ignore the attribute entirely. Say it here. */
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow: hidden;
}
h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -.01em; }
hr { border: 0; border-top: 1px solid var(--line-soft); margin: 18px 0; }
.muted { color: var(--ink-3); }
svg { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ───────────────────────── topbar ───────────────────────── */
.topbar {
  height: 66px;
  display: flex; align-items: center; gap: 14px;
  padding: 0 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
  position: relative; z-index: 5;
}
/* back to the site this lives under */
.backlink {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: var(--text-sm); font-weight: 700; color: var(--ink-3);
  text-decoration: none; padding: 7px 12px 7px 9px; border-radius: var(--pill);
  border: 1.5px solid transparent;
  transition: color .13s, background .13s, border-color .13s;
}
.backlink .chev { width: 13px; height: 13px; opacity: .7; transition: transform .14s; }
.backlink:hover .chev { transform: translateX(-2px); }
/* gwark.dev's own mark, inlined so it takes the link's color in both themes */
.backlink .gwark-mark { width: 26px; height: 26px; }
.backlink:hover { color: var(--accent); background: var(--accent-soft); border-color: var(--accent); }
.backlink:focus-visible { outline: 2.5px solid var(--accent); outline-offset: 2px; }
:root[data-theme="dark"] .backlink:hover { text-shadow: 0 0 10px rgba(74, 240, 247, .5); }
.topbar-divide { width: 1.5px; height: 26px; background: var(--line); border-radius: 2px; flex: none; }

.brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
.brand-mark { width: 32px; height: 32px; flex: none; color: #fff; }
.brand-mark rect { fill: var(--solid); stroke: none; }
:root[data-theme="dark"] .brand-mark rect { fill: var(--solid); }
.brand h1 {
  font-family: var(--display); font-weight: 400; font-size: 22px;
  letter-spacing: .01em; line-height: 1.1;
}
:root[data-theme="dark"] .brand h1 { color: #6cb6ff; text-shadow: var(--glow); }

/* the stats read like a little hit counter */
.topbar-stats {
  margin-left: auto; display: flex; gap: 8px; align-items: center;
  font-family: var(--mono); font-size: var(--text-sm); font-variant-numeric: tabular-nums;
  color: var(--ink-2);
  background: var(--bg-3); border: 1px solid var(--line-soft);
  padding: 6px 14px; border-radius: var(--pill); white-space: nowrap;
}
:root[data-theme="dark"] .topbar-stats { color: var(--accent); border-color: var(--line); }
.topbar-stats .dot { color: var(--ink-3); }
/* The theme toggle sits outside the action group, so on a phone it can stay
   on the top row beside the logo while the actions wrap below. On a wide
   screen it simply leads the actions. */
#themeToggle { margin-left: auto; }
.topbar-stats:not([hidden]) + #themeToggle { margin-left: 0; }
.topbar-actions { display: flex; gap: 9px; align-items: center; }

/* ───────────────────────── buttons ───────────────────────── */
.btn {
  appearance: none; border: 1.5px solid var(--line);
  background: var(--bg-2); color: var(--ink);
  font-family: inherit; font-weight: 700; font-size: var(--text-ui);
  padding: 9px 16px; border-radius: var(--pill);
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  transition: background .13s, border-color .13s, transform .07s, color .13s, box-shadow .13s;
  white-space: nowrap; user-select: none; line-height: 1.25;
}
.btn:hover { border-color: var(--ink-3); background: var(--bg-3); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }
.btn .ico, .btn svg { width: 16px; height: 16px; flex: none; }

.btn.primary {
  background: var(--solid); border-color: var(--solid); color: var(--solid-ink);
}
.btn.primary:hover { filter: brightness(1.14); border-color: var(--solid); }
:root[data-theme="dark"] .btn.primary { box-shadow: 0 0 16px rgba(123, 77, 255, .5); }

.btn.secondary { background: var(--accent-soft); border-color: transparent; color: var(--accent); }
:root[data-theme="dark"] .btn.secondary { color: var(--accent); border-color: var(--line); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--ink-2); }
.btn.ghost:hover { background: var(--bg-3); color: var(--ink); border-color: transparent; }
.btn.warnish { color: var(--ink-2); border-color: var(--line); background: transparent; }
.btn.warnish:hover {
  color: var(--danger); border-color: var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
}
.btn.danger { color: var(--danger); }
.btn.danger:hover { background: color-mix(in srgb, var(--danger) 13%, transparent); border-color: var(--danger); }
.btn.block { width: 100%; }
.btn.tiny { padding: 6px 12px; font-size: var(--text-sm); }
.icon-btn { padding: 9px; border-color: transparent; background: transparent; }
.icon-btn:hover { background: var(--bg-3); border-color: transparent; }
.icon-btn svg { width: 18px; height: 18px; }
.i-sun { display: none; }
:root[data-theme="light"] .i-moon { display: none; }
:root[data-theme="light"] .i-sun { display: block; }
.linkish { color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; font-weight: 700; }

/* ───────────────────────── layout ───────────────────────── */
.layout { height: calc(100% - 64px); display: flex; overflow: hidden; }
.layout.has-doc .dropzone { display: none; }

/* dropzone */
.dropzone {
  flex: 1; display: grid; place-items: center; padding: 26px;
  background-image: var(--stars); background-size: 220px 170px;
}
.dz-inner {
  width: min(600px, 100%); text-align: center;
  border: 2px dashed var(--line); border-radius: var(--radius-lg);
  padding: 50px 32px; background: var(--panel);
  transition: border-color .15s, background .15s;
}
:root[data-theme="dark"] .dz-inner { background: rgba(14, 6, 36, .82); backdrop-filter: blur(2px); }
.dropzone.hot .dz-inner { border-color: var(--accent); background: var(--accent-soft); }
.dz-icon { width: 50px; height: 50px; color: var(--accent); stroke-width: 1.6; }
.dz-inner h2 {
  margin: 18px 0 6px; font-size: 29px;
  font-family: var(--display); font-weight: 400; letter-spacing: .01em;
}
:root[data-theme="dark"] .dz-inner h2 { color: #6cb6ff; text-shadow: var(--glow); }
.dz-inner p { color: var(--ink-2); margin: 0; }
.dz-badges { display: flex; flex-wrap: wrap; gap: 9px; justify-content: center; margin: 26px 0 0; }
.badge {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: var(--text-sm); font-weight: 700; color: var(--warn);
  background: var(--warn-bg); border: 1.5px solid var(--warn-line);
  padding: 6px 14px; border-radius: var(--pill);
}
.badge .ico { width: 14px; height: 14px; }
.dz-home { margin-top: 22px !important; font-size: var(--text-base); color: var(--ink-2); }
.dz-home a { color: var(--accent); font-weight: 700; text-underline-offset: 3px; }
.dz-stars { margin-top: 20px; font-size: 13px; letter-spacing: 7px; color: var(--ink-3); user-select: none; }
:root[data-theme="dark"] .dz-stars { color: var(--violet); }

/* workspace */
.workspace { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.ws-head {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 18px; border-bottom: 1px solid var(--line);
  background: var(--panel); flex: none;
}
.ws-head-left { display: flex; align-items: baseline; gap: 10px; }
.ws-head-left strong { font-size: var(--text-lg); font-weight: 700; letter-spacing: -.01em; }
.ws-head-left .muted { font-size: var(--text-sm); font-family: var(--mono); }
.ws-head-right { margin-left: auto; display: flex; align-items: center; gap: 7px; }
.zoom { display: flex; align-items: center; gap: 7px; color: var(--ink-3); padding-left: 8px; }
.zoom .ico { width: 15px; height: 15px; }
.zoom input { width: 96px; }
.pagegrid {
  flex: 1; overflow: auto; padding: 20px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--tile, 180px), 1fr));
  gap: 20px; align-content: start; align-items: start;
  background-image: var(--stars); background-size: 220px 170px;
}

/* page tile */
.tile { position: relative; border-radius: var(--radius); background: transparent; }
.tile .thumb {
  position: relative; border: 1.5px solid var(--line); border-radius: var(--radius);
  background: var(--page); overflow: hidden; cursor: grab;
  box-shadow: var(--shadow);
  display: grid; place-items: center; aspect-ratio: 1 / 1.3;
  transition: border-color .13s, box-shadow .13s, transform .13s;
  /* stamp previews are sized in cqw, so they track the thumbnail at any zoom */
  container-type: inline-size;
}
.tile .thumb canvas { max-width: 100%; max-height: 100%; display: block; }
.tile .thumb .skel {
  position: absolute; inset: 0;
  background: linear-gradient(100deg, var(--bg-3) 30%, var(--bg-2) 50%, var(--bg-3) 70%);
  background-size: 220% 100%; animation: shimmer 1.1s linear infinite;
}
@keyframes shimmer { to { background-position: -120% 0; } }
.tile:hover .thumb { border-color: var(--ink-3); transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.tile.sel .thumb { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft), 0 0 0 1.5px var(--accent); }
:root[data-theme="dark"] .tile.sel .thumb { box-shadow: 0 0 0 2px var(--accent), 0 0 18px rgba(74, 240, 247, .4); }
.tile.dragging { opacity: .35; }
.tile.drop-before::before, .tile.drop-after::after {
  content: ""; position: absolute; top: -5px; bottom: 26px; width: 3px;
  background: var(--accent); border-radius: var(--pill);
}
.tile.drop-before::before { left: -11px; }
.tile.drop-after::after { right: -11px; }

/* the magnifier that opens the full-size view */
.tile .expand {
  position: absolute; inset: 0; border: 0; background: transparent;
  display: grid; place-items: center; cursor: zoom-in;
  opacity: 0; transition: opacity .14s;
  pointer-events: none;            /* clicks pass through to select or drag … */
}
.tile .expand span {
  pointer-events: auto;            /* … except on the button itself */
  display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%;
  background: var(--solid); color: var(--solid-ink);
  box-shadow: var(--shadow-lg);
}
.tile .expand svg { width: 21px; height: 21px; }
.tile:hover .expand, .tile .expand:focus-visible { opacity: 1; }

.tile-bar { display: flex; align-items: center; gap: 6px; padding: 8px 2px 0; }
/* The page number reads as a label, not a footnote: full-strength ink on a
   small badge, lit in the accent when the page is selected. */
.tile-bar .num {
  font-family: var(--mono); font-size: var(--text-sm); font-weight: 700;
  color: var(--ink); font-variant-numeric: tabular-nums;
  min-width: 2.4em; padding: 2px 8px; text-align: center;
  background: var(--bg-3); border: 1px solid var(--line); border-radius: var(--pill);
}
.tile.sel .tile-bar .num { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.tile-bar .src { font-size: var(--text-xs); color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
/* The per-page buttons are always there, a little muted until the page is
   hovered or selected. They used to be invisible until then, which on a
   phone, with no hover, meant they were effectively hidden. */
.tile-bar .acts { display: flex; gap: 1px; margin-left: auto; opacity: .7; transition: opacity .12s; }
.tile:hover .tile-bar .acts, .tile.sel .tile-bar .acts, .tile:focus-within .tile-bar .acts { opacity: 1; }
.tile-bar .acts button {
  background: transparent; border: 0; color: var(--ink-2); cursor: pointer;
  padding: 5px; border-radius: var(--pill); display: grid; place-items: center;
}
.tile-bar .acts button:hover { background: var(--bg-3); color: var(--ink); }
.tile-bar .acts button.rm:hover { color: var(--danger); }
.tile-bar .acts svg { width: 17px; height: 17px; }
/* Touch screens: full strength, and big enough to tap. */
@media (hover: none) {
  .tile-bar .acts { opacity: 1; }
  .tile-bar .acts button { padding: 6px; }
}

/* stamp previews drawn over a page */
.stamps { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.stamps .st { position: absolute; transform-origin: center; white-space: nowrap; font-weight: 700; line-height: 1; }
.stamps .st img { display: block; width: 100%; height: auto; }
.stamps .st.note { white-space: pre; box-sizing: border-box; text-align: left; }
.stamps .st.comment, .place-item .comment-pin {
  aspect-ratio: 1; border-radius: 3px; color: #1d1d1f; display: grid; place-items: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
}
.stamps .st.comment svg, .place-item .comment-pin svg { width: 80%; height: 80%; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linejoin: round; }

/* ───────────────────────── dock ───────────────────────── */
.dock {
  width: 364px; flex: none; display: flex; flex-direction: column;
  background: var(--panel); border-left: 1px solid var(--line);
}
.dock-tabs {
  display: grid; grid-template-columns: repeat(4, minmax(auto, 1fr));
  border-bottom: 1px solid var(--line); flex: none;
  padding: 8px 8px 0; gap: 4px;
}
.dock-tab {
  appearance: none; background: transparent; border: 1.5px solid transparent;
  border-radius: var(--pill);
  color: var(--ink-2); font-family: inherit; font-size: var(--text-ui); font-weight: 700;
  padding: 8px 9px; cursor: pointer; margin-bottom: 8px;
}
.dock-tab:hover { color: var(--ink); background: var(--bg-3); }
.dock-tab.active {
  color: var(--solid-ink); background: var(--solid); border-color: var(--solid);
}
.dock-body { flex: 1; overflow: auto; padding: 18px; }
.panel { display: none; }
.panel.active { display: block; }

.lbl {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: var(--text-xs); font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-3); margin: 18px 0 8px;
}
.lbl output { font-family: var(--mono); font-weight: 700; text-transform: none; letter-spacing: 0; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.lbl .deg-field { display: inline-flex; align-items: center; gap: 2px; font-family: var(--mono); color: var(--ink-2); text-transform: none; letter-spacing: 0; }
.lbl .deg-field input { width: 7ch; padding: 3px 8px; font-family: var(--mono); font-weight: 700; font-size: var(--text-xs); text-align: right; font-variant-numeric: tabular-nums; }
.panel > .lbl:first-child { margin-top: 0; }
.hint { font-size: var(--text-ui); color: var(--ink-2); margin: 10px 0 15px; line-height: 1.6; }
.field-row { display: flex; gap: 9px; align-items: flex-end; margin-bottom: 9px; }
.field-row > * { flex: 1; min-width: 0; }
.check { display: flex; align-items: center; gap: 9px; font-size: var(--text-ui); color: var(--ink-2); margin: 12px 0; cursor: pointer; }
.check input { accent-color: var(--accent); width: 16px; height: 16px; }
.warn {
  display: flex; gap: 10px; font-size: var(--text-sm); line-height: 1.6;
  color: var(--warn); background: var(--warn-bg);
  border: 1.5px solid var(--warn-line);
  padding: 11px 13px; border-radius: var(--radius); margin: 13px 0;
}
.warn .ico { width: 16px; height: 16px; flex: none; margin-top: 2px; }

input[type="text"], input[type="number"], select, textarea {
  width: 100%; font-family: inherit; font-size: var(--text-ui); color: var(--ink);
  background: var(--bg-2); border: 1.5px solid var(--line);
  border-radius: var(--pill); padding: 9px 15px; line-height: 1.4;
}
textarea { border-radius: var(--radius); }
select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%), linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
  background-position: calc(100% - 17px) 18px, calc(100% - 12px) 18px;
  background-size: 5px 5px; background-repeat: no-repeat; padding-right: 32px;
}
input:focus-visible, select:focus-visible, textarea:focus-visible,
.btn:focus-visible, .dock-tab:focus-visible, .tile .thumb:focus-visible, .expand:focus-visible {
  outline: 2.5px solid var(--accent); outline-offset: 2px;
}
input[type="range"] { width: 100%; accent-color: var(--accent); height: 22px; }
input[type="color"] { width: 100%; height: 38px; padding: 3px; background: var(--bg-2); border: 1.5px solid var(--line); border-radius: var(--pill); cursor: pointer; }
textarea {
  min-height: 180px; resize: vertical;
  font-family: var(--mono); font-size: var(--text-sm); line-height: 1.65; margin: 11px 0;
}

/* segmented control */
.seg { display: flex; background: var(--bg-3); border: 1.5px solid var(--line); border-radius: var(--pill); padding: 3px; gap: 3px; margin-bottom: 4px; }
.seg button {
  flex: 1; appearance: none; background: transparent; border: 0; border-radius: var(--pill);
  color: var(--ink-2); font-family: inherit; font-size: var(--text-sm); font-weight: 700;
  padding: 7px 4px; cursor: pointer; white-space: nowrap;
}
.seg button:hover { color: var(--ink); }
.seg button.active { background: var(--panel); color: var(--ink); box-shadow: var(--shadow); }
:root[data-theme="dark"] .seg button.active { background: var(--accent-soft); color: var(--accent); }

/* 3x3 position picker */
.posgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; max-width: 144px; }
.posgrid button {
  aspect-ratio: 1; appearance: none; background: var(--bg-2);
  border: 1.5px solid var(--line); border-radius: 8px; cursor: pointer; position: relative;
}
.posgrid button::after { content: ""; position: absolute; inset: 34%; border-radius: 2px; background: var(--ink-3); }
.posgrid button:hover { border-color: var(--ink-3); }
.posgrid button.active { border-color: var(--accent); background: var(--accent-soft); }
.posgrid button.active::after { background: var(--accent); }

/* lists */
.filelist, .stamplist { display: flex; flex-direction: column; gap: 8px; }
.row {
  display: flex; align-items: center; gap: 11px;
  background: var(--bg-2); border: 1.5px solid var(--line-soft);
  padding: 10px 13px; border-radius: var(--radius); font-size: var(--text-sm);
}
.row .grow { flex: 1; min-width: 0; font-weight: 700; }
/* the name truncates, but the detail line underneath wraps rather than
   getting sliced off mid-word */
.row .grow > :first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .sub {
  color: var(--ink-3); font-size: var(--text-xs); font-weight: 400;
  font-family: var(--mono); white-space: normal; line-height: 1.5; margin-top: 2px;
}
.row button { appearance: none; background: transparent; border: 0; color: var(--ink-3); cursor: pointer; padding: 4px; border-radius: var(--pill); }
.row button:hover { color: var(--danger); background: var(--bg-3); }
.row svg { width: 15px; height: 15px; }
.swatch { width: 14px; height: 14px; border-radius: 50%; flex: none; border: 1.5px solid var(--line); }

.result {
  margin-top: 14px; padding: 15px; border-radius: var(--radius);
  background: var(--bg-3); border: 1.5px solid var(--line-soft); font-size: var(--text-sm);
}
.result .big { font-size: var(--text-xl); font-weight: 700; color: var(--ok); display: block; margin-bottom: 4px; letter-spacing: -.02em; }
.result .cmp { color: var(--ink-3); font-family: var(--mono); font-variant-numeric: tabular-nums; }
.result .field-row { margin: 13px 0 0; }

.wm-preview, .typepreview {
  margin-top: 11px; border: 1.5px solid var(--line); border-radius: var(--radius);
  background: var(--bg-2); display: grid; place-items: center; min-height: 78px; padding: 10px; overflow: hidden;
}
.wm-preview img { max-width: 100%; max-height: 110px; display: block; }
.typepreview { font-size: 32px; color: var(--ink); min-height: 86px; }

/* signature pad */
.padwrap { position: relative; border: 1.5px solid var(--line); border-radius: var(--radius); background: var(--page); overflow: hidden; }
.padwrap canvas { display: block; width: 100%; height: 124px; touch-action: none; cursor: crosshair; }
.padline { position: absolute; left: 14px; right: 14px; bottom: 30px; border-bottom: 1.5px dashed #c9bda4; pointer-events: none; }
.padhint { position: absolute; left: 16px; bottom: 9px; font-size: var(--text-xs); color: #a39781; pointer-events: none; }
.padwrap.inked .padhint, .padwrap.inked .padline { opacity: 0; }

/* extracted images */
.imggrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 9px; margin: 13px 0; }
.imgcell { border: 1.5px solid var(--line); border-radius: var(--radius); overflow: hidden; background: var(--bg-2); cursor: pointer; position: relative; }
.imgcell img { display: block; width: 100%; height: 74px; object-fit: contain; background: repeating-conic-gradient(#f3ead8 0% 25%, #e4d8bf 0% 50%) 50%/12px 12px; }
.imgcell span { display: block; font-family: var(--mono); font-size: 12px; color: var(--ink-3); padding: 4px 5px; text-align: center; }
.imgcell:hover { border-color: var(--accent); }

/* ───────────────────────── full-size viewer ───────────────────────── */
.viewer { position: fixed; inset: 0; z-index: 45; background: var(--bg); display: flex; flex-direction: column; }
.viewer-bar {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: 10px 16px; background: var(--panel); border-bottom: 1px solid var(--line);
}
.viewer-nav { display: flex; align-items: center; gap: 4px; }
.viewer-count {
  font-family: var(--mono); font-size: var(--text-ui); font-weight: 700; color: var(--ink-2);
  font-variant-numeric: tabular-nums; min-width: 12ch; text-align: center;
}
.viewer-title { font-size: var(--text-sm); color: var(--ink-3); margin-left: 8px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 30ch; }
.viewer-tools { margin-left: auto; display: flex; align-items: center; gap: 4px; }
.viewer-zoom { font-family: var(--mono); font-size: var(--text-sm); font-weight: 700; color: var(--ink-2); min-width: 6ch; text-align: center; }
.viewer-sep { width: 1.5px; height: 22px; background: var(--line); margin: 0 7px; border-radius: 2px; }
/* A phone cannot fit the bar on one line, and the close button used to be
   pushed off the right edge with no Esc key to fall back on. Two rows
   instead: page navigation and close on top, the tools centered below. */
@media (max-width: 720px) {
  .viewer-bar { flex-wrap: wrap; row-gap: 6px; padding: 8px 10px; }
  #viewClose { order: 2; margin-left: auto; }
  .viewer-tools { order: 3; flex-basis: 100%; margin-left: 0; justify-content: center; flex-wrap: wrap; gap: 0; }
  .viewer-tools .viewer-sep { margin: 0 3px; }
  .viewer-tools .viewer-zoom { min-width: 4.5ch; }
  .viewer-tools #viewFit { padding-inline: 8px; }
  .viewer-sep-close { display: none; }
}
.viewer-stage {
  flex: 1; overflow: auto; display: grid; place-content: safe center;
  padding: 28px; background: var(--bg-3);
  background-image: var(--stars); background-size: 220px 170px;
}
.viewer-sheet {
  position: relative; background: var(--page); box-shadow: var(--shadow-lg);
  border-radius: 4px; container-type: inline-size; flex: none;
}
.viewer-sheet canvas { display: block; width: 100%; height: 100%; border-radius: 4px; }
.viewer.busy .viewer-sheet { opacity: .55; }
.viewer-foot {
  flex: none; display: flex; align-items: center; gap: 16px;
  padding: 9px 16px; border-top: 1px solid var(--line); background: var(--panel);
  font-size: var(--text-sm); color: var(--ink-3);
}
.viewer-foot kbd {
  font-family: var(--mono); font-size: var(--text-xs); font-weight: 700; color: var(--ink-2);
  background: var(--bg-3); border: 1.5px solid var(--line); border-bottom-width: 3px;
  border-radius: 7px; padding: 1px 7px; margin: 0 1px;
}

/* ───────────────────────── modal and overlay ───────────────────────── */
.modal { position: fixed; inset: 0; z-index: 50; background: rgba(35, 31, 26, .55); display: grid; place-items: center; padding: 20px; backdrop-filter: blur(4px); }
:root[data-theme="dark"] .modal { background: rgba(7, 3, 24, .72); }
.modal-card {
  background: var(--panel); border: 1.5px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); width: min(880px, 100%); display: flex; flex-direction: column;
  /* dvh, not vh: on a phone vh counts the space behind the browser's toolbars,
     so a 92vh card ran off the bottom. Scrolls inside itself as a last resort. */
  max-height: min(92vh, calc(100dvh - 24px)); overflow: auto;
}
.modal-card header, .modal-card footer { display: flex; align-items: center; gap: 12px; padding: 14px 16px; }
.modal-card header { border-bottom: 1px solid var(--line); }
.modal-card header strong { font-size: var(--text-lg); }
.modal-card footer { border-top: 1px solid var(--line); }
.modal-card header .icon-btn { margin-left: auto; }
.modal-card footer .field-row { margin: 0; margin-left: auto; flex: none; }
.modal-card footer .field-row .btn { flex: none; }
/* Phones: the hint gets its own line above the buttons instead of being
   squeezed into a column beside them. */
@media (max-width: 560px) {
  .modal { padding: 12px; }
  .modal-card footer { flex-wrap: wrap; gap: 10px; }
  .modal-card footer > .muted { flex-basis: 100%; }
  .modal-card footer .field-row { margin-left: 0; width: 100%; }
  .modal-card footer .field-row .btn { flex: 1; }
}
.place-stage { position: relative; margin: 18px auto; background: var(--page); box-shadow: var(--shadow-lg); touch-action: none; }
.place-stage canvas { display: block; }
.place-item { position: absolute; border: 2px dashed var(--accent); border-radius: 4px; cursor: move; }
.place-item img { display: block; width: 100%; height: 100%; pointer-events: none; }
.place-item .note-card { white-space: pre; pointer-events: none; text-align: left; }
.place-item.is-comment .comment-pin { width: 100%; height: 100%; pointer-events: none; }
.place-item .grip {
  position: absolute; right: -7px; bottom: -7px; width: 15px; height: 15px;
  background: var(--accent); border: 2.5px solid var(--panel); border-radius: 50%; cursor: nwse-resize;
}

.overlay { position: fixed; inset: 0; z-index: 60; background: rgba(35, 31, 26, .5); display: grid; place-items: center; backdrop-filter: blur(4px); }
:root[data-theme="dark"] .overlay { background: rgba(7, 3, 24, .7); }
.busy-card { background: var(--panel); border: 1.5px solid var(--line); border-radius: var(--radius-lg); padding: 26px 30px; width: 310px; text-align: center; box-shadow: var(--shadow-lg); }
.busy-card p { margin: 14px 0 12px; font-size: var(--text-ui); font-weight: 700; color: var(--ink-2); }
.spinner { width: 28px; height: 28px; margin: 0 auto; border: 3px solid var(--line); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.bar { height: 6px; background: var(--bg-3); border-radius: var(--pill); overflow: hidden; }
.bar > div { height: 100%; width: 0; background: var(--accent); border-radius: var(--pill); transition: width .18s; }

.toasts { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: 70; display: flex; flex-direction: column; gap: 9px; align-items: center; pointer-events: none; }
.toast {
  background: var(--panel); color: var(--ink); border: 1.5px solid var(--line);
  padding: 12px 18px; border-radius: var(--pill);
  box-shadow: var(--shadow-lg); font-size: var(--text-ui); font-weight: 700; max-width: 460px;
  animation: pop .22s cubic-bezier(.2, .9, .3, 1.2);
}
/* Only err/ok carry a left stripe; a plain toast is a neutral pill. */
.toast.err { border-left: 5px solid var(--danger); }
.toast.ok { border-left: 5px solid var(--ok); }
@keyframes pop { from { opacity: 0; transform: translateY(10px) scale(.97); } }

/* ───────────────────────── responsive ───────────────────────── */
@media (max-width: 900px) {
  body { overflow: auto; }
  .layout { flex-direction: column; height: auto; }
  .dock { width: auto; border-left: 0; border-top: 1px solid var(--line); }
  .pagegrid { padding: 14px; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); }
  .topbar { height: auto; flex-wrap: wrap; padding: 10px 12px; gap: 10px; }
  /* Two deliberate rows: back link, logo and theme toggle; then the actions,
     with the stats under them. Left to wrap on its own, the toggle rode down
     with the actions and ended up on a lower row. */
  #themeToggle, .topbar-stats:not([hidden]) + #themeToggle { margin-left: auto; }
  .topbar-actions { order: 2; width: 100%; justify-content: flex-end; }
  .topbar-actions:not(:has(> :not([hidden]))) { display: none; }
  .topbar-stats { order: 3; margin-left: 0; }
  .backlink span { display: none; }
  .backlink { padding: 7px 9px; }
  .topbar-divide { display: none; }
  .viewer-foot, .viewer-title { display: none; }
  .viewer-stage { padding: 12px; }
}
/* phones: the bigger type needs the two toolbars to wrap, not run off the edge */
@media (max-width: 560px) {
  .topbar-actions { flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
  .topbar-actions .btn { padding: 8px 13px; }
  .ws-head { flex-wrap: wrap; gap: 8px 12px; }
  .ws-head-right { margin-left: 0; width: 100%; }
  .zoom { margin-left: auto; padding-left: 0; }
}
@media (max-width: 520px) { .dz-inner { padding: 34px 18px; } }
@media (prefers-reduced-motion: reduce) { * { animation-duration: .01ms !important; transition-duration: .01ms !important; } }
