/* ==========================================================================
   TaxTami — "The Zimbabwe that is seen" map timeline
   Loaded only by about-zimbabwe.html. Every rule is scoped to
   `body.tt-zw-page` so nothing reaches the shared header, footer or menus,
   which this page inherits unchanged from about.html.

   Two themes, one set of markup. Light is the default and matches the rest of
   the site: white surfaces, green ink, hairlines, 4px corners. Dark is opt-in
   via `data-zw-theme="dark"` on the section.
   ========================================================================== */

body.tt-zw-page .zw-stage {
  /* ── Light (default) ─────────────────────────────────────────────────── */
  --zw-page:     #ffffff;   /* behind the frame */
  --zw-frame:    #ffffff;   /* the frame itself */
  --zw-map-bg:   #f6faf7;
  --zw-panel:    #ffffff;

  --zw-line:     rgba(26, 80, 56, .13);
  --zw-line-2:   rgba(26, 80, 56, .22);

  --zw-text:     #17231d;
  --zw-strong:   #0b1f16;
  --zw-muted:    #5d6f66;
  --zw-dim:      #8a978f;

  --zw-green:    #1a5038;
  --zw-green-2:  #2c724f;
  --zw-fill:     #2c724f;   /* a province counted as covered */
  --zw-fill-new: #3d8b63;   /* the one this stop adds */
  --zw-fill-ink: #1a5038;   /* its outline */

  /* A milestone that carries an adverse figure claims its province in the
     flag red, and keeps it. */
  --zw-red:      #ce1126;
  --zw-red-ink:  #9c0d1d;

  --zw-off:      #e6ece8;   /* an unlit province */
  --zw-off-ink:  #cbd8d1;

  --zw-shadow:   0 1px 2px rgba(11,31,22,.04), 0 18px 44px rgba(11,31,22,.07);

  background: var(--zw-page);
  padding: clamp(20px, 3.5vw, 52px) clamp(12px, 3vw, 44px) clamp(28px, 4vw, 64px);
  color: var(--zw-text);
}

/* ── Dark ──────────────────────────────────────────────────────────────── */

body.tt-zw-page .zw-stage[data-zw-theme="dark"] {
  --zw-page:     #1c1f21;
  --zw-frame:    #101314;
  --zw-map-bg:   #101314;
  --zw-panel:    #14181a;

  --zw-line:     rgba(255, 255, 255, .08);
  --zw-line-2:   rgba(255, 255, 255, .16);

  --zw-text:     #dfe7e2;
  --zw-strong:   #ffffff;
  --zw-muted:    #93a099;
  --zw-dim:      #6a776f;

  --zw-green:    #8bc34a;
  --zw-green-2:  #a8dd6b;
  --zw-fill:     #8bc34a;
  --zw-fill-new: #a8dd6b;
  --zw-fill-ink: #b5e57e;

  /* Flag red is too dark to read against charcoal, so it lifts. */
  --zw-red:      #e63946;
  --zw-red-ink:  #ff6b76;

  --zw-off:      #23292b;
  --zw-off-ink:  #2f3639;

  --zw-shadow:   0 40px 90px rgba(0, 0, 0, .45);
}

/* ── Intro ─────────────────────────────────────────────────────────────── */

body.tt-zw-page .zw-intro {
  max-width: 1400px;
  margin: 0 auto clamp(18px, 2.5vw, 34px);
  padding: 0 4px;
}
/* Matched to the lesson page header in css/lessons.css §9, so the About page
   reads at the same scale as every lesson: the eyebrow takes .lesson-number's
   0.85rem / 700 / .07em, and the heading takes .lesson-name's 2rem / 800 /
   1.15. The old clamp(1.5rem, 3.2vw, 2.5rem) only reached 2rem on a screen
   wider than about 1000px — on a laptop it resolved to roughly 1.6rem, which
   is why this looked small beside a lesson. */
body.tt-zw-page .zw-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: .85rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--zw-green-2);
  margin-bottom: 6px;
}
body.tt-zw-page .zw-eyebrow::before {
  content: "";
  width: 24px;
  height: 2px;
  background: var(--zw-green-2);
}
/* !important is not decoration here. css/main.css line 5169 carries a
   site-wide blanket:

       h1, h2, h3, h4, h5, h6 { font-size: 16px !important;
                                font-weight: bold !important; }

   so every unqualified heading on the site renders at 16px. The lesson page
   header escapes it because `.lesson-name` is a <span>, not a heading — which
   is why the lesson title looks like a title and this one did not. Rather than
   demote this to a <span> and leave the page with no h1, the blanket is
   overridden for this one heading. Specificity decides between two !important
   declarations, and 0,2,2 beats 0,0,1. */
body.tt-zw-page .zw-intro h1 {
  font-family: 'Work Sans', sans-serif;
  font-size: 2rem !important;       /* .lesson-name */
  font-weight: 800 !important;      /* .lesson-name */
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: var(--zw-strong);
  margin: 0 0 10px;
  /* one line. The measure that kept it to 32ch is gone, and the line is held
     together explicitly — at 2rem the title runs to roughly 950px, which the
     1400px stage carries comfortably. */
  max-width: none;
  white-space: nowrap;
}
/* Measured, not assumed: at 32px the title's advance width is 891px in
   Liberation Sans Bold (Arial metrics) and 1068px in the wider DejaVu Sans
   Bold, less about 35px of -0.02em tracking — so call it 860-1030px. The stage
   spends up to 88px on horizontal padding, which puts the breaking point near
   1120px of viewport. The release is set above that, at 1180px, so the line
   never overflows on a font that measures wider than Work Sans. */
@media (max-width: 1180px) {
  /* Narrower than the title, so let it wrap rather than overflow the page.
     Shrinking the type instead would break the match with the lesson header,
     which is the thing that was asked for. */
  body.tt-zw-page .zw-intro h1 { white-space: normal; }
}
@media (max-width: 768px) {
  /* the same step-down the lesson header takes */
  body.tt-zw-page .zw-intro h1 { font-size: 1.5rem !important; }
}

/* ── "the Zimbabwe That Is Not" ─────────────────────────────────────────────
   Bastiat's unseen half, behaving like it: red, because everything adverse on
   this page is red, and it keeps going out of sight. It fades and blurs away,
   stays gone long enough to be noticed as missing, then returns — a loop
   rather than a one-way disappearance, because a heading that permanently
   erases half of itself reads as a bug, and the sentence has to survive for a
   reader who arrives late. `will-change` keeps the repaint off the main
   thread; the text stays selectable and screen readers always read it whole. */
body.tt-zw-page .zw-unseen {
  will-change: opacity, filter;
  animation: zw-unseen 9s ease-in-out infinite;
}
/* the conjunction goes with the clause, but only the clause is red */
body.tt-zw-page .zw-unseen-ink { color: var(--zw-red); }

@keyframes zw-unseen {
  0%, 26%   { opacity: 1;   filter: blur(0); }
  46%, 60%  { opacity: .06; filter: blur(3px); }
  80%, 100% { opacity: 1;   filter: blur(0); }
}
/* Runs the full width of the frame beneath it rather than stopping at a
   reading measure — at 1400px a 74ch cap broke the line in the middle of the
   page and left the right half empty. The frame's own width is the margin. */
body.tt-zw-page .zw-intro p {
  font-size: .92rem;
  line-height: 1.6;
  color: var(--zw-muted);
  max-width: none;
  margin: 0;
}

/* ── Frame ─────────────────────────────────────────────────────────────── */

body.tt-zw-page .zw-frame {
  max-width: 1400px;
  margin: 0 auto;
  background: var(--zw-frame);
  border: 1px solid var(--zw-line);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: var(--zw-shadow);
  display: grid;
  grid-template-rows: auto 1fr auto;
}

body.tt-zw-page .zw-topbar {
  display: flex;
  align-items: center;
  /* the theme toggle that sat on the right has been removed */
  justify-content: flex-start;
  gap: 16px;
  padding: 13px 20px;
  border-bottom: 1px solid var(--zw-line);
}
body.tt-zw-page .zw-topbar-title {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--zw-dim);
}

/* ── Map | chapter ─────────────────────────────────────────────────────── */

body.tt-zw-page .zw-main {
  display: grid;
  grid-template-columns: minmax(0, 46%) minmax(0, 54%);
  min-height: 0;
}

body.tt-zw-page .zw-map {
  position: relative;
  background: var(--zw-map-bg);
  border-right: 1px solid var(--zw-line);
  padding: 22px 22px 16px;
  display: flex;
  flex-direction: column;
  min-height: 400px;
}
body.tt-zw-page .zw-map-figure {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
body.tt-zw-page .zw-map svg {
  width: 100%;
  height: 100%;
  max-height: 460px;
  overflow: visible;
}

body.tt-zw-page .zw-map .zw-provinces path {
  fill: var(--zw-off);
  stroke: var(--zw-off-ink);
  stroke-width: 1;
  stroke-linejoin: round;
  transition: fill .5s cubic-bezier(.22,.61,.36,1),
              stroke .5s cubic-bezier(.22,.61,.36,1);
}
body.tt-zw-page .zw-map .zw-provinces path.is-lit {
  fill: var(--zw-fill);
  stroke: var(--zw-fill-ink);
}
body.tt-zw-page .zw-map .zw-provinces path.is-new {
  fill: var(--zw-fill-new);
}
/* A province claimed at a milestone that carries an adverse figure. It keeps
   the red for the rest of the read — the bad years do not stop counting.
   Ordered after .is-lit so it wins when both classes are present. */
body.tt-zw-page .zw-map .zw-provinces path.is-red {
  fill: var(--zw-red);
  stroke: var(--zw-red-ink);
}

/* ── Readout above the map ─────────────────────────────────────────────── */

body.tt-zw-page .zw-readout {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
  min-height: 34px;
}
body.tt-zw-page .zw-readout b {
  font-size: 1.9rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--zw-green-2);
}
body.tt-zw-page .zw-readout span {
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--zw-dim);
}
body.tt-zw-page .zw-map.is-adverse .zw-readout b { color: var(--zw-red); }

/* ── Legend ────────────────────────────────────────────────────────────── */

body.tt-zw-page .zw-legend {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--zw-line);
  font-size: .7rem;
  line-height: 1.6;
  color: var(--zw-dim);
}
body.tt-zw-page .zw-legend-keys {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin-bottom: 8px;
}
body.tt-zw-page .zw-legend-keys span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--zw-muted);
}
body.tt-zw-page .zw-legend-keys i {
  width: 13px;
  height: 13px;
  border-radius: 2px;
  flex: 0 0 auto;
}
body.tt-zw-page .zw-legend-keys .k-fill { background: var(--zw-fill); }
body.tt-zw-page .zw-legend-keys .k-red  { background: var(--zw-red); }
body.tt-zw-page .zw-legend-keys .k-off  { background: var(--zw-off); border: 1px solid var(--zw-off-ink); }
body.tt-zw-page .zw-legend a { color: var(--zw-muted); text-decoration: underline; }

/* ── The chapter ───────────────────────────────────────────────────────── */

body.tt-zw-page .zw-panel {
  background: var(--zw-panel);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Stays put while the chapter scrolls, so it is always clear which stop is
   being read. */
body.tt-zw-page .zw-panel-head {
  padding: 26px 30px 16px;
  border-bottom: 1px solid var(--zw-line);
  background: var(--zw-panel);
}
body.tt-zw-page .zw-panel-place {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--zw-green-2);
  margin-bottom: 6px;
}
body.tt-zw-page .zw-panel-year {
  font-family: 'Work Sans', sans-serif;
  font-size: clamp(1.8rem, 2.5vw, 2.4rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  color: var(--zw-strong);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
  margin: 0 0 6px;
}
body.tt-zw-page .zw-panel-heading {
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--zw-green);
  line-height: 1.4;
  margin: 0;
}

body.tt-zw-page .zw-panel-body {
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  max-height: 460px;
  padding: 20px 30px 26px;
  scrollbar-width: thin;
  scrollbar-color: var(--zw-line-2) transparent;
  transition: opacity .28s ease;
}
body.tt-zw-page .zw-panel-body::-webkit-scrollbar { width: 7px; }
body.tt-zw-page .zw-panel-body::-webkit-scrollbar-thumb {
  background: var(--zw-line-2);
  border-radius: 4px;
}
body.tt-zw-page .zw-panel.is-swapping .zw-panel-body { opacity: 0; }

/* The chapter markup comes straight from about.html, so these selectors have
   to cover what the essay actually uses. */
body.tt-zw-page .zw-panel-body .tt-tl-text,
body.tt-zw-page .zw-panel-body p {
  font-size: .95rem;
  line-height: 1.82;
  color: var(--zw-text);
  margin: 0 0 15px;
  max-width: 68ch;
}
body.tt-zw-page .zw-panel-body p:last-child { margin-bottom: 0; }
body.tt-zw-page .zw-panel-body strong { color: var(--zw-strong); font-weight: 700; }

body.tt-zw-page .zw-panel-body .tt-tl-quote {
  font-size: .98rem;
  font-weight: 600;
  font-style: italic;
  line-height: 1.7;
  color: var(--zw-green);
  background: none;
  border: 0;
  border-left: 3px solid var(--zw-red);
  border-radius: 0;
  padding: 4px 0 4px 20px;
  margin: 4px 0 18px;
  max-width: 62ch;
}
body.tt-zw-page .zw-stage[data-zw-theme="dark"] .zw-panel-body .tt-tl-quote {
  color: var(--zw-green-2);
}

body.tt-zw-page .zw-panel-body .tt-tl-list { list-style: none; margin: 0 0 16px; padding: 0; }
body.tt-zw-page .zw-panel-body .tt-tl-list li {
  font-size: .9rem;
  line-height: 1.7;
  color: var(--zw-muted);
  padding: 8px 0 8px 18px;
  border-bottom: 1px solid var(--zw-line);
  position: relative;
}
body.tt-zw-page .zw-panel-body .tt-tl-list li:last-child { border-bottom: none; }
body.tt-zw-page .zw-panel-body .tt-tl-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 17px;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--zw-green-2);
}

body.tt-zw-page .zw-panel-body .tt-tl-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin: 14px 0 0;
}
body.tt-zw-page .zw-panel-body .tt-tl-tag {
  font-size: .72rem;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--zw-line-2);
  color: var(--zw-muted);
}

/* The stat chips the map is built from, shown beside it rather than inside
   the prose. */
/* One row, tiles sized to their own content.
   Equal columns (grid-auto-columns: 1fr) gave every tile a third of the panel
   whatever it held, so "158 / Countries in the comparator dataset" sat in the
   same width as a long IMF label and the row stretched wall to wall. Flex with
   an `auto` basis distributes the row in proportion to content instead: each
   tile takes what it needs, short ones stay short, and the row ends where the
   content ends. `align-items: stretch` keeps the tops and bottoms level, so the
   result is still a tidy band rather than a ragged one. */
body.tt-zw-page .zw-stats {
  display: flex;
  flex-wrap: nowrap;
  align-items: stretch;
  justify-content: flex-start;
  gap: 8px;
  margin: 0 0 18px;
}
body.tt-zw-page .zw-stat {
  flex: 0 1 auto;          /* fit content, shrink only if the row runs out */
  background: var(--zw-map-bg);
  border: 1px solid var(--zw-line);
  border-radius: 4px;
  padding: 9px 11px;
  min-width: 0;
  /* a ceiling so one verbose label cannot swallow the row */
  max-width: 20ch;
}
body.tt-zw-page .zw-stat b {
  display: block;
  font-size: clamp(.98rem, 1.35vw, 1.14rem);
  font-weight: 800;
  color: var(--zw-red);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
body.tt-zw-page .zw-stat span {
  display: block;
  font-size: .64rem;
  line-height: 1.35;
  color: var(--zw-dim);
  margin-top: 3px;
  hyphens: auto;
}

/* Three tiles across a phone would be three words wide, so below 560px they
   wrap and each takes the full width. */
@media (max-width: 560px) {
  body.tt-zw-page .zw-stats { flex-wrap: wrap; }
  body.tt-zw-page .zw-stat { flex: 1 1 100%; max-width: none; }
}

/* ── Scrubber ──────────────────────────────────────────────────────────── */

body.tt-zw-page .zw-scrub {
  position: relative;
  border-top: 1px solid var(--zw-line);
  padding: 24px 26px 18px;
  user-select: none;
  touch-action: pan-y;
}
body.tt-zw-page .zw-scrub-track { position: relative; height: 42px; cursor: pointer; }
body.tt-zw-page .zw-scrub-track::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--zw-line-2);
}
body.tt-zw-page .zw-scrub-progress {
  position: absolute;
  left: 0; top: 0;
  width: 100%;
  height: 1px;
  background: var(--zw-green-2);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .35s cubic-bezier(.22,.61,.36,1);
}

body.tt-zw-page .zw-tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  background: none;
  border: 0;
  padding: 10px 6px 0;
  cursor: pointer;
  color: var(--zw-dim);
  font-size: .68rem;
  letter-spacing: .05em;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  transition: color .2s ease;
}
/* Drawn full length and scaled at rest, so growth is a compositor transform
   rather than a height animation that relayouts eleven siblings. */
body.tt-zw-page .zw-tick::before {
  content: "";
  position: absolute;
  left: 50%; top: 0;
  width: 1px; height: 14px;
  background: var(--zw-line-2);
  transform: translateX(-50%) scaleY(.5);
  transform-origin: top center;
  transition: background .2s ease, transform .2s ease;
}
body.tt-zw-page .zw-tick:hover { color: var(--zw-text); }
body.tt-zw-page .zw-tick.is-past { color: var(--zw-muted); }
body.tt-zw-page .zw-tick.is-past::before { background: var(--zw-green-2); }
body.tt-zw-page .zw-tick.is-current {
  color: #fff;
  background: var(--zw-green-2);
  border-radius: 3px;
  font-weight: 700;
  padding: 5px 10px;
  top: 14px;
}
body.tt-zw-page .zw-stage[data-zw-theme="dark"] .zw-tick.is-current { color: #0b1f16; }
body.tt-zw-page .zw-tick.is-current::before {
  top: -14px;
  background: var(--zw-green-2);
  transform: translateX(-50%) scaleY(1);
}
/* A milestone carrying an adverse figure is marked on the axis itself. */
body.tt-zw-page .zw-tick.is-adverse::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -9px;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--zw-red);
  transform: translateX(-50%);
}
body.tt-zw-page .zw-tick:focus-visible { outline: 2px solid var(--zw-green-2); outline-offset: 2px; }

body.tt-zw-page .zw-scrub-hint {
  margin-top: 12px;
  font-size: .7rem;
  color: var(--zw-dim);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}

/* ── Narrower screens ──────────────────────────────────────────────────── */

@media (max-width: 1100px) {
  body.tt-zw-page .zw-main { grid-template-columns: 1fr; }
  body.tt-zw-page .zw-map {
    border-right: none;
    border-bottom: 1px solid var(--zw-line);
    min-height: 340px;
  }
  body.tt-zw-page .zw-panel-body { max-height: none; overflow: visible; }
  body.tt-zw-page .zw-panel-head { padding: 22px 22px 14px; }
  body.tt-zw-page .zw-panel-body { padding: 18px 22px 24px; }
}

@media (max-width: 700px) {
  /* Eleven ticks cannot share a phone's width, so the axis becomes a
     scrolling strip and the ticks lay out in flow. The script checks for
     `position: static` and stops treating x as a date. */
  body.tt-zw-page .zw-scrub { padding: 16px 14px 14px; }
  body.tt-zw-page .zw-scrub-track {
    height: auto;
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-top: 10px;
    scrollbar-width: none;
  }
  body.tt-zw-page .zw-scrub-track::-webkit-scrollbar { display: none; }
  body.tt-zw-page .zw-scrub-progress { display: none; }
  body.tt-zw-page .zw-tick {
    position: static;
    transform: none;
    flex: 0 0 auto;
    padding: 7px 12px;
    border: 1px solid var(--zw-line-2);
    border-radius: 4px;
  }
  body.tt-zw-page .zw-tick::before { display: none; }
  body.tt-zw-page .zw-tick.is-current { top: 0; }
  body.tt-zw-page .zw-tick.is-adverse::after { bottom: 3px; left: auto; right: 5px; transform: none; }
  body.tt-zw-page .zw-scrub-hint { justify-content: flex-start; }
}

/* ── Motion opt-out ────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  body.tt-zw-page .zw-map .zw-provinces path,
  body.tt-zw-page .zw-scrub-progress,
  body.tt-zw-page .zw-panel-body { transition: none !important; }
}

/* ══ Slide controls ═══════════════════════════════════════════════════════
   Added 30 July 2026: the arrows either side of the frame, the cue telling the
   reader the chapter scrolls, and the bar showing how long is left before the
   timeline advances on its own.
   ═══════════════════════════════════════════════════════════════════════ */

body.tt-zw-page .zw-deck {
  position: relative;
  max-width: 1400px;
  margin: 0 auto;
  /* room for the arrows to sit outside the frame on wide screens */
  padding: 0 clamp(0px, 4vw, 62px);
}
body.tt-zw-page .zw-deck > .zw-frame { max-width: none; }

/* ── The arrows ────────────────────────────────────────────────────────── */

body.tt-zw-page .zw-nav {
  position: absolute;
  top: 50%;
  z-index: 3;
  width: 70px;
  height: 70px;
  margin-top: -35px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Solid brand green rather than an outlined chip. These two arrows are now
     the only slide control on the page — the Earlier / Later pair under the
     axis has been removed — so they have to read as the primary action from
     across the page, not as quiet chrome. */
  background: var(--zw-green);
  border: 0;
  border-radius: 50%;
  color: #fff;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(11, 31, 22, .22);
  transition: background .2s ease, transform .16s ease, box-shadow .2s ease,
              opacity .2s ease;
}
body.tt-zw-page .zw-nav svg { width: 32px; height: 32px; }
body.tt-zw-page .zw-nav-prev { left: 0; }
body.tt-zw-page .zw-nav-next { right: 0; }

body.tt-zw-page .zw-nav:hover:not(:disabled),
body.tt-zw-page .zw-nav:focus-visible:not(:disabled) {
  background: var(--zw-green-2);
  transform: scale(1.12);
  box-shadow: 0 10px 26px rgba(11, 31, 22, .3);
}
body.tt-zw-page .zw-nav:active:not(:disabled) { transform: scale(1.02); }
body.tt-zw-page .zw-nav:disabled { opacity: .26; cursor: default; box-shadow: none; }
body.tt-zw-page .zw-nav:focus-visible { outline: 3px solid var(--zw-green-2); outline-offset: 4px; }

/* ── The pop ───────────────────────────────────────────────────────────────
   Three things at once, so the control is hard to miss: the button breathes,
   a ring pulses out of it, and the chevrons lean the way they travel. It runs
   only until the reader uses the control — the script strips `is-idle` on the
   first interaction — so it announces itself once and then stops competing
   with the reading. */
@keyframes zw-pop {
  0%, 100% { transform: scale(1);    box-shadow: 0 6px 18px rgba(11,31,22,.22), 0 0 0 0 rgba(44,114,79,.45); }
  35%      { transform: scale(1.14); box-shadow: 0 8px 22px rgba(11,31,22,.26), 0 0 0 14px rgba(44,114,79,0); }
  60%      { transform: scale(1);    box-shadow: 0 6px 18px rgba(11,31,22,.22), 0 0 0 0 rgba(44,114,79,0); }
}
@keyframes zw-nudge-left {
  0%, 30%, 100% { transform: translateX(0); }
  45%           { transform: translateX(-6px); }
  60%           { transform: translateX(0); }
  70%           { transform: translateX(-3px); }
}
@keyframes zw-nudge-right {
  0%, 30%, 100% { transform: translateX(0); }
  45%           { transform: translateX(6px); }
  60%           { transform: translateX(0); }
  70%           { transform: translateX(3px); }
}
body.tt-zw-page .zw-nav.is-idle:not(:disabled) {
  animation: zw-pop 2.2s ease-in-out infinite;
}
body.tt-zw-page .zw-nav.is-idle:not(:disabled) svg {
  animation: zw-nudge-right 2.2s ease-in-out infinite;
}
body.tt-zw-page .zw-nav-prev.is-idle:not(:disabled) svg {
  animation-name: zw-nudge-left;
}
/* the pop must not fight a hover the reader is already giving it */
body.tt-zw-page .zw-nav.is-idle:hover,
body.tt-zw-page .zw-nav.is-idle:focus-visible { animation: none; }

/* Below the padding threshold the arrows would hang off the page, so they move
   inside the frame and sit over the map and the panel. */
@media (max-width: 1240px) {
  body.tt-zw-page .zw-deck { padding: 0; }
  body.tt-zw-page .zw-nav-prev { left: 10px; }
  body.tt-zw-page .zw-nav-next { right: 10px; }
  body.tt-zw-page .zw-nav { width: 58px; height: 58px; margin-top: -29px; }
  body.tt-zw-page .zw-nav svg { width: 26px; height: 26px; }
}
@media (max-width: 700px) {
  /* These used to be hidden on a phone because the Earlier / Later buttons
     covered the same job. Those are gone, so the arrows have to stay — moved
     down out of the reading column and shrunk to clear the text. */
  body.tt-zw-page .zw-nav { width: 50px; height: 50px; top: auto; bottom: 14px; margin-top: 0; }
  body.tt-zw-page .zw-nav svg { width: 23px; height: 23px; }
  body.tt-zw-page .zw-nav-prev { left: 12px; }
  body.tt-zw-page .zw-nav-next { right: 12px; }
}

/* ── "more below" ──────────────────────────────────────────────────────── */

body.tt-zw-page .zw-panel-scroller { position: relative; flex: 1 1 auto; min-height: 0; }

body.tt-zw-page .zw-scroll-cue {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 26px 0 8px;
  pointer-events: none;
  color: var(--zw-green-2);
  font-size: .64rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  /* a fade so text does not appear to stop dead behind the cue */
  background: linear-gradient(to bottom, transparent, var(--zw-panel) 62%);
  transition: opacity .3s ease;
}
body.tt-zw-page .zw-scroll-cue svg { width: 20px; height: 20px; }
/* set by the script once the chapter is scrolled to its end, or when it fits */
body.tt-zw-page .zw-panel.is-read .zw-scroll-cue { opacity: 0; }

@keyframes zw-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(5px); }
}
body.tt-zw-page .zw-scroll-cue svg { animation: zw-bob 1.9s ease-in-out infinite; }

/* ── Time until the next stop ──────────────────────────────────────────── */

body.tt-zw-page .zw-autobar {
  height: 2px;
  background: var(--zw-line);
  overflow: hidden;
  opacity: 0;
  transition: opacity .25s ease;
}
body.tt-zw-page .zw-panel.is-auto .zw-autobar { opacity: 1; }
body.tt-zw-page .zw-autobar i {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--zw-green-2);
  transform: scaleX(0);
  transform-origin: left center;
}
/* the script sets the duration to the chapter's own reading time */
body.tt-zw-page .zw-panel.is-auto .zw-autobar i {
  animation: zw-countdown linear forwards;
}
@keyframes zw-countdown { from { transform: scaleX(0); } to { transform: scaleX(1); } }

body.tt-zw-page .zw-auto[aria-pressed="true"] {
  color: var(--zw-green-2);
  border-color: var(--zw-green-2);
}

/* ── Motion opt-out ───────────────────────────────────────────────────────
   No nudge, no bob, no countdown. The script also refuses to auto-advance,
   so the bar would have nothing to count. */
@media (prefers-reduced-motion: reduce) {
  body.tt-zw-page .zw-unseen,
  body.tt-zw-page .zw-nav.is-idle,
  body.tt-zw-page .zw-nav.is-idle svg,
  body.tt-zw-page .zw-scroll-cue svg,
  body.tt-zw-page .zw-panel.is-auto .zw-autobar i { animation: none !important; }
  body.tt-zw-page .zw-unseen { opacity: 1 !important; filter: none !important; }
  body.tt-zw-page .zw-autobar { display: none; }
}

/* The body is now inside .zw-panel-scroller, which owns the height; the old
   fixed max-height would fight the wrapper and leave the cue floating. */
body.tt-zw-page .zw-panel-scroller > .zw-panel-body {
  max-height: none;
  height: 100%;
}
@media (max-width: 1100px) {
  /* stacked layout: the chapter runs at its natural height, so nothing scrolls
     inside the panel and the cue is not needed */
  body.tt-zw-page .zw-panel-scroller > .zw-panel-body { height: auto; }
}

/* The qualifier on an estimated figure — "roughly", "reached", "close to".
   On the same line as the number, so the tile stays one line tall. Lower case
   and no letter-spacing: both cost horizontal room, and three tiles share the
   row. Small and muted so the figure still leads and the hedge follows. */
/* Inline flow rather than flex: a flex container drops the whitespace between
   its items, so the copied text came out as "roughly10%". Ordinary inline
   layout keeps the real space and wraps the pair naturally. */
body.tt-zw-page .zw-stat .zw-qual {
  display: inline;
  font-family: inherit;
  font-style: normal;
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--zw-dim);
  white-space: nowrap;
}
