/* EquipmentIcons font — loaded from Flutter web assets so the truck
   glyph (\e918) used by `.fd-dot__label::before` resolves. */
@font-face {
  font-family: 'EquipmentIcons';
  src: url('/assets/packages/future_driver_flutter_core/lib/fonts/EquipmentIcons.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
  font-display: block;
}

/*
 * Fresh AdvancedMarker styles — buildup v3.
 *
 * Geometry contract (matches `_DotMarker.anchorPx` in
 * apps/storybook/lib/map/dot_markers_example.dart):
 *
 *   wrapper          14 × 14   (the disc)
 *   anchorPx         (7, 7)    (disc centre = lat/lng pixel)
 *   stick            ::after   (vertical line above wrapper top)
 *
 * Two presentations, single wrapper / single anchor:
 *   .fd-dot                → zoom < 13. Plain disc.
 *                            On :hover, the stick grows in.
 *   .fd-dot.is-near        → zoom ≥ 13. Disc + stick visible.
 *
 * No layout/size change between states — the stick is painted by
 * ::after positioned above the wrapper, so the wrapper bounds (and
 * therefore the anchor pixel) stay fixed regardless of hover or
 * zoom-tier. Rule 5 / Rule 4 of
 * packages/core/lib/widget/map/ADVANCED_MARKER_ANCHORING.md.
 */

/* Generic hover-lift — every AdvancedMarker wrapper (tagged
   `data-fd-wrapper="1"` by the fork) jumps to z-index 1000 while
   under the cursor.
   ALSO lifts the wrapper's parent (the zero-size anchor host gmaps
   creates in anchorPx mode — see fork convert.dart:730). gmaps sets
   each host's z-index inline from the marker's `zIndex` Dart prop,
   so without this `:has` rule the host stays at its baseline value
   and stacks siblings on top of the hovered marker's content (the
   inner wrapper's CSS z-index can't escape its parent's stacking
   context). `*:has(> [data-fd-wrapper]:hover)` matches only the
   immediate host. */
[data-fd-wrapper]:hover,
*:has(> [data-fd-wrapper]:hover) {
  z-index: 1000 !important;
}

.fd-dot {
  --fd-dot-color: #6b7280;
  --fd-dot-size: 14px;
  /* Stick reaches this far above the wrapper top. */
  --fd-stick-height: 28px;

  width: var(--fd-dot-size);
  height: var(--fd-dot-size);
  border-radius: 50%;
  background: var(--fd-dot-color);
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  box-sizing: border-box;
  position: relative;
  overflow: visible;
  /* Pivot transforms around the anchor pixel — disc stays glued to
     lat/lng under scale/rotate. Rule 4. */
  transform-origin: var(--fd-anchor-x) var(--fd-anchor-y);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

/* Bitmap fallback — hide on web, the wrapper owns the visual. */
.fd-dot > img { display: none !important; }

/* Invisible hover shield — extends the hover hit area from the disc
   centre up past the lifted registration card so the cursor never
   leaves an element matching `.fd-dot:hover` while:
     - the user is moving cursor between disc → stick → label;
     - the reg card animates 22 px upward and the status pill scales
       in beneath it (transition gap would otherwise drop :hover and
       cause the layout to flap).
   The shield is part of `.fd-dot` (it's `::before`) so cursor over
   it still satisfies `.fd-dot:hover`.
   It activates only when there's visible content above the disc to
   hover — i.e. in `.is-near` (pill mode, label is always shown), or
   while the marker is already hovered (dot mode mid-hover) — so the
   shield doesn't intercept map clicks in dot mode at rest. */
.fd-dot::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 72px;
  height: 96px;
  margin-left: -36px;
  pointer-events: none;
}

.fd-dot.is-near::before,
.fd-dot:hover::before {
  pointer-events: auto;
}

/* Stick: vertical line above the disc. Painted by ::after positioned
   from the wrapper's TOP edge upward (`bottom: 100%`). Width 2 px,
   centered. Default state (zoom < 13) hides it; .is-near and :hover
   reveal it. */
.fd-dot::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 2px;
  height: var(--fd-stick-height);
  margin-left: -1px;
  background: var(--fd-dot-color);
  border-radius: 1px;
  transform-origin: bottom center;
  transform: scaleY(0);
  transition: transform 0.18s ease;
  pointer-events: none;
}

/* Stick reveal:
     – always in pill mode (.is-near, zoom ≥ 13)
     – on hover in dot mode (zoom < 13) so the dot morphs to look
       like the pill-mode visual without changing wrapper size. */
.fd-dot.is-near::after,
.fd-dot:hover::after {
  transform: scaleY(1);
}

/* Hover grow — pure scale around the anchor pixel; wrapper size
   unchanged, anchorPx unaffected. (z-index lift is owned by the
   generic `[data-fd-wrapper]:hover` rule at the top of the file —
   don't duplicate it here.) */
.fd-dot:hover {
  transform: scale(1.25);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
}

/* Selected — colour inversion. The marker turns into a white card
   with status-coloured border + status-coloured content; pulse is
   stopped so keyframes don't overwrite the static look. Stick + reg
   card are forced visible so the whole marker reads as "active". */
.fd-dot.is-selected {
  animation: none !important;
  transform: scale(1.4);
  background: #fff !important;
  border: 3px solid var(--fd-dot-color) !important;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
  /* Tier: selected — above persistent lifts (100), below hover (1000). */
  z-index: 200 !important;
}
.fd-dot.is-selected::after {
  transform: scaleY(1);
  /* Stick uses status colour against the now-white surroundings. */
  background: var(--fd-dot-color);
}
.fd-dot.is-selected .fd-dot__label {
  transform: translateX(-50%) scale(1) !important;
  /* White card body, status-coloured text + border. */
  background: #fff !important;
  color: var(--fd-dot-color) !important;
  border-color: var(--fd-dot-color) !important;
}
/* Equipment icon chip — status-coloured glyph against white reg card. */
.fd-dot.is-selected .fd-dot__label::before {
  color: var(--fd-dot-color);
}
/* Presence dot keeps its green/red signal — only thicker outline. */
.fd-dot.is-selected .fd-dot__reg::after {
  box-shadow: 0 0 0 1.5px var(--fd-dot-color);
}

/* Registration card — sits on top of the stick. Bottom of the card
   aligns with the top of the stick (= wrapper top + stick height),
   centred horizontally on the disc.
   The card is painted outside the wrapper, so the wrapper bounds
   stay 14×14 and anchorPx remains the disc centre regardless of card
   width / hover state. */
.fd-dot__label {
  position: absolute !important;
  left: 50% !important;
  bottom: calc(100% + var(--fd-stick-height)) !important;
  top: auto !important;
  right: auto !important;
  transform: translateX(-50%) scale(0) !important;
  transform-origin: bottom center;
  padding: 5px 10px;
  border-radius: 7px;
  background: var(--fd-dot-color);
  color: #fff;
  font: 700 13px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0.02em;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  border: 1.5px solid #fff;
  /* Hoverable — cursor on the label triggers `.fd-dot:hover` via
     DOM ancestry, expanding the status row and lifting the card. */
  pointer-events: auto;
  cursor: pointer;
  transition: transform 0.18s ease, bottom 0.18s ease,
              border-radius 0.18s ease;
}

/* Card reveal — same trigger as the stick: pill mode or hover. */
.fd-dot.is-near .fd-dot__label,
.fd-dot:hover .fd-dot__label {
  transform: translateX(-50%) scale(1) !important;
}

/* Reg sub-span — holds the registration text plus the trailing
   presence dot (`.fd-dot__reg::after`). Wrapping the reg lets the
   driver name drop onto its own line below WITHOUT stranding the
   presence dot: the dot lives inside this span, so it stays on the reg
   line instead of flowing after the block-level driver line. The
   leading equipment glyph stays on `.fd-dot__label::before`. */
.fd-dot__reg {
  display: inline-block;
}

/* Driver name — printed on a quieter SECOND line under the
   registration for any marker that resolves to a (latest) driver.
   Block so it wraps below reg + presence dot; `white-space: nowrap`
   inherited from the label keeps the name itself on one line. */
.fd-dot__driver {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.01em;
  opacity: 0.9;
}

/* Status row — white card under the registration. Painted outside
   the wrapper so wrapper bounds / anchorPx stay constant. Sits at
   the SAME bottom as the reg card by default (= top of the stick).
   On hover the reg card is lifted up by the status-row height so
   they stack as two cards in a column. */
.fd-dot__status {
  position: absolute !important;
  left: 50% !important;
  bottom: calc(100% + var(--fd-stick-height)) !important;
  top: auto !important;
  right: auto !important;
  /* Fork applies inline `transform: translate(50%, -50%)` for the
     default top-right badge anchor — override with !important so the
     status pill stays centred over the disc, not pinned to the
     wrapper corner. */
  transform: translateX(-50%) scale(0) !important;
  transform-origin: bottom center;
  padding: 3px 8px;
  border-radius: 6px;
  background: #ffffff;
  color: #1f2937;
  font: 700 10px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0.05em;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  border: 1.5px solid var(--fd-dot-color);
  /* Hoverable too — when the cursor enters the lifted card, the
     status pill takes the card's old slot under the cursor, so hover
     sustains as the layout shifts. */
  pointer-events: auto;
  cursor: pointer;
  transition: transform 0.18s ease;
}

/* Hover reveals status pill and lifts the registration card so they
   stack: reg on top, status below, both above the stick. The lift
   distance matches the status pill's outer height (text 10 +
   padding 2×3 + border 2×1.5 ≈ 19; round to 20 + 2 px gap). */
.fd-dot:hover .fd-dot__status {
  transform: translateX(-50%) scale(1) !important;
}
.fd-dot:hover .fd-dot__label {
  bottom: calc(100% + var(--fd-stick-height) + 22px) !important;
}

/* Presence — online pulses, offline stays still. Composed alongside
   the base box-shadow so the existing drop shadow keeps working. The
   pulse uses the status colour so it reads as "this status, live". */
.fd-dot { --fd-presence-color: #94a3b8; }
.fd-dot.is-online  { --fd-presence-color: #22c55e; }
.fd-dot.is-offline { --fd-presence-color: #ef4444; }

@keyframes fd-dot-pulse {
  0% {
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35),
                0 0 0 0 var(--fd-dot-color);
  }
  100% {
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35),
                0 0 0 10px rgba(0, 0, 0, 0);
  }
}

.fd-dot.is-online {
  animation: fd-dot-pulse 1.6s ease-out infinite;
}

/* Time-since-last-update buckets — Dart adds one of these classes
   based on the minutes since the equipment's last beacon. Bound
   class set lets us encode the hover-pill text without per-marker
   inline styles (which the fork doesn't currently expose). For
   showcase usage outside the live map, `--fd-time` can also be set
   inline on the wrapper. */
.fd-dot.fd-since-now    { --fd-time: 'now'; }
.fd-dot.fd-since-recent { --fd-time: '<5m'; }
.fd-dot.fd-since-near   { --fd-time: '<30m'; }
.fd-dot.fd-since-hour   { --fd-time: '<1h'; }
.fd-dot.fd-since-day    { --fd-time: '<1d'; }
.fd-dot.fd-since-old    { --fd-time: 'old'; }

/* Equipment glyph preceding the reg text. EquipmentIcons font is
   declared at the top of this file — \e918 is the truck glyph. When
   marker data gets a per-type code, swap the glyph via a CSS var
   (e.g. `.fd-dot.fd-eq-trailer .fd-dot__label::before { content: …; }`). */
.fd-dot__label::before {
  content: var(--fd-eq-glyph, '\e918');
  font-family: 'EquipmentIcons';
  font-size: 17px;
  line-height: 1;
  margin-right: 7px;
  vertical-align: middle;
  display: inline-block;
  position: relative;
  top: -1px;
  color: inherit;
}

/* Presence dot trailing the registration text in the reg card. Drawn
   as a ::after pseudo on the reg span (NOT the label) so it stays on
   the reg line when a driver name occupies a block second line.
   Inherits its colour from --fd-presence-color so online/offline flip
   with the wrapper class. On hover the dot expands into a coloured pill
   carrying the time-since-last-update string from `--fd-time`. */
.fd-dot__reg::after {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  margin-left: 6px;
  padding: 0;
  background: var(--fd-presence-color);
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.9);
  vertical-align: middle;
  position: relative;
  top: -1px;
  font: 700 10px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0.02em;
  color: #fff;
  overflow: hidden;
  transition: width 0.18s ease, padding 0.18s ease;
}

/* Time pill — reveals on any hover (dot mode too, since dot hover
   already expands the label into pill form via the scale(0→1) rule
   above). Selector unscoped from `.is-near`. */
.fd-dot:hover .fd-dot__reg::after {
  content: var(--fd-time, '');
  width: auto;
  height: auto;
  padding: 2px 7px;
  top: 0;
}

/* Status colours — keys match ServiceStatus.name verbatim. */
.fd-dot.fd-dot-status-readyToUse    { --fd-dot-color: #5CAF8B; }
.fd-dot.fd-dot-status-needsService  { --fd-dot-color: #FF7A3A; }
.fd-dot.fd-dot-status-notAvailable  { --fd-dot-color: #A1A6AC; }
.fd-dot.fd-dot-status-atWorkshop    { --fd-dot-color: #0D436D; }
.fd-dot.fd-dot-status-booked        { --fd-dot-color: #C62D89; }
.fd-dot.fd-dot-status-urgentService { --fd-dot-color: #DF322D; }

/* Activity colours for tacho-unit hex markers — keys match
 * TachoActivityType.name. Same palette used by `.fd-tacho-portal`
 * and the legacy `.fd-tacho-hex` so the hex / popup / cluster-pill
 * all read in the same colour for the same activity. Applies when
 * the marker has no `fd-dot-status-*` class (tacho units render
 * with activity instead of service status). */
.fd-dot.a-drive     { --fd-dot-color: #0D436D; }
.fd-dot.a-rest      { --fd-dot-color: #A1A6AC; }
.fd-dot.a-work      { --fd-dot-color: #8C2DC6; }
.fd-dot.a-available { --fd-dot-color: #FF7A3A; }
.fd-dot.a-unknown   { --fd-dot-color: #A1A6AC; }

/* ============================================================
   Yard zone marker — untouched by the equipment-marker rebuild.
   ============================================================ */

.custom-marker-label {
  position: absolute !important;
  left: 50% !important;
  top: 0 !important;
  bottom: auto !important;
  transform: translate(-50%, calc(-100% - 8px)) !important;
}

.fd-yard {
  /* Bumped from 16×16 → 24×24 so a 2-digit count fits legibly
     inside the squircle. anchorPx in `_YardZone.anchorPx` follows:
       tiny    → Offset(12, 12) centre
       visible → Offset(12, 24) bottom-centre. */
  width: 24px !important;
  height: 24px !important;
  position: relative;
  box-sizing: border-box;
  overflow: visible;
  transform-origin: var(--fd-anchor-x) var(--fd-anchor-y);
}

/* Persistent lift — the yard squircle (always-cluster) sits above
   plain markers so it's never hidden by an ordinary equipment dot
   that happens to overlap. Hover is owned by the generic rule at
   the top of the file. */
.fd-yard.fd-yard--has-cluster {
  /* Tier: persistent lift — above base markers, below selected/hover. */
  z-index: 100 !important;
}

/* Selected yard — warm outer halo + thicker white ring around the
   squircle, label gains a white outline + slight scale. The polygon
   fill itself is owned by gmap (SVG fillColor) and bumps via Dart;
   here we only style the marker/label DOM. */
.fd-yard.is-selected.is-tiny::before,
.fd-yard.is-selected.fd-yard--has-cluster::before {
  border-width: 2.5px;
  box-shadow:
    0 0 0 3px rgba(200, 80, 23, 0.35),
    0 0 0 6px rgba(200, 80, 23, 0.18),
    0 2px 6px rgba(0, 0, 0, 0.45);
}
.fd-yard.is-selected .fd-yard__label {
  background: #C85017;
  box-shadow:
    0 0 0 1.5px #fff,
    0 0 0 3px rgba(200, 80, 23, 0.35),
    0 3px 8px rgba(0, 0, 0, 0.35);
  transform: translate(-50%, -4px) scale(1.06) !important;
}
.fd-yard.is-selected.is-tiny .fd-yard__label,
.fd-yard.is-selected.fd-yard--has-cluster .fd-yard__label {
  transform: translate(-50%, calc(-100% - 4px)) scale(1.06) !important;
}
.fd-yard.is-selected.fd-yard--has-cluster {
  /* Lift above sibling yards so the halo isn't clipped. */
  z-index: 200 !important;
}

.fd-yard img { display: none !important; }

/* Squircle paints in two cases:
   – `.is-tiny` → polygon is sub-pixel, this is the only visible
     marker for the zone.
   – `.fd-yard--has-cluster` → cluster has occupants; the squircle
     + count badge become the affordance (matches the showcase
     "tiny + cluster" cell). */
.fd-yard.is-tiny::before,
.fd-yard.fd-yard--has-cluster::before {
  content: '';
  position: absolute;
  inset: 0;
  background: #C85017;
  border: 2px solid #fff;
  border-radius: 32%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  box-sizing: border-box;
  transform: rotate(45deg);
}

/* Yard-with-cluster — the squircle reads as an EQUIPMENT cluster
   affordance here, not a yard marker. Repaint it in the
   `.fd-equip-cluster` blue palette so users can tell apart:
     · plain tiny yard (orange) → empty yard, just a label
     · yard with cluster (blue) → equipment grouped inside the yard
     · multi-yard cluster (.fd-yard-cluster, orange stack) → yards
   The yard's polygon stays orange regardless — colour swap is on
   the count squircle only. This rule sits AFTER the base orange
   block so the cascade hands the win to blue when both apply. */
.fd-yard.fd-yard--has-cluster::before {
  background: #4797D3;
  box-shadow:
    0 1px 3px rgba(0, 0, 0, 0.4),
    0 0 0 4px rgba(71, 151, 211, 0.20);
}
.fd-yard.is-area.fd-yard--has-cluster::before {
  /* Area-category yards also flip to blue when they contain a
     cluster — the cluster identity wins over the yellow area
     palette. */
  background: #4797D3;
}
.fd-yard.is-selected.fd-yard--has-cluster::before {
  /* Selected-state halo also flips to blue so the cluster palette
     stays consistent across states. */
  box-shadow:
    0 0 0 3px rgba(71, 151, 211, 0.35),
    0 0 0 6px rgba(71, 151, 211, 0.18),
    0 2px 6px rgba(0, 0, 0, 0.45);
}

/* Count overlay — drawn at the squircle centre. Border, fill and
   shadow of the squircle itself stay identical to the no-cluster
   tiny yard; only the count text differs to signal occupancy. The
   wrapper is unrotated so the count reads upright while the
   ::before pseudo (rotated 45°) gives the diamond outline. */
.fd-yard__count {
  position: absolute !important;
  left: 50% !important;
  top: 50% !important;
  right: auto !important;
  bottom: auto !important;
  transform: translate(-50%, -50%) !important;
  color: #fff;
  font: 700 12px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.45);
  pointer-events: none;
}

/* History-view variant — equipment-history contribution tags the
   visited yard polygons with `fd-yard--history` to recolour the
   squircle + label in the history palette (FigmaColors.blue200 =
   #4797D3), matching the entered/left geozone event pins, tile
   dots, and timeline lane markers. Rules apply on top of the base
   .fd-yard styling so the squircle shape, hover, and cluster
   behaviour stay identical to the standard yard. */
.fd-yard.fd-yard--history::before,
.fd-yard.fd-yard--history.is-tiny::before,
.fd-yard.fd-yard--history.fd-yard--has-cluster::before {
  background: #4797D3;
  border-color: #FFFFFF;
}
.fd-yard.fd-yard--history .fd-yard__label {
  background: #4797D3;
  color: #FFFFFF;
}
.fd-yard.fd-yard--history.is-selected::before {
  box-shadow:
    0 0 0 3px rgba(71, 151, 211, 0.4),
    0 0 0 6px rgba(71, 151, 211, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.45);
}

/* ============================================================
   Equipment cluster — count badge for grouped equipment markers
   outside zones. fdBlue disc (matches service-map pin colour), white
   count. Kept visually distinct from the yard squircle (orange) and
   the multi-yard cluster (stacked orange squircles).
   ============================================================ */
.fd-equip-cluster {
  --fd-cluster-color: #4797D3;
  --fd-cluster-size: 36px;
  width: var(--fd-cluster-size) !important;
  height: var(--fd-cluster-size) !important;
  border-radius: 50%;
  background: var(--fd-cluster-color);
  border: 2px solid #fff;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.35),
              0 0 0 6px rgba(71, 151, 211, 0.20);
  box-sizing: border-box;
  position: relative;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  color: #fff;
  font: 700 13px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0.01em;
  transform-origin: var(--fd-anchor-x) var(--fd-anchor-y);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.fd-equip-cluster:hover {
  /* Hover signal is the popover reveal — no scale on the disc so
     popover pills (DOM children of the disc) stay at their designed
     size. Shadow boost only. (z-index owned by generic rule.) */
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4),
              0 0 0 8px rgba(71, 151, 211, 0.28);
}
.fd-equip-cluster > img { display: none !important; }

/* Count label — emitted via customHtml as a plain <span>; positioned
   here explicitly (the fork's typed-slot center anchor isn't applied
   because we don't use the label slot). Inherits colour/font from
   the wrapper so we don't duplicate size/weight rules. */
.fd-equip-cluster__count {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  white-space: nowrap;
  color: inherit;
  font: inherit;
}
/* Size bucket for big clusters — slight growth so 100+ is obvious. */
.fd-equip-cluster.is-big {
  --fd-cluster-size: 44px;
  font-size: 14px;
}

/* ============================================================
   Yard cluster — multiple yards grouped at low zoom. Two stacked
   orange squircles: the FRONT squircle is centred on the wrapper
   (and therefore on the anchor pixel), the BACK squircle peeks out
   bottom-right behind it. Anchor stays at the count-bearing front,
   so the cluster reads as "located at the crosshair".
   ============================================================ */
.fd-yard-cluster {
  --fd-yc-size: 32px;
  --fd-yc-diamond: 22px;
  --fd-yc-color: #C85017;
  --fd-yc-color-back: #A0411A;
  width: var(--fd-yc-size) !important;
  height: var(--fd-yc-size) !important;
  position: relative;
  box-sizing: border-box;
  overflow: visible;
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  transform-origin: var(--fd-anchor-x) var(--fd-anchor-y);
}
.fd-yard-cluster img { display: none !important; }

/* Back squircle — peeks out to the right behind the front (x-only
   displacement, keeps the stack on the anchor's horizontal line). */
.fd-yard-cluster::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--fd-yc-diamond);
  height: var(--fd-yc-diamond);
  margin: calc(var(--fd-yc-diamond) / -2) 0 0
          calc(var(--fd-yc-diamond) / -2);
  transform: translate(8px, 0) rotate(45deg);
  background: var(--fd-yc-color-back);
  border: 1.5px solid #fff;
  border-radius: 32%;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  box-sizing: border-box;
  z-index: 0;
}

/* Front squircle — centred on the anchor; holds the count. */
.fd-yard-cluster::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--fd-yc-diamond);
  height: var(--fd-yc-diamond);
  margin: calc(var(--fd-yc-diamond) / -2) 0 0
          calc(var(--fd-yc-diamond) / -2);
  transform: rotate(45deg);
  background: var(--fd-yc-color);
  border: 1.5px solid #fff;
  border-radius: 32%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35);
  box-sizing: border-box;
  z-index: 1;
}

/* Count text — wrapper is unrotated so digits read upright; sits at
   wrapper centre which is also the front-squircle centre. */
.fd-yard-cluster__count {
  position: absolute !important;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  font: 700 12px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  z-index: 2;
}

.fd-yard-cluster:hover::after {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
}

/* Bigger bucket — ≥10 yards in the cluster. */
.fd-yard-cluster.is-big {
  --fd-yc-size: 40px;
  --fd-yc-diamond: 28px;
}
.fd-yard-cluster.is-big .fd-yard-cluster__count {
  font-size: 13px;
}

/* Yard pill — popover list of yard names. Orange filled pill,
   matches the yard squircle palette. Single key (`s-yard`) avoids
   per-status colour scattering. */
.fd-cluster-pill.s-yard {
  --pill-color: #C85017;
  background: var(--pill-color);
  color: #fff;
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 11px;
}
.fd-cluster-pill.s-yard .fd-cluster-pill__dot {
  background: rgba(255, 255, 255, 0.85);
  border: 1.5px solid #fff;
}

/* ----------------------------------------------------------------
   Cluster hover popover — reveals the breakdown of grouped items.
   Two variants:
     .is-list   → count < 5: vertical stack of registration pills,
                  each in its equipment status colour.
     .is-flower → count ≥ 5: status-tally pills radially placed
                  around the disc; per-pill (top, left) set inline.
   The popover is an absolutely-positioned child of the cluster
   wrapper so the cluster's hover state ( :hover OR forced via
   .cell.is-hover for the showcase ) reveals it without changing
   the wrapper bounds — anchorPx stays glued to the disc centre.
   ---------------------------------------------------------------- */
.fd-cluster-popover {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
  z-index: 5;
}

.fd-equip-cluster:hover .fd-cluster-popover,
.cell.is-hover .fd-cluster-popover,
/* Keep the popover visible while the cursor is on any pill, so the
   user can move from the disc onto a registration pill without it
   collapsing. Uses :has() (Chrome 105+, Safari 15.4+ — fine for our
   web target). */
.fd-equip-cluster:has(.fd-cluster-pill:hover) .fd-cluster-popover,
/* Yard squircle in EITHER tiny OR visible mode (with a cluster)
   reuses the same popover — hover the diamond / label to reveal the
   grouped-equipment breakdown. */
.fd-yard.fd-yard--has-cluster:hover .fd-cluster-popover,
.fd-yard.fd-yard--has-cluster:has(.fd-cluster-pill:hover) .fd-cluster-popover,
/* Yard cluster (multi-yard) — hover reveals the names list. */
.fd-yard-cluster:hover .fd-cluster-popover,
.fd-yard-cluster:has(.fd-cluster-pill:hover) .fd-cluster-popover {
  opacity: 1;
}

/* Individual pill — white card, coloured dot left, text right. */
.fd-cluster-pill {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px 5px 8px;
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18);
  font: 700 10px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  color: #94a3b8;
  white-space: nowrap;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  /* Override the popover container's pointer-events:none so pills
     get their own :hover (and the parent :has() rule above can keep
     the popover visible while cursor is on a pill). */
  pointer-events: auto;
  cursor: pointer;
  /* (top, left) set inline per pill — translate(-50%,-50%) centres
     the pill on that coordinate so radial math is symmetric. The
     hover rule below preserves the centring while adding scale. */
  transform: translate(-50%, -50%) scale(1);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.fd-cluster-pill:hover {
  transform: translate(-50%, -50%) scale(1.12);
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.28);
  /* Hover tier — same value as `[data-fd-wrapper]:hover`. The pill
     lives inside the wrapper's stacking context, so this competes
     with sibling pills (where any large number suffices) but the
     value matches the universal "hovered" tier for consistency. */
  z-index: 1000;
}

.fd-cluster-pill__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--pill-color, #94a3b8);
  flex: 0 0 auto;
}

.fd-cluster-pill__count {
  font-size: 12px;
  color: #1f2937;
}

/* Status palette — keys match ServiceStatus.name. */
.fd-cluster-pill.s-readyToUse    { --pill-color: #5CAF8B; }
.fd-cluster-pill.s-needsService  { --pill-color: #FF7A3A; }
.fd-cluster-pill.s-notAvailable  { --pill-color: #A1A6AC; }
.fd-cluster-pill.s-atWorkshop    { --pill-color: #0D436D; }
.fd-cluster-pill.s-booked        { --pill-color: #C62D89; }
.fd-cluster-pill.s-urgentService { --pill-color: #DF322D; }
/* Activity-keyed pills for tacho-unit cluster popover entries. */
.fd-cluster-pill.s-drive         { --pill-color: #0D436D; }
.fd-cluster-pill.s-rest          { --pill-color: #A1A6AC; }
.fd-cluster-pill.s-work          { --pill-color: #8C2DC6; }
.fd-cluster-pill.s-available     { --pill-color: #FF7A3A; }
.fd-cluster-pill.s-unknown       { --pill-color: #A1A6AC; }

/* Reg-pill modifier — used in `<5` listings where each pill shows a
   single registration in its equipment status colour. Pill is filled
   with the status colour and the dot inverts to a white badge so it
   reads as a "stamp" on the colour. */
.fd-cluster-pill--reg {
  background: var(--pill-color);
  color: #fff;
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 11px;
}
.fd-cluster-pill--reg .fd-cluster-pill__dot {
  background: rgba(255, 255, 255, 0.85);
  border: 1.5px solid #fff;
}

.fd-yard__label {
  /* Default (visible polygon): wrapper is 24 tall with anchorPx at
     bottom-centre (12, 24) on the polygon top edge. Pin the label's
     BOTTOM to the wrapper bottom edge so it sits ~4 px above the
     anchor (= polygon top edge) instead of floating up by the full
     wrapper height. */
  position: absolute !important;
  left: 50% !important;
  top: auto !important;
  bottom: 0 !important;
  /* `bottom: 0` puts the label's bottom edge at the wrapper's bottom
     (= the anchor pixel, since wrapper top = -anchorY). translate
     only nudges 4 px upward — NO `-100%` (that would re-lift by the
     full label height and recreate the old big gap). */
  transform: translate(-50%, -4px) !important;
  padding: 4px 8px;
  border-radius: 4px;
  background: rgba(200, 80, 23, 0.95);
  color: #fff;
  font: 600 12px/1.2 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

/* Area-category zone — yellow polygon theme. Label is a white pill
   with a yellow border + dark text so it reads against the yellow
   fill without re-using the yard orange. Squircle (tiny / has-cluster)
   also flips to yellow so the marker matches the polygon. */
.fd-yard.is-area .fd-yard__label {
  background: rgba(255, 255, 255, 0.95);
  color: #5A4500;
  border: 1px solid #D0A404;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.fd-yard.is-area.is-tiny::before,
.fd-yard.is-area.fd-yard--has-cluster::before {
  background: #F3C935;
  border-color: #fff;
}
.fd-yard.is-area .fd-yard__count {
  color: #5A4500;
  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
}
/* Selected area — keep the white pill, add a subtle yellow halo so
   selection is visually distinct without re-introducing the orange
   that's reserved for yards. Stays below the yard `.is-selected`
   z-index bump (area sits below yards by gmap zIndex anyway). */
.fd-yard.is-area.is-selected .fd-yard__label {
  background: rgba(255, 255, 255, 1);
  box-shadow:
    0 0 0 1.5px #D0A404,
    0 0 0 3px rgba(243, 201, 53, 0.35),
    0 3px 8px rgba(0, 0, 0, 0.25);
  transform: translate(-50%, -4px) scale(1.06) !important;
}
.fd-yard.is-area.is-selected.is-tiny .fd-yard__label,
.fd-yard.is-area.is-selected.fd-yard--has-cluster .fd-yard__label {
  transform: translate(-50%, calc(-100% - 4px)) scale(1.06) !important;
}
/* Area must not borrow the yard `is-selected.has-cluster` z-index
   bump — selected areas should stay BELOW yards regardless of state.
   The generic rule lifts to 200; cancel it for areas. */
.fd-yard.is-area.is-selected.fd-yard--has-cluster {
  z-index: auto !important;
}

/* Label sits ABOVE the squircle whenever the squircle paints — i.e.
   tiny mode OR has-cluster. The rotated diamond's corners poke ~5 px
   above the wrapper top, so the literal `4px` offset gives ~9 px of
   visible gap from the diamond's tip to the label bottom — tight but
   clear. Pointer-events auto so cursor on the label also triggers
   `.fd-yard:hover` via DOM ancestry. */
.fd-yard.is-tiny .fd-yard__label,
.fd-yard.fd-yard--has-cluster .fd-yard__label {
  top: 0 !important;
  bottom: auto !important;
  transform: translate(-50%, calc(-100% - 4px)) !important;
  pointer-events: auto !important;
}

/* ============================================================
   Detail card — secondary hover variant.
   Opt-in via `.fd-dot--detail` on the wrapper. When the pill is
   hovered, instead of (or in addition to) the simple status-pill
   reveal, a full info card opens above the marker. The card lives
   inside the wrapper as `customHtml` so it scopes to this marker.
   Initial render is in a skeleton state; flip `.is-loaded` on the
   card root once data has resolved.
   ============================================================ */

.fd-detail-card {
  position: absolute !important;
  left: 50% !important;
  bottom: calc(100% + var(--fd-stick-height)) !important;
  top: auto !important;
  right: auto !important;
  /* Hidden by default; revealed only when the wrapper is hovered. */
  transform: translateX(-50%) scale(0) !important;
  transform-origin: bottom center;
  width: 280px;
  background: #fff;
  border: 2px solid var(--fd-dot-color);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22);
  color: #1f2937;
  font: 500 12px/1.3 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  /* Card swallows pointer so cursor moving from disc onto the card
     keeps the wrapper :hover alive (DOM-ancestor rule). */
  pointer-events: auto;
  cursor: pointer;
  transition: transform 0.2s ease;
}

.fd-dot.fd-dot--detail:hover .fd-detail-card {
  transform: translateX(-50%) scale(1) !important;
}

/* Hide the simpler status-pill / time-pill expansion in detail mode —
   the detail card replaces it. */
.fd-dot.fd-dot--detail:hover .fd-dot__status { display: none !important; }
.fd-dot.fd-dot--detail:hover .fd-dot__label { bottom: calc(100% + var(--fd-stick-height)) !important; }

/* ---- Header band (status colour) ---- */
.fd-detail-card__header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: color-mix(in srgb, var(--fd-dot-color) 18%, #fff);
  color: var(--fd-dot-color);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.02em;
}
.fd-detail-card__hdr-icon {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'EquipmentIcons';
  font-size: 13px;
  color: var(--fd-dot-color);
  flex: 0 0 auto;
}
.fd-detail-card__reg {
  font-weight: 700;
  font-size: 14px;
  color: #1f2937;
  flex: 1 1 auto;
}
.fd-detail-card__hdr-right {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  letter-spacing: 0.05em;
}
.fd-detail-card__check {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--fd-dot-color);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
}
/* ---- Body ---- */
.fd-detail-card__body {
  background: #fff;
}
.fd-detail-card__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-top: 1px solid #f1f5f9;
}
.fd-detail-card__row:first-child { border-top: 0; }
.fd-detail-card__row--cols-2 { gap: 0; }
.fd-detail-card__row--cols-2 > .fd-detail-card__field { flex: 1 1 0; padding-right: 8px; }
.fd-detail-card__row--cols-2 > .fd-detail-card__field + .fd-detail-card__field {
  border-left: 1px solid #f1f5f9;
  padding-left: 10px;
  padding-right: 0;
}

.fd-detail-card__field {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
}
.fd-detail-card__ic {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #e2e8f0;
  color: #475569;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
}
/* Warning palette — kept for the wrapper-embedded legacy markup
   that uses `--warning` modifier directly. */
.fd-detail-card__field--warning .fd-detail-card__ic {
  background: #fee2e2;
  color: #dc2626;
}
/* Same palette, applied conditionally to the last-report field when
   the card root has `.is-stale` (last metric older than the 15-min
   threshold or missing entirely). The dynamic version — Dart toggles
   the class on the card root post-load. */
.fd-detail-card.is-stale .fd-detail-card__field--last-report .fd-detail-card__ic {
  background: #fee2e2;
  color: #dc2626;
}
.fd-detail-card__field-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.fd-detail-card__field-value {
  font-size: 12px;
  color: #1f2937;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.fd-detail-card__field--warning .fd-detail-card__field-value { color: #dc2626; }
.fd-detail-card.is-stale .fd-detail-card__field--last-report .fd-detail-card__field-value { color: #dc2626; }
.fd-detail-card__field-label {
  font-size: 10px;
  color: #94a3b8;
}

/* "No report" row — special composition: small grid placeholder +
   "No report" text + a couple of icons on the right. */
.fd-detail-card__row--no-report .fd-detail-card__no-report-grid {
  width: 26px;
  height: 16px;
  background:
    linear-gradient(90deg, #cbd5e1 0 5px, transparent 5px 7px) repeat-x,
    linear-gradient(90deg, transparent 0 9px, #cbd5e1 9px 14px, transparent 14px 16px) repeat-x,
    linear-gradient(90deg, transparent 0 18px, #cbd5e1 18px 23px, transparent 23px 26px) repeat-x;
  background-size: 26px 5px, 26px 5px, 26px 5px;
  background-position: 0 0, 0 6px, 0 12px;
  flex: 0 0 auto;
}
.fd-detail-card__row--no-report .fd-detail-card__no-report-text {
  font-weight: 700;
  color: #475569;
  flex: 1 1 auto;
}
.fd-detail-card__no-report-icons {
  display: inline-flex;
  gap: 6px;
  flex: 0 0 auto;
}
.fd-detail-card__no-report-icons::before,
.fd-detail-card__no-report-icons::after {
  content: '';
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 1.5px dashed #fca5a5;
  border-radius: 4px;
}

/* ---- Footer link ---- */
.fd-detail-card__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-top: 1px solid #f1f5f9;
  font-weight: 700;
  color: #0f172a;
  text-decoration: none;
  cursor: pointer;
}
.fd-detail-card__footer:hover {
  background: #f8fafc;
}
.fd-detail-card__footer::after {
  content: '›';
  font-size: 16px;
  color: #64748b;
}

/* ---- Skeleton shimmer ---- */
@keyframes fd-skel-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.fd-skel {
  /* Replaces text content with a shimmering bar in loading state.
     `.fd-detail-card.is-loaded` flips this off (see rule below). */
  display: inline-block;
  width: 70%;
  height: 12px;
  border-radius: 4px;
  background: linear-gradient(90deg, #e2e8f0 0%, #f1f5f9 50%, #e2e8f0 100%);
  background-size: 200% 100%;
  animation: fd-skel-shimmer 1.4s ease-in-out infinite;
  color: transparent;
  vertical-align: middle;
}
.fd-skel--sm { height: 9px; width: 50%; }

/* Loaded state — JS adds `.is-loaded` either to the card root
   (wrapper-embedded variant, web app patches the card directly) OR
   to the portal parent (storybook adds the class to the
   `.fd-detail-portal` className via Dart state when the fake-async
   load timer fires). Skeleton bars revert to their text content
   in both cases. */
.fd-detail-card.is-loaded .fd-skel,
.fd-detail-portal.is-loaded .fd-skel {
  display: inline;
  width: auto;
  height: auto;
  background: none;
  animation: none;
  color: inherit;
}

/* ============================================================
   Per-equipment-type glyph — `.fd-eq-{type}` swaps the truck
   default. Codepoints map 1:1 to the `EquipmentTypeIcon` enum (see
   `packages/core/lib/model/equipment/equipment_type_icons.dart`)
   and are sourced from the EquipmentIcons font declared at the top
   of this file. Painted inside `.fd-dot__label::before`; only the
   `content` differs per type — size / padding / colour stay.
   ============================================================ */
/* Type-specific glyph code published as a CSS variable on the wrapper.
 * Consumed by `.fd-dot__label::before` (the reg-card glyph) and
 * `.fd-dot__glyph::before` (the centred hex glyph when the marker
 * runs in `.fd-dot--tacho` mode). One source of truth per type. */
.fd-dot.fd-eq-truckFixedBox         { --fd-eq-glyph: '\e900'; }
.fd-dot.fd-eq-swapBodyRefrigerator  { --fd-eq-glyph: '\e901'; }
.fd-dot.fd-eq-bulkContainer         { --fd-eq-glyph: '\e902'; }
.fd-dot.fd-eq-containerChassis      { --fd-eq-glyph: '\e903'; }
.fd-dot.fd-eq-gasContainerTruckLift { --fd-eq-glyph: '\e904'; }
.fd-dot.fd-eq-liftContainer         { --fd-eq-glyph: '\e905'; }
.fd-dot.fd-eq-containerTruck        { --fd-eq-glyph: '\e906'; }
.fd-dot.fd-eq-curtainsider          { --fd-eq-glyph: '\e907'; }
.fd-dot.fd-eq-dolly                 { --fd-eq-glyph: '\e908'; }
.fd-dot.fd-eq-flatbed               { --fd-eq-glyph: '\e909'; }
.fd-dot.fd-eq-gasContainerTruck     { --fd-eq-glyph: '\e90a'; }
.fd-dot.fd-eq-gasTractor            { --fd-eq-glyph: '\e90b'; }
.fd-dot.fd-eq-linkTrailer           { --fd-eq-glyph: '\e90c'; }
.fd-dot.fd-eq-movingFloor           { --fd-eq-glyph: '\e90d'; }
.fd-dot.fd-eq-removableGooseneck    { --fd-eq-glyph: '\e90e'; }
.fd-dot.fd-eq-stretchRGN            { --fd-eq-glyph: '\e90f'; }
.fd-dot.fd-eq-swapBodySide          { --fd-eq-glyph: '\e910'; }
.fd-dot.fd-eq-swapBody              { --fd-eq-glyph: '\e911'; }
.fd-dot.fd-eq-tankTrailer           { --fd-eq-glyph: '\e912'; }
.fd-dot.fd-eq-thermoTrailer         { --fd-eq-glyph: '\e913'; }
.fd-dot.fd-eq-thermoLinkTrailer     { --fd-eq-glyph: '\e914'; }
.fd-dot.fd-eq-tipperTrailer         { --fd-eq-glyph: '\e915'; }
.fd-dot.fd-eq-tractor               { --fd-eq-glyph: '\e916'; }
.fd-dot.fd-eq-truckElectrical       { --fd-eq-glyph: '\e917'; }
.fd-dot.fd-eq-truck                 { --fd-eq-glyph: '\e918'; }
.fd-dot.fd-eq-van                   { --fd-eq-glyph: '\e919'; }
.fd-dot.fd-eq-trike                 { --fd-eq-glyph: '\e91a'; }
.fd-dot.fd-eq-deliveryBike          { --fd-eq-glyph: '\e91b'; }

/* =============================================================
 * `.fd-dot--tacho` modifier — equipment row with a linked
 * TachoVehicle. Wrapper becomes a flat-top hex with the equipment
 * type icon centred inside; the reg-label card below the marker
 * keeps the standard `.fd-dot` styling so behaviour matches every
 * other equipment marker. Set by `EquipmentDataSource` when the
 * row's uuid is in `tachoLinkedEquipmentUuidsProvider`.
 * Pairs with `TachoUnitDataSource` skipping equipment-linked
 * vehicles so layers never paint two markers at the same fix.
 * ============================================================= */
/* Wrapper is 30×28 — the visible hex sits at the centre (22×20 via
 * `::before inset: 4px`), and the surrounding 4 px transparent ring
 * is the hover-hit-area. Without it the hover hit-area would be the
 * tight 22×20 hex bounds; hover scale (1.25x) momentarily moves the
 * painted bounds past the cursor, `:hover` flips off, scale snaps
 * back, cursor re-enters, → oscillating mouseenter/mouseleave loop.
 * The ring keeps the wrapper rect comfortably larger than the
 * scaled hex so the cursor stays inside.
 *
 * Anchor compensates: `Offset(15, 14)` is the centre of the 30×28
 * wrapper AND the centre of the 22×20 hex, so the marker stays glued
 * to its GPS fix when toggling the tacho mod. See
 * `equipment_map_object.dart::anchorPx`. */
.fd-dot.fd-dot--tacho {
  width: 30px;
  height: 28px;
  border: 0;
  /* Round the (transparent) wrapper so the online pulse — which is
   * painted via `box-shadow` on the wrapper — reads as a circle
   * around the hex instead of a rectangle. Wrapper is 30×28 so the
   * pulse is a near-circle ellipse; visually indistinguishable from
   * the regular disc marker's pulse in motion. */
  border-radius: 50%;
  background: transparent;
  box-shadow: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.35));
}

/* Hex pulse keyframe — same expansion as `fd-dot-pulse` but without
 * the static `0 1px 3px rgba(0,0,0,0.35)` shadow leg. The hex carries
 * its own drop shadow via `filter: drop-shadow` (hex-shaped), so the
 * base keyframe's rectangular dark shadow would clash with it. */
@keyframes fd-hex-pulse {
  0%   { box-shadow: 0 0 0 0 var(--fd-dot-color); }
  100% { box-shadow: 0 0 0 10px rgba(0, 0, 0, 0); }
}

/* Override the base `.fd-dot.is-online` animation for hex mode so the
 * pulse uses the hex-specific keyframe (circular ring, no rectangular
 * drop shadow). Higher specificity wins over the base rule. */
.fd-dot.fd-dot--tacho.is-online {
  animation: fd-hex-pulse 1.6s ease-out infinite;
}
/* ::before is the disc hover-shield in default mode; in tacho mode
 * it becomes the visible hex fill. `inset: 4px` shrinks it back to
 * 22×20 so the hex shape stays its production size while the
 * surrounding wrapper ring catches hover. */
.fd-dot.fd-dot--tacho::before {
  position: absolute;
  /* `inset: 4px` shrinks the box to the 22×20 hex bounds. The base
   * `.fd-dot::before` (hover shield) sets `width: 72px`, `height: 96px`,
   * `left: 50%`, `margin-left: -36px`, `bottom: 0` — those leak through
   * the cascade unless explicitly reset. Without these resets the
   * over-constrained box keeps its 72×96 dimensions and the clip-path
   * paints a giant hex stretching past the wrapper. */
  inset: 4px;
  top: 4px;
  left: 4px;
  width: auto;
  height: auto;
  margin: 0;
  background: var(--fd-dot-color);
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
  pointer-events: none;
}
/* The base `.fd-dot.is-selected` rule slams a white background + 3px
 * solid border + box-shadow on the wrapper via `!important`, which
 * would clobber the hex's transparent wrapper and stamp a circular
 * disc / rectangular shadow around it. Reassert transparency and
 * box-shadow:none so the hex shape stays clean; the
 * `transform: scale(1.4)` from the base selected rule still
 * applies and the hex's own `filter: drop-shadow` from the base
 * `.fd-dot.fd-dot--tacho` rule keeps providing the lift. */
.fd-dot.fd-dot--tacho.is-selected {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
}
/* Hover also gives the wrapper a rectangular box-shadow (default
 * disc rule, no !important needed since selector specificity wins).
 * Drop it — the hex's `filter: drop-shadow` is the right shape. */
.fd-dot.fd-dot--tacho:hover {
  box-shadow: none;
}
/* Selected-state border treatment — inverted palette like the
 * tacho hex marker uses: white fill, dot-color border + glyph. */
.fd-dot.fd-dot--tacho.is-selected::before {
  background: #fff;
  outline: 2px solid var(--fd-dot-color);
}
.fd-dot.fd-dot--tacho.is-selected .fd-dot__glyph {
  color: var(--fd-dot-color);
}

/* Centred type glyph. Hidden by default (regular discs don't need
 * it); revealed only inside `.fd-dot--tacho`. Glyph comes from the
 * shared `--fd-eq-glyph` variable set per type above. */
.fd-dot__glyph { display: none; }
.fd-dot.fd-dot--tacho .fd-dot__glyph {
  display: flex;
  position: absolute;
  inset: 0;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-family: 'EquipmentIcons';
  font-size: 11px;
  line-height: 1;
  pointer-events: none;
  z-index: 1;
}
.fd-dot.fd-dot--tacho .fd-dot__glyph::before {
  content: var(--fd-eq-glyph, '\e918');
}

/* Stick + reg-card alignment for tacho hex mode. Hex `::before` is
 * inset:4 within the 30×28 wrapper — visible hex top sits 4 px inside
 * the wrapper top. The base `.fd-dot::after` stick anchors to wrapper
 * top (`bottom: 100%`), so without an override there's a 4 px gap
 * between stick bottom and hex top. Shift the stick down 4 px so it
 * touches the hex top, then pull the reg card up by the same amount
 * so card-bottom = stick-top.
 *
 * No status pill in tacho mode (the wrapper html omits `.fd-dot__status`),
 * so suppress the hover lift that would otherwise stack two cards on
 * top of each other — there's only one card. */
.fd-dot.fd-dot--tacho::after {
  bottom: calc(100% - 4px);
}
.fd-dot.fd-dot--tacho.is-near .fd-dot__label,
.fd-dot.fd-dot--tacho:hover .fd-dot__label,
.fd-dot.fd-dot--tacho.is-selected .fd-dot__label {
  bottom: calc(100% + var(--fd-stick-height) - 4px) !important;
}

/* ============================================================
   WebMarkerPortal positioning (fork v2.17.0+22).
   Portals mount on `document.body` (or the browser top layer via
   Popover API). The plugin writes these CSS vars on the portal el
   every camera/resize frame:
     --fd-popup-left  · final clamped left edge,  viewport coords
     --fd-popup-top   · final clamped top  edge
   We just consume them with `position: fixed`.
   ============================================================ */

/* Popover API user-agent reset — when the portal is in the browser
   top layer via `showPopover()`, the [popover] element inherits a
   dotted black border, white background, and `inset:0` centering
   from UA styles. Strip them; visual chrome lives on the inner card. */
.fd-detail-portal,
.fd-portal-popover,
.fd-tacho-portal {
  border: 0;
  padding: 0;
  margin: 0;
  background: transparent;
  inset: auto;
  overflow: visible;
  color: inherit;
}

/* Detail-card portal — wraps `.fd-detail-card` on document.body.
   Mounted only while the marker is hovered (state-driven), so no
   `:hover` reveal needed — just paint at native size. */
.fd-detail-portal {
  position: fixed;
  left: var(--fd-popup-left);
  top: var(--fd-popup-top);
  width: 280px;
  pointer-events: auto;
  z-index: 99999;
}

/* Inside the portal the card lays out in normal flow — kill the
   absolute positioning + hidden-scale that the wrapper-embedded
   variant uses. `!important` overrides the rules higher up that
   target `.fd-detail-card` directly. */
.fd-detail-portal .fd-detail-card {
  position: static !important;
  transform: none !important;
  left: auto !important;
  bottom: auto !important;
  top: auto !important;
  right: auto !important;
}

/* Hide the wrapper's status pill while the portal is showing the
   detail card. Old rule keyed on `:hover` of the wrapper-embedded
   card; this one keys on the `is-hovered` class set by the data
   source / state. */
.fd-dot.fd-dot--detail.is-hovered .fd-dot__status { display: none !important; }

/* When the detail portal is open, the tail (`.fd-detail-card__tail`)
   renders a 14×14 disc that lands EXACTLY on top of the marker. The
   default `.fd-dot:hover` rule scales the original disc 1.25× — that
   would leave a thin ring of the original poking out from under the
   portal's disc. Neutralize the scale in detail-portal mode so the
   two discs overlap perfectly. Original disc remains visible
   underneath (its pulse / presence states keep working). */
.fd-dot.fd-dot--detail.is-hovered {
  transform: none !important;
}

/* ----------------------------------------------------------------
   Detail-card TAIL — visual bridge between the portal-mounted card
   and the original marker. Stick (12 px) drops from the card bottom
   to the marker disc's top edge; disc (14×14) lands EXACTLY on top
   of the existing marker so they merge into one shape. Without this,
   the portal floats disconnected above tiny markers.

   Geometry:
     portal_bottom  = wrapper_top - 12   (portal `offset: 12`)
     marker_top     = anchor_y - 7       (wrapper 14 px, anchor at 7,7)
     marker_bottom  = anchor_y + 7
     tail_height    = 26 px              (12 stick + 14 disc)
     tail.bottom    = -26 px             → tail_bottom = portal_bottom + 26
                                          = wrapper_top + 14
                                          = marker_bottom ✓
   ---------------------------------------------------------------- */
.fd-detail-card__tail {
  position: absolute;
  left: 50%;
  bottom: -26px;
  width: 14px;
  height: 26px;
  margin-left: -7px;
  pointer-events: none;
}
.fd-detail-card__tail::before {
  /* Stick — 2 px wide, 12 px tall, fills the portal offset gap. */
  content: '';
  position: absolute;
  left: 50%;
  top: 0;
  width: 2px;
  height: 12px;
  margin-left: -1px;
  background: var(--fd-tail-color, #94a3b8);
  border-radius: 1px;
}
.fd-detail-card__tail::after {
  /* Disc — same 14×14 size as `.fd-dot`, lands on the marker. */
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--fd-tail-color, #94a3b8);
  border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  box-sizing: border-box;
}

/* Tacho-mode portal — the hover detail card is shown over a hex
   marker (22×20) instead of the 14×14 disc. The default tail
   disc (`::after`) would lay a round overlay on top of the hex
   and visually erase the linkage shape on hover. Hide the disc;
   the underlying hex (with its drop-shadow + hover scale)
   remains the visual anchor, while the stick (`::before`) still
   bridges the portal to the marker so the popup doesn't feel
   detached. */
.fd-detail-portal.fd-detail-portal--tacho .fd-detail-card__tail::after {
  display: none;
}

/* Status palette — mirrors `.fd-dot.fd-dot-status-X`. Set on the
   PORTAL root by the data source / state so the tail (a descendant)
   inherits the right colour. */
.fd-detail-portal.fd-dot-status-readyToUse    { --fd-tail-color: #5CAF8B; }
.fd-detail-portal.fd-dot-status-needsService  { --fd-tail-color: #FF7A3A; }
.fd-detail-portal.fd-dot-status-notAvailable  { --fd-tail-color: #A1A6AC; }
.fd-detail-portal.fd-dot-status-atWorkshop    { --fd-tail-color: #0D436D; }
.fd-detail-portal.fd-dot-status-booked        { --fd-tail-color: #C62D89; }
.fd-detail-portal.fd-dot-status-urgentService { --fd-tail-color: #DF322D; }

/* Cluster-popover portal — wraps the `.fd-cluster-popover` element
   on document.body. Pills inside have inline `top:Npx; left:0px`
   from the radial layout; flatten them into a vertical flex column
   so the popup auto-sizes correctly for the plugin's measurement
   pass. */
.fd-portal-popover {
  position: fixed;
  left: var(--fd-popup-left);
  top: var(--fd-popup-top);
  pointer-events: auto;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.fd-portal-popover .fd-cluster-popover {
  position: static !important;
  width: auto !important;
  height: auto !important;
  opacity: 1 !important;
  display: flex;
  flex-direction: column;
  gap: 6px;
  pointer-events: auto;
}

/* Flatten the absolutely-positioned pills (inline `top:Npx; left:0px`)
   into normal flow. `top: auto` defeats the inline style without
   needing inline overrides. */
.fd-portal-popover .fd-cluster-pill {
  position: static !important;
  top: auto !important;
  left: auto !important;
  transform: scale(1) !important;
}

.fd-portal-popover .fd-cluster-pill:hover {
  transform: scale(1.06) !important;
}

/* ============================================================
   Header glyph for `.fd-detail-card__hdr-icon` — mirrors the
   per-type table for `.fd-dot__label::before` so the card's
   header circle paints the same EquipmentIcons glyph as the
   marker pill. Codepoints come from `EquipmentTypeIcon` enum.
   The card root must carry `fd-eq-{type}` (added by the caller).
   ============================================================ */
.fd-detail-card.fd-eq-truckFixedBox         .fd-detail-card__hdr-icon::before { content: '\e900'; }
.fd-detail-card.fd-eq-swapBodyRefrigerator  .fd-detail-card__hdr-icon::before { content: '\e901'; }
.fd-detail-card.fd-eq-bulkContainer         .fd-detail-card__hdr-icon::before { content: '\e902'; }
.fd-detail-card.fd-eq-containerChassis      .fd-detail-card__hdr-icon::before { content: '\e903'; }
.fd-detail-card.fd-eq-gasContainerTruckLift .fd-detail-card__hdr-icon::before { content: '\e904'; }
.fd-detail-card.fd-eq-liftContainer         .fd-detail-card__hdr-icon::before { content: '\e905'; }
.fd-detail-card.fd-eq-containerTruck        .fd-detail-card__hdr-icon::before { content: '\e906'; }
.fd-detail-card.fd-eq-curtainsider          .fd-detail-card__hdr-icon::before { content: '\e907'; }
.fd-detail-card.fd-eq-dolly                 .fd-detail-card__hdr-icon::before { content: '\e908'; }
.fd-detail-card.fd-eq-flatbed               .fd-detail-card__hdr-icon::before { content: '\e909'; }
.fd-detail-card.fd-eq-gasContainerTruck     .fd-detail-card__hdr-icon::before { content: '\e90a'; }
.fd-detail-card.fd-eq-gasTractor            .fd-detail-card__hdr-icon::before { content: '\e90b'; }
.fd-detail-card.fd-eq-linkTrailer           .fd-detail-card__hdr-icon::before { content: '\e90c'; }
.fd-detail-card.fd-eq-movingFloor           .fd-detail-card__hdr-icon::before { content: '\e90d'; }
.fd-detail-card.fd-eq-removableGooseneck    .fd-detail-card__hdr-icon::before { content: '\e90e'; }
.fd-detail-card.fd-eq-stretchRGN            .fd-detail-card__hdr-icon::before { content: '\e90f'; }
.fd-detail-card.fd-eq-swapBodySide          .fd-detail-card__hdr-icon::before { content: '\e910'; }
.fd-detail-card.fd-eq-swapBody              .fd-detail-card__hdr-icon::before { content: '\e911'; }
.fd-detail-card.fd-eq-tankTrailer           .fd-detail-card__hdr-icon::before { content: '\e912'; }
.fd-detail-card.fd-eq-thermoTrailer         .fd-detail-card__hdr-icon::before { content: '\e913'; }
.fd-detail-card.fd-eq-thermoLinkTrailer     .fd-detail-card__hdr-icon::before { content: '\e914'; }
.fd-detail-card.fd-eq-tipperTrailer         .fd-detail-card__hdr-icon::before { content: '\e915'; }
.fd-detail-card.fd-eq-tractor               .fd-detail-card__hdr-icon::before { content: '\e916'; }
.fd-detail-card.fd-eq-truckElectrical       .fd-detail-card__hdr-icon::before { content: '\e917'; }
.fd-detail-card.fd-eq-truck                 .fd-detail-card__hdr-icon::before { content: '\e918'; }
.fd-detail-card.fd-eq-van                   .fd-detail-card__hdr-icon::before { content: '\e919'; }
.fd-detail-card.fd-eq-trike                 .fd-detail-card__hdr-icon::before { content: '\e91a'; }
.fd-detail-card.fd-eq-deliveryBike          .fd-detail-card__hdr-icon::before { content: '\e91b'; }

/* ============================================================
   Equipment-history hover tooltip — small dark pill anchored above
   the hovered route segment showing its start datetime. Emitted by
   `EquipmentHistoryHoverTooltip` (AdvancedLocationMapObject with
   `customHtml`) from the equipment-history `MapContribution` when
   `MapPathHoverDetector` reports a hover.
   ============================================================ */
.fd-hover-tooltip {
  pointer-events: none !important;
  background: transparent !important;
  overflow: visible !important;
}
.fd-hover-tooltip > img { display: none !important; }
.fd-hover-tooltip .fd-hover-tooltip__text,
.fd-hover-tooltip__text {
  position: absolute !important;
  left: 50% !important;
  bottom: 0 !important;
  top: auto !important;
  right: auto !important;
  transform: translate(-50%, -100%) !important;
  display: inline-block !important;
  padding: 5px 9px !important;
  background: rgba(15, 23, 42, 0.94) !important;
  color: #ffffff !important;
  font: 700 12px/1.2 -apple-system, BlinkMacSystemFont, 'Segoe UI',
      Roboto, sans-serif !important;
  letter-spacing: 0.04em !important;
  border-radius: 6px !important;
  white-space: nowrap !important;
  box-shadow:
    0 0 0 1.5px #ffffff,
    0 3px 8px rgba(0, 0, 0, 0.45) !important;
  z-index: 950 !important;
  text-shadow: none !important;
}
/* ================================================================
 * Equipment history event marker — one per EquipmentEvent on the
 * per-day route. 28-px circular disc with a 10-px tail pointing
 * down at the route point. Four type modifiers (--enter / --leave /
 * --report / --alarm) drive the colour, mirroring
 * `EquipmentEventType.color` / `.textColor` in
 * packages/core/lib/model/equipment/event/equipment_event.dart.
 *
 * Anchor: bottom centre of the wrapper bounds (14, 34) — the pin
 * tip sits 6 px below the disc bottom. Dart wrapper element:
 *
 *   <div class="fd-event fd-event--alarm [is-selected]"
 *        style="position:absolute; left:-14px; top:-34px;
 *               --fd-anchor-x:14px; --fd-anchor-y:34px;">
 *     <span class="fd-event__icon">⚠</span>
 *   </div>
 *
 * `z-index: 0` on the wrapper establishes a local stacking context
 * so the `::after` tail (z-index: -1) stays behind the disc
 * without escaping into ancestor layers.
 * ================================================================ */
.fd-event {
  position: relative;
  z-index: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--fd-event-color, #4797D3);
  color: #fff;
  border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Scale around the pin tip — 6 px below the wrapper bottom — so
   * hover grow keeps the tip glued to the route point. */
  transform-origin: 50% calc(100% + 6px);
  transition: transform 120ms ease, box-shadow 120ms ease;
}

.fd-event > img { display: none !important; }

.fd-event::after {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 100%;
  width: 10px;
  height: 10px;
  background: var(--fd-event-color, #4797D3);
  border-right: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: translate(-50%, -50%) rotate(45deg);
}

/* Icon — inline-SVG path inside a span. Absolute-positioned so the
 * disc centre (14, 14) is the icon centre regardless of whether the
 * parent flex centring is doing its job (Flutter web's fork wraps
 * the marker in extra containers that occasionally throw off flex
 * alignment in the disc + tail composite). Strokes inherit white
 * via `currentColor` on the icon span. */
.fd-event__icon {
  position: absolute;
  left: 50%;
  top: 14px;                  /* disc centre (wrapper is 28×28) */
  transform: translate(-50%, -50%);
  width: 16px;
  height: 16px;
  color: #fff;
  pointer-events: none;
}
.fd-event__icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.fd-event:hover {
  transform: scale(1.15);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

/* Type palette — `--fd-event-color` is the disc/tail fill in the
 * default (unselected) state; `--fd-event-selected-color` swaps in
 * for icon + tail border under `.is-selected`. */
.fd-event--enter,
.fd-event--leave {
  --fd-event-color: #4797D3;          /* FigmaColors.blue200 */
  --fd-event-selected-color: #2671AB; /* FigmaColors.blue300 */
}
.fd-event--report {
  --fd-event-color: #C62D61;          /* FigmaColors.pink */
  --fd-event-selected-color: #C62D89; /* FigmaColors.purple100 */
}
.fd-event--alarm {
  --fd-event-color: #DF322D;          /* FigmaColors.red300 */
  --fd-event-selected-color: #A1201C; /* FigmaColors.red400 */
}
.fd-event--coupled,
.fd-event--decoupled {
  --fd-event-color: #8C2DC6;          /* FigmaColors.purple200 */
  --fd-event-selected-color: #5A1D80;
}
.fd-event--loaded,
.fd-event--unloaded {
  --fd-event-color: #FF7A3A;          /* FigmaColors.orange200 */
  --fd-event-selected-color: #C04F1A;
}

/* Selected — an amber ring (no grow, no bounce), the same selection
 * language as the routes-tab stop pin. Paints above neighbours. */
.fd-event.is-selected {
  z-index: 2;
  box-shadow:
    0 0 0 3px #f5a524,
    0 2px 6px rgba(0, 0, 0, 0.25);
}

/* Row-hover — the cursor is over this entry's row in the list/timeline
 * (class toggled by `equipmentHistoryHoveredEntryProvider`, not a
 * cursor-over-marker hover). Lift to the front + grow so hovering a row
 * lights up its pin. */
.fd-event.is-hovered {
  transform: scale(1.2);
  z-index: 1;
  box-shadow:
    0 6px 14px rgba(0, 0, 0, 0.3),
    0 2px 6px rgba(0, 0, 0, 0.22);
}

/* Selected AND row-hovered — keep the amber ring (it must not drop when
 * you point at the selected entry's row) on top of the hover lift.
 * Declared after `.is-hovered` so its box-shadow wins the cascade. */
.fd-event.is-selected.is-hovered {
  transform: scale(1.2);
  z-index: 3;
  box-shadow:
    0 0 0 3px #f5a524,
    0 6px 14px rgba(0, 0, 0, 0.3);
}

/* Selected — no `::after` to recolor now that the tail is gone;
 * leaving the rule here as a guard against regressions where a tail
 * pseudo gets added back accidentally. */

/* Hover label — small card above the disc revealed only while the
 * cursor is over the wrapper. Content per type:
 *   enter / leave → timestamp (e.g. "14:23")
 *   alarm         → alarm name
 *   report        → report type + status badge
 * Hidden by default with `opacity: 0` so it doesn't paint to the
 * GPU layer when no cursor is near; pure CSS reveal — no Dart-side
 * hover state needed at this stage. */
.fd-event__label {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* Default: single line. Only `.fd-event--alarm` opts into wrap
   * (see rule below) — enter/leave timestamps and report titles
   * are always short, so wrapping them just adds visual noise. */
  white-space: nowrap;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  padding: 5px 8px;
  border-radius: 6px;
  background: #fff;
  color: #1f2937;
  border: 1px solid rgba(15, 23, 42, 0.12);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease, transform 120ms ease;
}
.fd-event:hover .fd-event__label,
.fd-event.is-selected .fd-event__label {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Selected — label sticks even when the cursor leaves. Counter-scale
 * the wrapper's 1.3× so the label and its badge keep their resting
 * font-size; without this they enlarge alongside the disc and the
 * tooltip overhangs neighbouring markers. */
.fd-event.is-selected .fd-event__label {
  transform: translateX(-50%) translateY(0) scale(0.77);
  transform-origin: 50% 100%;
}

/* Alarm — the only event type whose text can run long. The wrapper
 * (`.fd-event`) is only 28-px wide, so an abs-positioned label's
 * shrink-to-fit collapses to `min-content` (longest word) and
 * `max-width: 500px` never engages. `width: max-content` forces
 * the label to size to its single-line width first; `max-width`
 * then caps that and triggers wrap for paragraph-length alerts. */
.fd-event--alarm .fd-event__label {
  display: inline-block;
  white-space: normal;
  width: max-content;
  max-width: 500px;
  line-height: 1.3;
  text-align: center;
}

/* Pill rendered next to the label text — only used by report events
 * for the report's "status". Picks up the marker's accent colour
 * (`--fd-event-color`, set by the type modifier) for the fill. */
.fd-event__badge {
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--fd-event-color, #4797D3);
  color: #fff;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}


/* ================================================================
 * Report marker — singleton flag pin contributed by the
 * equipment-reports list window. Same geometry as `.fd-event` so
 * the two share the same anchor and the same hover lift. Single
 * deep-purple palette matches the legacy `ReportMapObject`
 * (`PinMarkerIcon` with `pinColor: Colors.deepPurple`).
 * ================================================================ */
.fd-report {
  position: relative;
  z-index: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #673AB7;                /* Material deepPurple */
  color: #fff;
  border: 2px solid #fff;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  transform-origin: 50% calc(100% + 6px);
  transition: transform 120ms ease, box-shadow 120ms ease;
}

.fd-report > img { display: none !important; }

.fd-report::after {
  content: '';
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 100%;
  width: 10px;
  height: 10px;
  background: #673AB7;
  border-right: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: translate(-50%, -50%) rotate(45deg);
}

.fd-report__icon {
  position: absolute;
  left: 50%;
  top: 14px;                  /* disc centre (wrapper is 28×28) */
  transform: translate(-50%, -50%);
  width: 16px;
  height: 16px;
  color: #fff;
  pointer-events: none;
}
.fd-report__icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.fd-report:hover {
  transform: scale(1.15);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

.fd-report.is-selected {
  transform: scale(1.3);
  z-index: 2;
  box-shadow:
    0 8px 18px rgba(0, 0, 0, 0.35),
    0 2px 6px rgba(0, 0, 0, 0.25);
}
.fd-report.is-selected:hover {
  transform: scale(1.4);
}

/* Hover label for the report flag pin — same shape as
 * `.fd-event__label`. Default content is "<report type> <STATUS>";
 * the badge picks up the deep-purple accent so it reads as the same
 * marker family. */
.fd-report__label {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* Single line — report titles are always short (type + status
   * badge). Wrap behaviour is reserved for `.fd-event--alarm`. */
  white-space: nowrap;
  font-size: 11px;
  font-weight: 600;
  line-height: 1;
  padding: 5px 8px;
  border-radius: 6px;
  background: #fff;
  color: #1f2937;
  border: 1px solid rgba(15, 23, 42, 0.12);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease, transform 120ms ease;
}
.fd-report:hover .fd-report__label,
.fd-report.is-selected .fd-report__label {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Selected — counter-scale the label to neutralize the wrapper's
 * 1.3× transform (same rationale as .fd-event.is-selected). */
.fd-report.is-selected .fd-report__label {
  transform: translateX(-50%) translateY(0) scale(0.77);
  transform-origin: 50% 100%;
}
.fd-report__badge {
  padding: 2px 6px;
  border-radius: 999px;
  background: #673AB7;
  color: #fff;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* =============================================================
 * Tacho hex — combined vehicle+driver marker. Flat-top hexagon
 * with the EquipmentIcons truck glyph at the centre. Fill encodes
 * driver activity (TachoActivityType.defaultColor); reg label
 * sits below the hex.
 *
 * Selection is INVERTED:
 *   unselected → activity fill,  white border, white glyph
 *   selected   → white  fill,   activity border, activity glyph
 * Keeps the activity hue visible (now on the border + icon)
 * instead of swapping it out entirely — preserves identity while
 * making the selection unmistakable on a busy map.
 *
 * Hover reveals a popover above the hex with driver name, vehicle
 * reg, current activity + duration, and compliance summary. The
 * card is part of the same wrapper so cursor over either it or
 * the hex keeps the popover visible (matches the
 * `.fd-dot__label` / `.fd-yard__popover` reveal pattern).
 * ============================================================= */
.fd-tacho-hex {
  --fd-activity-color: #495A6B;
  --fd-activity-accent: #495A6B;
  position: relative;
  width: 40px;
  height: 36px;
  transition: transform 120ms ease, filter 120ms ease;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
  cursor: pointer;
}
.fd-tacho-hex > img { display: none !important; }

.fd-tacho-hex::before,
.fd-tacho-hex::after {
  content: '';
  position: absolute;
  /* Flat-top hexagon: top + bottom edges horizontal, points on
   * left/right. Six vertices on the inscribed circle. */
  clip-path: polygon(
    25%   0%,
    75%   0%,
    100% 50%,
    75% 100%,
    25% 100%,
     0% 50%
  );
}
.fd-tacho-hex::before {
  inset: 0;
  background: #fff;
}
.fd-tacho-hex::after {
  inset: 3px;
  background: var(--fd-activity-color);
}

/* Centred truck glyph from the EquipmentIcons font already
 * declared at the top of this file. `font-display: block` on the
 * @font-face entry keeps showcase from showing the U+E918
 * placeholder square before the TTF resolves. */
.fd-tacho-hex__glyph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-family: 'EquipmentIcons';
  font-size: 16px;
  font-weight: normal;
  z-index: 1;
  pointer-events: none;
}
.fd-tacho-hex__glyph::before { content: '\e918'; }

/* Tiny tier — `is-tiny` (zoom < `_kNearZoom`, mirrors `.fd-yard
 * .is-tiny`'s pattern). Shrinks the wrapper to 22×22, hides the
 * glyph + reg label so the hex reads as a tiny presence dot at
 * low zoom. Activity colour, selection inversion, hover portal
 * all keep working unchanged.
 *
 * Border inset shrinks from 3 px → 2 px so the coloured fill
 * doesn't get swallowed by the white outline at the smaller size.
 *
 * The wrapper drop-shadow is dropped too — at this size the
 * shadow doubles the visual weight of the marker. */
.fd-tacho-hex.is-tiny {
  /* Aspect 0.9 matches the base 40×36 wrapper so the hex stays a
   * flat-top hexagon when shrunk. 22×22 (aspect 1.0) squashes the
   * shape vertically and reads as a rounded square. */
  width: 22px;
  height: 20px;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.25));
}
.fd-tacho-hex.is-tiny::after {
  inset: 2px;
}
.fd-tacho-hex.is-tiny .fd-tacho-hex__glyph,
.fd-tacho-hex.is-tiny .fd-tacho-hex__label {
  display: none;
}
/* Hover scale stays modest at this size so the disc doesn't
 * trample neighbouring tiny markers in a dense cluster. */
.fd-tacho-hex.is-tiny:hover {
  transform: scale(1.18);
}
.fd-tacho-hex.is-tiny.is-selected:hover {
  transform: scale(1.25);
}

.fd-tacho-hex__label {
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 2px 6px;
  background: #fff;
  border-radius: 4px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  font-size: 11px;
  font-weight: 600;
  color: #1f2937;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
  pointer-events: none;
}

.fd-tacho-hex:hover {
  transform: scale(1.1);
  z-index: 2;
}

.fd-tacho-hex.is-selected {
  transform: scale(1.15);
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.45));
  z-index: 3;
}
.fd-tacho-hex.is-selected::before { background: var(--fd-activity-accent); }
.fd-tacho-hex.is-selected::after  { background: #fff; }
.fd-tacho-hex.is-selected .fd-tacho-hex__glyph {
  color: var(--fd-activity-accent);
}
.fd-tacho-hex.is-selected:hover { transform: scale(1.2); }

/* Activity palette — derived from TachoActivityType.defaultColor.
 * `*-color` drives the unselected fill; `*-accent` drives the
 * selected border + glyph tint. Where they differ (rest/available)
 * the accent is the next shade darker so the selected variant
 * holds enough contrast on a white background. */
.fd-tacho-hex.a-drive     { --fd-activity-color: #0D436D; --fd-activity-accent: #0D436D; }
.fd-tacho-hex.a-rest      { --fd-activity-color: #A1A6AC; --fd-activity-accent: #6D7986; }
.fd-tacho-hex.a-work      { --fd-activity-color: #8C2DC6; --fd-activity-accent: #8C2DC6; }
.fd-tacho-hex.a-available { --fd-activity-color: #FF7A3A; --fd-activity-accent: #C85017; }
.fd-tacho-hex.a-unknown   { --fd-activity-color: #A1A6AC; --fd-activity-accent: #6D7986; }

/* Hover popover — full driver + vehicle card. Inside the wrapper
 * so cursor over the card keeps it open. `.is-forced` mirrors the
 * `.cell.is-hover` showcase trick used by `.fd-dot`: it pins the
 * popover open without needing a cursor, for the "popover" demo
 * row that's meant to read at-a-glance. */
.fd-tacho-hex__popover {
  position: absolute;
  bottom: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%) translateY(6px);
  width: 240px;
  padding: 12px 14px;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms ease, transform 140ms ease;
  z-index: 20;
  text-align: left;
  font-size: 12px;
  color: #1f2937;
}
.fd-tacho-hex:hover .fd-tacho-hex__popover,
.fd-tacho-hex.is-forced .fd-tacho-hex__popover {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.fd-tacho-hex__popover::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -7px;
  border: 7px solid transparent;
  border-top-color: #fff;
  filter: drop-shadow(0 2px 1px rgba(0, 0, 0, 0.08));
}
.fd-tacho-hex__popover .pop-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
  margin-bottom: 8px;
  border-bottom: 1px solid #eef2f7;
}
.fd-tacho-hex__popover .pop-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--fd-activity-color);
  color: #fff;
  font-family: 'EquipmentIcons';
  font-size: 14px;
  flex: none;
}
.fd-tacho-hex__popover .pop-chip::before { content: '\e918'; }
.fd-tacho-hex__popover .pop-title {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.fd-tacho-hex__popover .pop-reg {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.fd-tacho-hex__popover .pop-driver {
  font-size: 11px;
  color: #6D7986;
}
.fd-tacho-hex__popover .pop-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 3px 0;
}
.fd-tacho-hex__popover .pop-row > span:first-child {
  color: #6D7986;
  font-size: 11px;
}
.fd-tacho-hex__popover .pop-row > span:last-child {
  font-size: 12px;
  font-weight: 500;
  text-align: right;
}
.fd-tacho-hex__popover .pop-activity {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  background: var(--fd-activity-color);
  text-transform: capitalize;
}

/* =============================================================
 * Tacho hex — portal popover.
 *
 * Live storybook + production use the WebMarkerPortal path so the
 * popover paints in the browser's top layer (popover API), above
 * the map and any other marker — never clipped by the map's
 * `overflow: hidden`. The portal container `.fd-tacho-portal`
 * inherits `--fd-activity-color` from a sibling `a-<activity>`
 * class on itself so the chip + activity pill match the hex.
 *
 * Card content is the same `.pop-*` markup the inline popover
 * uses; rules below mirror the inline ones so styling stays in
 * one place. Positioning of the portal element is handled by
 * the fork — no `position: absolute` here.
 * ============================================================= */
.fd-tacho-portal {
  /* Same positioning contract as `.fd-detail-portal`: the fork
   * resolves the marker → screen-space coords and writes them to
   * `--fd-popup-left` / `--fd-popup-top` on the portal element.
   * Without these rules the popover element falls back to the
   * popover-API default (top: 0; left: 0; inset: 0) and lands in
   * the top-left corner. */
  position: fixed;
  left: var(--fd-popup-left);
  top: var(--fd-popup-top);
  z-index: 99999;
  --fd-activity-color: #495A6B;
  --fd-activity-accent: #495A6B;
  box-sizing: border-box;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  color: #1f2937;
  font-size: 12px;
  pointer-events: auto;
}
.fd-tacho-portal.a-drive     { --fd-activity-color: #0D436D; --fd-activity-accent: #0D436D; }
.fd-tacho-portal.a-rest      { --fd-activity-color: #A1A6AC; --fd-activity-accent: #6D7986; }
.fd-tacho-portal.a-work      { --fd-activity-color: #8C2DC6; --fd-activity-accent: #8C2DC6; }
.fd-tacho-portal.a-available { --fd-activity-color: #FF7A3A; --fd-activity-accent: #C85017; }
.fd-tacho-portal.a-unknown   { --fd-activity-color: #A1A6AC; --fd-activity-accent: #6D7986; }

.fd-tacho-portal .fd-tacho-card {
  position: relative;
  width: 240px;
  padding: 12px 14px;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
  /* Activity-coloured frame ties the floating card back to the
   * marker hex underneath it. Thicker left bar reads as a status
   * stripe; the rest of the border keeps the same hue but at lower
   * weight so the card still feels white-dominant. */
  border: 1px solid var(--fd-activity-color);
  border-left-width: 4px;
}

/* Leader line — thin activity-coloured stem dropping from the
 * card's bottom-centre toward the anchor below. Pure visual cue
 * tying the floating popover to its marker; length is fixed and
 * approximates the portal `offset` (28 near / 18 tiny) so it
 * visually meets the hex top edge at both tiers. White outline
 * gives contrast against any map tile. */
.fd-tacho-portal .fd-tacho-card::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  width: 2px;
  height: 22px;
  margin-left: -1px;
  background: var(--fd-activity-color);
  border-radius: 1px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.95);
}
.fd-tacho-portal .pop-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 8px;
  margin-bottom: 8px;
  border-bottom: 1px solid #eef2f7;
}
.fd-tacho-portal .pop-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--fd-activity-color);
  color: #fff;
  font-family: 'EquipmentIcons';
  font-size: 14px;
  flex: none;
}
.fd-tacho-portal .pop-chip::before { content: '\e918'; }
.fd-tacho-portal .pop-title {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.fd-tacho-portal .pop-reg {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.fd-tacho-portal .pop-driver {
  font-size: 11px;
  color: #6D7986;
}
.fd-tacho-portal .pop-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 3px 0;
}
.fd-tacho-portal .pop-row > span:first-child {
  color: #6D7986;
  font-size: 11px;
}
.fd-tacho-portal .pop-row > span:last-child {
  font-size: 12px;
  font-weight: 500;
  text-align: right;
}
.fd-tacho-portal .pop-activity {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  background: var(--fd-activity-color);
  text-transform: capitalize;
}
