/* ==========================================================================
   The world: layers, paper, ink, boil, markings, the car.
   Loaded after site.css. Everything here is drawn by js/world.js.
   ========================================================================== */

.w-layer { position: absolute; inset: 0; }
.patch, .stream, .road, .it, .flat { position: absolute; }
.world svg, .card-paper svg { display: block; overflow: visible; max-width: none; }

/* ground patches are simply there: they are placed just below the fold,
   where an arrival animation was never seen but still cost raster work */

/* standing things start folded flat, like a closed pop-up book, and spring
   up with a CSS transition on scale - composited, so it costs the main
   thread nothing while the page scrolls. JS only ever bends them. */
.it {
  scale: 1 .001;
  transition: scale .78s cubic-bezier(.3, 1.65, .5, 1);
}
.it.up { scale: 1 1; }
/* no per-item layers: hundreds of them made Chrome re-layer the page every
   frame; small things repaint into the world layer instead, which is cheaper */
.it-face { position: absolute; will-change: transform; transform: rotateX(-88deg); }
.k-sign { perspective: 260px; }

/* flat things drop onto the map */
.flat > svg {
  opacity: 0;
  transform: scale(1.2) rotate(-5deg);
  transition: opacity .45s var(--ease-fade), transform .9s var(--ease-spring);
}
.flat.is-down > svg { opacity: 1; transform: none; }
.flat.is-up > svg { filter: drop-shadow(1px 3px 1px rgb(var(--shadow) / .25)); }

.w-grain {
  background-image: url("../assets/grain.webp");
  background-size: 320px 320px;
  pointer-events: none;
}
/* at night the paper keeps its texture but the pale fibres step back */
:root[data-theme="dark"] .w-grain { opacity: .16; }
:root[data-theme="dark"] body { background-image: none; }
:root[data-theme="dark"] .card-paper .c-grain { opacity: .3; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .w-grain { opacity: .16; }
  :root:not([data-theme="light"]) body { background-image: none; }
  :root:not([data-theme="light"]) .card-paper .c-grain { opacity: .3; }
}
:root.is-reduced .it,
:root.is-reduced .it-face { transform: none; scale: 1 1; transition: none; }

/* road markings, painted just ahead of the car */
.dash, .zebra, .stopline {
  position: absolute;
  display: block;
  background: var(--paint);
  pointer-events: none;
}
.dash {
  height: 2.5px;
  margin-top: -1.25px;
  border-radius: 1.2px;
  transform-origin: 0 50%;
  scale: 0 1;
  transition: scale .5s var(--ease-spring);
}
.zebra, .stopline {
  border-radius: 1px;
  transform-origin: 50% 0;
  scale: 1 0;
  transition: scale .55s var(--ease-spring);
}
.dash.on, .zebra.on, .stopline.on { scale: 1 1; }
.no-t { transition: none !important; }

/* the 10 fps line boil: three drawings, one visible at a time */
.world .bf1, .world .bf2 { visibility: hidden; }
.world .B1 .bf0, .world .B2 .bf0 { visibility: hidden; }
.world .B1 .bf1, .world .B2 .bf2 { visibility: visible; }
.it, .flat { contain: layout style; }

/* ---- fills and strokes that are not plain tokens ----------------------- */
.world .ik { fill: var(--line); }
.world .f-sh { fill: rgb(var(--shadow) / var(--sh-a)); }
.world .f-sh2 { fill: rgb(var(--shadow) / calc(var(--sh-a) * .5)); }
.world .f-core { fill: var(--core); }
.world .f-housing { fill: #2b2725; }
.world .f-sheep { fill: #3b3431; }
.world .f-tail { fill: #7d2119; }
.world .f-shine { fill: rgba(255, 255, 255, .55); }
.world .f-flag-w { fill: #fbfaf5; }
.world .f-flag-g { fill: #00966e; }
.world .f-flag-r { fill: #d62612; }
.world .f-ink-fixed { fill: #241f1b; }
.world .s-ink-fixed { stroke: #241f1b; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.world .hatch {
  fill: none;
  stroke: rgb(var(--shadow) / .3);
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-dasharray: 3.2 1.3 5 1 2.2 1.6;
}
.world .hatch-w { fill: none; stroke: var(--wheat-2); stroke-width: 1.2; stroke-linecap: round; stroke-dasharray: 4 1.5 2 1.2; }
.world .rows-wheat { fill: none; stroke: var(--wheat-2); stroke-width: 1.6; stroke-linecap: round; stroke-dasharray: 5 2 9 1.5; opacity: .8; }
.world .rows-soil { fill: none; stroke: var(--bark); stroke-width: 1.8; stroke-linecap: round; stroke-dasharray: 7 2 4 2; opacity: .45; }
.world .s-paint { stroke: var(--paint); stroke-width: 2.2; fill: none; stroke-linecap: round; }
.world .s-paint-dash { stroke: var(--paint); stroke-width: 2; fill: none; stroke-dasharray: 9 7; stroke-linecap: round; }
.world .s-edge { stroke: var(--paint); stroke-width: 1.35; fill: none; opacity: .8; stroke-linejoin: round; }
.world .s-zebra { stroke: var(--paint); fill: none; }
.world .s-foam { stroke: var(--foam); stroke-width: 1.3; fill: none; stroke-linecap: round; opacity: .85; }
.world .s-red { stroke: var(--red); fill: none; stroke-linecap: round; }
.world .s-map-road { stroke: var(--map-road); stroke-width: 3.2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.world .s-map-road2 { stroke: var(--map-road-2); stroke-width: 2.2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.world .s-map-water { stroke: var(--map-water); stroke-width: 4.5; fill: none; stroke-linecap: round; }
.world .s-map-line { stroke: var(--map-line); stroke-width: .9; fill: none; }
.world .s-note-line { stroke: var(--note-line); stroke-width: .7; }
.world .s-ink3 { stroke: var(--ink-3); stroke-width: .8; fill: none; }
.world .t-sign { font-family: var(--font-label); font-weight: 850; fill: #fbfaf5; letter-spacing: .02em; }
.world .t-dark { fill: #241f1b; }
.world .t-town { font-family: var(--font-label); font-weight: 800; fill: #241f1b; letter-spacing: .03em; }

/* world traffic lights */
.world .tl .lp { fill: var(--lamp-off); }
.world .tl.st-r .l-r, .world .tl.st-ra .l-r { fill: var(--lamp-red); }
.world .tl.st-ra .l-a, .world .tl.st-a .l-a { fill: var(--lamp-amber); }
.world .tl.st-g .l-g { fill: var(--lamp-green); }
.world .tl .lg { opacity: 0; transition: opacity .35s var(--ease-fade); }
.world .l-rg { fill: var(--lamp-red); }
.world .l-ag { fill: var(--lamp-amber); }
.world .l-gg { fill: var(--lamp-green); }
.world .tl.st-r .l-rg, .world .tl.st-ra .l-rg, .world .tl.st-ra .l-ag,
.world .tl.st-a .l-ag, .world .tl.st-g .l-gg { opacity: .32; }

/* street lamps glow only at night */
.world .st-glow { stop-color: var(--glow); }
.world .st-glow0 { stop-color: var(--glow); stop-opacity: 0; }

/* ---- water: foam that rides the current ---------------------------------- */
.foam {
  position: absolute;
  left: 0; top: 0;
  height: 5px;
  margin-top: -2.5px;
  border-top: 1.6px solid var(--foam);
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: 0;
  will-change: transform, opacity;
  pointer-events: none;
}

/* ---- clouds, nearer the eye, and the shadows they drop on the map --------- */
.cloud, .cloud-sh { position: absolute; will-change: transform; }
.world .f-cloud { fill: var(--cloud); }
.world .f-cloud-2 { fill: var(--cloud-2); }
.world .f-cshade { fill: rgb(var(--shadow) / calc(var(--sh-a) * .55)); }
.cloud-sh { opacity: .42; filter: blur(5px); }

/* ---- the car ------------------------------------------------------------- */
.car { position: absolute; left: 0; top: 0; will-change: transform; }
.car-sh, .car-body, .car-beam { position: absolute; will-change: transform; }
.car-beam {
  transform-origin: 50% 100%;
  background: radial-gradient(60% 100% at 50% 100%, var(--glow), transparent 72%);
  clip-path: polygon(40% 100%, 60% 100%, 100% 0, 0 0);
}
.honk {
  position: absolute;
  z-index: 2;
  font-family: var(--font-hand);
  font-weight: 600;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--ink);
  background: var(--card);
  padding: .2rem .6rem .3rem;
  border-radius: .7rem .7rem .7rem .15rem;
  box-shadow: 0 1px 0 rgb(var(--shadow) / .2), 0 8px 16px -8px rgb(var(--shadow) / .6);
  white-space: nowrap;
  translate: -15% -100%;
  animation: honk 1.05s var(--ease-spring) forwards;
  pointer-events: none;
}
@keyframes honk {
  0% { opacity: 0; transform: scale(.4) rotate(-10deg); }
  22% { opacity: 1; transform: scale(1.08) rotate(3deg); }
  40% { transform: scale(1) rotate(-2deg); }
  80% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-14px) rotate(-2deg); }
}

/* ---- card paper ---------------------------------------------------------- */
.card-paper .c-sh { fill: rgb(var(--shadow) / calc(var(--sh-a) * 1.1)); }
.card-paper .c-sh2 { fill: rgb(var(--shadow) / calc(var(--sh-a) * .5)); }
.card-paper .c-sh3 { fill: rgb(var(--shadow) / calc(var(--sh-a) * .3)); }
.card-paper .c-core { fill: var(--core); }
.card-paper .c-note { fill: var(--note); }
.card-paper .c-card { fill: var(--card); }
.card-paper .c-kraft { fill: var(--kraft); }
.card-paper .c-map { fill: var(--map); }
.card-paper .c-rule { stroke: var(--note-line); stroke-width: 1; fill: none; }
.card-paper .c-margin { stroke: var(--note-margin); stroke-width: 1; fill: none; }
.card-paper .c-grid { stroke: var(--note-line); stroke-width: .6; fill: none; opacity: .55; }
.card-paper .c-grain { fill: url(#grain-pat); }
.card-paper .c-map-road { stroke: var(--map-road); stroke-width: 3.4; fill: none; stroke-linecap: round; }
.card-paper .c-map-water { stroke: var(--map-water); stroke-width: 5; fill: none; stroke-linecap: round; }
.card-paper .c-map-line { stroke: var(--map-line); stroke-width: 1; fill: none; }

/* ---- nav states -------------------------------------------------------- */
.nav { transition: transform .6s var(--ease-spring); }
.nav.is-away { transform: translateY(-130%); }

/* theme switch: the new theme spreads from the sun/moon button as a circle.
   It is a view transition - two snapshots, clipped by the compositor - so
   nothing on the page has to animate its own colours. */
::view-transition-old(root),
::view-transition-new(root) {
  animation: none;
  mix-blend-mode: normal;
}
::view-transition-new(root) {
  animation: theme-reveal .75s cubic-bezier(.32, .72, 0, 1) both;
}
@keyframes theme-reveal {
  from { clip-path: circle(0 at var(--vt-x, 100%) var(--vt-y, 0)); }
  to { clip-path: circle(var(--vt-r, 150vmax) at var(--vt-x, 100%) var(--vt-y, 0)); }
}
