/* ==========================================================================
   Grid-first: the map is the room, and white panels float on it.
   At rest: the world as the dot matrix the Map and Overview use, your areas pinned
   on it (the one being searched larger, breathing). Once you are in an area the
   land fills in (data-tier 1) and plots appear, substations and lines after them
   (2 and 3); links and the 20 km ring when a plot is selected.
   Type: the contract's styles only. On the map: meta for names at rest, strong
   for what you are looking at; lines are knocked out under labels, never haloed.
   Colour: ink and the neutrals. The scout at work is motion, never a colour: a
   line that reads the area and leaves fine dots on the land behind it, and
   dots that breathe.
   ========================================================================== */
.view-grid { overflow: hidden; }
.gf {
  position: absolute; inset: 0; overflow: hidden; background: var(--bg);
  --lw: 340px; --rw: 368px;
  --ss: .42; --ps: .3; /* substation and plot size by zoom tier (SS and PS in grid.js) */
}
.gf[data-tier="2"] { --ss: .62; --ps: .8; }
.gf[data-tier="3"] { --ss: 1; --ps: 1; }

/* ---------- The map ---------- */
.gf-svg { position: absolute; inset: 0; width: 100%; height: 100%; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.gf.is-panning .gf-svg { cursor: grabbing; }
.gf.is-drawing .gf-svg { cursor: crosshair; }
.gf-svg text { font-family: var(--font); font-variant-numeric: tabular-nums; }
/* The land: the dot matrix over the world (data-tier 0), filled land once you are in an area (1 and up), handing over in a cross-fade.
   The hidden one stops painting once it has faded. */
.gf-land, .gf-dots { transition: opacity var(--dur-3) var(--ease), visibility 0s; }
.gf[data-tier="0"] .gf-land, .gf:not([data-tier="0"]) .gf-dots { opacity: 0; visibility: hidden; transition: opacity var(--dur-3) var(--ease), visibility 0s var(--dur-3); }
.gf-land path { stroke: var(--bg); stroke-width: 1; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.gf-rest path { fill: var(--fill); }
.gf-ours path { fill: var(--fill-2); } /* countries whose grid the scout has read */
.gf-dots { pointer-events: none; }
.gf-dots path { fill: none; stroke-linecap: round; }
.gf-dots-rest { stroke: var(--stroke-faint); }
.gf-dots-ours { stroke: var(--stroke); } /* their main landmass, as on the Overview */
/* The grid the zoom calls for (is-on) hands over to the next; the other stops painting once it has faded */
.gf-dgrid { opacity: 0; visibility: hidden; transition: opacity 240ms var(--ease), visibility 0s 240ms; }
.gf-dgrid.is-on { opacity: 1; visibility: inherit; transition: opacity 240ms var(--ease), visibility 0s; }

/* Marks keep their pixel size at any zoom: --inv = 1 / zoom */
.gf-m { transform: scale(var(--inv, 1)); }
.gf-plot > .gf-m, .gf-apin > .gf-m { transform: scale(var(--inv, 1)) translate(var(--dx, 0px), var(--dy, 0px)); }
.gf-sz { transform: scale(var(--ss)); transition: transform var(--dur-3) var(--ease); }
.gf-pz { transform: scale(var(--ps)); transition: transform var(--dur-3) var(--ease); }
.gf-hit { fill: transparent; }

/* Detail appears as you zoom in: plots from tier 1, the grid and pipeline sites from tier 2 */
.gf-lines, .gf-subs, .gf-sites, .gf-slabels, .gf-reachg, .gf-reach-edge, .gf-ghosts { transition: opacity var(--dur-3) var(--ease); }
.gf:is([data-tier="0"], [data-tier="1"]) :is(.gf-lines, .gf-subs, .gf-sites, .gf-slabels, .gf-reachg, .gf-reach-edge) { opacity: 0; pointer-events: none; }
.gf[data-tier="0"] .gf-ghosts { opacity: 0; }
.gf[data-tier="2"] .gf-lines { opacity: .75; }
.gf[data-tier="2"] .gf-sites { opacity: .8; }

/* ---------- Areas of interest: a soft fill under a fine ink outline, or a pin while too small to see ---------- */
.gf-area, .gf-aedge, .gf-apin { transition: opacity var(--dur-2) var(--ease); }
.gf-area { cursor: pointer; }
.gf-area.is-selected { cursor: inherit; }
.gf-area-fill { fill: var(--hover); transition: fill var(--dur-2) var(--ease); }
.gf-area.is-queued .gf-area-fill { fill: transparent; }
.gf-area.is-hot .gf-area-fill { fill: var(--fill); }
.gf-area.is-selected .gf-area-fill { fill: color-mix(in srgb, var(--surface) 45%, transparent); }
.gf-aedge {
  fill: none; stroke: var(--ink); stroke-width: 1.25; stroke-linejoin: round; vector-effect: non-scaling-stroke; pointer-events: none;
  transition: opacity var(--dur-2) var(--ease), stroke var(--dur-2) var(--ease), stroke-width var(--dur-2) var(--ease);
}
.gf-aedge.is-queued { stroke: var(--stroke); stroke-dasharray: 5 4; }
.gf-aedge.is-hot { stroke-width: 1.75; }
.gf-aedge.is-selected { stroke-width: 2; }
.gf-aedge.is-queued:is(.is-hot, .is-selected) { stroke: var(--ink); }
.gf-area.is-pin, .gf-aedge.is-pin { opacity: 0; pointer-events: none; }

/* The pin: a ring at the area's middle.  Done: an ink dot in it.  Searching: a larger ring, the dot breathes.  Queued: an empty dashed ring.
   Pins too close to each other are nudged apart (--dx, --dy, from grid.js). */
.gf-apin { cursor: pointer; opacity: 0; pointer-events: none; }
.gf-apin.is-pin { opacity: 1; pointer-events: auto; }
.gf-apin.is-selected { cursor: inherit; }
.gf-apin-ring { fill: var(--surface); stroke: var(--ink); stroke-width: 1.5; transition: stroke-width var(--dur-1) var(--ease); }
.gf-apin-dot { fill: var(--ink); }
.gf-apin.is-searching .gf-apin-ring { stroke-width: 2; }
.gf-apin.is-searching .gf-apin-dot { animation: breathe var(--breath) var(--ease-io) infinite; }
.gf-apin.is-queued .gf-apin-ring { stroke: var(--stroke); stroke-dasharray: 2.6 2.2; }
.gf-apin.is-queued .gf-apin-dot { display: none; }
.gf-apin:is(:hover, .is-hot, .is-selected) .gf-apin-ring { stroke-width: 2.25; }
.gf-apin.is-searching:is(:hover, .is-hot, .is-selected) .gf-apin-ring { stroke-width: 2.75; }
.gf-apin.is-queued:is(:hover, .is-hot, .is-selected) .gf-apin-ring { stroke: var(--ink); }

/* The scout reading an area: a line crossing it at the share it last reported, fine dots on the land it has read.
   While a new report comes in the line walks there (is-scanning); otherwise it breathes. */
.gf-scan { pointer-events: none; transition: opacity var(--dur-3) var(--ease); }
.gf-texture { fill: none; stroke: var(--stroke); stroke-width: 1.6; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.gf-scanline { stroke: var(--ink); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.gf-area:not(.is-scanning) .gf-scanline { animation: breathe var(--breath) var(--ease-io) infinite; }
.gf-scan.is-fading { animation: fade-out 800ms var(--ease) forwards; }
/* The scout off, or on but not at work right now: what it was doing stays where it is, still; nothing claims to be working */
.gf:is(.is-off, .is-idle) :is(.gf-scanline, .gf-apin-dot) { animation: none; }
.gf:is(.is-off, .is-idle) :is(.gf-plot-live, .gf-rk-live) { visibility: hidden; }

/* ---------- Labels: plain type, placed clear of the marks and of each other ---------- */
.gf-lab { pointer-events: none; }
.gf-lab.is-hidden { visibility: hidden; }
.gf-lab text { fill: var(--ink); font-size: var(--fs-meta); font-weight: 400; }
.gf-lab-area { pointer-events: auto; cursor: pointer; }
.gf-lab-area.is-selected { cursor: inherit; }
.gf-lab-area:is(.is-selected, .is-searching) .gf-lab-name, .gf-lab-sub .gf-lab-name { font-size: var(--fs-body); font-weight: 500; }
.gf-lab-sub { animation: gf-fade var(--dur-3) var(--ease) both; }

/* ---------- The grid: substations sized by spare capacity, fine lines ---------- */
.gf-line { fill: none; stroke: var(--stroke); stroke-width: .8; vector-effect: non-scaling-stroke; stroke-linecap: round; }
.gf-line.kv-hi { stroke-width: 1.2; }
.gf-line.is-new { animation: gf-fade 1200ms var(--ease) both; }
.gf-sub-halo {
  fill: var(--fill); stroke: var(--stroke); stroke-width: 1;
  transition: fill var(--dur-2) var(--ease), stroke var(--dur-2) var(--ease);
}
.gf-sub-core { fill: var(--ink); }
.gf-sub:hover .gf-sub-halo, .gf-sub.is-hot .gf-sub-halo { fill: var(--fill-2); stroke: var(--ink); }
.gf-sub.is-linked .gf-sub-halo { stroke: var(--ink); }
/* Just recorded by the scout: the halo grows in on an ink ring, then settles */
.gf-sub.is-new .gf-sub-halo { animation: gf-sub-in 1600ms var(--ease) backwards; }
@keyframes gf-sub-in {
  0% { transform: scale(0); stroke: var(--ink); stroke-width: 2; }
  30% { transform: scale(1.12); }
  60% { stroke: var(--ink); stroke-width: 2; }
}

/* ---------- Pipeline sites: faint rings only ---------- */
.gf-site { cursor: pointer; }
.gf-site-ring { fill: color-mix(in srgb, var(--surface) 55%, transparent); stroke: var(--stroke); stroke-width: 1.5; transition: stroke var(--dur-1) var(--ease); }
.gf-site:hover .gf-site-ring { stroke: var(--ink); }

/* ---------- Plots: ink squares numbered by rank ---------- */
.gf-plot { cursor: pointer; }
.gf-plot-sq { fill: var(--ink); stroke: var(--surface); stroke-width: 2; }
.gf-plot-n { fill: var(--on-ink); font-size: var(--fs-meta); font-weight: 400; text-anchor: middle; dominant-baseline: central; pointer-events: none; transition: opacity var(--dur-2) var(--ease); }
.gf:is([data-tier="0"], [data-tier="1"]) :is(.gf-plot-n, .gf-plot-live) { opacity: 0; }
.gf-plot-ring { fill: color-mix(in srgb, var(--surface) 70%, transparent); stroke: var(--ink); stroke-width: 1.5; opacity: 0; transition: opacity var(--dur-2) var(--ease); }
.gf-plot:hover .gf-plot-ring, .gf-plot.is-hot .gf-plot-ring { opacity: .5; }
.gf-plot.is-selected .gf-plot-ring { opacity: 1; }
.gf-plot-live { fill: var(--ink); stroke: var(--surface); stroke-width: 2; animation: breathe var(--breath) var(--ease-io) infinite; }
/* Just found by the scout: the square grows in and an ink ring rings out once */
.gf-plot.is-new .gf-pz { animation: gf-plot-in 520ms var(--ease) backwards; }
.gf-plot.is-new .gf-plot-ring { animation: gf-ping 1600ms var(--ease) backwards; }
@keyframes gf-plot-in { from { opacity: 0; transform: scale(calc(var(--ps) * .55)); } }
@keyframes gf-ping { 0% { opacity: 1; transform: scale(.7); fill: transparent; } 100% { opacity: 0; transform: scale(1.7); fill: transparent; } }

/* A selected plot brings its own power forward; everything else steps back */
.gf-plots > *, .gf-subs > *, .gf-sites, .gf-lines { transition: opacity var(--dur-3) var(--ease); }
.gf.has-plot .gf-plot:not(.is-selected) { opacity: .2; }
.gf.has-plot .gf-sub:not(.is-linked) { opacity: .4; }
.gf.has-plot .gf-lines { opacity: .45; }
.gf.has-plot .gf-sites { opacity: .45; }
.gf.has-plot .gf-scan { opacity: 0; }
.gf-link { stroke: var(--ink); stroke-width: 1.5; vector-effect: non-scaling-stroke; stroke-linecap: round; pointer-events: none; animation: gf-fade var(--dur-3) var(--ease) both; }
.gf-link.is-far { stroke-width: 1.25; stroke-dasharray: 2 4; }
.gf-reach { fill: color-mix(in srgb, var(--surface) 28%, transparent); pointer-events: none; animation: gf-fade var(--dur-3) var(--ease) both; }
.gf-reach-edge { fill: none; stroke: var(--stroke); stroke-width: 1; stroke-dasharray: 3 4; vector-effect: non-scaling-stroke; pointer-events: none; animation: gf-fade var(--dur-3) var(--ease) both; }
.gf-ghost { pointer-events: none; }
.gf-ghost :is(circle, rect) { fill: color-mix(in srgb, var(--surface) 85%, transparent); stroke: var(--ink); stroke-width: 1.5; }
.gf-ghost.is-dismissed rect { stroke-dasharray: 3 2.5; }
/* At world scale the areas speak for their plots (the selected one stays) */
.gf[data-tier="0"] .gf-plot:not(.is-selected) { opacity: 0; pointer-events: none; }
@keyframes gf-fade { from { opacity: 0; } }

/* ---------- Drawing an area: ink, because a person is drawing ---------- */
.gf-draft-shape { fill: var(--fill); stroke: var(--ink); stroke-width: 1.5; stroke-dasharray: 6 4; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.gf.is-naming .gf-draft-shape { stroke-dasharray: none; fill: color-mix(in srgb, var(--surface) 40%, transparent); }
.gf-draft-line { fill: none; stroke: var(--ink); stroke-width: 1.5; stroke-dasharray: 6 4; vector-effect: non-scaling-stroke; stroke-linejoin: round; }
.gf-draft-pt { fill: var(--surface); stroke: var(--ink); stroke-width: 1.5; }
.gf-draft-pt.is-first { fill: var(--ink); }
.gf-draft-size { fill: var(--ink); font-size: var(--fs-meta); font-weight: 400; }

/* ==========================================================================
   Floating pieces: white, on the map, 16 px from the edges
   ========================================================================== */
.gf-panel { position: absolute; z-index: 5; display: flex; flex-direction: column; min-height: 0; top: 72px; max-height: calc(100% - 148px); background: var(--surface); border-radius: var(--r-4); box-shadow: var(--shadow-2); }

/* ---------- Left: areas.  Area names and plot names share one left edge (68 px in); everything on the right
   (the share read, Start now, the settings glyph, Mark an area, the progress bar) ends 24 px in ---------- */
.gf-left { left: 16px; width: var(--lw); }
.gf-lhead { flex: none; padding: 16px 24px 12px; transition: box-shadow var(--dur-2) var(--ease); }
.gf-lrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 36px; }
.gf-lrow > .icon-btn { margin-right: -10px; } /* its glyph ends on that edge; its hover disc reaches past it */
.gf-scout { align-items: flex-start; margin-top: 4px; }
.gf-scout .dot { margin: 6px 2px 0; }
.gf-scout .live-text { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.45; }
.gf-list { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 4px 8px 8px; }
.gf-lfoot { flex: none; padding: 8px 24px 16px; transition: box-shadow var(--dur-2) var(--ease); }
/* Only while rows scroll beneath them do the head and foot get a hairline */
.gf-left.is-scrolled .gf-lhead { box-shadow: 0 1px 0 var(--line); }
.gf-left.has-more .gf-lfoot { box-shadow: 0 -1px 0 var(--line); }

/* An area: its outline, name, country and how far along (the bar runs under the name and the share, to the right edge);
   open, or being searched while none is open, its plots below it.  Areas are parted by a hairline. */
.gf-arow { position: relative; }
.gf-arow + .gf-arow { margin-top: 9px; }
.gf-arow + .gf-arow::before { content: ""; position: absolute; left: 16px; right: 16px; top: -5px; height: 1px; background: var(--line); }
.gf-ahead { position: relative; display: flex; border-radius: var(--r-3); transition: background var(--dur-1) var(--ease); }
.gf-arow.is-active > .gf-ahead { background: var(--fill); }
.gf-abtn {
  flex: 1 1 auto; min-width: 0; display: grid; grid-template-columns: 32px minmax(0, 1fr) auto; grid-template-areas: "g m f" ". p p";
  column-gap: 12px; align-items: start; padding: 10px 16px; border: 0; border-radius: var(--r-3);
  background: none; text-align: left; color: inherit; transition: background var(--dur-1) var(--ease);
}
.gf-ahead:hover > .gf-abtn, .gf-arow.is-hot > .gf-ahead .gf-abtn { background: var(--hover); }
.gf-aglyph { grid-area: g; width: 32px; height: 32px; margin-top: 2px; padding: 4px; border-radius: var(--r-2); background: var(--fill); overflow: visible; }
.gf-aglyph path { fill: var(--fill); stroke: var(--ink); stroke-width: 1.3; stroke-linejoin: round; }
.gf-arow.is-queued .gf-aglyph path { fill: none; stroke: var(--stroke); stroke-dasharray: 2.5 2; }
.gf-arow.is-active .gf-aglyph { background: var(--surface); }
.gf-amain { grid-area: m; display: flex; flex-direction: column; min-width: 0; }
.gf-aname { font-weight: 500; line-height: 1.45; overflow-wrap: anywhere; }
.gf-asub { font-size: var(--fs-meta); line-height: 1.4; overflow-wrap: anywhere; }
.gf-ameta { grid-area: f; padding-top: 2px; font-size: var(--fs-meta); line-height: 1.4; white-space: nowrap; }
.gf-aprog { grid-area: p; display: block; margin: 8px 0 2px; }
/* A queued area waits its turn: "Next" on the right.  Pointing at the row, or opening it, offers to start it now in that place. */
.gf-arow.is-queued .gf-ameta { align-self: center; padding-top: 0; min-width: 112px; text-align: right; transition: opacity var(--dur-1) var(--ease); }
.gf-astart { position: absolute; right: 16px; top: 50%; translate: 0 -50%; opacity: 0; transition: opacity var(--dur-1) var(--ease), background var(--dur-1) var(--ease), box-shadow var(--dur-1) var(--ease); }
.gf-ahead:hover > .gf-astart, .gf-astart:focus-visible, .gf-arow.is-open .gf-astart { opacity: 1; }
.gf-arow.is-queued > .gf-ahead:hover .gf-ameta, .gf-arow.is-queued.is-open .gf-ameta { opacity: 0; }
.gf-arow.is-queued > .gf-ahead:has(.gf-astart:focus-visible) .gf-ameta { opacity: 0; }
@media (hover: none) {
  .gf-astart { opacity: 1; }
  .gf-arow.is-queued .gf-ameta { opacity: 0; }
}

/* Plots of the open area: the rank square sits under the area's outline */
.gf-plist { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; }
.gf-prow {
  display: flex; align-items: center; gap: 16px; width: 100%; min-width: 0; padding: 8px 16px 8px 20px; border: 0; border-radius: var(--r-2);
  background: none; text-align: left; color: inherit; transition: background var(--dur-1) var(--ease);
}
.gf-prow:hover, .gf-prow.is-hot { background: var(--hover); }
.gf-prow.is-selected { background: var(--fill); }
.gf-prow.is-new { animation: rise var(--dur-3) var(--ease) both; }
.gf-pmain, .gf-pfig { display: flex; flex-direction: column; min-width: 0; }
.gf-pmain { flex: 1 1 auto; }
.gf-pfig { flex: none; align-items: flex-end; white-space: nowrap; }
.gf-pname, .gf-pmw { font-weight: 500; line-height: 1.45; }
.gf-pname { overflow-wrap: anywhere; }
.gf-psub, .gf-peur { font-size: var(--fs-meta); line-height: 1.4; }
.gf-psub { overflow-wrap: anywhere; }
.gf-prow:is(.is-moved, .is-dismissed) .gf-pname { font-weight: 400; }

/* The rank square: the same mark as on the map.  In the pipeline: a site's ring; dismissed: a dashed square. */
.gf-rk {
  position: relative; flex: none; display: grid; place-items: center; width: 24px; height: 24px; border-radius: var(--r-1);
  background: var(--ink); color: var(--on-ink); font-size: var(--fs-meta); font-weight: 400; line-height: 1; font-variant-numeric: tabular-nums;
}
.gf-rk:is(.is-moved, .is-dismissed) { background: none; }
.gf-rk:is(.is-moved, .is-dismissed)::after { content: ""; width: 12px; height: 12px; border: 1.5px solid var(--stroke); border-radius: 50%; }
.gf-rk.is-dismissed::after { border-style: dashed; border-radius: 3px; }
.gf-rk-live { position: absolute; right: -3px; top: -3px; width: 8px; height: 8px; border-radius: 50%; background: var(--ink); box-shadow: 0 0 0 2px var(--surface); animation: breathe-dot var(--breath) var(--ease-io) infinite; }
.gf-rk-lg { width: 32px; height: 32px; border-radius: var(--r-2); font-size: var(--fs-body); font-weight: 500; }

/* ---------- Right: one plot ---------- */
.gf-right { right: 16px; width: var(--rw); }
.gf-right.is-entering { animation: gf-panel-in var(--dur-3) var(--ease); }
@keyframes gf-panel-in { from { opacity: 0; transform: translateX(14px); } }
.gf-rhead { position: relative; flex: none; display: flex; align-items: flex-start; gap: 16px; padding: 20px 24px 0; }
.gf-rhead > .icon-btn { position: absolute; top: 14px; right: 14px; } /* in the corner, so the place line runs the full width */
.gf-rheading { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gf-rheading > .t-title { padding-right: 28px; }
.gf-rbody { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 24px 24px 20px; }
/* The two figures that decide it, set big and light; under each, its name with how sure we are */
.gf-figs { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.gf-fig { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; }
.gf-sec { margin-top: 28px; }
.gf-sec > .section-title { margin-bottom: 2px; }
.gf-right .attr.is-far .attr-val { font-weight: 400; }
.gf-rfoot { flex: none; display: flex; align-items: center; gap: 8px; padding: 16px 24px 20px; border-top: 1px solid var(--line); }
.gf-rstate { white-space: nowrap; font-weight: 500; }

/* ---------- Bottom strip: country coverage, centred between the areas panel and the zoom control ---------- */
.gf-strip {
  position: absolute; z-index: 4; left: calc(var(--lw) + 32px + (100% - var(--lw) - 108px) / 2); bottom: 16px; translate: -50% 0;
  display: flex; align-items: center; height: 44px; padding: 0 6px; white-space: nowrap;
  border-radius: var(--r-pill); background: var(--surface); box-shadow: var(--shadow-2);
}
.gf-sg { position: relative; display: inline-flex; align-items: center; gap: 2px; padding: 0 8px; }
.gf-sg + .gf-sg::before { content: ""; position: absolute; left: 0; top: 50%; height: 20px; margin-top: -10px; width: 1px; background: var(--line); }
.gf-sg-l { padding: 0 6px 0 4px; font-size: var(--fs-meta); }
.gf-cc { padding: 0 10px; gap: 8px; }
.gf-pct { font-weight: 400; }
.gf-more { padding: 0 6px 0 2px; font-size: var(--fs-meta); cursor: default; }

/* ---------- Zoom: the shared UI.zoomctl, at the bottom right of the free map.  Beside an open plot it stands with
   its foot level with the panel's (--gf-zb, from grid.js), clear of the strip, so the plot keeps the whole height. ---------- */
.gf > .zoomctl { transition: right var(--dur-3) var(--ease), bottom var(--dur-3) var(--ease); }
.gf.has-plot > .zoomctl { right: calc(var(--rw) + 32px); bottom: var(--gf-zb, 76px); }

/* ---------- Drawing: the bar at the top and the name card ---------- */
.gf-hint {
  position: absolute; z-index: 6; top: 12px; left: 50%; translate: -50% 0;
  display: flex; align-items: center; gap: 16px; height: 44px; padding: 0 6px 0 5px; white-space: nowrap;
  border-radius: var(--r-pill); background: var(--surface); box-shadow: var(--shadow-2);
  animation: pop-in var(--dur-2) var(--ease);
}
.gf-hint-text { font-weight: 500; }
.gf-hint .btn .kbd { margin-left: 2px; }

.gf-card {
  position: absolute; z-index: 7; left: 0; top: 0; width: 312px;
  display: flex; flex-direction: column; gap: 12px; padding: 20px;
  border-radius: var(--r-4); background: var(--surface); box-shadow: var(--shadow-3);
  animation: gf-fade var(--dur-2) var(--ease);
}
.gf-card-fact { display: flex; align-items: center; gap: 10px; padding-top: 2px; line-height: 1.4; }
.gf-card-fact .ic { width: 16px; height: 16px; }
.gf-card-actions { display: flex; align-items: center; gap: 8px; margin-top: 4px; }
.gf-card-actions .icon-btn { margin-right: -6px; }

/* In this room the country strip owns the bottom edge: toasts rise above it */
.app[data-mode="grid"] ~ .toasts { bottom: 76px; }

/* ---------- Smaller screens (1280 × 800) ---------- */
@media (max-width: 1360px) {
  .gf { --lw: 316px; --rw: 344px; }
}
@media (max-height: 860px) {
  .gf-lhead { padding-top: 12px; }
  .gf-abtn { padding-top: 8px; padding-bottom: 8px; }
  .gf-rhead { padding-top: 16px; }
  .gf-rbody { padding-top: 20px; }
  .gf-sec { margin-top: 24px; }
  .gf-rfoot { padding-top: 12px; padding-bottom: 16px; }
}
