/* ==========================================================================
   Chapter 02: SVG motion
   ========================================================================== */
:root { --pink: #ff7eb6; }
.dot-svg { background: var(--pink); }
.demo .tags li.svg { border-color: color-mix(in oklab, var(--pink) 60%, transparent); color: var(--pink); }

/* ---------- Self-drawing illustration ---------- */
.draw-art { position: absolute; inset: 0; width: 100%; height: 100%; padding: 18px 18px 60px; }
.draw-art .ink path { fill: none; stroke: var(--ink); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.draw-art .g-far path { stroke: var(--violet); stroke-width: 1.8; }
.draw-art .g-near path { stroke-width: 2.2; }
.draw-art .g-hatch path { stroke: var(--mute); stroke-width: 1.1; }
.draw-art .g-sun path { stroke: var(--accent); }
.draw-art .g-sky path { stroke: var(--pink); stroke-width: 1.4; }
.draw-art .g-bridge path { stroke-width: 1.7; }
.draw-art .g-cable path { stroke: var(--accent-2); stroke-width: 2; }
.draw-art .g-hanger path { stroke-width: 0.9; stroke: var(--mute); }
.draw-art .g-water path { stroke: var(--k-scroll, #4cc9f0); stroke-width: 1.2; }
.draw-art .g-glint path { stroke: var(--accent); stroke-width: 2; }
.draw-art .g-trees path { stroke: var(--mint); stroke-width: 1.5; }
.draw-art .pen { fill: #fff; stroke: none; transition: opacity .3s; }
/* The watercolor wash under the ink */
.draw-art .wash path { stroke: none; }
.draw-art .w-sky { fill: url(#dw-sky); opacity: .55; }
.draw-art .w-sun { fill: var(--accent); opacity: .85; }
.draw-art .w-far { fill: #6f5fb8; opacity: .55; }
.draw-art .w-near { fill: #2b2347; opacity: .85; }
.draw-art .w-water { fill: url(#dw-water); opacity: .7; }
.draw-art .w-balloon { fill: var(--accent); opacity: .7; }
.draw-art .w-sail { fill: #f3ede4; opacity: .75; }
.draw-art .w-hill { fill: #1f3a33; opacity: .95; }

/* ---------- Shape morphing ---------- */
.morph { position: absolute; inset: 0; width: 100%; height: 100%; padding: 30px 30px 70px; cursor: pointer; }
.morph path { fill: var(--c, var(--accent)); transition: fill .7s; filter: drop-shadow(0 12px 30px color-mix(in oklab, var(--c, var(--accent)) 45%, transparent)); }
.morph-btns .btn { padding: 5px 10px; }

/* ---------- Motion along a path ---------- */
.flight { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }
.flight .route { fill: none; stroke: var(--line-2); stroke-width: 2; stroke-dasharray: 2 8; stroke-linecap: round; }
.flight .route.drawing { stroke: var(--accent); stroke-dasharray: none; }
.flight .plane path { fill: var(--ink); stroke: none; }
.flight .plane .fold { fill: none; stroke: var(--bg-2); stroke-width: 1.2; }
.flight .trail circle { fill: var(--accent); }

/* ---------- Living filters ---------- */
.liquid { position: absolute; inset: 0; width: 100%; height: 100%; padding-bottom: 50px; }
.liquid text { font-family: var(--serif); font-style: italic; font-size: 104px; fill: var(--ink); }
.liquid .blob-a { fill: var(--accent); }
.liquid .blob-b { fill: var(--violet); }

/* ---------- Animated icons ---------- */
.icons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; padding: 20px; }
@media (max-width: 520px) { .icons { grid-template-columns: repeat(2, 1fr); } }
.ico {
  display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 18px 8px 12px;
  border-radius: 16px; border: 1px solid var(--line); background: var(--card-2); color: var(--ink); cursor: pointer;
  transition: border-color .2s, transform .15s;
}
.ico:hover { border-color: var(--line-2); }
.ico:active { transform: scale(.96); }
.ico:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ico svg { width: 44px; height: 44px; overflow: visible; }
.ico svg * { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.ico svg .fill { fill: currentColor; stroke: none; }
.ico svg mask * { stroke: none; }
.ico svg mask rect { fill: #fff; }
.ico svg mask .bite { fill: #000; }
.ico span { font-size: 12px; color: var(--mute); }
.ico.on span { color: var(--ink); }

/* Menu to close */
.ico .l1, .ico .l2, .ico .l3 { transform-box: fill-box; transform-origin: center; transition: transform .45s cubic-bezier(.3, 1.5, .5, 1), opacity .2s; }
.ico.on .l1 { transform: translateY(5px) rotate(45deg); }
.ico.on .l2 { transform: scaleX(0); opacity: 0; }
.ico.on .l3 { transform: translateY(-5px) rotate(-45deg); }
/* Play to pause (the path morph itself runs in JS) */
.ico[data-ico="play"].on { color: var(--accent); }
/* Check */
.ico .base { stroke: var(--line-2); }
/* Dash 1, gap 2 and an offset just past 1 keep an undrawn stroke fully hidden, round cap included. */
.ico .ring, .ico .tick, .ico .slash { stroke-dasharray: 1 2; stroke-dashoffset: 1.01; }
.ico[data-ico="check"] .ring { stroke: var(--mint); transition: stroke-dashoffset .5s; }
.ico[data-ico="check"] .tick { stroke: var(--mint); stroke-width: 2.2; transition: stroke-dashoffset .3s; }
.ico[data-ico="check"].on .ring { stroke-dashoffset: 0; }
.ico[data-ico="check"].on .tick { stroke-dashoffset: 0; transition-delay: .45s; }
/* Heart */
.ico .heart { transform-box: fill-box; transform-origin: center; transition: fill .2s, stroke .2s; }
.ico.on .heart { fill: #ff3d7f; stroke: #ff3d7f; animation: pop .45s cubic-bezier(.3, 1.8, .5, 1); }
.ico .burst circle { fill: #ff3d7f; stroke: none; opacity: 0; transform-origin: 12px 12px; }
.ico .burst.go circle { animation: burst .6s ease-out; }
@keyframes pop { 0% { transform: scale(.6); } 100% { transform: scale(1); } }
@keyframes burst {
  0% { opacity: 1; transform: rotate(var(--a)) translateY(-6px) scale(1); }
  100% { opacity: 0; transform: rotate(var(--a)) translateY(-14px) scale(.2); }
}
/* Bell */
.ico .bell { transform-box: fill-box; transform-origin: 50% 0; }
.ico .bell.go { animation: ring .9s ease-in-out; }
.ico .badge { fill: var(--accent); stroke: none; transform-box: fill-box; transform-origin: center; transform: scale(0); transition: transform .4s cubic-bezier(.3, 1.8, .5, 1); }
.ico.on .badge { transform: scale(1); }
@keyframes ring { 10%, 50% { transform: rotate(16deg); } 30%, 70% { transform: rotate(-14deg); } 85% { transform: rotate(6deg); } 0%, 100% { transform: rotate(0); } }
/* Sun to moon */
.ico .orb { transform-box: fill-box; transform-origin: center; transition: transform .5s cubic-bezier(.3, 1.4, .5, 1); }
.ico .bite { transition: transform .5s cubic-bezier(.3, 1.4, .5, 1); }
.ico .rays { transform-origin: 12px 12px; transition: transform .5s, opacity .3s; }
.ico.on .orb { transform: scale(1.45); }
.ico.on .bite { transform: translate(-7px, 5px); }
.ico.on .rays { transform: rotate(90deg) scale(.4); opacity: 0; }
.ico[data-ico="theme"].on { color: var(--violet); }
/* Download */
.ico[data-ico="download"] .ring { stroke: var(--accent); transition: stroke-dashoffset .2s; }
.ico[data-ico="download"] .tick { stroke: var(--accent); stroke-width: 2.2; transition: stroke-dashoffset .2s; }
.ico .arrow { transition: transform .2s, opacity .2s; }
.ico[data-ico="download"].on .arrow { transform: translateY(4px); opacity: 0; transition: transform .3s, opacity .2s .35s; }
.ico[data-ico="download"].on .ring { stroke-dashoffset: 0; transition: stroke-dashoffset 1s .3s ease-in-out; }
.ico[data-ico="download"].on .tick { stroke-dashoffset: 0; transition: stroke-dashoffset .3s 1.3s; }
/* Eye */
.ico .pupil { transform-box: fill-box; transform-origin: center; transition: transform .3s; }
.ico .lid { transition: opacity .3s; }
.ico .slash { transition: stroke-dashoffset .35s; }
.ico[data-ico="eye"].on .slash { stroke-dashoffset: 0; }
.ico[data-ico="eye"].on .pupil { transform: scale(.3); }
.ico[data-ico="eye"].on .lid { opacity: .55; }

/* ---------- Logo intro and loaders ---------- */
.logo-stage { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 26px; padding: 34px 20px 64px; min-height: 420px; }
.logo-intro { display: flex; flex-direction: column; align-items: center; }
.flask { width: 120px; height: 120px; overflow: visible; }
.flask .outline { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1 2; stroke-dashoffset: 1.01; }
.flask .wave { fill: var(--accent); animation: wave-x 2s linear infinite; }
.flask .liquid-level { transform: translateY(112px); }
.flask .bubble { fill: #fff; opacity: 0; }
.wordmark { font-family: var(--serif); font-size: 56px; line-height: 1; margin-top: 10px; display: flex; }
.wordmark span { display: inline-block; opacity: 0; transform: translateY(-28px); }
.tagline { color: var(--mute); margin: 8px 0 0; opacity: 0; }
.play .flask .outline { animation: draw 1.1s ease-in-out forwards; }
.play .flask .liquid-level { animation: fill-up 1.4s .9s cubic-bezier(.3, .7, .3, 1) forwards; }
.play .flask .bubble { animation: bubble-rise 2.4s 2s ease-in infinite; }
.play .flask .bubble:nth-of-type(2) { animation-delay: 2.7s; }
.play .flask .bubble:nth-of-type(3) { animation-delay: 3.3s; }
.play .wordmark span { animation: drop .6s calc(1.9s + var(--i) * 60ms) cubic-bezier(.3, 1.6, .5, 1) forwards; }
.play .tagline { animation: fade .6s 2.6s forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
@keyframes fill-up { to { transform: translateY(64px); } }
@keyframes wave-x { to { transform: translateX(-60px); } }
@keyframes bubble-rise { 0% { opacity: 0; transform: translateY(0); } 20% { opacity: .85; } 100% { opacity: 0; transform: translateY(-38px); } }
@keyframes drop { to { opacity: 1; transform: none; } }
@keyframes fade { to { opacity: 1; } }

.loaders { display: flex; gap: 22px; align-items: center; }
.loaders svg { width: 46px; height: 46px; overflow: visible; }
.ld-arc { animation: spin 1.4s linear infinite; }
.ld-arc circle { fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; animation: arc 1.4s ease-in-out infinite; }
@keyframes arc { 0% { stroke-dasharray: 1 150; stroke-dashoffset: 0; } 50% { stroke-dasharray: 90 150; stroke-dashoffset: -35; } 100% { stroke-dasharray: 90 150; stroke-dashoffset: -124; } }
.ld-dots circle { fill: var(--violet); animation: hop .5s ease-in-out infinite alternate; }
.ld-dots circle:nth-child(2) { animation-delay: .15s; }
.ld-dots circle:nth-child(3) { animation-delay: .3s; }
@keyframes hop { to { transform: translateY(-9px); } }
.ld-pulse circle { fill: none; stroke: var(--mint); stroke-width: 2.5; transform-box: fill-box; transform-origin: center; animation: pulse 1.6s ease-out infinite; }
.ld-pulse circle:nth-child(2) { animation-delay: .8s; }
@keyframes pulse { from { transform: scale(.4); opacity: 1; } to { transform: scale(2.6); opacity: 0; } }
.ld-smil rect { fill: var(--sun); }

/* ---------- Transit map ---------- */
.metro { display: grid; grid-template-columns: minmax(0, 1fr) 270px; gap: 8px; padding: 20px; }
@media (max-width: 860px) { .metro { grid-template-columns: 1fr; } }
.metro-map { width: 100%; height: auto; }
.metro-map .line { fill: none; stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; transition: opacity .25s; }
.metro-map .dim { opacity: .14; }
.metro-map .stn { cursor: pointer; transition: opacity .25s; }
.metro-map .stn circle { fill: var(--bg-2); stroke: var(--ink); stroke-width: 2.5; transform-box: fill-box; transform-origin: center; transition: transform .2s, fill .2s; }
.metro-map .stn.x circle { stroke-width: 3.5; }
.metro-map .stn:hover circle, .metro-map .stn:focus-visible circle, .metro-map .stn.sel circle { transform: scale(1.4); fill: var(--accent); }
.metro-map .stn:focus { outline: none; }
.metro-map .stn text { font-family: var(--mono); font-size: 9.5px; fill: var(--mute); pointer-events: none; }
.metro-map .stn:hover text, .metro-map .stn.sel text { fill: var(--ink); }
.metro-map .train rect { fill: var(--ink); stroke: var(--bg-2); stroke-width: 1.5; }
.metro-side { display: flex; flex-direction: column; gap: 14px; padding: 6px 0 0 12px; }
.metro-side > .mono { color: var(--mute); }
.metro-legend { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.metro-legend button { width: 100%; display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; border: 1px solid var(--line); background: none; cursor: pointer; font-size: 13.5px; text-align: left; }
.metro-legend button:hover, .metro-legend button.on { border-color: var(--line-2); background: var(--card-2); }
.metro-legend i { width: 22px; height: 6px; border-radius: 3px; background: var(--c); }
.metro-info { border-top: 1px solid var(--line); padding-top: 14px; display: flex; flex-direction: column; gap: 4px; }
.metro-info strong { font-family: var(--serif); font-weight: 400; font-size: 28px; line-height: 1.1; }
.metro-info span { color: var(--mute); font-size: 13.5px; }
.metro-info .lines { display: flex; gap: 6px; margin-top: 4px; }
.metro-info .lines i { width: 12px; height: 12px; border-radius: 50%; background: var(--c); }
.metro-info .ride { align-self: flex-start; margin-top: 10px; text-decoration: none; }

@media (prefers-reduced-motion: reduce) {
  .flask .outline { stroke-dashoffset: 0; }
  .flask .liquid-level { transform: translateY(64px); }
  .wordmark span, .tagline { opacity: 1; transform: none; }
}
