/* ---------- the earlier homepage's map section rules, verbatim (styles.css 1033-1172) ---------- */
/* The figure carries no chrome of its own any more. The card IS the map view:
   the ground runs edge to edge inside a rounded, clipped panel, exactly as the
   Map tab does under its segmented control. A cream mat around a map view is
   what made this section read as an illustration rather than as the product,
   so the padding is gone and the caption sits outside the card, on the panel. */
.map__frame { margin: 0; position: relative; }
/* No media query on purpose: the min-width is the whole rule. Wherever the
   frame is at least 760px the map simply fills it (up to the height cap
   below) and the scroll container has nothing to scroll; below that the map
   holds its width and pans, because a world map squeezed to 318px cannot
   carry a legible 0-to-10 score and a map that cannot show its scores is not
   the payoff this section promises. */
/* Full bleed. The earlier map card's hairline border and rounded corners are gone
   because the map runs to the window's edges (page.css, the map block); radius 0 is
   stated so :focus-visible's 8px cannot round it. */
.map__scroll {
  overflow: auto hidden;
  overscroll-behavior-x: contain;
  border: 0;
  border-radius: 0;
  background: var(--map-water);
}
/* In High Contrast the card's border was the map's only edge: keep one above and
   below (the sides are the window's). Here, after the rule above, so it wins. */
@media (forced-colors: active) { .map__scroll { border-block: 1px solid CanvasText; } }
.map__svg { display: block; width: 100%; min-width: 760px; height: auto; }
/* A ceiling on the map's size, set by the window's height. The map is always 0.39 as tall as it is wide, so a map
   as wide as an ultrawide window is taller than the window and the whole world is
   never on screen at once: 3440 by 1300 drew it 1342px tall, with Chile and New
   Zealand below the fold. So its width is also held to what the window's height
   allows, less 96px, and the auto margins center it. 96px is 48px of page above
   and below a centered band, enough to show both of its edges, which is what makes
   it read as a band laid across the page rather than a screen it fills; and it is
   little enough that none of the ordinary windows this page is checked at (390 by
   844, 768 by 1024, 1280 by 800, 1440 by 900, 1920 by 1080, 2560 by 1440) reaches
   the cap. On windows 496px tall or more it binds when they are more than about
   2.1 to 2.4 times as wide as they are tall (the bar rises with the height);
   below that the bar rises to 2.56 by 400px tall (the air, below). The band
   still runs edge to edge: the water either side of the art is .map__scroll's
   own background, the same color (in High Contrast, an underlay of it, below).
   100svh rather than 100vh, so the band also fits a phone's window with its
   toolbars showing. Where the two disagree min-width beats max-width, so a phone
   keeps the 760px map that pans.
   The 96px of air is for a window with
   height to spare. Below 496px tall it shrinks, to nothing by 400px: a phone held
   sideways (844 by 390, 932 by 430) drew its full-width map whole before the cap,
   and a fixed 96px shrank it to the 760px floor with water beside it to keep an
   air it had no room for. So on a short window the air gives way first: up to
   400px tall the cap binds only where the full-width map would not fit at all,
   and then holds the band to the window's height; between 400 and 496px tall it
   holds a 400px band, the rest of the height its air. */
.map__svg { max-width: calc((100svh - clamp(0px, 100svh - 400px, 96px)) / 0.39); margin-inline: auto; }
/* Once the cap binds, the art stops short of the window's edges, and its two ends
   are the antimeridian, where the land is cut straight down. A straight cut
   standing in open water is a hard edge the full-width band never showed, because
   there the cut was the window's own edge. So while the art is narrower than its
   band, its ends fade into the water, in two bands, because the land that reaches
   the ends lies in two places.

   The north, the top 44%, has nothing at either end but the tip of Russia's far
   east and the islands off it (Wrangel, St. Lawrence): there the fade runs 3% of
   the width, 30 map units, long enough to read as land going out of sight rather
   than land cut off, and short of Alaska, which starts 32.8 units in. The south,
   the rest, has Fiji at both ends and New Zealand at the right, so there the fade
   is 0.6%, 6 units: as far in as it can go without reaching a label, because the
   mask takes in the labels and pins too, and NEW ZEALAND ends at 993.4 units (in
   the fallback face; 992.1 in Roboto). It does brush the tip of New Zealand's East
   Cape, at 995.8, which keeps about 70% of its tint. The two bands overlap by 2%
   so that no row is left out of both, and they meet near 22N, where nothing lies
   within 40 units of either end (nothing does anywhere between 59N and 15S), so
   the change from one to the other cannot be seen.

   The query asks exactly the question "is the art narrower than its band": the
   container is the svg's own containing block, and the condition repeats the two
   rules above, since a query cannot read a custom property. Wherever the art fills
   the band there is no mask at all, so those windows render exactly as they did.
   Plus 0.02px: a browser works the condition out in
   one precision and the width in another, so where the cap lands exactly on the
   band's width the two could disagree, and Chromium faded the ends of a map that
   filled its band (1600 by 720, and about two dozen other exact sizes; Firefox
   had its own set before this rule changed). For a window of whole pixels the
   cap is a whole number of 1/39ths of a pixel, about 0.026, so 0.02px turns the
   query off only where the cap is exactly the band's width. */
.map__scroll { container-type: inline-size; }
@container (width > 760px) and (width > calc((100svh - clamp(0px, 100svh - 400px, 96px)) / 0.39 + 0.02px)) {
  .map__svg {
    -webkit-mask-image:
      linear-gradient(to right, transparent, #000 3%, #000 97%, transparent),
      linear-gradient(to right, transparent, #000 0.6%, #000 99.4%, transparent);
    mask-image:
      linear-gradient(to right, transparent, #000 3%, #000 97%, transparent),
      linear-gradient(to right, transparent, #000 0.6%, #000 99.4%, transparent);
    -webkit-mask-size: 100% 44%, 100% 58%;
    mask-size: 100% 44%, 100% 58%;
    -webkit-mask-position: 0 0, 0 100%;
    mask-position: 0 0, 0 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
  }
  /* The same water in High
     Contrast. Forced colors repaints a background in the user's Canvas color but
     leaves the map's own fills alone (Chromium gives every svg forced-color-adjust:
     preserve-parent-color, and Firefox does not force the fills either), so the art
     keeps its ocean there. The water either side of a capped map is a background,
     so it turned to Canvas, white or black with the theme, beside the art's own
     water, and the ends above faded into that Canvas, which drew the mask's two
     bands as a stepped haze; measured in Chromium's light and dark palettes and in
     Firefox's own forced colors. So here, inside the fade's own query so that the
     two can never disagree, an underlay paints that water, opted out of forced
     colors as the art is. It is a layer of its own, not forced-color-adjust: none
     on the scroller itself, because the scroller also draws two things that should
     stay in the user's colors: its scrollbar, and its focus ring when the map pans,
     which Chromium draws in the palette's Highlight and drew olive with the
     scroller opted out. */
  @media (forced-colors: active) {
    .map__scroll::before { content: ""; position: absolute; inset: 0; z-index: -1; background: var(--map-water); forced-color-adjust: none; }
  }
}
/* The scroller's half of that underlay, outside the query because a query cannot
   style its own container: position and z-index make the scroller the box the
   underlay fills and the stacking context that keeps it above the scroller's own
   background and below the art (container-type gives it neither). Neither draws
   anything, so every window the cap leaves alone renders exactly as before in High
   Contrast too. */
@media (forced-colors: active) { .map__scroll { position: relative; z-index: 0; } }
/* The app's map ground, which is the Google DEFAULT palette the app keeps,
   sampled from an App Store capture of the app (see the token block up
   top for the measurements). Countries are grouped into one path per shade
   rather than one path per country: three nodes instead of 176, and because
   every country is still its own closed subpath inside its group, the border
   stroke below draws each outline exactly as it would ungrouped.

   Both the fill layer and the border layer are <use> references to the same
   three paths in <defs>. Nothing inside a <use> shadow tree is selectable
   from here, so the paths carry no class of their own and take fill and
   stroke by INHERITANCE from the <use> element. That is the whole reason
   the layers can be separated for free: the landcover raster sits between
   them without washing out a border it is drawn under. */
.map__water { fill: var(--map-water); }
.map__fills { stroke: none; }
.map__land--2 { fill: var(--map-land-2); }
.map__land--3 { fill: var(--map-land-3); }
.map__land--4 { fill: var(--map-land-4); }
.map__borders {
  fill: none;
  stroke: var(--map-border);
  stroke-width: 0.4;
  stroke-linejoin: round;
}
/* Lakes are the same water as the ocean in the capture, and they sit above
   the landcover raster because they are holes in the land, not land. */
.map__lake { fill: var(--map-water); }
/* The capture's interior line is dotted, not solid, and lighter than the
   international one. Round caps make each dash read as a dot at this size. */
.map__admin1 {
  fill: none;
  stroke: var(--map-admin1);
  stroke-width: 0.35;
  stroke-dasharray: 0.7 1.3;
  stroke-linecap: round;
}
/* Google Maps sets its labels in Roboto. The face is fetched only when the
   map arms (demo.js), so the eager page weight is unchanged; until then, and
   with no script at all, these fall back to the system sans, which carries
   the same all-caps letter-spaced shape. Sizes are in USER UNITS, so a label
   scales with the map exactly as the ground does and the offline collision
   layout stays valid at every width.

   paint-order: stroke is how a map halos a label: the white stroke is painted
   first and the fill covers its inner half, so the letterform keeps its own
   weight instead of being eroded by its own outline. */
.map__labels {
  font-family: Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
  paint-order: stroke;
  stroke: #fff;
  stroke-opacity: 0.72;
  stroke-linejoin: round;
  pointer-events: none;
}
.map__label {
  fill: var(--map-label);
  font-size: 9.6px;
  font-weight: 500;
  letter-spacing: 0.96px;
  stroke-width: 1.25px;
  text-anchor: middle;
  dominant-baseline: middle;
}
/* The small size class: Google's size-by-importance convention, doing the one
   job it exists for. A name that cannot clear its neighbors, the demo markers
   and the crop at 9.6 units often can at 7, so several countries that had no
   label at all now have a quieter one instead of none.

   Same voice one step down - same face, weight, color and halo - with the
   tracking pulled from 0.10em to 0.06em because spacing that reads as
   generous at the full size reads as loose here, and the halo cut to 0.9px so
   it does not erode the smaller letterforms. Which names take this class is
   decided offline by the generator, not at runtime. */
.map__label--sm {
  font-size: 7px;
  letter-spacing: 0.42px;
  stroke-width: 0.9px;
}
/* Water labels in the capture carry no halo and no letter-spacing: they are
   set in mixed case in a muted teal, a quieter voice than the land labels. */
.map__label--sea {
  fill: var(--map-sea);
  font-size: 10.4px;
  font-weight: 400;
  letter-spacing: 0;
  stroke: none;
}
/* The landcover raster. Its href is empty in the markup and is set by demo.js
   when the section comes within a QUARTER of a viewport (rootMargin 25%, not
   the 50% the floating crops use), so it costs nothing on a visit that never
   scrolls this far. The quarter is measured, not picked: the map frame sits
   about 1347px down, so on an ordinary 900px desktop viewport a half-viewport
   margin already reaches it and this and the Roboto fetch would both happen
   on load for a visitor who never scrolls. The vector tints underneath are
   the no-script ground and stay visible through it at this opacity. */
.map__cover {
  opacity: 0;
  transition: opacity 0.5s var(--ease-out);
}
/* 0.45 is measured, not chosen. The raster's own lookup table is a histogram
   match onto the capture's land lightness, and this is the opacity at which
   the COMPOSITE of raster over country tints reproduces it: p10 73.65,
   p50 78.44, p90 83.29 against the capture's 73.53 / 78.43 / 83.33. Changing
   it without re-deriving the raster's gain moves the ground off the app's. */
.map__cover--in { opacity: 0.45; }
.map__note,
.map__hint {
  margin-top: clamp(0.7rem, 1.6vw, 1rem);
  font-size: 0.875rem;  /* 0.85rem on the earlier homepage; 0.875 is a size this page already uses */
  color: var(--ink-soft);
}
@keyframes map-pin-drop {
  from { opacity: 0; transform: translateY(-16px); }
  to { opacity: 1; transform: none; }
}
.map__pin--drop {
  animation: map-pin-drop 0.6s var(--ease-out) both;
  animation-delay: var(--pd, 0s);
}

@media (prefers-reduced-motion: reduce) { .map__pin--drop { animation: none !important; } }
