/* ==========================================================================
   Unslop design system — components
   --------------------------------------------------------------------------
   One implementation per control. Surfaces add these classes next to their
   own JS-hook classes (e.g. class="tp-btn-action ds-btn ds-btn-primary");
   the hook class keeps behaviour, the ds- class owns the look.
   ========================================================================== */

/* No focus boxes, anywhere (Mustafa, 2026-10-16): a focused control draws no outline, ring
   or border of its own, and the browser's ring is off. A page that doesn't load this file
   carries the same rule in its own stylesheet (tests/no-focus-boxes.test.js). */
:focus, :focus-visible { outline: none !important; }

/* Every component box takes the system's corner shape (bevel). */
:is(.ds-btn, .ds-icon-btn, .ds-field, .ds-chip, .ds-seg, .ds-seg > button, .ds-kind, .ds-menu, .ds-menu-item,
    .ds-tooltip, .ds-toast, .ds-dialog, .ds-panel, .ds-kbd, .ds-well, .ds-switch, .ds-switch::after) {
  corner-shape: var(--corner-shape);
}

/* ── Labels ── */
.ds-micro {
  font: 600 var(--text-micro)/1.2 var(--font-ui);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg-subtle);
}
.ds-label {
  display: block;
  font: 500 var(--text-meta)/1.3 var(--font-ui);
  color: var(--fg-muted);
}

/* ── Buttons ── */
.ds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--control-h);
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-default);
  font: 500 var(--text-ui)/1 var(--font-ui);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out), transform var(--dur-instant) var(--ease-out);
}
.ds-btn:active:not(:disabled) { transform: translateY(0.5px); }
.ds-btn-primary { background: var(--primary-bg); color: var(--primary-fg); }
.ds-btn-primary:hover:not(:disabled) { background: var(--primary-hover); }
.ds-btn-accent { background: var(--accent); color: var(--on-accent); }
.ds-btn-accent:hover:not(:disabled) { background: var(--accent-hover); }
.ds-btn-secondary { background: var(--bg-surface); border-color: var(--border-default); }
.ds-btn-secondary:hover:not(:disabled) { background: var(--bg-hover); border-color: var(--border-strong); }
.ds-btn-ghost { color: var(--fg-muted); }
.ds-btn-ghost:hover:not(:disabled) { background: var(--bg-hover); color: var(--fg-default); }
.ds-btn-danger { background: var(--danger); color: var(--on-accent); }
.ds-btn-danger:hover:not(:disabled) { background: color-mix(in oklch, var(--danger) 88%, black); }
.ds-btn-danger-ghost { color: var(--danger); }
.ds-btn-danger-ghost:hover:not(:disabled) { background: var(--danger-subtle); }
.ds-btn:disabled, .ds-btn[aria-disabled="true"] {
  background: var(--bg-sunken);
  border-color: transparent;
  color: var(--fg-disabled);
  cursor: not-allowed;
}
.ds-btn-sm { height: var(--control-h-sm); padding: 0 10px; font-size: var(--text-meta); }
.ds-btn-block { width: 100%; }

.ds-icon-btn {
  display: inline-grid;
  place-items: center;
  width: var(--control-h);
  height: var(--control-h);
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--icon-default);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.ds-icon-btn:hover:not(:disabled) { background: var(--bg-hover); color: var(--fg-default); }
.ds-icon-btn[aria-pressed="true"] { background: var(--bg-active); color: var(--fg-default); }
.ds-icon-btn:disabled { color: var(--fg-disabled); cursor: not-allowed; }
.ds-icon-btn-sm { width: 26px; height: 26px; }
.ds-icon-btn-sm .ds-icon { width: 15px; height: 15px; }

/* ── Fields ── */
.ds-field {
  width: 100%;
  height: var(--control-h);
  padding: 0 10px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--fg-default);
  font: 400 var(--text-ui)/1.45 var(--font-ui);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
textarea.ds-field { height: auto; min-height: 64px; padding: 8px 10px; resize: vertical; }
.ds-field::placeholder { color: var(--fg-subtle); }
.ds-field:hover { border-color: var(--border-strong); }

/* ── Chips & segmented control ── */
.ds-chip {
  display: inline-flex;
  align-items: center;
  height: var(--control-h-sm);
  padding: 0 10px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--bg-surface);
  color: var(--fg-muted);
  font: 500 var(--text-meta)/1 var(--font-ui);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.ds-chip:hover { color: var(--fg-default); border-color: var(--border-strong); }
/* A chosen chip is pressed in, never filled: a solid fill means "do it" (the primary button) */
.ds-chip[aria-pressed="true"], .ds-chip.is-selected {
  background: var(--bg-active);
  border-color: var(--border-strong);
  color: var(--fg-default);
}

.ds-seg {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
}
.ds-seg > button {
  flex: 1;
  height: 26px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  font: 500 var(--text-meta)/1 var(--font-ui);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.ds-seg > button:hover { color: var(--fg-default); }
.ds-seg > button[aria-pressed="true"], .ds-seg > button[aria-selected="true"], .ds-seg > button.is-selected {
  background: var(--bg-surface);
  color: var(--fg-default);
  box-shadow: var(--shadow-raised);
}

/* ── Kinds: a new document's choices, drawn (DraftsSidebar.kindChooser) ──
   Picking one makes the document, so a kind has no selected state. Its drawing
   is graphite, and inks in under the pointer. */
.ds-kinds {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-xs);
}
.ds-kind {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  justify-items: center;
  align-items: center;
  row-gap: var(--space-xs);
  padding: var(--space-sm) var(--space-xs) var(--space-xs);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: transparent;
  color: var(--fg-default);
  font: 500 var(--text-ui)/1.2 var(--font-ui);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.ds-kind > svg:not(.pencil) {
  grid-column: 1 / -1;
  width: 100%;
  max-width: 104px;
  height: auto;
  color: var(--fg-subtle);
  transition: color var(--dur-fast) var(--ease-out);
}
.ds-kind > [data-pencil-label] { grid-column: 2; }
/* While it's made, the pencil's pilcrow writes itself before the name without moving it */
.ds-kind > .pencil-beside { grid-column: 1; grid-row: 2; justify-self: end; margin-right: var(--space-2xs); }
.ds-kind:hover:not(:disabled) { background: var(--bg-hover); border-color: var(--border-default); }
.ds-kind:hover:not(:disabled) > svg:not(.pencil) { color: var(--icon-default); }
.ds-kind:active:not(:disabled) { transform: translateY(0.5px); }
.ds-kind:disabled { cursor: progress; }

/* ── Switch ── */
.ds-switch {
  position: relative;
  flex: none;
  width: 30px;
  height: 18px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--border-default);
  cursor: pointer;
  transition: background-color var(--dur-base) var(--ease-out);
}
.ds-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: var(--radius-xs);
  background: var(--bg-surface);
  box-shadow: 0 1px 2px oklch(0 0 0 / 0.2);
  transition: transform var(--dur-base) var(--ease-out);
}
.ds-switch[aria-checked="true"] { background: var(--fg-default); }
.ds-switch[aria-checked="true"]::after { transform: translateX(12px); }

/* ── Keyboard hint ── */
.ds-kbd {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 5px;
  border: 1px solid var(--border-default);
  border-bottom-width: 2px;
  border-radius: var(--radius-xs);
  background: var(--bg-surface);
  color: var(--fg-muted);
  font: 500 10.5px/1 var(--font-ui);
}

/* ── Menu ── */
.ds-menu {
  min-width: 200px;
  padding: 4px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--bg-surface);
  box-shadow: var(--shadow-overlay);
}
.ds-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  height: 30px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--fg-default);
  font: 400 var(--text-ui)/1 var(--font-ui);
  text-align: left;
  cursor: pointer;
}
.ds-menu-item:hover, .ds-menu-item:focus-visible { background: var(--bg-hover); }
.ds-menu-item .ds-icon { color: var(--icon-default); }
.ds-menu-item[aria-checked="true"] { color: var(--fg-default); font-weight: 600; }
.ds-menu-sep { height: 1px; margin: 4px -4px; background: var(--border-subtle); border: 0; }

/* ── Tooltip ── */
.ds-tooltip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px;
  border-radius: var(--radius-xs);
  background: var(--bg-inverse);
  color: var(--fg-inverse);
  font: 500 var(--text-meta)/1.2 var(--font-ui);
  white-space: nowrap;
}

/* ── Toast ── */
.ds-toast {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: 380px;
  padding: 10px 12px 10px 12px;
  border-radius: var(--radius-lg);
  background: var(--bg-inverse);
  color: var(--fg-inverse);
  box-shadow: var(--shadow-overlay);
  font: 500 var(--text-ui)/1.4 var(--font-ui);
}
.ds-toast .ds-icon { margin-top: 1px; color: color-mix(in oklch, var(--fg-inverse) 72%, transparent); }
.ds-toast[data-tone="error"] .ds-icon { color: var(--danger); }
[data-theme="dark"] .ds-toast[data-tone="error"] .ds-icon { color: oklch(0.52 0.19 25); }
.ds-toast-message { flex: 1; min-width: 0; overflow-wrap: anywhere; }

/* ── Dialog ── */
.ds-scrim { background: var(--scrim); }
.ds-dialog {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
  color: var(--fg-default);
  box-shadow: var(--shadow-modal);
  font-family: var(--font-ui);
}
/* Errors and confirmations: a small, left-aligned dialog the pencil marks.
   An error's title is squiggled; the subject of a delete is struck through. */
.ds-alert {
  width: min(400px, calc(100vw - 32px));
  display: grid;
  gap: 10px;
  padding: 20px 20px 16px;
  text-align: left;
}
.ds-alert-title {
  position: relative;
  justify-self: start;
  margin: 0;
  padding-bottom: 7px;
  font: 600 var(--text-ui-lg)/1.3 var(--font-ui);
  color: var(--fg-default);
  overflow-wrap: anywhere;
}
.ds-alert-message { margin: 0; color: var(--fg-muted); font: 400 var(--text-ui)/1.55 var(--font-ui); overflow-wrap: anywhere; }
.ds-alert-subject {
  position: relative;
  justify-self: start;
  margin: 0;
  font: 400 calc(1.125rem * var(--write-scale, 1)) / 1.35 var(--font-text);
  color: var(--text-ink);
}
:is(.ds-alert-message, .ds-alert-subject)[hidden] { display: none; }
.ds-alert-error { color: var(--danger); }
.ds-alert-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 6px; }
.ds-well {
  padding: 10px 12px;
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  color: var(--fg-muted);
  font: 400 var(--text-ui)/1.55 var(--font-ui);
}

/* ── Status line: "Saved · 412 words · 2 min read" ── */
.ds-status {
  position: fixed;
  left: 20px;
  bottom: 16px;
  z-index: var(--z-status);
  height: 18px;
  overflow: hidden;
  color: var(--fg-subtle);
  font: 500 var(--text-meta)/18px var(--font-ui);
  letter-spacing: 0.01em;
  user-select: none;
}
/* Messages pass through the status line: the save state rolls up and the message takes its place. */
.ds-status-track { transition: transform var(--dur-slow) var(--ease-out); }
.ds-status.is-message .ds-status-track { transform: translateY(-18px); }
/* A long message can run past the margin into the text: a soft halo of paper keeps both readable. */
.ds-status {
  padding: 0 10px 0 8px;
  margin-left: -8px;
  border-radius: var(--radius-sm);
  transition: background-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.ds-status.is-message {
  background: color-mix(in oklch, var(--bg-canvas) 94%, transparent);
  box-shadow: 0 0 10px 8px color-mix(in oklch, var(--bg-canvas) 94%, transparent);
  user-select: text;
}
.ds-status-line { display: flex; align-items: center; gap: 8px; height: 18px; white-space: nowrap; }
.ds-status-message .ds-status-text { color: var(--fg-default); }
.ds-status-message[data-tone="error"] .ds-status-text { color: var(--danger); }
.ds-status-message .ds-status-dot { background: var(--fg-subtle); }
.ds-status-message[data-tone="success"] .ds-status-dot { background: var(--success); }
.ds-status-message[data-tone="warning"] .ds-status-dot { background: var(--warning); }
.ds-status-message[data-tone="error"] .ds-status-dot { background: var(--danger); }
.ds-status-action {
  padding: 0;
  border: 0;
  background: none;
  color: var(--fg-default);
  font: 600 var(--text-meta)/18px var(--font-ui);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--border-strong);
}
.ds-status-action:hover { text-decoration-color: currentColor; }
.ds-status .save-indicator {
  position: static;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: auto;
  height: auto;
  border-radius: 0;
  background: none;
  animation: none;
}
.ds-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  transition: background-color var(--dur-base) var(--ease-out);
}
.save-indicator:is(.unsaved, .saving) .ds-status-dot { background: var(--warning); }
.save-indicator.saving .ds-status-dot { animation: ds-pulse 1s var(--ease-in-out) infinite; }
.save-indicator.error .ds-status-dot { background: var(--danger); }
.save-indicator.error .ds-status-label { color: var(--danger); }
.ds-status-stats { display: inline-flex; align-items: center; gap: 8px; }
.ds-status-sep { width: 3px; height: 3px; border-radius: 50%; background: var(--border-strong); }
.ds-status :is(.ds-status-dot, .ds-status-sep) { flex: none; corner-shape: round; }
:is(.ds-status-stats, .ds-status-sep, #editor-read-time)[hidden] { display: none; }

@keyframes ds-pulse { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
  .save-indicator.saving .ds-status-dot { animation: none; }
}

/* ── Sidebar shell (Version history, Modify/Refactor, Content manager) ── */
.ds-sidebar {
  background: var(--bg-surface);
  border-right: 1px solid var(--border-subtle);
  box-shadow: var(--shadow-overlay);
  color: var(--fg-default);
  font-family: var(--font-ui);
}
.ds-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 56px;
  padding: 12px 12px 12px 20px;
  border-bottom: 1px solid var(--border-subtle);
}
.ds-sidebar-title {
  margin: 0;
  font: 600 var(--text-ui-lg)/1.25 var(--font-ui);
  color: var(--fg-default);
}
.ds-sidebar-tabs { padding: 12px 16px; border-bottom: 1px solid var(--border-subtle); }
.ds-sidebar-tabs .ds-seg { display: flex; width: 100%; }
.ds-sidebar-foot { padding: 12px 16px; border-top: 1px solid var(--border-subtle); }
.ds-sidebar-foot:empty { display: none; }
.ds-dialog-title { margin: 0; font: 600 var(--text-ui-lg)/1.3 var(--font-ui); color: var(--fg-default); }
.ds-field-writing { font-family: var(--font-text); font-size: 1rem; line-height: 1.5; }

/* ── List rows (drafts, posts, history): quiet rows, not boxed cards ── */
.ds-list-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 8px;
  margin: 0 -8px;
  padding: 10px 8px;
  border-radius: var(--radius-sm);
  corner-shape: var(--corner-shape);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.ds-list-row + .ds-list-row { box-shadow: 0 -1px 0 var(--border-subtle); }
.ds-list-row:hover { background: var(--bg-hover); }
.ds-list-row[aria-current="true"] { background: var(--bg-active); }
.ds-list-row:hover + .ds-list-row, .ds-list-row[aria-current="true"] + .ds-list-row { box-shadow: none; }
.ds-list-title {
  grid-column: 1;
  margin: 0;
  font: var(--write-heading-weight) calc(1.0625rem * var(--write-scale))/1.3 var(--font-text);
  color: var(--text-ink);
  overflow-wrap: anywhere;
}
/* A draft with no title yet: "Untitled" in the placeholder's grey */
.ds-list-title.is-untitled { color: var(--fg-subtle); }
.ds-list-title.is-renaming {
  padding: 0 4px;
  border-radius: var(--radius-xs);
  background: var(--bg-surface);
}
.ds-list-meta {
  grid-column: 1;
  display: flex;
  align-items: center;
  gap: 6px;
  font: 400 var(--text-meta)/1.3 var(--font-ui);
  color: var(--fg-subtle);
}
.ds-list-meta .ds-icon { width: 13px; height: 13px; }
.ds-list-actions {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: flex;
  align-items: flex-start;
  gap: 2px;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.ds-list-row:is(:hover, :focus-within, [aria-current="true"]) .ds-list-actions { opacity: 1; }
.ds-icon-btn-danger:hover:not(:disabled) { background: var(--danger-subtle); color: var(--danger); }
.ds-empty {
  margin: 32px 8px;
  font: 400 var(--text-ui)/1.5 var(--font-ui);
  color: var(--fg-subtle);
  text-align: center;
}
.ds-empty-error { color: var(--danger); }
@media (hover: none) { .ds-list-actions { opacity: 1; } }

/* ── Version history rows. The legacy JS still toggles bg-blue-100 (current)
      and bg-gray-200 (previewing); both map to the system's states here. ── */
.ds-history-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 9px 10px;
  border: 0;
  border-radius: var(--radius-sm);
  corner-shape: var(--corner-shape);
  background: transparent;
  color: var(--fg-default);
  font: 400 var(--text-ui)/1.3 var(--font-ui);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
}
.ds-history-row:hover { background: var(--bg-hover); }
.ds-history-row.bg-blue-100 { background: var(--bg-active); }
.ds-history-row.bg-gray-200 { background: var(--accent-subtle); color: var(--accent-fg); }
.ds-badge {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 6px;
  border-radius: var(--radius-xs);
  corner-shape: var(--corner-shape);
  background: var(--bg-sunken);
  color: var(--fg-muted);
  font: 600 var(--text-micro)/1 var(--font-ui);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}
/* The stats sit in the left margin; when the margin is narrower than they are
   (text column is 60vw), keep only the save state rather than overlap the text. */
@media (max-width: 1260px) { .ds-status-stats { display: none !important; } }

/* ── Pencil: strokes drawn by pencil.js ─────────────────────────────────
   Red for the system's marks; graphite for placeholder handwriting. */
.pencil { overflow: visible; pointer-events: none; flex: none; }
.pencil path {
  fill: none;
  stroke: var(--pencil-ink, var(--accent));
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
}
.pencil-under, .pencil-abs, .pencil-cover { position: absolute; }
.ds-btn-primary .pencil { --pencil-ink: var(--pencil-on-primary); }
.ds-btn-danger .pencil { --pencil-ink: currentColor; }
.pencil-graphite { --pencil-ink: var(--fg-subtle); }
.pencil-beside { width: 16px; height: 16px; }
.pencil-beside path { stroke-width: 1.9; }
.pencil-icon { width: 18px; height: 18px; }
.pencil-icon path { stroke-width: 1.7; }
.pencil-tone { width: 10px; height: 10px; }
.pencil-status { width: 46px; height: 14px; }
.pencil-status path { stroke-width: 1.2; }
.pencil-reading { position: absolute; left: 0; top: 0; }
.pencil-reading path { stroke-width: 1.4; }
.pencil-tone path { stroke: var(--tone, currentColor); stroke-width: 1.5; }

/* Markup: the red pen on a draft (UnslopPencil.markup and .note). Drawn on a layer
   beside the text, never inside it; nothing in it takes the pointer. */
.pencil-markup { position: absolute; top: 0; left: 0; z-index: 1; pointer-events: none; mix-blend-mode: var(--markup-blend); }
.pencil-markup path { stroke-width: 1.6; }
.pencil-note {
  position: absolute;
  z-index: 1;
  color: var(--pencil-ink, var(--accent));
  font: 400 var(--text-hand) / 1 var(--font-hand);
  text-wrap: balance;
  transform: rotate(var(--pencil-note-tilt, 0deg));
  transform-origin: left top;
  mix-blend-mode: var(--markup-blend);
  pointer-events: none;
}
/* Each word its own box, so the pen can write one word after another */
.pencil-note-word { display: inline-block; }
/* A narrow margin: the same hand, a size smaller. Notes never sit over the text. */
.pencil-note.is-small { font-size: calc(var(--text-hand) * 0.86); }

/* ── Stamp: an impression in riso ink, tilted and double-ruled (UnslopDS.stamp) ──
   Large, it covers a panel for something sent off; small, it sits on a row's lower
   right for a state reached. Its host is positioned. Nothing in it takes the pointer. */
.ds-stamp-defs { position: absolute; }
.ds-stamp { position: absolute; z-index: 5; pointer-events: none; mix-blend-mode: var(--doodle-blend); }
.ds-stamp-lg { inset: 0; display: grid; place-items: center; }
.ds-stamp-sm { right: var(--space-2xs); bottom: var(--space-2xs); }
.ds-stamp-rule {
  display: block;
  padding: var(--space-2xs);
  border: 2px solid var(--accent);
  border-radius: var(--radius-sm);
  corner-shape: var(--corner-shape);
  color: var(--accent);
  filter: url(#ds-stamp-ink);
  rotate: var(--ds-stamp-tilt, -6deg);
}
.ds-stamp-face {
  display: block;
  padding: var(--space-sm) var(--space-lg);
  border: 1px solid var(--accent);
  border-radius: var(--radius-xs);
  corner-shape: var(--corner-shape);
  font: 700 var(--text-display) / 1 var(--font-ui);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
}
.ds-stamp-sm .ds-stamp-rule { padding: var(--space-3xs); border-width: 1.5px; }
.ds-stamp-sm .ds-stamp-face { padding: 1px 5px 0; font-size: var(--text-micro); line-height: 1.45; letter-spacing: 0.14em; }

.pencil-skel { display: grid; width: 100%; }
/* Rows match a draft row's height (title + meta), so nothing jumps when the list arrives */
.pencil-skel-list .pencil-skel-row { display: grid; align-content: center; gap: 9px; min-height: 56px; padding: 8px 0; }
.pencil-words-row { display: grid; grid-template-columns: 88px minmax(0, 1fr); align-items: center; gap: 12px; padding: 7px 0; }
.pencil-words { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
/* Tiles match a grid of pictures: crossed boxes with a title and a status typed under each.
   A page sets --tile-min and --tile-h to its own grid's measure. */
.pencil-skel-tiles {
  grid-template-columns: repeat(auto-fill, minmax(var(--tile-min, 185px), 1fr));
  gap: var(--space-xl) var(--space-lg);
}
.pencil-tile { display: grid; gap: var(--space-xs); align-content: start; }
.pencil-tile-frame { position: relative; height: var(--tile-h, 192px); }
.pencil-tile .pencil-type-line { min-height: 12px; }
.pencil-tick path { stroke-width: 1.9; }
/* Passages match a heading over paragraphs of writing, so nothing jumps when the text arrives */
.pencil-skel-passages .pencil-skel-row + .pencil-skel-row { margin-top: var(--space-lg); }
.pencil-passage-head { min-height: var(--control-h); margin-bottom: var(--space-2xs); }
.pencil-passage { display: grid; padding: var(--space-sm) 0; }
.pencil-passage .pencil-type-line { min-height: calc(1.125rem * var(--write-scale, 1) * 1.65); }
.pencil-passage .pencil-block { height: 10px; }
.pencil-type-line { display: flex; align-items: center; gap: 5px; min-height: 12px; }
.pencil-block {
  display: inline-block;
  height: 9px;
  border-radius: var(--radius-xs);
  corner-shape: var(--corner-shape);
  background: var(--border-subtle);
  transition: background-color 90ms linear;
}
.pencil-meta .pencil-block, .pencil-cat-block { height: 7px; }
.pencil-word-block { height: 11px; }
.pencil-block.is-typed { background: var(--border-default); }
.pencil-caret {
  display: inline-block;
  width: 1.5px;
  height: 14px;
  margin-left: -2px;
  background: var(--accent);
  animation: pencil-blink 1.06s steps(1) infinite;
}
@keyframes pencil-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .pencil-caret { animation: none; } }

/* ── Doodles (doodles.js) ──
   The riso doodles as illustrations: ink line art over a riso colour layer printed
   off-register, overprinting the paper. `is-drawing` sketches the strokes in one by
   one and stamps the colour after them. */
.ds-doodle {
  overflow: visible;
  mix-blend-mode: var(--doodle-blend);
}
.ds-doodle path {
  fill: none;
  stroke: var(--doodle-ink);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}
.ds-doodle path.tinted { stroke: var(--c); stroke-width: 2.2; }
.ds-doodle .fill { translate: var(--ox) var(--oy); filter: url(#ds-doodle-grain); }
.ds-doodle .fill path { fill: var(--c); stroke: none; }
.ds-doodle.is-drawing .draw {
  stroke-dasharray: 1 1;
  animation: ds-doodle-sketch var(--dur, 280ms) var(--ease-out) var(--at, 0ms) both;
}
.ds-doodle.is-drawing .fill { animation: ds-doodle-stamp 560ms var(--ease-out) var(--fill-at, 0ms) both; }
@keyframes ds-doodle-sketch { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes ds-doodle-stamp { from { opacity: 0; translate: 0 0; } }
@media (prefers-reduced-motion: reduce) {
  .ds-doodle.is-drawing .draw,
  .ds-doodle.is-drawing .fill { animation: none; }
  .ds-doodle.is-drawing .draw { stroke-dasharray: none; }
}

/* ── Voice: a slip the pencil writes on (voice.js) ──
   In the status line's corner (Mustafa, 2026-10-16): while voice works, the save state and
   the counts roll up out of sight, as they do for a message, and the slip takes their
   place; when it's done they roll back. It stays in the margin, apart from the text, so it
   never seems to point at a place in it. No panel: the pencil's line and its words carry a
   halo of the page's own colour. On it, one pencil line (UnslopPencil.trace):
   - opening the microphone: only the nib, waiting (is-starting);
   - listening: the line is written as the paper runs past, flat in silence and in smooth
     waves as tall as the voice is loud;
   - from the second tap: the line goes still and flat, with a ripple running along it;
   - once the tool is picked, what is under way is written by hand at its left end
     ("rewriting"); as the tool's answer arrives, the pencil draws along the line as far
     as it has come;
   - then, held a moment before the slip goes: the line flicks into a tick when something
     was done, draws in to a dash in graphite when nothing was, or turns into the error's
     squiggle;
   - stopped with Escape, at any point: the pencil runs back along the line.
   Nothing in it takes the pointer. */
/* Its line and word start where the status line's words do (.ds-status: 20px in, its 18px
   line 16px up), and it keeps within the margin, which is a fifth of the window */
.ds-voice {
  position: fixed;
  left: calc(20px - var(--space-md));
  bottom: calc(16px + 9px - (var(--control-h) + var(--space-sm)) / 2);
  z-index: var(--z-status);
  width: min(calc(var(--space-3xl) * 3), calc(20vw - var(--space-md)));
  height: calc(var(--control-h) + var(--space-sm));
  pointer-events: none;
  opacity: 0;
  translate: 0 var(--space-xs);
  transition: opacity var(--dur-base) var(--ease-out), translate var(--dur-slow) var(--ease-out);
}
.ds-voice.is-on { opacity: 1; translate: 0 0; }
/* The status line rolls its words up out of sight while the slip has its place */
.ds-status.is-voice .ds-status-track { transform: translateY(-36px); }
.ds-voice .pencil { mix-blend-mode: var(--markup-blend); }

/* The line: red pencil, graphite when nothing came of it or while it waits to be drawn
   over, a little firmer once it has set; its oldest part fades into the page until a word
   is written at its start. */
.pencil-trace {
  position: absolute;
  overflow: visible;
  mask-image: linear-gradient(to right, transparent, black 30%);
  filter: drop-shadow(0 0 1px var(--bg-canvas)) drop-shadow(0 0 2.5px var(--bg-canvas));
}
.pencil-trace.is-labelled { mask-image: none; }
.pencil-trace .pencil-trace-ink,
.pencil-trace .pencil-trace-drawn {
  stroke-width: 1.8;
  stroke-dasharray: none;
  stroke-dashoffset: 0;
  transition: stroke var(--dur-slow) var(--ease-out), stroke-width var(--dur-slow) var(--ease-out);
}
.pencil-trace .pencil-trace-tick { stroke-width: 2; }
.pencil-trace.is-solid .pencil-trace-ink { stroke-width: 2; }
.pencil-trace:is(.is-graphite, .is-drawing) .pencil-trace-ink { stroke: var(--fg-subtle); }
.pencil-trace-nib { fill: var(--accent); transition: opacity var(--dur-instant) var(--ease-out); }
.ds-voice.is-starting .pencil-trace-nib { animation: ds-voice-poised 1.2s var(--ease-in-out) infinite; }
@keyframes ds-voice-poised {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.2; }
}
.pencil-trace:is(.is-held, .is-taken) .pencil-trace-nib { opacity: 0; }
.pencil-trace.is-drawing .pencil-trace-nib { opacity: 1; }

/* What is under way, in the pencil's hand at the line's start, written in from the left */
.pencil-trace-word {
  position: absolute;
  left: var(--space-md);
  bottom: calc(50% - 0.32em);
  color: var(--accent);
  font: 400 var(--text-hand) / 1 var(--font-hand);
  white-space: nowrap;
  text-shadow: 0 0 1px var(--bg-canvas), 0 0 3px var(--bg-canvas), 0 0 5px var(--bg-canvas);
  mix-blend-mode: var(--markup-blend);
  clip-path: inset(-0.4em 100% -0.4em -0.2em);
  transition: clip-path var(--dur-reflow) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.pencil-trace-word.is-written { clip-path: inset(-0.4em -0.2em -0.4em -0.2em); }
.pencil-trace.is-graphite ~ .pencil-trace-word { color: var(--fg-subtle); }
.pencil-trace.is-taken ~ .pencil-trace-word { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .ds-voice.is-starting .pencil-trace-nib { animation: none; }
}
