/* Products screen and account lists (OPS-9). Dark tokens apply only under body.ops, so the
   sign-in, code, enrol and recovery cards stay exactly as they were. Tokens are the command-center set.
   Layout follows OPS-9-UI-SPEC.md: wall >= 1800, laptop 1100-1799, tablet 640-1099, phone < 640. */

@font-face {
  font-family: "IBM Plex Mono";
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  src: url("ibm-plex-mono-500.woff2") format("woff2");
}

body.ops {
  --bg: #05090d;
  --panel: #08111a;
  --panel-2: #0c1823;
  --line: #173040;
  --line-strong: #25506a;
  --text: #e4f0f6;
  --text-2: #a3b9c6;
  --text-3: #7c93a2;
  --ok: #5be0f5;
  --warn: #ffb547;
  --crit: #ff6b6b;
  --none: #7c93a2;
  --ok-bg: rgba(91, 224, 245, 0.08);
  --warn-bg: rgba(255, 181, 71, 0.1);
  --crit-bg: rgba(255, 107, 107, 0.12);
  --r: 4px;
  --gap: 1.1rem;
  --mono: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  --label: "Chakra Petch", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  display: block;
  align-items: initial;
  justify-content: initial;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font: 400 1rem/1.4 -apple-system, BlinkMacSystemFont, "Segoe UI", ui-sans-serif, sans-serif;
}
html:has(body.ops) { font-size: 15px; color-scheme: dark; }
@media (max-width: 1099px) { html:has(body.ops) { font-size: 16px; } }
@media (min-width: 1800px) { html:has(body.ops) { font-size: clamp(13px, 0.78vw, 20px); } }

body.ops *, body.ops *::before, body.ops *::after { box-sizing: border-box; }
body.ops :focus-visible { outline: 2px solid var(--ok); outline-offset: 2px; }
body.ops .sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
body.ops .num, body.ops .num * { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 500; }

/* Controls: the sign-in cards style every button full width; reset for this screen. */
body.ops button, body.ops .btn {
  width: auto; min-height: 44px; padding: 0 1rem; background: none; border: 1px solid var(--line-strong);
  border-radius: var(--r); color: var(--text); font: inherit; cursor: pointer;
}
body.ops button:disabled { opacity: 0.55; cursor: default; }
body.ops a { color: var(--ok); }

body.ops header {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1.2rem; padding: var(--gap);
  border-bottom: 1px solid var(--line);
}
body.ops .brand {
  margin: 0; font: 700 1.15rem/1 var(--label); letter-spacing: 0.18em; text-transform: uppercase; color: var(--text);
}
body.ops main > h1 { margin: 0 0 var(--gap); font: 700 1.05rem/1.2 var(--label); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text); }
body.ops main > h1:focus { outline: none; }
body.ops .status { flex: 1; font-weight: 600; min-width: 12rem; }
body.ops .updated { color: var(--text-3); font-size: 0.85rem; }
body.ops .logout { text-decoration: none; color: var(--text); font-size: inherit; margin: 0; }
body.ops .backlink { display: inline-flex; align-items: center; min-height: 44px; text-decoration: none; }
body.ops main { padding: var(--gap); }

body.ops .notice { background: var(--ok-bg); color: var(--text-2); border: 1px solid var(--line); border-radius: var(--r); padding: 0.7rem 0.9rem; margin-bottom: var(--gap); }
body.ops .error { background: var(--crit-bg); color: var(--text); border: 1px solid var(--crit); border-radius: var(--r); padding: 0.7rem 0.9rem; margin-bottom: var(--gap); }
body.ops .panel-btn { display: inline-flex; align-items: center; min-height: 44px; width: auto; padding: 0 0.9rem; margin: 0 0 var(--gap); border: 1px solid var(--line-strong); border-radius: var(--r); background: none; color: var(--ok); text-decoration: none; font-size: inherit; }

body.ops .need { display: none; margin-bottom: var(--gap); }
body.ops .need a {
  display: flex; align-items: center; gap: 0.5rem; min-height: 44px; color: var(--text); text-decoration: none;
  border: 1px solid var(--warn); border-radius: var(--r); padding: 0 0.8rem; margin-bottom: 0.4rem;
}

body.ops .grid { display: grid; gap: var(--gap); grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1799px) { body.ops .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1099px) { body.ops .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 639px) {
  body.ops .grid { grid-template-columns: 1fr; }
  body.ops .need { display: block; }
  body.ops main, body.ops header { padding: 16px; }
  body.ops .overview { display: none; }
}
/* Laptop and tablet: the overview is a full-width strip above the tiles. */
@media (max-width: 1799px) { body.ops .overview { grid-column: 1 / -1; order: -1; } }
/* Wall: the page does not scroll; 4 x 2 with the overview as the eighth cell; each tile scrolls inside itself. */
@media (min-width: 1800px) {
  body.ops #cc-shell { height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
  body.ops main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
  body.ops .grid { flex: 1; min-height: 0; grid-template-rows: repeat(2, minmax(0, 1fr)); }
  body.ops .tile, body.ops .overview { overflow: auto; }
}

body.ops .tile {
  position: relative; background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 1px solid var(--line);
  border-radius: var(--r); padding: 1rem; display: flex; flex-direction: column; gap: 0.7rem;
}
body.ops .tile:hover { border-color: var(--line-strong); }
body.ops .tile:has(.act:focus-visible) { outline: 2px solid var(--ok); outline-offset: 2px; }
body.ops .tile.warn { border-color: var(--warn); background: var(--warn-bg); }
body.ops .tile.crit { border: 2px solid var(--crit); background: var(--crit-bg); }
body.ops .tile.unreach { border: 2px dashed var(--warn); }
body.ops .tile.none { border: 1px dashed var(--line-strong); background: none; }
body.ops .tile.flash { animation: ops-flash 900ms ease-out 1; }
@keyframes ops-flash { from { outline: 2px solid var(--ok); outline-offset: 2px; } to { outline: 2px solid transparent; outline-offset: 2px; } }
@media (prefers-reduced-motion: reduce) { body.ops .tile.flash { animation: none; } }
body.ops .upd { color: var(--ok); font-size: 0.78rem; }

body.ops .head { display: flex; justify-content: space-between; gap: 0.5rem; align-items: baseline; }
body.ops h2 { margin: 0; font: 700 0.95rem/1.2 var(--label); letter-spacing: 0.14em; text-transform: uppercase; color: var(--text); }
body.ops .chip { font-weight: 700; font-size: 0.85rem; white-space: nowrap; }
body.ops .chip.ok, body.ops .ov.ok { color: var(--ok); }
body.ops .chip.warn, body.ops .chip.unreach, body.ops .ov.warn, body.ops .ov.unreach { color: var(--warn); }
body.ops .chip.crit, body.ops .ov.crit { color: var(--crit); }
body.ops .chip.none, body.ops .ov.none { color: var(--none); }

body.ops .big { font-size: 1.75rem; line-height: 1; }
body.ops .big small { display: block; font: 400 0.78rem/1.2 -apple-system, "Segoe UI", ui-sans-serif, sans-serif; color: var(--text-3); margin-top: 0.2rem; }
body.ops .dl { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem 1rem; margin: 0; }
body.ops .dl div { min-width: 0; }
body.ops .dl dt { font-size: 0.78rem; color: var(--text-3); }
body.ops .dl dd { margin: 0; }
body.ops .na { color: var(--text-3); }
body.ops .att { margin: 0; padding: 0; list-style: none; color: var(--warn); font-size: 0.9rem; }
body.ops .att.crit { color: var(--crit); }
body.ops .quiet { color: var(--text-3); font-size: 0.85rem; margin: 0; }
body.ops .msg { margin: 0; color: var(--text-2); }
body.ops .foot { margin-top: auto; display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; font-size: 0.78rem; color: var(--text-3); }
body.ops .old { color: var(--warn); }

/* One tab stop per tile: the action is stretched over the whole tile; the secondary link sits above it. */
body.ops .act {
  color: var(--ok); text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; font-weight: 600;
  background: none; border: 0; padding: 0; font-size: 0.95rem; width: fit-content;
}
body.ops .act::after { content: ""; position: absolute; inset: 0; }
body.ops .act:focus-visible { outline: 2px solid var(--ok); outline-offset: 2px; }
@supports selector(:has(a)) { body.ops .act:focus-visible { outline: none; } }
body.ops .sec { position: relative; z-index: 1; color: var(--text-2); font-size: 0.85rem; min-height: 44px; display: inline-flex; align-items: center; }

body.ops .bar { display: block; height: 0.7rem; background: var(--line); border-radius: 2px; margin: 0.3rem 0; width: 70%; }
body.ops .bar.tall { height: 1.75rem; width: 40%; }
body.ops .bar.rowbar { width: 100%; height: 2rem; }

/* More numbers: a closed disclosure on phones only; JS opens it from 640px up. */
body.ops details.more > summary { display: flex; align-items: center; margin-bottom: 0.5rem; list-style: none; }
body.ops details.more > .dl { margin-top: 0.5rem; }
@media (min-width: 640px) { body.ops details.more > summary { display: none; } body.ops details.more > .dl { margin-top: 0; } }

/* Overview */
body.ops .overview { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: 0.9rem; }
body.ops .ovrow { display: flex; flex-wrap: wrap; gap: 0.6rem; font-size: 1.1rem; }
body.ops .ov { min-width: 2rem; text-align: center; }

/* Account list */
body.ops .tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r); }
body.ops table.accounts { width: 100%; border-collapse: collapse; }
body.ops table.accounts th, body.ops table.accounts td { text-align: left; padding: 0.6rem 0.8rem; border-bottom: 1px solid var(--line); vertical-align: top; overflow-wrap: anywhere; }
body.ops table.accounts th { position: sticky; top: 0; background: var(--panel-2); color: var(--text-3); font-size: 0.78rem; font-weight: 600; }
body.ops table.accounts td.num { text-align: right; }
body.ops .rel { color: var(--text-3); }
body.ops .st.warn { color: var(--warn); }
body.ops .st.none { color: var(--none); }
body.ops .tfoot { display: flex; align-items: center; gap: 1rem; margin-top: var(--gap); color: var(--text-3); }
@media (max-width: 639px) { body.ops .hide-phone { display: none; } body.ops .tablewrap { overflow-x: visible; } }

/* ---- Command center (OPS-5): shell, Home, Alerts, Second brain, capture, dialogs ---- */
body.ops input, body.ops textarea, body.ops select { background: var(--panel); color: var(--text); border: 1px solid var(--line-strong); border-radius: var(--r); font: inherit; margin: 0; }
body.ops .field { display: block; width: 100%; min-height: 48px; padding: 0.5rem 0.8rem; }
body.ops textarea.field { min-height: 6rem; resize: vertical; }
body.ops button.pri { background: var(--ok); color: #031014; border-color: var(--ok); font-weight: 600; }
body.ops button.danger { background: var(--crit); color: #1a0505; border-color: var(--crit); font-weight: 600; }
body.ops button.linkish { border: 0; min-height: 44px; padding: 0 0.3rem; color: var(--ok); text-decoration: underline; }
body.ops button.logout { border-color: transparent; }
body.ops kbd { font-size: 0.78rem; border: 1px solid var(--line-strong); border-radius: 3px; padding: 0 0.3rem; margin-left: 0.3rem; }
body.ops header .status { font-size: 0.95rem; }
body.ops .s-ok { color: var(--ok); } body.ops .s-warn { color: var(--warn); } body.ops .s-crit { color: var(--crit); } body.ops .s-none { color: var(--none); }

body.ops #tabs { display: flex; gap: 0.25rem; padding: 0 var(--gap); border-bottom: 1px solid var(--line); }
body.ops #tabs a { min-height: 44px; display: flex; align-items: center; gap: 0.3rem; padding: 0 0.9rem; color: var(--text-2); text-decoration: none; border-bottom: 2px solid transparent; }
body.ops #tabs a[aria-current="page"] { color: var(--text); border-bottom-color: var(--ok); }
body.ops #tabs .ico, body.ops #tabs .cap { display: none; }
body.ops .badge { font: 600 0.72rem var(--mono); padding: 0.1rem 0.4rem; border-radius: 99px; border: 1px solid var(--warn); color: var(--warn); }
body.ops .badge.crit { border-color: var(--crit); color: var(--crit); }
body.ops .qcount { color: var(--warn); }
body.ops .qcount[hidden], body.ops .badge[hidden], body.ops .banner[hidden], body.ops .toast[hidden], body.ops .queue[hidden] { display: none; }
body.ops .banner { display: flex; gap: 0.6rem; align-items: center; flex-wrap: wrap; padding: 0.55rem var(--gap); font-size: 0.88rem; border-bottom: 1px solid var(--line); background: var(--warn-bg); color: var(--warn); }
body.ops .toast { max-width: calc(100vw - 2rem); position: fixed; left: 50%; bottom: 5rem; transform: translateX(-50%); display: flex; gap: 0.8rem; align-items: center; background: var(--panel-2); border: 1px solid var(--line-strong); border-radius: var(--r); padding: 0.4rem 0.8rem; z-index: 5; }

body.ops .wrap { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: var(--gap); max-width: 1500px; margin: 0 auto; }
body.ops .wrap.brain { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
body.ops .col { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
@media (max-width: 1099px) { body.ops .wrap, body.ops .wrap.brain { grid-template-columns: 1fr; } }
body.ops .panel { background: linear-gradient(180deg, var(--panel-2), var(--panel)); border: 1px solid var(--line); border-radius: var(--r); padding: 1rem; margin-bottom: var(--gap); }
body.ops .col .panel { margin-bottom: 0; }
body.ops .panel > h2 { display: flex; gap: 0.6rem; align-items: baseline; margin: 0 0 0.75rem; }
body.ops .panel h3 { margin: 1rem 0 0.4rem; font: 700 0.85rem/1.2 var(--label); letter-spacing: 0.1em; text-transform: uppercase; }
body.ops .meta { margin-left: auto; font: 400 0.78rem/1.2 -apple-system, "Segoe UI", ui-sans-serif, sans-serif; letter-spacing: 0; text-transform: none; color: var(--text-3); }
body.ops a.meta { display: inline-flex; align-items: center; min-height: 44px; color: var(--ok); }
body.ops .row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; margin: 0.5rem 0; }
body.ops .old { color: var(--warn); font-size: 0.88rem; margin: 0 0 0.5rem; }

body.ops .st { display: inline-flex; gap: 0.35rem; align-items: center; font-weight: 600; font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase; white-space: nowrap; }
body.ops .st.ok { color: var(--ok); } body.ops .st.crit { color: var(--crit); }
body.ops .tag, body.ops .stage { border: 1px solid var(--line-strong); border-radius: 3px; padding: 0 0.35rem; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-2); }
body.ops .q { border: 1px solid var(--line); border-left: 4px solid var(--warn); border-radius: var(--r); padding: 0.8rem 0.9rem; margin-bottom: 0.7rem; background: var(--warn-bg); }
body.ops .q.crit { border-left-color: var(--crit); background: var(--crit-bg); }
body.ops .q .tags, body.ops .evt .tags { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; font-size: 0.78rem; color: var(--text-3); }
body.ops .q p { margin: 0.35rem 0; }
body.ops .q .why { color: var(--text-2); font-size: 0.88rem; }
body.ops .acts { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.6rem; }
body.ops a.btn { display: inline-flex; align-items: center; text-decoration: none; }
body.ops a.btn.pri { background: var(--ok); color: #031014; font-weight: 600; }

body.ops .kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr)); gap: 0.7rem; margin: 0; }
body.ops .kv > div { border: 1px solid var(--line); border-radius: var(--r); padding: 0.6rem 0.7rem; }
body.ops .kv dt { font-size: 0.75rem; color: var(--text-3); }
body.ops .kv dd { margin: 0; font-size: 1.5rem; font-weight: 600; }
body.ops .kv dd small { font-size: 0.75rem; color: var(--text-2); font-weight: 400; }
body.ops .lines { margin: 0.6rem 0 0; padding-left: 1.1rem; color: var(--text-2); }
body.ops details.more > summary { min-height: 44px; }

body.ops .chips { display: flex; gap: 0.5rem; flex-wrap: wrap; }
body.ops .pill { min-height: 44px; display: inline-flex; align-items: center; gap: 0.4rem; padding: 0 0.8rem; border: 1px solid var(--line); border-radius: 99px; text-decoration: none; color: var(--text); font-size: 0.88rem; background: none; cursor: pointer; }
body.ops button.pill[aria-pressed="true"] { border-color: var(--ok); color: var(--ok); }
body.ops .pill.warn, body.ops .pill.unreach { border: 1px dashed var(--warn); background: var(--warn-bg); }
body.ops .pill.crit { border: 2px solid var(--crit); background: var(--crit-bg); }
body.ops .pill.none { border: 1px dashed var(--line-strong); }
body.ops .pill .quiet { margin: 0; }

body.ops .idea, body.ops .res { display: block; padding: 0.7rem 0; border-top: 1px solid var(--line); color: var(--text); text-decoration: none; }
body.ops .idea:first-of-type, body.ops .res:first-of-type { border-top: 0; }
body.ops .idea p, body.ops .res p { margin: 0.2rem 0; }
body.ops .m { font-size: 0.78rem; color: var(--text-3); display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }
body.ops mark { background: var(--warn-bg); color: var(--warn); border-radius: 2px; }
body.ops .note-body { white-space: pre-wrap; overflow-wrap: anywhere; }
body.ops pre.draft { white-space: pre-wrap; overflow-wrap: anywhere; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); padding: 0.7rem; }
body.ops .tgt { font-weight: 600; overflow-wrap: anywhere; }
body.ops .frow { display: grid; gap: 0.25rem; margin: 0.6rem 0; }
body.ops .frow label { font-size: 0.85rem; color: var(--text-2); }

body.ops .capture-out, body.ops .queue { margin-top: 0.5rem; font-size: 0.9rem; }
body.ops .queue { border: 1px dashed var(--warn); border-radius: var(--r); padding: 0.6rem; background: var(--warn-bg); }
body.ops .queue .bad { border-top: 1px solid var(--crit); margin-top: 0.4rem; padding-top: 0.4rem; }
body.ops .evt { border-top: 1px solid var(--line); padding: 0.4rem 0; }
body.ops .evt summary { min-height: 44px; display: flex; align-items: center; gap: 0.4rem; cursor: pointer; }
body.ops .act-row { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; padding: 0.2rem 0; }

body.ops dialog { max-height: 100dvh; overflow-y: auto; background: var(--panel); color: var(--text); border: 1px solid var(--line-strong); border-radius: var(--r); padding: 1rem; max-width: min(34rem, calc(100vw - 2rem)); width: 100%; }
body.ops dialog::backdrop { background: rgba(0, 0, 0, 0.7); }
body.ops dialog h2 { margin: 0 0 0.6rem; }
body.ops dialog.sheet { max-height: 92dvh; overflow-y: auto; margin: auto auto 0; max-width: 100%; border-radius: 12px 12px 0 0; padding-bottom: calc(1rem + env(safe-area-inset-bottom)); }

/* Phone: the tabs become a bottom bar with the capture "+" in the middle. */
@media (max-width: 639px) {
  body.ops { padding-bottom: calc(76px + env(safe-area-inset-bottom)); }
  body.ops header .status { flex-basis: 100%; order: 3; }
  body.ops .find { display: none; }
  body.ops #tabs { position: fixed; bottom: 0; left: 0; right: 0; z-index: 4; display: grid; grid-template-columns: repeat(7, 1fr); gap: 0; padding: 0 0 env(safe-area-inset-bottom); background: var(--panel); border-top: 1px solid var(--line-strong); border-bottom: 0; }
  body.ops #tabs a { min-height: 56px; flex-direction: column; justify-content: center; padding: 0; font-size: 0.72rem; line-height: 1.1; text-align: center; border-bottom: 0; position: relative; }
  body.ops #tabs a[aria-current="page"] { color: var(--ok); }
  body.ops #tabs .ico { display: block; width: 0.5rem; height: 0.5rem; border: 1px solid currentColor; border-radius: 50%; }
  body.ops #tabs .badge { position: absolute; top: 4px; right: 22%; }
  body.ops #tabs .cap { display: grid; place-items: center; width: 44px; height: 44px; min-height: 44px; margin: auto; padding: 0; border-radius: 50%; background: var(--ok); color: #031014; border-color: var(--ok); font: 600 1.5rem var(--mono); }
  body.ops .toast { bottom: 5.5rem; }
  body.ops .acts button, body.ops .acts a.btn { flex: 1; justify-content: center; }
  body.ops .kv { grid-template-columns: 1fr 1fr; }
}
@media (prefers-reduced-motion: reduce) { body.ops * { animation: none !important; transition: none !important; } }

/* --- OPS-5bc: approvals, library, board ---------------------------------------------------------------- */
body.ops .lbl-short { display: none; }
body.ops .subnav { display: flex; gap: 0.5rem; flex-wrap: wrap; margin: 0 0 var(--gap); }
body.ops .subnav a { min-height: 44px; display: inline-flex; align-items: center; padding: 0 0.9rem; border: 1px solid var(--line); border-radius: 99px; color: var(--text-2); text-decoration: none; }
body.ops .subnav a[aria-current="page"] { border-color: var(--ok); color: var(--ok); }
body.ops .meta-line { margin: 0 0 0.4rem; }
body.ops .lib-title { font-weight: 600; margin: 0.2rem 0; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
body.ops .snip { margin: 0.2rem 0; color: var(--text-2); overflow-wrap: anywhere; }

/* Approvals list */
body.ops .ap-row { display: block; min-height: 64px; padding: 0.7rem 0.8rem; margin-bottom: 0.5rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--panel); color: var(--text); text-decoration: none; }
body.ops .ap-top, body.ops .ap-mid { display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }
body.ops .ap-where { overflow-wrap: anywhere; }
body.ops .ap-exp { margin-left: auto; font-size: 0.85rem; color: var(--text-2); }
body.ops .exp.soon { color: var(--warn); }
body.ops .exp.crit { color: var(--crit); font-weight: 600; }
body.ops .ap-title { overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
body.ops .ap-bottom { font-size: 0.82rem; margin-top: 0.2rem; }

/* One request: the signed block and the agent's words are visibly different things. */
body.ops .ap-signed { border: 2px solid var(--line-strong); background: var(--panel-2); border-radius: var(--r); padding: 1rem; margin-bottom: var(--gap); }
body.ops .ap-agent { border: 1px dashed var(--line-strong); background: var(--bg); border-radius: var(--r); padding: 1rem; margin-bottom: var(--gap); color: var(--text-2); }
body.ops .ap-signed h2, body.ops .ap-agent h2 { margin: 0 0 0.6rem; font-size: 1rem; }
body.ops .facts { margin: 0; display: grid; gap: 0.6rem; }
body.ops .facts dt { font-size: 0.78rem; color: var(--text-3); }
body.ops .facts dd { margin: 0; font-size: 1.05rem; overflow-wrap: anywhere; }
body.ops .facts code { font-size: 1rem; overflow-wrap: anywhere; }
body.ops .sha .grp { display: inline-block; margin-right: 0.6rem; }
body.ops .sha strong { color: var(--ok); }
body.ops .clamp { display: -webkit-box; -webkit-line-clamp: 12; -webkit-box-orient: vertical; overflow: hidden; }
body.ops details summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; }
body.ops .ap-actions { display: flex; gap: 0.6rem; margin: 0.6rem 0; }
body.ops .ap-actions button { min-height: 48px; }
body.ops dialog.sign { max-width: min(34rem, calc(100vw - 2rem)); }
body.ops .sign-form .sign-buttons { position: sticky; bottom: 0; background: var(--panel); padding: 0.5rem 0; }
body.ops .sign-lines { list-style: none; margin: 0.4rem 0 0; padding: 0; display: grid; gap: 0.15rem; }
body.ops .sign-lines li { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: 0.5rem; }
body.ops .sign-lines .gl { color: var(--text-3); font-size: 0.75rem; user-select: none; }
body.ops .sign-lines code { white-space: pre-wrap; overflow-wrap: anywhere; font-size: 0.85rem; }
body.ops .sign-result h3 { margin: 0 0 0.5rem; }

/* Library */
body.ops .lib-row { display: block; padding: 0.7rem 0; border-top: 1px solid var(--line); color: var(--text); text-decoration: none; }
body.ops .item-grid { display: grid; grid-template-columns: minmax(0, 46rem) minmax(0, 1fr); gap: var(--gap); align-items: start; }
@media (max-width: 1099px) { body.ops .item-grid { grid-template-columns: 1fr; } body.ops .rail { order: -1; } body.ops .toc { display: none; } }
@media (min-width: 1100px) { body.ops #jump { display: none; } body.ops .rail { position: sticky; top: 1rem; } }
body.ops .lib-body { overflow-wrap: anywhere; }
body.ops .doc-h { margin: 1.2rem 0 0.4rem; }
body.ops .doc-h:focus { outline: none; }
body.ops .tablewrap-x { overflow-x: auto; max-width: 100%; }
body.ops .tablewrap-x table { border-collapse: collapse; }
body.ops .tablewrap-x th, body.ops .tablewrap-x td { border: 1px solid var(--line); padding: 0.3rem 0.5rem; text-align: left; vertical-align: top; }
body.ops .toc { list-style: none; margin: 0; padding: 0; }
body.ops .att { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; padding: 0.4rem 0; border-top: 1px solid var(--line); }
body.ops .att-name { overflow-wrap: anywhere; min-width: 0; }

/* Board (read only) */
body.ops .board-strip { display: flex; gap: 0.6rem 1rem; flex-wrap: wrap; align-items: center; margin-bottom: var(--gap); }
body.ops .board-cols { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--gap); align-items: start; }
body.ops .bcol h2 { font-size: 0.95rem; margin: 0 0 0.5rem; }
body.ops .bcards { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
body.ops .bcard { display: block; min-height: 56px; padding: 0.55rem 0.65rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--panel); color: var(--text); text-decoration: none; }
body.ops .bc-title { margin: 0 0 0.2rem; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
body.ops .feed { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
body.ops .feed li { border: 1px solid var(--line); border-radius: var(--r); padding: 0.5rem 0.65rem; }
body.ops .feed p { margin: 0 0 0.2rem; overflow-wrap: anywhere; }
body.ops .col-switch { display: none; }
@media (max-width: 1099px) {
  body.ops .board-cols { display: flex; overflow-x: auto; scroll-snap-type: x proximity; gap: var(--gap); }
  body.ops .bcol { flex: 0 0 18rem; scroll-snap-align: start; }
}
@media (max-width: 639px) {
  body.ops .col-switch { display: flex; margin-bottom: var(--gap); }
  body.ops .board-cols { display: block; overflow: visible; }
  body.ops .bcol { display: none; }
  body.ops .bcol.on { display: block; }
  body.ops.ap-detail #tabs { display: none; }
  body.ops.ap-detail { padding-bottom: calc(96px + env(safe-area-inset-bottom)); }
  body.ops .ap-bar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 5; padding: 0.5rem var(--gap) calc(0.5rem + env(safe-area-inset-bottom)); background: var(--panel); border-top: 1px solid var(--line-strong); }
  body.ops .ap-bar .quiet:empty { display: none; }
  body.ops .ap-actions button { flex: 1; }
  body.ops #tabs .lbl-full { display: none; }
  body.ops #tabs .lbl-short { display: inline; }
  body.ops dialog.sign { max-width: 100%; height: 100dvh; margin: 0; border-radius: 0; }
  body.ops .sign-lines code { font-size: 0.8rem; }
  body.ops .att { display: grid; }
  body.ops .rail .row button { flex: 1; }
}

/* ---- Village (V-4). Plates and chips sit on solid --panel so contrast never depends on the art. ---- */
body.ops .vil { display: grid; gap: var(--gap); grid-template-columns: minmax(0, 1fr); padding: var(--gap) 0; }
body.ops .vil [hidden] { display: none !important; }
body.ops .vil-skip { position: absolute; left: -999px; }
body.ops .vil-skip:focus { position: static; }
body.ops .vil h2 { margin: 0 0 0.4rem; font-size: 0.9rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-2); }
body.ops .vil-top { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
body.ops .vil-chip { display: inline-flex; align-items: center; min-height: 44px; padding: 0 0.8rem; background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--r); color: var(--text); text-decoration: none; font: inherit; font-size: 0.9rem; font-weight: 600; }
body.ops .vil-chip.ok { color: var(--ok); }
body.ops .vil-chip.busy { color: var(--text); border-color: var(--ok); }
body.ops .vil-chip.crit { color: var(--crit); border: 3px solid var(--crit); }
body.ops .vil-chip.warn { color: var(--warn); }
body.ops .vil-chip.dashed, body.ops .vil-waiting.dashed { border-style: dashed; }
body.ops .vil-chip.vil-p1-none { color: var(--text-3); font-weight: 400; }
body.ops .vil-chip.vil-sky, body.ops .vil-chip.vil-lostchip { font-weight: 400; cursor: default; }
body.ops .vil-lostchip { border-style: dashed; color: var(--warn); }
body.ops button.vil-chip { cursor: pointer; }
body.ops .vil-age { color: var(--text-2); font-size: 0.9rem; }
body.ops .vil-age.warn { color: var(--warn); }
body.ops .vil-meta { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
body.ops .vil-main { display: flex; flex-direction: column; gap: 0.6rem; min-width: 0; }
body.ops .vil-switch { order: 2; display: inline-flex; align-self: flex-start; }
body.ops .vil-switch button { min-height: 44px; padding: 0 1rem; background: var(--panel); color: var(--text-2); border: 1px solid var(--line-strong); }
body.ops .vil-switch button[aria-pressed="true"] { color: var(--text); border-color: var(--ok); }
body.ops .vil-stage { position: relative; width: 100%; aspect-ratio: 2752 / 1536; background: #000; border: 1px solid var(--line); overflow: hidden; }
body.ops .vil-stage.vil-square { aspect-ratio: 1; max-width: 30rem; margin-inline: auto; }
body.ops .vil-art, body.ops .vil-wx { position: absolute; inset: 0; width: 100%; height: 100%; }
body.ops .vm-dusk, body.ops .vm-night { opacity: 0; }
body.ops .sky-dusk .vm-dusk, body.ops .sky-night .vm-night { opacity: 1; }
body.ops .vil-armed .vm { transition: opacity 300s linear; }
body.ops .spr-night, body.ops .smk-night { opacity: 0; }
body.ops .ph-dawn .spr-night, body.ops .ph-dusk .spr-night, body.ops .ph-dawn .smk-night, body.ops .ph-dusk .smk-night { opacity: 0.35; }
body.ops .ph-night .spr-night, body.ops .ph-night .smk-night { opacity: 1; }
body.ops .ph-day .smk-night { opacity: 0; }
/* The pile and the scaffolds have one picture each: dimmed at dusk and night, no night art. */
body.ops .fix, body.ops .mo { pointer-events: none; }
body.ops .ph-dawn .fix, body.ops .ph-dusk .fix { filter: brightness(0.75); }
body.ops .ph-night .fix { filter: brightness(0.55) saturate(0.8); }
body.ops .vil-weather { position: absolute; inset: 0; opacity: 0.35; pointer-events: none; }
body.ops .wx-layer { display: none; }
body.ops .vil-stage[data-wx="rain"] .wx-rain, body.ops .vil-stage[data-wx="snow"] .wx-snow, body.ops .vil-stage[data-wx="wind"] .wx-wind { display: inline; }
body.ops .wx-rain.wx-a { animation: wxrain 0.8s linear infinite; }
body.ops .wx-rain.wx-b { animation: wxrain 1.1s linear infinite; }
body.ops .wx-snow { animation: wxsnow 6s linear infinite; }
body.ops .wx-wind { animation: wxwind 3s linear infinite; }
body.ops .wx-fog { display: none; position: absolute; inset: -20%; background: linear-gradient(100deg, transparent 10%, rgba(220, 230, 236, 0.9) 40%, transparent 60%, rgba(220, 230, 236, 0.8) 85%); }
body.ops .vil-stage[data-wx="fog"] .wx-fog { display: block; animation: wxfog 60s ease-in-out infinite alternate; }
body.ops .vil-still .vil-weather { opacity: 0.25; }
@keyframes wxrain { to { transform: translate(-18px, 90px); } }
@keyframes wxsnow { to { transform: translate(10px, 110px); } }
@keyframes wxwind { to { transform: translate(160px, 0); } }
@keyframes wxfog { to { transform: translateX(15%); } }
body.ops .vh { position: absolute; display: block; margin: 0; padding: 0; min-width: 44px; min-height: 44px; background: transparent; border: 0; border-radius: var(--r); cursor: pointer; font: inherit; color: var(--text); }
body.ops .vh:focus-visible, body.ops .vil-row:focus-visible { outline: 2px solid var(--ok); outline-offset: 2px; box-shadow: 0 0 0 6px #05090d; }
body.ops .vh.ring { box-shadow: inset 0 0 0 3px var(--ok); }
body.ops .vp { position: absolute; z-index: 2; padding: 0.15rem 0.45rem; background: var(--panel); border: 1px solid var(--line-strong); border-radius: var(--r); font-size: 0.8rem; line-height: 1.25; white-space: nowrap; }
body.ops.wall .vp { font-size: 1rem; }
/* A stage under 1100 px wide shows the glyph and the name only (spec 15.2). */
body.ops .vil-stage { container-type: inline-size; }
@container (max-width: 1099px) { body.ops .vp-s { display: none; } }
body.ops .vh:hover .vp { background: var(--panel-2); border-color: var(--ok); }
body.ops .vh[data-cls="warn"] .vp { border: 2px solid var(--warn); }
body.ops .vh[data-cls="crit"] .vp { border: 3px solid var(--crit); }
body.ops .vh[data-cls="none"] .vp { border: 2px dashed var(--text-3); color: var(--text-2); }
body.ops .vh[data-cls="unreach"] .vp { border: 2px dashed var(--warn); }
body.ops .vh[data-cls="warn"] .vp-g, body.ops .vh[data-cls="unreach"] .vp-g { color: var(--warn); }
body.ops .vh[data-cls="crit"] .vp-g { color: var(--crit); }
body.ops .vil-rail { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; }
body.ops .vil-rail > section, body.ops .vil-panel { padding: 0.8rem; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); }
body.ops .vil-bignum { margin: 0; font-size: 2.4rem; line-height: 1.1; }
body.ops .vil-ctls { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0.5rem; }
body.ops .vil-ctl { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 44px; padding: 0.2rem 0.4rem; background: var(--panel-2); color: var(--text); border: 1px solid var(--line-strong); border-radius: var(--r); font: inherit; cursor: pointer; }
body.ops .vil-ctl[aria-disabled="true"] { color: var(--text-2); border-style: dashed; background: transparent; cursor: default; }
body.ops .vil-ctl.none { border: 1px dashed var(--line-strong); background: transparent; color: var(--text-2); }
body.ops .vil-tag { margin-top: 0.1rem; padding: 0 0.35rem; border: 1px solid var(--line-strong); border-radius: var(--r); font-size: 0.8rem; }
body.ops .vil-dock-note:empty { display: none; }
body.ops .vil-ticker { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.25rem; }
body.ops .vil-ticker li { min-height: 2rem; display: flex; align-items: center; }
body.ops .vil-ticker a { display: flex; align-items: center; min-height: 44px; color: var(--text); text-decoration: none; width: 100%; }
body.ops .vil-ticker li:nth-child(n + 5) { display: none; }
body.ops .vil-ticker.all li { display: flex; }
body.ops .vil-more { display: none; min-height: 44px; }
body.ops .vil-panel .vil-phead { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
body.ops .vil-ph { margin: 0; font-size: 1.15rem; text-transform: none; letter-spacing: 0; color: var(--text); }
body.ops .vil-close { min-width: 44px; min-height: 44px; font-size: 1.5rem; background: transparent; color: var(--text); border: 1px solid var(--line-strong); border-radius: var(--r); cursor: pointer; }
body.ops .vil-state { margin: 0.4rem 0 0; font-weight: 600; }
body.ops .vil-state.warn, body.ops .vil-state.unreach { color: var(--warn); }
body.ops .vil-state.crit { color: var(--crit); }
body.ops .vil-state.none { color: var(--text-2); }
body.ops .vil-state.ok, body.ops .vil-state.busy { color: var(--ok); }
body.ops .vil-kvs { margin: 0.6rem 0; display: grid; gap: 0.2rem; }
body.ops .vil-kv { display: flex; justify-content: space-between; gap: 1rem; padding: 0.25rem 0; border-bottom: 1px solid var(--line); }
body.ops .vil-kv dt, body.ops .vil-kv dd { margin: 0; }
body.ops .vil-kv.none { border-bottom: 1px dashed var(--line-strong); color: var(--text-2); }
body.ops .vil-links { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem; }
body.ops .vil-figs { display: flex; gap: 0.8rem; align-items: center; margin: 0.6rem 0; }
body.ops .vil-fig { width: 7rem; height: auto; }
body.ops .vil-rows, body.ops .vil-list { list-style: none; margin: 0.4rem 0; padding: 0; display: grid; gap: 0.4rem; }
body.ops .vil-row { display: grid; grid-template-columns: 1.4rem 1fr auto; gap: 0.1rem 0.5rem; align-items: center; width: 100%; min-height: 64px; padding: 0.4rem 0.6rem; text-align: left; background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: var(--r); font: inherit; cursor: pointer; }
body.ops .vil-row .vil-rt { grid-column: 2 / 3; color: var(--text-2); font-size: 0.9rem; }
body.ops .vil-row .vil-chev { grid-column: 3; grid-row: 1 / 3; }
body.ops .vil-row .vil-rs { grid-column: 3; grid-row: 1; font-size: 0.8rem; }
body.ops .vil-row.warn { border: 2px solid var(--warn); }
body.ops .vil-row.crit { border: 3px solid var(--crit); }
body.ops .vil-row.none { border: 1px dashed var(--line-strong); }
body.ops .vil-row.unreach { border: 2px dashed var(--warn); }
body.ops .vil-calm { padding: 0.8rem; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r); }
body.ops .vil-all summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; }
body.ops .vil-error { grid-column: 1 / -1; }
body.ops .vil-error:empty { display: none; }
/* Tablet and phone: one column. A building's panel is a right-edge sheet (tablet) or a modal bottom sheet (phone). */
@media (min-width: 740px) and (max-width: 1099px) {
  body.ops .vil-panel { position: fixed; z-index: 6; top: 0; right: 0; bottom: 0; width: 22rem; max-width: 100%; overflow-y: auto; border-radius: 0; }
  body.ops .vil-waiting { display: none; }
  body.ops .vil-ticker li:nth-child(n + 4) { display: none; }
  body.ops .vil-ticker.all li { display: flex; }
}
@media (max-width: 739px) {
  /* The counter, P1 and sky chips share one row, and the square sits as high as it can (spec 15 review). */
  body.ops .vil { gap: 0.5rem; padding-top: 0.25rem; }
  body.ops .vil-top { flex-wrap: nowrap; gap: 0.35rem; }
  body.ops .vil-top .vil-chip { flex: 1 1 auto; min-width: 0; padding: 0 0.5rem; font-size: 0.8rem; line-height: 1.15; }
  body.ops .vil-meta { order: 3; }
  body.ops .vil-rail { order: 4; }
  body.ops main:has(.vil) > h1 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  body.ops .vil-chip.vil-p1-none { display: none; }
  body.ops .vil-waiting { display: none; }
  body.ops .vil-ticker li:nth-child(n + 2) { display: none; }
  body.ops .vil-ticker.all li { display: flex; }
  body.ops .vil-more { display: inline-block; }
  body.ops dialog.vil-sheet { height: 85dvh; }
}
/* Laptop: the stage and a 22 rem rail. A panel replaces the Herbert and Today blocks. */
@media (min-width: 1100px) {
  body.ops .vil { grid-template-columns: minmax(0, 1fr) 22rem; align-items: start; }
  body.ops .vil-top { grid-column: 1; grid-row: 1; }
  body.ops .vil-meta { grid-column: 1; grid-row: 2; }
  body.ops .vil-main { grid-column: 1; grid-row: 3; }
  body.ops .vil-rail { grid-column: 2; grid-row: 1 / span 3; }
  body.ops .vil-rail.vil-has-panel > .vil-dock, body.ops .vil-rail.vil-has-panel > .vil-today { display: none; }
}
/* Wall: one compact header row and one tab row (the hub's own, kept: they are the way out on a touch wall), the
   counter strip, the stage letterboxed, and one bottom strip with the last three lines and the dock. At 1920 x 1080
   the stage is 0.56 of the map. */
body.ops.wall:has(.vil) header { padding-block: 0.3rem; min-height: 0; }
body.ops.wall:has(.vil) header .status, body.ops.wall:has(.vil) header #updated, body.ops.wall:has(.vil) header #qcount, body.ops.wall:has(.vil) header #session { display: none; }
body.ops.wall:has(.vil) #tabs a { min-height: 40px; }
body.ops.wall main:has(.vil) { padding-block: 0.3rem 0; }
body.ops.wall .vil-ctl { flex-direction: row; padding: 0 0.6rem; }
body.ops.wall .vil-tag { margin: 0 0 0 0.4rem; }
body.ops.wall main:has(.vil) > h1 { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
body.ops.wall .vil { grid-template-columns: minmax(0, 1fr) auto; gap: 0.4rem 0.8rem; padding: 0 var(--gap) 0.6rem; align-items: center; }
body.ops.wall .vil-top { grid-column: 1; grid-row: 1; }
body.ops.wall .vil-meta { grid-column: 2; grid-row: 1; }
body.ops.wall .vil-main, body.ops.wall .vil-error { grid-column: 1 / -1; grid-row: 2; }
body.ops.wall .vil-rail { grid-column: 1 / -1; grid-row: 3; }
body.ops.wall .vil-stage { width: min(100%, calc((100dvh - 218px) * 2752 / 1536), 2752px); margin-inline: auto; }
body.ops.wall .vil-switch, body.ops.wall .vil-waiting, body.ops.wall .vil-help, body.ops.wall .vil-more, body.ops.wall .vil-rail h2, body.ops.wall .vil-dock-note { display: none; }
body.ops.wall .vil-rail { flex-direction: row; align-items: center; gap: 1rem; }
body.ops.wall .vil-rail > section { padding: 0.3rem 0.6rem; }
body.ops.wall .vil-rail > .vil-today { flex: 1; min-width: 0; }
body.ops.wall .vil-dock .vil-ctls { width: 24rem; }
body.ops.wall .vil-rail.vil-has-panel > .vil-dock, body.ops.wall .vil-rail.vil-has-panel > .vil-today { display: block; }
body.ops.wall .vil-ticker { display: flex; gap: 1.5rem; }
body.ops.wall .vil-ticker li { min-height: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
body.ops.wall .vil-ticker li:nth-child(n + 4) { display: none; }
body.ops.wall .vil-panel { position: fixed; z-index: 6; top: 0; right: 0; bottom: 0; width: 26rem; max-width: 100%; overflow-y: auto; border-radius: 0; }
body.ops.wall .vil-panelhost { display: contents; }
/* Reduced motion, or the Motion switch turned off: nothing animates. */
body.ops .vil-still *, body.ops .vil-still *::before, body.ops .vil-still *::after { animation: none !important; transition: none !important; }
@media (forced-colors: active) { body.ops .vp, body.ops .vil-chip, body.ops .vil-row { border: 1px solid CanvasText; } }
/* Moments: one-shots of 2.8 s or less, on transform and opacity only. */
body.ops .mo { transform-box: fill-box; transform-origin: 50% 100%; opacity: 0; animation-fill-mode: both; animation-timing-function: ease-out; }
body.ops .mo-bell { transform-origin: 50% 0; animation: mobell 2.5s; }
body.ops .mo-carrier { animation: mocarrier 2.8s; }
body.ops .mo-book { animation: mobook 1.8s; }
body.ops .mo-barrow { animation: mobarrow 2.4s; }
body.ops .mo-wrench { animation: mowrench 2.8s; }
body.ops .mo-ribbon { animation: moribbon 2s; }
body.ops .mo-stamp { animation: mostamp 1.6s; }
body.ops .mo-sign { animation: mosign 2s; }
body.ops .mo-flare { animation: moflare 2.2s; }
body.ops .spr-g { transform-box: fill-box; }
body.ops .spr-g.mo-bounce { animation: moshake3 1.2s ease-out; }
body.ops .spr-g.mo-sheet { animation: molift 1.4s ease-out; }
@keyframes mobell { 0% { opacity: 0; transform: rotate(0); } 8% { opacity: 1; } 25% { transform: rotate(16deg); } 45% { transform: rotate(-16deg); } 65% { transform: rotate(10deg); } 85% { opacity: 1; transform: rotate(0); } 100% { opacity: 0; } }
@keyframes mocarrier { 0% { opacity: 0; transform: translate(0, 0); } 8% { opacity: 1; } 90% { opacity: 1; } 100% { opacity: 0; transform: translate(300px, 40px); } }
@keyframes mobook { 0% { opacity: 0; transform: translateY(-90px); } 12% { opacity: 1; } 75% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(0); } }
@keyframes mobarrow { 0% { opacity: 0; transform: translateX(0); } 10% { opacity: 1; } 90% { opacity: 1; } 100% { opacity: 0; transform: translateX(160px); } }
@keyframes mowrench { 0% { opacity: 0; transform: translateY(50px); } 10% { opacity: 1; } 85% { opacity: 1; transform: translateY(-70px); } 100% { opacity: 0; transform: translateY(-70px); } }
@keyframes moribbon { 0% { opacity: 0; transform: translateY(0); } 15% { opacity: 1; } 55% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(70px); } }
@keyframes mostamp { 0% { opacity: 0; transform: translateY(-70px); } 25% { opacity: 1; transform: translateY(0); } 40% { transform: translateY(6px); } 55% { transform: translateY(0); } 85% { opacity: 1; } 100% { opacity: 0; } }
@keyframes mosign { 0% { opacity: 0; transform: translateY(30px); } 15% { opacity: 1; transform: translateY(0); } 85% { opacity: 1; } 100% { opacity: 0; } }
@keyframes moflare { 0% { opacity: 0; transform: scale(0.9); } 15% { opacity: 1; transform: scale(1.08); } 40% { transform: scale(1); } 85% { opacity: 1; } 100% { opacity: 0; } }
@keyframes moshake3 { 0%, 100% { transform: translateX(0); } 12% { transform: translateX(3px); } 25% { transform: translateX(-3px); } 37% { transform: translateX(3px); } 50% { transform: translateX(-3px); } }
@keyframes molift { 0%, 100% { transform: translateY(0); } 40% { transform: translateY(-6px); } }
/* Village hotspots and plates, in percent of the 2752 x 1536 map. Generated from village/manifest.json (hit boxes
   already cut so none overlap; label points nudged so no two plates overlap); test_static_page.py checks them. */
body.ops .vh-engine { left: 3.089%; top: 6.836%; width: 21.875%; height: 44.922%; }
body.ops .vh-engine .vp { left: 50.997%; top: 103.478%; transform: translate(-50%, 0); }
body.ops .vh-silo { left: 88.118%; top: 12.695%; width: 9.266%; height: 19.206%; }
body.ops .vh-silo .vp { left: 49.804%; top: 108.136%; transform: translate(-50%, 0); }
body.ops .vh-post { left: 25.073%; top: 19.206%; width: 10.865%; height: 20.638%; }
body.ops .vh-post .vp { left: 51.839%; top: 120.189%; transform: translate(-50%, 0); }
body.ops .vh-library { left: 35.938%; top: 11.068%; width: 12.209%; height: 23.698%; }
body.ops .vh-library .vp { left: 46.726%; top: 110.440%; transform: translate(-50%, 0); }
body.ops .vh-townhall { left: 52.253%; top: 0.326%; width: 20.240%; height: 48.828%; }
body.ops .vh-townhall .vp { left: 56.912%; top: 104.533%; transform: translate(-50%, 0); }
body.ops .vh-notices { left: 45.349%; top: 34.766%; width: 6.904%; height: 12.109%; }
body.ops .vh-notices .vp { left: 49.474%; top: 103.226%; transform: translate(-50%, 0); }
body.ops .vh-hubpro { left: 24.964%; top: 45.247%; width: 18.314%; height: 31.706%; }
body.ops .vh-hubpro .vp { left: 56.151%; top: 108.624%; transform: translate(-50%, 0); }
body.ops .vh-trades { left: 43.278%; top: 49.154%; width: 11.955%; height: 28.971%; }
body.ops .vh-trades .vp { left: 41.641%; top: 105.393%; transform: translate(-50%, 0); }
body.ops .vh-fleet { left: 57.594%; top: 51.432%; width: 12.718%; height: 25.391%; }
body.ops .vh-fleet .vp { left: 50.000%; top: 106.154%; transform: translate(-50%, 0); }
body.ops .vh-shop { left: 71.039%; top: 52.083%; width: 13.445%; height: 29.622%; }
body.ops .vh-shop .vp { left: 50.000%; top: 105.275%; transform: translate(-50%, 0); }
body.ops .vh-gate { left: 0.727%; top: 62.174%; width: 17.260%; height: 37.109%; }
body.ops .vh-gate .vp { left: 50.105%; top: 100.877%; transform: translate(-50%, -100%); }
body.ops .vh-bank { left: 56.686%; top: 76.823%; width: 11.628%; height: 23.177%; }
body.ops .vh-bank .vp { left: 50.000%; top: 42.135%; transform: translate(-50%, 0); }
body.ops .vh-watchtower { left: 35.065%; top: 76.953%; width: 8.176%; height: 23.047%; }
body.ops .vh-watchtower .vp { left: 50.222%; top: 98.305%; transform: translate(-50%, -100%); }
body.ops .vh-yard { left: 43.968%; top: 82.031%; width: 11.628%; height: 17.969%; }
body.ops .vh-yard .vp { left: 25.000%; top: 25.362%; transform: translate(-50%, 0); }
body.ops .vh-angus { left: 71.584%; top: 81.771%; width: 14.535%; height: 18.229%; }
body.ops .vh-angus .vp { left: 50.000%; top: 97.857%; transform: translate(-50%, -100%); }
body.ops .vq-townhall { left: 22.461%; top: 0.488%; width: 54.395%; height: 73.242%; }
body.ops .vq-townhall .vp { left: 56.912%; top: 104.533%; transform: translate(-50%, 0); }
body.ops .vq-notices { left: 3.906%; top: 52.148%; width: 18.555%; height: 18.164%; }
body.ops .vq-notices .vp { left: 49.474%; top: 103.226%; transform: translate(-50%, 0); }
body.ops .vil-panelhost:empty { display: none; }
