/* Verso — the app, rebuilt in the browser.
   Every figure on this site is the interface redrawn in HTML and CSS: the same
   floating sidebar, the same paper on grey, the same tool pill along the
   bottom, the same inspector down the right. Pages carry placeholder rules
   rather than words — the shape of a document, never anyone's document.
   The whole mock scales from one unit, `--u`, so a window drawn at Mac size
   fits any column without a single magic number changing. */

.stage { container-type: inline-size; width: 100%; }

.app {
  --u: min(1px, calc(100cqi / 980));
  --card-r: calc(var(--u) * 12);
  --win-r: calc(var(--u) * 12);

  position: relative;
  width: 100%;
  border-radius: var(--win-r);
  overflow: hidden;
  background: var(--app-canvas);
  color: var(--app-ink);
  font-family: var(--font-sans);
  font-size: calc(var(--u) * 13);
  line-height: 1.35;
  letter-spacing: -0.005em;
  text-align: left;

  --app-canvas: #d9dbe0;
  --app-chrome: #edeef1;
  --app-card: #ffffff;
  --app-ink: #1d1d1f;
  --app-ink-2: #6b6b70;
  --app-ink-3: #8e8e93;
  --app-line: rgba(10, 20, 45, 0.1);
  --app-field: #e9eaee;
  --app-blue: #1d6ff0;
  --app-sel: rgba(29, 111, 240, 0.16);
  --app-paper: #ffffff;
  --paper-ink: #1d1d1f;
  --paper-ink-2: #62646c;
  --paper-field: #eceef4;
  --paper-line: rgba(10, 20, 45, 0.16);
  --app-rule: #c3c7d2;
  --app-rule-2: #d6d9e2;
  --app-glass: rgba(249, 250, 252, 0.86);
  --app-glass-rim: rgba(255, 255, 255, 0.9);
  --app-shadow: 0 calc(var(--u) * 1) calc(var(--u) * 3) rgba(10, 20, 45, 0.1),
    0 calc(var(--u) * 8) calc(var(--u) * 20) rgba(10, 20, 45, 0.07);

  box-shadow:
    0 0 0 calc(var(--u) * 1) rgba(10, 20, 45, 0.11),
    0 calc(var(--u) * 24) calc(var(--u) * 70) calc(var(--u) * -18) rgba(10, 20, 45, 0.36);
}

:root[data-theme="dark"] .app,
.app.dark {
  --app-canvas: #18191f;
  --app-chrome: #232530;
  --app-card: #24262f;
  --app-ink: #f2f2f5;
  --app-ink-2: #a3a3ac;
  --app-ink-3: #78787f;
  --app-line: rgba(255, 255, 255, 0.1);
  --app-field: #1a1b22;
  --app-blue: #4a90ff;
  --app-sel: rgba(74, 144, 255, 0.22);
  --app-paper: #eceef3;
  --app-rule: #b6bac6;
  --app-rule-2: #ccd0d9;
  --app-glass: rgba(30, 32, 42, 0.8);
  --app-glass-rim: rgba(255, 255, 255, 0.1);
  --app-shadow: inset 0 0 0 calc(var(--u) * 1) rgba(255, 255, 255, 0.08);
  box-shadow:
    0 0 0 calc(var(--u) * 1) rgba(255, 255, 255, 0.1),
    0 calc(var(--u) * 24) calc(var(--u) * 70) calc(var(--u) * -18) rgba(0, 0, 0, 0.72);
}

/* A figure that is a piece of the app rather than a whole window. The dark
   override above is more specific than a bare `.app.flat`, so the reset has to
   match its weight or the window ring comes back in dark mode. */
.app.flat,
:root[data-theme="dark"] .app.flat {
  background: transparent;
  box-shadow: none;
  border-radius: 0;
  overflow: visible;
}
.stage.card .app { --u: min(1.3px, calc(100cqi / 430)); }
.stage.wide .app { --u: min(1px, calc(100cqi / 1180)); }

/* --------------------------------------------------------- window chrome -- */

.app-bar {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 10);
  height: calc(var(--u) * 36);
  padding-inline: calc(var(--u) * 14);
  background: var(--app-chrome);
  border-bottom: calc(var(--u) * 1) solid var(--app-line);
}
.lights { display: flex; gap: calc(var(--u) * 8); flex: none; }
.lights i {
  width: calc(var(--u) * 11);
  height: calc(var(--u) * 11);
  border-radius: 50%;
  display: block;
}
.lights i:nth-child(1) { background: #ff5f57; }
.lights i:nth-child(2) { background: #febc2e; }
.lights i:nth-child(3) { background: #28c840; }

/* Document tabs across the top of the one window. */
.app-tabs { display: flex; gap: calc(var(--u) * 5); align-items: center; min-width: 0; }
.app-tab {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 6);
  max-width: calc(var(--u) * 150);
  padding: calc(var(--u) * 5) calc(var(--u) * 11);
  border-radius: calc(var(--u) * 7);
  font-size: calc(var(--u) * 11.5);
  color: var(--app-ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.app-tab i {
  width: calc(var(--u) * 8);
  height: calc(var(--u) * 10);
  border-radius: calc(var(--u) * 1.5);
  background: var(--app-paper);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line);
  flex: none;
}
.app-tab.on {
  background: var(--app-card);
  color: var(--app-ink);
  font-weight: 600;
  box-shadow: var(--app-shadow);
}

.app-body { display: flex; min-height: calc(var(--u) * 100); position: relative; }

/* ------------------------------------------------------- the left sidebar -- */

.vp-side {
  flex: none;
  width: calc(var(--u) * 186);
  margin: calc(var(--u) * 12);
  border-radius: calc(var(--u) * 12);
  background: var(--app-glass);
  box-shadow: inset 0 0 0 calc(var(--u) * 1) var(--app-glass-rim), var(--app-shadow);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.vp-side-tabs {
  display: flex;
  gap: calc(var(--u) * 3);
  padding: calc(var(--u) * 9) calc(var(--u) * 10) calc(var(--u) * 6);
}
.vp-stab {
  width: calc(var(--u) * 24);
  height: calc(var(--u) * 21);
  border-radius: calc(var(--u) * 6);
  display: grid;
  place-items: center;
  color: var(--app-ink-2);
}
.vp-stab svg { width: calc(var(--u) * 13); height: calc(var(--u) * 13); }
.vp-stab.on { background: var(--app-blue); color: #fff; }

.vp-thumbs {
  display: grid;
  gap: calc(var(--u) * 12);
  padding: calc(var(--u) * 6) calc(var(--u) * 14) calc(var(--u) * 16);
  justify-items: center;
  overflow: hidden;
}
.vp-thumb {
  width: calc(var(--u) * 92);
  aspect-ratio: 17 / 22;
  border-radius: calc(var(--u) * 3);
  background: var(--app-paper);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line), var(--app-shadow);
  padding: calc(var(--u) * 9) calc(var(--u) * 8);
  display: flex;
  flex-direction: column;
  gap: calc(var(--u) * 3.4);
  position: relative;
}
.vp-thumb.on { box-shadow: 0 0 0 calc(var(--u) * 2) var(--app-blue), var(--app-shadow); }
.vp-thumb::after {
  content: attr(data-n);
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--u) * -13);
  text-align: center;
  font-size: calc(var(--u) * 9);
  color: var(--app-ink-3);
}
.vp-thumb.on::after { color: var(--app-blue); font-weight: 650; }

/* Search pane, when the sidebar is showing it instead. */
.vp-search-field {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 6);
  margin: calc(var(--u) * 2) calc(var(--u) * 10) calc(var(--u) * 10);
  padding: calc(var(--u) * 5) calc(var(--u) * 8);
  border-radius: calc(var(--u) * 6);
  background: var(--app-field);
  font-size: calc(var(--u) * 10.5);
  color: var(--app-ink-3);
}
.vp-search-field svg { width: calc(var(--u) * 10); height: calc(var(--u) * 10); }
.vp-hit {
  margin: 0 calc(var(--u) * 10) calc(var(--u) * 6);
  padding: calc(var(--u) * 7) calc(var(--u) * 9);
  border-radius: calc(var(--u) * 6);
  background: var(--app-field);
  display: grid;
  gap: calc(var(--u) * 4);
}
.vp-hit .n { font-size: calc(var(--u) * 9); color: var(--app-ink-3); }

/* The outline pane. */
.vp-outline { padding: calc(var(--u) * 2) calc(var(--u) * 10) calc(var(--u) * 14); display: grid; gap: calc(var(--u) * 2); }
.vp-ol {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 7);
  padding: calc(var(--u) * 6) calc(var(--u) * 8);
  border-radius: calc(var(--u) * 6);
}
.vp-ol.d2 { padding-left: calc(var(--u) * 20); }
.vp-ol.d3 { padding-left: calc(var(--u) * 32); }
.vp-ol.on { background: var(--app-sel); }

/* ------------------------------------------------------------- the canvas -- */

.vp-canvas {
  flex: 1;
  min-width: 0;
  position: relative;
  padding: calc(var(--u) * 20) calc(var(--u) * 10);
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: calc(var(--u) * 14);
  overflow: hidden;
}
.vp-canvas.pad-0 { padding-block: 0; }

.vp-sheet {
  position: relative;
  flex: none;
  display: flex;
}
.vp-page {
  position: relative;
  width: calc(var(--u) * 300);
  aspect-ratio: 17 / 22;
  background: var(--app-paper);
  border-radius: calc(var(--u) * 2);
  box-shadow: 0 calc(var(--u) * 2) calc(var(--u) * 10) rgba(10, 20, 45, 0.18);
  padding: calc(var(--u) * 34) calc(var(--u) * 30);
  display: flex;
  flex-direction: column;
  gap: calc(var(--u) * 9);
  overflow: hidden;
  flex: none;
}
.vp-page.sm { width: calc(var(--u) * 210); padding: calc(var(--u) * 24) calc(var(--u) * 21); gap: calc(var(--u) * 7); }
.vp-page.lg { width: calc(var(--u) * 360); }

/* The placeholder grammar: rules where words would be. */
.ln {
  display: block;   /* an <i> is inline by default, and an inline box ignores
                       width and height — so a rule nested inside a mark wrapper
                       would render as nothing at all. */
  height: calc(var(--u) * 6);
  border-radius: 999px;
  background: var(--app-rule);
  width: 100%;
  flex: none;
}
.ln.soft { background: var(--app-rule-2); }

/* Width utilities. Not scoped to .ln, because a mark wrapper takes the width
   of the rule it marks — that is what keeps a highlight the length of its
   line rather than the length of the column. */
.w100 { width: 100%; } .w96 { width: 96%; } .w95 { width: 95%; }
.w94 { width: 94%; } .w92 { width: 92%; } .w90 { width: 90%; }
.w88 { width: 88%; } .w86 { width: 86%; } .w85 { width: 85%; }
.w84 { width: 84%; } .w82 { width: 82%; } .w80 { width: 80%; }
.w78 { width: 78%; } .w76 { width: 76%; } .w75 { width: 75%; }
.w74 { width: 74%; } .w72 { width: 72%; } .w70 { width: 70%; }
.w66 { width: 66%; } .w65 { width: 65%; } .w64 { width: 64%; }
.w62 { width: 62%; } .w60 { width: 60%; } .w58 { width: 58%; }
.w55 { width: 55%; } .w52 { width: 52%; } .w50 { width: 50%; }
.w45 { width: 45%; } .w40 { width: 40%; } .w35 { width: 35%; }
.w30 { width: 30%; } .w25 { width: 25%; }

.ln-title {
  height: calc(var(--u) * 11);
  border-radius: 999px;
  background: var(--rule-blue);
  width: 52%;
  flex: none;
  margin-bottom: calc(var(--u) * 5);
}
.ln-h {
  height: calc(var(--u) * 8);
  border-radius: 999px;
  background: var(--app-ink-3);
  opacity: 0.7;
  width: 38%;
  flex: none;
  margin-top: calc(var(--u) * 6);
}
.blk {
  display: block;   /* same trap as .ln: an <i> is inline, and an inline box
                       ignores height — so a block nested inside a mark wrapper
                       collapses to nothing at all. */
  height: calc(var(--u) * 62);
  border-radius: calc(var(--u) * 5);
  background: linear-gradient(140deg, #98bcf2, #c9dbf8);
  flex: none;
  margin: calc(var(--u) * 4) 0;
}
.para { display: flex; flex-direction: column; gap: calc(var(--u) * 9); }
.vp-gap { flex: 1; min-height: calc(var(--u) * 4); }

/* ------------------------------------------------------ the tool pill -- */

.vp-tools {
  position: absolute;
  left: 50%;
  bottom: calc(var(--u) * 14);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 2);
  padding: calc(var(--u) * 5) calc(var(--u) * 8);
  border-radius: 999px;
  background: var(--app-glass);
  -webkit-backdrop-filter: blur(calc(var(--u) * 14)) saturate(180%);
  backdrop-filter: blur(calc(var(--u) * 14)) saturate(180%);
  box-shadow: inset 0 0 0 calc(var(--u) * 1) var(--app-glass-rim),
    0 calc(var(--u) * 6) calc(var(--u) * 18) rgba(10, 20, 45, 0.2);
  z-index: 4;
}
.vp-tool {
  width: calc(var(--u) * 26);
  height: calc(var(--u) * 24);
  border-radius: calc(var(--u) * 7);
  display: grid;
  place-items: center;
  color: var(--app-ink-2);
  transition: background 0.3s var(--smooth), color 0.3s var(--smooth);
}
.vp-tool svg { width: calc(var(--u) * 14); height: calc(var(--u) * 14); }
.vp-tool.on { background: var(--app-blue); color: #fff; }
.vp-tool-sep {
  width: calc(var(--u) * 1);
  height: calc(var(--u) * 16);
  background: var(--app-line);
  margin-inline: calc(var(--u) * 5);
  flex: none;
}

/* ------------------------------------------------------- the inspector -- */

.vp-inspect {
  flex: none;
  width: calc(var(--u) * 176);
  margin: calc(var(--u) * 12);
  border-radius: calc(var(--u) * 12);
  background: var(--app-glass);
  box-shadow: inset 0 0 0 calc(var(--u) * 1) var(--app-glass-rim), var(--app-shadow);
  padding: calc(var(--u) * 12);
  display: flex;
  flex-direction: column;
  gap: calc(var(--u) * 9);
  overflow: hidden;
}
.vp-in-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: calc(var(--u) * 12);
  font-weight: 650;
  color: var(--app-ink);
}
.vp-in-head svg { width: calc(var(--u) * 12); height: calc(var(--u) * 12); color: var(--app-ink-3); }
.vp-in-label {
  font-size: calc(var(--u) * 9.5);
  font-weight: 600;
  color: var(--app-ink-3);
  letter-spacing: 0.01em;
}
.vp-layout {
  height: calc(var(--u) * 54);
  border-radius: calc(var(--u) * 7);
  background: #b9bcc4;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: calc(var(--u) * 6);
  padding: calc(var(--u) * 8);
}
.vp-layout i { background: #fff; border-radius: calc(var(--u) * 2); height: 100%; width: calc(var(--u) * 26); display: block; }
.vp-seg {
  display: flex;
  gap: calc(var(--u) * 2);
  padding: calc(var(--u) * 2);
  border-radius: 999px;
  background: var(--app-field);
}
.vp-seg i {
  flex: 1;
  height: calc(var(--u) * 17);
  border-radius: 999px;
  display: grid;
  place-items: center;
}
.vp-seg i.on { background: var(--app-blue); }
.vp-seg.vp-zoom i { font-size: calc(var(--u) * 10); color: var(--app-ink-2); }
.vp-seg.vp-zoom i.on-quiet { color: var(--app-blue); font-weight: 600; }
.vp-seg i svg { width: calc(var(--u) * 10); height: calc(var(--u) * 10); color: var(--app-ink-2); }
.vp-seg i.on svg { color: #fff; }
.vp-in-caption { font-size: calc(var(--u) * 10); color: var(--app-ink-2); text-align: center; }

.vp-switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: calc(var(--u) * 11);
  color: var(--app-ink);
}
.vp-switch {
  width: calc(var(--u) * 30);
  height: calc(var(--u) * 17);
  border-radius: 999px;
  background: var(--app-field);
  position: relative;
  transition: background 0.35s var(--smooth);
  flex: none;
}
.vp-switch::after {
  content: "";
  position: absolute;
  top: calc(var(--u) * 2);
  left: calc(var(--u) * 2);
  width: calc(var(--u) * 13);
  height: calc(var(--u) * 13);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 calc(var(--u) * 1) calc(var(--u) * 2) rgba(10, 20, 45, 0.28);
  transition: transform 0.35s var(--snappy);
}
.vp-switch.on { background: var(--app-blue); }
.vp-switch.on::after { transform: translateX(calc(var(--u) * 13)); }

.vp-actions { display: grid; gap: calc(var(--u) * 3); overflow: hidden; }
.vp-act {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 7);
  padding: calc(var(--u) * 5) calc(var(--u) * 8);
  border-radius: calc(var(--u) * 6);
  background: var(--app-field);
  font-size: calc(var(--u) * 10.5);
  color: var(--app-ink);
  white-space: nowrap;
}
.vp-act svg { width: calc(var(--u) * 11); height: calc(var(--u) * 11); color: var(--app-ink-2); flex: none; }
.vp-act .lock { margin-left: auto; width: calc(var(--u) * 9); height: calc(var(--u) * 9); color: var(--app-ink-3); }
.vp-act.on { background: var(--app-sel); color: var(--app-blue); font-weight: 600; }
.vp-act.on svg { color: var(--app-blue); }

/* ==========================================================================
   Animated figures. Every stage runs only while `.live` is on the `.app`,
   which site.js toggles as the figure enters and leaves the viewport.
   ========================================================================== */

.app .an { animation-play-state: paused; }
.app.live .an { animation-play-state: running; }

/* --- reading ruler ------------------------------------------------------ */

.vp-ruler {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  --band: 4.4%;
  --pos: 45%;
  background: linear-gradient(180deg,
      rgba(22, 30, 52, 0.55) 0,
      rgba(22, 30, 52, 0.55) calc(var(--pos) - var(--band) / 2),
      rgba(22, 30, 52, 0) calc(var(--pos) - var(--band) / 2),
      rgba(22, 30, 52, 0) calc(var(--pos) + var(--band) / 2),
      rgba(22, 30, 52, 0.55) calc(var(--pos) + var(--band) / 2),
      rgba(22, 30, 52, 0.55) 100%);
  animation: ruler-track 7s var(--smooth) infinite;
}
@keyframes ruler-track {
  0%, 6% { --pos: 26%; }
  28% { --pos: 38%; }
  52% { --pos: 50%; }
  76% { --pos: 62%; }
  94%, 100% { --pos: 26%; }
}
@property --pos { syntax: "<percentage>"; inherits: false; initial-value: 40%; }

/* --- read aloud: the word that is being spoken -------------------------- */

.vp-speak { position: relative; }
.vp-speak .ln { position: relative; overflow: hidden; }
.vp-speak .ln::after {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -3) auto calc(var(--u) * -3) 0;
  width: 22%;
  border-radius: calc(var(--u) * 3);
  background: rgba(29, 111, 240, 0.3);
  transform: translateX(-120%);
}
.vp-speak.an .ln:nth-child(1)::after { animation: speak 6s linear infinite; }
.vp-speak.an .ln:nth-child(2)::after { animation: speak 6s linear 1.5s infinite; }
.vp-speak.an .ln:nth-child(3)::after { animation: speak 6s linear 3s infinite; }
.vp-speak.an .ln:nth-child(4)::after { animation: speak 6s linear 4.5s infinite; }
@keyframes speak {
  0% { transform: translateX(-10%); opacity: 0; }
  2% { opacity: 1; }
  23% { transform: translateX(340%); opacity: 1; }
  25%, 100% { transform: translateX(340%); opacity: 0; }
}

/* The two palettes a page can float: the Read Aloud control (a speaker, the
   shape of the voice, the speed it is reading at) and the drawing brushes.
   One pill, two sets of contents. */
.vp-speak-bar,
.vp-brush-bar {
  position: absolute;
  left: 50%;
  bottom: calc(var(--u) * 16);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 11);
  padding: calc(var(--u) * 8) calc(var(--u) * 14);
  border-radius: 999px;
  background: var(--app-glass);
  -webkit-backdrop-filter: blur(calc(var(--u) * 14)) saturate(180%);
  backdrop-filter: blur(calc(var(--u) * 14)) saturate(180%);
  box-shadow: inset 0 0 0 calc(var(--u) * 1) var(--app-glass-rim),
    0 calc(var(--u) * 6) calc(var(--u) * 18) rgba(10, 20, 45, 0.24);
  z-index: 6;
}
.vp-speak-bar .sp {
  width: calc(var(--u) * 26);
  height: calc(var(--u) * 26);
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--app-blue);
  color: #fff;
  flex: none;
}
.vp-speak-bar .sp svg { width: calc(var(--u) * 14); height: calc(var(--u) * 14); }
.vp-speak-bar .glyph { color: var(--app-ink-2); display: grid; place-items: center; }
.vp-speak-bar .glyph svg { width: calc(var(--u) * 15); height: calc(var(--u) * 15); }
/* The voice, drawn as the bars a level meter would show. */
.vp-wave { display: flex; align-items: center; gap: calc(var(--u) * 3); }
.vp-wave i {
  width: calc(var(--u) * 3);
  border-radius: 999px;
  background: var(--app-blue);
  display: block;
}
.vp-speak-bar .rate {
  font-size: calc(var(--u) * 11);
  font-weight: 650;
  color: var(--app-ink);
  font-variant-numeric: tabular-nums;
}

/* A pen ring drawn round something on the page. It wraps what it marks, so it
   is always the right size and in the right place. */
.vp-ring { position: relative; flex: none; }
.vp-ring::after {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -9) calc(var(--u) * -11);
  border: calc(var(--u) * 3) solid var(--rule-blue);
  border-radius: calc(var(--u) * 10);
  pointer-events: none;
}

/* The drawing palette: the three brushes, the three weights they come in,
   the shapes, and the colour they are all set to. */
.vp-brush-bar { gap: calc(var(--u) * 9); }
.vp-brush-bar .br {
  width: calc(var(--u) * 26);
  height: calc(var(--u) * 26);
  border-radius: calc(var(--u) * 8);
  display: grid;
  place-items: center;
  color: var(--app-ink-2);
  flex: none;
}
.vp-brush-bar .br svg { width: calc(var(--u) * 15); height: calc(var(--u) * 15); }
.vp-brush-bar .br.on { background: var(--app-blue); color: #fff; }
.vp-brush-bar .sep {
  display: block;
  width: calc(var(--u) * 1.4);
  height: calc(var(--u) * 18);
  border-radius: 999px;
  background: var(--app-rule);
  flex: none;
}
/* Three weights, drawn as the three widths of stroke they lay down. */
.vp-wt { display: flex; flex-direction: column; justify-content: center;
  gap: calc(var(--u) * 4); flex: none; }
.vp-wt i {
  display: block;
  width: calc(var(--u) * 16);
  border-radius: 999px;
  background: var(--app-ink-2);
}
.vp-brush-bar .dot {
  display: block;
  width: calc(var(--u) * 15);
  height: calc(var(--u) * 15);
  border-radius: 50%;
  background: var(--rule-blue);
  box-shadow: 0 0 0 calc(var(--u) * 2) var(--app-paper),
    0 0 0 calc(var(--u) * 3.4) var(--app-rule);
  flex: none;
  margin-right: calc(var(--u) * 3);
}

/* --- markup: highlight sweeping across a line --------------------------- */

.hl { position: relative; flex: none; align-self: flex-start; }
.hl::before {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -4) auto calc(var(--u) * -4) 0;
  width: 100%;
  border-radius: calc(var(--u) * 3);
  background: var(--hl-color, rgba(255, 214, 51, 0.62));
  transform: scaleX(0);
  transform-origin: left center;
}
.hl.an::before { animation: hl-sweep 4.4s var(--smooth) infinite; }
.hl.d1::before { animation-delay: 0.35s; }
.hl.d2::before { animation-delay: 0.7s; }
@keyframes hl-sweep {
  0%, 3% { transform: scaleX(0); }
  22%, 92% { transform: scaleX(1); }
  99%, 100% { transform: scaleX(0); }
}
.hl-under::before {
  inset: auto auto calc(var(--u) * -4) 0;
  height: calc(var(--u) * 2.5);
  border-radius: 999px;
  background: var(--rule-red);
}
.hl-strike::before {
  inset: 50% auto auto 0;
  height: calc(var(--u) * 2.2);
  margin-top: calc(var(--u) * -1.1);
  border-radius: 999px;
  background: var(--rule-red);
  transform-origin: left center;
}
/* A struck line reads as withdrawn, so the rule under it fades back. */
.hl-strike .ln { opacity: 0.55; }

/* a sticky note that pops on */
.vp-note {
  position: absolute;
  width: calc(var(--u) * 86);
  padding: calc(var(--u) * 9);
  border-radius: calc(var(--u) * 6);
  background: #fff3c4;
  box-shadow: 0 calc(var(--u) * 4) calc(var(--u) * 12) rgba(10, 20, 45, 0.24);
  display: grid;
  gap: calc(var(--u) * 5);
  transform-origin: 10% 0;
  opacity: 0;
  z-index: 5;
}
.vp-note .ln { background: #c9a53d; height: calc(var(--u) * 4); }
.vp-note.an { animation: note-pop 4.4s var(--smooth) 0.9s infinite; }
@keyframes note-pop {
  0%, 12% { opacity: 0; transform: scale(0.6) rotate(-6deg); }
  22%, 76% { opacity: 1; transform: scale(1) rotate(-2deg); }
  90%, 100% { opacity: 0; transform: scale(0.85) rotate(-2deg); }
}

/* an ink stroke that draws itself */
.vp-ink {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 4;
}
.vp-ink path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
}
.vp-ink.an path { animation: draw-in 4.4s var(--smooth) infinite; }
@keyframes draw-in {
  0%, 6% { stroke-dashoffset: 1000; }
  40%, 76% { stroke-dashoffset: 0; }
  94%, 100% { stroke-dashoffset: 1000; }
}

/* --- redaction: the bar that takes the content out ---------------------- */

.rd { position: relative; flex: none; align-self: flex-start; }
.rd::before {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -3) auto calc(var(--u) * -3) 0;
  width: 100%;
  border-radius: calc(var(--u) * 1.5);
  background: #16181d;
  transform: scaleX(0);
  transform-origin: left center;
}
.rd.an::before { animation: rd-sweep 4.6s var(--snappy) infinite; }
.rd.d1::before { animation-delay: 0.5s; }
.rd.d2::before { animation-delay: 1s; }
@keyframes rd-sweep {
  0%, 6% { transform: scaleX(0); }
  26%, 92% { transform: scaleX(1); }
  99%, 100% { transform: scaleX(0); }
}
/* the rule underneath vanishes with it — the content is gone, not covered */
.rd.an .ln-inner { animation: rd-erase 4.6s var(--snappy) infinite; }
@keyframes rd-erase {
  0%, 22% { opacity: 1; }
  30%, 94% { opacity: 0; }
  100% { opacity: 1; }
}

/* --- reorder: a page lifting out and landing two rows up ---------------- */

.vp-rows { position: relative; width: 100%; }
.vp-row {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 10);
  padding: calc(var(--u) * 7);
  border-radius: calc(var(--u) * 8);
  background: transparent;
  position: relative;
}
.vp-row .pg {
  width: calc(var(--u) * 34);
  aspect-ratio: 17 / 22;
  border-radius: calc(var(--u) * 2.5);
  background: var(--app-paper);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line);
  display: grid;
  place-items: center;
  font-size: calc(var(--u) * 11);
  font-weight: 700;
  color: var(--app-ink-3);
  flex: none;
}
.vp-row .meta { display: grid; gap: calc(var(--u) * 6); flex: 1; }
.vp-row.lift {
  background: var(--app-card);
  box-shadow: 0 0 0 calc(var(--u) * 2) var(--app-blue),
    0 calc(var(--u) * 8) calc(var(--u) * 18) rgba(10, 20, 45, 0.3);
  z-index: 6;
}
.vp-rows.an .vp-row.lift { animation: row-lift 5s var(--smooth) infinite; }
.vp-rows.an .vp-row.shift { animation: row-shift 5s var(--smooth) infinite; }
@keyframes row-lift {
  0%, 8% { transform: translate(0, 0) scale(1); }
  20% { transform: translate(calc(var(--u) * 8), 0) scale(1.05); }
  46%, 74% { transform: translate(calc(var(--u) * 8), calc(var(--u) * -116)) scale(1.05); }
  90%, 100% { transform: translate(0, 0) scale(1); }
}
@keyframes row-shift {
  0%, 16% { transform: translateY(0); }
  46%, 74% { transform: translateY(calc(var(--u) * 58)); }
  90%, 100% { transform: translateY(0); }
}

/* --- merge: files sliding together into one ---------------------------- */

.vp-merge { position: relative; display: grid; place-items: center; width: 100%; }
.vp-merge .doc {
  position: absolute;
  width: calc(var(--u) * 104);
  aspect-ratio: 17 / 22;
  border-radius: calc(var(--u) * 4);
  background: var(--app-paper);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line),
    0 calc(var(--u) * 6) calc(var(--u) * 16) rgba(10, 20, 45, 0.2);
  padding: calc(var(--u) * 12) calc(var(--u) * 10);
  display: flex;
  flex-direction: column;
  gap: calc(var(--u) * 5);
}
.vp-merge .doc i {
  height: calc(var(--u) * 4);
  border-radius: 999px;
  background: var(--app-rule);
  display: block;
}
.vp-merge .doc::before {
  content: "";
  height: calc(var(--u) * 6);
  border-radius: 999px;
  width: 60%;
  background: var(--tint, var(--rule-blue));
  margin-bottom: calc(var(--u) * 3);
}
/* The resting position is the one that reads: three separate documents. The
   animation gathers them and lets them go again. */
.vp-merge .doc { transform: translateX(var(--dx)) rotate(var(--rot)); }
.vp-merge.an .doc { animation: merge-in 5s var(--smooth) infinite; }
.vp-merge .doc:nth-child(1) { --tint: var(--rule-amber); --dx: -105%; --rot: -8deg; }
.vp-merge .doc:nth-child(2) { --tint: var(--rule-blue); --dx: 0%; --rot: 0deg; z-index: 2; }
.vp-merge .doc:nth-child(3) { --tint: var(--rule-red); --dx: 105%; --rot: 8deg; }
@keyframes merge-in {
  0%, 12% { transform: translateX(var(--dx)) rotate(var(--rot)); }
  46%, 78% { transform: translateX(calc(var(--dx) * 0.16)) rotate(calc(var(--rot) * 0.18)); }
  94%, 100% { transform: translateX(var(--dx)) rotate(var(--rot)); }
}

/* --- split: one document parting into pieces --------------------------- */

.vp-split { position: relative; display: grid; place-items: center; width: 100%; }
.vp-split .doc {
  position: absolute;
  width: calc(var(--u) * 104);
  aspect-ratio: 17 / 22;
  border-radius: calc(var(--u) * 4);
  background: var(--app-paper);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line),
    0 calc(var(--u) * 6) calc(var(--u) * 16) rgba(10, 20, 45, 0.2);
  padding: calc(var(--u) * 14) calc(var(--u) * 12);
  display: flex;
  flex-direction: column;
  gap: calc(var(--u) * 6);
}
.vp-split .doc i {
  height: calc(var(--u) * 4.5);
  border-radius: 999px;
  background: var(--app-rule);
  display: block;
}
.vp-split .doc::before {
  content: "";
  height: calc(var(--u) * 7);
  border-radius: 999px;
  width: 58%;
  background: var(--rule-blue);
  margin-bottom: calc(var(--u) * 4);
}
.vp-split .doc { transform: translateX(var(--dx)) rotate(var(--rot)); }
.vp-split.an .doc { animation: split-out 5s var(--smooth) infinite; }
.vp-split .doc:nth-child(1) { --dx: -100%; --rot: -7deg; }
.vp-split .doc:nth-child(2) { --dx: 0%; --rot: 0deg; z-index: 2; }
.vp-split .doc:nth-child(3) { --dx: 100%; --rot: 7deg; }
@keyframes split-out {
  0%, 14% { transform: translateX(0) rotate(0); }
  48%, 80% { transform: translateX(var(--dx)) rotate(var(--rot)); }
  96%, 100% { transform: translateX(0) rotate(0); }
}

/* --- editing text in place --------------------------------------------- */

/* The row being edited has to read as *a row being edited*, so it carries the
   same tinted field the app puts behind live text, plus the caret and the
   newly typed run in the accent colour. */
.vp-edit {
  position: relative;
  height: calc(var(--u) * 6);
  flex: none;
}
.vp-edit::before {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -7) calc(var(--u) * -8);
  border-radius: calc(var(--u) * 5);
  background: var(--app-sel);
  box-shadow: inset 0 0 0 calc(var(--u) * 1) var(--app-blue);
  opacity: 0;
}
.vp-edit.an::before { animation: edit-field 5s var(--smooth) infinite; }
@keyframes edit-field {
  0%, 4% { opacity: 0; }
  14%, 88% { opacity: 1; }
  98%, 100% { opacity: 0; }
}
.vp-edit .ln { position: relative; }
.vp-edit .caret {
  position: absolute;
  top: calc(var(--u) * -4);
  width: calc(var(--u) * 1.8);
  height: calc(var(--u) * 14);
  background: var(--app-blue);
  border-radius: 999px;
}
.vp-edit.an .caret { animation: caret-run 5s var(--smooth) infinite, caret-blink 1s steps(1) infinite; }
@keyframes caret-run {
  0%, 14% { left: 30%; }
  40%, 88% { left: 62%; }
  98%, 100% { left: 30%; }
}
@keyframes caret-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0.15; } }
.vp-edit .fresh {
  position: absolute;
  left: 30%;
  top: 0;
  height: calc(var(--u) * 6);
  border-radius: 999px;
  background: var(--app-blue);
  width: 0;
}
.vp-edit.an .fresh { animation: type-in 5s var(--smooth) infinite; }
@keyframes type-in {
  0%, 14% { width: 0; }
  40%, 88% { width: 32%; }
  98%, 100% { width: 0; }
}

/* --- OCR: a scan bar crossing a flat page, leaving readable text -------- */

.vp-ocr { position: relative; overflow: hidden; }
.vp-ocr .scan {
  position: absolute;
  left: 0;
  right: 0;
  height: calc(var(--u) * 26);
  background: linear-gradient(180deg, rgba(29, 111, 240, 0) 0%,
      rgba(29, 111, 240, 0.28) 45%, rgba(29, 111, 240, 0.5) 50%,
      rgba(29, 111, 240, 0.28) 55%, rgba(29, 111, 240, 0) 100%);
  z-index: 3;
  top: -12%;
}
.vp-ocr.an .scan { animation: scan-down 5s var(--smooth) infinite; }
@keyframes scan-down {
  0%, 8% { top: -12%; opacity: 0; }
  14% { opacity: 1; }
  62% { top: 100%; opacity: 1; }
  70%, 100% { top: 100%; opacity: 0; }
}
.vp-ocr .ln { transition: none; }
.vp-ocr.an .ln.found { animation: ocr-wake 5s var(--smooth) infinite; }
@keyframes ocr-wake {
  0%, 18% { background: var(--app-rule-2); }
  30%, 84% { background: var(--rule-blue); }
  96%, 100% { background: var(--app-rule-2); }
}

/* --- signing: a signature writing itself, a stamp landing --------------- */

.vp-sign-path {
  fill: none;
  stroke: #1b3f8f;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 320;
  stroke-dashoffset: 320;
}
.an .vp-sign-path { animation: sign-write 5s var(--smooth) infinite; }
@keyframes sign-write {
  0%, 8% { stroke-dashoffset: 320; }
  46%, 82% { stroke-dashoffset: 0; }
  96%, 100% { stroke-dashoffset: 320; }
}
.vp-stamp {
  position: absolute;
  padding: calc(var(--u) * 5) calc(var(--u) * 10);
  border-radius: calc(var(--u) * 4);
  border: calc(var(--u) * 2) solid #17803d;
  color: #17803d;
  font-size: calc(var(--u) * 11);
  font-weight: 800;
  letter-spacing: 0.012em;
  opacity: 0;
  transform: rotate(-9deg) scale(1.9);
}
.an .vp-stamp { animation: stamp-land 5s var(--spring) infinite; }
@keyframes stamp-land {
  0%, 44% { opacity: 0; transform: rotate(-9deg) scale(1.9); }
  56%, 86% { opacity: 1; transform: rotate(-9deg) scale(1); }
  96%, 100% { opacity: 0; transform: rotate(-9deg) scale(1.2); }
}

/* --- forms: a field filling, a box ticking, a menu opening -------------- */

.vp-field {
  display: grid;
  gap: calc(var(--u) * 5);
}
.vp-field .lb { font-size: calc(var(--u) * 10); font-weight: 600; color: var(--paper-ink-2); }
.vp-field .bx {
  height: calc(var(--u) * 24);
  border-radius: calc(var(--u) * 6);
  background: var(--paper-field);
  box-shadow: inset 0 0 0 calc(var(--u) * 1) var(--paper-line);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 2);
  padding-inline: calc(var(--u) * 9);
  position: relative;
  overflow: hidden;
}
.vp-field .typed {
  height: calc(var(--u) * 6);
  border-radius: 999px;
  background: var(--paper-ink-2);
  width: 0;
}
.vp-field.an .typed { animation: type-field 5s steps(14) infinite; }
@keyframes type-field {
  0%, 8% { width: 0; }
  40%, 82% { width: 58%; }
  96%, 100% { width: 0; }
}
.vp-field .cur { width: calc(var(--u) * 1.6); height: calc(var(--u) * 12); background: var(--app-blue); border-radius: 999px; }
.vp-field.an .cur { animation: caret-blink 1s steps(1) infinite; }

.vp-check {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 8);
  font-size: calc(var(--u) * 11);
  color: var(--paper-ink-2);
}
.vp-check .box {
  width: calc(var(--u) * 17);
  height: calc(var(--u) * 17);
  border-radius: calc(var(--u) * 4);
  box-shadow: inset 0 0 0 calc(var(--u) * 1.5) var(--paper-ink-2);
  display: grid;
  place-items: center;
  flex: none;
  position: relative;
}
.vp-check .box svg { width: calc(var(--u) * 11); height: calc(var(--u) * 11); color: #fff; opacity: 0; }
.vp-check .box::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: calc(var(--u) * 4);
  background: var(--app-blue);
  transform: scale(0);
}
.vp-check.an .box::before { animation: tick-fill 5s var(--spring) infinite; }
.vp-check.an .box svg { animation: tick-mark 5s var(--smooth) infinite; }
@keyframes tick-fill { 0%, 44% { transform: scale(0); } 56%, 86% { transform: scale(1); } 96%, 100% { transform: scale(0); } }
@keyframes tick-mark { 0%, 48% { opacity: 0; } 58%, 86% { opacity: 1; } 96%, 100% { opacity: 0; } }

/* --- compare: two versions, the difference lighting up ----------------- */

.vp-compare { display: flex; gap: calc(var(--u) * 16); justify-content: center; width: 100%; }
.vp-diff-add { position: relative; flex: none; align-self: flex-start; }
.vp-diff-add::after {
  content: "";
  position: absolute;
  inset: calc(var(--u) * -4) calc(var(--u) * -6);
  border-radius: calc(var(--u) * 4);
  background: rgba(23, 128, 61, 0.2);
  box-shadow: inset 0 0 0 calc(var(--u) * 1.5) rgba(23, 128, 61, 0.5);
  opacity: 0;
}
.vp-diff-del::after { background: rgba(209, 74, 74, 0.2); box-shadow: inset 0 0 0 calc(var(--u) * 1.5) rgba(209, 74, 74, 0.55); }
.an .vp-diff-add::after { animation: diff-glow 4.6s var(--smooth) infinite; }
.an .vp-diff-add.d1::after { animation-delay: 0.45s; }
@keyframes diff-glow { 0%, 14% { opacity: 0; } 30%, 82% { opacity: 1; } 96%, 100% { opacity: 0; } }

/* --- export: the document leaving as other formats --------------------- */

.vp-export { position: relative; display: grid; place-items: center; width: 100%; }
.fmt {
  position: absolute;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 7);
  padding: calc(var(--u) * 8) calc(var(--u) * 13);
  border-radius: calc(var(--u) * 9);
  background: var(--app-card);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line), var(--app-shadow);
  font-size: calc(var(--u) * 11.5);
  font-weight: 620;
  color: var(--app-ink);
  white-space: nowrap;
}
.fmt > span { font-size: calc(var(--u) * 11.5); }
.fmt b {
  width: calc(var(--u) * 22);
  height: calc(var(--u) * 22);
  border-radius: calc(var(--u) * 5);
  display: grid;
  place-items: center;
  color: #fff;
  font-size: calc(var(--u) * 9);
  font-weight: 800;
  background: var(--fc, #1d6ff0);
  flex: none;
}
.vp-export.an .fmt { animation: fmt-fly 5.6s var(--spring) both infinite; }
/* Each tile arrives once and then holds, so the figure reads at any moment. */
@keyframes fmt-fly {
  0%, 4% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
  24%, 100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* --- protection: the lock closing ------------------------------------- */

.vp-lock { position: relative; display: grid; place-items: center; }
.vp-lock svg { width: calc(var(--u) * 104); height: auto; }
.vp-lock .shackle {
  fill: none;
  stroke: currentColor;
  stroke-width: 3.4;
  stroke-linecap: round;
}
/* The shackle lifts and drops; the units are the SVG's own, so nothing clips. */
.an .vp-lock svg { width: calc(var(--u) * 104); height: auto; }
.vp-lock .shackle { animation: shackle-close 4.4s var(--snappy) infinite; }
@keyframes shackle-close {
  0%, 12% { transform: translateY(-11px); }
  42%, 84% { transform: translateY(0); }
  96%, 100% { transform: translateY(-11px); }
}

/* --- sanitize: the document's own details, cleared --------------------- */

.vp-meta { display: grid; gap: calc(var(--u) * 9); width: 100%; }
.vp-meta-row {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 12);
  padding: calc(var(--u) * 8) calc(var(--u) * 12);
  border-radius: calc(var(--u) * 8);
  background: var(--app-card);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line);
  font-size: calc(var(--u) * 11);
  color: var(--app-ink-2);
}
.vp-meta-row .k { width: calc(var(--u) * 62); flex: none; font-weight: 600; }
.vp-meta-row .v { flex: 1; min-width: 0; }
.vp-meta-row .x {
  width: calc(var(--u) * 12);
  height: calc(var(--u) * 12);
  color: var(--app-ink-3);
  flex: none;
  opacity: 0;
}
.vp-meta.an .vp-meta-row .v { animation: meta-clear 5s var(--smooth) var(--d, 0s) infinite; }
.vp-meta.an .vp-meta-row .x { animation: meta-x 5s var(--smooth) var(--d, 0s) infinite; }
@keyframes meta-clear {
  0%, 16% { opacity: 1; transform: none; }
  34%, 86% { opacity: 0; transform: translateX(calc(var(--u) * 10)); }
  97%, 100% { opacity: 1; transform: none; }
}
@keyframes meta-x {
  0%, 18% { opacity: 0; }
  36%, 86% { opacity: 1; }
  97%, 100% { opacity: 0; }
}

/* --- batch: a folder of documents running through a recipe ------------- */

.vp-batch { display: grid; gap: calc(var(--u) * 8); width: 100%; }
.vp-batch-row {
  display: flex;
  align-items: center;
  gap: calc(var(--u) * 10);
  padding: calc(var(--u) * 8) calc(var(--u) * 11);
  border-radius: calc(var(--u) * 8);
  background: var(--app-card);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line);
  font-size: calc(var(--u) * 11);
}
.vp-batch-row .pg {
  width: calc(var(--u) * 20);
  height: calc(var(--u) * 25);
  border-radius: calc(var(--u) * 2.5);
  background: var(--app-paper);
  box-shadow: 0 0 0 calc(var(--u) * 1) var(--app-line);
  flex: none;
}
.vp-batch-row .bar {
  flex: 1;
  height: calc(var(--u) * 7);
  border-radius: 999px;
  background: var(--app-field);
  overflow: hidden;
  position: relative;
}
.vp-batch-row .bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  border-radius: 999px;
  background: var(--app-blue);
  display: block;
}
.vp-batch.an .bar i { animation: batch-run 5s var(--smooth) infinite; }
.vp-batch.an .vp-batch-row:nth-child(2) .bar i { animation-delay: 0.5s; }
.vp-batch.an .vp-batch-row:nth-child(3) .bar i { animation-delay: 1s; }
@keyframes batch-run {
  0%, 6% { width: 0; }
  56%, 86% { width: 100%; }
  96%, 100% { width: 0; }
}
.vp-batch-row .tick { width: calc(var(--u) * 13); height: calc(var(--u) * 13); color: #17803d; opacity: 0; flex: none; }
.vp-batch.an .tick { animation: batch-tick 5s var(--spring) infinite; }
.vp-batch.an .vp-batch-row:nth-child(2) .tick { animation-delay: 0.5s; }
.vp-batch.an .vp-batch-row:nth-child(3) .tick { animation-delay: 1s; }
@keyframes batch-tick { 0%, 52% { opacity: 0; transform: scale(0.4); } 64%, 88% { opacity: 1; transform: scale(1); } 96%, 100% { opacity: 0; } }

/* --- crop: the frame pulling in --------------------------------------- */

.vp-crop {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  overflow: hidden;
  border-radius: calc(var(--u) * 2);
}
.vp-crop .frame {
  position: absolute;
  inset: 4%;
  box-shadow: 0 0 0 calc(var(--u) * 1.6) var(--app-blue), 0 0 0 100vmax rgba(22, 30, 52, 0.38);
}
.vp-crop.an .frame { animation: crop-in 5s var(--smooth) infinite; }
@keyframes crop-in {
  0%, 12% { inset: 3%; }
  46%, 80% { inset: 12% 14% 20%; }
  96%, 100% { inset: 3%; }
}
.vp-crop .handle {
  position: absolute;
  width: calc(var(--u) * 8);
  height: calc(var(--u) * 8);
  background: var(--app-blue);
  border-radius: calc(var(--u) * 2);
}

/* --- rotate ------------------------------------------------------------ */
.vp-rotate { transform-origin: center; }
.vp-rotate.an { animation: rot 5s var(--snappy) infinite; }
@keyframes rot { 0%, 14% { transform: rotate(0); } 46%, 82% { transform: rotate(90deg); } 96%, 100% { transform: rotate(0); } }

/* --- compress: the file getting smaller -------------------------------- */
.vp-squeeze { display: grid; place-items: center; gap: calc(var(--u) * 10); }
.vp-squeeze .sizebar {
  width: 100%;
  height: calc(var(--u) * 20);
  border-radius: calc(var(--u) * 6);
  background: linear-gradient(90deg, #4a86e8, #1e3880);
  transform-origin: left center;
}
.vp-squeeze.an .sizebar { animation: squeeze 4.8s var(--smooth) infinite; }
@keyframes squeeze { 0%, 14% { transform: scaleX(1); } 48%, 82% { transform: scaleX(0.34); } 96%, 100% { transform: scaleX(1); } }
.vp-squeeze .sizeval { font-size: calc(var(--u) * 13); font-weight: 680; color: var(--app-ink); font-variant-numeric: tabular-nums; }

/* --- watermark --------------------------------------------------------- */
.vp-watermark {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 2;
  pointer-events: none;
}
.vp-watermark span {
  font-size: calc(var(--u) * 44);
  font-weight: 800;
  letter-spacing: 0.02em;
  color: rgba(29, 95, 212, 0.16);
  transform: rotate(-28deg) scale(0.6);
  opacity: 0;
}
.vp-watermark.an span { animation: wm-in 4.6s var(--spring) infinite; }
@keyframes wm-in {
  0%, 12% { opacity: 0; transform: rotate(-28deg) scale(0.6); }
  34%, 82% { opacity: 1; transform: rotate(-28deg) scale(1); }
  96%, 100% { opacity: 0; transform: rotate(-28deg) scale(0.8); }
}

/* --- reduced motion: hold every stage on a legible frame --------------- */

@media (prefers-reduced-motion: reduce) {
  /* Most marks are drawn with ::before / ::after, and an element selector
     never reaches a pseudo-element — so the kill list has to name them. */
  .app .an, .app .an *,
  .app.live .an, .app.live .an *,
  .app .an::before, .app .an::after,
  .app .an *::before, .app .an *::after,
  .app.live .an::before, .app.live .an::after,
  .app.live .an *::before, .app.live .an *::after { animation: none !important; }
  .hl::before, .rd::before { transform: scaleX(1); }
  .rd .ln-inner { opacity: 0; }
  .vp-note { opacity: 1; transform: rotate(-2deg); }
  .vp-ink path { stroke-dashoffset: 0; }
  .vp-sign-path { stroke-dashoffset: 0; }
  .vp-stamp { opacity: 1; transform: rotate(-9deg); }
  .vp-check .box::before { transform: scale(1); }
  .vp-check .box svg { opacity: 1; }
  .vp-field .typed { width: 58%; }
  .vp-edit .fresh { width: 32%; }
  .vp-edit::before { opacity: 1; }
  .vp-edit .caret { left: 62%; }
  .vp-batch-row .bar i { width: 100%; }
  .vp-batch-row .tick { opacity: 1; }
  .vp-watermark span { opacity: 1; transform: rotate(-28deg); }
  .vp-ocr .ln.found { background: var(--rule-blue); }
  .vp-squeeze .sizebar { transform: scaleX(0.34); }
  .vp-ruler { --pos: 45%; }
  .vp-speak .ln::after { transform: translateX(60%); opacity: 1; }
  .vp-diff-add::after { opacity: 1; }
  .vp-merge .doc, .vp-split .doc { transform: translateX(var(--dx)) rotate(var(--rot)); }
  .vp-meta-row .v { opacity: 0; transform: translateX(calc(var(--u) * 10)); }
  .vp-meta-row .x { opacity: 1; }
  .vp-lock .shackle { transform: none; }
  .vp-crop .frame { inset: 12% 14% 20%; }
  .vp-rotate { transform: rotate(90deg); }
  .vp-rows .vp-row.lift { transform: translate(calc(var(--u) * 8), calc(var(--u) * -116)) scale(1.05); }
  .vp-rows .vp-row.shift { transform: translateY(calc(var(--u) * 58)); }
}
