/* Laminate animation for slide 2. Loaded after styles.css.

   Each layer is a sheet of clear tinted film laid over the map. On its step, the film (sheet, tab and lines) is
   revealed by a diagonal wipe from the top-left corner. Once the sheet lands, its tint relaxes so later sheets
   don't wash out the lines under them; then the labels pop out of their points and the legend row joins the card.

   Animations start when deck.js adds .is-shown and stop the moment it is removed, so stepping back lifts the sheet
   at once. Stepping back into the slide from the next one shows the end state without replaying (.instant). */

.laminates {
  /* The sheet's box on the stage. The top margin leaves room for the tabs. */
  --sheet-t: 64px; --sheet-r: 20px; --sheet-b: 20px; --sheet-l: 20px;
  --lay: 1.7s;                              /* how long one sheet takes to cover the map */
  --lay-ease: cubic-bezier(.5, .04, .22, 1);
  --land: calc(var(--lay) - .15s);          /* when labels and the legend begin */
  --tab-step: 256px; --tab-w: 240px;
}

/* ---- the film ---- */
.laminates .film { position: absolute; inset: 0; visibility: hidden; }
.laminates .film.is-shown { visibility: visible; animation: film-lay var(--lay) var(--lay-ease) both; }
/* A triangle growing from the top-left corner: its edge is a 45-degree line sweeping to the bottom-right.
   3100px reaches past the far corner (1920 + 1080). */
@keyframes film-lay {
  from { clip-path: polygon(-60px -60px, -60px -60px, -60px -60px); }
  to   { clip-path: polygon(-60px -60px, 3100px -60px, -60px 3100px); }
}

.laminates .sheet {
  inset: var(--sheet-t) var(--sheet-r) var(--sheet-b) var(--sheet-l); opacity: 1; border-radius: 18px;
  background:
    linear-gradient(115deg, transparent 34%, rgba(255, 255, 255, .10) 41%, transparent 49%),   /* gloss */
    color-mix(in srgb, var(--c) var(--tint), rgba(255, 255, 255, var(--wash-a)));
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 255, 255, .8),
    inset 0 0 0 3px color-mix(in srgb, var(--c) 35%, transparent),
    0 10px 26px rgba(27, 36, 51, .10);
  --tint: 6%; --wash-a: .06;
}
.laminates .film.is-shown .sheet { animation: sheet-relax .9s ease-out var(--land) both; }
@property --tint { syntax: "<percentage>"; inherits: false; initial-value: 6%; }
@property --wash-a { syntax: "<number>"; inherits: false; initial-value: .06; }
@keyframes sheet-relax { from { --tint: 6%; --wash-a: .06; } to { --tint: 2%; --wash-a: .015; } }

/* The tab: one per layer, stepped along the top edge like index tabs on overlay sheets. */
.laminates .tab {
  position: absolute; left: calc(var(--sheet-l) + 40px + var(--i) * var(--tab-step)); top: calc(var(--sheet-t) - 44px);
  width: var(--tab-w); height: 46px; display: flex; align-items: center; justify-content: center;
  font: 600 24px/1 var(--display); letter-spacing: .04em; text-transform: uppercase; color: #fff;
  background: var(--c); border-radius: 12px 12px 0 0;
  box-shadow: inset 0 2px 0 rgba(255, 255, 255, .35), 0 -2px 10px rgba(27, 36, 51, .12);
}

/* Lines stay on the sheet. */
.laminates .features { clip-path: inset(var(--sheet-t) var(--sheet-r) var(--sheet-b) var(--sheet-l) round 18px); }

/* ---- labels ---- */
.laminates .geo[data-n="1"] { --n: 1; }
.laminates .geo[data-n="2"] { --n: 2; }
.laminates .geo { --n: 0; opacity: 0; }
.laminates .geo.is-shown { animation: label-pop .55s cubic-bezier(.3, 1.5, .5, 1) calc(var(--land) + var(--n) * .16s) both; }
@keyframes label-pop {
  from { opacity: 0; transform: scale(.35); }
  to   { opacity: 1; transform: scale(1); }
}
/* A ping on the point as its label appears. */
.laminates .geo .dot::after {
  content: ""; position: absolute; inset: -3px; border-radius: 50%; border: 3px solid var(--c); opacity: 0;
}
.laminates .geo.is-shown .dot::after { animation: ping .8s ease-out calc(var(--land) + var(--n) * .16s + .1s) both; }
@keyframes ping { from { opacity: .9; transform: scale(1); } to { opacity: 0; transform: scale(3.6); } }

/* ---- legend ---- */
/* The card grows by one row per sheet laid (--rows, set on the slide by laminate.js). */
.laminates #s2-legend-card {
  height: calc(44px + var(--rows) * 100px); opacity: 0;
  transition: height .45s cubic-bezier(.2, .8, .3, 1) var(--land);
}
.laminates #s2-legend-card.is-shown { animation: card-in .5s cubic-bezier(.2, .8, .3, 1) var(--land) both; }
@keyframes card-in { from { opacity: 0; transform: translateX(60px); } to { opacity: 1; transform: none; } }

.laminates .legend-row { opacity: 0; }
.laminates .legend-row.is-shown { animation: row-in .45s cubic-bezier(.2, .8, .3, 1) calc(var(--land) + .25s) both; }
@keyframes row-in { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
/* The legend's line draws itself. */
.laminates .legend-row.is-shown svg { animation: glyph-draw .5s ease-out calc(var(--land) + .4s) both; }
@keyframes glyph-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* ================================================================ into the app (steps 5 and 6) */
/* laminate.js sets .app-mode from step 5 and .app-in from step 6. */

/* A piece of an app screenshot, at its own place on the stage. --x/--y/--w/--h is the piece's box in the
   1920 x 1080 window; the 2x screenshot is drawn at 1x so the piece stays sharp. */
.laminates .crop {
  position: absolute; left: var(--x); top: var(--y); width: var(--w); height: var(--h);
  background: url("assets/app/q1-typed.webp") calc(-1 * var(--x)) calc(-1 * var(--y)) / 1920px 1080px no-repeat;
}
.laminates .crop.from-answer { background-image: url("assets/app/q1-answer.webp"); }
.laminates .crop.from-cite { background-image: url("assets/app/q1-cite.webp"); }
.laminates .crop.from-hover { background-image: url("assets/app/q1-hover.webp"); }
.laminates .crop.from-q2typed { background-image: url("assets/app/q2-typed.webp"); }
.laminates .crop.from-q2answer { background-image: url("assets/app/q2-answer.webp"); }
.laminates .crop.from-q3map { background-image: url("assets/app/q3-map.webp"); }
.laminates .crop.from-q330 { background-image: url("assets/app/q3-30days.webp"); }
.laminates .crop.from-q3pan { background-image: url("assets/app/q3-pan.webp"); }
.laminates .crop.from-q3hover { background-image: url("assets/app/q3-hover.webp"); }
.laminates .crop.from-q3pin { background-image: url("assets/app/q3-pin.webp"); }

/* The lens: laminate.js sets its transform (a zoom about a point) per step. */
.laminates .lens { position: absolute; inset: 0; transform-origin: 0 0; }

/* The app's map under the camera, without its bars. */
#s2-app-under { clip-path: inset(74px 0 104px 0); }
.laminates { background: #F2F3EF; }   /* the map's land color, for the corners nothing covers mid-move */

/* ---- step 5: clear the overlays ---- */
.laminates .camera { position: absolute; inset: 0; transform-origin: 0 0; transition: transform 1.3s cubic-bezier(.6, 0, .25, 1) .2s; }
/* From the views: the deck's base map (assets/stage.json) onto the app's map in q1-typed (layout.json), 13.8% closer in. */
.laminates.app-mode .camera { transform: matrix(1.13784, 0, 0, 1.13784, 83.77, -153.10); }

.laminates.app-mode .geo.is-shown { animation: fade-out .3s ease-in both; }
@keyframes fade-out { to { opacity: 0; } }
.laminates .tab { transition: opacity .35s ease-in, transform .35s ease-in; }
.laminates.app-mode .tab { opacity: 0; transform: translateY(-40px); }
.laminates .film .sheet { transition: opacity .6s ease; }
.laminates.app-mode .film .sheet { opacity: 0; }
/* The lines leave their sheets for the full window, as the app draws them. */
.laminates .features { transition: clip-path .8s ease; }
.laminates.app-mode .features { clip-path: inset(0 0 0 0 round 0px); }

/* The legend card shrinks onto the app's map key; the key fades in over it. */
.laminates.app-mode #s2-legend-card {
  left: 1644px; top: 688px; width: 264px; height: 354px; border-radius: 14px;
  transition: left .9s cubic-bezier(.6, 0, .25, 1) .15s, top .9s cubic-bezier(.6, 0, .25, 1) .15s,
              width .9s cubic-bezier(.6, 0, .25, 1) .15s, height .9s cubic-bezier(.6, 0, .25, 1) .15s,
              border-radius .9s ease .15s;
}
.laminates.app-mode .legend-row.is-shown { animation: fade-out .25s ease-in both; }
#s2-app-key { z-index: 2; border-radius: 14px; opacity: 0; transition: opacity .6s ease; }
.laminates.app-mode #s2-app-key { opacity: 1; transition-delay: .4s; }

/* ---- step 6: the app comes in ---- */
.laminates .app-bar { z-index: 4; border-radius: 14px; opacity: 0; box-shadow: var(--lift);
  transition: transform .65s cubic-bezier(.2, .8, .3, 1), opacity .3s ease; }
#s2-app-topbar { transform: translateY(-90px); }
#s2-app-askbar { transform: translateY(110px); transition-delay: .15s; }
.laminates.app-in #s2-app-topbar, .laminates.app-in #s2-app-askbar { opacity: 1; transform: none; }

/* The window fades in under the bars once they have landed: the app's own lines, pins, zoom and footer. */
#s2-app-typed { opacity: 0; transition: opacity .9s ease .7s; }
.laminates.app-in #s2-app-typed { opacity: 1; }

/* The empty ask box. */
.ask-empty { position: absolute; inset: 0; }
.ask-empty .ask-cover { position: absolute; left: 58px; right: 80px; top: 5px; height: 46px; background: #fff; }   /* the pin stays */

/* ---- step 7: type the question ---- */
/* laminate.js moves the cover's left edge across the typed question, one letter at a time. The hint and the resting
   button go first, so the screenshot's own yellow Ask shows: the app lights it once there is text. */
.ask-empty .ask-hint, .ask-empty .ask-rest { transition: opacity .15s ease; }
.laminates.typing .ask-empty .ask-hint, .laminates.typing .ask-empty .ask-rest { opacity: 0; }
.ask-empty .caret { position: absolute; left: -1px; top: 11px; width: 2px; height: 26px; background: var(--ink); opacity: 0; }
.laminates.typing .ask-empty .caret { opacity: 1; animation: blink 1s steps(1) .9s infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ---- step 8: click Ask, zoom in, open the answer ---- */
.laminates .pointer { position: absolute; left: 0; top: 0; z-index: 6; width: 48px; height: 48px; opacity: 0;
  transform-origin: 6px 4px; filter: drop-shadow(0 2px 3px rgba(27, 36, 51, .35)); pointer-events: none; }
.laminates .pointer svg { width: 100%; height: 100%; display: block; }
/* A pointer goes from (--x0, --y0) to (--x1, --y1), clicks, and fades; the tip is at (6, 4) of its 48 px box.
   --pd delays it; --o0 is its opacity at the start (1 when it carries on from the last step's pointer). */
.laminates .pointer { --pd: 0s; --o0: 0; }
@keyframes pointer-click {
  0%   { opacity: var(--o0); transform: translate(calc(var(--x0) - 6px), calc(var(--y0) - 4px)); }
  12%  { opacity: 1; }
  60%  { transform: translate(calc(var(--x1) - 6px), calc(var(--y1) - 4px)); }
  66%  { transform: translate(calc(var(--x1) - 6px), calc(var(--y1) - 4px)) scale(.84); }
  74%  { transform: translate(calc(var(--x1) - 6px), calc(var(--y1) - 4px)) scale(1); }
  88%  { opacity: 1; }
  100% { opacity: 0; transform: translate(calc(var(--x1) - 6px), calc(var(--y1) - 4px)); }
}
/* The same, but it stays where it lands (a hover). */
@keyframes pointer-rest {
  0%   { opacity: var(--o0); transform: translate(calc(var(--x0) - 6px), calc(var(--y0) - 4px)); }
  15%  { opacity: 1; }
  100% { opacity: 1; transform: translate(calc(var(--x1) - 6px), calc(var(--y1) - 4px)); }
}
.laminates.ask-go #s2-pointer { animation: pointer-click 1.4s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }

/* A click: a light flash and a yellow ring on the box (--x/--y/--w/--h), after --pd. Filled forwards only, so
   nothing shows before the click (a dark overlay on the yellow button reads as green). */
.laminates .press { position: absolute; left: var(--x); top: var(--y); width: var(--w); height: var(--h); z-index: 5;
  border-radius: 8px; opacity: 0; pointer-events: none; }
@keyframes press {
  0%   { opacity: 1; background: rgba(255, 255, 255, .45); box-shadow: 0 0 0 0 rgba(255, 212, 59, .9); }
  100% { opacity: 0; background: rgba(255, 255, 255, 0); box-shadow: 0 0 0 22px rgba(255, 212, 59, 0); }
}
.laminates.ask-go #s2-ask-press { animation: press .55s ease-out var(--pd) forwards; }

/* The zoom: about the fixed point of q1-typed -> q1-answer (from their views in layout.json:
   x' = 2.24498 x - 410.98, y' = 2.24498 y - 978.75), i.e. (330.11, 786.16). The bars, the key and the footer are cut out of this copy; their own pieces stay still. */
#s2-app-fly { opacity: 0; transform-origin: 330.11px 786.16px;
  clip-path: polygon(0 74px, 1920px 74px, 1920px 680px, 1636px 680px, 1636px 980px, 0 980px); }
.laminates.ask-go #s2-app-fly { animation: fly 1.5s cubic-bezier(.5, 0, .2, 1) 1.5s both; }
@keyframes fly { from { opacity: 1; transform: none; } to { opacity: 1; transform: scale(2.24498); } }

/* The bars leave as the answer's window, with its own bars, fades in. */
.laminates.ask-go #s2-app-topbar, .laminates.ask-go #s2-app-askbar { opacity: 0; transition: opacity .5s ease 2.6s; }
#s2-ans-map { z-index: 3; opacity: 0; }
.laminates.ask-go #s2-ans-map { animation: fade-in .6s ease 2.6s both, sheet-hole 4s linear both; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
/* A hole where the sheet will open, until it has. */
@keyframes sheet-hole {
  0%, 99% { clip-path: polygon(evenodd, 0 0, 1920px 0, 1920px 1080px, 0 1080px, 0 0,
                               2px 64px, 2px 1052px, 422px 1052px, 422px 64px, 2px 64px); }
  100%    { clip-path: none; }
}
#s2-ans-sheet { position: absolute; left: 12px; top: 74px; width: 400px; height: 0; z-index: 3; overflow: hidden;
  border-radius: 14px; box-shadow: var(--lift); opacity: 0; }
.laminates.ask-go #s2-ans-sheet { animation: sheet-open .9s cubic-bezier(.2, .8, .3, 1) 3s both; }
@keyframes sheet-open { from { opacity: 1; height: 0; } to { opacity: 1; height: 968px; } }

/* ---- step 9: ring the headline ---- */
#s2-ring-headline { position: absolute; left: 22px; top: 130px; width: 380px; height: 70px; z-index: 5; border-radius: 14px;
  box-shadow: 0 0 0 4px var(--hl), 0 0 18px 3px rgba(255, 212, 59, .45); opacity: 0; pointer-events: none; }
.laminates.ring-on #s2-ring-headline { animation: ring-in .5s cubic-bezier(.3, 1.4, .5, 1) both; }
@keyframes ring-in { from { opacity: 0; transform: scale(1.12); } to { opacity: 1; transform: none; } }

/* ================================================================ Q1, continued (steps 10-11) */
/* Step 10: the ring leaves; citation 2 is clicked; its record's panel slides in. */
.laminates.cite #s2-ring-headline { animation: fade-out .3s ease both; }
.laminates.cite #s2-pointer-cite { animation: pointer-click 1.4s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.cite #s2-cite-press { animation: press .55s ease-out var(--pd) forwards; }
#s2-cite-map, #s2-cite-panel, #s2-hover-map, #s2-hover-tip { z-index: 3; opacity: 0; }
#s2-cite-map { clip-path: inset(0 380px 0 0); }   /* its panel comes in as its own piece */
.laminates.cite #s2-cite-map { animation: fade-in .35s ease .95s both; }
#s2-cite-panel { box-shadow: -10px 0 30px rgba(27, 36, 51, .14); }
.laminates.cite #s2-cite-panel { animation: panel-in .5s cubic-bezier(.2, .8, .3, 1) .95s both; }
@keyframes panel-in { from { opacity: 1; transform: translateX(400px); } to { opacity: 1; transform: none; } }

/* Step 11: hover the green lane; its tip pops out. */
.laminates.hover #s2-pointer-hover { animation: pointer-rest .9s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.hover #s2-hover-map { animation: fade-in .2s ease 1.2s both; }
#s2-hover-tip { border-radius: 10px; transform-origin: 8px 8px; }
.laminates.hover #s2-hover-tip { animation: tip-in .35s cubic-bezier(.3, 1.4, .5, 1) 1.2s both; }
@keyframes tip-in { from { opacity: 0; transform: scale(.85); } to { opacity: 1; transform: none; } }

/* ================================================================ Q2: the Rocky Run (steps 12-16) */
/* Step 12: New topic. The hover ends, the panel slides away, the empty ask box comes back. */
.laminates.newtopic #s2-pointer-hover { animation: fade-out 0s both; }
.laminates.newtopic #s2-pointer-new { animation: pointer-click 1.4s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.newtopic #s2-new-press { animation: press .55s ease-out var(--pd) forwards; }
.laminates.newtopic #s2-cite-panel { animation: panel-out .55s ease-in 1.2s both; }
@keyframes panel-out { from { opacity: 1; transform: none; } to { opacity: 1; transform: translateX(400px); } }
.laminates.newtopic #s2-hover-tip { animation: fade-out .2s ease 1.15s both; }
#s2-q2 { position: absolute; inset: 0; z-index: 3; opacity: 0; }
.laminates.newtopic #s2-q2 { animation: fade-in .7s ease 1.45s both; }
/* The q2 ask box is the same bar as the answer's (x 424 to 1632), so its hint and resting button fit as they are. */
#s2-q2 .ask-cover { position: absolute; left: 470px; right: 368px; top: 991px; height: 46px; background: #fff; }   /* right edge fixed at the Ask button (x 1552) */
#s2-q2 .ask-hint, #s2-q2 .ask-rest { transition: opacity .15s ease; }
.laminates.typing2 #s2-q2 .ask-hint, .laminates.typing2 #s2-q2 .ask-rest { opacity: 0; }
#s2-q2 .caret { position: absolute; left: -1px; top: 11px; width: 2px; height: 26px; background: var(--ink); opacity: 0; }
.laminates.typing2 #s2-q2 .caret { opacity: 1; animation: blink 1s steps(1) .9s infinite; }

/* Step 14: Ask. The map zooms out about the fixed point of q2-typed -> q2-answer (from their views in layout.json:
   x' = 0.147839 x + 1041.58, y' = 0.147839 y + 989.06), i.e. (1222.28, 1160.65). */
.laminates.ask2 #s2-pointer-ask2 { animation: pointer-click 1.4s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.ask2 #s2-ask2-press { animation: press .55s ease-out var(--pd) forwards; }
#s2-q2-map, #s2-q2-sheet { z-index: 3; opacity: 0; }
#s2-q2-fly { opacity: 0; }
/* The answer's window, with a hole over the sheet so the old answer stays until the new one wipes over it. */
.laminates.ask2 #s2-q2-map { animation: fade-in .5s ease 1.6s both, sheet-hole 4.8s linear both; }
/* Clipped to the map area on screen (the wrapper), so the shrinking map never passes over the bars or the sheet. */
#s2-q2-flywrap { position: absolute; inset: 0; z-index: 3;
  clip-path: polygon(424px 74px, 1920px 74px, 1920px 640px, 1636px 640px, 1636px 980px, 424px 980px); }
/* The copy itself is cut to its own map too (no sheet, bars or key), so none of them shrink into view. */
#s2-q2-fly { transform-origin: 1222.28px 1160.65px;
  clip-path: polygon(424px 74px, 1920px 74px, 1920px 640px, 1636px 640px, 1636px 980px, 424px 980px); }
.laminates.ask2 #s2-q2-fly { animation: fly-out 2.3s cubic-bezier(.45, 0, .2, 1) 1.6s both; }
@keyframes fly-out {
  0%   { opacity: 1; transform: none; }
  60%  { opacity: 1; }
  100% { opacity: 0; transform: scale(.147839); }
}
#s2-q2-sheet { border-radius: 14px; }
.laminates.ask2 #s2-q2-sheet { animation: sheet-wipe 1.2s cubic-bezier(.3, .7, .3, 1) 3.5s both; }
@keyframes sheet-wipe { from { opacity: 1; clip-path: inset(0 0 100% 0); } to { opacity: 1; clip-path: inset(0 0 0 0); } }

/* Steps 15-16: one ring lit at a time, the rest of the frame dimmed, a card beside it. */
.laminates .spot { position: absolute; left: var(--x); top: var(--y); width: var(--w); height: var(--h); z-index: 5;
  border-radius: 10px; opacity: 0; pointer-events: none;
  box-shadow: 0 0 0 4px var(--hl), 0 0 0 9999px rgba(27, 36, 51, .42); }
.laminates .callout { position: absolute; left: var(--x); top: var(--y); z-index: 5; width: 470px; opacity: 0;
  display: flex; flex-direction: column; gap: 6px; padding: 16px 20px 18px 24px; background: var(--surface);
  border-radius: 14px; box-shadow: var(--high), inset 6px 0 0 var(--hl); }
.laminates .callout b { font: 700 24px/1.2 var(--ui); color: var(--ink); }
.laminates .callout span { font: 400 19px/1.35 var(--ui); color: var(--muted); }
.laminates.infer #s2-spot-date { animation: fade-in .6s ease 1s both; }
.laminates.infer #s2-callout-date { animation: cap-in-left .6s cubic-bezier(.2, .8, .3, 1) 1.5s both; }
.laminates.tavily #s2-spot-date, .laminates.tavily #s2-callout-date { animation: fade-out .45s ease both; }
.laminates.tavily #s2-spot-web { animation: fade-in .6s ease .45s both; }
.laminates.tavily #s2-callout-web { animation: cap-in-left .6s cubic-bezier(.2, .8, .3, 1) .95s both; }
@keyframes cap-in-left { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: none; } }

/* ================================================================ the request path (top right) */
/* Shown once each answer has landed; hidden while the lens is on the citation, the hover and the second question. */
.laminates .arch-strip { position: absolute; right: 24px; top: 84px; width: 800px; height: 155px; z-index: 7; opacity: 0;
  background: rgba(255, 255, 255, .96); border-radius: 16px; box-shadow: var(--high); pointer-events: none;
  transition: opacity .4s ease; }
.arch-strip svg { width: 100%; height: 100%; display: block; }
.arch-strip .a-node rect { fill: var(--surface); stroke: var(--rule); stroke-width: 1.5; transition: fill .4s, stroke .4s; }
.arch-strip .a-node text { font: 600 15px var(--ui); fill: var(--ink); text-anchor: middle; }
.arch-strip .a-node text.s { font: 400 12px var(--ui); fill: var(--muted); }
.arch-strip .a-node.model rect { fill: var(--ink); stroke: none; }
.arch-strip .a-node.model text { fill: #fff; }
.arch-strip .a-node.model text.s { fill: rgba(255, 255, 255, .8); }
.arch-strip .a-node.web rect { stroke-dasharray: 5 4; stroke: var(--muted); }
.arch-strip .a-edge { fill: none; stroke: var(--rule); stroke-width: 2; transition: stroke .4s; }
.arch-strip .a-edge.web { stroke-dasharray: 5 4; }
/* Off the path: faded. On it: dark edges, tools in the highlighter's yellow. */
.arch-strip .a-node, .arch-strip .a-edge { opacity: .3; transition: opacity .4s ease; }
.arch-strip .on { opacity: 1; }
.arch-strip .a-edge.on { stroke: var(--ink); }
.arch-strip .a-node.tool.on rect, .arch-strip .a-node.web.on rect { fill: var(--hl); stroke: var(--ink); }
.arch-strip .a-node.store.on rect { stroke: var(--ink); stroke-width: 2.5; }
.arch-strip .pulse rect { animation: a-pulse 1.1s ease-in-out 2; }
@keyframes a-pulse { 50% { stroke-width: 5; } }

.laminates.ask-go #s2-arch { opacity: 1; transition-delay: 3.9s; }
.laminates.cite #s2-arch { opacity: 0; transition-delay: 0s; }
.laminates.ask2 #s2-arch { opacity: 1; transition-delay: 4.9s; }

/* ================================================================ Q3: browsing the map (steps 17-18) */
/* A yellow ring without the dimming, for short pointers. */
.laminates .ring2 { position: absolute; left: var(--x); top: var(--y); width: var(--w); height: var(--h); z-index: 5;
  border-radius: 10px; opacity: 0; pointer-events: none;
  box-shadow: 0 0 0 4px var(--hl), 0 0 18px 3px rgba(255, 212, 59, .5); }

/* Step 17: the Rocky Run cards and the strip leave; the map over Center City comes back. */
.laminates.q3 #s2-spot-web, .laminates.q3 #s2-callout-web { animation: fade-out .3s ease both; }
.laminates.q3 #s2-arch { opacity: 0; transition-delay: 0s; }
#s2-q3-map, #s2-q3-30, #s2-q3-pan, #s2-q3-hover, #s2-q3-tip, #s2-q3-pin, #s2-q3-panel { z-index: 3; opacity: 0; }
.laminates.q3 #s2-q3-map { animation: fade-in .5s ease .3s both; }
.laminates.q3 #s2-pointer-30 { animation: pointer-click 1.4s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.q3 #s2-press-30 { animation: press .55s ease-out var(--pd) forwards; }
.laminates.q3 #s2-q3-30 { animation: fade-in .25s ease 1.85s both; }
.laminates.q3 #s2-ring-30 { animation: ring-blink 1s ease 1.8s both; }
@keyframes ring-blink { 0% { opacity: 0; transform: scale(1.15); } 25%, 70% { opacity: 1; transform: none; } 100% { opacity: 0; } }

/* The whip south: 0.6 s, a little blur at speed. The real move is 1,850 px; it is drawn as one screen so the two
   maps touch. The frame and both maps leave out the bars, zoom buttons, key and footer, which stay still. */
.laminates .q3-whip, .laminates .q3-whip > .crop {
  clip-path: path(evenodd, "M0 0 H1920 V1080 H0 Z M12 12 H896 V62 H12 Z M1874 8 H1916 V68 H1874 Z M8 980 H1636 V1050 H8 Z M1640 684 H1912 V1046 H1640 Z M0 1050 H1920 V1080 H0 Z"); }
.laminates .q3-whip { position: absolute; inset: 0; z-index: 3; visibility: hidden; }
.laminates.q3 .q3-whip { animation: whip-show .6s linear 2.5s both; }
@keyframes whip-show { from { visibility: visible; } to { visibility: visible; } }
.laminates.q3 .q3-whip .whip-out { animation: whip-out .6s cubic-bezier(.55, 0, .35, 1) 2.5s both; }
.laminates.q3 .q3-whip .whip-in { animation: whip-in .6s cubic-bezier(.55, 0, .35, 1) 2.5s both; }
@keyframes whip-out { from { transform: none; filter: none; } 50% { filter: blur(5px); } to { transform: translateY(-1080px); filter: none; } }
@keyframes whip-in { from { transform: translateY(1080px); filter: none; } 50% { filter: blur(5px); } to { transform: none; filter: none; } }
.laminates.q3 #s2-q3-pan { animation: fade-in .12s linear 3.08s both; }

/* Hover the Afrojack pin; its tip pops out. */
.laminates.q3 #s2-pointer-pin { animation: pointer-rest .9s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.q3 #s2-q3-hover { animation: fade-in .2s ease 4.2s both; }
#s2-q3-tip { border-radius: 10px; transform-origin: 6px 6px; }
.laminates.q3 #s2-q3-tip { animation: tip-in .35s cubic-bezier(.3, 1.4, .5, 1) 4.2s both; }

/* Step 18: click the pin; the listing's panel slides in; then the two rings. */
.laminates.q3pin #s2-pointer-pin, .laminates.q3pin #s2-q3-tip { animation: fade-out 0s both; }
.laminates.q3pin #s2-pointer-pinclick { animation: pointer-click 1.4s cubic-bezier(.45, 0, .25, 1) var(--pd) both; }
.laminates.q3pin #s2-press-pin { animation: press .55s ease-out var(--pd) forwards; }
#s2-q3-pin { clip-path: inset(0 380px 0 0); }
.laminates.q3pin #s2-q3-pin { animation: fade-in .3s ease .4s both; }
#s2-q3-panel { box-shadow: -10px 0 30px rgba(27, 36, 51, .14); }
.laminates.q3pin #s2-q3-panel { animation: panel-in .5s cubic-bezier(.2, .8, .3, 1) .4s both; }
.laminates.q3pin #s2-ring-listed { animation: ring-in .5s cubic-bezier(.3, 1.4, .5, 1) 2s both; }
.laminates.q3pin #s2-ring-link { animation: ring-in .5s cubic-bezier(.3, 1.4, .5, 1) 2.4s both; }

/* ---- stepping back: end state, no replay ---- */
.laminates.instant *, .laminates.instant *::before, .laminates.instant *::after {
  animation-duration: 0s !important; animation-delay: 0s !important; transition: none !important;
}
