:root {
  color-scheme: light;
  --bg: #f6f4ee;
  --surface: #fff;
  --surface-2: #fbfaf5;
  --border: #e5e1d6;
  --border-strong: #c8c2b2;
  --ink-1: #15181b;
  --ink-2: #2a2e33;
  --ink-3: #5a5f66;
  --bistre: #5e4400;
  --saffron: #f2c115;
  --saffron-rgb: 242 193 21;
  --forest: #2d5e3e;
  --crimson: #9a2a2a;
  --font-body: "Source Serif 4", Georgia, serif;
  --font-ui: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* === DISIE Paper — size + space scale =============================
     Single shared scale used by the unified component layer
     (.workflow-steps, .page-header, .surface-card, .page-action-bar,
     .upload-zone, .callout, .stat-tile, .stat-pill). NOT new
     typography — the fonts above stay the only CSS-loaded faces.
     These are just consistent step values so the same H1 / card /
     action bar appears on every one of the seven workflow pages. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 2.5rem;
  --space-8: 3rem;
  --space-10: 4rem;
  --space-12: 6rem;

  /* Heading + body size scale, capped at 2rem. The cap is deliberate:
     no 4rem "AI dashboard" hero. H1 is the same size on upload and on
     final-check. Editorial restraint, journal front-matter feel. */
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-md: 1.0625rem;
  --text-lg: 1.25rem;
  --text-xl: 1.625rem;
  --text-2xl: 2rem;

  --radius-sm: 4px;
  --radius: 8px;
  --radius-paper: 2px;
  --shadow-1: 0 1px 2px rgba(21, 24, 27, 0.04);
  --shadow-2: 0 4px 14px rgba(21, 24, 27, 0.06);

  /* === Block-type palette ============================================
     Used in two places that mirror each other:
       1. The left outline rail (one chip per outline item).
       2. The small per-block badge that sits in the paper's left margin.
     Each type has a -bg, -fg and -border token. Colours are picked to
     sit alongside the DISIE saffron without fighting it: H1 IS the
     saffron, H3 reuses the DISIE forest green, H2 is a slightly
     desaturated journal blue, Tables get a warm rosé and Figures a
     muted teal so all five hues feel printed on cream paper. */
  --type-h1-bg: #f2c115;       /* DISIE saffron */
  --type-h1-fg: #2b2200;
  --type-h1-border: #c79c0c;

  --type-h2-bg: #c9d8ec;       /* soft journal blue */
  --type-h2-fg: #1d3f7a;
  --type-h2-border: #8eaad0;

  --type-h3-bg: #cfe2d5;       /* DISIE forest, tinted for badge bg */
  --type-h3-fg: #1f4a2e;
  --type-h3-border: #82ad94;

  --type-h4-bg: #d4dfd8;       /* deeper green-grey so H4 ≠ Body */
  --type-h4-fg: #2f4234;
  --type-h4-border: #98ac9f;

  --type-t-bg: #f3d8dc;        /* warm rosé */
  --type-t-fg: #7a2e3a;
  --type-t-border: #d49aa6;

  --type-f-bg: #cfe6e3;        /* muted teal */
  --type-f-fg: #1f5a55;
  --type-f-border: #82bcb6;

  --type-l-bg: #ece7da;        /* parchment, ties to the bg */
  --type-l-fg: #5e4400;        /* bistre */
  --type-l-border: #c8b890;

  --type-b-bg: #f1efe9;        /* almost invisible warm grey */
  --type-b-fg: #767069;
  --type-b-border: #d8d3c7;
}

* { box-sizing: border-box; }
body {
  background: linear-gradient(180deg, #fbfaf5 0%, var(--bg) 28rem);
  color: var(--ink-2);
  font: 17px/1.6 var(--font-body);
  margin: 0;
}
a { color: var(--bistre); }

/* === Global HTMX progress bar =====================================
   Thin saffron stripe pinned to the top of the viewport while any
   HTMX request is in flight. Gives the editor a visible "the action
   was received and is processing" signal — and visually anchors the
   page during the brief swap-flash so the eye doesn't read the
   in-between paint as a glitch. Indeterminate sliding animation
   matches the no-fluff aesthetic (no exact-progress claim — htmx
   doesn't know the actual progress; the stripe just confirms work
   is happening).
   The body.htmx-pending class adds a progress cursor so even off-bar
   clicks read as "wait, processing". */
.htmx-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg,
                              rgba(242, 193, 21, 0)   0%,
                              rgba(242, 193, 21, 0.78) 50%,
                              rgba(242, 193, 21, 0)   100%);
  background-size: 35% 100%;
  background-repeat: no-repeat;
  animation: htmxProgressSlide 0.9s cubic-bezier(0.55, 0, 0.45, 1) infinite;
  pointer-events: none;
  z-index: 100;
}
.htmx-progress[hidden] { display: none; }
@keyframes htmxProgressSlide {
  0%   { background-position: -40% 0; }
  100% { background-position: 140% 0; }
}
body.htmx-pending { cursor: progress; }
body.htmx-pending button,
body.htmx-pending a,
body.htmx-pending select { cursor: progress; }

/* === Accessibility utility: visually hidden, screen-reader visible.
   Used when we suppress a visible field label (because it duplicates
   the section heading) but still need a label in the accessibility
   tree so screen-reader users hear what the input is for. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* === Site footer ===================================================
   Legally-required footer (Impressum + Datenschutz, § 5 TMG / DSGVO)
   pinned to the bottom of every page. Sits AFTER <main>; on long
   pages it appears at the natural end of content, on short pages the
   body's min-height pushes it to the bottom of the viewport. The
   build-stamp on the right gives a visual cue which image is live —
   useful when the deploy is automated and there is no other obvious
   signal that origin/main has shipped. */
.site-footer {
  align-items: baseline;
  border-top: 1px solid var(--border);
  color: var(--ink-3);
  display: flex;
  flex-wrap: wrap;
  font: 0.74rem/1.5 var(--font-ui);
  gap: 0.5rem 1.5rem;
  justify-content: space-between;
  margin: 3.5rem auto 0;
  max-width: 1320px;
  padding: 0.9rem 1.5rem 1rem;
}
.site-footer p { margin: 0; }
.footer-legal a {
  color: var(--ink-2);
  text-decoration: none;
  transition: color 0.12s ease;
}
.footer-legal a:hover { color: var(--bistre); text-decoration: underline; }
.footer-build {
  color: var(--ink-3);
  font: 500 0.68rem/1 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.04em;
  opacity: 0.55;
  text-transform: lowercase;
  transition: opacity 0.15s ease;
  user-select: all;
}
.footer-build:hover { opacity: 0.95; }
/* Push footer to the bottom of short pages without making long pages
   scroll past it. body becomes a column flex so <main> can grow to
   fill the available space. */
html, body { min-height: 100vh; }
body { display: flex; flex-direction: column; }
main { flex: 1 0 auto; }

/* === Global focus-visible ring ====================================
   Single brand-consistent focus indicator on every interactive
   element. Keyboard users get an unmistakable cue; mouse users see
   nothing extra (`:focus-visible` rather than `:focus`).
   Saffron-saturated ring with a small offset so it works over
   both white surfaces (forms) and the paper background. */
:focus { outline: none; }
button:focus-visible,
a:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
summary:focus-visible,
[tabindex]:not([tabindex="-1"]):focus-visible {
  outline: 2px solid var(--saffron);
  outline-offset: 2px;
  border-radius: 4px;
}

/* === Mobile / narrow viewport: explicit "desktop required" notice.
   The three-column review workspace doesn't survive narrow screens
   gracefully (sticky 13rem rails stack 200vh below the visible
   area; the editor controls require multi-button hover and
   drag-select). Rather than ship a half-broken mobile experience
   we show a clear stop sign + the desktop URL so the user knows to
   switch devices. Trigger at ≤720px (phone landscape and below). */
@media (max-width: 720px) {
  body::before {
    content: "DISIE Typesetter requires a desktop browser. Please open this page on a laptop or larger screen — the review workspace doesn't fit on mobile.";
    background: var(--saffron);
    color: var(--ink-1);
    display: block;
    font: 600 0.85rem/1.4 var(--font-ui);
    padding: 0.95rem 1.1rem;
    text-align: center;
  }
}
.site-header {
  align-items: center;
  background: rgba(246, 244, 238, 0.95);
  border-bottom: 1px solid var(--border);
  display: flex;
  font-family: var(--font-ui);
  justify-content: space-between;
  min-height: 72px;
  padding: 0 5vw;
  position: sticky;
  top: 0;
  z-index: 10;
}
.brand {
  color: var(--ink-1);
  font-weight: 700;
  text-decoration: none;
}
main { margin: 0 auto; max-width: 1440px; padding: clamp(24px, 4vw, 56px) 5vw; }

/* .asset-intake-screen is the centered wrapper used by intake_tables /
   intake_figures / intake_materials. Layout-only — colour comes from
   the global body inherit now that the dark theme is gone. */
.asset-intake-screen {
  font-family: var(--font-ui);
  margin: 0 auto;
  max-width: 980px;
  width: 100%;
}
.metric-grid {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  margin-bottom: 0.9rem;
}
.metric-grid article,
.analysis-panel,
.asset-confirmation,
.uploaded-strip {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.metric-grid article {
  display: grid;
  gap: 0.45rem;
  min-height: 8rem;
  padding: 1rem;
}
.metric-grid span {
  color: var(--ink-3);
  font: 800 0.72rem/1.2 var(--font-ui);
  text-transform: uppercase;
}
.metric-grid strong {
  color: var(--ink-1);
  font: 800 2.05rem/1 var(--font-ui);
}
.analysis-panels {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: 1fr 1.3fr 0.9fr;
}
.analysis-panel {
  min-height: 16rem;
  padding: 1.1rem;
}
.analysis-panel h2,
.uploaded-strip h2 {
  color: var(--ink-1);
  font: 800 1rem/1.15 var(--font-ui);
  margin: 0 0 0.9rem;
}
.fact-list {
  display: grid;
  gap: 0.7rem 1rem;
  grid-template-columns: minmax(8rem, 0.8fr) minmax(0, 1fr);
}
.fact-list dt {
  color: var(--ink-3);
  font: 700 0.78rem/1.25 var(--font-ui);
}
.fact-list dd {
  color: var(--ink-1);
  font: 760 0.96rem/1.25 var(--font-ui);
  overflow-wrap: anywhere;
}
.detected-split {
  display: grid;
  gap: 0.8rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.detected-split article {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: grid;
  gap: 0.35rem;
  min-height: 11rem;
  padding: var(--space-4);
}
.detected-split strong {
  color: var(--bistre);
  font: 700 3rem/0.95 var(--font-ui);
}
.detected-split span {
  color: var(--ink-1);
  font-weight: 800;
}
.detected-split em {
  color: var(--ink-3);
  font-style: normal;
}
.analysis-panel-quality {
  align-items: center;
  display: grid;
  justify-items: center;
  text-align: center;
}
.quality-ring {
  align-items: center;
  background:
    radial-gradient(circle, var(--surface) 0 58%, transparent 59%),
    conic-gradient(var(--saffron) calc(var(--score) * 1%), var(--border) 0);
  border: 1px solid var(--border);
  border-radius: 50%;
  display: flex;
  height: 9rem;
  justify-content: center;
  width: 9rem;
}
.quality-ring strong {
  color: var(--ink-1);
  font: 700 2.25rem/1 var(--font-ui);
}
.quality-ring span {
  color: var(--ink-3);
  font: 500 0.9rem/1 var(--font-ui);
  margin-left: 0.12rem;
}
.analysis-panel-quality p {
  color: var(--ink-3);
  font: 0.86rem/1.45 var(--font-ui);
  margin: 0.8rem 0 0;
}
/* Footer action bar on analysis.html — alias for the .page-action-bar
   look. The template still calls it .intake-next-bar; Stage 5 may
   migrate it to .page-action-bar once the template is touched. */
.intake-next-bar {
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: flex;
  flex-wrap: wrap;
  font-family: var(--font-ui);
  gap: var(--space-3) var(--space-4);
  justify-content: space-between;
  margin: var(--space-5) 0 var(--space-3);
  padding: var(--space-3) var(--space-4);
}
.intake-next-bar p {
  color: var(--ink-3);
  font: 500 var(--text-sm)/1.4 var(--font-ui);
  margin: 0;
  max-width: 62ch;
}
.intake-next-bar .button-primary { width: auto; }
.asset-confirmation {
  align-content: center;
  display: grid;
  padding: 1rem;
}
.asset-confirmation strong {
  color: var(--ink-1);
  font: 850 1.1rem/1.2 var(--font-ui);
}
.asset-confirmation span {
  color: var(--ink-3);
  font: 0.86rem/1.45 var(--font-ui);
}
.asset-intake-form {
  display: grid;
  gap: 0.75rem;
  grid-template-columns: minmax(0, 1fr);
}
/* Wrapping strip around the .upload-zone + dynamically-inserted
   .asset-item rows on the intake_tables / figures / materials
   pages. The dashed-outline visual lives on .upload-zone itself
   now; this strip is just the surrounding light surface. */
.asset-upload-strip {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: grid;
  gap: var(--space-3);
  padding: var(--space-4);
}
.asset-list {
  display: grid;
  gap: 0.55rem;
}
.asset-item {
  align-items: start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--ink-1);
  display: grid;
  gap: var(--space-3);
  grid-template-columns: 72px minmax(0, 1fr);
  padding: var(--space-3);
}
.asset-thumb {
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: zoom-in;
  display: flex;
  height: 72px;
  justify-content: center;
  margin: 0;
  overflow: hidden;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
  width: 72px;
}
.asset-thumb:hover,
.asset-thumb:focus-visible {
  border-color: var(--border-strong);
  box-shadow: 0 0 0 3px rgba(242, 193, 21, 0.16);
}
.asset-thumb img {
  height: 100%;
  object-fit: contain;
  width: 100%;
}
.asset-thumb span {
  color: var(--ink-3);
  font: 700 0.7rem/1 var(--font-ui);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.asset-thumb.has-table {
  background: var(--surface);
  padding: 0.25rem;
}
.asset-thumb.is-loading {
  cursor: progress;
}
.asset-thumb.is-unavailable {
  cursor: zoom-in;
}
.asset-table-thumb {
  border-collapse: collapse;
  color: #15181b;
  font: 700 0.42rem/1.1 var(--font-ui);
  height: 100%;
  table-layout: fixed;
  width: 100%;
}
.asset-table-thumb td {
  border: 1px solid var(--border-strong);
  max-width: 1rem;
  overflow: hidden;
  padding: 0.1rem;
  text-overflow: clip;
  white-space: nowrap;
}
.asset-fields {
  display: grid;
  gap: 0.5rem;
  min-width: 0;
}
.asset-item-head {
  align-items: end;
  display: grid;
  gap: 0.65rem;
  grid-template-columns: minmax(0, 1fr) minmax(82px, 112px);
}
.asset-item-head-simple {
  align-items: center;
  grid-template-columns: minmax(0, 1fr) auto;
}
.asset-item-head strong {
  color: var(--ink-1);
  font: 850 0.9rem/1.25 var(--font-ui);
  overflow-wrap: anywhere;
}
.asset-number-field,
.asset-field,
.asset-link-panel {
  color: var(--ink-1);
  display: grid;
  gap: 0.28rem;
  font: 750 0.72rem/1.15 var(--font-ui);
}
.asset-link-panel span {
  color: var(--ink-1);
}
.asset-field-stack {
  display: grid;
  gap: 0.55rem;
}
.asset-field-two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.asset-item input,
.asset-item textarea,
.asset-link-panel textarea {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--ink-1);
  font: var(--text-sm)/1.4 var(--font-ui);
  padding: var(--space-2) var(--space-3);
  width: 100%;
}
.asset-item input:focus,
.asset-item textarea:focus,
.asset-link-panel textarea:focus {
  border-color: var(--border-strong);
}
.asset-item input {
  min-height: 2.35rem;
}
.asset-item textarea {
  min-height: 3.05rem;
  resize: vertical;
}
.asset-item input::placeholder,
.asset-item textarea::placeholder,
.asset-link-panel textarea::placeholder {
  color: var(--ink-3);
  opacity: 0.7;
}
.asset-row-meta {
  color: var(--ink-3);
  font: 0.78rem/1.35 var(--font-ui);
  justify-self: end;
  text-align: right;
}
.upload-empty-hint {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--ink-3);
  font: var(--text-sm)/1.4 var(--font-ui);
  margin: 0;
  padding: var(--space-2) var(--space-3);
}
.uploaded-strip {
  margin-top: 0.75rem;
  padding: 0.75rem;
}
.uploaded-strip ol {
  display: grid;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.uploaded-strip li {
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  display: flex;
  gap: 0.8rem;
  justify-content: space-between;
  padding: var(--space-2) var(--space-3);
}
.uploaded-strip strong {
  color: var(--ink-1);
  overflow-wrap: anywhere;
}
.uploaded-strip span {
  color: var(--ink-3);
  font-size: 0.82rem;
  white-space: nowrap;
}
.material-link-field {
  margin-top: 0.2rem;
}
.material-link-field textarea {
  border-radius: 8px;
  font: 0.9rem/1.45 var(--font-ui);
  min-height: 4.6rem;
  padding: 0.85rem;
  resize: vertical;
  width: 100%;
}
/* Save-and-continue strip at the bottom of intake_tables / figures /
   materials. Same visual contract as .page-action-bar — copy on the
   left, button group on the right. */
.asset-action-bar {
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: flex;
  flex-wrap: wrap;
  font-family: var(--font-ui);
  gap: var(--space-3) var(--space-4);
  justify-content: space-between;
  margin: var(--space-5) 0 var(--space-3);
  padding: var(--space-3) var(--space-4);
}
.asset-action-copy h2 {
  color: var(--ink-1);
  font: 600 var(--text-md)/1.2 var(--font-ui);
  margin: 0;
}
.asset-action-copy p {
  color: var(--ink-3);
  font: var(--text-sm)/1.4 var(--font-ui);
  margin: var(--space-1) 0 0;
  max-width: 62ch;
}
.asset-action-buttons {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: flex-end;
}
.asset-action-buttons .button-primary,
.asset-action-buttons .button-secondary {
  width: auto;
}
.asset-action-buttons .button-secondary {
  text-decoration: none;
}
body.asset-preview-open {
  overflow: hidden;
}
.asset-preview-modal[hidden] {
  display: none;
}
.asset-preview-modal {
  align-items: center;
  display: grid;
  inset: 0;
  justify-items: center;
  padding: 1.5rem;
  position: fixed;
  z-index: 1000;
}
.asset-preview-backdrop {
  background: rgba(4, 6, 10, 0.76);
  backdrop-filter: blur(8px);
  inset: 0;
  position: absolute;
}
.asset-preview-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.32);
  color: var(--ink-1);
  display: grid;
  max-height: min(760px, calc(100vh - 3rem));
  overflow: hidden;
  position: relative;
  width: min(980px, calc(100vw - 3rem));
}
.asset-preview-head {
  align-items: center;
  border-bottom: 1px solid var(--border);
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  padding: var(--space-3) var(--space-4);
}
.asset-preview-head h2 {
  color: var(--ink-1);
  font: 600 var(--text-md)/1.2 var(--font-ui);
  margin: 0;
  overflow-wrap: anywhere;
}
.asset-preview-head p {
  color: var(--ink-3);
  font: var(--text-sm)/1.35 var(--font-ui);
  margin: 0.2rem 0 0;
}
.asset-preview-close {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  cursor: pointer;
  font: 600 var(--text-sm)/1 var(--font-ui);
  padding: var(--space-2) var(--space-3);
}
.asset-preview-close:hover {
  background: var(--surface-2);
  color: var(--ink-1);
}
.asset-preview-body {
  display: grid;
  justify-items: center;
  overflow: auto;
  padding: 1rem;
}
.asset-preview-image {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  max-height: calc(100vh - 12rem);
  max-width: 100%;
  object-fit: contain;
}
.asset-table-preview-wrap {
  justify-self: stretch;
  overflow: auto;
  width: 100%;
}
.asset-table-preview {
  background: #fbfaf5;
  border-collapse: collapse;
  color: #15181b;
  font: 0.86rem/1.35 var(--font-ui);
  min-width: min(720px, 100%);
  width: 100%;
}
.asset-table-preview td {
  border: 1px solid #d7d1c2;
  padding: 0.48rem 0.55rem;
  vertical-align: top;
}
.asset-preview-note {
  color: var(--ink-3);
  font: 0.82rem/1.4 var(--font-ui);
  margin: 0.7rem 0 0;
}
.asset-preview-fallback {
  align-content: center;
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  display: grid;
  gap: var(--space-2);
  justify-items: center;
  min-height: 16rem;
  padding: var(--space-5);
  text-align: center;
  width: 100%;
}
.asset-preview-fallback strong {
  color: var(--bistre);
  font: 700 var(--text-xl)/1 var(--font-ui);
}
.asset-preview-fallback p {
  color: var(--ink-3);
  font: 0.9rem/1.45 var(--font-ui);
  margin: 0;
  max-width: 34rem;
}
/* Small-desktop / large-tablet breakpoint. The 720px wall further
   below catches phone-class viewports outright (Desktop-only is the
   deliberate target — see plan and ADR-0008 amendment). This block
   keeps the multi-column intake panels usable on a 13" laptop. */
@media (max-width: 1180px) {
  .analysis-panels {
    grid-template-columns: 1fr;
  }
  .metric-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .detected-split { grid-template-columns: 1fr; }
}
h1, h2, h3 {
  color: var(--ink-1);
  font-weight: 600;
  line-height: 1.1;
  margin: 0 0 0.7rem;
}
h1 { font-size: var(--text-2xl); max-width: 28ch; }
h2 { font-size: var(--text-xl); }
/* "Download the template" callout under the hero copy. Saffron-tinted
   card so it reads as a useful starting-point offer, not a generic
   secondary action. Visible enough for first-time authors to find
   without distracting returning ones. */
.hero-template {
  background: rgba(242, 193, 21, 0.10);
  border: 1px solid rgba(242, 193, 21, 0.45);
  border-left: 3px solid var(--saffron);
  border-radius: 6px;
  margin-top: 1.2rem;
  padding: 0.85rem 1.05rem;
}
/* The landing-page variant now carries two paragraphs (explanation +
   download link). Tighten the inner spacing so they read as one
   block rather than two separate paragraphs with default margins. */
.hero-template > p {
  color: var(--ink-2);
  font: 0.92rem/1.5 var(--font-ui);
  margin: 0 0 0.55rem;
  max-width: 64ch;
}
.hero-template > p:last-child { margin-bottom: 0; }
.hero-template strong { color: var(--ink-1); }
.hero-template-link {
  color: var(--bistre);
  font-weight: 600;
  text-decoration: none;
}
.hero-template-link:hover { text-decoration: underline; }

/* === Landing-page paths (".landing-paths" grid + ".landing-path" card)
   Two large clickable tiles on the typesetter root, one per submission
   kind. Visually parallel but coloured differently so the eye picks
   them apart at a glance: New = saffron accent (the journal's primary
   action colour); Revision = crimson accent (matches the review-stage
   watermark + the "request revisions" status colour elsewhere). The
   tiles are <a>'s so they're full-area clickable and keyboard-focusable
   without extra JS. ============================================== */
.landing-paths {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: var(--space-5) 0 var(--space-4);
}
@media (max-width: 720px) {
  /* Stack the tiles on phones / small windows so each gets the full
     width — the descriptions are 2-3 lines so cramming side-by-side
     gets unreadable below ~720px. */
  .landing-paths { grid-template-columns: 1fr; }
}
.landing-path {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--ink-1);
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: var(--space-5) var(--space-5) var(--space-4);
  text-decoration: none;
  transition: border-color 0.12s ease, background 0.12s ease, transform 0.12s ease;
}
.landing-path:hover,
.landing-path:focus-visible {
  background: #ffffff;
  outline: none;
  transform: translateY(-1px);
}
.landing-path:focus-visible {
  /* Visible focus ring for keyboard users — accent matches the kind. */
  box-shadow: 0 0 0 2px rgba(242, 193, 21, 0.45);
}
.landing-path--new {
  border-left: 4px solid var(--saffron);
}
.landing-path--new:hover,
.landing-path--new:focus-visible { border-color: var(--saffron); }
.landing-path--revise {
  border-left: 4px solid var(--crimson);
}
.landing-path--revise:hover,
.landing-path--revise:focus-visible { border-color: var(--crimson); }
.landing-path--revise:focus-visible {
  box-shadow: 0 0 0 2px rgba(154, 42, 42, 0.40);
}
.landing-path-kind {
  color: var(--ink-3);
  font: 600 0.72rem var(--font-ui);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.landing-path--new .landing-path-kind { color: var(--bistre); }
.landing-path--revise .landing-path-kind { color: var(--crimson); }
.landing-path-title {
  color: var(--ink-1);
  font: 600 1.25rem/1.2 var(--font-body);
  margin: 0;
}
.landing-path-desc {
  color: var(--ink-3);
  font: 0.95rem/1.5 var(--font-ui);
  margin: 0;
  max-width: 50ch;
}
.landing-path-cta {
  color: var(--ink-2);
  font: 600 0.85rem var(--font-ui);
  margin-top: auto;
}
.landing-path--new .landing-path-cta { color: var(--bistre); }
.landing-path--revise .landing-path-cta { color: var(--crimson); }
.landing-template { margin-top: var(--space-5); }

/* === Revision token entry (manual fallback at /revise without ?invite=)
   Simple single-field form for authors who lost the e-mail link. Layout
   matches other inline forms on the typesetter (label above input,
   small help text under, primary CTA below). The aside is the
   "no token? what to do" callout — surface-card with info severity. */
.revise-entry {
  display: grid;
  gap: var(--space-3);
  margin: var(--space-4) 0;
  max-width: 36rem;
}
.revise-entry-field {
  display: grid;
  gap: 0.35rem;
}
.revise-entry-label {
  color: var(--ink-2);
  font: 600 0.78rem var(--font-ui);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.revise-entry-input {
  background: #ffffff;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  font: 0.95rem ui-monospace, "SF Mono", Menlo, monospace;
  padding: 0.55rem 0.75rem;
}
.revise-entry-input:focus-visible {
  border-color: var(--crimson);
  outline: none;
  box-shadow: 0 0 0 2px rgba(154, 42, 42, 0.30);
}
.revise-entry-help {
  color: var(--ink-3);
  font: 0.78rem/1.45 var(--font-ui);
}
.revise-entry-help code {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  font: 0.72rem ui-monospace, "SF Mono", Menlo, monospace;
  padding: 0.05rem 0.3rem;
}
.revise-entry-aside { margin-top: var(--space-4); max-width: 56ch; }
.revise-entry-error {
  /* Surfaces the 403 case at /revise?invite=<bad-token>: the same
     entry form re-renders with this error lede above it instead of
     the optimistic intro copy. Crimson because that's the review-
     stage accent across the typesetter. */
  color: var(--crimson);
  font-weight: 500;
}

/* === Revision landing (/revise?invite=<valid-token>) =================
   Two-card grid: original-.docx download on the left, revised-.docx
   upload on the right. The cards inherit ``surface-card`` so they
   pick up the existing severity rail; we layer revision-specific
   spacing on top. The aside below is for the "post your response in
   Janeway, not here" reminder, styled as a warning so the author
   notices before they paste their response letter into a /revise
   text field that does not exist. */
.revise-header .revise-kind {
  color: var(--crimson);
  font: 700 0.78rem var(--font-ui);
  letter-spacing: 0.08em;
  margin: 0 0 0.45rem;
  text-transform: uppercase;
}
.revise-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: var(--space-5) 0;
}
@media (max-width: 820px) {
  .revise-grid { grid-template-columns: 1fr; }
}
.revise-card {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
.revise-card-heading {
  color: var(--ink-1);
  font: 600 1rem/1.25 var(--font-body);
  margin: 0;
}
.revise-card-help {
  color: var(--ink-3);
  font: 0.88rem/1.5 var(--font-ui);
  margin: 0;
}
.revise-download { align-self: flex-start; }
.revise-upload { display: grid; gap: 0.7rem; }
.revise-aside { margin: var(--space-4) 0; max-width: 70ch; }

.report-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1rem;
}
.report-summary span {
  align-items: baseline;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--ink-3);
  display: inline-flex;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  gap: 0.35rem;
  padding: 0.36rem 0.65rem;
}
.report-summary strong {
  color: var(--ink-1);
}
.asset-manifest-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(21, 24, 27, 0.05);
  margin: 1rem 0;
  padding: 1rem;
}
.asset-manifest-panel > header {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
  justify-content: space-between;
}
.asset-manifest-panel > header strong {
  color: var(--ink-1);
  font-family: var(--font-ui);
}
.asset-manifest-panel > header span {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.82rem;
}
.asset-manifest-grid {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin-top: 0.8rem;
}
.asset-manifest-grid h3 {
  font: 700 0.82rem/1.2 var(--font-ui);
  margin: 0 0 0.45rem;
  text-transform: uppercase;
}
.asset-manifest-grid ol {
  display: grid;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.asset-manifest-grid li {
  border-left: 3px solid var(--border-strong);
  display: grid;
  gap: 0.1rem;
  padding-left: 0.55rem;
}
.asset-manifest-grid li strong,
.asset-manifest-grid li span,
.asset-manifest-grid li em {
  font-family: var(--font-ui);
  font-size: 0.78rem;
}
.asset-manifest-grid li span {
  color: var(--ink-2);
  overflow-wrap: anywhere;
}
.asset-manifest-grid li em {
  color: var(--ink-3);
  font-style: normal;
}
/* Two stateful variants for the single-pill metadata summary —
   "done" turns the border DISIE-forest green, "pending" keeps a
   muted saffron tint so the eye is drawn without alarming. */
.report-summary-pill-done {
  background: rgba(45, 94, 62, 0.07) !important;
  border-color: rgba(45, 94, 62, 0.35) !important;
  color: var(--forest) !important;
}
.report-summary-pill-done strong { color: var(--forest); }
.report-summary-pill-pending {
  background: rgba(242, 193, 21, 0.10) !important;
  border-color: rgba(199, 156, 12, 0.5) !important;
  color: var(--bistre) !important;
}
.report-summary-pill-pending strong { color: var(--bistre); }

/* === Metadata-form blocking errors banner =========================
   Shown when the user submits the metadata form but the validator
   still flags fields the form itself owns (missing author email,
   missing required custom properties, etc.). Keeps the editor on
   /metadata to fix the issues in place instead of bouncing them to
   /report where the same complaint is wrapped in DOCX-style
   boilerplate. */
.metadata-form-errors {
  background: rgba(199, 156, 12, 0.06);
  border: 1px solid rgba(199, 156, 12, 0.45);
  border-left: 4px solid var(--saffron);
  border-radius: 8px;
  margin: 0 0 1.2rem 0;
  padding: 0.9rem 1.1rem;
}
.metadata-form-errors h2 {
  color: var(--bistre);
  font: 600 1.02rem var(--font-ui);
  margin: 0 0 0.3rem 0;
}
.metadata-form-errors-hint {
  color: var(--ink-2);
  font-size: 0.92rem;
  margin: 0 0 0.55rem 0;
}
.metadata-form-errors-list {
  list-style: disc;
  margin: 0;
  padding-left: 1.4rem;
}
.metadata-form-errors-list li {
  color: var(--ink-1);
  font-size: 0.95rem;
  line-height: 1.45;
  margin: 0.2rem 0;
}
.metadata-form-errors-detail {
  color: var(--ink-3);
  margin-left: 0.45rem;
}

/* === Final-check page ============================================
   Step 3 of the workflow — read-only structural overview the user
   scrolls through before rendering. Cards are collapsed by default
   and the one closest to the viewport centre expands (.is-active);
   clicking a card pins it open (.is-pinned). Status icons (✓ / ⚠ /
   ○) give a glance-level pass/fail per item. */

/* Unmatched-citation warning. Sits above the render bar so the editor
   sees orphan (Author, Year) citations BEFORE hitting Render — those
   stay as plain text in the PDF (no DOI / no anchor jump), so we want
   the editor to either add the missing References entry or fix the
   author / year spelling first. Saffron-tinted like the render bar
   border, so visually adjacent to the gate. */
.final-check-warnings {
  background: rgba(199, 122, 0, 0.08);
  border: 1px solid rgba(199, 122, 0, 0.32);
  border-left: 3px solid var(--saffron);
  border-radius: 8px;
  font-family: var(--font-ui);
  margin: 0.4rem 0 1rem;
  padding: 0.75rem 1rem 0.85rem;
}
.final-check-warnings header {
  align-items: center;
  display: flex;
  gap: 0.5rem;
  margin-bottom: 0.3rem;
}
.final-check-warnings h2 {
  color: var(--ink-1);
  font: 600 1.05rem var(--font-body);
  margin: 0;
}
.final-check-warnings p {
  color: var(--ink-2);
  font-size: 0.92rem;
  margin: 0 0 0.5rem;
}
.fc-unmatched-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.25rem;
}
.fc-unmatched-list li {
  align-items: baseline;
  display: flex;
  font-size: 0.9rem;
  gap: 0.5rem;
}
.fc-unmatched-list code {
  background: rgba(0, 0, 0, 0.04);
  border-radius: 3px;
  font-family: var(--font-mono, ui-monospace, monospace);
  padding: 0.05rem 0.35rem;
}
.fc-unmatched-loc {
  color: var(--ink-3, var(--ink-2));
  font-size: 0.82rem;
}

/* Sticky render bar pinned to the top of the page. The bottom copy
   uses the same class minus the sticky positioning for the
   end-of-list duplicate. */
.final-check-render-bar {
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--saffron);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  display: flex;
  flex-wrap: wrap;
  font-family: var(--font-ui);
  gap: var(--space-3) var(--space-4);
  justify-content: space-between;
  margin: var(--space-3) 0 var(--space-5);
  padding: var(--space-3) var(--space-4);
  position: sticky;
  top: 4.5rem;
  z-index: 30;
}
.final-check-render-bar-bottom {
  position: static;
  margin-top: 1.4rem;
  background: var(--surface);
  flex-direction: column;
  align-items: flex-start;
}
.final-check-render-bar .render-form {
  align-items: center;
  display: flex;
  gap: 0.6rem;
  margin: 0;
}

.final-check-list {
  display: grid;
  gap: 0.55rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.fc-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  font-family: var(--font-ui);
  padding: 0.55rem 0.85rem;
  transition: padding 0.25s ease, box-shadow 0.25s ease,
              border-color 0.25s ease, background 0.25s ease;
}
.fc-item.is-active,
.fc-item.is-pinned {
  background: white;
  border-color: var(--border-strong);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.06);
  padding: 0.9rem 1.1rem;
}
.fc-item.is-pinned { border-left: 3px solid var(--saffron); }

.fc-head {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
}
.fc-head .fc-status { margin-left: auto; }

.fc-kind {
  background: var(--type-b-bg);
  border: 1px solid var(--type-b-border);
  border-radius: 3px;
  color: var(--type-b-fg);
  font: 700 0.62rem var(--font-ui);
  letter-spacing: 0.06em;
  min-width: 1.8rem;
  padding: 0.13rem 0.4rem;
  text-align: center;
  text-transform: uppercase;
}
.fc-kind-tbl { background: var(--type-t-bg); border-color: var(--type-t-border); color: var(--type-t-fg); }
.fc-kind-fig { background: var(--type-f-bg); border-color: var(--type-f-border); color: var(--type-f-fg); }
.fc-kind-ref { background: var(--type-l-bg); border-color: var(--type-l-border); color: var(--type-l-fg); }

/* Section card heading level indent — H1 flush left, H2/H3/H4 step
   in 0.6rem each so the structure reads as a tree. */
.fc-head-section.fc-level-1 { padding-left: 0; }
.fc-head-section.fc-level-2 { padding-left: 1rem; }
.fc-head-section.fc-level-3 { padding-left: 2rem; }
.fc-head-section.fc-level-4 { padding-left: 3rem; }
.fc-head-section .fc-kind {
  background: var(--type-h1-bg);
  border-color: var(--type-h1-border);
  color: var(--type-h1-fg);
}
.fc-head-section.fc-level-2 .fc-kind { background: var(--type-h2-bg); border-color: var(--type-h2-border); color: var(--type-h2-fg); }
.fc-head-section.fc-level-3 .fc-kind { background: var(--type-h3-bg); border-color: var(--type-h3-border); color: var(--type-h3-fg); }
.fc-head-section.fc-level-4 .fc-kind { background: var(--type-h4-bg); border-color: var(--type-h4-border); color: var(--type-h4-fg); }

.fc-title {
  color: var(--ink-1);
  font: 600 0.95rem var(--font-ui);
  margin: 0;
}
.fc-subtitle { color: var(--ink-3); font: italic 0.85rem var(--font-body); margin: 0.25rem 0 0.6rem; }

.fc-status {
  align-items: center;
  border-radius: 999px;
  display: inline-flex;
  font: 700 0.78rem var(--font-ui);
  height: 1.4rem;
  justify-content: center;
  min-width: 1.4rem;
  padding: 0 0.35rem;
}
.fc-status-ok   { background: rgba(45, 94, 62, 0.12);  color: var(--forest); }
.fc-status-warn { background: rgba(199, 122, 0, 0.14); color: #8c5500; }

/* Card body — visible only when card is .is-active or .is-pinned.
   Uses max-height transition so the collapse animates smoothly. */
.fc-body {
  color: var(--ink-2);
  font-size: 0.86rem;
  line-height: 1.5;
  margin-top: 0.5rem;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height 0.3s ease, opacity 0.2s ease, margin-top 0.2s ease;
}
.fc-item.is-active .fc-body,
.fc-item.is-pinned .fc-body {
  max-height: 4000px; /* big enough for long tables / ref lists */
  opacity: 1;
  margin-top: 0.6rem;
}

/* Compact body-run row — never expanded; just a thin "N body
   paragraphs" line between structural items. */
.fc-body-run {
  align-items: baseline;
  color: var(--ink-3);
  display: flex;
  gap: 0.5rem;
  font-size: 0.78rem;
  margin: 0;
  padding-left: 1rem;
}

.fc-keyvals {
  display: grid;
  gap: 0.25rem 0.9rem;
  grid-template-columns: 9rem 1fr;
  margin: 0;
}
.fc-keyvals dt { color: var(--ink-3); font-weight: 600; font-size: 0.82rem; }
.fc-keyvals dd { color: var(--ink-1); margin: 0; font-size: 0.85rem; }

.fc-flags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem 0.55rem;
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
}
.fc-flags li {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  font: 600 0.72rem var(--font-ui);
  padding: 0.15rem 0.55rem;
}
.fc-flags li.flag-ok   { color: var(--forest); border-color: rgba(45, 94, 62, 0.35); background: rgba(45, 94, 62, 0.06); }
.fc-flags li.flag-warn { color: #8c5500;       border-color: rgba(199, 122, 0, 0.4); background: rgba(199, 122, 0, 0.08); }
.fc-flags li.flag-info { color: var(--ink-3); }

.fc-issues {
  background: rgba(199, 122, 0, 0.08);
  border-left: 2px solid #c97a00;
  border-radius: 3px;
  color: #8c5500;
  font-size: 0.82rem;
  list-style: disc inside;
  margin: 0.4rem 0;
  padding: 0.4rem 0.7rem;
}
.fc-warn { color: #8c5500; font-style: italic; font-size: 0.82rem; }

/* Table thumbnail inside the figure card. We reuse the paper-table
   APA styling but shrunk so it doesn't dominate the card. */
.fc-table-thumb {
  background: var(--surface-2);
  border-radius: 4px;
  margin-top: 0.5rem;
  overflow-x: auto;
  padding: 0.55rem 0.75rem;
}
.fc-table-thumb table {
  border-collapse: collapse;
  border-top: 2px double var(--ink-1);
  border-bottom: 1px solid var(--ink-1);
  font: 0.78rem/1.35 var(--font-body);
  width: 100%;
  table-layout: fixed;
}
.fc-table-thumb th,
.fc-table-thumb td {
  border: 0;
  overflow-wrap: break-word;
  padding: 0.3rem 0.45rem;
  text-align: left;
  vertical-align: top;
}
.fc-table-thumb tr.is-header th,
.fc-table-thumb tr.is-header td {
  font-weight: 600;
  text-align: center;
}
.fc-table-thumb tr.is-header:not(:has(+ tr.is-header)) th,
.fc-table-thumb tr.is-header:not(:has(+ tr.is-header)) td {
  border-bottom: 1px solid var(--ink-1);
}
.fc-table-truncated {
  color: var(--ink-3);
  font: italic 0.75rem var(--font-ui);
  margin: 0.4rem 0 0;
}

.fc-note {
  color: var(--ink-2);
  font: italic 0.82rem var(--font-body);
  margin: 0.5rem 0 0;
}
.fc-note em { color: var(--ink-3); font-style: normal; font-weight: 600; }

.fc-subtle { color: var(--ink-3); font: 500 0.72rem var(--font-ui); letter-spacing: 0.04em; margin: 0.5rem 0 0.2rem; text-transform: uppercase; }
.fc-refs-list {
  color: var(--ink-2);
  font: 0.82rem/1.45 var(--font-body);
  margin: 0 0 0.3rem;
  padding-left: 1.6rem;
}
.fc-refs-list li { margin-bottom: 0.2rem; }
.fc-refs-all {
  background: var(--surface-2);
  border-radius: 4px;
  margin-top: 0.5rem;
  padding: 0.5rem 0.7rem;
}
.fc-refs-all summary { cursor: pointer; color: var(--ink-1); font: 600 0.82rem var(--font-ui); }
.fc-refs-all ol {
  color: var(--ink-2);
  font: 0.8rem/1.45 var(--font-body);
  margin: 0.4rem 0 0;
  padding-left: 1.6rem;
}

/* === Render-status page === */
/* Replaces the previous bare-bones meta-refresh page. While the
   worker is preparing the PDF the panel shows a small spinner and a
   "back to review" escape hatch; on success the download buttons
   take over; on failure we print the worker's error message in a
   readable pre block plus a "back to review" link to retry. */
.render-status-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--forest);
  border-radius: 8px;
  margin: 1rem 0;
  padding: 1.1rem 1.2rem;
  font-family: var(--font-ui);
}
.render-status-panel[data-status="failed"] { border-left-color: var(--crimson); }
.render-status-panel[data-status="rendered"] { border-left-color: var(--forest); }
.render-status-message,
.render-status-hint,
.render-status-ok,
.render-status-failed { margin: 0.45rem 0; }
.render-status-message { color: var(--ink-2); font-size: 0.95rem; }
.render-status-hint    { color: var(--ink-3); font-size: 0.82rem; }
.render-status-ok      { color: var(--forest); font-weight: 600; font-size: 1rem; }
.render-status-failed  { color: var(--crimson); font-weight: 600; font-size: 1rem; }
.render-status-error {
  background: #fcf3f3;
  border: 1px solid #f1c4c8;
  border-radius: 6px;
  color: var(--crimson);
  font: 0.78rem/1.4 ui-monospace, Menlo, monospace;
  margin: 0.7rem 0;
  max-height: 16rem;
  overflow-y: auto;
  padding: 0.6rem 0.8rem;
  white-space: pre-wrap;
}
.render-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.8rem;
}
.render-actions a { text-decoration: none; }
.render-downloads {
  display: grid;
  gap: 1.4rem;
  margin-top: 1rem;
}
.render-download-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem 1.1rem;
}
.render-download-group h2 {
  color: var(--ink-1);
  font: 600 1rem var(--font-ui);
  margin: 0 0 0.35rem;
}
.render-download-hint {
  color: var(--ink-3);
  font: 0.85rem/1.4 var(--font-ui);
  margin: 0 0 0.4rem;
}
.render-actions-verify { margin-top: 0.4rem; }

/* === Finalise / submit hero (post-render) ===========================
   This is the visual climax of the workflow: render is done, the
   author downloads the signed bundle, then clicks Submit. The two
   primary CTAs sit in a numbered ordered list so the order itself
   communicates the gate (download → unlocks → submit). State chips
   on each step ("not downloaded yet" / "downloaded", "download the
   bundle first" / "ready to submit") narrate what the JS gating
   is doing so the editor never wonders why Submit is greyed out. */
.render-finalise {
  background: #ffffff;
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--saffron);
  border-radius: 8px;
  padding: 1.2rem 1.4rem 1.4rem;
}
.render-finalise-heading {
  color: var(--ink-1);
  font: 700 1.15rem/1.2 var(--font-body);
  margin: 0 0 0.55rem;
}
.render-finalise-hint {
  color: var(--ink-2);
  font: 0.92rem/1.5 var(--font-ui);
  margin: 0 0 1.1rem;
  max-width: 64ch;
}
.render-finalise-hint code {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  font: 0.82rem ui-monospace, "SF Mono", Menlo, monospace;
  padding: 0 0.3rem;
}
.render-finalise-steps {
  display: grid;
  gap: 0.95rem;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: render-step;
}
.render-finalise-steps > li {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin: 0;
  padding: 0;
}
.render-finalise-download,
.render-finalise-submit {
  /* Both CTAs share the same visual weight — Submit is the goal,
     Download is the unlock. The disabled state on Submit communicates
     the dependency. */
  font-size: 0.95rem;
  min-width: 18rem;
  padding: 0.55rem 1.05rem;
  text-decoration: none;
}
.render-finalise-submit:disabled,
.render-finalise-submit[aria-disabled="true"] {
  background: #ecead8;
  border-color: #d4d0c0;
  color: #a39d8a;
  cursor: not-allowed;
}
.render-finalise-step-state {
  color: var(--ink-3);
  font: italic 0.82rem var(--font-ui);
}
.render-finalise-step-state.is-done,
.render-finalise-step-state.is-ready {
  color: var(--forest);
  font-style: normal;
  font-weight: 600;
}
.render-finalise-handoff-off {
  color: var(--ink-3);
  font: 0.85rem/1.5 var(--font-ui);
  margin: 0;
  max-width: 64ch;
}
.render-finalise-handoff-off code {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  font: 0.78rem ui-monospace, "SF Mono", Menlo, monospace;
  padding: 0 0.3rem;
}

/* Collapsible "Inspect individual files" details below the hero —
   secondary affordance so authors who want to spot-check a single
   variant don't have to unzip the bundle. */
.render-individual-files {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.4rem 1rem;
}
.render-individual-files > summary {
  color: var(--ink-2);
  cursor: pointer;
  font: 600 0.88rem var(--font-ui);
  list-style: revert;
  padding: 0.45rem 0;
}
.render-individual-files[open] > summary { margin-bottom: 0.6rem; }
.render-individual-grid {
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
  margin: 0 0 0.6rem;
}
.render-individual-grid .render-download-group {
  background: #ffffff;
  padding: 0.8rem 0.95rem;
}
.render-individual-grid .render-download-group h3 {
  color: var(--ink-1);
  font: 600 0.92rem var(--font-ui);
  margin: 0 0 0.3rem;
}

.render-hint {
  color: var(--ink-3);
  font: 0.82rem/1.35 var(--font-ui);
  margin: 0 0 0.6rem;
}
/* Spinner — small ring that rotates while the worker runs. We use
   conic-gradient + transform so there's no GIF/SVG dependency. */
.render-spinner {
  background: conic-gradient(from 0deg, var(--saffron), rgba(242, 193, 21, 0.08));
  border-radius: 50%;
  display: inline-block;
  height: 28px;
  margin-right: 0.55rem;
  vertical-align: middle;
  width: 28px;
  position: relative;
  animation: render-spin 1.2s linear infinite;
}
.render-spinner::after {
  content: "";
  background: var(--surface);
  border-radius: 50%;
  inset: 4px;
  position: absolute;
}
@keyframes render-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
.analysis-banner {
  align-items: baseline;
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--forest);
  border-radius: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 0.8rem;
  margin-top: 0.85rem;
  padding: 0.7rem 0.85rem;
}
.analysis-banner strong {
  color: var(--forest);
  font-family: var(--font-ui);
  font-size: 0.9rem;
}
.analysis-banner span {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.88rem;
}
.flash {
  border-radius: 8px;
  border: 1px solid var(--border);
  font-family: var(--font-ui);
  font-size: 0.9rem;
  margin: 0.9rem 0;
  padding: 0.7rem 0.9rem;
}
.flash-info { border-left: 3px solid var(--forest); background: var(--surface); }
.flash-warn { border-left: 3px solid #c97a00; background: #fff8eb; }
.flash strong { color: var(--ink-1); }
.flash ul { margin: 0.45rem 0 0; padding-left: 1.1rem; }
.flash code { background: var(--surface); padding: 0 0.25rem; border-radius: 3px; }
.side-effect-panel .hint { color: var(--ink-3); margin-top: 0.4rem; }

.revision-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  /* Forest (action / success) rather than wine-red. The revision
     stack is a positive thing — a record of successful edits the
     user can roll back. Wine-red read as "alert!" stacked next
     to the post-Accept "Repair applied." flash. */
  border-left: 3px solid var(--forest);
  border-radius: 8px;
  margin: 0.85rem 0;
  padding: 0.75rem 0.95rem;
}
.revision-panel header { display: flex; justify-content: space-between; gap: 0.6rem; flex-wrap: wrap; }
.revision-panel header strong { font-family: var(--font-ui); color: var(--ink-1); }
.revision-panel header span { color: var(--ink-3); font-size: 0.85rem; }
.revision-panel details { margin-top: 0.55rem; }
.revision-panel details summary { cursor: pointer; color: var(--ink-2); font-size: 0.9rem; }
.revision-panel ul { margin: 0.45rem 0 0 1.1rem; padding: 0; }
.revision-panel li { margin: 0.4rem 0; }
.revision-panel .muted { color: var(--ink-3); }
.revision-actions { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin-top: 0.7rem; }
.revision-actions .hint { color: var(--ink-3); font-size: 0.82rem; }
.button-danger {
  background: #8b3a3a;
  color: white;
  border: 0;
  padding: 0.45rem 0.85rem;
  border-radius: 6px;
  font-family: var(--font-ui);
  font-size: 0.88rem;
  cursor: pointer;
}
.button-danger:hover { background: #6f2c2c; }

.manual-dismiss {
  margin-top: 1rem;
  padding: 0.8rem 0.95rem;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: var(--surface);
}
.manual-dismiss h3 { margin: 0 0 0.3rem; font-family: var(--font-ui); font-size: 0.95rem; }
.manual-dismiss .hint { color: var(--ink-3); font-size: 0.85rem; margin-bottom: 0.5rem; }
.dismiss-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  padding: 0.3rem 0;
}
.dismiss-row code { background: white; padding: 0.05rem 0.3rem; border-radius: 3px; }
.dismiss-row button {
  background: transparent;
  color: var(--ink-2);
  border: 1px solid var(--border);
  padding: 0.25rem 0.55rem;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.82rem;
}
.dismiss-row button:hover { background: white; }

button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.upload-panel, .preflight-grid article, .issue, .verify-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(21, 24, 27, 0.06);
}
.upload-panel {
  display: grid;
  gap: 1.1rem;
  padding: 1.25rem;
}
.upload-wizard {
  align-content: start;
}
.upload-step {
  border-top: 1px solid var(--border);
  display: grid;
  gap: 0.85rem;
  padding-top: 1rem;
}
.upload-step:first-of-type {
  border-top: 0;
  padding-top: 0;
}
.upload-step header {
  align-items: start;
  display: grid;
  gap: 0.7rem;
  grid-template-columns: auto minmax(0, 1fr);
}
.upload-step h2 {
  font: 700 0.95rem/1.2 var(--font-ui);
  margin: 0 0 0.15rem;
}
.upload-step p {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  line-height: 1.45;
  margin: 0;
}
.upload-step-index {
  align-items: center;
  background: var(--saffron);
  border-radius: 999px;
  color: var(--ink-1);
  display: inline-flex;
  font: 700 0.82rem/1 var(--font-ui);
  height: 1.65rem;
  justify-content: center;
  width: 1.65rem;
}
.asset-rows {
  display: grid;
  gap: 0.75rem;
}
.asset-row {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  display: grid;
  gap: 0.75rem;
  padding: 0.85rem;
}
.asset-row header {
  align-items: end;
  display: grid;
  gap: 0.75rem;
  grid-template-columns: minmax(0, 1fr) minmax(90px, 120px);
}
.asset-row strong {
  color: var(--ink-1);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  overflow-wrap: anywhere;
}
.upload-empty-hint {
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  border-radius: 8px;
  padding: 0.7rem 0.8rem;
}
label {
  color: var(--ink-1);
  display: grid;
  font-family: var(--font-ui);
  font-size: 0.88rem;
  font-weight: 700;
  gap: 0.45rem;
}
input[type="file"], input[type="text"], select {
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  color: var(--ink-3);
  font: 0.9rem var(--font-ui);
  padding: 0.7rem;
  width: 100%;
}
.upload-panel textarea {
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  color: var(--ink-3);
  font: 0.9rem/1.45 var(--font-ui);
  padding: 0.7rem;
  resize: vertical;
  width: 100%;
}
button, .button {
  align-items: center;
  background: var(--saffron);
  border: 0;
  border-radius: 6px;
  color: var(--ink-1);
  cursor: pointer;
  display: inline-flex;
  font: 700 0.92rem var(--font-ui);
  justify-content: center;
  min-height: 44px;
  padding: 0.7rem 1rem;
  text-decoration: none;
}
.secondary {
  background: var(--surface);
  border: 1px solid var(--border-strong);
}
.preflight-grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 1.5rem 0;
}
.preflight-grid article, .verify-box { padding: 1.2rem; }
dl {
  display: grid;
  gap: 0.55rem 1rem;
  grid-template-columns: 160px 1fr;
}
dt {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  font-weight: 700;
}
dd { margin: 0; }
.issue-list { margin: 1.5rem 0; }
.issue, .repair-card {
  border-left: 3px solid var(--crimson);
  margin: 0.6rem 0;
  padding: 0.85rem;
}
.issue.warning { border-left-color: var(--bistre); }
.issue.suggestion { border-left-color: var(--forest); }
.repair-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--forest);
  border-radius: 8px;
  box-shadow: 0 1px 0 rgba(21, 24, 27, 0.03);
}
.repair-card.medium { border-left-color: var(--bistre); }
.repair-card.none { border-left-color: var(--ink-3); }
.issue-top {
  align-items: center;
  display: flex;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  gap: 1rem;
  justify-content: space-between;
}
.issue-top span,
.issue-top a {
  color: var(--ink-3);
  font-size: 0.8rem;
  font-weight: 600;
}
.fix {
  background: var(--surface-2);
  border-top: 1px solid var(--border);
  color: var(--ink-1);
  margin: 0.8rem -1rem -1rem;
  padding: 0.8rem 1rem;
}
.why-matters {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  margin-top: 0.45rem;
}
.issue-debug {
  font-family: var(--font-ui);
  font-size: 0.78rem;
  margin-top: 0.7rem;
}
.issue-debug summary {
  color: var(--ink-3);
  cursor: pointer;
}
.issue-debug dl {
  display: grid;
  grid-template-columns: 9rem 1fr;
  gap: 0.3rem 0.7rem;
  margin: 0.6rem 0 0;
}
.issue-debug dt { color: var(--ink-3); font-weight: 600; }
.issue-debug dd { color: var(--ink-2); }
.issue-debug code {
  background: var(--surface-2);
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  padding: 0.05rem 0.35rem;
}
.block-issues {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
}
.block-issues li {
  font-family: var(--font-ui);
  font-size: 0.82rem;
  padding: 0.15rem 0;
}
.document-map {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-family: var(--font-ui);
  margin-bottom: 1.4rem;
  padding: 0.45rem 0.65rem;
}
.document-map ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.map-row {
  align-items: baseline;
  border-bottom: 1px solid var(--border);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 0.6rem;
  padding: 0.55rem 0.25rem;
}
.map-row:last-child { border-bottom: 0; }
.map-row a, .map-row > span:first-child {
  color: var(--ink-1);
  font-weight: 600;
  text-decoration: none;
}
.map-row.empty > span:first-child { color: var(--ink-3); font-weight: 500; }
.map-row a:hover { text-decoration: underline; }
.map-status {
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  padding: 0.15rem 0.55rem;
  text-transform: uppercase;
}
.map-row.status-valid .map-status            { background: rgba(45, 94, 62, 0.12); color: var(--forest); }
.map-row.status-needs_style_fix .map-status  { background: rgba(94, 68, 0, 0.12); color: var(--bistre); }
.map-row.status-unsupported_style .map-status{ background: rgba(154, 42, 42, 0.12); color: var(--crimson); }
.map-row.status-missing .map-status          { background: rgba(154, 42, 42, 0.12); color: var(--crimson); }
.map-row.status-incomplete .map-status       { background: rgba(94, 68, 0, 0.12); color: var(--bistre); }
.map-row.status-auto_fix_available .map-status { background: rgba(242, 193, 21, 0.25); color: var(--ink-1); }
.map-count {
  color: var(--ink-3);
  font-size: 0.78rem;
}
.map-sublist {
  color: var(--crimson);
  font-size: 0.78rem;
  grid-column: 1 / -1;
  list-style: disc;
  margin: 0.3rem 0 0 1.1rem;
}
.sticky-head-secondary { margin-top: 0.6rem; }
.style-mapping {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-family: var(--font-ui);
  margin: 0.5rem 0 1.2rem;
  padding: 0.8rem 0.9rem 0.4rem;
}
.style-mapping h3 { font-size: 0.95rem; margin: 0 0 0.25rem; }
.style-mapping .hint { color: var(--ink-3); font-size: 0.82rem; margin: 0 0 0.6rem; }
.style-mapping table { border-collapse: collapse; font-size: 0.85rem; width: 100%; }
.style-mapping th, .style-mapping td {
  border-bottom: 1px solid var(--border);
  padding: 0.45rem 0.4rem;
  text-align: left;
  vertical-align: top;
}
.style-mapping th { color: var(--ink-3); font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase; }
.style-mapping code {
  background: var(--surface-2);
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
  padding: 0.05rem 0.35rem;
}
.style-mapping tr.kind-citation_manager td:first-child code { color: var(--crimson); }
.badge {
  background: rgba(94, 68, 0, 0.12);
  border-radius: 999px;
  color: var(--bistre);
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 700;
  margin-left: 0.35rem;
  padding: 0.05rem 0.45rem;
  text-transform: uppercase;
}
.paragraph-list summary { color: var(--ink-3); cursor: pointer; font-size: 0.78rem; }
.paragraph-list span { color: var(--ink-3); font-size: 0.78rem; }
.mapping-toggle { align-items: center; display: flex; gap: 0.35rem; font-size: 0.82rem; }
.metadata-form-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--saffron);
  border-radius: 10px;
  font-family: var(--font-ui);
  margin-bottom: 1.4rem;
  padding: 0.7rem 1rem 1rem;
}
.metadata-form-panel summary {
  align-items: center;
  cursor: pointer;
  display: flex;
  font-size: 1.05rem;
  font-weight: 700;
  gap: 0.8rem;
  justify-content: space-between;
  list-style: none;
}
.metadata-form-panel summary::-webkit-details-marker { display: none; }
.metadata-form-panel .hint { color: var(--ink-3); font-size: 0.88rem; margin: 0.4rem 0 0.6rem; }
.meta-status { border-radius: 999px; font-size: 0.72rem; padding: 0.15rem 0.55rem; }
.meta-status.ok  { background: rgba(45, 94, 62, 0.12); color: var(--forest); }
.meta-status.bad { background: rgba(154, 42, 42, 0.12); color: var(--crimson); }
.metadata-form { display: grid; gap: 0.85rem; margin-top: 0.5rem; }
.metadata-workspace {
  align-items: start;
  display: grid;
  gap: clamp(1rem, 2.4vw, 2rem);
  grid-template-columns: minmax(380px, 0.72fr) minmax(420px, 1fr);
}
.metadata-page-form {
  display: grid;
  gap: 0.9rem;
  min-width: 0;
}
.metadata-section {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: grid;
  gap: 0.8rem;
  padding: 1rem;
}
.metadata-section h2 {
  border-bottom: 1px solid var(--border);
  font-family: var(--font-ui);
  font-size: 1rem;
  margin: 0;
  padding-bottom: 0.55rem;
}
.form-field { display: grid; gap: 0.25rem; }
.field-label { color: var(--ink-1); font-size: 0.92rem; font-weight: 600; }
/* Required-field marker. Neutral ink-3 grey rather than crimson —
   crimson is reserved exclusively for validation FAILURES, not for
   "this field is required". */
.field-label em { color: var(--ink-3); font-style: normal; font-weight: 700; }
.form-field input,
.form-field select,
.form-field textarea {
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  font: inherit;
  padding: 0.45rem 0.55rem;
}
.form-field textarea { font-family: var(--font-body); min-height: 2.4rem; resize: vertical; }
.field-hint { color: var(--ink-3); font-size: 0.78rem; }
.field-hint em { color: var(--ink-3); font-style: italic; font-weight: 500; }
.field-why { color: var(--ink-3); font-size: 0.74rem; font-style: italic; }
.metadata-form button { justify-self: start; margin-top: 0.4rem; }
.metadata-actions {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.65rem;
}
.titlepage-preview {
  min-width: 0;
  position: sticky;
  top: 88px;
}
.paper-preview {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 12px 28px rgba(21, 24, 27, 0.08);
  color: var(--ink-1);
  font-size: 0.92rem;
  line-height: 1.45;
  padding: clamp(1.1rem, 2vw, 1.7rem);
}
.paper-preview h2 {
  font-size: clamp(1.45rem, 2.1vw, 2.15rem);
  line-height: 1.15;
  margin-bottom: 0.8rem;
}
.paper-preview h3 {
  font-family: var(--font-ui);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  margin: 1rem 0 0.35rem;
  text-transform: uppercase;
}
.paper-preview p { margin: 0.2rem 0; }
.paper-preview dl {
  font-size: 0.85rem;
  grid-template-columns: 5.5rem 1fr;
}
.article-kicker,
.titlepage-short,
.orcid-line,
.muted {
  color: var(--ink-3);
  font-family: var(--font-ui);
}
.article-kicker {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.preview-author {
  margin-bottom: 0.65rem;
}
.preview-author:last-child {
  margin-bottom: 0;
}
.paper-preview .is-empty {
  color: #8b7f6b;
  font-style: italic;
}
.orcid-line { font-size: 0.8rem; }
.repair-preview {
  background: var(--surface-2);
  border-radius: 6px;
  display: grid;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  gap: 0.2rem 0.7rem;
  grid-template-columns: 5rem 1fr;
  margin: 0.7rem 0 0;
  padding: 0.55rem 0.7rem;
}
.repair-preview dt { color: var(--ink-3); font-weight: 600; }
.repair-preview dd { color: var(--ink-1); margin: 0; word-break: break-word; }
.repair-preview .before { color: var(--ink-3); text-decoration: line-through; }
.repair-preview .after  { color: var(--forest); font-weight: 600; }
.action-note { color: var(--ink-3); font-size: 0.78rem; margin-top: 0.55rem; }
.readiness-sticky {
  position: sticky;
  top: 0;
  z-index: 50;
  background: white;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-ui);
  margin: 0.5rem 0 0.8rem;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}
.readiness-sticky summary {
  align-items: center;
  cursor: pointer;
  display: flex;
  gap: 0.75rem;
  list-style: none;
  padding: 0.45rem 0.85rem;
}
.readiness-sticky summary::-webkit-details-marker { display: none; }
.readiness-sticky-score strong {
  color: var(--ink-1);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
}
.readiness-sticky-of { color: var(--ink-3); font-size: 0.78rem; margin-left: 0.1rem; }
.readiness-sticky-bar {
  background: var(--border);
  border-radius: 999px;
  flex: 1;
  height: 6px;
  max-width: 14rem;
  overflow: hidden;
}
.readiness-sticky-bar > span {
  background: var(--forest);
  display: block;
  height: 100%;
}
.readiness-needs_fixes .readiness-sticky-bar > span,
.readiness-needs_fixes .readiness-sticky-score strong { color: var(--bistre); }
.readiness-not_ready .readiness-sticky-bar > span,
.readiness-not_ready .readiness-sticky-score strong { color: var(--crimson); }
.readiness-almost_ready .readiness-sticky-bar > span { background: var(--saffron); }
.readiness-needs_fixes  .readiness-sticky-bar > span { background: var(--bistre); }
.readiness-not_ready    .readiness-sticky-bar > span { background: var(--crimson); }
.readiness-sticky-label {
  color: var(--ink-2);
  font-size: 0.85rem;
  flex: 0 1 auto;
}
.readiness-sticky-caret {
  color: var(--ink-3);
  font-size: 0.85rem;
  margin-left: auto;
  transition: transform 0.15s ease;
}
.readiness-sticky[open] .readiness-sticky-caret { transform: rotate(180deg); }
.readiness-areas-compact {
  border-top: 1px solid var(--border);
  display: grid;
  gap: 0.4rem 1rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  list-style: none;
  margin: 0;
  padding: 0.5rem 0.85rem 0.7rem;
}
@media (max-width: 720px) { .readiness-areas-compact { grid-template-columns: 1fr; } }
.readiness-areas-compact .readiness-area {
  align-items: center;
  background: transparent;
  display: grid;
  gap: 0.5rem;
  grid-template-columns: 9rem 1fr 2.5rem;
  padding: 0.2rem 0;
}
.readiness-areas-compact .area-title { font-size: 0.82rem; font-weight: 500; }
.readiness-areas-compact .area-score { color: var(--ink-3); font-size: 0.78rem; text-align: right; }
.readiness-areas-compact .area-bar {
  background: var(--border);
  border-radius: 999px;
  display: block;
  height: 5px;
  overflow: hidden;
}
.readiness-areas-compact .area-bar > span { background: var(--forest); display: block; height: 100%; }
.readiness-areas-compact .score-mid .area-bar > span { background: var(--saffron); }
.readiness-areas-compact .score-low .area-bar > span { background: var(--crimson); }

.readiness {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  font-family: var(--font-ui);
  margin: 1rem 0 1.4rem;
  padding: 1rem 1.1rem 0.8rem;
}
.readiness header {
  align-items: center;
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  margin-bottom: 0.7rem;
}
.readiness h2 { font-size: 1rem; margin: 0; }
.readiness-status {
  color: var(--ink-3);
  font-size: 0.9rem;
  margin: 0.15rem 0 0;
}
.readiness-score strong {
  color: var(--ink-1);
  font-size: 2.1rem;
  font-weight: 800;
  line-height: 1;
}
.readiness-score span { color: var(--ink-3); font-size: 0.95rem; margin-left: 0.15rem; }
.readiness-ready       { border-left: 3px solid var(--forest); }
.readiness-almost_ready{ border-left: 3px solid var(--saffron); }
.readiness-needs_fixes { border-left: 3px solid var(--bistre); }
.readiness-not_ready   { border-left: 3px solid var(--crimson); }
.readiness-areas {
  display: grid;
  gap: 0.7rem 1rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (max-width: 720px) { .readiness-areas { grid-template-columns: 1fr; } }
.readiness-area { background: var(--surface-2); border-radius: 8px; padding: 0.55rem 0.7rem; }
.area-head {
  align-items: baseline;
  display: flex;
  justify-content: space-between;
}
.area-title { font-size: 0.88rem; font-weight: 600; }
.area-score { color: var(--ink-3); font-size: 0.82rem; }
.area-bar { background: var(--border); border-radius: 999px; height: 6px; margin-top: 0.35rem; overflow: hidden; }
.area-bar span { background: var(--forest); display: block; height: 100%; }
.readiness-area.score-mid .area-bar span { background: var(--saffron); }
.readiness-area.score-low .area-bar span { background: var(--crimson); }
.area-note { color: var(--ink-3); font-size: 0.76rem; margin: 0.35rem 0 0; }
.ok { color: var(--forest); }
.bad { color: var(--crimson); }
.manual-only {
  color: var(--crimson);
  font-family: var(--font-ui);
  font-size: 0.9rem;
}
.repair-card p {
  margin: 0.65rem 0 0;
}
.repair-card label + label {
  margin-top: 0.55rem;
}
.repair-workspace {
  align-items: start;
  display: grid;
  gap: clamp(1rem, 2.4vw, 2rem);
  grid-template-columns: minmax(0, 1.18fr) minmax(340px, 0.82fr);
}
.doc-preview, .issue-inspector {
  min-width: 0;
}
.sticky-head {
  align-items: center;
  background: rgba(246, 244, 238, 0.96);
  border-bottom: 1px solid var(--border);
  display: flex;
  gap: 0.8rem;
  justify-content: space-between;
  margin-bottom: 0.85rem;
  padding: 0.45rem 0 0.65rem;
  position: sticky;
  top: 73px;
  z-index: 2;
}
.sticky-head h2 { margin: 0; }
.issue-inspector .sticky-head {
  background: rgba(246, 244, 238, 0.98);
}
.missing-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--bistre);
  border-radius: var(--radius);
  margin: 0 0 0.85rem;
  padding: 0;
}
.missing-panel summary {
  align-items: center;
  cursor: pointer;
  display: flex;
  font-family: var(--font-ui);
  gap: 0.8rem;
  justify-content: space-between;
  list-style: none;
  padding: 0.65rem 0.8rem;
}
.missing-panel summary::-webkit-details-marker { display: none; }
.missing-panel summary span {
  font-family: var(--font-ui);
  font-size: 0.9rem;
  font-weight: 700;
}
.missing-panel summary strong {
  align-items: center;
  background: var(--bistre);
  border-radius: 999px;
  color: #fff;
  display: inline-flex;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  height: 1.55rem;
  justify-content: center;
  min-width: 1.55rem;
  padding: 0 0.45rem;
}
.missing-list {
  border-top: 1px solid var(--border);
  display: grid;
  gap: 0.25rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  max-height: 15rem;
  overflow: auto;
  padding: 0.75rem 0.8rem;
}
.missing-list a {
  font-family: var(--font-ui);
  font-size: 0.84rem;
}
.preview-blocks {
  display: grid;
  gap: 0.65rem;
}
.preview-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 4px solid transparent;
  border-radius: 8px;
  padding: 0.82rem 0.9rem;
}
.preview-block.role-title {
  border-left-color: var(--forest);
  padding-block: 1.1rem;
}
.preview-block.role-title p {
  color: var(--ink-1);
  font-size: clamp(1.75rem, 2.4vw, 2.55rem);
  font-weight: 700;
  line-height: 1.12;
}
.preview-block.role-subtitle p {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 1.05rem;
}
.preview-block.role-heading-1,
.preview-block.role-heading-2,
.preview-block.role-heading-3 {
  background: linear-gradient(180deg, #ffffff 0%, var(--surface-2) 100%);
}
.preview-block.role-heading-1 p,
.preview-block.role-heading-2 p,
.preview-block.role-heading-3 p {
  color: var(--ink-1);
  font-family: var(--font-ui);
  font-weight: 800;
  line-height: 1.2;
}
.preview-block.role-heading-1 p { font-size: 1.35rem; }
.preview-block.role-heading-2 p { font-size: 1.18rem; }
.preview-block.role-heading-3 p { font-size: 1.02rem; }
.preview-block.role-caption p,
.preview-block.role-declaration p,
.preview-block.role-reference p {
  font-family: var(--font-ui);
  font-size: 0.92rem;
}
.preview-block.role-caption p {
  color: var(--bistre);
  font-weight: 700;
}
.preview-block.role-reference {
  background: var(--surface-2);
}
.preview-block.role-reference p {
  padding-left: 1.4rem;
  text-indent: -1.4rem;
}
.preview-block.role-code p {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9rem;
}
.preview-block:target,
.issue:target,
.repair-card:target {
  outline: 3px solid rgba(242, 193, 21, 0.65);
  outline-offset: 2px;
}
.preview-block.error { border-left-color: var(--crimson); }
.preview-block.warning { border-left-color: var(--bistre); }
.preview-block.suggestion { border-left-color: var(--forest); }
.block-meta {
  color: var(--ink-3);
  display: flex;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 700;
  gap: 0.6rem;
  justify-content: space-between;
  text-transform: uppercase;
}
.preview-block p { margin: 0.35rem 0 0; }
.preview-block ul {
  border-top: 1px solid var(--border);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  margin: 0.7rem 0 0;
  padding: 0.65rem 0 0 1rem;
}
.structure {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem 1rem 1rem 2.5rem;
}
.structure li { border-bottom: 1px solid var(--border); padding: 0.55rem 0; }
.structure li:last-child { border-bottom: 0; }
.structure span {
  color: var(--bistre);
  display: inline-block;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 700;
  margin-right: 0.8rem;
  min-width: 80px;
  text-transform: uppercase;
}
.render-form, .actions { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-top: 1.5rem; }
.check {
  align-items: center;
  display: flex;
  gap: 0.55rem;
}
@media (max-width: 820px) {
  .hero, .preflight-grid, .repair-workspace, .metadata-workspace, .asset-manifest-grid { grid-template-columns: 1fr; }
  .asset-row header { grid-template-columns: 1fr; }
  h1 { max-width: none; }
  dl { grid-template-columns: 1fr; }
  .sticky-head { position: static; }
}

/* === Title page preview inside report.html === */
.titlepage-report {
  background: white;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 0.9rem 0;
  padding: 0;
  font-family: var(--font-ui);
}
.titlepage-report > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.55rem 0.85rem;
  border-bottom: 1px solid var(--border);
}
.titlepage-report > summary::-webkit-details-marker { display: none; }
.titlepage-report > summary::before {
  content: "▸";
  color: var(--ink-3);
  margin-right: 0.25rem;
  transition: transform 0.15s ease;
}
.titlepage-report[open] > summary::before { transform: rotate(90deg); }
.titlepage-report > summary strong { font-size: 0.95rem; }
.titlepage-report > summary .muted { color: var(--ink-3); font-size: 0.82rem; }
.titlepage-report .titlepage-paper { padding: 1rem 1.2rem; font-size: 0.85rem; }
.titlepage-report .titlepage-paper h2 { font-size: 1.4rem; margin: 0.4rem 0; }
.titlepage-report .titlepage-paper h3 {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  margin: 0.9rem 0 0.3rem;
}
.titlepage-report .article-kicker {
  color: var(--ink-3);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 0;
}
.titlepage-report .titlepage-short { color: var(--ink-3); font-size: 0.82rem; }
.titlepage-report .preview-author { margin: 0.3rem 0; }
.titlepage-report .preview-author p { margin: 0; }
.titlepage-report .orcid-line { color: var(--ink-2); font-size: 0.82rem; }
.titlepage-report .muted { color: var(--ink-3); }
.titlepage-report dl {
  display: grid;
  grid-template-columns: 6rem 1fr;
  gap: 0.2rem 0.6rem;
  margin: 0.3rem 0 0;
}
.titlepage-report dt { color: var(--ink-3); font-weight: 600; }
.titlepage-report dd { margin: 0; }

/* === Metadata ↔ body merge decisions === */
.merge-panel {
  background: #fff8eb;
  border: 1px solid #f1c573;
  border-left: 3px solid #c97a00;
  border-radius: 8px;
  margin: 0.9rem 0;
  padding: 0.85rem 1rem 0.95rem;
}
.merge-panel > header { margin-bottom: 0.55rem; }
.merge-panel > header strong { font-family: var(--font-ui); }
.merge-panel .hint { color: var(--ink-2); font-size: 0.88rem; margin: 0.2rem 0 0; }
.merge-card {
  background: white;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.7rem 0.9rem;
  margin-top: 0.6rem;
}
.merge-card h3 { font-family: var(--font-ui); font-size: 0.95rem; margin: 0 0 0.25rem; }
.merge-status { color: var(--ink-3); font-size: 0.84rem; margin: 0 0 0.55rem; }
.merge-options {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem;
}
@media (max-width: 720px) { .merge-options { grid-template-columns: 1fr; } }
.merge-option {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.5rem 0.65rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.merge-source-label {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.78rem;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.merge-option blockquote {
  background: white;
  border-left: 3px solid var(--border);
  margin: 0;
  padding: 0.4rem 0.6rem;
  color: var(--ink-1);
  font-size: 0.88rem;
  max-height: 6rem;
  overflow: auto;
  white-space: pre-wrap;
}
.merge-option button {
  align-self: flex-start;
  background: var(--ink-1);
  color: white;
  border: 0;
  padding: 0.35rem 0.7rem;
  border-radius: 5px;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  cursor: pointer;
}
.merge-option button:hover { background: var(--forest); }

/* === Compact metadata summary on report page === */
.metadata-summary {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.95rem;
  margin: 0.85rem 0;
}
.metadata-summary header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.metadata-summary header strong { font-family: var(--font-ui); }
.metadata-summary .meta-status {
  font-size: 0.82rem;
  margin-left: 0.5rem;
}
.metadata-summary .meta-status.ok { color: var(--forest); }
.metadata-summary .meta-status.bad { color: #c97a00; }


/* ============================================================ */
/* Review page — two-column workspace                            */
/* Left: the paper (PDF-like preview, page 1 = title page)        */
/* Right: comments pane (Google-Docs-style suggestions)           */
/* ============================================================ */

/* Override the default narrow main width so the workspace breathes. */
body:has(.workspace) main { max-width: 1480px; }

/* Compact status strip — sticky at the top of the workspace.
   Designed to fade into the page chrome unless the user is actually
   looking at it: thin row, small type, small buttons. */
.status-banner {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  font-family: var(--font-ui);
  margin: 0.3rem 0 0.7rem;
  padding: var(--space-3) var(--space-4);
  position: sticky;
  top: 4.5rem;
  z-index: 50;
}
.status-banner.status-ready { border-left: 3px solid var(--forest); }
.status-banner.status-work  { border-left: 3px solid #c97a00; }
.status-main {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  justify-content: space-between;
}
.status-text {
  align-items: baseline;
  display: flex;
  flex: 1 1 auto;
  flex-wrap: wrap;
  gap: 0.45rem;
  min-width: 0;
}
.status-text strong { color: var(--ink-1); font-size: 0.86rem; font-weight: 600; }
.status-text span   { color: var(--ink-3); font-size: 0.78rem; }
.status-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }
.inline-form { display: inline; margin: 0; }
/* Render form when status is ready: anonymize checkbox sits next to
   the Render button. The anonymized path strips author names and
   affiliations from the rendered PDF — used for double-blind peer
   review. We surface it inline rather than on a separate page so
   the user picks the mode at the exact moment they hit Render. */
.render-form {
  align-items: center;
  display: inline-flex;
  gap: 0.55rem;
  margin: 0;
}
.render-anonymize {
  align-items: center;
  color: var(--ink-2);
  cursor: pointer;
  display: inline-flex;
  font: 500 0.76rem var(--font-ui);
  gap: 0.3rem;
  user-select: none;
}
.render-anonymize input { accent-color: var(--forest); }
/* === Button system ============================================
   Three classes, one role each:
     .button-primary    — the page's main CTA (saffron, brand)
     .button-secondary  — supportive / parallel action (white + border)
     .button-danger     — destructive (crimson) — defined further up
   .button-tiny-secondary is the small footprint variant used inside
   the style-mapping table in the advanced view. The default bare
   `<button>` rule near the top of the stylesheet still works as a
   visually "primary" fallback for forms that haven't picked a
   modifier — the colour matches .button-primary so the hierarchy
   stays consistent. */
.button-primary, .button-secondary, .button-tiny-secondary {
  align-items: center;
  border: 1px solid transparent;
  border-radius: 5px;
  cursor: pointer;
  display: inline-flex;
  font: 600 0.78rem var(--font-ui);
  justify-content: center;
  min-height: 0;
  padding: 0.3rem 0.7rem;
}
.button-primary {
  background: var(--saffron);
  color: var(--ink-1);
  border-color: var(--type-h1-border);
}
.button-primary:hover:not(:disabled) { background: #e3b30b; }
.button-primary:disabled {
  background: #ecead8;
  color: #a39d8a;
  border-color: #d4d0c0;
  cursor: not-allowed;
}
.button-secondary { background: white; color: var(--ink-2); border-color: var(--border-strong); }
.button-secondary:hover { background: var(--surface); color: var(--ink-1); }
.button-tiny-secondary {
  background: white;
  border-color: var(--border-strong);
  color: var(--ink-2);
  font-size: 0.72rem;
  padding: 0.22rem 0.55rem;
}
.button-tiny-secondary:hover { background: var(--surface); color: var(--ink-1); }
.status-progress { align-items: center; display: flex; gap: 0.45rem; margin-top: 0.3rem; }
.status-progress-bar { background: var(--border); border-radius: 999px; display: block; flex: 0 0 11rem; height: 3px; overflow: hidden; }
.status-progress-bar > span { background: var(--forest); display: block; height: 100%; }
.status-progress-label { color: var(--ink-3); font-size: 0.72rem; }

/* === Inline blocking-error list ====================================
   Shown inside the status banner when the gate blocks but the comments
   pane has nothing to act on (every blocking error is either a manual
   fix the user hasn't dismissed yet, or a Word-only fix the validator
   surfaced without a repair card). Without this the user reads
   "N issues blocking render" and has no idea what they are. */
.blocking-errors-inline {
  background: white;
  border: 1px solid var(--border);
  border-left: 3px solid #c97a00;
  border-radius: 6px;
  margin-top: 0.6rem;
  padding: 0.55rem 0.8rem 0.6rem;
}
.blocking-errors-inline > summary {
  color: var(--ink-1);
  cursor: pointer;
  font: 600 0.82rem var(--font-ui);
  list-style: none;
  padding: 0.05rem 0;
}
.blocking-errors-inline > summary::-webkit-details-marker { display: none; }
.blocking-errors-inline[open] > summary { margin-bottom: 0.5rem; }
.blocking-errors-inline ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.blocking-errors-inline li {
  border-top: 1px solid var(--border);
  padding: 0.45rem 0;
  font-size: 0.8rem;
  display: grid;
  grid-template-columns: auto auto 1fr;
  gap: 0.3rem 0.55rem;
  align-items: baseline;
}
.blocking-errors-inline li:first-child { border-top: 0; padding-top: 0.1rem; }
.blocking-rule {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  color: var(--ink-2);
  font: 600 0.7rem ui-monospace, "SF Mono", Menlo, monospace;
  padding: 0.05rem 0.35rem;
}
.blocking-anchor {
  color: var(--bistre);
  font: 500 0.74rem var(--font-ui);
  text-decoration: none;
}
.blocking-anchor:hover { text-decoration: underline; }
.blocking-message {
  color: var(--ink-1);
  grid-column: 3 / -1;
}
.blocking-fix {
  color: var(--ink-3);
  display: block;
  font: italic 0.76rem/1.45 var(--font-body);
  grid-column: 1 / -1;
  margin-top: 0.15rem;
}
.blocking-errors-inline p.hint {
  border-top: 1px solid var(--border);
  color: var(--ink-3);
  font: 0.76rem/1.45 var(--font-ui);
  margin: 0.5rem 0 0;
  padding-top: 0.5rem;
}

/* === Workspace: outline · paper · comments (three columns) === */
.workspace {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr) 380px;
  gap: 1.5rem;
  align-items: start;
  margin: 1.5rem 0 2.5rem;
}
@media (max-width: 1320px) {
  .workspace { grid-template-columns: 130px minmax(0, 1fr) 360px; gap: 1.2rem; }
}
@media (max-width: 1180px) {
  .workspace {
    grid-template-columns: 1fr;
  }
  .paper-outline { display: none; }
}

/* === Document outline (left rail) === */
/* Sits below the sticky status banner. --rails-top is updated by JS
   (setupRailsTop in report.html) to match the actual banner +
   revert-panel + side-effect-panel stack height, so the rails
   always start right under whatever banner stack is currently
   rendered. Fallback of 13rem covers the typical "banner only"
   case during the first paint before JS runs. */
.paper-outline {
  font-family: var(--font-ui);
  position: sticky;
  top: var(--rails-top, 13rem);
  max-height: calc(100vh - var(--rails-top, 13rem) - 1rem);
  overflow-y: auto;
}
.paper-outline-header {
  color: var(--ink-3);
  font: 600 0.7rem var(--font-ui);
  letter-spacing: 0.08em;
  margin: 0 0 0.4rem;
  padding-left: 0.2rem;
  text-transform: uppercase;
}
.paper-outline-list {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.outline-item {
  align-items: center;
  background: white;
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--ink-2);
  cursor: pointer;
  display: flex;
  flex-wrap: wrap;
  font: 600 0.78rem var(--font-ui);
  gap: 0.15rem 0.4rem;
  padding: 0.32rem 0.55rem;
  transition: opacity 0.2s ease, box-shadow 0.2s, border-color 0.2s;
}
.outline-item:hover { border-color: var(--ink-3); }
.outline-tag {
  flex: 1 1 auto;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.outline-sub {
  color: var(--ink-3);
  flex: 0 0 100%;
  font: 500 0.68rem var(--font-ui);
  letter-spacing: 0.02em;
}
.outline-sub em { font-style: normal; margin-right: 0.1rem; }
.outline-count {
  color: var(--ink-3);
  font: 500 0.7rem ui-monospace, Menlo, monospace;
  margin-left: auto;
}

/* Per-type colours — mirrored on the paper badges so the rail and the
   paper share one visual language. */
.outline-item.is-h1 { background: var(--type-h1-bg); border-color: var(--type-h1-border); color: var(--type-h1-fg); }
.outline-item.is-h2 { background: var(--type-h2-bg); border-color: var(--type-h2-border); color: var(--type-h2-fg); }
.outline-item.is-h3 { background: var(--type-h3-bg); border-color: var(--type-h3-border); color: var(--type-h3-fg); }
.outline-item.is-h4 { background: var(--type-h4-bg); border-color: var(--type-h4-border); color: var(--type-h4-fg); }
.outline-item.is-t  { background: var(--type-t-bg);  border-color: var(--type-t-border);  color: var(--type-t-fg); }
.outline-item.is-f  { background: var(--type-f-bg);  border-color: var(--type-f-border);  color: var(--type-f-fg); }
.outline-item.is-l  { background: var(--type-l-bg);  border-color: var(--type-l-border);  color: var(--type-l-fg); }
.outline-item.is-b  { background: var(--type-b-bg);  border-color: var(--type-b-border);  color: var(--type-b-fg); }

/* Heading hierarchy indent — deeper headings step right so the
   document's structure is visible at a glance. H1 stays flush;
   H2 / H3 / H4 each add 8px of left padding. The template emits
   `outline-level-N` on every heading outline item. */
.outline-item.outline-level-1 { padding-left: 0.55rem; }
.outline-item.outline-level-2 { padding-left: 0.95rem; }
.outline-item.outline-level-3 { padding-left: 1.35rem; }
.outline-item.outline-level-4 { padding-left: 1.75rem; }

/* Visibility state — driven by IntersectionObserver. We dropped the
   "magnet-pull" translateX experiment: items now hold their column
   position and just dim/brighten. The currently-topmost visible item
   gets a stronger border + a soft shadow so the eye can find it. */
.outline-item.is-past     { opacity: 0.45; }
.outline-item.is-upcoming { opacity: 0.78; }
.outline-item.is-visible  { opacity: 1; }
.outline-item.is-current {
  opacity: 1;
  border-color: var(--ink-1);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 4px 10px rgba(0, 0, 0, 0.08);
  z-index: 2;
}

/* === Per-block type badge on the paper ============================
   A small chip that sits in the paper's left margin next to each
   structural block. Colours mirror the outline rail. We render it
   via ::before on every paper-page-body block so no template change
   is needed beyond a "data-type" attribute.

   The paper has 5rem of horizontal padding; the badge sits 3.5rem
   left of the text edge, comfortably inside the margin gutter. */
.paper-page-body .paper-h1,
.paper-page-body .paper-h2,
.paper-page-body .paper-h3,
.paper-page-body .paper-h4,
.paper-page-body .paper-p,
.paper-page-body .paper-quote,
.paper-page-body .paper-reference,
.paper-page-body .paper-figcaption,
.paper-page-body .paper-fignote,
.paper-page-body .paper-tablecaption,
.paper-page-body .paper-tablenote,
.paper-page-body .paper-table,
.paper-page-body .paper-figure {
  position: relative;
}
.paper-page-body [data-type-badge]::before {
  content: attr(data-type-badge);
  position: absolute;
  left: -3.2rem;
  top: 0.05rem;
  background: var(--badge-bg, var(--type-b-bg));
  color: var(--badge-fg, var(--type-b-fg));
  border: 1px solid var(--badge-border, var(--type-b-border));
  border-radius: 3px;
  font: 700 0.6rem/1 var(--font-ui);
  letter-spacing: 0.04em;
  padding: 0.18rem 0.32rem;
  min-width: 1.55rem;
  text-align: center;
  pointer-events: none;
  user-select: none;
  white-space: nowrap;
  text-transform: uppercase;
}
/* Body badge: extra-quiet by default; sharpens on hover so the user can
   still confirm a block's type without it shouting from the margin. */
.paper-page-body .paper-p[data-type-badge]::before,
.paper-page-body .paper-reference[data-type-badge]::before {
  opacity: 0.35;
  transition: opacity 0.15s ease;
}
.paper-page-body .paper-p:hover[data-type-badge]::before,
.paper-page-body .paper-reference:hover[data-type-badge]::before { opacity: 0.85; }

/* Collapse runs of identical kinds. A body paragraph that follows
   another body paragraph reuses the badge from the first one in the
   group — visually the "body block" becomes a single big body, not a
   ladder of dim B chips. Same for consecutive reference entries
   (the ref list shows one "Ref" badge for the whole bibliography). */
.paper-page-body .paper-p + .paper-p[data-type-badge]::before,
.paper-page-body .paper-reference + .paper-reference[data-type-badge]::before {
  display: none;
}

.paper-page-body .paper-h1 { --badge-bg: var(--type-h1-bg); --badge-fg: var(--type-h1-fg); --badge-border: var(--type-h1-border); }
.paper-page-body .paper-h2 { --badge-bg: var(--type-h2-bg); --badge-fg: var(--type-h2-fg); --badge-border: var(--type-h2-border); }
.paper-page-body .paper-h3 { --badge-bg: var(--type-h3-bg); --badge-fg: var(--type-h3-fg); --badge-border: var(--type-h3-border); }
.paper-page-body .paper-h4 { --badge-bg: var(--type-h4-bg); --badge-fg: var(--type-h4-fg); --badge-border: var(--type-h4-border); }
.paper-page-body .paper-table,
.paper-page-body .paper-tablecaption,
.paper-page-body .paper-tablenote { --badge-bg: var(--type-t-bg); --badge-fg: var(--type-t-fg); --badge-border: var(--type-t-border); }
.paper-page-body .paper-figure,
.paper-page-body .paper-figcaption,
.paper-page-body .paper-fignote,
.paper-page-body .paper-placeholder-figure { --badge-bg: var(--type-f-bg); --badge-fg: var(--type-f-fg); --badge-border: var(--type-f-border); }
.paper-page-body .paper-placeholder-table { --badge-bg: var(--type-t-bg); --badge-fg: var(--type-t-fg); --badge-border: var(--type-t-border); }
.paper-page-body .paper-reference { --badge-bg: var(--type-l-bg); --badge-fg: var(--type-l-fg); --badge-border: var(--type-l-border); }
.paper-page-body .paper-p,
.paper-page-body .paper-quote { --badge-bg: var(--type-b-bg); --badge-fg: var(--type-b-fg); --badge-border: var(--type-b-border); }

/* === Inline placeholder paragraphs ================================
   "### Figure 1: HLM Model 1 ###" / "<<< INSERT TABLE 6 >>>" lines.
   Detected by the validator + flagged by build_preview with a
   placeholder_kind field. We render them in a muted dashed box with
   the figure / table family accent colour so it visually reads as
   "structural marker, not heading / not body" even when the Word
   style under the hood is DISIE Heading 1 (Markdown auto-format) or
   plain Body. Goes with the "Upload Figure N image" / "Upload
   Table N (.docx)" card in the comments rail. */
.paper-placeholder {
  background: var(--surface);
  border: 1.5px dashed var(--border-strong);
  border-radius: 4px;
  color: var(--ink-2);
  font: italic 0.95em/1.45 var(--font-body);
  margin: 0.6em 0;
  padding: 0.55em 0.85em;
}
.paper-placeholder-figure {
  border-color: var(--type-f-border);
  background: rgba(207, 230, 227, 0.18); /* tinted with --type-f-bg */
}
.paper-placeholder-table {
  border-color: var(--type-t-border);
  background: rgba(243, 216, 220, 0.18); /* tinted with --type-t-bg */
}

/* On narrower viewports the paper padding shrinks — pull the badge
   inside the text column as a small inline chip instead of into a
   margin that no longer exists. */
@media (max-width: 720px) {
  .paper-page-body [data-type-badge]::before {
    position: static;
    display: inline-block;
    margin-right: 0.4rem;
    transform: translateY(-1px);
  }
}

/* Margin indicator for paragraphs that have at least one suggestion
   on the comments rail. Renders a thin warm-saffron mark on the right
   edge of the block via the `data-has-comment` attribute emitted by
   the template. The user gets a quiet "there's a card for this one"
   cue without having to read the column. */
.paper-page-body [data-has-comment]::after {
  content: "";
  position: absolute;
  right: -2.25rem;
  top: 0.25rem;
  bottom: 0.25rem;
  width: 3px;
  background: var(--saffron);
  border-radius: 2px;
  opacity: 0.55;
  pointer-events: none;
}
.paper-page-body [data-has-comment]:hover::after { opacity: 0.95; }

/* === The paper itself ============================================
   The base font is set in *pixels* and child element sizes are mostly
   em-based, so the whole paper scales as one. 13px ≈ 10pt — the body
   size used in the final DISIE production PDF — so the on-screen
   review looks like the printed galley rather than a draft. */
.paper {
  --paper-width: 720px;
  display: flex;
  flex-direction: column;
  /* Larger inter-page gap with a faux "page-break" stripe between
     sheets — the editor sees two distinct A4 surfaces, not one long
     scroll. The gap doubled from 1.8rem to 3.2rem so each page reads
     as a separate piece of paper. */
  gap: 3.2rem;
  font: 13px/1.55 var(--font-body);
  color: var(--ink-1);
  margin: 0 auto;
  width: 100%;
  max-width: var(--paper-width);
}

.paper-page {
  background: white;
  border: 1px solid var(--border);
  border-radius: 2px;
  /* Sharper, darker shadow than the original 0.08 alpha — the page
     now visibly lifts off the workspace background so the gap between
     pages reads as physical separation, not just margin. */
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.13), 0 4px 10px rgba(0, 0, 0, 0.07);
  padding: 4.2rem 5rem 5.5rem;
  position: relative;
  /* No forced min-height. Sheets size to their actual content; pages
     paginated server-side may legitimately be shorter than a full
     A4 (the last body page often is). Forcing 950px just to look
     "A4-like" created a stretch of empty whitespace below short
     pages AND, on overfilled heading-heavy pages, made it visually
     unclear where the sheet ended — content overflowed past the
     fake page edge and the editor reported text "spilling past the
     end". The "— next page —" chip between siblings still signals
     where one logical page ends and the next begins. */
}
/* Page-break indicator: a thin centred chip that sits in the gap
   between two pages and labels the next sheet ("— page 2 —"). Only
   shown between siblings so the first page has no chip above it. */
.paper-page + .paper-page::before {
  content: "— next page —";
  position: absolute;
  top: -2rem;
  left: 50%;
  transform: translateX(-50%);
  color: var(--ink-3);
  font: 600 0.65rem var(--font-ui);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--bg, white);
  padding: 0.1rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  pointer-events: none;
}
@media (max-width: 720px) {
  .paper-page { padding: 2rem 1.5rem 2.5rem; min-height: 0; }
}
.page-number-marker {
  position: absolute;
  top: 0.7rem;
  left: 1.2rem;
  color: var(--ink-3);
  font: 600 0.7rem var(--font-ui);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.6;
  margin: 0;
}

/* === Page 1: title page === */
.paper-page-titlepage .titlepage-inner {
  align-items: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 800px;
  text-align: center;
}
.paper-kicker {
  color: var(--ink-3);
  font: 600 0.8rem var(--font-ui);
  letter-spacing: 0.1em;
  margin: 0 0 1.2rem;
  text-transform: uppercase;
}
.paper-title {
  color: var(--ink-1);
  font: 700 1.95rem/1.25 var(--font-body);
  margin: 0 0 0.8rem;
  max-width: none;
  text-wrap: balance;
}
.paper-short-title {
  color: var(--ink-3);
  font: italic 0.92rem var(--font-body);
  margin: 0 0 2.5rem;
}
.paper-authors { margin: 1.5rem 0 0.8rem; }
.paper-author { font: 1rem/1.5 var(--font-body); margin: 0.6rem 0; }
.paper-author-name { color: var(--ink-1); font-weight: 600; }
.paper-author-orcid { color: var(--forest); font: 500 0.82rem var(--font-ui); }
.paper-author-affil { color: var(--ink-3); font: italic 0.88rem var(--font-body); }
.paper-correspondence { color: var(--ink-3); font: 0.88rem var(--font-body); margin: 1.5rem 0 2rem; }
.paper-declarations {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  display: grid;
  font: 0.85rem var(--font-ui);
  gap: 0.28rem 0.9rem;
  grid-template-columns: 5.5rem 1fr;
  margin: 1.5rem auto 0;
  max-width: 28rem;
  padding: 0.7rem 1rem;
  text-align: left;
}
.paper-declarations dt { color: var(--ink-3); font-weight: 600; }
.paper-declarations dd { color: var(--ink-1); margin: 0; }

/* === Page 2+: body =================================================
   Single-column screen layout mirroring the print spec
   (Schaffer-Boone-style journal density): 10pt-equivalent body,
   line-height 1.2, compact H1 12pt bold / H2 12pt italic / H3
   11pt bold, justified + hyphenated. Em-based so the whole tree
   scales as one. */
.paper-page-body {
  padding-top: 3rem;
  position: relative;
  font-size: 0.92em; /* 13px base → ~10pt feel */
  line-height: 1.2;
}
.paper-page-body > * { margin: 0; }
/* Classic journal-galley paragraph: first-line indent, no
   after-spacing. First paragraph after a heading / abstract /
   table / figure has no indent (parent block is the cue). */
.paper-p {
  text-align: justify;
  hyphens: auto;
  margin: 0;
  text-indent: 1.2em;
}
.paper-page-body h2.paper-h1 + .paper-p,
.paper-page-body h3.paper-h2 + .paper-p,
.paper-page-body h4.paper-h3 + .paper-p,
.paper-page-body h5.paper-h4 + .paper-p,
.paper-page-body .paper-abstract-heading + .paper-p,
.paper-page-body figure + .paper-p,
.paper-page-body table + .paper-p,
.paper-page-body .paper-tablenote + .paper-p,
.paper-page-body .paper-fignote + .paper-p {
  text-indent: 0;
}
/* Compact heading hierarchy matching Schaffer-Boone: small,
   close-to-body sizes that read as journal section labels rather
   than draft document outlines. */
.paper-page-body h2.paper-h1 {
  font: 700 1.18em/1.25 var(--font-body);
  margin: 1.3em 0 0.4em;
  max-width: none;
  text-align: left;
}
.paper-page-body h3.paper-h2 {
  font: 700 italic 1.18em/1.25 var(--font-body);
  margin: 1.1em 0 0.35em;
  text-align: left;
}
.paper-page-body h4.paper-h3 {
  font: 700 1.05em/1.25 var(--font-body);
  margin: 0.9em 0 0.3em;
  text-align: left;
}
.paper-page-body h5.paper-h4 {
  /* Legacy H4 fallback — same look as H3. */
  font: 700 1.05em/1.25 var(--font-body);
  margin: 0.9em 0 0.3em;
  text-align: left;
  color: var(--ink-1);
  padding-left: 0;
}
.paper-abstract-heading {
  color: var(--ink-3);
  font: 600 0.78em var(--font-ui);
  letter-spacing: 0.08em;
  margin: 2em 0 0.4em;
  text-transform: uppercase;
}
.paper-abstract {
  font: 0.92em/1.3 var(--font-body);
  text-align: justify;
  margin: 0 0.8em 0.8em;
}
.paper-keywords {
  color: var(--ink-2);
  font: italic 0.92em var(--font-body);
  margin: 0.3em 0.8em 1.2em;
}
.paper-keywords em { color: var(--ink-3); }
/* Block quote per spec: 10pt-equivalent, indented L/R, no quote
   marks, no italic. */
.paper-quote {
  color: var(--ink-2);
  font: 0.92em/1.35 var(--font-body);
  margin: 0.6em 0.8em;
  padding: 0;
  text-align: justify;
}
/* Reference entry per spec: 10pt-equivalent, hanging indent 5mm
   (≈ 0.5em), line-height 1.2, 3pt (≈ 0.25em) between entries. */
.paper-reference {
  font: 0.92em/1.2 var(--font-body);
  padding-left: 0.5em;
  text-indent: -0.5em;
  margin: 0 0 0.25em;
}
.paper-code {
  background: var(--surface);
  border-radius: 4px;
  font: 0.85em/1.45 ui-monospace, "SF Mono", Menlo, monospace;
  overflow-x: auto;
  padding: 0.6em 0.85em;
}
/* DISIE List Bullet / List Number — render as hanging-indent
   paragraphs with the marker (• or "1.") in the gutter. Word stores
   the bullet/number as paragraph formatting, not as text content, so
   python-docx strips it and the preview used to render bullets as
   plain bodies. preview.py computes block.list_marker; the template
   prepends it via <span class="paper-list-marker">. */
.paper-list {
  margin: 0.2em 0;
  padding-left: 1.6em;
  text-indent: 0;
}
.paper-list-marker {
  color: var(--ink-3);
  display: inline-block;
  font-variant-numeric: tabular-nums;
  margin-left: -1.6em;
  text-align: right;
  width: 1.3em;
  padding-right: 0.3em;
}
.paper-list-number .paper-list-marker {
  color: var(--ink-2);
  font-weight: 600;
}
/* APA-7 caption: sits ABOVE the figure / table, left-aligned, italic. */
.paper-figcaption, .paper-tablecaption {
  color: var(--ink-2);
  font: italic 0.9em/1.3 var(--font-body);
  margin: 0.3em 0 0.4em;
  text-align: left;
}
/* APA-7 note: sits BELOW the figure / table, left-aligned. Body
   text is regular weight; "Note." prefix is italic. */
.paper-fignote, .paper-tablenote {
  color: var(--ink-2);
  font: 0.9em/1.3 var(--font-body);
  margin: 0.3em 0 0.8em;
  text-align: left;
}
.paper-fignote::before, .paper-tablenote::before {
  color: var(--ink-2);
  content: "Note. ";
  font-style: italic;
  font-weight: 400;
  margin-right: 0.15em;
}
.paper-fignote.has-prefix::before, .paper-tablenote.has-prefix::before { content: ""; }
/* APA 7 table style: no vertical borders, double rule above the
   header rows, single rule below the LAST header row, single rule
   at the bottom of the body. Caption sits as .paper-tablecaption
   above, note as .paper-tablenote below — both already styled. */
.paper-table {
  border-collapse: collapse;
  border-top: 3px double var(--ink-1);
  border-bottom: 1px solid var(--ink-1);
  font: 0.9em/1.45 var(--font-body);
  margin: 0.6em 0 0.4em;
  width: 100%;
  /* Stop a wide academic table from blowing past the paper's right
     margin. table-layout: fixed makes columns share width equally
     instead of growing to fit long author lists; overflow-wrap +
     hyphens give the renderer permission to break long words /
     comma-separated tokens so cells wrap inside their column. */
  table-layout: fixed;
}
.paper-table td,
.paper-table th {
  overflow-wrap: break-word;
  word-wrap: break-word;
  hyphens: auto;
}
/* The last <tr class="is-header"> in a run carries the rule under it.
   When the Word table uses w:trHeader on multiple top rows we mark
   each of those rows .is-header from the template; the rule lands
   under whichever one is last in the run, so multi-row pivot headers
   read correctly. We also style <th> with semibold weight + center
   alignment per APA convention. */
.paper-table tr.is-header th,
.paper-table tr.is-header td { font-weight: 600; text-align: center; }
.paper-table tr.is-header:not(:has(+ tr.is-header)) th,
.paper-table tr.is-header:not(:has(+ tr.is-header)) td {
  border-bottom: 1px solid var(--ink-1);
}
/* Fallback for browsers/legacy paths without :has(): treat the first
   row as the header if no row is explicitly marked. */
.paper-table:not(:has(tr.is-header)) tr:first-child td,
.paper-table:not(:has(tr.is-header)) tr:first-child th {
  border-bottom: 1px solid var(--ink-1);
  font-weight: 600;
}
.paper-table td,
.paper-table th {
  border: 0;
  padding: 0.5em 0.7em;
  vertical-align: top;
}
.paper-table td:first-child,
.paper-table th:first-child { padding-left: 0; text-align: left; }
.paper-table td:last-child,
.paper-table th:last-child  { padding-right: 0; }
.paper-figure {
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  color: var(--ink-3);
  margin: 0.8em 0;
  padding: 2em;
  text-align: center;
  font: italic 0.92em var(--font-body);
}
/* When the figure carries a real <img> (served by /u/{id}/figure/...)
   drop the dashed-placeholder treatment so the image speaks for
   itself — same convention the print stylesheet uses. */
.paper-figure.has-image {
  background: transparent;
  border: 0;
  padding: 0.4em 0;
}
.paper-figure.has-image img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 auto;
}

/* === Severity marker on paragraphs (subtle left rail) === */
.paper-page-body .has-error,
.paper-page-body .has-warning,
.paper-page-body .has-suggestion {
  border-left: 3px solid;
  padding-left: 0.8rem;
  margin-left: -1.1rem;
  border-radius: 1px;
}
.paper-page-body .has-error      { border-left-color: var(--crimson); }
.paper-page-body .has-warning    { border-left-color: #c97a00; }
.paper-page-body .has-suggestion { border-left-color: var(--forest); }

/* Hover/focus interaction from comment cards */
.paper-focus { background: #fff8c4 !important; transition: background 0.15s; }
.paper-flash { animation: paperFlash 1.4s ease-out; }
@keyframes paperFlash {
  0%   { background: #fff48a; }
  60%  { background: #fff48a; }
  100% { background: transparent; }
}

/* === Right column: comments pane === */
.comments-pane {
  background: transparent;
  font-family: var(--font-ui);
  position: sticky;
  top: var(--rails-top, 13rem);
  max-height: calc(100vh - var(--rails-top, 13rem) - 1rem);
  overflow-y: auto;
  padding-right: 0.4rem;
}
@media (max-width: 1100px) {
  .comments-pane { position: static; max-height: none; }
}
.comments-header {
  align-items: baseline;
  background: white;
  border: 1px solid var(--border);
  border-radius: 8px;
  display: flex;
  gap: 0.5rem;
  justify-content: space-between;
  margin-bottom: 0.7rem;
  padding: 0.5rem 0.85rem;
  position: sticky;
  top: 0;
  z-index: 2;
}
.comments-header strong { font-size: 0.95rem; color: var(--ink-1); }
.comments-count {
  background: var(--ink-1);
  border-radius: 999px;
  color: white;
  font: 600 0.78rem var(--font-ui);
  padding: 0.12rem 0.55rem;
}
.comments-empty {
  background: white;
  border: 1px dashed var(--border);
  border-radius: 8px;
  color: var(--ink-3);
  font-size: 0.88rem;
  padding: 0.9rem;
  text-align: center;
}

/* === Quick bulk actions panel === */
/* Surfaced at the top of the comments-pane when several paragraphs
   share the same source→target style mapping. Lets the user clear
   40 near-identical "Apply DISIE Body" cards in one click instead
   of clicking each individually. */
.quick-bulk-panel {
  background: white;
  border: 1px solid var(--border);
  border-left: 3px solid var(--saffron);
  border-radius: 6px;
  margin-bottom: 0.7rem;
  padding: 0.55rem 0.85rem 0.65rem;
}
.quick-bulk-panel > summary {
  color: var(--ink-1);
  cursor: pointer;
  font: 600 0.85rem var(--font-ui);
  list-style: none;
  padding: 0.1rem 0;
}
.quick-bulk-panel > summary::-webkit-details-marker { display: none; }
.quick-bulk-panel[open] > summary { margin-bottom: 0.45rem; }
.quick-bulk-hint {
  color: var(--ink-3);
  font: 0.78rem/1.45 var(--font-ui);
  margin: 0 0 0.55rem;
}
.quick-bulk-form {
  align-items: stretch;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0 0 0.45rem;
  padding: 0.4rem 0.55rem 0.5rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 5px;
}
.quick-bulk-form:last-of-type { margin-bottom: 0; }
.quick-bulk-line {
  align-items: center;
  color: var(--ink-2);
  display: flex;
  flex-wrap: wrap;
  font: 0.78rem var(--font-ui);
  gap: 0.35rem;
}
.quick-bulk-source,
.quick-bulk-target {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  font: 0.72rem ui-monospace, Menlo, monospace;
  padding: 0.05rem 0.3rem;
}
.quick-bulk-arrow { color: var(--ink-3); font-weight: 600; }
.quick-bulk-count {
  background: var(--saffron);
  border-radius: 999px;
  color: var(--ink-1);
  font: 700 0.7rem var(--font-ui);
  margin-left: auto;
  padding: 0.05rem 0.45rem;
}
.quick-bulk-apply {
  align-self: flex-start;
  font: 600 0.78rem var(--font-ui);
  padding: 0.3rem 0.7rem;
}

/* === Comment card === */
.comment-card {
  background: white;
  border: 1px solid var(--border);
  border-left: 3px solid var(--forest);
  border-radius: 6px;
  cursor: pointer; /* the whole card jumps to its paragraph on click */
  margin-bottom: 0.7rem;
  padding: 0.7rem 0.85rem 0.6rem;
  position: relative;
  transition: box-shadow 0.12s, transform 0.12s;
}
/* Interactive widgets inside the card keep their default cursor —
   we only want the "jump to paragraph" affordance on neutral areas. */
.comment-card button,
.comment-card a,
.comment-card label,
.comment-card details,
.comment-card summary { cursor: pointer; }
.comment-card input,
.comment-card textarea,
.comment-card select { cursor: text; }
.comment-card input[type="file"],
.comment-card input[type="checkbox"],
.comment-card input[type="radio"] { cursor: pointer; }
.comment-card:hover {
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
  transform: translateX(-2px);
}
.comment-card.severity-high   { border-left-color: var(--forest); }
.comment-card.severity-medium { border-left-color: #c97a00; }
.comment-card.severity-low    { border-left-color: var(--ink-3); }
.comment-card.from-metadata::before {
  content: "from metadata";
  position: absolute;
  top: -0.55rem;
  right: 0.5rem;
  background: var(--forest);
  color: white;
  font: 500 0.66rem var(--font-ui);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.08rem 0.45rem;
  border-radius: 999px;
}
.comment-head {
  align-items: baseline;
  display: flex;
  gap: 0.45rem;
  justify-content: space-between;
  margin-bottom: 0.25rem;
}
.comment-ref {
  background: var(--surface);
  border-radius: 3px;
  color: var(--ink-2);
  cursor: pointer;
  font: 600 0.78rem ui-monospace, Menlo, monospace;
  padding: 0.05rem 0.35rem;
  text-decoration: none;
}
.comment-ref:hover { background: var(--bg); }
.comment-ref-doc { background: var(--ink-1); color: white; font-family: var(--font-ui); }
.comment-rule {
  color: var(--ink-3);
  font: 500 0.7rem ui-monospace, Menlo, monospace;
}
.comment-title {
  color: var(--ink-1);
  font: 600 0.92rem var(--font-ui);
  margin: 0 0 0.3rem;
}
.comment-what {
  color: var(--ink-3);
  font-size: 0.82rem;
  margin: 0.2rem 0 0.35rem;
}
/* Instruction text on manual_only cards — these issues can't be
   auto-fixed; the user has to address them in Word. We render the
   `manual_reason` as a slightly stronger paragraph than the dim
   `comment-what` so the "what to do" copy actually reads. */
.comment-manual-reason {
  background: rgba(242, 193, 21, 0.08);
  border-left: 2px solid var(--saffron);
  border-radius: 3px;
  color: var(--ink-2);
  font-size: 0.84rem;
  line-height: 1.45;
  margin: 0.4rem 0 0.5rem;
  padding: 0.45rem 0.6rem;
}
.comment-diff {
  background: var(--surface);
  border-radius: 4px;
  font-size: 0.78rem;
  margin: 0.3rem 0;
  padding: 0.35rem 0.5rem;
}
.comment-diff p { margin: 0.1rem 0; }
.comment-diff em {
  color: var(--ink-3);
  font-style: normal;
  font-weight: 600;
  margin-right: 0.35rem;
  text-transform: uppercase;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
}
.comment-before { color: var(--ink-3); text-decoration: line-through; }
.comment-after { color: var(--ink-1); font-weight: 500; }

.comment-form { margin: 0; }
.comment-form-uploaded {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  margin: 0.55rem 0;
  padding: 0.65rem;
}
.comment-input-label {
  color: var(--ink-3);
  display: block;
  font: 600 0.74rem var(--font-ui);
  letter-spacing: 0.04em;
  margin: 0.4rem 0 0.2rem;
  text-transform: uppercase;
}
.comment-input-label input[type=text],
.comment-input-label textarea,
.comment-input-label select {
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  display: block;
  font: 0.86rem var(--font-ui);
  margin-top: 0.25rem;
  padding: 0.35rem 0.5rem;
  width: 100%;
}
.comment-meta-source {
  color: var(--forest);
  font: italic 0.76rem var(--font-ui);
  margin: 0.35rem 0 0.2rem;
}
.comment-buttons { display: flex; gap: 0.4rem; margin-top: 0.5rem; }
.comment-accept {
  background: var(--forest);
  border: 0;
  border-radius: 5px;
  color: white;
  cursor: pointer;
  flex: 1;
  font: 600 0.84rem var(--font-ui);
  padding: 0.42rem 0.7rem;
}
.comment-accept:hover { background: #244e33; }
.comment-accept-alt {
  background: white;
  border: 1px solid var(--border-strong);
  border-radius: 5px;
  color: var(--ink-2);
  cursor: pointer;
  font: 500 0.8rem var(--font-ui);
  padding: 0.42rem 0.55rem;
  white-space: nowrap;
}
.comment-accept-alt:hover { background: var(--surface); color: var(--ink-1); }

.comment-reject-form { margin: 0; position: absolute; top: 0.5rem; right: 0.55rem; }
.comment-reject {
  background: transparent;
  border: 0;
  color: var(--ink-3);
  cursor: pointer;
  font: 700 1rem var(--font-ui);
  line-height: 1;
  padding: 0.2rem 0.35rem;
  border-radius: 3px;
}
.comment-reject:hover { background: var(--bg); color: var(--crimson); }
.from-metadata .comment-reject { top: 0.6rem; }

/* Advanced view */
.advanced-view {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-ui);
  margin: 2rem 0;
  padding: 0.45rem 1rem 1rem;
}
.advanced-view > summary {
  color: var(--ink-3);
  cursor: pointer;
  font-size: 0.88rem;
  list-style: none;
  padding: 0.4rem 0;
}
.advanced-view > summary::before { content: "▸ "; }
.advanced-view[open] > summary::before { content: "▾ "; }
.adv-block { margin: 0.7rem 0; }
.adv-block h3 { font-size: 0.92rem; margin: 0 0 0.4rem; }
.style-mapping-table { font-size: 0.85rem; width: 100%; border-collapse: collapse; }
.style-mapping-table th, .style-mapping-table td { border-bottom: 1px solid var(--border); padding: 0.3rem 0.5rem; text-align: left; }
.raw-issues { font-size: 0.83rem; margin: 0; padding-left: 1.1rem; }
.raw-issues li { margin: 0.3rem 0; }
.raw-issues code { background: var(--bg); padding: 0 0.2rem; border-radius: 3px; font-size: 0.78rem; }

/* === Active-comment ↔ active-paragraph linking === */

/* Active paragraph in the paper (the one whose comment is currently
   topmost-visible in the right pane) — persistent soft highlight. */
.is-target-active {
  background: linear-gradient(90deg, rgba(255,228,128,0.45), rgba(255,228,128,0.18));
  border-radius: 3px;
  transition: background 0.25s ease;
}

/* Active comment in the pane — stronger left rail, slight scale */
.comment-card.is-active {
  border-color: var(--ink-1);
  border-left-width: 5px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.10);
  transform: translateX(-3px);
}

/* HTMX request states — show loading on the affected button */
.htmx-request .comment-accept,
.htmx-request.comment-accept {
  opacity: 0.65;
  pointer-events: none;
  position: relative;
}
.htmx-request .comment-accept::after,
.htmx-request.comment-accept::after {
  content: "";
  position: absolute;
  right: 0.6rem;
  top: 50%;
  width: 12px;
  height: 12px;
  margin-top: -6px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.htmx-request .button-primary, .htmx-request.button-primary,
.htmx-request .button-secondary, .htmx-request.button-secondary,
.htmx-request .button-danger, .htmx-request.button-danger {
  opacity: 0.65;
  pointer-events: none;
}

/* Subtle fade-in when content gets swapped in */
#review-content {
  animation: contentSwapIn 0.18s ease-out;
}
@keyframes contentSwapIn {
  from { opacity: 0.55; }
  to   { opacity: 1; }
}

/* === Style badges on comment cards === */
/* Visual anchor: each card opens with a square badge showing what kind
   of style the suggestion will apply (H1/H2/B/T/Ref/Fig/Decl/Key/Abs/
   Fmt/Alt/⚠). Colour-coded so the user can scan the comments column. */
.comment-head-row {
  align-items: flex-start;
  display: flex;
  gap: 0.65rem;
  margin-bottom: 0.35rem;
}
.comment-meta-stack {
  flex: 1 1 0;
  min-width: 0;
}
.style-badge {
  border-radius: 7px;
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  font: 700 1.05rem/1 var(--font-ui);
  height: 2.3rem;
  letter-spacing: 0.01em;
  min-width: 2.3rem;
  padding: 0 0.55rem;
  text-align: center;
  user-select: none;
}
.style-badge > span { line-height: 1; }
.style-badge small {
  font-size: 0.58em;
  font-weight: 700;
  line-height: 0;
  margin-left: 0.05em;
  vertical-align: super;
}

/* Headings — per level, sharing the colour with the outline rail
   and the paper badges. H1 is the DISIE saffron; H2/H3/H4 step down
   into blue / green / pale green-grey. */
.badge-h1 {
  background: var(--type-h1-bg);
  color: var(--type-h1-fg);
  border: 1px solid var(--type-h1-border);
  box-shadow: inset 0 -2px 0 rgba(0,0,0,0.08);
}
.badge-h2 {
  background: var(--type-h2-bg);
  color: var(--type-h2-fg);
  border: 1px solid var(--type-h2-border);
}
.badge-h3 {
  background: var(--type-h3-bg);
  color: var(--type-h3-fg);
  border: 1px solid var(--type-h3-border);
}
.badge-h4 {
  background: var(--type-h4-bg);
  color: var(--type-h4-fg);
  border: 1px solid var(--type-h4-border);
}

/* Body: most common, very neutral */
.badge-body {
  background: var(--type-b-bg);
  color: var(--type-b-fg);
  border: 1px solid var(--type-b-border);
}

/* Title: dark, important, identity */
.badge-title {
  background: var(--ink-1);
  color: white;
}

/* Reference: parchment / bistre — ties to the page bg */
.badge-ref {
  background: var(--type-l-bg);
  color: var(--type-l-fg);
  border: 1px solid var(--type-l-border);
}

/* Figure: muted teal */
.badge-fig {
  background: var(--type-f-bg);
  color: var(--type-f-fg);
  border: 1px solid var(--type-f-border);
}

/* Table: warm rosé */
.badge-tbl {
  background: var(--type-t-bg);
  color: var(--type-t-fg);
  border: 1px solid var(--type-t-border);
}

/* Declarations: amber, related to ethics/funding */
.badge-decl {
  background: #fdf2dd;
  color: #6f4400;
  border: 1px solid #ecc880;
}

/* Keywords: forest green */
.badge-key {
  background: #e3f0e8;
  color: #1f4530;
  border: 1px solid #c1deca;
}

/* Abstract: lighter green */
.badge-abs {
  background: #eef5e3;
  color: #36502a;
  border: 1px solid #cfe1b3;
}

/* Direct-formatting cleanup: red-ish */
.badge-fmt {
  background: #fcebed;
  color: var(--crimson);
  border: 1px solid #f1c4c8;
}

/* Manual fix required: red warning */
.badge-manual {
  background: #fcebed;
  color: var(--crimson);
  border: 1px solid #f1c4c8;
  font-size: 1.15rem;
}

/* Generic / meta */
.badge-meta {
  background: var(--surface);
  color: var(--ink-3);
  border: 1px dashed var(--border-strong);
}

/* The card title and ref line lose their top margin now that they sit
   inside .comment-meta-stack alongside the badge. */
.comment-head-row .comment-head {
  margin-bottom: 0.15rem;
}
.comment-head-row .comment-title {
  margin: 0;
}

/* === Universal style override dropdown === */
.comment-style-override {
  margin: 0.4rem 0 0;
  font-family: var(--font-ui);
}
.comment-style-override > summary {
  color: var(--ink-3);
  cursor: pointer;
  font-size: 0.78rem;
  list-style: none;
  padding: 0.15rem 0;
  user-select: none;
}
.comment-style-override > summary::-webkit-details-marker { display: none; }
.comment-style-override > summary::before {
  content: "▸ ";
  color: var(--ink-3);
  font-size: 0.7rem;
  margin-right: 0.1rem;
}
.comment-style-override[open] > summary::before { content: "▾ "; }
.comment-style-override > summary:hover { color: var(--ink-2); }
.comment-style-select {
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  display: block;
  font: 0.82rem var(--font-ui);
  margin-top: 0.3rem;
  padding: 0.3rem 0.45rem;
  width: 100%;
}

/* Advanced view metadata section + merge cards: tighter layout */
.advanced-view .merge-card { margin-top: 0.5rem; padding: 0.6rem 0.8rem; }
.advanced-view .merge-card h4 { font-size: 0.92rem; margin: 0 0 0.3rem; font-family: var(--font-ui); }
.advanced-view .merge-options { grid-template-columns: 1fr 1fr; }
@media (max-width: 720px) { .advanced-view .merge-options { grid-template-columns: 1fr; } }
/* === Structured authors editor === */

.authors-field {
  display: grid;
  gap: 0.5rem;
}
.authors-rows {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

/* One author per row. On wide screens: index · name · ORCID · affiliation · ×.
   Status and search-result panels span the full row width below. */
/* Each author gets a card. The three input cells stack vertically so
   long names and affiliations have full width to breathe; the row
   number and the × removal button sit on the side, anchored to the
   first row. */
.author-row {
  background: white;
  border: 1px solid var(--border);
  border-radius: 10px;
  display: grid;
  grid-template-columns: 1.8rem minmax(0, 1fr) 1.8rem;
  grid-template-areas:
    "num   name        remove"
    "blank orcid       blank2"
    "blank email       blank3"
    "blank affiliation blank4"
    "status status     status";
  align-items: start;
  gap: 0.5rem 0.7rem;
  padding: 0.85rem 1rem;
  position: relative;
}
.author-row-num            { grid-area: num; align-self: center; }
.author-cell-name          { grid-area: name; }
.author-cell-orcid         { grid-area: orcid; }
.author-cell-email         { grid-area: email; }
.author-cell-affiliation   { grid-area: affiliation; }
.author-remove             { grid-area: remove; align-self: center; }
.author-row-status         { grid-area: status; }

.author-row-num {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--ink-3);
  display: inline-flex;
  font: 600 0.78rem var(--font-ui);
  height: 1.55rem;
  justify-content: center;
  align-items: center;
  width: 1.55rem;
}

.author-cell {
  display: flex;
  gap: 0.3rem;
  align-items: stretch;
  min-width: 0;
}
.author-cell input[type=text] {
  background: white;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  color: var(--ink-1);
  font: 0.98rem var(--font-body);
  min-height: 2.7rem;
  padding: 0.5rem 0.7rem;
  width: 100%;
}
.author-cell input[type=text]::placeholder { color: var(--ink-3); opacity: 0.55; }
.author-cell input[type=text]:focus {
  border-color: var(--forest);
  outline: 2px solid rgba(45, 94, 62, 0.18);
  outline-offset: 0;
}

.author-cell-button {
  background: white;
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  color: var(--ink-2);
  cursor: pointer;
  font: 600 1.05rem/1 var(--font-ui);
  min-height: 2.7rem;
  min-width: 2.7rem;
  padding: 0 0.7rem;
}
.author-cell-button:hover { background: var(--surface); color: var(--ink-1); border-color: var(--border-strong); }
.author-cell-button:disabled { color: var(--ink-3); cursor: not-allowed; }

.author-remove {
  align-self: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 5px;
  color: var(--ink-3);
  cursor: pointer;
  font: 700 1.05rem/1 var(--font-ui);
  height: 1.9rem;
  width: 1.9rem;
  padding: 0;
}
.author-remove:hover {
  background: rgba(154, 42, 42, 0.08);
  border-color: rgba(154, 42, 42, 0.25);
  color: var(--crimson);
}

/* Status line — hidden until something to say, sits below all inputs */
.author-row-status {
  color: var(--ink-3);
  font: 0.84rem var(--font-ui);
  margin-top: 0.15rem;
}
.author-row-status[hidden] { display: none; }
.author-row-status.pending { color: var(--bistre); }
.author-row-status.ok      { color: var(--forest); }
.author-row-status.error   { color: var(--crimson); }

/* === ORCID search modal — scoped under .orcid-modal so the global
   button rule cannot leak in. === */

dialog.orcid-modal {
  background: white;
  border: 0;
  border-radius: 14px;
  box-shadow: 0 32px 80px rgba(0, 0, 0, 0.28), 0 4px 12px rgba(0, 0, 0, 0.08);
  color: var(--ink-1);
  font-family: var(--font-ui);
  max-width: 38rem;
  padding: 0;
  width: 92vw;
}
dialog.orcid-modal::backdrop {
  background: rgba(15, 18, 22, 0.55);
  backdrop-filter: blur(3px);
}

.orcid-modal-head {
  align-items: center;
  border-bottom: 1px solid var(--border);
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  padding: 0.95rem 1.2rem 0.85rem;
}
.orcid-modal-head h2 {
  color: var(--ink-1);
  font: 600 1.05rem var(--font-ui);
  margin: 0;
}
.orcid-modal-close {
  align-items: center;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--ink-3);
  cursor: pointer;
  display: inline-flex;
  font: 700 1.3rem/1 var(--font-ui);
  height: 2rem;
  justify-content: center;
  min-height: 0;
  padding: 0;
  width: 2rem;
}
.orcid-modal-close:hover {
  background: var(--surface);
  border-color: var(--border);
  color: var(--ink-1);
}

.orcid-modal-search {
  border-bottom: 1px solid var(--border);
  display: flex;
  gap: 0.5rem;
  padding: 0.85rem 1.2rem;
}
.orcid-modal-search input {
  background: white;
  border: 1px solid var(--border-strong);
  border-radius: 7px;
  color: var(--ink-1);
  flex: 1 1 0;
  font: 0.98rem var(--font-body);
  min-height: 2.5rem;
  padding: 0.5rem 0.75rem;
}
.orcid-modal-search input:focus {
  border-color: var(--forest);
  outline: 2px solid rgba(45, 94, 62, 0.2);
  outline-offset: 0;
}
.orcid-modal-search button {
  background: var(--ink-1);
  border: 0;
  border-radius: 7px;
  color: white;
  cursor: pointer;
  font: 600 0.92rem var(--font-ui);
  min-height: 2.5rem;
  padding: 0 1.2rem;
}
.orcid-modal-search button:hover { background: var(--forest); }
.orcid-modal-search button:disabled { background: var(--ink-3); cursor: not-allowed; }

.orcid-modal-status {
  color: var(--ink-3);
  font: 0.84rem var(--font-ui);
  margin: 0;
  min-height: 1.2rem;
  padding: 0.55rem 1.2rem;
}
.orcid-modal-status:empty { display: none; }
.orcid-modal-status.state-pending { color: var(--bistre); }
.orcid-modal-status.state-ok { color: var(--forest); }
.orcid-modal-status.state-error { color: var(--crimson); }

.orcid-modal-empty {
  color: var(--ink-3);
  font: italic 0.88rem var(--font-body);
  margin: 0;
  padding: 1.4rem 1.4rem 2rem;
  text-align: center;
}
.orcid-modal-empty[hidden] { display: none; }

.orcid-modal-results {
  list-style: none;
  margin: 0;
  max-height: 28rem;
  overflow-y: auto;
  padding: 0.35rem 0.5rem 0.5rem;
}
.orcid-modal-results:empty { display: none; }

.orcid-result {
  background: white;
  border: 1px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  display: grid;
  gap: 0.18rem;
  padding: 0.7rem 0.9rem;
  text-align: left;
}
.orcid-result:hover,
.orcid-result:focus-visible {
  background: var(--surface);
  border-color: var(--border-strong);
  outline: none;
}
.orcid-result-name {
  color: var(--ink-1);
  font: 600 1rem var(--font-ui);
  line-height: 1.2;
}
.orcid-result-inst {
  color: var(--ink-2);
  font: 0.9rem/1.3 var(--font-body);
}
.orcid-result-inst.is-missing {
  color: var(--ink-3);
  font-style: italic;
}
.orcid-result-id {
  color: var(--ink-3);
  font: 500 0.82rem ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 0.01em;
}

/* + Add author */
.authors-add {
  align-self: start;
  background: white;
  border: 1px dashed var(--border-strong);
  border-radius: 6px;
  color: var(--ink-2);
  cursor: pointer;
  font: 500 0.88rem var(--font-ui);
  min-height: 2rem;
  padding: 0.35rem 0.85rem;
}
.authors-add:hover {
  background: var(--surface);
  border-color: var(--ink-3);
  color: var(--ink-1);
}

/* === Metadata page · realistic PDF page-1 preview === */
/* Replaces the old .titlepage-preview / .paper-preview block in the
   right column of the metadata form with a single white "sheet" that
   shows what page 1 of the rendered PDF will look like (journal-style,
   flush-left, serif body). Below the title-page block we render the
   first body paragraphs from the Word document so the user can see
   where the title page ends and the manuscript text begins. */

.page-preview {
  align-self: start;
  min-width: 0;
  position: sticky;
  top: 5.5rem;
}
.page-preview-tag {
  color: var(--ink-3);
  font: 600 0.74rem var(--font-ui);
  letter-spacing: 0.06em;
  margin: 0 0 0.5rem;
  text-transform: uppercase;
}
.page-sheet {
  background: white;
  border: 1px solid var(--border);
  border-radius: 3px;
  box-shadow: 0 18px 48px rgba(15, 18, 22, 0.10), 0 2px 4px rgba(15, 18, 22, 0.05);
  color: var(--ink-1);
  font: 16px/1.55 var(--font-body);
  padding: 3.4rem 3.6rem 3rem;
}
@media (max-width: 1100px) {
  .page-sheet { padding: 2.4rem 2rem 2rem; }
}

/* Small text-only article-type label between the saffron rule
   and the manuscript title. Italic small caps, no colour stripe. */
.page-article-label {
  color: var(--ink-3);
  font: italic 0.85em/1.3 var(--font-body);
  letter-spacing: 0.01em;
  margin: 0.6em 0 0.4em;
}

/* === Elsevier-style metadata grid on the title page ===============
   LEFT: ARTICLE INFO sidebar (article type, language, keywords, DOI).
   RIGHT: ABSTRACT + ZUSAMMENFASSUNG stacked. Both columns lead
   with a thin saffron rule on the left edge. */
.page-meta-grid {
  display: grid;
  gap: 1.6em;
  /* `minmax(0, 1fr)` on the abstracts track stops min-content from
     pushing the right column to ~0px when a long unbreakable token
     (DOI, single-word keyword) lives in the article-info side. */
  grid-template-columns: 9em minmax(0, 1fr);
  margin: 1.2em 0 1em;
}
.page-meta-heading {
  color: var(--bistre);
  font: 700 0.78em var(--font-ui);
  letter-spacing: 0.08em;
  margin: 0 0 0.5em;
  text-transform: uppercase;
}
.page-article-info {
  border-left: 1px solid var(--saffron);
  padding-left: 0.7em;
}
.page-article-info dl {
  display: grid;
  /* Override the global `dl { grid-template-columns: 160px 1fr }`
     rule (~l.930) — that's right for wide repair-card dls but
     here `.page-article-info` is only 9em wide. With 160px dt the
     dd would collapse to ~0px and `word-break: break-word` would
     stack every character on its own line. We want a single
     column: dt stacked above dd, with row-gap between pairs. */
  grid-template-columns: none;
  gap: 0.6em;
  margin: 0;
}
.page-article-info dt {
  color: var(--ink-3);
  font: 600 0.66em var(--font-ui);
  letter-spacing: 0.04em;
  margin: 0 0 0.1em;
  text-transform: uppercase;
}
.page-article-info dd {
  color: var(--ink-1);
  font: 0.86em/1.3 var(--font-body);
  margin: 0;
  word-break: break-word;
}

/* Title-page block at the top (flush-left, journal style) */
.page-titleblock { }
.page-kicker {
  color: var(--ink-3);
  font: 600 0.78em var(--font-ui);
  letter-spacing: 0.1em;
  margin: 0 0 0.7em;
  text-transform: uppercase;
}
.page-title {
  color: var(--ink-1);
  font: 700 1.45em/1.18 var(--font-body);
  margin: 0 0 0.35em;
  max-width: none;
  text-wrap: balance;
}
.page-short-title {
  color: var(--ink-3);
  font: italic 0.82em var(--font-body);
  margin: 0 0 1em;
  min-height: 1em;
}
.page-short-title:empty::before {
  color: var(--ink-3);
  content: "(no short title set)";
  font-style: italic;
  opacity: 0.5;
}

.page-authors { margin: 0.5em 0 0.7em; }
.page-author { margin: 0 0 0.35em; }
.page-author-name {
  color: var(--ink-1);
  font: 600 0.86em var(--font-body);
  margin: 0;
}
.page-author-orcid {
  color: var(--ink-3);
  font: 500 0.7em var(--font-ui);
  letter-spacing: 0.01em;
  margin-left: 0.4em;
  text-decoration: none;
  white-space: nowrap;
}
.page-author-orcid .orcid-icon {
  display: inline-block;
  height: 0.85em;
  margin-right: 0.2em;
  vertical-align: -0.12em;
  width: 0.85em;
}
.page-author-orcid span {
  border-bottom: 1px dotted var(--ink-3);
  padding-bottom: 0.5px;
}
.page-author-affil {
  color: var(--ink-3);
  font: italic 0.78em var(--font-body);
  margin: 0;
}
.page-author-empty {
  color: var(--ink-3);
  font: italic 0.8em var(--font-body);
  margin: 0;
}

.page-correspondence {
  color: var(--ink-2);
  font: 0.78em var(--font-body);
  margin: 0.3em 0 1em;
}
.page-correspondence span:first-child {
  color: var(--ink-3);
  font-family: var(--font-ui);
  font-size: 0.68em;
  font-weight: 600;
  letter-spacing: 0.03em;
  margin-right: 0.2em;
  text-transform: uppercase;
}

/* Declarations: small boxed compliance block tied to the article-
   type accent via a subtle surface — visually distinct from the
   abstract (which uses the accent tint) but still part of the
   "journal metadata" family. */
.page-declarations {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  display: grid;
  font: 0.85em/1.3 var(--font-body);
  gap: 0.3em 0.85em;
  grid-template-columns: 5.5em 1fr;
  margin: 1.4em 0 0;
  padding: 0.85em 1.1em;
}
.page-declarations dt {
  color: var(--ink-3);
  font: 600 0.78em var(--font-ui);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.page-declarations dd {
  color: var(--ink-1);
  font-family: var(--font-body);
  margin: 0;
}

/* Divider between title-page block and body preview */
.page-divider {
  border: 0;
  border-top: 1px dashed var(--border-strong);
  margin: 2.2rem 0 0.4rem;
}
.page-divider-label {
  color: var(--ink-3);
  font: 600 0.72rem var(--font-ui);
  letter-spacing: 0.08em;
  margin: 0 0 1rem;
  text-align: center;
  text-transform: uppercase;
}

/* Body-preview pulled from the Word doc */
.page-bodypreview {
  border-top: 1px solid var(--border);
  padding-top: 1.6rem;
}
.page-bodypreview > * {
  margin: 0 0 0.6rem;
}
.page-body-h1 {
  font: 600 1.25rem/1.25 var(--font-body);
  margin-top: 1.3rem;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.2rem;
}
.page-body-h2 { font: 600 1.1rem/1.25 var(--font-body); margin-top: 1rem; }
.page-body-h3 { font: 600 1rem/1.25 var(--font-body); margin-top: 0.9rem; }
.page-body-h4 { font: italic 600 0.95rem/1.25 var(--font-body); margin-top: 0.8rem; }
.page-body-p  { font: 0.96rem/1.55 var(--font-body); text-align: justify; hyphens: auto; }
.page-body-abstract {
  background: var(--surface);
  border-left: 3px solid var(--border-strong);
  font: 0.92rem/1.55 var(--font-body);
  padding: 0.5rem 0.8rem;
  text-align: justify;
}
.page-body-quote {
  border-left: 3px solid var(--border-strong);
  color: var(--ink-2);
  font-style: italic;
  margin: 0.8rem 0;
  padding-left: 0.95rem;
}
.page-body-continued {
  color: var(--ink-3);
  font: italic 0.82rem var(--font-body);
  margin-top: 0.7rem;
  text-align: center;
}
.page-body-empty {
  color: var(--ink-3);
  font: italic 0.88rem var(--font-body);
  text-align: center;
}

/* === Journal masthead on the page-1 preview (shared partial) === */
/* Two columns: DISIE wordmark on the left, identifier block on the
   right (QR · DOI · journal URL · APA citation). The right column
   drives the height so the masthead is a constant strip across
   different metadata states. */

/* === DISIE masthead (screen mirror) ============================
   LEFT: DISIE lockup (logo SVG with wordmark + descriptive strap
   baked in). RIGHT: three uniform small upright metadata lines
   (catalog caption / homepage / DOI), all same family + size +
   weight. Thin saffron rule below as the DISIE signature. */
.page-masthead {
  align-items: center;
  display: grid;
  gap: 1.4rem;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  margin: 0 0 0.35rem;
  padding: 0;
}
.page-masthead-mark { min-width: 0; }
.page-masthead-logo {
  display: block;
  height: auto;
  max-width: 14rem;
  width: 100%;
}
.page-masthead-meta {
  color: var(--ink-3);
  font: 0.78rem/1.4 var(--font-body);
  justify-self: end;
  text-align: right;
}
.page-masthead-meta p { margin: 0 0 0.15rem; }
.page-masthead-meta p:last-child { margin-bottom: 0; }
.page-masthead-meta a { color: var(--ink-2); }
.page-masthead-doi-label {
  color: var(--ink-3);
  font-weight: 600;
  letter-spacing: 0.05em;
  margin-right: 0.25rem;
}
.page-saffron-rule {
  background: var(--saffron);
  height: 1.5px;
  margin: 0 0 0.7rem;
}
@media (max-width: 720px) {
  .page-masthead { grid-template-columns: 1fr; align-items: start; }
  .page-masthead-meta { justify-self: start; text-align: left; }
}

/* Inline variant of .page-sheet for embedding inside the report's
   .paper-page-titlepage (no double shadow / border). The report
   page provides those via .paper-page. */
.page-sheet-inline {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 0;
}
/* Stop the old APA-centred title-page-inner styles from leaking onto
   the unified flush-left .page-titleblock now used on the report page. */
.paper-page-titlepage .titlepage-inner { display: none; }

/* === Abstracts on the title page — Elsevier-style right column ===
   Lives inside .page-meta-grid as the wider right column. No
   tinted box anymore (keywords moved to the left ARTICLE INFO
   sidebar); just a thin saffron rule on the left edge tying it
   to the article-info column visually. */
.page-abstracts {
  border-left: 1px solid var(--saffron);
  display: grid;
  gap: 0.9em;
  margin: 0;
  padding-left: 0.7em;
}
.page-abstracts:empty { display: none; }
.page-abstract {
  background: transparent;
  border: 0;
  padding: 0;
}
.page-abstract h3.page-meta-heading {
  color: var(--bistre);
  font: 700 0.78em var(--font-ui);
  letter-spacing: 0.08em;
  margin: 0 0 0.4em;
  text-transform: uppercase;
}
.page-abstract p {
  color: var(--ink-1);
  font: 0.92em/1.35 var(--font-body);
  margin: 0 0 0.4em;
  text-align: justify;
  white-space: pre-wrap;
}
.page-abstract p:last-child { margin-bottom: 0; }

/* === Per-paragraph editor toolbar === */
/* Floats above the active paragraph and exposes Style, Edit text and
   Delete. Position is set by JS via getBoundingClientRect. */
.paper-edit-toolbar, .paper-range-toolbar {
  align-items: center;
  background: var(--ink-1);
  border-radius: 8px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25), 0 2px 6px rgba(0, 0, 0, 0.10);
  color: white;
  display: inline-flex;
  font: 500 0.84rem var(--font-ui);
  gap: 0.4rem;
  padding: 0.35rem 0.45rem;
  pointer-events: auto;
  z-index: 70;
}
.paper-edit-toolbar[hidden], .paper-range-toolbar[hidden] { display: none; }
.paper-edit-info, .paper-range-info {
  color: rgba(255, 255, 255, 0.6);
  font: 500 0.75rem ui-monospace, "SF Mono", Menlo, monospace;
  padding: 0 0.3rem;
}
.paper-edit-toolbar select,
.paper-range-toolbar select {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 5px;
  color: white;
  font: 500 0.8rem var(--font-ui);
  min-height: 1.9rem;
  padding: 0.1rem 0.45rem;
}
.paper-edit-toolbar select option,
.paper-range-toolbar select option {
  background: var(--ink-1);
  color: white;
}
.paper-edit-btn {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 5px;
  color: white;
  cursor: pointer;
  font: 500 0.8rem var(--font-ui);
  min-height: 1.9rem;
  padding: 0.1rem 0.65rem;
}
.paper-edit-btn:hover { background: rgba(255, 255, 255, 0.16); }
.paper-edit-delete:hover { background: rgba(154, 42, 42, 0.6); }
.paper-edit-delete-armed {
  background: var(--crimson) !important;
  border-color: var(--crimson) !important;
  /* Establish positioning context for the countdown bar below.
     overflow: hidden clips the shrinking bar to the button shape. */
  position: relative;
  overflow: hidden;
}
/* 4-second countdown bar that drains from 100% width to 0 along the
   bottom edge of the armed delete button. JS arms the button for 4s
   then auto-disarms; the bar gives the user a visible "time left"
   cue so the timeout isn't a surprise. Animation duration must
   match the setTimeout value in setupEditor's deleteBtn handler. */
.paper-edit-delete-armed::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: rgba(255, 255, 255, 0.85);
  transform-origin: left center;
  animation: deleteArmedCountdown 4s linear forwards;
  pointer-events: none;
}
@keyframes deleteArmedCountdown {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}
/* While the user is inline-editing the paragraph text we disable
   the Style dropdown and the Delete button so a stray click can't
   race the text-save POST. The disabled attribute is set in JS; this
   rule gives them a "muted" look so the locked state is obvious. */
.paper-edit-toolbar select.is-locked,
.paper-edit-btn.is-locked {
  cursor: not-allowed;
  opacity: 0.4;
}
.paper-edit-close {
  background: transparent;
  border: 0;
  color: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  font: 700 1.1rem/1 var(--font-ui);
  margin-left: 0.1rem;
  padding: 0 0.4rem;
}
.paper-edit-close:hover { color: white; }

/* Edit-mode hint chip — surfaced inside the toolbar while the
   paragraph is contenteditable so the editor knows that Enter no
   longer auto-saves (it now splits) and which shortcut commits. */
.paper-edit-hint {
  background: rgba(242, 193, 21, 0.18); /* saffron tint */
  border-radius: 4px;
  color: white;
  font: 500 0.7rem var(--font-ui);
  letter-spacing: 0.01em;
  margin-left: 0.35rem;
  opacity: 0.95;
  padding: 0.25rem 0.5rem;
  white-space: nowrap;
}
.paper-edit-hint[hidden] { display: none; }

/* Active paragraph styling — while the toolbar is open or text edit
   is in progress. */
.paper-page-body .is-edit-active {
  background: linear-gradient(90deg, rgba(255, 228, 128, 0.25), rgba(255, 228, 128, 0.08));
  border-radius: 3px;
  outline: 1px dashed var(--saffron);
  outline-offset: 2px;
}
.paper-page-body [contenteditable="true"] {
  background: #fff;
  box-shadow: 0 0 0 2px rgba(45, 94, 62, 0.25);
  outline: none;
  padding: 0.1rem 0.2rem;
}

/* Hint cursor: every paragraph in the body is clickable for the
   editor. */
.paper-page-body .paper-p,
.paper-page-body .paper-h1,
.paper-page-body .paper-h2,
.paper-page-body .paper-h3,
.paper-page-body .paper-h4,
.paper-page-body .paper-abstract-heading,
.paper-page-body .paper-abstract,
.paper-page-body .paper-keywords,
.paper-page-body .paper-quote,
.paper-page-body .paper-reference,
.paper-page-body .paper-figcaption,
.paper-page-body .paper-fignote,
.paper-page-body .paper-tablecaption,
.paper-page-body .paper-tablenote,
.paper-page-body .paper-code {
  cursor: text;
}

/* === Figure placeholder upload card === */
.comment-figure-detected {
  background: var(--surface);
  border-left: 3px solid var(--saffron);
  border-radius: 4px;
  color: var(--ink-1);
  font: 0.85rem/1.4 var(--font-ui);
  margin: 0.4rem 0;
  padding: 0.45rem 0.6rem;
}
.comment-figure-detected strong { color: var(--ink-1); }
.comment-figure-detected em { color: var(--ink-3); font-style: italic; }

/* Refusal banner shared by every upload action (upload_figure /
   replace_figure_image / upload_table). Crimson left-rule + tinted
   background so the user can't miss why the previous upload didn't
   take. Sticks across page loads — unlike the page-top flash, which
   disappears on the next click. */
.comment-refusal-banner {
  background: rgba(154, 42, 42, 0.07);
  border-left: 3px solid var(--crimson);
  border-radius: 4px;
  color: var(--ink-1);
  font: 0.85rem/1.45 var(--font-ui);
  margin: 0.4rem 0;
  padding: 0.5rem 0.7rem;
}
.comment-refusal-banner strong { color: var(--crimson); }
.comment-file-label input[type="file"] {
  background: white;
  border: 1px dashed var(--border-strong);
  border-radius: 6px;
  cursor: pointer;
  font: 0.85rem var(--font-ui);
  margin-top: 0.3rem;
  padding: 0.5rem;
  width: 100%;
}
.comment-file-label input[type="file"]:hover {
  border-color: var(--forest);
  background: var(--surface);
}

/* ================================================================== */
/* === DISIE Paper — unified component layer (Stage 1+) ============== */
/*                                                                    */
/* Eight components that replace the divergent per-page patterns      */
/* (intake-shell vs. report, workflow-ribbon vs. step-trail, five     */
/* different action-bars, six different callouts, ten different       */
/* surface-card variants). Stage 1 just defines them; Stages 2–4      */
/* rewire templates and delete the old rules.                         */
/*                                                                    */
/* Constraints:                                                       */
/*  - Source Serif 4 + Inter remain the only CSS-loaded fonts.        */
/*  - Saffron `#f2c115` is fill-only per ADR-0006; bistre carries     */
/*    readable text where any non-default colour is needed.           */
/*  - No animations beyond .htmx-progress and .render-spinner above.  */
/* ================================================================== */

/* --- .workflow-steps — replaces .workflow-ribbon and .step-trail --- */
/* Same compact inline-pill bar on every one of the seven workflow    */
/* pages. The current step is rendered as a saffron pill.             */
.workflow-steps {
  align-items: baseline;
  color: var(--ink-3);
  display: flex;
  flex-wrap: wrap;
  font: 600 var(--text-sm) var(--font-ui);
  gap: var(--space-2);
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}
.workflow-steps li {
  align-items: baseline;
  display: inline-flex;
  gap: var(--space-1);
}
.workflow-steps li + li::before {
  color: var(--border-strong);
  content: "→";
  margin-right: var(--space-1);
}
.workflow-steps li span {
  color: var(--ink-3);
  font: 500 var(--text-xs) ui-monospace, "SF Mono", Menlo, monospace;
}
.workflow-steps li a {
  color: var(--ink-2);
  text-decoration: none;
}
.workflow-steps li a:hover {
  color: var(--ink-1);
  text-decoration: underline;
}
.workflow-steps li.is-current {
  background: var(--saffron);
  border-radius: 999px;
  color: var(--ink-1);
  padding: 0.18rem 0.6rem;
}
.workflow-steps li.is-current span {
  color: var(--ink-1);
}

/* --- .page-header — replaces six different page-head patterns ----- */
/* Same H1 size (var(--text-2xl), 2rem) on every page. The 4.7rem    */
/* intake hero, the 3.8rem analysis hero, the 2.05rem intake_*       */
/* override, and the 1.6rem final-check header all collapse here.    */
.page-header {
  margin: var(--space-3) 0 var(--space-5);
}
.page-header h1 {
  color: var(--ink-1);
  font: 600 var(--text-2xl)/1.15 var(--font-body);
  margin: 0 0 var(--space-2);
  max-width: 28ch;
}
.page-header > p,
.page-header .lede {
  color: var(--ink-3);
  font: var(--text-md)/1.5 var(--font-ui);
  margin: 0;
  max-width: 62ch;
}

/* --- .surface-card — replaces ten different card patterns --------- */
/* Solid white on cream, 1px border, no shadow by default. The 3px   */
/* left-border carries severity (matching the .callout convention).  */
.surface-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: var(--font-ui);
  padding: var(--space-4) var(--space-5);
}
.surface-card[data-severity="error"] {
  border-left: 3px solid var(--crimson);
}
.surface-card[data-severity="warning"] {
  border-left: 3px solid #c97a00;
}
.surface-card[data-severity="info"],
.surface-card[data-severity="ok"] {
  border-left: 3px solid var(--forest);
}
.surface-card[data-severity="action"] {
  border-left: 3px solid var(--saffron);
}

/* --- .page-action-bar — copy left, buttons right ------------------ */
/* Replaces .status-banner, .final-check-render-bar, .asset-action-  */
/* bar, .intake-next-bar. Modifiers: .is-sticky for top-pinned       */
/* gates, .is-gate(-ready|-blocking) for the colored left border.    */
.page-action-bar {
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: flex;
  flex-wrap: wrap;
  font-family: var(--font-ui);
  gap: var(--space-3) var(--space-4);
  justify-content: space-between;
  margin: var(--space-3) 0 var(--space-5);
  padding: var(--space-3) var(--space-4);
}
.page-action-bar .action-copy {
  flex: 1 1 auto;
  min-width: 0;
}
.page-action-bar .action-copy strong {
  color: var(--ink-1);
  font: 600 var(--text-md) var(--font-ui);
}
.page-action-bar .action-copy p {
  color: var(--ink-3);
  font: var(--text-sm)/1.4 var(--font-ui);
  margin: var(--space-1) 0 0;
}
.page-action-bar .action-buttons {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.page-action-bar.is-sticky {
  position: sticky;
  top: 4.5rem;
  z-index: 30;
  box-shadow: var(--shadow-1);
}
.page-action-bar.is-gate {
  border-left: 3px solid var(--saffron);
}
.page-action-bar.is-gate-ready {
  border-left: 3px solid var(--forest);
}
.page-action-bar.is-gate-blocking {
  border-left: 3px solid #c97a00;
}

/* --- .upload-zone — replaces .dropzone and .asset-upload-target --- */
/* Solid white card with a dashed inner outline. No scan animation,  */
/* no cyan shimmer, no glassmorphism. Same widget for upload/tables/ */
/* figures/materials. The dashed line uses ::before so the outer     */
/* border can stay solid for hover/focus emphasis.                   */
.upload-zone {
  align-items: center;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  display: grid;
  font-family: var(--font-ui);
  gap: var(--space-3);
  grid-template-columns: auto minmax(0, 1fr) auto;
  padding: var(--space-5) var(--space-5);
  position: relative;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.upload-zone:hover,
.upload-zone:focus-within {
  background: var(--surface-2);
  border-color: var(--border-strong);
}
.upload-zone::before {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  content: "";
  inset: var(--space-2);
  pointer-events: none;
  position: absolute;
}
.upload-zone input[type="file"] {
  cursor: pointer;
  inset: 0;
  opacity: 0;
  position: absolute;
}
.upload-zone .zone-icon {
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--bistre);
  display: flex;
  font: 700 var(--text-xs) var(--font-ui);
  height: 2.75rem;
  justify-content: center;
  letter-spacing: 0.05em;
  position: relative;
  text-transform: uppercase;
  width: 2.75rem;
}
.upload-zone .zone-copy {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
  position: relative;
}
.upload-zone .zone-copy strong {
  color: var(--ink-1);
  font: 600 var(--text-md) var(--font-ui);
}
.upload-zone .zone-copy em {
  color: var(--ink-3);
  font: var(--text-sm)/1.4 var(--font-ui);
  font-style: normal;
  overflow-wrap: anywhere;
}
.upload-zone .zone-action {
  background: var(--saffron);
  border: 1px solid var(--type-h1-border);
  border-radius: var(--radius-sm);
  color: var(--ink-1);
  font: 600 var(--text-sm) var(--font-ui);
  padding: var(--space-2) var(--space-3);
  pointer-events: none;
  position: relative;
  white-space: nowrap;
}
.upload-form {
  display: grid;
  gap: var(--space-4);
}

/* --- .callout — replaces six different banner patterns ------------ */
/* 1px border + 3px coloured left-border for semantic emphasis.      */
/* .is-collapsible wraps a <details> with a custom summary chevron.  */
.callout {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--forest);
  border-radius: var(--radius);
  font: var(--text-sm)/1.5 var(--font-ui);
  margin: var(--space-3) 0;
  padding: var(--space-3) var(--space-4);
}
.callout strong {
  color: var(--ink-1);
}
.callout p {
  margin: var(--space-1) 0 0;
}
.callout[data-severity="warning"] {
  background: #fff8eb;
  border-left-color: #c97a00;
}
.callout[data-severity="error"] {
  border-left-color: var(--crimson);
}
.callout[data-severity="info"] {
  border-left-color: var(--forest);
}
.callout[data-severity="action"] {
  border-left-color: var(--saffron);
}
.callout.is-collapsible > summary {
  color: var(--ink-1);
  cursor: pointer;
  font: 600 var(--text-sm) var(--font-ui);
  list-style: none;
  padding: 0;
}
.callout.is-collapsible > summary::-webkit-details-marker {
  display: none;
}
.callout.is-collapsible > summary::before {
  color: var(--ink-3);
  content: "▸ ";
  display: inline-block;
  margin-right: var(--space-1);
  transition: transform 0.12s ease;
}
.callout.is-collapsible[open] > summary::before {
  transform: rotate(90deg);
}
.callout.is-collapsible[open] > summary {
  margin-bottom: var(--space-2);
}

/* --- .stat-tile / .stat-pill — two scales of the same "metric" ---- */
/* .stat-tile is the big card (Analysis page metrics); .stat-pill is */
/* the inline pill (Report page summary chips). Both can carry an    */
/* optional data-status="ok|pending" to tint the surface.            */
.stat-tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: grid;
  font-family: var(--font-ui);
  gap: var(--space-1);
  padding: var(--space-4);
}
.stat-tile > span {
  color: var(--ink-3);
  font: 700 var(--text-xs)/1.2 var(--font-ui);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.stat-tile > strong {
  color: var(--ink-1);
  font: 700 var(--text-xl)/1 var(--font-ui);
}

.stat-pill {
  align-items: baseline;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--ink-3);
  display: inline-flex;
  font: var(--text-sm) var(--font-ui);
  gap: var(--space-1);
  padding: 0.36rem 0.65rem;
}
.stat-pill strong {
  color: var(--ink-1);
  font-weight: 600;
}
.stat-pill[data-status="ok"] {
  background: rgba(45, 94, 62, 0.07);
  border-color: rgba(45, 94, 62, 0.35);
  color: var(--forest);
}
.stat-pill[data-status="ok"] strong {
  color: var(--forest);
}
.stat-pill[data-status="pending"] {
  background: rgba(242, 193, 21, 0.10);
  border-color: rgba(199, 156, 12, 0.5);
  color: var(--bistre);
}
.stat-pill[data-status="pending"] strong {
  color: var(--bistre);
}

/* End of DISIE Paper component layer. ============================== */

/* === Admin console (/console/*) ====================================
   Separate visual lane from the author-facing typesetter — no fixed
   "Under review" banner (this is the editor's tooling, not a review
   surface), tighter density, and a constant header/nav so the
   dashboard / submissions / detail / stats pages all share the same
   chrome. Colours come from the typesetter token palette so the
   visual identity stays consistent. */
.console-body {
  background: var(--bg);
  color: var(--ink-1);
  font: 0.95rem/1.5 var(--font-ui);
  margin: 0;
  /* The author-facing @media-screen "Under review" badge shouldn't
     show in the console. Suppress just for this surface. */
}
.console-body::before { content: none !important; display: none !important; }
.console-header {
  background: var(--ink-1);
  color: #fff;
  padding: 0.7rem 0;
}
.console-header-inner {
  align-items: center;
  display: flex;
  gap: 2rem;
  margin: 0 auto;
  max-width: 1280px;
  padding: 0 1.5rem;
}
.console-brand {
  color: #fff;
  font: 700 1rem var(--font-ui);
  text-decoration: none;
}
.console-brand span { color: var(--saffron); font-weight: 500; }
.console-nav {
  display: flex;
  gap: 1.5rem;
  margin-left: auto;
}
.console-nav a {
  color: rgba(255, 255, 255, 0.78);
  font: 600 0.85rem var(--font-ui);
  text-decoration: none;
  padding: 0.3rem 0;
}
.console-nav a:hover { color: #fff; }
.console-nav a.is-current { color: var(--saffron); border-bottom: 2px solid var(--saffron); }
.console-main {
  margin: 0 auto;
  max-width: 1280px;
  padding: 2rem 1.5rem 3rem;
}
.console-page-header {
  margin-bottom: 1.5rem;
}
.console-page-header h1 {
  color: var(--ink-1);
  font: 600 1.6rem var(--font-body);
  margin: 0 0 0.4rem;
}
.console-lede {
  color: var(--ink-3);
  font-size: 0.92rem;
  margin: 0;
}
.console-footer {
  border-top: 1px solid var(--border);
  color: var(--ink-3);
  font-size: 0.8rem;
  margin: 4rem auto 2rem;
  max-width: 1280px;
  padding: 1rem 1.5rem 0;
}
.console-footer a { color: var(--bistre); }

/* --- Status strip (dashboard) -------------------------------------- */
.console-status-strip {
  display: grid;
  gap: 0.7rem;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  margin-bottom: 2rem;
}
.console-status-tile {
  background: var(--surface);
  border: 1px solid var(--border);
  border-left: 3px solid var(--ink-3);
  border-radius: 5px;
  color: var(--ink-1);
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.8rem 1rem;
  text-decoration: none;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.console-status-tile:hover { background: var(--surface-2); border-color: var(--border-strong); }
.console-status-tile.is-empty { opacity: 0.55; }
.console-status-count {
  color: var(--ink-1);
  font: 600 1.4rem var(--font-body);
  line-height: 1;
}
.console-status-label {
  color: var(--ink-3);
  font: 600 0.72rem var(--font-ui);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Per-status accent on the left rail. Mirrors the meaning in the UI
   (forest = good outcome, crimson = blocked, saffron = in progress). */
.console-status-tile.console-status-submitted { border-left-color: var(--forest); }
.console-status-tile.console-status-rendered { border-left-color: var(--forest); }
.console-status-tile.console-status-validated { border-left-color: var(--forest); }
.console-status-tile.console-status-failed,
.console-status-tile.console-status-validation_failed { border-left-color: var(--crimson); }
.console-status-tile.console-status-queued,
.console-status-tile.console-status-rendering { border-left-color: var(--saffron); }

/* --- Tables (list + recent) ---------------------------------------- */
.console-section { margin-bottom: 2rem; }
.console-section-header {
  align-items: baseline;
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  margin-bottom: 0.7rem;
}
.console-section-header h2 {
  color: var(--ink-1);
  font: 600 1.05rem var(--font-body);
  margin: 0;
}
.console-section-link { color: var(--bistre); font-size: 0.85rem; text-decoration: none; }
.console-section-link:hover { text-decoration: underline; }

.console-table {
  background: var(--surface);
  border: 1px solid var(--border);
  border-collapse: collapse;
  border-radius: 5px;
  font-size: 0.9rem;
  overflow: hidden;
  width: 100%;
}
.console-table th, .console-table td {
  border-bottom: 1px solid var(--border);
  padding: 0.6rem 0.85rem;
  text-align: left;
  vertical-align: top;
}
.console-table thead th {
  background: var(--surface-2);
  color: var(--ink-3);
  font: 600 0.72rem var(--font-ui);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.console-table tbody tr:hover { background: var(--surface-2); }
.console-table tbody tr:last-child td { border-bottom: 0; }
.console-table a { color: var(--ink-1); font-weight: 500; text-decoration: none; }
.console-table a:hover { color: var(--bistre); text-decoration: underline; }

.console-token {
  color: var(--ink-3);
  font: 0.78rem ui-monospace, "SF Mono", Menlo, monospace;
}
.console-empty {
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: 5px;
  color: var(--ink-3);
  padding: 1.4rem;
  text-align: center;
}

/* --- Status pill (inline status indicator) ------------------------- */
.console-status-pill {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--ink-2);
  display: inline-block;
  font: 600 0.7rem var(--font-ui);
  letter-spacing: 0.03em;
  padding: 0.15rem 0.55rem;
  text-transform: uppercase;
}
.console-status-pill.console-status-submitted,
.console-status-pill.console-status-rendered,
.console-status-pill.console-status-validated { background: rgba(45, 94, 62, 0.12); color: var(--forest); border-color: rgba(45, 94, 62, 0.3); }
.console-status-pill.console-status-failed,
.console-status-pill.console-status-validation_failed { background: rgba(154, 42, 42, 0.10); color: var(--crimson); border-color: rgba(154, 42, 42, 0.3); }
.console-status-pill.console-status-queued,
.console-status-pill.console-status-rendering { background: rgba(242, 193, 21, 0.16); color: var(--bistre); border-color: rgba(242, 193, 21, 0.4); }

.console-revision-badge {
  background: rgba(154, 42, 42, 0.08);
  border: 1px solid rgba(154, 42, 42, 0.3);
  border-radius: 3px;
  color: var(--crimson);
  font: 600 0.66rem var(--font-ui);
  letter-spacing: 0.04em;
  margin-left: 0.4rem;
  padding: 0.05rem 0.35rem;
  text-transform: uppercase;
}

/* --- Filter bar + pagination -------------------------------------- */
.console-filter-bar {
  align-items: end;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.2rem;
  padding: 0.9rem 1rem;
}
.console-filter-field { display: grid; gap: 0.3rem; min-width: 13rem; }
.console-filter-field > span {
  color: var(--ink-3);
  font: 600 0.7rem var(--font-ui);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.console-filter-field input,
.console-filter-field select {
  background: #fff;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  font: 0.9rem var(--font-ui);
  padding: 0.45rem 0.6rem;
}
.console-filter-reset {
  align-self: center;
  color: var(--ink-3);
  font: 0.82rem var(--font-ui);
  text-decoration: underline;
}
.console-pagination {
  align-items: center;
  display: flex;
  gap: 1rem;
  justify-content: center;
  margin-top: 1.2rem;
}
.console-pagination-info { color: var(--ink-3); font-size: 0.82rem; }

/* --- Submission detail -------------------------------------------- */
.console-breadcrumb {
  color: var(--ink-3);
  font-size: 0.82rem;
  margin: 0 0 0.4rem;
}
.console-breadcrumb a { color: var(--bistre); text-decoration: none; }
.console-breadcrumb a:hover { text-decoration: underline; }

.console-detail-grid {
  display: grid;
  gap: 1.6rem;
}
.console-section > h2 {
  color: var(--ink-1);
  font: 600 1.05rem var(--font-body);
  margin: 0 0 0.5rem;
}
.console-section-hint {
  color: var(--ink-3);
  font-size: 0.85rem;
  margin: 0 0 0.7rem;
}

.console-timeline {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.console-timeline li {
  border-bottom: 1px solid var(--border);
  display: grid;
  gap: 0.4rem;
  grid-template-columns: 9rem 1fr;
  padding: 0.55rem 0.95rem;
}
.console-timeline li:last-child { border-bottom: 0; }
.console-timeline-label {
  color: var(--ink-3);
  font: 600 0.72rem var(--font-ui);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.console-timeline-when {
  color: var(--ink-1);
  font: 0.88rem var(--font-ui);
}

.console-empty-inline { color: var(--ink-3); font-style: italic; }
.console-json {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--ink-2);
  font: 0.78rem ui-monospace, "SF Mono", Menlo, monospace;
  margin: 0;
  max-height: 22rem;
  overflow: auto;
  padding: 0.7rem 0.85rem;
}
.console-verify-result {
  font: 600 0.82rem var(--font-ui);
  margin-left: 0.6rem;
}

/* --- Stats: horizontal bar chart for submissions/month ------------- */
.console-bar-chart {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  display: grid;
  gap: 0.45rem;
  padding: 0.9rem 1rem;
}
.console-bar-row {
  align-items: center;
  display: grid;
  gap: 0.7rem;
  grid-template-columns: 5.5rem 1fr 2.5rem;
}
.console-bar-label {
  color: var(--ink-3);
  font: 600 0.78rem var(--font-ui);
}
.console-bar-track {
  background: var(--surface-2);
  border-radius: 2px;
  display: block;
  height: 0.85rem;
  overflow: hidden;
}
.console-bar-fill {
  background: var(--saffron);
  display: block;
  height: 100%;
}
.console-bar-value {
  color: var(--ink-1);
  font: 600 0.82rem var(--font-ui);
  text-align: right;
}

/* --- Revisions-chain block (on the submission detail page) -------- */
.console-chain {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 5px;
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}
.console-chain-node {
  align-items: center;
  border-bottom: 1px solid var(--border);
  display: grid;
  gap: 0.9rem;
  grid-template-columns: 3rem 1fr;
  padding: 0.65rem 0.95rem;
}
.console-chain-node:last-child { border-bottom: 0; }
.console-chain-node.is-current {
  background: rgba(242, 193, 21, 0.08);
  border-left: 3px solid var(--saffron);
  padding-left: calc(0.95rem - 3px);
}
.console-chain-round {
  background: var(--ink-1);
  border-radius: 4px;
  color: #fff;
  font: 700 0.78rem var(--font-ui);
  padding: 0.25rem 0;
  text-align: center;
}
.console-chain-body {
  display: grid;
  gap: 0.2rem;
}
.console-chain-title {
  color: var(--ink-1);
  font: 600 0.92rem var(--font-body);
  text-decoration: none;
}
.console-chain-title:hover { color: var(--bistre); text-decoration: underline; }
.console-chain-meta {
  color: var(--ink-3);
  font: 0.82rem var(--font-ui);
}
.console-chain-token {
  color: var(--ink-3);
  font: 0.72rem ui-monospace, "SF Mono", Menlo, monospace;
}
