/* SignalData motion layer (v4, Oct. 29, 2026). Loaded after glass.css on every page (src/partials/layout.html).
   Everything here is gated by html.mo, which assets/motion.js sets; without the script, or with "reduce motion"
   set on the device, nothing is hidden and nothing moves. Content is never removed or reworded by this file.

   Tokens: one family of easings and durations, used by every animated thing on the site. */
:root {
  --mo-out: cubic-bezier(.2, .8, .2, 1);      /* fast start, soft landing: entrances, hovers */
  --mo-std: cubic-bezier(.4, 0, .2, 1);       /* color and theme changes */
  --mo-pop: cubic-bezier(.3, .7, .4, 1.35);   /* map pies and dots: slight overshoot */
  --mo-fast: .2s;
  --mo-mid: .45s;
  --mo-slow: .8s;
  --mo-lift: 0 18px 40px -22px rgba(23, 32, 36, .38);
}
html.gloss { --mo-lift: 0 18px 40px -18px rgba(0, 0, 0, .7); }

/* Page-to-page: a soft cross-fade where the browser supports it (Chrome, Edge, Safari 18+). */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .28s; animation-timing-function: var(--mo-std); }

/* Theme switch: colors glide instead of snapping. */
body, .panel, .tcard, .tcd, .fedcard, .ncard, .trk, .cv-map, .ev-rank { transition: background-color .5s var(--mo-std), border-color .5s var(--mo-std), color .5s var(--mo-std); }

/* ---- Reveal on scroll ---------------------------------------------------------------------------------------------
   motion.js tags elements with .mo-r and adds .mo-in when they enter the viewport. --mo-i staggers siblings. */
html.mo:not(.mo-off) .mo-r { opacity: 0; transform: translateY(18px); }
html.mo .mo-r.mo-in { opacity: 1; transform: none; transition: opacity var(--mo-slow) var(--mo-out), transform var(--mo-slow) var(--mo-out);
  transition-delay: calc(var(--mo-i, 0) * 70ms); }
html.mo .mo-r.mo-in.mo-done { transition-delay: 0s; }
html.mo .mo-r.mo-now, html.mo .mo-bar.mo-now { transition: none; }
html.mo .mo-map.mo-now .ev-pie, html.mo .mo-map.mo-now .mm-dot circle, html.mo .mo-map.mo-now .dc-dot circle { animation: none; }

/* Bars fill from the left when their section comes into view. */
html.mo:not(.mo-off) .mo-bar { clip-path: inset(0 100% 0 0); }
html.mo .mo-bar.mo-in { clip-path: inset(0 0 0 0); transition: clip-path 1.3s var(--mo-out); transition-delay: calc(120ms + var(--mo-i, 0) * 45ms); }

/* Map marks (early-vote pies, data center dots) pop in, west to east (--mo-d set by motion.js from each mark's x). */
html.mo .ev-pie, html.mo .mm-dot circle, html.mo .dc-dot circle { transform-box: fill-box; transform-origin: center; }
html.mo:not(.mo-off) .mo-map:not(.mo-in) .ev-pie, html.mo:not(.mo-off) .mo-map:not(.mo-in) .mm-dot circle,
html.mo:not(.mo-off) .mo-map:not(.mo-in) .dc-dot circle { transform: scale(0); opacity: 0; }
html.mo .mo-map.mo-in .ev-pie, html.mo .mo-map.mo-in .mm-dot circle, html.mo .mo-map.mo-in .dc-dot circle { animation: mo-pop .6s var(--mo-pop) backwards; animation-delay: var(--mo-d, 0ms); }
/* Map layer switch: states or counties recolor in a wave from west to east (motion.js adds .mo-wave for under a second). */
.cmap-svg .cty { transition: fill .35s var(--mo-std), opacity .12s; }
.cmap-svg.mo-wave .cty { transition-delay: var(--mo-w, 0ms), 0s; }

/* Page heroes (/elections/2026/, /investigations/, /news/, /data-centers/, /fl/): lines rise in one after another; the
   accent second line of the headline wipes in from the left. */
html.mo:not(.mo-off) .hero > .wrap > *, html.mo:not(.mo-off) .dc-hero > .wrap > div > *, html.mo:not(.mo-off) .dc-stats > .dc-stat,
html.mo:not(.mo-off) .hx.fl .hx-left > *, html.mo:not(.mo-off) .hx.sth .hx-left > *, html.mo:not(.mo-off) .bhero .wrap > *,
html.mo:not(.mo-off) .nstrip .nst-l > li { animation: mo-rise .9s var(--mo-out) backwards; }
.hero > .wrap > :nth-child(2), .dc-hero > .wrap > div > :nth-child(2), .hx.fl .hx-left > :nth-child(2), .hx.sth .hx-left > :nth-child(2), .bhero .wrap > :nth-child(2) { animation-delay: 70ms; }
.hero > .wrap > :nth-child(3), .dc-hero > .wrap > div > :nth-child(3), .hx.fl .hx-left > :nth-child(3), .hx.sth .hx-left > :nth-child(3), .bhero .wrap > :nth-child(3) { animation-delay: 150ms; }
.hero > .wrap > :nth-child(4), .dc-hero > .wrap > div > :nth-child(4), .hx.fl .hx-left > :nth-child(4), .hx.sth .hx-left > :nth-child(4), .bhero .wrap > :nth-child(n+4) { animation-delay: 230ms; }
.hero > .wrap > :nth-child(n+5), .dc-hero > .wrap > div > :nth-child(n+5) { animation-delay: 300ms; }
.dc-stats > .dc-stat:nth-child(1) { animation-delay: 200ms; }
.dc-stats > .dc-stat:nth-child(2) { animation-delay: 280ms; }
.dc-stats > .dc-stat:nth-child(3) { animation-delay: 360ms; }
.dc-stats > .dc-stat:nth-child(4) { animation-delay: 440ms; }
.nstrip .nst-l > li:nth-child(1) { animation-delay: 300ms; }
.nstrip .nst-l > li:nth-child(2) { animation-delay: 380ms; }
.nstrip .nst-l > li:nth-child(3) { animation-delay: 460ms; }
.nstrip .nst-l > li:nth-child(4) { animation-delay: 540ms; }
.hero h1 .hl, .dc-hero h1 .hl { display: inline-block; }
html.mo:not(.mo-off) .hero h1 .hl, html.mo:not(.mo-off) .dc-hero h1 .hl { animation: mo-wipe 1.1s var(--mo-out) .35s backwards; }
@keyframes mo-wipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 -2% 0 0); } }
/* Florida's county art floats in and then breathes very slowly. */
html.mo:not(.mo-off) .hx.fl .hx-art, html.mo:not(.mo-off) .hx.sth .hx-art { animation: mo-slide 1s var(--mo-out) .2s backwards; }
html.mo .hx.fl .hx-art img, html.mo .hx.sth .hx-art img { animation: mo-drift 24s ease-in-out 1.2s infinite alternate; }
/* Data center hero tiles lift like cards. */
.dc-stat { transition: transform .3s var(--mo-out), box-shadow .3s var(--mo-out), border-color .3s; }
@media (hover: hover) { a.dc-stat:hover, a.dc-card:hover, a.nrow:hover { transform: translateY(-3px); box-shadow: var(--mo-lift); } }
.dc-card, .nrow { transition: transform .3s var(--mo-out), box-shadow .3s var(--mo-out), background-color .3s; }
/* Hero chapter links and news rows: underline slides in. */
.chapters a { transition: transform .2s var(--mo-out), background-color .2s, color .2s; }
.chapters a:hover { transform: translateY(-2px); }
@media (hover: hover) { .nrow .nh a, .irow .nh a { background-image: linear-gradient(currentColor, currentColor); background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px; transition: background-size .35s var(--mo-out); text-decoration: none; }
  .nrow:hover .nh a, .irow:hover .nh a { background-size: 100% 1px; } }
/* News and investigations: rows that return after a filter change rise in (display change restarts the animation). */
.nlist.mo-filtered .nrow { animation: mo-rise .45s var(--mo-out) backwards; }

/* Printing and saving as PDF: everything shows, nothing waits for a scroll. */
@media print {
  html.mo .mo-r, html.mo .mo-bar, html.mo .mo-map .ev-pie, html.mo .mo-map .mm-dot circle, html.mo .mo-map .dc-dot circle,
  html.mo .hero > .wrap > *, html.mo .dc-hero *, html.mo .hx *, html.mo .bhero * { opacity: 1 !important; transform: none !important; clip-path: none !important; animation: none !important; transition: none !important; }
}
@keyframes mo-pop { from { transform: scale(0); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ---- Hover and press ------------------------------------------------------------------------------------------- */
.tcard, .tcd, .fedcard, .ncard, .file-card, .link-card, .hcard, .ibar, a.link-recipient {
  transition: transform .3s var(--mo-out), box-shadow .3s var(--mo-out), border-color .3s var(--mo-out), background-color .5s var(--mo-std); }
@media (hover: hover) {
  a.tcard:hover, a.tcd:hover, a.fedcard:hover, a.ncard:hover, a.file-card:hover, a.link-card:hover, a.hcard:hover, a.ibar:hover {
    transform: translateY(-4px); box-shadow: var(--mo-lift); }
  .ta, .tgo, .ngo, a.more, .trk-cta { transition: transform .25s var(--mo-out); }
  a:hover > .tb > .ta, a:hover .tgo, a:hover .ngo, a.more:hover, .trk-cta:hover { transform: translateX(4px); }
  .tcard .ph img { transition: transform .8s var(--mo-out); }
  .tcard:hover .ph img { transform: scale(1.04); }
}
.btn, .chip { transition: transform var(--mo-fast) var(--mo-out), background-color var(--mo-fast), color var(--mo-fast), border-color var(--mo-fast), filter var(--mo-fast); }
.btn:hover { transform: translateY(-1px); }
.btn:active, .chip:active { transform: translateY(1px) scale(.98); }

/* Two-way switches (.cv-mode: Early Vote 2026 | All Races): a thumb slides under the pressed button (motion.js). */
.mo-seg { position: relative; isolation: isolate; }
.mo-seg .mo-thumb { position: absolute; z-index: -1; top: 0; left: 0; height: 100%; border-radius: 30px; background: var(--ink);
  transition: transform var(--mo-mid) var(--mo-out), width var(--mo-mid) var(--mo-out); pointer-events: none; }
html.mo .mo-seg .chip[aria-pressed="true"] { background: transparent; border-color: transparent; color: var(--surface); }
html.mo .mo-seg .chip { transition: color .3s var(--mo-std), border-color .3s var(--mo-std); }

/* Map hover cards: glass, a short scale-in each time they open, and a smooth follow. */
.cv-tip:not([hidden]), .mm-tip:not([hidden]), .cmap-tip:not([hidden]) { animation: mo-tip .22s var(--mo-out); }
.cv-tip { transition: left .12s var(--mo-out), top .12s var(--mo-out); }
@keyframes mo-tip { from { opacity: 0; transform: translateY(6px) scale(.97); } to { opacity: 1; transform: none; } }

/* Live dots (Topics, Latest, Breaking) breathe. */
.tops-dot, .nbrk::before { position: relative; }
.tops-dot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: inherit; animation: mo-ping 1.8s cubic-bezier(0, 0, .2, 1) infinite; }
@keyframes mo-ping { 0% { transform: scale(1); opacity: .65; } 100% { transform: scale(2.6); opacity: 0; } }

/* Count-ups keep their width while the digits change. */
.mo-num { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  html.mo .mo-r, html.mo .mo-bar, html.mo .mo-map .ev-pie, html.mo .mo-map .mm-dot circle, html.mo .mo-map path { opacity: 1 !important; transform: none !important; clip-path: none !important; animation: none !important; }
  .tops-dot::after, .cv-tip, .mm-tip, .cmap-tip { animation: none !important; }
  .hx.sth *, .bhero * { animation: none !important; }
  .hero > .wrap > *, .hero h1 .hl, .dc-hero *, .hx.fl *, .nstrip li, .nlist .nrow, .mo-map .dc-dot circle { animation: none !important; clip-path: none !important; }
  .cmap-svg .cty { transition: none !important; }
}

/* ---- Homepage (v4) ------------------------------------------------------------------------------------------------ */
/* Hero: headline, lede and address bar rise in one after another; the key-dates card slides in from the right. */
html.mo:not(.mo-off) .home-hx .hx-left > *, html.mo:not(.mo-off) .home-hx .hdate-card { animation: mo-rise .9s var(--mo-out) backwards; }
.home-hx .hx-left > :nth-child(2) { animation-delay: 60ms; }
.home-hx .hx-left > :nth-child(3) { animation-delay: 140ms; }
.home-hx .hx-left > :nth-child(4) { animation-delay: 240ms; }
.home-hx .hx-left > :nth-child(5) { animation-delay: 320ms; }
html.mo:not(.mo-off) .home-hx .hdate-card { animation-name: mo-slide; animation-delay: 260ms; }
@keyframes mo-rise { from { opacity: 0; transform: translateY(22px); } to { opacity: 1; transform: none; } }
@keyframes mo-slide { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
/* "Election Day." gets a lime marker stroke that sweeps in under it. */
.home-hx #e26-count { background-image: linear-gradient(var(--lime), var(--lime)); background-repeat: no-repeat; background-position: 0 88%; background-size: 100% .16em; }
html.mo:not(.mo-off) .home-hx #e26-count { animation: mo-mark 1.2s var(--mo-out) .55s backwards; }
@keyframes mo-mark { from { background-size: 0 .16em; } to { background-size: 100% .16em; } }
html.gloss .home-hx #e26-count { background-image: linear-gradient(rgba(217, 250, 128, .55), rgba(217, 250, 128, .55)); }
/* The address box lights up when it has focus. */
.home-hx .blook input { transition: box-shadow .25s var(--mo-out), border-color .25s var(--mo-out); }
.home-hx .blook input:focus { box-shadow: 0 0 0 4px rgba(214, 245, 121, .55); }
/* Early-vote map: the state under the pointer lifts slightly. */
@media (hover: hover) {
  .home-states .cv-st path { transition: fill .15s, opacity .2s, filter .2s; }
  .home-states .cv-st:hover path, .home-states .cv-st.hl path { filter: brightness(1.06) drop-shadow(0 2px 4px rgba(0, 0, 0, .18)); }
  .home-states .ev-rank li { transition: transform .2s var(--mo-out), background-color .2s; }
  .home-states .ev-rank li.hl { transform: translateX(3px); }
}
/* Featured band: the illustration drifts slowly. */
html.mo .band .hx-bg img { animation: mo-drift 22s ease-in-out infinite alternate; }
@keyframes mo-drift { from { transform: translate3d(0, 0, 0) scale(1.02); } to { transform: translate3d(-14px, -8px, 0) scale(1.06); } }
@media (prefers-reduced-motion: reduce) {
  .home-hx .hx-left > *, .home-hx .hdate-card, .home-hx #e26-count, .band .hx-bg img { animation: none !important; }
}

/* Phase 3 templates: Files' panels and recipient cards lift; topic vote rows open smoothly. */
@media (hover: hover) { .grid > .panel, .recipient { transition: transform .3s var(--mo-out), box-shadow .3s var(--mo-out); }
  a.recipient:hover { transform: translateY(-3px); box-shadow: var(--mo-lift); } }
.tp-vote[open] > :not(summary) { animation: mo-rise .35s var(--mo-out); }
html.mo:not(.mo-off) .timeline > li.mo-r { transform: translateX(-12px); }
html.mo:not(.mo-off) .timeline > li.mo-r.mo-in { transform: none; }
