/* DN-MOPD project page, p5d_polish layer. Loaded after style.css; purely additive.
   Navigation (chapter rail, reading progress, active section), page choreography (hero load-in, staggered reveals,
   scroll cue), micro-interactions (buttons, figures, lightbox, copy feedback), mobile fit, and performance helpers.
   Motion uses transform/opacity only and lives inside prefers-reduced-motion: no-preference blocks.
   Nothing here hides content unless JS has already marked it for a reveal (html.rv-on, set by app.js). */

:root {
  --sec-pad: 120px;
  --ov-pad: 96px;
  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --ease-spring: cubic-bezier(.3, 1.35, .5, 1);
  --rail-x: 22px;
}
@media (max-width: 680px) { :root { --sec-pad: 80px; --ov-pad: 72px; } }

/* ------------------------------------------------------------------ anchors
   A section jump lands with the kicker ~28px under the sticky nav instead of the section's
   empty top padding; tables and the abstract keep a small gap under the nav. */
.section[id] { scroll-margin-top: calc(var(--nav-h) + 28px - var(--sec-pad)); }
#overview { scroll-margin-top: calc(var(--nav-h) + 28px - var(--ov-pad)); }
figure[id], #abstract { scroll-margin-top: calc(var(--nav-h) + 20px); }

/* ------------------------------------------------------------------ reading progress (bar injected by polish.js) */
.nav .progress {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; pointer-events: none;
  transform-origin: 0 50%; transform: scaleX(0);
  background: linear-gradient(90deg, var(--teal) 0%, var(--blue) 42%, var(--purple) 72%, var(--gold) 100%);
}

/* ------------------------------------------------------------------ top nav: active section */
.nav-links a { position: relative; }
.nav-links a::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: 3px; height: 2px; border-radius: 2px;
  background: var(--teal); transform: scaleX(0); transform-origin: 50% 50%; transition: transform .28s var(--ease-out);
}
.nav-links a[aria-current="true"] { color: var(--heading); background: var(--surface-3); }
.nav-links a[aria-current="true"]::after { transform: scaleX(1); }
/* aria-current (set by polish.js) is the only active state; the merged app.js no longer sets .active */

/* compact menu: numbered like the chapters, active item marked, gentle open */
.menu-panel { counter-reset: mp; min-width: 220px; }
.menu-panel a { display: flex; align-items: center; gap: 12px; min-height: 44px; transition: background-color .15s, color .15s; }
.menu-panel a::before {
  counter-increment: mp; content: "0" counter(mp);
  font-family: var(--font-mono); font-size: 11.5px; font-weight: 500; color: var(--muted);
}
.menu-panel a[aria-current="true"] { background: var(--teal-wash); color: var(--teal-ink); }
.menu-panel a[aria-current="true"]::before { color: var(--teal-ink); }

/* ------------------------------------------------------------------ chapter rail (desktop >= 1200px) */
.rail { display: none; }
@media (min-width: 1200px) {
  .rail { display: block; position: fixed; left: var(--rail-x); top: 50%; transform: translateY(-50%); z-index: 40; }
}
/* 1200-1327px: widen the side gutters so the rail never sits on top of the content column */
@media (min-width: 1200px) and (max-width: 1327.98px) { :root { --gutter: 64px; } }
.rail ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; position: relative; }
.rail ol::before, .rail ol::after {
  content: ""; position: absolute; left: 13px; top: 14px; bottom: 14px; width: 2px; border-radius: 2px;
}
.rail ol::before { background: var(--border); }
.rail ol::after {
  background: var(--teal); transform-origin: 50% 0; transform: scaleY(var(--rail-k, 0));
  transition: transform .45s var(--ease-out);
}
.rail li { position: relative; z-index: 1; }
.rail a {
  position: relative; display: flex; align-items: center; text-decoration: none;
  padding: 6px; margin: -6px; border-radius: 999px;
}
.rail a:focus-visible { outline-offset: 0; border-radius: 999px; }
.rail-dot {
  width: 28px; height: 28px; flex: none; border-radius: 50%; display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 10.5px; font-weight: 500; line-height: 1; letter-spacing: 0;
  color: var(--muted); background: var(--surface); box-shadow: inset 0 0 0 1.5px var(--border-strong);
  transition: background-color .25s ease, color .25s ease, box-shadow .25s ease, transform .25s var(--ease-out);
}
.rail a:hover .rail-dot { color: var(--heading); box-shadow: inset 0 0 0 1.5px var(--axis); transform: scale(1.08); }
.rail a.is-past .rail-dot { color: var(--teal-ink); box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--teal) 55%, var(--border)); }
.rail a[aria-current="true"] .rail-dot {
  background: var(--btn-bg); color: var(--btn-fg); font-weight: 600;
  box-shadow: 0 0 0 4px var(--teal-wash), 0 4px 12px -4px color-mix(in srgb, var(--teal) 70%, transparent);
  transform: scale(1.06);
}
.rail-lbl {
  position: absolute; left: 44px; top: 50%; white-space: nowrap; pointer-events: none;
  padding: 3px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 600; color: var(--heading);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow);
  opacity: 0; transform: translate(-6px, -50%); transition: opacity .18s ease, transform .22s var(--ease-out);
}
.rail a:hover .rail-lbl, .rail a:focus-visible .rail-lbl { opacity: 1; transform: translate(0, -50%); }
.rail a[aria-current="true"] .rail-lbl { color: var(--teal-ink); }

/* ------------------------------------------------------------------ hero: TL;DR tag, scroll cue */
.tldr-tag {
  display: inline-block; margin-right: 6px; padding: 1px 8px; border-radius: 6px; vertical-align: .16em;
  font-family: var(--font-mono); font-size: .62em; font-weight: 500; line-height: 1.55; letter-spacing: .02em;
  color: var(--teal-ink); background: var(--teal-wash); border: 1px solid color-mix(in srgb, var(--teal) 28%, transparent);
}
.scroll-cue {
  margin-top: 30px; display: inline-flex; flex-direction: column; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
}
.scroll-cue svg {
  width: 30px; height: 30px; padding: 6px; border-radius: 50%; box-sizing: border-box;
  color: var(--teal-ink); background: var(--pill-bg); border: 1px solid var(--border-strong); box-shadow: var(--shadow-sm);
}
/* merge: the teaser's top margin is hero.css's (the stat row now sits between the cue and the teaser) */
@media (max-width: 680px) {
  .scroll-cue { display: none; }
}

/* ------------------------------------------------------------------ figures: expand affordance */
.fig-white { position: relative; }
.js .float-card .fig-white img { cursor: zoom-in; }
.fig-expand {
  position: absolute; top: 10px; right: 10px; z-index: 2; width: 40px; height: 40px; padding: 0;
  display: grid; place-items: center; border-radius: 10px; cursor: pointer;
  color: #173B5B; background: rgba(255, 255, 255, .94); border: 1px solid #D9E2EA;
  box-shadow: 0 6px 16px -8px rgba(16, 38, 61, .45);
  opacity: 0; transform: translateY(-4px) scale(.96);
  transition: opacity .2s ease, transform .22s var(--ease-out), border-color .15s ease;
}
.fig-expand:hover { border-color: #9FB2C4; }
.float-card:hover .fig-expand, .fig-expand:focus-visible { opacity: 1; transform: none; }
.fig-expand:focus-visible { outline-color: #148F86; border-radius: 10px; }
@media (hover: none) { .fig-expand { opacity: .96; transform: none; } }
.fig-open { position: relative; }
.fig-open::after { content: ""; position: absolute; inset: -10px -6px; } /* larger tap area, no layout change */
.fig-open > span { display: inline-block; transition: transform .2s var(--ease-out); }
.fig-open:hover > span { transform: translate(2px, -2px); }

/* ------------------------------------------------------------------ lightbox (built by polish.js on a <dialog>) */
.lb {
  padding: 16px; margin: 0; border: 0; width: 100%; height: 100%; max-width: none; max-height: none;
  background: transparent; color: var(--text); overflow: hidden;
}
.lb[open] { display: flex; align-items: center; justify-content: center; }
.lb::backdrop { background: rgba(5, 12, 20, .72); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.lb-panel {
  width: min(1360px, 100%); max-height: 100%; display: flex; flex-direction: column; min-height: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: 20px; box-shadow: var(--shadow-lg); overflow: hidden;
}
.lb-bar { display: flex; align-items: center; gap: 8px; padding: 10px 10px 10px 18px; border-bottom: 1px solid var(--border); }
.lb-title { flex: 1; min-width: 0; font-family: var(--font-display); font-weight: 650; font-size: 1rem; color: var(--heading); }
.lb-title .fig-tag { margin-right: 8px; }
.lb-btn {
  height: 40px; min-width: 40px; padding: 0 12px; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border-radius: 10px; border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  font-family: var(--font-body); font-size: 13.5px; font-weight: 600; text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: color .15s ease, border-color .15s ease, background-color .15s ease, transform .15s ease;
}
.lb-btn:hover { color: var(--heading); border-color: var(--border-strong); text-decoration: none; }
.lb-btn:active { transform: scale(.96); }
.lb-btn:focus-visible { border-radius: 10px; outline-offset: 2px; }
.lb-btn[aria-pressed="true"] { color: var(--teal-ink); border-color: color-mix(in srgb, var(--teal) 45%, var(--border)); background: var(--teal-wash); }
.lb-close { padding: 0; }
.lb-stage { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: 14px; background: var(--surface-2); }
.lb-paper { background: #FFFFFF; border: 1px solid #EEF2F6; border-radius: 12px; padding: clamp(10px, 2vw, 24px); }
.lb-img { display: block; width: 100%; height: auto; max-height: calc(100dvh - 250px); object-fit: contain; cursor: zoom-in; }
.lb.zoomed .lb-paper { width: 230%; }
.lb.zoomed .lb-img { max-height: none; cursor: zoom-out; }
.lb-cap { padding: 12px 18px 14px; font-size: .9rem; line-height: 1.55; color: var(--text-2); border-top: 1px solid var(--border); max-height: 22vh; overflow: auto; }
.lb-cap b { color: var(--heading); font-weight: 600; }
.lb-hint { font-size: 12px; color: var(--muted); margin-right: 4px; }
@media (max-width: 680px) {
  .lb { padding: 8px; }
  .lb-bar { padding: 8px 8px 8px 14px; gap: 6px; }
  .lb-newtab .lb-txt, .lb-hint { display: none; }
  .lb-newtab { padding: 0; }
  .lb-stage { padding: 8px; }
  .lb-img { max-height: calc(100dvh - 230px); }
  .lb-cap { font-size: .84rem; padding: 10px 14px 12px; }
}

/* ------------------------------------------------------------------ buttons, cards, focus */
.btn:active { transform: translateY(0) scale(.98); }
.btn-primary:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 12px 26px -12px rgba(20, 143, 134, .95); }
.btn:focus-visible { border-radius: 11px; outline-offset: 3px; }
.btn-sm:focus-visible, .icon-btn:focus-visible { border-radius: 9px; }
.icon-btn { transition: color .15s ease, border-color .15s ease, background-color .15s ease, transform .15s ease; }
.icon-btn:active { transform: scale(.94); }
.paper-card:focus-visible { border-radius: 20px; }
.copy-btn:focus-visible { border-radius: 8px; outline-color: #7FDCCF; }
.gc-row:focus-visible { border-radius: 8px; }
.table-wrap:focus-visible { border-radius: 14px; outline-offset: 2px; }
.data-view summary { transition: color .15s ease; }
.data-view summary:hover { color: var(--heading); }
.paper-go span { display: inline-block; transition: transform .2s var(--ease-out); }
.paper-card:hover .paper-go span { transform: translateX(4px); }
.paper-card picture { display: block; }
.contrib, .eq-card, .pd, .controls li, .lim, .setup-facts, .setup-bench, .table-card, .callout, .mech-card {
  transition: border-color .2s ease, box-shadow .2s ease;
}
.contrib:hover, .eq-card:hover, .pd:hover, .controls li:hover, .lim:hover { border-color: var(--border-strong); }

/* theme toggle: the new icon turns in */
.theme-toggle svg { transform-origin: 50% 50%; }

/* copy BibTeX: icon swaps to a check, the code block glows once */
.copy-btn { transition: background-color .15s ease, border-color .15s ease, color .15s ease, transform .15s ease; }
.copy-btn:active { transform: scale(.96); }
.copy-btn .i-check { display: none; }
.copy-btn.done .i-copy { display: none; }
.copy-btn.done .i-check { display: block; }
.bib { position: relative; }
.bib::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; border-radius: inherit; opacity: 0;
  box-shadow: inset 0 0 0 2px rgba(127, 220, 207, .55); background: rgba(47, 181, 167, .08);
}

/* ------------------------------------------------------------------ Table 3 as cards on phones (classes added by polish.js)
   #table3 scoping outranks the base table rules (sticky first column, group separators, row hover). */
@media (max-width: 680px) {
  #table3 .table-wrap.has-cards { border: 0; border-radius: 0; overflow: visible; }
  #table3 .dt-cards, #table3 .dt-cards tbody { display: block; }
  #table3 .dt-cards thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  #table3 .dt-cards tbody { display: grid; gap: 10px; }
  #table3 .dt-cards tbody tr {
    display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px 0; padding: 14px 14px 12px;
    border: 1px solid var(--border); border-radius: 14px; background: var(--surface);
  }
  #table3 .dt-cards tbody tr > th, #table3 .dt-cards tbody tr > td {
    position: static; padding: 0 8px 0 0; border: 0; white-space: normal; background: transparent; box-shadow: none; text-align: left;
  }
  #table3 .dt-cards tbody tr > th { grid-column: 1 / -1; font-family: var(--font-display); font-weight: 650; font-size: 1.02rem; color: var(--heading); }
  #table3 .dt-cards tbody tr > td { grid-column: span 2; font-size: 1rem; font-weight: 600; color: var(--heading); }
  #table3 .dt-cards tbody tr > td:nth-child(2), #table3 .dt-cards tbody tr > td:nth-child(3) {
    grid-column: span 3; font-size: .9rem; font-weight: 500; color: var(--text-2);
  }
  #table3 .dt-cards tbody tr > td::before {
    content: attr(data-label); display: block; margin-bottom: 1px;
    font-family: var(--font-body); font-size: 10.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
  }
  #table3 .dt-cards tbody tr > td:nth-child(n+4) { padding-top: 8px; border-top: 1px solid var(--border-soft); }
  #table3 .dt-cards tbody tr.dn-row {
    background: var(--dn-row-bg); border-color: color-mix(in srgb, var(--teal) 45%, var(--border));
    box-shadow: inset 3px 0 0 var(--teal);
  }
  #table3 .dt-cards tbody tr.dn-row > td:nth-child(n+4) { border-top-color: color-mix(in srgb, var(--teal) 22%, transparent); }
}

/* ------------------------------------------------------------------ touch targets (>= 40px) */
@media (max-width: 860px), (pointer: coarse) {
  .icon-btn { width: 40px; height: 40px; }
  .nav-actions .btn-sm { height: 40px; }
  .copy-btn { height: 40px; padding: 0 14px; }
  .data-view summary { display: inline-flex; align-items: center; min-height: 40px; }
  .foot-links a { display: inline-flex; align-items: center; min-height: 40px; }
  .skip { padding: 11px 16px; }
  .brand { min-height: 40px; }
  /* merge: the same floor for the segmented switches the other directions added (p5b size switch, p5c chart toggles);
     scoped one level deeper because scrolly.css and datamotion.css load after this file */
  .sy .sy-seg button, .dm-fig .dm-seg button { min-height: 40px; min-width: 44px; }
}
@media (max-width: 680px) {
  .foot-links { gap: 0 18px; }
  .footer { padding: 18px 0 26px; }
  .lede { text-wrap: pretty; }
}

/* ------------------------------------------------------------------ choreography (motion only when welcome) */
@media (prefers-reduced-motion: no-preference) {
  /* hero title block: a short staggered rise on load (CSS only, finishes without JS) */
  .hero-inner > * { animation: pl-rise .8s var(--ease-out) both; }
  .hero-inner > :nth-child(2) { animation-delay: .06s; }
  .hero-inner > :nth-child(3) { animation-delay: .14s; }
  .hero-inner > :nth-child(4) { animation-delay: .2s; }
  .hero-inner > :nth-child(5) { animation-delay: .24s; }
  .hero-inner > :nth-child(6) { animation-delay: .3s; }
  .hero-inner > :nth-child(7) { animation: pl-fade .8s ease .7s both; }
  /* merge: the teaser is below the fold now (p5a's schematic and stat row come first); it takes the ordinary scroll
     reveal, and the schematic and stat row take the load-in instead (hero.css) */
  .hero .aurora { animation: pl-fade 1.6s ease-out both; }
  .scroll-cue svg { animation: pl-bob 2.4s ease-in-out 1.6s infinite; }
  html.hero-off .aurora span, html.hero-off .scroll-cue svg { animation-play-state: paused; }

  /* rail: dots settle in once (a transition, so a display toggle at the breakpoint never replays it;
     html.pl-on is set by polish.js, so the rail is never hidden without it) */
  .rail li { transition: opacity .45s ease, transform .55s var(--ease-out); }
  html.pl-on:not(.rail-in) .rail li { opacity: 0; transform: translateX(-10px); }
  .rail li:nth-child(2) { transition-delay: .05s; } .rail li:nth-child(3) { transition-delay: .1s; }
  .rail li:nth-child(4) { transition-delay: .15s; } .rail li:nth-child(5) { transition-delay: .2s; }
  .rail li:nth-child(6) { transition-delay: .25s; }

  /* reveals: siblings in the same row enter one after another (delay set by polish.js) */
  html.rv-on .rv.in { transition-delay: var(--rv-d, 0ms); }
  /* after the reveal, hand transitions back to hover states */
  html.rv-on .rv.rv-done {
    transition: opacity .3s ease, transform .25s ease, border-color .2s ease, box-shadow .2s ease;
    transition-delay: 0ms;
  }
  /* section heads: kicker, heading and lede cascade instead of moving as one block */
  html.rv-on .sec-head.rv { opacity: 1; transform: none; }
  html.rv-on .sec-head.rv > * { opacity: 0; transform: translateY(12px); transition: opacity .6s ease, transform .75s var(--ease-out); }
  html.rv-on .sec-head.rv.in > * { opacity: 1; transform: none; }
  html.rv-on .sec-head.rv.in > :nth-child(2) { transition-delay: .08s; }
  html.rv-on .sec-head.rv.in > :nth-child(3) { transition-delay: .16s; }
  html.rv-on .sec-head.rv.in > :nth-child(4) { transition-delay: .24s; } /* merge: p5b's scroll hint in #method */
  /* cards revealed after they were already scrolled past (fast jumps) skip the entrance */
  html.rv-on .rv.rv-now, html.rv-on .rv.rv-now > *, html.rv-on .rv.rv-now .kicker span { transition: none; }
  /* kicker number ticks in */
  html.rv-on .sec-head.rv .kicker span { display: inline-block; transition: transform .5s var(--ease-spring) .1s; transform: scale(.7); }
  html.rv-on .sec-head.rv.in .kicker span { transform: none; }

  .menu[open] .menu-panel { animation: pl-pop .18s var(--ease-out) both; transform-origin: 100% 0; }
  .theme-toggle.flip svg { animation: pl-spin .5s var(--ease-out) both; }
  .copy-btn.done .i-check { animation: pl-check .4s var(--ease-spring) both; }
  .bib.flash::after { animation: pl-glow 1.1s ease-out both; }
  .lb[open] .lb-panel { animation: pl-lb .3s var(--ease-out) both; }
  .lb[open]::backdrop { animation: pl-fade .25s ease both; }
}
/* the glow is a state cue, keep a static version for reduced motion */
@media (prefers-reduced-motion: reduce) {
  .bib.flash::after { opacity: 1; }
}
@keyframes pl-rise { from { opacity: 0; transform: translateY(14px); } }
@keyframes pl-rise-lg { from { opacity: 0; transform: translateY(26px) scale(.985); } }
@keyframes pl-fade { from { opacity: 0; } }
@keyframes pl-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(5px); } }
@keyframes pl-pop { from { opacity: 0; transform: translateY(-6px) scale(.98); } }
@keyframes pl-spin { from { opacity: 0; transform: rotate(-80deg) scale(.55); } }
@keyframes pl-check { from { opacity: 0; transform: scale(.4) rotate(-25deg); } }
@keyframes pl-glow { 0% { opacity: 0; } 20% { opacity: 1; } 100% { opacity: 0; } }
@keyframes pl-lb { from { opacity: 0; transform: translateY(12px) scale(.985); } }

/* ------------------------------------------------------------------ performance: skip rendering far-off sections
   Sections below the fold start with content-visibility:auto and a size estimate, which shortens the first render.
   html.cv-off switches it off: the head script sets it for deep links, reloads and history navigation; polish.js sets
   it before any in-page jump, before printing, and in idle time right after the load event. Anchors, find-in-page
   and full-page captures therefore always see real sizes. */
@supports (content-visibility: auto) {
  html:not(.cv-off) #results, html:not(.cv-off) #analysis, html:not(.cv-off) #limitations, html:not(.cv-off) #cite {
    content-visibility: auto;
  }
  /* estimates are content-box heights (real height minus the section padding), re-measured on the merged page at
     1440/1280/1100 (first set), 1024/900/768 (second) and 390 px (third); #analysis grew with p5c's two charts.
     #method is deliberately not in this list: p5b's sticky diagram lives there. */
  #results { contain-intrinsic-size: auto 4650px; }
  #analysis { contain-intrinsic-size: auto 4200px; }
  #limitations { contain-intrinsic-size: auto 480px; }
  #cite { contain-intrinsic-size: auto 390px; }
  @media (max-width: 1080px) {
    #results { contain-intrinsic-size: auto 5500px; }
    #analysis { contain-intrinsic-size: auto 5200px; }
    #limitations { contain-intrinsic-size: auto 680px; }
    #cite { contain-intrinsic-size: auto 610px; }
  }
  @media (max-width: 680px) {
    #results { contain-intrinsic-size: auto 7600px; }
    #analysis { contain-intrinsic-size: auto 5900px; }
    #limitations { contain-intrinsic-size: auto 1000px; }
    #cite { contain-intrinsic-size: auto 650px; }
  }
}

/* ------------------------------------------------------------------ print */
@media print {
  .rail, .nav .progress, .scroll-cue, .fig-expand, .lb { display: none !important; }
  .hero-inner > *, .hero .aurora, .hx-art, .hx-stat { animation: none !important; }
  .rail li { opacity: 1 !important; transform: none !important; }
  .sec-head.rv > * { opacity: 1 !important; transform: none !important; }
  #results, #analysis, #limitations, #cite { content-visibility: visible !important; }
}
