/* =========================================================================
   EmpoweredHouse Visuals — base
   The one shared layer: tokens, the frame, drawing primitives, motion.
   Every composition stylesheet builds on this file and on nothing else.

   No inline styles anywhere. The site CSP is `style-src 'self'`, so every
   modifier is a class and every data-driven number is an SVG attribute.
   ========================================================================= */

/* -------------------------------------------------------------------------
   Tokens. Each one reads the host page's token when it exists (the names in
   apps/empowered_landing_web/assets/css/app.css) and falls back to the brand
   value, so a composition looks right on a page that defines nothing.
   ------------------------------------------------------------------------- */
.ehv {
  --ehv-canvas: var(--canvas, #0b0b0c);
  --ehv-surface-1: var(--surface-1, #131316);
  --ehv-surface-2: var(--surface-2, #1a1a1e);
  --ehv-surface-3: var(--surface-3, #222226);

  --ehv-border-faint: var(--border-faint, rgba(255, 248, 232, 0.06));
  --ehv-border-soft: var(--border-soft, rgba(255, 248, 232, 0.1));
  --ehv-border-strong: var(--border-strong, rgba(255, 248, 232, 0.18));

  --ehv-ink: var(--text-primary, #f2efe6);
  --ehv-ink-2: var(--text-secondary, #a6a39a);
  --ehv-ink-3: var(--text-tertiary, #87837a);
  --ehv-ink-4: var(--text-muted, #4a4843);

  /* One accent. --ehv-lime draws lines and text, --ehv-lime-fill fills shapes. */
  --ehv-lime: var(--lime, #d0ff6d);
  --ehv-lime-fill: var(--lime, #d0ff6d);
  --ehv-lime-soft: var(--lime-soft, rgba(208, 255, 109, 0.14));
  --ehv-on-lime: #0b0b0c;
  --ehv-coral: var(--coral, #ff7a6b);
  --ehv-coral-soft: rgba(255, 122, 107, 0.14);
  --ehv-glow: var(--glow-warm, rgba(255, 226, 170, 0.22));

  --ehv-sans: var(--sans, "Albert Sans", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif);
  --ehv-mono: var(--mono, "JetBrains Mono", ui-monospace, Menlo, monospace);

  /* One curve. --ehv-step is the stagger between siblings. */
  --ehv-ease: var(--ease, cubic-bezier(0.2, 0.7, 0.2, 1));
  --ehv-dur: 700ms;
  --ehv-step: 90ms;
  --ehv-max-w: 420px;
}

/* The reversed surface: cream paper, near-black ink, lime-deep for lines. */
.ehv--light {
  --ehv-canvas: #f2efe6;
  --ehv-surface-1: #fbf9f3;
  --ehv-surface-2: #ebe7dc;
  --ehv-surface-3: #e2ddd0;
  --ehv-border-faint: rgba(11, 11, 12, 0.07);
  --ehv-border-soft: rgba(11, 11, 12, 0.13);
  --ehv-border-strong: rgba(11, 11, 12, 0.26);
  --ehv-ink: #0b0b0c;
  --ehv-ink-2: #4a4843;
  --ehv-ink-3: #6e6b63;
  --ehv-ink-4: #a6a39a;
  --ehv-lime: #5a8a1a;
  --ehv-lime-fill: #d0ff6d;
  --ehv-lime-soft: rgba(90, 138, 26, 0.14);
  --ehv-coral: #c8402f;
  --ehv-coral-soft: rgba(200, 64, 47, 0.12);
  --ehv-glow: rgba(255, 196, 110, 0.3);
}

/* -------------------------------------------------------------------------
   Frame
   ------------------------------------------------------------------------- */
.ehv {
  position: relative;
  isolation: isolate;
  display: block;
  width: 100%;
  height: 100%;
  min-height: 15rem;
  overflow: hidden;
  border-radius: inherit;
  color: var(--ehv-ink);
  font-family: var(--ehv-sans);
  -webkit-font-smoothing: antialiased;
}

.ehv__glow {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(52% 46% at 50% 46%, var(--ehv-glow), transparent 72%);
  opacity: 0.5;
}

/* The stage is pinned to the frame, so its one grid track has a definite
   size and the SVG can scale to fit both the width and the height. */
.ehv__stage {
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  display: grid;
  grid-template: minmax(0, 1fr) / minmax(0, 1fr);
  place-items: center;
  padding: clamp(16px, 6%, 36px);
}

.ehv__stage > svg {
  display: block;
  width: 100%;
  height: 100%;
  max-width: var(--ehv-max-w);
  overflow: visible;
}

.ehv--fade .ehv__stage {
  -webkit-mask-image: linear-gradient(to bottom, #000 58%, transparent 96%);
  mask-image: linear-gradient(to bottom, #000 58%, transparent 96%);
}

/* The plane of the platform stack on the homepage. */
.ehv--iso .ehv__stage > svg {
  transform: perspective(1600px) rotateX(54deg) rotateZ(-34deg) scale(var(--ehv-iso-scale, 0.94));
  transform-origin: 50% 50%;
}

/* -------------------------------------------------------------------------
   Drawing primitives. Colour comes from classes; geometry and font sizes are
   SVG attributes in the markup.
   ------------------------------------------------------------------------- */
.ehv svg text {
  font-family: var(--ehv-sans);
  font-weight: 400;
  letter-spacing: -0.012em;
  fill: var(--ehv-ink);
}

.ehv svg .ehv-t-strong { font-weight: 500; }
.ehv svg .ehv-t-display { font-weight: 500; letter-spacing: -0.035em; }
.ehv svg .ehv-t-2 { fill: var(--ehv-ink-2); }
.ehv svg .ehv-t-3 { fill: var(--ehv-ink-3); }
.ehv svg .ehv-t-4 { fill: var(--ehv-ink-4); }
.ehv svg .ehv-t-lime { fill: var(--ehv-lime); }
.ehv svg .ehv-t-coral { fill: var(--ehv-coral); }
.ehv svg .ehv-t-on-lime { fill: var(--ehv-on-lime); }

/* Mono records and eyebrows: uppercase in the markup, tracked out here. */
.ehv svg .ehv-mono {
  font-family: var(--ehv-mono);
  letter-spacing: 0.08em;
  fill: var(--ehv-ink-3);
}
.ehv svg .ehv-mono.ehv-t-2 { fill: var(--ehv-ink-2); }
.ehv svg .ehv-mono.ehv-t-4 { fill: var(--ehv-ink-4); }
.ehv svg .ehv-mono.ehv-t-ink { fill: var(--ehv-ink); }
.ehv svg .ehv-mono.ehv-t-lime { fill: var(--ehv-lime); }
.ehv svg .ehv-mono.ehv-t-coral { fill: var(--ehv-coral); }
.ehv svg .ehv-mono.ehv-t-on-lime { fill: var(--ehv-on-lime); }
.ehv svg .ehv-code { font-family: var(--ehv-mono); letter-spacing: 0; }

/* Surfaces: hairline borders, never drop shadows. */
.ehv .ehv-card { fill: var(--ehv-surface-1); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv .ehv-card-2 { fill: var(--ehv-surface-2); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv .ehv-card-3 { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv .ehv-well { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv .ehv-card-lime { fill: var(--ehv-surface-1); stroke: var(--ehv-lime); stroke-width: 1; }

.ehv .ehv-line { fill: none; stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv .ehv-line-soft { fill: none; stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv .ehv-line-faint { fill: none; stroke: var(--ehv-border-faint); stroke-width: 1; }
.ehv .ehv-line-ink { fill: none; stroke: var(--ehv-ink-2); stroke-width: 1.25; }
.ehv .ehv-line-lime { fill: none; stroke: var(--ehv-lime); stroke-width: 1.25; }
.ehv .ehv-line-coral { fill: none; stroke: var(--ehv-coral); stroke-width: 1.25; }
.ehv .ehv-dash { stroke-dasharray: 2 4; }
.ehv .ehv-round { stroke-linecap: round; stroke-linejoin: round; }

.ehv .ehv-fill-ink { fill: var(--ehv-ink); }
.ehv .ehv-fill-2 { fill: var(--ehv-ink-2); }
.ehv .ehv-fill-3 { fill: var(--ehv-ink-3); }
.ehv .ehv-fill-4 { fill: var(--ehv-ink-4); }
.ehv .ehv-fill-soft { fill: var(--ehv-border-soft); }
.ehv .ehv-fill-strong { fill: var(--ehv-border-strong); }
.ehv .ehv-fill-canvas { fill: var(--ehv-canvas); }
.ehv .ehv-fill-surface-2 { fill: var(--ehv-surface-2); }
.ehv .ehv-fill-surface-3 { fill: var(--ehv-surface-3); }
.ehv .ehv-fill-lime { fill: var(--ehv-lime-fill); }
.ehv .ehv-fill-lime-soft { fill: var(--ehv-lime-soft); }
.ehv .ehv-fill-coral { fill: var(--ehv-coral); }
.ehv .ehv-fill-coral-soft { fill: var(--ehv-coral-soft); }
.ehv .ehv-fill-none { fill: none; }

/* A node: canvas inside, ink ring. Used for graph points and step markers. */
.ehv .ehv-node { fill: var(--ehv-canvas); stroke: var(--ehv-ink); stroke-width: 1.25; }
.ehv .ehv-node-soft { fill: var(--ehv-canvas); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv .ehv-node-lime { fill: var(--ehv-canvas); stroke: var(--ehv-lime); stroke-width: 1.25; }

/* The mark. Same geometry as the site lockup. */
.ehv .ehv-mark { overflow: visible; }
.ehv .ehv-mark__frame { fill: none; stroke: var(--ehv-ink); stroke-width: 5; }
.ehv .ehv-mark__core { fill: var(--ehv-lime-fill); }

/* -------------------------------------------------------------------------
   Motion. Entrances animate *from* a hidden state *to* the natural one, so a
   composition without `animated` is simply its final frame.

   Put `ehv-a-*` on an element that has no `transform` attribute: a CSS
   transform replaces the attribute while it runs.
   ------------------------------------------------------------------------- */
@keyframes ehv-rise { from { opacity: 0; transform: translateY(10px); } }
@keyframes ehv-drop { from { opacity: 0; transform: translateY(-10px); } }
@keyframes ehv-slide { from { opacity: 0; transform: translateX(-12px); } }
@keyframes ehv-fade { from { opacity: 0; } }
@keyframes ehv-pop { from { opacity: 0; transform: scale(0.5); } }
@keyframes ehv-grow-y { from { transform: scaleY(0); } }
@keyframes ehv-grow-x { from { transform: scaleX(0); } }
@keyframes ehv-draw { from { stroke-dashoffset: 1; } }
@keyframes ehv-pulse { 50% { opacity: 0.3; } }
@keyframes ehv-ping {
  from { opacity: 0.7; transform: scale(1); }
  to { opacity: 0; transform: scale(2.6); }
}

.ehv :is(.ehv-a-rise, .ehv-a-drop, .ehv-a-slide, .ehv-a-pop, .ehv-a-grow-y, .ehv-a-grow-x, .ehv-a-ping, .ehv-h-lift) {
  transform-box: fill-box;
}
.ehv .ehv-a-pop,
.ehv .ehv-a-ping { transform-origin: center; }
.ehv .ehv-a-grow-y { transform-origin: bottom; }
.ehv .ehv-a-grow-x { transform-origin: left; }

/* A drawn line needs pathLength="1" in the markup. */
.ehv .ehv-a-draw { stroke-dasharray: 1 1; }

.ehv--animated :is(.ehv-a-rise, .ehv-a-drop, .ehv-a-slide, .ehv-a-fade, .ehv-a-pop, .ehv-a-grow-y, .ehv-a-grow-x, .ehv-a-draw) {
  animation-duration: var(--ehv-dur);
  animation-timing-function: var(--ehv-ease);
  animation-fill-mode: backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step));
}
.ehv--animated .ehv-a-rise { animation-name: ehv-rise; }
.ehv--animated .ehv-a-drop { animation-name: ehv-drop; }
.ehv--animated .ehv-a-slide { animation-name: ehv-slide; }
.ehv--animated .ehv-a-fade { animation-name: ehv-fade; }
.ehv--animated .ehv-a-pop { animation-name: ehv-pop; }
.ehv--animated .ehv-a-grow-y { animation-name: ehv-grow-y; }
.ehv--animated .ehv-a-grow-x { animation-name: ehv-grow-x; }
.ehv--animated .ehv-a-draw { animation-name: ehv-draw; animation-duration: calc(var(--ehv-dur) * 1.6); }

/* Loops: a live dot, a ring that pings out. They wait for the entrance. */
.ehv--animated .ehv-a-pulse {
  animation: ehv-pulse 2.4s ease-in-out infinite;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step) + var(--ehv-dur));
}
.ehv .ehv-a-ping { opacity: 0; }
.ehv--animated .ehv-a-ping {
  animation: ehv-ping 2.4s var(--ehv-ease) infinite;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step) + var(--ehv-dur));
}

/* Stagger index: ehv-i-0 … ehv-i-24. */
.ehv .ehv-i-0 { --ehv-i: 0; }
.ehv .ehv-i-1 { --ehv-i: 1; }
.ehv .ehv-i-2 { --ehv-i: 2; }
.ehv .ehv-i-3 { --ehv-i: 3; }
.ehv .ehv-i-4 { --ehv-i: 4; }
.ehv .ehv-i-5 { --ehv-i: 5; }
.ehv .ehv-i-6 { --ehv-i: 6; }
.ehv .ehv-i-7 { --ehv-i: 7; }
.ehv .ehv-i-8 { --ehv-i: 8; }
.ehv .ehv-i-9 { --ehv-i: 9; }
.ehv .ehv-i-10 { --ehv-i: 10; }
.ehv .ehv-i-11 { --ehv-i: 11; }
.ehv .ehv-i-12 { --ehv-i: 12; }
.ehv .ehv-i-13 { --ehv-i: 13; }
.ehv .ehv-i-14 { --ehv-i: 14; }
.ehv .ehv-i-15 { --ehv-i: 15; }
.ehv .ehv-i-16 { --ehv-i: 16; }
.ehv .ehv-i-17 { --ehv-i: 17; }
.ehv .ehv-i-18 { --ehv-i: 18; }
.ehv .ehv-i-19 { --ehv-i: 19; }
.ehv .ehv-i-20 { --ehv-i: 20; }
.ehv .ehv-i-21 { --ehv-i: 21; }
.ehv .ehv-i-22 { --ehv-i: 22; }
.ehv .ehv-i-23 { --ehv-i: 23; }
.ehv .ehv-i-24 { --ehv-i: 24; }

/* Hover: the main group lifts a few pixels. Compositions add their own. */
.ehv--hover .ehv-h-lift { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-h-lift { transform: translateY(-4px); }

/* -------------------------------------------------------------------------
   Triggers. assets/js/eh-visuals.js adds `ehv-js` to <html> and `is-inview`
   to a frame when it scrolls into view. Without the script nothing is held
   back: every animated composition plays on load.
   ------------------------------------------------------------------------- */
.ehv-js .ehv--animated:is([data-trigger="in-view"], [data-trigger="in-view-repeat"]):not(.is-inview) * {
  animation-play-state: paused !important;
}

.ehv.is-reset * {
  animation: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .ehv--animated * {
    animation: none !important;
  }
  .ehv .ehv-a-ping { opacity: 0; }
  .ehv .ehv-smil { display: none; }
  .ehv--hover .ehv-h-lift { transition: none; }
}

/* hero/agent-hub */
.ehv-hero-agent-hub { --ehv-max-w: 760px; --ehv-step: 110ms; --ehv-dur: 800ms; }

/* Hairlines stay one pixel wide on a face that lies in the ground plane. */
.ehv-hero-agent-hub__plane *:not(.ehv-mark__frame) { vector-effect: non-scaling-stroke; }

.ehv-hero-agent-hub__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}

.ehv-hero-agent-hub__base {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
}

.ehv-hero-agent-hub__core {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}

.ehv-hero-agent-hub__tile {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-hero-agent-hub__tile--on { stroke: var(--ehv-lime); }

.ehv--hover .ehv-hero-agent-hub__tile { transition: fill 200ms var(--ehv-ease), stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-hero-agent-hub__tile:hover { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); }

/* hero/platform-stack */
.ehv-hero-platform-stack { --ehv-max-w: 620px; --ehv-step: 150ms; --ehv-dur: 900ms; }
.ehv-hero-platform-stack .ehv__glow { background: radial-gradient(46% 40% at 50% 52%, var(--ehv-glow), transparent 72%); }

/* Hairlines stay one pixel wide in the skewed plane of a plate. */
.ehv-hero-platform-stack__plane * { vector-effect: non-scaling-stroke; }

.ehv-hero-platform-stack__plate {
  fill: var(--ehv-surface-1);
  fill-opacity: 0.92;
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-hero-platform-stack__plate--open { stroke-dasharray: 3 4; }
.ehv-hero-platform-stack__plate--on { stroke: var(--ehv-lime); stroke-dasharray: none; }

.ehv-hero-platform-stack__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}

.ehv-hero-platform-stack__tile {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-ink-3);
  stroke-width: 1;
}

.ehv-hero-platform-stack__edge { stroke-width: 1; }

.ehv--hover .ehv-hero-platform-stack__tile { transition: fill 200ms var(--ehv-ease), stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-hero-platform-stack__tile { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); }

/* hero/process-map */
.ehv-hero-process-map { --ehv-max-w: 760px; --ehv-step: 110ms; --ehv-iso-scale: 0.74; }

.ehv-hero-process-map__halo {
  fill: var(--ehv-lime-soft);
  stroke: none;
}

/* hero/security-gateway */
.ehv-hero-security-gateway { --ehv-max-w: 760px; --ehv-step: 110ms; --ehv-dur: 800ms; }

/* Hairlines stay one pixel wide on the ground and on the faces of the wall. */
.ehv-hero-security-gateway__plane * { vector-effect: non-scaling-stroke; }

.ehv-hero-security-gateway__wall {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
  stroke-linejoin: round;
}
.ehv-hero-security-gateway__top {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
  stroke-linejoin: round;
}
.ehv-hero-security-gateway__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}

/* A gate: the opening, the floor inside it and the inner side of the wall. */
.ehv-hero-security-gateway__gate {
  fill: var(--ehv-canvas);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-hero-security-gateway__gate--shut { fill: var(--ehv-surface-3); stroke: var(--ehv-coral); }
.ehv-hero-security-gateway__floor { fill: var(--ehv-surface-2); }
.ehv-hero-security-gateway__jamb { fill: var(--ehv-surface-3); }

.ehv-hero-security-gateway__packet { stroke-width: 1; }
.ehv-hero-security-gateway__packet--ink { fill: var(--ehv-surface-3); stroke: var(--ehv-ink-3); }
.ehv-hero-security-gateway__packet--lime { fill: var(--ehv-lime-fill); stroke: var(--ehv-lime); }
.ehv-hero-security-gateway__packet--coral { fill: var(--ehv-coral); stroke: var(--ehv-coral); }

.ehv-hero-security-gateway__tag { fill: var(--ehv-canvas); stroke: var(--ehv-coral); stroke-width: 1; }

.ehv--hover .ehv-hero-security-gateway__gate { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-hero-security-gateway__gate:not(.ehv-hero-security-gateway__gate--shut) { stroke: var(--ehv-lime); }

/* hero/software-factory */
.ehv-hero-software-factory { --ehv-max-w: 760px; --ehv-step: 110ms; --ehv-dur: 800ms; }

/* Hairlines stay one pixel wide on a face that lies in the ground plane. */
.ehv-hero-software-factory__plane * { vector-effect: non-scaling-stroke; }

.ehv-hero-software-factory__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}

.ehv-hero-software-factory__plate {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}

.ehv-hero-software-factory__block {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-ink-3);
  stroke-width: 1;
}

.ehv-hero-software-factory__app {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-lime);
  stroke-width: 1;
}

.ehv--hover .ehv-hero-software-factory__block { transition: fill 200ms var(--ehv-ease), stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-hero-software-factory__block { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); }

/* hero/workflow-automation */
.ehv-hero-workflow-automation { --ehv-max-w: 800px; --ehv-step: 100ms; --ehv-iso-scale: 0.74; }

/* The dotted grid of the canvas. */
.ehv-hero-workflow-automation__dot { fill: var(--ehv-border-soft); }

.ehv--hover .ehv-hero-workflow-automation__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-hero-workflow-automation__card:hover { stroke: var(--ehv-lime); }

/* process/approval */
.ehv-process-approval { --ehv-max-w: 360px; }

.ehv-process-approval__outcome--go { fill: var(--ehv-lime-fill); }
.ehv-process-approval__outcome--wait { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-process-approval__outcome--stop { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; }

.ehv svg .ehv-mono.ehv-process-approval__outcome-text--go { fill: var(--ehv-on-lime); }
.ehv svg .ehv-mono.ehv-process-approval__outcome-text--wait { fill: var(--ehv-ink-2); }
.ehv svg .ehv-mono.ehv-process-approval__outcome-text--stop { fill: var(--ehv-coral); }

/* process/flow */
.ehv-process-flow { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

/* process/stages */
.ehv-process-stages { --ehv-max-w: 560px; --ehv-step: 120ms; --ehv-iso-scale: 0.82; }

/* intelligence/ask */
.ehv-intelligence-ask { --ehv-max-w: 380px; --ehv-step: 110ms; }

.ehv-intelligence-ask__arrow { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1.5; }

@keyframes ehv-intelligence-ask-blink { 50% { opacity: 0; } }
.ehv--animated .ehv-intelligence-ask__caret { animation: ehv-intelligence-ask-blink 1.1s steps(1) infinite; }

/* intelligence/knowledge-graph */
.ehv-intelligence-knowledge-graph { --ehv-max-w: 440px; }

.ehv--hover .ehv-intelligence-knowledge-graph__node { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-intelligence-knowledge-graph__node:hover { stroke: var(--ehv-lime); }

/* intelligence/wiki-page */
.ehv-intelligence-wiki-page { --ehv-max-w: 380px; }

/* agents/handoff */
.ehv-agents-handoff { --ehv-max-w: 520px; --ehv-step: 140ms; --ehv-iso-scale: 0.82; }

/* agents/run */
.ehv-agents-run { --ehv-max-w: 360px; --ehv-step: 130ms; }

/* The spinner turns around the centre of its own track circle. */
@keyframes ehv-agents-run-spin { to { transform: rotate(360deg); } }

.ehv-agents-run__spin { transform-box: fill-box; transform-origin: center; }
.ehv--animated .ehv-agents-run__spin { animation: ehv-agents-run-spin 1.1s linear infinite; }

/* events/stream */
.ehv-events-stream { --ehv-max-w: 400px; --ehv-step: 110ms; }

/* apps/form */
.ehv-apps-form { --ehv-max-w: 340px; }

.ehv .ehv-apps-form__input--focus { stroke: var(--ehv-lime); }
.ehv-apps-form__tick { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1.5; }

@keyframes ehv-apps-form-blink { 50% { opacity: 0; } }
.ehv--animated .ehv-apps-form__caret { animation: ehv-apps-form-blink 1.1s steps(1) infinite; }

.ehv--hover .ehv-apps-form__submit { transition: fill 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-apps-form__submit { fill: var(--ehv-ink); }

/* apps/window */
.ehv-apps-window { --ehv-max-w: 500px; }

.ehv-apps-window__pill--ok { fill: var(--ehv-lime-soft); }
.ehv-apps-window__pill--wait { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-apps-window__pill--risk { fill: var(--ehv-coral-soft); }

.ehv svg .ehv-mono.ehv-apps-window__pill-text--ok { fill: var(--ehv-lime); }
.ehv svg .ehv-mono.ehv-apps-window__pill-text--wait { fill: var(--ehv-ink-2); }
.ehv svg .ehv-mono.ehv-apps-window__pill-text--risk { fill: var(--ehv-coral); }

/* activity/timeline */
.ehv-activity-timeline { --ehv-max-w: 360px; --ehv-step: 110ms; }

/* The state an event left is neutral, the state it reached is lime or coral. */
.ehv-activity-timeline__chip { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-activity-timeline__chip--ok { fill: var(--ehv-lime-soft); stroke: none; }
.ehv-activity-timeline__chip--risk { fill: var(--ehv-coral-soft); stroke: none; }

.ehv svg .ehv-mono.ehv-activity-timeline__state--ok { fill: var(--ehv-lime); }
.ehv svg .ehv-mono.ehv-activity-timeline__state--risk { fill: var(--ehv-coral); }

/* ai/model-picker */
.ehv-ai-model-picker { --ehv-max-w: 370px; --ehv-step: 110ms; }

.ehv-ai-model-picker__row { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-ai-model-picker__row--on { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); }

.ehv--hover .ehv-ai-model-picker__row { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-ai-model-picker__tier:hover .ehv-ai-model-picker__row { stroke: var(--ehv-border-strong); }
.ehv--hover .ehv-ai-model-picker__tier:hover .ehv-ai-model-picker__row--on { stroke: var(--ehv-lime); }

/* The radio dot and the meter of the chosen tier: the line lime, so they hold on cream. */
.ehv-ai-model-picker__on { fill: var(--ehv-lime); }

/* The caret is a glyph in the text, so it always sits right after the last word. */
.ehv svg .ehv-ai-model-picker__caret { fill: var(--ehv-lime); }

@keyframes ehv-ai-model-picker-blink { 50% { fill-opacity: 0; } }
.ehv--animated .ehv-ai-model-picker__caret { animation: ehv-ai-model-picker-blink 1.1s steps(1) infinite; }

/* ai/neural-net */
.ehv-ai-neural-net { --ehv-max-w: 470px; --ehv-step: 110ms; }

.ehv-ai-neural-net__node { fill: var(--ehv-surface-2); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-ai-neural-net__core { fill: var(--ehv-lime); }

.ehv--hover .ehv-ai-neural-net__node { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-ai-neural-net__node:hover { stroke: var(--ehv-lime); }

/* ai/presence */
.ehv-ai-presence { --ehv-max-w: 410px; --ehv-step: 100ms; }

.ehv-ai-presence__avatar { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-ai-presence__avatar--you { fill: var(--ehv-surface-1); stroke: var(--ehv-lime); stroke-width: 1.25; }

.ehv-ai-presence__selection { fill: var(--ehv-border-strong); }
.ehv-ai-presence__box--done { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-ai-presence__tick { fill: none; stroke: var(--ehv-ink-2); stroke-width: 1.25; }

.ehv-ai-presence__arrow { fill: var(--ehv-ink); stroke: var(--ehv-canvas); stroke-width: 1; stroke-linejoin: round; }
.ehv-ai-presence__arrow--you { fill: var(--ehv-lime-fill); stroke: var(--ehv-on-lime); }
.ehv-ai-presence__glyph { fill: var(--ehv-ink-2); }
.ehv-ai-presence__glyph--you { fill: var(--ehv-on-lime); }

/* The caret is a glyph in the line it types into, right after the last word. */
.ehv svg .ehv-ai-presence__caret { fill: var(--ehv-ink-2); }
.ehv svg .ehv-ai-presence__caret--you { fill: var(--ehv-lime); }

@keyframes ehv-ai-presence-blink { 50% { fill-opacity: 0; } }
.ehv--animated .ehv-ai-presence__caret { animation: ehv-ai-presence-blink 1.1s steps(1) infinite; }

/* Live cursors never sit still: each drifts a few pixels on its own phase. */
@keyframes ehv-ai-presence-drift {
  35% { transform: translate(5px, -3px); }
  70% { transform: translate(-3px, 3px); }
}
.ehv--animated .ehv-ai-presence__drift {
  animation: ehv-ai-presence-drift 6s ease-in-out infinite;
  animation-delay: calc(var(--ehv-i, 0) * -600ms);
}

.ehv--hover .ehv-ai-presence__cursor { transition: transform 300ms var(--ehv-ease); }
.ehv--hover:hover .ehv-ai-presence__cursor--you { transform: translate(8px, 5px); }

@media (prefers-reduced-motion: reduce) {
  .ehv--hover .ehv-ai-presence__cursor { transition: none; }
}

/* ai/prompt-box */
.ehv-ai-prompt-box { --ehv-max-w: 500px; --ehv-step: 110ms; }

.ehv-ai-prompt-box__arrow { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1.5; }

/* The caret is a glyph in the prompt, so it always sits right after the last word. */
.ehv svg .ehv-ai-prompt-box__caret { fill: var(--ehv-lime); }

@keyframes ehv-ai-prompt-box-blink { 50% { fill-opacity: 0; } }
.ehv--animated .ehv-ai-prompt-box__caret { animation: ehv-ai-prompt-box-blink 1.1s steps(1) infinite; }

.ehv-ai-prompt-box__send { transform-box: fill-box; transform-origin: center; }
.ehv--hover .ehv-ai-prompt-box__send { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-ai-prompt-box__send { transform: translateY(-3px); }

@media (prefers-reduced-motion: reduce) {
  .ehv--hover .ehv-ai-prompt-box__send { transition: none; }
}

/* ai/retrieval */
.ehv-ai-retrieval { --ehv-max-w: 560px; --ehv-iso-scale: 0.82; --ehv-step: 110ms; }

/* Packets, the query's outlet and the score bars of the lit sources. */
.ehv-ai-retrieval__lime { fill: var(--ehv-lime); }

.ehv--hover .ehv-ai-retrieval__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-ai-retrieval__source:hover .ehv-ai-retrieval__card { stroke: var(--ehv-lime); }

/* ai/thinking */
.ehv-ai-thinking { --ehv-max-w: 370px; --ehv-step: 150ms; }

.ehv-ai-thinking__tick { fill: none; stroke: var(--ehv-ink-2); stroke-width: 1.25; }
.ehv-ai-thinking__live { fill: var(--ehv-lime); }

/* ai/voice */
.ehv-ai-voice { --ehv-max-w: 350px; }

.ehv-ai-voice__bar {
  stroke: var(--ehv-ink-3);
  stroke-width: 2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
  transform-origin: center;
}
.ehv-ai-voice__bar--loud { stroke: var(--ehv-ink); }

/* Each bar breathes around its own middle, on a phase taken from ehv-i-N. */
@keyframes ehv-ai-voice-wave { 50% { transform: scale(0.4); } }
.ehv--animated .ehv-ai-voice__bar--live {
  animation: ehv-ai-voice-wave 1.3s ease-in-out infinite;
  animation-delay: calc(var(--ehv-i, 0) * -110ms);
}

/* Thinking: an arc goes round the ring. The hidden circle keeps the group's box centred on the orb. */
.ehv-ai-voice__arc { fill: none; stroke: var(--ehv-lime); stroke-width: 2; }
.ehv-ai-voice__spin { transform-box: fill-box; transform-origin: center; }

@keyframes ehv-ai-voice-spin { to { transform: rotate(360deg); } }
.ehv--animated .ehv-ai-voice__spin { animation: ehv-ai-voice-spin 1.6s linear infinite; }

.ehv-ai-voice__dot { fill: var(--ehv-lime); }

.ehv--hover .ehv-ai-voice__bar { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-ai-voice__bar--loud { stroke: var(--ehv-lime); }

/* ai/writer */
.ehv-ai-writer { --ehv-max-w: 410px; --ehv-step: 110ms; }

.ehv-ai-writer__spark { fill: var(--ehv-ink-2); }

/* The caret is a glyph in the ghost line, right after its last word. */
.ehv svg .ehv-ai-writer__caret { fill: var(--ehv-lime); }

@keyframes ehv-ai-writer-blink { 50% { fill-opacity: 0; } }
.ehv--animated .ehv-ai-writer__caret { animation: ehv-ai-writer-blink 1.1s steps(1) infinite; }

.ehv-ai-writer__accept { transform-box: fill-box; transform-origin: center; }
.ehv--hover .ehv-ai-writer__accept { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-ai-writer__accept { transform: translateY(-2px); }

@media (prefers-reduced-motion: reduce) {
  .ehv--hover .ehv-ai-writer__accept { transition: none; }
}

/* api/logs */
.ehv-api-logs { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; --ehv-step: 110ms; }

.ehv--hover .ehv-api-logs__chip { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-api-logs__chip:hover { stroke: var(--ehv-lime); }

/* api/rate-limit */
.ehv-api-rate-limit { --ehv-max-w: 440px; --ehv-step: 110ms; }
.ehv-api-rate-limit .ehv__glow { background: radial-gradient(46% 40% at 50% 56%, var(--ehv-glow), transparent 72%); }

.ehv-api-rate-limit__floor { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; stroke-linejoin: round; }
.ehv-api-rate-limit__face--left { fill: var(--ehv-surface-2); stroke: var(--ehv-border-strong); stroke-width: 1; stroke-linejoin: round; }
.ehv-api-rate-limit__face--right { fill: var(--ehv-surface-1); stroke: var(--ehv-border-strong); stroke-width: 1; stroke-linejoin: round; }
.ehv-api-rate-limit__top { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; stroke-linejoin: round; }
.ehv-api-rate-limit__top--lime { fill: var(--ehv-lime-fill); stroke: var(--ehv-lime); stroke-width: 1; stroke-linejoin: round; }

.ehv-api-rate-limit__in--coral { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1.25; stroke-linejoin: round; }
.ehv-api-rate-limit__in--lime { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-width: 1.25; stroke-linejoin: round; }

/* Cubes fall into their slot. The rejected one hits the pile and bounces back up. */
@keyframes ehv-api-rate-limit-fall { from { opacity: 0; transform: translateY(-48px); } }
@keyframes ehv-api-rate-limit-bounce {
  0% { opacity: 0; transform: translateY(-44px); }
  55% { opacity: 1; transform: translateY(40px); }
  100% { transform: translateY(0); }
}

.ehv-api-rate-limit__cube,
.ehv-api-rate-limit__incoming { transform-box: fill-box; }

.ehv--animated .ehv-api-rate-limit__cube,
.ehv--animated .ehv-api-rate-limit__incoming--bounce {
  animation-duration: var(--ehv-dur);
  animation-timing-function: var(--ehv-ease);
  animation-fill-mode: backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step));
}
.ehv--animated .ehv-api-rate-limit__cube { animation-name: ehv-api-rate-limit-fall; }
.ehv--animated .ehv-api-rate-limit__incoming--bounce {
  animation-name: ehv-api-rate-limit-bounce;
  animation-duration: calc(var(--ehv-dur) * 1.4);
}

.ehv--hover .ehv-api-rate-limit__incoming { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-api-rate-limit__incoming { transform: translateY(-8px); }

/* api/request */
.ehv-api-request { --ehv-max-w: 500px; --ehv-iso-scale: 0.82; --ehv-step: 110ms; }

/* The arrowhead takes the line colour, so it stays readable on the light surface. */
.ehv-api-request__tip { fill: var(--ehv-lime); }

/* api/webhook */
.ehv-api-webhook { --ehv-max-w: 410px; --ehv-step: 130ms; }

.ehv-api-webhook__outcome--go { fill: var(--ehv-lime-fill); }
.ehv-api-webhook__outcome--wait { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-api-webhook__outcome--stop { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; }

.ehv svg .ehv-mono.ehv-api-webhook__outcome-text--go { fill: var(--ehv-on-lime); }
.ehv svg .ehv-mono.ehv-api-webhook__outcome-text--wait { fill: var(--ehv-ink-2); }
.ehv svg .ehv-mono.ehv-api-webhook__outcome-text--stop { fill: var(--ehv-coral); }

/* avatars/grid */
.ehv-avatars-grid { --ehv-max-w: 370px; --ehv-step: 70ms; }

.ehv--hover .ehv-avatars-grid__avatar { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-avatars-grid__avatar:hover { stroke: var(--ehv-lime); }

/* avatars/profile-card */
.ehv-avatars-profile-card { --ehv-max-w: 350px; }

.ehv--hover .ehv-avatars-profile-card__avatar { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-avatars-profile-card__avatar { stroke: var(--ehv-lime); }

/* avatars/stack */
.ehv-avatars-stack { --ehv-max-w: 350px; }

/* The ring in the card's own colour that separates one avatar from the next. */
.ehv-avatars-stack__gap { fill: var(--ehv-surface-1); }

/* Hover fans the stack out: each avatar moves a little further than the last. */
.ehv--hover .ehv-avatars-stack__slot { transition: transform 260ms var(--ehv-ease); }
.ehv--hover:hover .ehv-avatars-stack__slot--0 { transform: translateX(0); }
.ehv--hover:hover .ehv-avatars-stack__slot--1 { transform: translateX(3px); }
.ehv--hover:hover .ehv-avatars-stack__slot--2 { transform: translateX(6px); }
.ehv--hover:hover .ehv-avatars-stack__slot--3 { transform: translateX(9px); }
.ehv--hover:hover .ehv-avatars-stack__slot--4 { transform: translateX(12px); }
.ehv--hover:hover .ehv-avatars-stack__slot--5 { transform: translateX(15px); }

/* brand/mark */
.ehv-brand-mark { --ehv-max-w: 400px; }

.ehv-brand-mark__word { letter-spacing: -0.02em; }

/* The outline draws itself, then the lime core lands and keeps breathing. */
@keyframes ehv-brand-mark-breathe { 50% { transform: scale(0.84); } }

.ehv-brand-mark .ehv-mark__core { transform-box: fill-box; transform-origin: center; }

.ehv--animated.ehv-brand-mark .ehv-mark__frame {
  stroke-dasharray: 1 1;
  animation: ehv-draw 1.1s var(--ehv-ease) backwards;
}
.ehv--animated.ehv-brand-mark .ehv-mark__core {
  animation:
    ehv-pop 500ms var(--ehv-ease) 700ms backwards,
    ehv-brand-mark-breathe 3.2s ease-in-out 1.6s infinite;
}

.ehv--hover.ehv-brand-mark .ehv-mark__core { transition: fill 200ms var(--ehv-ease); }
.ehv--hover.ehv-brand-mark:hover .ehv-mark__core { fill: var(--ehv-ink); }

/* brand/spotlight */
.ehv-brand-spotlight { --ehv-max-w: 440px; }

/* The glow sits over the icon, not in the middle of the frame. */
.ehv-brand-spotlight .ehv__glow {
  background: radial-gradient(40% 46% at 50% 34%, var(--ehv-glow), transparent 72%);
  opacity: 0.8;
}

.ehv-brand-spotlight__icon { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }

/* Plain tiles, fainter the further they are from the icon. */
.ehv-brand-spotlight__tile { fill: var(--ehv-surface-3); stroke: var(--ehv-ink-4); stroke-width: 1; }
.ehv-brand-spotlight__tile--0 { opacity: 1; }
.ehv-brand-spotlight__tile--1 { opacity: 0.78; }
.ehv-brand-spotlight__tile--2 { opacity: 0.52; }
.ehv-brand-spotlight__tile--3 { opacity: 0.3; }
.ehv-brand-spotlight__tile--4 { opacity: 0.15; }

/* The outline of the mark draws itself, then the lime core lands. */
.ehv--animated.ehv-brand-spotlight .ehv-mark__frame {
  stroke-dasharray: 1 1;
  animation: ehv-draw 1.1s var(--ehv-ease) 300ms backwards;
}
.ehv-brand-spotlight .ehv-mark__core { transform-box: fill-box; transform-origin: center; }
.ehv--animated.ehv-brand-spotlight .ehv-mark__core { animation: ehv-pop 500ms var(--ehv-ease) 1000ms backwards; }

.ehv--hover .ehv-brand-spotlight__tile { transition: opacity 200ms var(--ehv-ease), stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-brand-spotlight__tile:hover { opacity: 1; stroke: var(--ehv-ink-2); }

/* browser/loading */
.ehv-browser-loading { --ehv-max-w: 440px; }

/* The spinner in the address bar turns around the centre of its own track. */
@keyframes ehv-browser-loading-spin { to { transform: rotate(360deg); } }

.ehv-browser-loading__spin { transform-box: fill-box; transform-origin: center; }
.ehv--animated .ehv-browser-loading__spin { animation: ehv-browser-loading-spin 1.1s linear infinite; }

/* browser/simple */
.ehv-browser-simple { --ehv-max-w: 440px; }

/* On hover the one button of the page comes forward. */
.ehv-browser-simple__button { transform-box: fill-box; }
.ehv--hover .ehv-browser-simple__button { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-browser-simple__button { transform: translateY(-2px); }

/* browser/tabs */
.ehv-browser-tabs { --ehv-max-w: 460px; }

/* The active tab has the colour of the window, so it reads as one piece with
   the toolbar under it. */
.ehv .ehv-browser-tabs__active { fill: var(--ehv-surface-1); stroke: var(--ehv-border-soft); stroke-width: 1; }

/* A hit area, so a tab reacts to the pointer over its whole width. */
.ehv .ehv-browser-tabs__hit { fill: transparent; }

.ehv--hover .ehv-browser-tabs__title { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-browser-tabs__tab:hover .ehv-browser-tabs__title { fill: var(--ehv-ink); }

/* calendar/date-picker */
.ehv-calendar-date-picker { --ehv-max-w: 350px; --ehv-step: 70ms; }

.ehv--hover .ehv-calendar-date-picker__selected { transition: r 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-calendar-date-picker__selected { r: 15; }

/* calendar/event-list */
.ehv-calendar-event-list { --ehv-max-w: 370px; --ehv-step: 110ms; }

.ehv-calendar-event-list__row { fill: var(--ehv-surface-2); stroke: var(--ehv-border-faint); stroke-width: 1; }
.ehv-calendar-event-list__row--on { stroke: var(--ehv-border-strong); }

.ehv--hover .ehv-calendar-event-list__row { transition: stroke 200ms var(--ehv-ease), fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-calendar-event-list__row:hover { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); }

/* calendar/month-view */
.ehv-calendar-month-view { --ehv-max-w: 470px; --ehv-step: 70ms; }

.ehv svg .ehv-mono.ehv-calendar-month-view__today { fill: var(--ehv-canvas); }

.ehv-calendar-month-view__bar { stroke-linejoin: round; }
.ehv-calendar-month-view__bar--ink { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-calendar-month-view__bar--on { fill: var(--ehv-lime-fill); }
.ehv-calendar-month-view__bar--risk { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; }

.ehv svg .ehv-mono.ehv-calendar-month-view__name--ink { fill: var(--ehv-ink-2); letter-spacing: 0.04em; }
.ehv svg .ehv-mono.ehv-calendar-month-view__name--on { fill: var(--ehv-on-lime); letter-spacing: 0.04em; }
.ehv svg .ehv-mono.ehv-calendar-month-view__name--risk { fill: var(--ehv-coral); letter-spacing: 0.04em; }

.ehv--hover .ehv-calendar-month-view__bar--ink { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-calendar-month-view__bar--ink:hover { stroke: var(--ehv-ink-2); }

/* charts/bar */
.ehv-charts-bar { --ehv-max-w: 380px; --ehv-step: 60ms; }

.ehv-charts-bar__bar {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-charts-bar__bar--on { fill: var(--ehv-lime-fill); stroke: none; }

.ehv--hover .ehv-charts-bar__bar { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-charts-bar__bar:not(.ehv-charts-bar__bar--on):hover { fill: var(--ehv-ink-4); }

/* charts/block-stack */
.ehv-charts-block-stack { --ehv-max-w: 450px; --ehv-step: 70ms; --ehv-dur: 600ms; }
.ehv-charts-block-stack .ehv__glow { background: radial-gradient(46% 40% at 52% 56%, var(--ehv-glow), transparent 72%); }

/* Hairlines stay one pixel wide in the skewed plane of the plate. */
.ehv-charts-block-stack__plane * { vector-effect: non-scaling-stroke; }

.ehv-charts-block-stack__plate {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-charts-block-stack__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}

/* A block: the top is the lightest face, the right one the darkest. */
.ehv-charts-block-stack__top,
.ehv-charts-block-stack__left,
.ehv-charts-block-stack__right {
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
  stroke-linejoin: round;
}
.ehv-charts-block-stack__top { fill: var(--ehv-surface-3); }
.ehv-charts-block-stack__left { fill: var(--ehv-surface-2); }
.ehv-charts-block-stack__right { fill: var(--ehv-surface-1); }

.ehv-charts-block-stack__column--on :is(.ehv-charts-block-stack__top, .ehv-charts-block-stack__left, .ehv-charts-block-stack__right) {
  stroke: var(--ehv-on-lime);
  stroke-opacity: 0.55;
}
.ehv-charts-block-stack__column--on .ehv-charts-block-stack__top { fill: var(--ehv-lime-fill); }
.ehv-charts-block-stack__column--on .ehv-charts-block-stack__left { fill: color-mix(in srgb, var(--ehv-lime-fill) 76%, var(--ehv-on-lime)); }
.ehv-charts-block-stack__column--on .ehv-charts-block-stack__right { fill: color-mix(in srgb, var(--ehv-lime-fill) 54%, var(--ehv-on-lime)); }

.ehv--hover .ehv-charts-block-stack__column { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-charts-block-stack__column--on { transform: translateY(-5px); }

/* charts/donut */
.ehv-charts-donut { --ehv-max-w: 390px; --ehv-step: 110ms; }

/* Segments are strokes. The neutral ones step down in ink, one is lime. */
.ehv-charts-donut__seg { fill: none; stroke: var(--ehv-ink); stroke-width: 17; }
.ehv-charts-donut__seg--1 { stroke-opacity: 0.6; }
.ehv-charts-donut__seg--2 { stroke-opacity: 0.38; }
.ehv-charts-donut__seg--3 { stroke-opacity: 0.24; }
.ehv-charts-donut__seg--4 { stroke-opacity: 0.15; }
.ehv-charts-donut__seg--5 { stroke-opacity: 0.09; }
.ehv-charts-donut__seg--6 { stroke-opacity: 0.06; }
.ehv-charts-donut__seg--on { stroke: var(--ehv-lime-fill); }

.ehv-charts-donut__key { fill: var(--ehv-ink); }
.ehv-charts-donut__key--1 { fill-opacity: 0.6; }
.ehv-charts-donut__key--2 { fill-opacity: 0.38; }
.ehv-charts-donut__key--3 { fill-opacity: 0.24; }
.ehv-charts-donut__key--4 { fill-opacity: 0.15; }
.ehv-charts-donut__key--5 { fill-opacity: 0.09; }
.ehv-charts-donut__key--6 { fill-opacity: 0.06; }
.ehv-charts-donut__key--on { fill: var(--ehv-lime-fill); }

.ehv--hover .ehv-charts-donut__seg { transition: stroke-width 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-charts-donut__seg--on { stroke-width: 22; }

/* charts/funnel */
.ehv-charts-funnel { --ehv-max-w: 390px; --ehv-step: 110ms; }

.ehv-charts-funnel__slab {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
  stroke-linejoin: round;
}
.ehv-charts-funnel__slab--on { fill: var(--ehv-lime-fill); stroke: var(--ehv-lime-fill); }

.ehv--hover .ehv-charts-funnel__slab { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-charts-funnel__slab:not(.ehv-charts-funnel__slab--on):hover { fill: var(--ehv-ink-4); }

/* charts/gauge */
.ehv-charts-gauge { --ehv-max-w: 350px; }

.ehv-charts-gauge__track {
  fill: none;
  stroke: var(--ehv-border-soft);
  stroke-width: 12;
  stroke-linecap: round;
}
.ehv-charts-gauge__value {
  fill: none;
  stroke: var(--ehv-lime-fill);
  stroke-width: 12;
  stroke-linecap: round;
}
.ehv-charts-gauge__value--warn { stroke: var(--ehv-coral); }
.ehv-charts-gauge__zone { fill: none; stroke: var(--ehv-coral); stroke-width: 2; stroke-linecap: round; }
.ehv-charts-gauge__target { fill: none; stroke: var(--ehv-ink); stroke-width: 1.5; stroke-linecap: round; }

.ehv--hover .ehv-charts-gauge__value { transition: stroke-width 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-charts-gauge__value { stroke-width: 15; }

/* charts/line */
.ehv-charts-line { --ehv-max-w: 380px; }

.ehv-charts-line__area { fill: var(--ehv-ink); opacity: 0.05; }

.ehv--hover .ehv-charts-line__dot { transition: r 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-charts-line__dot { r: 5.5; }

/* charts/sparkline */
.ehv-charts-sparkline { --ehv-max-w: 340px; }

.ehv--hover .ehv-charts-sparkline__dot { transition: r 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-charts-sparkline__dot { r: 5; }

/* chat/bubbles */
.ehv-chat-bubbles { --ehv-max-w: 390px; --ehv-step: 130ms; }

.ehv-chat-bubbles__team { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-width: 1; stroke-opacity: 0.35; }

.ehv-chat-bubbles__dot { fill: var(--ehv-ink-3); transform-box: fill-box; transform-origin: center; }
.ehv-chat-bubbles__dot--team { fill: var(--ehv-lime); }

/* Typing: the three dots hop one after the other. */
@keyframes ehv-chat-bubbles-hop {
  0%, 60%, 100% { transform: translateY(0); opacity: 0.45; }
  30% { transform: translateY(-3px); opacity: 1; }
}
.ehv--animated .ehv-chat-bubbles__dot {
  animation: ehv-chat-bubbles-hop 1.2s ease-in-out infinite;
  animation-delay: calc(var(--ehv-i, 0) * 160ms);
}

/* chat/thread */
.ehv-chat-thread { --ehv-max-w: 390px; --ehv-step: 120ms; }

.ehv-chat-thread__core { fill: var(--ehv-ink-2); }

/* Reactions: a count pill with a tiny drawn glyph. Yours is the lime one. */
.ehv-chat-thread__pill { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-chat-thread__pill--mine { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); }
.ehv-chat-thread__glyph { fill: none; stroke: var(--ehv-ink-2); stroke-width: 1.25; }
.ehv-chat-thread__glyph--mine { stroke: var(--ehv-lime); }
.ehv-chat-thread__pupil { fill: var(--ehv-ink-2); }
.ehv-chat-thread__pupil--mine { fill: var(--ehv-lime); }

.ehv--hover .ehv-chat-thread__pill { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-chat-thread__reaction:hover .ehv-chat-thread__pill { stroke: var(--ehv-lime); }

/* code/editor */
.ehv-code-editor { --ehv-max-w: 460px; --ehv-step: 70ms; --ehv-dur: 400ms; }

.ehv-code-editor__current { fill: var(--ehv-surface-2); }

/* The caret takes the line colour, so it stays visible on the light surface. */
.ehv-code-editor__caret { fill: var(--ehv-lime); }

@keyframes ehv-code-editor-blink { 50% { opacity: 0; } }
.ehv--animated .ehv-code-editor__caret {
  animation: ehv-fade var(--ehv-dur) var(--ehv-ease) backwards, ehv-code-editor-blink 1.1s steps(1) infinite;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step)), calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step) + var(--ehv-dur));
}

/* code/snippet */
.ehv-code-snippet { --ehv-max-w: 410px; --ehv-step: 80ms; }

.ehv-code-snippet__button { fill: var(--ehv-canvas); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-code-snippet__button--copied { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); }

.ehv--hover .ehv-code-snippet__button { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-code-snippet__button { stroke: var(--ehv-lime); }

/* code/terminal */
.ehv-code-terminal { --ehv-max-w: 440px; --ehv-step: 170ms; --ehv-dur: 300ms; }

@keyframes ehv-code-terminal-blink { 50% { opacity: 0; } }
.ehv--animated .ehv-code-terminal__caret { animation: ehv-code-terminal-blink 1.1s steps(1) infinite; }

/* connections/converge */
.ehv-connections-converge { --ehv-max-w: 440px; }

.ehv--hover .ehv-connections-converge__chip { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-connections-converge__chip:hover { stroke: var(--ehv-lime); }

/* connections/flow */
.ehv-connections-flow { --ehv-max-w: 540px; --ehv-iso-scale: 0.82; }

.ehv--hover .ehv-connections-flow__node { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-connections-flow__node:hover { stroke: var(--ehv-lime); }

/* connections/hub */
.ehv-connections-hub { --ehv-max-w: 440px; }

.ehv--hover .ehv-connections-hub__chip { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-connections-hub__chip:hover { stroke: var(--ehv-lime); }

/* connections/layer-stack */
.ehv-connections-layer-stack { --ehv-max-w: 400px; --ehv-step: 110ms; }

/* Hairlines stay one pixel wide on the skewed top of a slab. */
.ehv-connections-layer-stack__plane * { vector-effect: non-scaling-stroke; }

.ehv-connections-layer-stack__slab {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-connections-layer-stack__slab--on { stroke: var(--ehv-lime); }

.ehv-connections-layer-stack__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}
.ehv-connections-layer-stack__side--on { stroke: var(--ehv-lime); }

.ehv--hover .ehv-connections-layer-stack__slab { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-connections-layer-stack__slab:hover { fill: var(--ehv-surface-3); }

/* connections/sync */
.ehv-connections-sync { --ehv-max-w: 500px; --ehv-iso-scale: 0.82; }

/* dashboard/widget-grid */
.ehv-dashboard-widget-grid { --ehv-max-w: 510px; --ehv-step: 80ms; }

.ehv-dashboard-widget-grid__tile {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
}

.ehv-dashboard-widget-grid__bar {
  fill: var(--ehv-surface-3);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}
.ehv-dashboard-widget-grid__bar--on { fill: var(--ehv-lime-fill); stroke: none; }

.ehv-dashboard-widget-grid__track { fill: none; stroke: var(--ehv-border-soft); stroke-width: 7; }
.ehv-dashboard-widget-grid__ring {
  fill: none;
  stroke: var(--ehv-lime-fill);
  stroke-width: 7;
  stroke-linecap: round;
}

.ehv--hover .ehv-dashboard-widget-grid__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-dashboard-widget-grid__widget:hover .ehv-dashboard-widget-grid__tile { stroke: var(--ehv-lime); }

/* The arrow in the badge is drawn in the line colour, so it holds on cream. */
.ehv-dashboard-widget-grid__up { fill: var(--ehv-lime); }

/* data/filters */
.ehv-data-filters { --ehv-max-w: 410px; --ehv-step: 110ms; }

.ehv--hover .ehv-data-filters__add { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-data-filters__add { stroke: var(--ehv-lime); }

/* data/import */
.ehv-data-import { --ehv-max-w: 460px; --ehv-iso-scale: 0.82; --ehv-step: 110ms; }

.ehv-data-import__cell--loose { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; stroke-dasharray: 2 3; }
.ehv-data-import__port--loose { fill: var(--ehv-canvas); stroke: var(--ehv-coral); stroke-width: 1.25; }

.ehv--hover .ehv-data-import__wire { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-data-import__wire { stroke: var(--ehv-ink); }

/* data/query */
.ehv-data-query { --ehv-max-w: 430px; --ehv-step: 110ms; }

.ehv-data-query__run { fill: var(--ehv-canvas); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-data-query__run--idle { fill: var(--ehv-lime-fill); stroke: none; }
.ehv-data-query__run--running { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); }
.ehv-data-query__run--done { fill: var(--ehv-canvas); }
.ehv-data-query__play { fill: var(--ehv-on-lime); }

/* The spinner turns around the centre of its own track circle. */
@keyframes ehv-data-query-spin { to { transform: rotate(360deg); } }

.ehv-data-query__spin { transform-box: fill-box; transform-origin: center; }
.ehv--animated .ehv-data-query__spin { animation: ehv-data-query-spin 1.1s linear infinite; }

.ehv--hover .ehv-data-query__run { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-data-query__run { stroke: var(--ehv-lime); }

/* devices/laptop */
.ehv-devices-laptop { --ehv-max-w: 480px; }

/* devices/phone */
.ehv-devices-phone { --ehv-max-w: 270px; }

/* On hover the approve button comes forward. */
.ehv-devices-phone__primary { transform-box: fill-box; }
.ehv--hover .ehv-devices-phone__primary { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-devices-phone__primary { transform: translateY(-2px); }

/* devices/tablet */
.ehv-devices-tablet { --ehv-max-w: 480px; }

/* A list row lights up under the pointer. */
.ehv .ehv-devices-tablet__row-bg { fill: transparent; }
.ehv--hover .ehv-devices-tablet__row-bg { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-devices-tablet__row:hover .ehv-devices-tablet__row-bg { fill: var(--ehv-surface-2); }

/* email/compose */
.ehv-email-compose { --ehv-max-w: 400px; }

/* The caret blinks on the line the writer is on. */
@keyframes ehv-email-compose-blink { 50% { opacity: 0; } }

.ehv--animated .ehv-email-compose__caret {
  animation: ehv-email-compose-blink 1.1s steps(1, end) infinite;
  animation-delay: 1.6s;
}

.ehv .ehv-email-compose__plane { fill: var(--ehv-on-lime); }

/* On hover the send button comes forward. */
.ehv-email-compose__send { transform-box: fill-box; }
.ehv--hover .ehv-email-compose__send { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-email-compose__send { transform: translateY(-2px); }

/* email/inbox */
.ehv-email-inbox { --ehv-max-w: 420px; }

.ehv svg .ehv-email-inbox__subject { fill: var(--ehv-ink); }

/* A row lights up under the pointer. */
.ehv .ehv-email-inbox__bg { fill: transparent; }
.ehv--hover .ehv-email-inbox__bg { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-email-inbox__row:hover .ehv-email-inbox__bg { fill: var(--ehv-surface-2); }

/* files/explorer */
.ehv-files-explorer { --ehv-max-w: 480px; }

/* A file row lights up under the pointer. */
.ehv .ehv-files-explorer__bg { fill: transparent; }
.ehv--hover .ehv-files-explorer__bg { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-files-explorer__row:hover .ehv-files-explorer__bg { fill: var(--ehv-surface-2); }

/* files/simple */
.ehv-files-simple { --ehv-max-w: 340px; }

/* On hover the page lifts off its well and the download arrow dips. */
.ehv-files-simple__page,
.ehv-files-simple__arrow { transform-box: fill-box; }
.ehv--hover :is(.ehv-files-simple__page, .ehv-files-simple__arrow) { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-files-simple__page { transform: translateY(-3px); }
.ehv--hover:hover .ehv-files-simple__arrow { transform: translateY(1.5px); }

/* files/stacked */
.ehv-files-stacked { --ehv-max-w: 400px; }

/* On hover the cards behind fan out a little further. */
.ehv-files-stacked__back { transform-box: fill-box; }
.ehv--hover .ehv-files-stacked__back { transition: transform 260ms var(--ehv-ease); }
.ehv--hover:hover .ehv-files-stacked__back--1 { transform: translate(5px, -5px); }
.ehv--hover:hover .ehv-files-stacked__back--2 { transform: translate(10px, -10px); }
.ehv--hover:hover .ehv-files-stacked__back--3 { transform: translate(15px, -15px); }

/* files/upload */
.ehv-files-upload { --ehv-max-w: 370px; }

.ehv .ehv-files-upload__zone {
  fill: var(--ehv-canvas);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
  stroke-dasharray: 5 5;
}

/* Lime is the finished file. A running upload is ink, a failed one coral. */
.ehv .ehv-files-upload__bar--done { fill: var(--ehv-lime-fill); }
.ehv .ehv-files-upload__bar--active { fill: var(--ehv-ink-2); }
.ehv .ehv-files-upload__bar--failed { fill: var(--ehv-coral); }

/* On hover the drop zone answers: the border turns lime, the arrow rises. */
.ehv-files-upload__arrow { transform-box: fill-box; }
.ehv--hover .ehv-files-upload__zone { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-files-upload__arrow { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-files-upload__zone { stroke: var(--ehv-lime); }
.ehv--hover:hover .ehv-files-upload__arrow { transform: translateY(-3px); }

/* geo/edge-network */
.ehv-geo-edge-network { --ehv-max-w: 640px; --ehv-iso-scale: 0.82; }

/* One path of zero-length strokes: the round caps are the dots. */
.ehv-geo-edge-network__dots {
  fill: none;
  stroke: var(--ehv-ink-3);
  stroke-width: 3.4;
  stroke-linecap: round;
  opacity: 0.62;
}

.ehv-geo-edge-network__edge { fill: var(--ehv-canvas); stroke: var(--ehv-ink-2); stroke-width: 1.25; }
.ehv-geo-edge-network__spoke { fill: none; stroke: var(--ehv-ink-3); stroke-width: 1; stroke-dasharray: 2 3; }
.ehv-geo-edge-network__route { fill: none; stroke: var(--ehv-lime); stroke-width: 1.75; }

.ehv--hover .ehv-geo-edge-network__edge { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-geo-edge-network__edge:hover { stroke: var(--ehv-lime); }

/* geo/geofence */
.ehv-geo-geofence { --ehv-max-w: 440px; }

.ehv-geo-geofence__street { fill: none; stroke-width: 1; }
.ehv-geo-geofence__street--minor { stroke: var(--ehv-border-soft); }
.ehv-geo-geofence__street--major { stroke: var(--ehv-border-strong); stroke-width: 2; }
.ehv-geo-geofence__block { fill: var(--ehv-border-faint); }

.ehv-geo-geofence__zone { fill: var(--ehv-lime-soft); }
.ehv-geo-geofence__alert { fill: var(--ehv-canvas); stroke: var(--ehv-coral); stroke-width: 1; }

.ehv--hover .ehv-geo-geofence__dot { transition: r 200ms var(--ehv-ease); }
.ehv--hover .ehv-geo-geofence__vehicle:hover .ehv-geo-geofence__dot { r: 5.5; }

/* geo/globe */
.ehv-geo-globe { --ehv-max-w: 420px; }

/* One path of zero-length strokes: the round caps are the dots. */
.ehv-geo-globe__dots {
  fill: none;
  stroke: var(--ehv-ink-3);
  stroke-width: 3;
  stroke-linecap: round;
  opacity: 0.8;
}
.ehv-geo-globe__dots--rim { stroke: var(--ehv-ink-4); stroke-width: 2.4; }

.ehv-geo-globe__arc { fill: none; stroke: var(--ehv-ink-2); stroke-width: 1.25; }

.ehv--hover .ehv-geo-globe__node { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-geo-globe__spot:hover .ehv-geo-globe__node { stroke: var(--ehv-lime); }

/* geo/pin-drop */
.ehv-geo-pin-drop { --ehv-max-w: 460px; }

/* Breaks a ring behind its distance label. */
.ehv-geo-pin-drop__gap { fill: var(--ehv-surface-1); }
.ehv-geo-pin-drop__wedge { fill: var(--ehv-border-faint); }

.ehv-geo-pin-drop__body { fill: var(--ehv-surface-3); stroke: var(--ehv-ink-2); stroke-width: 1.25; stroke-linejoin: round; }
.ehv-geo-pin-drop__body.ehv-geo-pin-drop--active { fill: var(--ehv-lime-fill); stroke: var(--ehv-lime); }
.ehv-geo-pin-drop__body.ehv-geo-pin-drop--far { fill: var(--ehv-surface-1); stroke: var(--ehv-ink-4); }

.ehv svg .ehv-mono.ehv-geo-pin-drop__number { fill: var(--ehv-ink); letter-spacing: 0; }
.ehv svg .ehv-mono.ehv-geo-pin-drop__number.ehv-geo-pin-drop--active { fill: var(--ehv-on-lime); }
.ehv svg .ehv-mono.ehv-geo-pin-drop__number.ehv-geo-pin-drop--far { fill: var(--ehv-ink-4); }

/* The sweep arm turns around the centre of the field: the group holds an
   unpainted circle of the field's size, so its box is centred there. */
@keyframes ehv-geo-pin-drop-sweep { to { transform: rotate(360deg); } }

.ehv-geo-pin-drop__sweep { transform-box: fill-box; transform-origin: center; }
.ehv--animated .ehv-geo-pin-drop__sweep { animation: ehv-geo-pin-drop-sweep 6s linear infinite; }

.ehv--hover .ehv-geo-pin-drop__pin { transition: transform 200ms var(--ehv-ease); }
.ehv--hover .ehv-geo-pin-drop__spot:hover .ehv-geo-pin-drop__pin { transform: translateY(-4px); }

@media (prefers-reduced-motion: reduce) {
  .ehv--hover .ehv-geo-pin-drop__pin { transition: none; }
}

/* geo/world-map */
.ehv-geo-world-map { --ehv-max-w: 640px; --ehv-iso-scale: 0.82; }

/* One path of zero-length strokes: the round caps are the dots. */
.ehv-geo-world-map__dots {
  fill: none;
  stroke: var(--ehv-ink-3);
  stroke-width: 3.4;
  opacity: 0.62;
  stroke-linecap: round;
}

.ehv-geo-world-map__ring { fill: none; stroke: var(--ehv-border-strong); stroke-width: 1; }

.ehv--hover .ehv-geo-world-map__ring { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-geo-world-map__spot:hover .ehv-geo-world-map__ring { stroke: var(--ehv-lime); }

/* git/branch-graph */
.ehv-git-branch-graph { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; --ehv-step: 120ms; }

/* git/diff */
.ehv-git-diff { --ehv-max-w: 460px; --ehv-step: 70ms; }

/* git/pull-request */
.ehv-git-pull-request { --ehv-max-w: 380px; --ehv-step: 150ms; }

.ehv-git-pull-request__merge { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-git-pull-request__merge--ready { fill: var(--ehv-lime-fill); stroke: none; }

/* The spinner turns around the centre of its own track circle. */
@keyframes ehv-git-pull-request-spin { to { transform: rotate(360deg); } }

.ehv-git-pull-request__spin { transform-box: fill-box; transform-origin: center; }
.ehv--animated .ehv-git-pull-request__spin { animation: ehv-git-pull-request-spin 1.1s linear infinite; }

.ehv--hover .ehv-git-pull-request__merge--ready { transition: fill-opacity 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-git-pull-request__merge--ready { fill-opacity: 0.86; }

/* images/carousel */
.ehv-images-carousel { --ehv-max-w: 400px; }

/* The edge of a neighbouring slide, open on the side that leaves the card. */
.ehv-images-carousel__peek { fill: var(--ehv-surface-2); stroke: var(--ehv-border-soft); stroke-width: 1; }

.ehv-images-carousel__chevron { pointer-events: none; }
.ehv-images-carousel__arrow--off { opacity: 0.35; }

.ehv--hover .ehv-images-carousel__arrow { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-images-carousel__arrow:hover { stroke: var(--ehv-lime); }
.ehv--hover .ehv-images-carousel__slide { transition: transform 260ms var(--ehv-ease); }
.ehv--hover:hover .ehv-images-carousel__slide { transform: translateX(-4px); }

/* images/gallery */
.ehv-images-gallery { --ehv-max-w: 400px; --ehv-step: 70ms; }

.ehv-images-gallery__tile--on { fill: var(--ehv-canvas); stroke: var(--ehv-lime); stroke-width: 1.5; }
.ehv-images-gallery__scene { pointer-events: none; }
.ehv-images-gallery__check { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1.5; }

.ehv--hover .ehv-images-gallery__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-images-gallery__tile:hover { stroke: var(--ehv-ink-2); }
.ehv--hover .ehv-images-gallery__tile--on:hover { stroke: var(--ehv-lime); }

/* The selection badge sits on the corner, cut out of the tile by a ring in the card's colour. */
.ehv-images-gallery__gap { fill: var(--ehv-surface-1); }

/* integrations/logo-marquee */
.ehv-integrations-logo-marquee { --ehv-max-w: 500px; --ehv-iso-scale: 0.82; }

/* The rows run past both edges of the picture and fade out there. The mask
   sits on the SVG itself, so it works without an id in the markup. */
.ehv-integrations-logo-marquee .ehv__stage > svg {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 17%, #000 83%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 17%, #000 83%, transparent);
}

/* A track is two cycles wide, so half its own width is one cycle. */
@keyframes ehv-integrations-logo-marquee-left { to { transform: translateX(-50%); } }
@keyframes ehv-integrations-logo-marquee-right { from { transform: translateX(-50%); } }

.ehv-integrations-logo-marquee__track { transform-box: fill-box; }
.ehv--animated .ehv-integrations-logo-marquee__track--left { animation: ehv-integrations-logo-marquee-left 54s linear infinite; }
.ehv--animated .ehv-integrations-logo-marquee__track--right { animation: ehv-integrations-logo-marquee-right 66s linear infinite; }

.ehv-integrations-logo-marquee__tile--on { stroke: var(--ehv-lime); }

.ehv--hover .ehv-integrations-logo-marquee__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-integrations-logo-marquee__tile:hover { stroke: var(--ehv-lime); }
.ehv--hover:hover .ehv-integrations-logo-marquee__track { animation-play-state: paused; }

/* integrations/logo-orbit */
.ehv-integrations-logo-orbit { --ehv-max-w: 380px; }

/* A ring turns around the middle of the viewBox. Each seat turns the other
   way around its own centre, so the tile on it stays upright. */
@keyframes ehv-integrations-logo-orbit-cw { to { transform: rotate(360deg); } }
@keyframes ehv-integrations-logo-orbit-ccw { to { transform: rotate(-360deg); } }

.ehv-integrations-logo-orbit__ring { transform-box: view-box; transform-origin: 50% 50%; }
.ehv-integrations-logo-orbit__seat { transform-box: fill-box; transform-origin: center; }

.ehv--animated .ehv-integrations-logo-orbit__ring--inner { animation: ehv-integrations-logo-orbit-cw 56s linear infinite; }
.ehv--animated .ehv-integrations-logo-orbit__ring--inner .ehv-integrations-logo-orbit__seat { animation: ehv-integrations-logo-orbit-ccw 56s linear infinite; }
.ehv--animated .ehv-integrations-logo-orbit__ring--outer { animation: ehv-integrations-logo-orbit-ccw 84s linear infinite; }
.ehv--animated .ehv-integrations-logo-orbit__ring--outer .ehv-integrations-logo-orbit__seat { animation: ehv-integrations-logo-orbit-cw 84s linear infinite; }

.ehv-integrations-logo-orbit__tile--on { stroke: var(--ehv-lime); }

.ehv--hover .ehv-integrations-logo-orbit__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-integrations-logo-orbit__tile:hover { stroke: var(--ehv-lime); }
.ehv--hover:hover :is(.ehv-integrations-logo-orbit__ring, .ehv-integrations-logo-orbit__seat) { animation-play-state: paused; }

/* integrations/logo-reel */
.ehv-integrations-logo-reel { --ehv-max-w: 460px; --ehv-iso-scale: 0.82; --ehv-reel-step: 2.6s; }

/* The row runs past both edges and fades out there. The mask sits on the SVG
   itself, so it works without an id in the markup. */
.ehv-integrations-logo-reel .ehv__stage > svg {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 24%, #000 76%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 24%, #000 76%, transparent);
}

.ehv-integrations-logo-reel__spot { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-width: 1.25; }
.ehv-integrations-logo-reel__glyph { stroke-width: 0.8; }

/* Only the name of the tile in the spotlight shows. */
.ehv-integrations-logo-reel__label { opacity: 0; }
.ehv-integrations-logo-reel__label--on { opacity: 1; }

/* The reel is two cycles wide: half its width is one cycle, taken a tile at
   a time. The slide inside moves one tile (92) at the end of every step. */
@keyframes ehv-integrations-logo-reel-jump { to { transform: translateX(-50%); } }
@keyframes ehv-integrations-logo-reel-slide {
  0%, 68% { transform: translateX(0); }
  100% { transform: translateX(-92px); }
}

.ehv-integrations-logo-reel__reel { transform-box: fill-box; }
.ehv--animated .ehv-integrations-logo-reel__reel { animation: ehv-integrations-logo-reel-jump linear infinite; }
.ehv--animated .ehv-integrations-logo-reel__reel--m7 { animation-duration: calc(7 * var(--ehv-reel-step)); animation-timing-function: steps(7); }
.ehv--animated .ehv-integrations-logo-reel__reel--m8 { animation-duration: calc(8 * var(--ehv-reel-step)); animation-timing-function: steps(8); }
.ehv--animated .ehv-integrations-logo-reel__reel--m9 { animation-duration: calc(9 * var(--ehv-reel-step)); animation-timing-function: steps(9); }
.ehv--animated .ehv-integrations-logo-reel__reel--m10 { animation-duration: calc(10 * var(--ehv-reel-step)); animation-timing-function: steps(10); }
.ehv--animated .ehv-integrations-logo-reel__reel--m12 { animation-duration: calc(12 * var(--ehv-reel-step)); animation-timing-function: steps(12); }
.ehv--animated .ehv-integrations-logo-reel__slide { animation: ehv-integrations-logo-reel-slide var(--ehv-reel-step) var(--ehv-ease) infinite; }

/* A name shows for one step out of n and leaves as the row starts to slide.
   Its stagger index is the step it belongs to, so a negative delay puts
   every name at its place in the loop. */
@keyframes ehv-integrations-logo-reel-show-1 { 0%, 100% { opacity: 1; } }
@keyframes ehv-integrations-logo-reel-show-2 { 0% { opacity: 0; } 4%, 34% { opacity: 1; } 40%, 100% { opacity: 0; } }
@keyframes ehv-integrations-logo-reel-show-3 { 0% { opacity: 0; } 3%, 22.7% { opacity: 1; } 26.7%, 100% { opacity: 0; } }
@keyframes ehv-integrations-logo-reel-show-4 { 0% { opacity: 0; } 2%, 17% { opacity: 1; } 20%, 100% { opacity: 0; } }
@keyframes ehv-integrations-logo-reel-show-5 { 0% { opacity: 0; } 2%, 13.6% { opacity: 1; } 16%, 100% { opacity: 0; } }
@keyframes ehv-integrations-logo-reel-show-6 { 0% { opacity: 0; } 1.5%, 11.3% { opacity: 1; } 13.3%, 100% { opacity: 0; } }
@keyframes ehv-integrations-logo-reel-show-7 { 0% { opacity: 0; } 1.3%, 9.7% { opacity: 1; } 11.4%, 100% { opacity: 0; } }
@keyframes ehv-integrations-logo-reel-show-8 { 0% { opacity: 0; } 1.1%, 8.5% { opacity: 1; } 10%, 100% { opacity: 0; } }

.ehv--animated .ehv-integrations-logo-reel__label {
  animation: linear infinite;
  animation-duration: calc(var(--ehv-reel-n) * var(--ehv-reel-step));
  animation-delay: calc((var(--ehv-i, 0) - var(--ehv-reel-n)) * var(--ehv-reel-step));
}
.ehv-integrations-logo-reel__labels--n1 { --ehv-reel-n: 1; }
.ehv-integrations-logo-reel__labels--n2 { --ehv-reel-n: 2; }
.ehv-integrations-logo-reel__labels--n3 { --ehv-reel-n: 3; }
.ehv-integrations-logo-reel__labels--n4 { --ehv-reel-n: 4; }
.ehv-integrations-logo-reel__labels--n5 { --ehv-reel-n: 5; }
.ehv-integrations-logo-reel__labels--n6 { --ehv-reel-n: 6; }
.ehv-integrations-logo-reel__labels--n7 { --ehv-reel-n: 7; }
.ehv-integrations-logo-reel__labels--n8 { --ehv-reel-n: 8; }
.ehv--animated .ehv-integrations-logo-reel__labels--n1 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-1; }
.ehv--animated .ehv-integrations-logo-reel__labels--n2 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-2; }
.ehv--animated .ehv-integrations-logo-reel__labels--n3 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-3; }
.ehv--animated .ehv-integrations-logo-reel__labels--n4 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-4; }
.ehv--animated .ehv-integrations-logo-reel__labels--n5 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-5; }
.ehv--animated .ehv-integrations-logo-reel__labels--n6 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-6; }
.ehv--animated .ehv-integrations-logo-reel__labels--n7 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-7; }
.ehv--animated .ehv-integrations-logo-reel__labels--n8 .ehv-integrations-logo-reel__label { animation-name: ehv-integrations-logo-reel-show-8; }

.ehv--hover:hover :is(.ehv-integrations-logo-reel__reel, .ehv-integrations-logo-reel__slide, .ehv-integrations-logo-reel__label) { animation-play-state: paused; }

/* integrations/plugin-slot */
.ehv-integrations-plugin-slot { --ehv-max-w: 540px; --ehv-step: 70ms; }
.ehv-integrations-plugin-slot .ehv__glow { background: radial-gradient(46% 40% at 50% 56%, var(--ehv-glow), transparent 72%); }

/* Hairlines stay one pixel wide in the skewed plane of the board. */
.ehv-integrations-plugin-slot__plane * { vector-effect: non-scaling-stroke; }

.ehv-integrations-plugin-slot__board { fill: var(--ehv-surface-1); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-integrations-plugin-slot__edge { fill: var(--ehv-surface-2); stroke: var(--ehv-border-soft); stroke-width: 1; stroke-linejoin: round; }

.ehv-integrations-plugin-slot__socket { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-integrations-plugin-slot__socket--open { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-dasharray: 3 3; }

/* A cube: the lid is the lightest face, the right side the darkest. */
.ehv-integrations-plugin-slot__lid { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-integrations-plugin-slot__side { fill: var(--ehv-surface-2); stroke: var(--ehv-border-strong); stroke-width: 1; stroke-linejoin: round; }
.ehv-integrations-plugin-slot__side--dark { fill: var(--ehv-surface-1); }
.ehv-integrations-plugin-slot__lid--new,
.ehv-integrations-plugin-slot__side--new { stroke: var(--ehv-lime); }

/* On the cream surface the tones run the other way. */
.ehv--light .ehv-integrations-plugin-slot__lid { fill: var(--ehv-surface-1); }
.ehv--light .ehv-integrations-plugin-slot__side--dark { fill: var(--ehv-surface-3); }

/* The new cube hovers 56 above its slot, drops in, sits, and starts over. */
@keyframes ehv-integrations-plugin-slot-drop {
  0%, 18% { transform: translateY(0); opacity: 1; }
  44%, 86% { transform: translateY(56px); opacity: 1; }
  92% { transform: translateY(56px); opacity: 0; }
  93% { transform: translateY(0); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}
@keyframes ehv-integrations-plugin-slot-guide {
  0%, 18% { opacity: 1; }
  42%, 93% { opacity: 0; }
  100% { opacity: 1; }
}

.ehv--animated .ehv-integrations-plugin-slot__incoming {
  animation: ehv-integrations-plugin-slot-drop 5.4s var(--ehv-ease) infinite;
  animation-delay: calc(var(--ehv-delay, 0ms) + 12 * var(--ehv-step) + var(--ehv-dur));
}
.ehv--animated .ehv-integrations-plugin-slot__guides {
  animation: ehv-integrations-plugin-slot-guide 5.4s var(--ehv-ease) infinite;
  animation-delay: calc(var(--ehv-delay, 0ms) + 12 * var(--ehv-step) + var(--ehv-dur));
}

.ehv--hover .ehv-integrations-plugin-slot__lid { transition: fill 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-integrations-plugin-slot__lid--new { fill: var(--ehv-lime-soft); }

/* keyboard/isometric-keys */
.ehv-keyboard-isometric-keys { --ehv-max-w: 560px; --ehv-step: 110ms; }

/* Hairlines stay one pixel wide in the skewed plane of a key top. */
.ehv-keyboard-isometric-keys__plane * { vector-effect: non-scaling-stroke; }

.ehv-keyboard-isometric-keys__deck { fill: var(--ehv-surface-1); stroke: var(--ehv-border-strong); stroke-width: 1; stroke-linejoin: round; }
.ehv-keyboard-isometric-keys__side { fill: var(--ehv-surface-2); stroke: var(--ehv-border-soft); stroke-width: 1; stroke-linejoin: round; }

.ehv-keyboard-isometric-keys__top { fill: var(--ehv-surface-3); stroke: var(--ehv-ink-3); stroke-width: 1; stroke-linejoin: round; }
.ehv-keyboard-isometric-keys__face { fill: var(--ehv-surface-2); stroke: var(--ehv-ink-3); stroke-width: 1; stroke-linejoin: round; }
.ehv-keyboard-isometric-keys__face--end { fill: var(--ehv-surface-1); }

/* A pressed key is one lime slab with dark edges; the long face is a shade darker. */
.ehv-keyboard-isometric-keys__top--on,
.ehv-keyboard-isometric-keys__face--on { fill: var(--ehv-lime-fill); stroke: var(--ehv-on-lime); stroke-width: 1; stroke-linejoin: round; }
.ehv-keyboard-isometric-keys__shade { fill: var(--ehv-on-lime); opacity: 0.22; }
.ehv-keyboard-isometric-keys__dish--on { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1; opacity: 0.35; }

/* The press: each pressed key first stands at full height (the ghost), then
   the ghost goes and the lime slab comes down. Still, the ghost is hidden. */
@keyframes ehv-keyboard-isometric-keys-release { from { opacity: 1; } }
@keyframes ehv-keyboard-isometric-keys-press { from { opacity: 0; transform: translateY(-18px); } }

.ehv-keyboard-isometric-keys__ghost { opacity: 0; }
.ehv--animated .ehv-keyboard-isometric-keys__ghost {
  animation: ehv-keyboard-isometric-keys-release 180ms linear backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step) + var(--ehv-dur) + 250ms);
}
.ehv--animated .ehv-keyboard-isometric-keys__pressed {
  animation: ehv-keyboard-isometric-keys-press 260ms var(--ehv-ease) backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step) + var(--ehv-dur) + 250ms);
}

/* Hover lets the pressed keys come up a little. */
.ehv--hover .ehv-keyboard-isometric-keys__pressed { transition: transform 220ms var(--ehv-ease); }
.ehv--hover:hover .ehv-keyboard-isometric-keys__pressed { transform: translateY(-5px); }

/* keyboard/shortcut */
.ehv-keyboard-shortcut { --ehv-max-w: 380px; --ehv-step: 110ms; }

/* A keycap is two rounded rectangles: the base, and the face a few units above it. */
.ehv-keyboard-shortcut__base { fill: var(--ehv-canvas); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-keyboard-shortcut__base--on { stroke: var(--ehv-lime); }
.ehv-keyboard-shortcut__face { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-keyboard-shortcut__face--on { fill: var(--ehv-lime-fill); stroke: var(--ehv-lime); }

/* Hover presses the keys that are still up. */
.ehv--hover .ehv-keyboard-shortcut__cap { transition: transform 160ms var(--ehv-ease); }
.ehv--hover:hover .ehv-keyboard-shortcut__cap { transform: translateY(3px); }
.ehv--hover:hover .ehv-keyboard-shortcut__cap--on { transform: none; }

/* media/audio-waveform */
.ehv-media-audio-waveform { --ehv-max-w: 400px; --ehv-step: 45ms; }

/* Bars grow out of the middle line. The played ones take the line lime, which
   stays readable on the cream surface. */
.ehv-media-audio-waveform__bar { fill: var(--ehv-ink-4); }
.ehv-media-audio-waveform__bar--played { fill: var(--ehv-lime); }
.ehv .ehv-media-audio-waveform__bar.ehv-a-grow-y { transform-origin: center; }

.ehv--hover .ehv-media-audio-waveform__play { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-media-audio-waveform__play { stroke: var(--ehv-lime); }

/* media/video-player */
.ehv-media-video-player { --ehv-max-w: 440px; }

.ehv-media-video-player__scene { fill: none; stroke: var(--ehv-ink-3); stroke-width: 1.25; }
.ehv-media-video-player__glyph { fill: var(--ehv-on-lime); }

.ehv-media-video-player__play { transform-box: fill-box; transform-origin: center; }
.ehv--hover .ehv-media-video-player__play { transition: transform 220ms var(--ehv-ease); }
.ehv--hover:hover .ehv-media-video-player__play { transform: scale(1.08); }
.ehv--hover .ehv-media-video-player__knob { transition: r 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-media-video-player__knob { r: 7; }

/* metrics/comparison */
.ehv-metrics-comparison { --ehv-max-w: 390px; }

.ehv-metrics-comparison__before { fill: var(--ehv-ink-4); }

.ehv-metrics-comparison__badge--good { fill: var(--ehv-lime-soft); }
.ehv-metrics-comparison__badge--bad { fill: var(--ehv-coral-soft); }
.ehv-metrics-comparison__badge--flat { fill: var(--ehv-surface-3); }

.ehv-metrics-comparison__arrow--good { fill: var(--ehv-lime); }
.ehv-metrics-comparison__arrow--bad { fill: var(--ehv-coral); }

.ehv svg .ehv-mono.ehv-metrics-comparison__delta--good { fill: var(--ehv-lime); }
.ehv svg .ehv-mono.ehv-metrics-comparison__delta--bad { fill: var(--ehv-coral); }
.ehv svg .ehv-mono.ehv-metrics-comparison__delta--flat { fill: var(--ehv-ink-2); }

/* metrics/goal */
.ehv-metrics-goal { --ehv-max-w: 360px; }

/* metrics/health-grid */
.ehv-metrics-health-grid { --ehv-max-w: 360px; --ehv-step: 45ms; --ehv-dur: 500ms; }

.ehv-metrics-health-grid__cell { stroke-width: 1; }
.ehv-metrics-health-grid__cell--3 { fill: var(--ehv-lime-fill); stroke: none; }
.ehv-metrics-health-grid__cell--2 { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-opacity: 0.35; }
.ehv-metrics-health-grid__cell--1 { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); }
.ehv-metrics-health-grid__cell--0 { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); }

.ehv--hover .ehv-metrics-health-grid__cell { transition: opacity 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-metrics-health-grid__cell:not(:hover) { opacity: 0.55; }

/* metrics/trend */
.ehv-metrics-trend { --ehv-max-w: 390px; }

.ehv-metrics-trend__line { stroke-width: 1.6; }

/* The period before: same scale, dashed and a tone back. */
.ehv-metrics-trend__previous {
  fill: none;
  stroke: var(--ehv-ink-3);
  stroke-width: 1.25;
  stroke-dasharray: 3 4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ehv--hover .ehv-metrics-trend__dot { transition: r 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-metrics-trend__dot { r: 5.5; }

/* The arrow in the badge is drawn in the line colour, so it holds on cream. */
.ehv-metrics-trend__up { fill: var(--ehv-lime); }

/* notifications/bell */
.ehv-notifications-bell { --ehv-max-w: 440px; --ehv-step: 110ms; }

.ehv-notifications-bell__icon { fill: none; stroke: var(--ehv-ink); stroke-width: 1.5; }

/* The badge sits on the corner of the tile, ringed in the canvas colour. */
.ehv-notifications-bell__badge { fill: var(--ehv-lime-fill); stroke: var(--ehv-canvas); stroke-width: 3; }

/* The bell swings from its top, then rests. */
@keyframes ehv-notifications-bell-ring {
  0%, 24%, 100% { transform: rotate(0deg); }
  4% { transform: rotate(-11deg); }
  9% { transform: rotate(9deg); }
  14% { transform: rotate(-6deg); }
  19% { transform: rotate(3deg); }
}

.ehv-notifications-bell__ring { transform-box: fill-box; transform-origin: 50% 0%; }
.ehv--animated .ehv-notifications-bell__ring {
  animation: ehv-notifications-bell-ring 3.6s ease-in-out infinite;
  animation-delay: var(--ehv-dur);
}

.ehv--hover .ehv-notifications-bell__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-notifications-bell__card { stroke: var(--ehv-lime); }

@media (prefers-reduced-motion: reduce) {
  .ehv--animated .ehv-notifications-bell__ring { animation: none; }
}

/* notifications/list */
.ehv-notifications-list { --ehv-max-w: 370px; --ehv-step: 110ms; }

/* A row has no surface of its own until it is hovered. */
.ehv-notifications-list__row { fill: var(--ehv-surface-2); opacity: 0; }
.ehv--hover .ehv-notifications-list__row { transition: opacity 200ms var(--ehv-ease); }
.ehv--hover .ehv-notifications-list__row:hover { opacity: 1; }

/* notifications/toast */
.ehv-notifications-toast { --ehv-max-w: 440px; }

/* The page behind is only an outline: it must not compete with the toast. */
.ehv-notifications-toast__page { fill: var(--ehv-surface-1); fill-opacity: 0.5; stroke: var(--ehv-border-soft); stroke-width: 1; }

.ehv-notifications-toast__card { fill: var(--ehv-surface-2); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-notifications-toast__card--risk { stroke: var(--ehv-coral); }
.ehv-notifications-toast__action { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); stroke-width: 1; }

/* The toast slides in from the side of the page it sits on. */
@keyframes ehv-notifications-toast-in-right { from { opacity: 0; transform: translateX(32px); } }
@keyframes ehv-notifications-toast-in-left { from { opacity: 0; transform: translateX(-32px); } }

.ehv--animated .ehv-notifications-toast__in {
  animation-duration: var(--ehv-dur);
  animation-timing-function: var(--ehv-ease);
  animation-fill-mode: backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step));
}
.ehv--animated .ehv-notifications-toast__in--right { animation-name: ehv-notifications-toast-in-right; }
.ehv--animated .ehv-notifications-toast__in--left { animation-name: ehv-notifications-toast-in-left; }

/* The time left before the toast leaves: the bar runs down from full to where it rests. */
@keyframes ehv-notifications-toast-timer { from { transform: scaleX(1.6667); } }

.ehv-notifications-toast__timer { transform-box: fill-box; transform-origin: left; }
.ehv--animated .ehv-notifications-toast__timer {
  animation: ehv-notifications-toast-timer 2.8s linear backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + 4 * var(--ehv-step) + var(--ehv-dur));
}

.ehv--hover .ehv-notifications-toast__action { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-notifications-toast__action { stroke: var(--ehv-ink-2); }

/* payments/checkout */
.ehv-payments-checkout { --ehv-max-w: 370px; }

.ehv-payments-checkout__pay-text { pointer-events: none; }
.ehv--hover .ehv-payments-checkout__pay { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-payments-checkout__pay:hover { fill: var(--ehv-ink); }

/* payments/credit-card */
.ehv-payments-credit-card { --ehv-max-w: 370px; }

.ehv-payments-credit-card__body { fill: var(--ehv-surface-2); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-payments-credit-card__chip { fill: var(--ehv-surface-3); stroke: var(--ehv-ink-3); stroke-width: 1; }

.ehv--hover .ehv-payments-credit-card__chip { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-payments-credit-card__chip { stroke: var(--ehv-lime); }

/* payments/usage-meter */
.ehv-payments-usage-meter { --ehv-max-w: 390px; }

/* search/command-palette */
.ehv-search-command-palette { --ehv-max-w: 420px; --ehv-step: 80ms; }

.ehv-search-command-palette__icon { stroke-width: 1.1; }

/* The caret is a character of the query, so it always follows the text. */
@keyframes ehv-search-command-palette-blink { 50% { opacity: 0; } }

.ehv svg .ehv-search-command-palette__caret { font-weight: 400; }
.ehv--animated .ehv-search-command-palette__caret {
  animation: ehv-search-command-palette-blink 1.1s steps(1) infinite;
}

@media (prefers-reduced-motion: reduce) {
  .ehv--animated .ehv-search-command-palette__caret { animation: none; }
}

/* search/results */
.ehv-search-results { --ehv-max-w: 420px; --ehv-step: 90ms; }

.ehv-search-results__chip { fill: none; stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-search-results__chip--on { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); }

/* A match: SVG paints an underline with the fill of the element that asks
   for it, so the outer span is lime and the word inside it keeps the ink. */
.ehv svg .ehv-search-results__hit {
  fill: var(--ehv-lime);
  text-decoration: underline;
  text-decoration-thickness: 1.25px;
  text-underline-offset: 2.5px;
}
.ehv svg .ehv-search-results__word { fill: var(--ehv-ink); }

/* A result has no surface of its own until it is hovered. */
.ehv-search-results__row { fill: var(--ehv-surface-2); opacity: 0; }
.ehv--hover .ehv-search-results__row { transition: opacity 200ms var(--ehv-ease); }
.ehv--hover .ehv-search-results__row:hover { opacity: 1; }

/* search/semantic */
.ehv-search-semantic { --ehv-max-w: 440px; --ehv-step: 80ms; }

.ehv-search-semantic__radius { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-width: 1; stroke-dasharray: 3 4; }
.ehv-search-semantic__tie { fill: none; stroke: var(--ehv-lime); stroke-width: 1; stroke-opacity: 0.45; }

/* A neighbour starts as any other dot and lights up once the radius reaches it. */
@keyframes ehv-search-semantic-light { from { fill: var(--ehv-ink-4); } }

.ehv-search-semantic__near { fill: var(--ehv-lime); stroke: var(--ehv-canvas); stroke-width: 1; }
.ehv--animated .ehv-search-semantic__near {
  animation: ehv-search-semantic-light 500ms var(--ehv-ease) backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + var(--ehv-i, 0) * var(--ehv-step));
}

.ehv--hover .ehv-search-semantic__radius {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 300ms var(--ehv-ease);
}
.ehv--hover:hover .ehv-search-semantic__radius { transform: scale(1.08); }

/* sections/auth */
.ehv-sections-auth { --ehv-max-w: 540px; --ehv-iso-scale: 0.82; }

/* The field being typed in. */
.ehv .ehv-sections-auth__field--focus { stroke: var(--ehv-ink-3); }

.ehv--hover .ehv-sections-auth__sso { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-auth__sso:hover { stroke: var(--ehv-ink-2); }
.ehv--hover .ehv-sections-auth__submit { transition: opacity 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-auth__submit:hover { opacity: 0.86; }

/* sections/backgrounds */
.ehv-sections-backgrounds { --ehv-max-w: 500px; --ehv-step: 60ms; --ehv-iso-scale: 0.82; }

/* One step of the warm glow. Fourteen of them stack up towards the middle. */
.ehv-sections-backgrounds__glow { fill: var(--ehv-glow); opacity: 0.065; }

/* The pattern thins out behind the heading: flat ellipses in the colour of
   the section, stacked the same way. */
.ehv-sections-backgrounds__clearing { fill: var(--ehv-canvas); opacity: 0.22; }

/* The first button is ink on the section, with the text reversed. */
.ehv svg .ehv-sections-backgrounds__action-text { fill: var(--ehv-canvas); }

.ehv--hover .ehv-sections-backgrounds__action { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-backgrounds__action:hover { fill: var(--ehv-lime-fill); }

/* sections/bento */
.ehv-sections-bento { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv-sections-bento__avatar { fill: var(--ehv-surface-3); stroke: var(--ehv-surface-1); stroke-width: 2; }
.ehv-sections-bento__track { fill: none; stroke: var(--ehv-border-soft); stroke-width: 4; }
.ehv-sections-bento__arc { fill: none; stroke: var(--ehv-ink-2); stroke-width: 4; stroke-linecap: round; }

.ehv--hover .ehv-sections-bento__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-bento__tile:hover { stroke: var(--ehv-ink-3); }

/* sections/blog */
.ehv-sections-blog { --ehv-max-w: 440px; }

.ehv--hover .ehv-sections-blog__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-blog__post:hover .ehv-sections-blog__card { stroke: var(--ehv-lime); }

.ehv--hover .ehv-sections-blog__arrow { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-blog__arrow { transform: translateX(2px); }

/* sections/blog-post */
.ehv-sections-blog-post { --ehv-max-w: 440px; }

/* The rule beside the pull quote is a line, so it takes the line lime. */
.ehv .ehv-sections-blog-post__bar { fill: var(--ehv-lime); }

/* sections/comments */
.ehv-sections-comments { --ehv-max-w: 440px; }

.ehv-sections-comments__chevron { transform-box: fill-box; }
.ehv--hover .ehv-sections-comments__chevron { transition: transform 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-comments__row:hover .ehv-sections-comments__chevron { transform: translateY(-2px); }

/* sections/components */
.ehv-sections-components { --ehv-max-w: 440px; }

.ehv .ehv-sections-components__field--on { stroke: var(--ehv-lime); }
.ehv-sections-components__knob { transform-box: fill-box; }
.ehv-sections-components__knob--on { fill: var(--ehv-on-lime); }
.ehv-sections-components__tick { fill: none; stroke: var(--ehv-canvas); stroke-width: 1.5; }
.ehv-sections-components__tick--on { stroke: var(--ehv-on-lime); }

/* The caret in the input is the one live thing. */
@keyframes ehv-sections-components-blink { 50% { opacity: 0; } }
.ehv--animated .ehv-sections-components__caret {
  animation: ehv-sections-components-blink 1.1s steps(1) infinite;
}

.ehv--hover .ehv-sections-components__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-components__item:hover .ehv-sections-components__tile {
  stroke: var(--ehv-lime);
}

/* sections/cta */
.ehv-sections-cta { --ehv-max-w: 440px; }

.ehv-sections-cta__arrow {
  fill: none;
  stroke: var(--ehv-on-lime);
  stroke-width: 1.25;
  transform-box: fill-box;
}

.ehv--hover .ehv-sections-cta__arrow { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-cta__arrow { transform: translateX(3px); }

/* sections/faq */
.ehv-sections-faq { --ehv-max-w: 440px; }

/* A closed row has no surface, only something for the pointer to land on. */
.ehv-sections-faq__hit { fill: transparent; }

.ehv--hover .ehv-sections-faq__icon { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-faq__row:hover .ehv-sections-faq__icon { stroke: var(--ehv-lime); }

/* sections/features */
.ehv-sections-features { --ehv-max-w: 440px; }

.ehv-sections-features__tile { stroke-width: 1; }

.ehv--hover .ehv-sections-features__tile { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-features__cell:hover .ehv-sections-features__tile {
  stroke: var(--ehv-lime);
}

/* sections/footers */
.ehv-sections-footers { --ehv-max-w: 440px; }

.ehv--hover .ehv-sections-footers__link { transition: fill 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-footers__link:hover { fill: var(--ehv-ink); }

/* sections/headers */
.ehv-sections-headers { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv-sections-headers__word { letter-spacing: -0.02em; }
.ehv-sections-headers__arrow { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1.25; }

.ehv--hover .ehv-sections-headers__arrow { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-headers__arrow { transform: translateX(2px); }

/* sections/hero */
.ehv-sections-hero { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv-sections-hero__arrow { fill: none; stroke: var(--ehv-on-lime); stroke-width: 1.25; }

.ehv--hover .ehv-sections-hero__arrow { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-hero__arrow { transform: translateX(2px); }

/* sections/logos */
.ehv-sections-logos { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

/* Four ways to set a name, so the grid reads as different companies. */
.ehv svg .ehv-sections-logos__name--a { font-weight: 500; letter-spacing: -0.035em; }
.ehv svg .ehv-sections-logos__name--b { font-family: var(--ehv-mono); letter-spacing: 0.16em; }
.ehv svg .ehv-sections-logos__name--c { letter-spacing: 0.01em; }
.ehv svg .ehv-sections-logos__name--d { font-weight: 500; letter-spacing: 0.12em; }

.ehv--hover svg .ehv-sections-logos__name { transition: fill 200ms var(--ehv-ease); }
.ehv--hover:hover svg .ehv-sections-logos__name { fill: var(--ehv-ink); }
.ehv--hover .ehv-sections-logos__arrow { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-logos__arrow { transform: translateX(2px); }

/* sections/newsletter */
.ehv-sections-newsletter { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv .ehv-sections-newsletter__input--focus { stroke: var(--ehv-lime); }

@keyframes ehv-sections-newsletter-blink { 50% { opacity: 0; } }
.ehv--animated .ehv-sections-newsletter__caret {
  animation: ehv-sections-newsletter-blink 1.1s steps(1) infinite;
}

.ehv--hover .ehv-sections-newsletter__input { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-newsletter__input { stroke: var(--ehv-lime); }

/* sections/pricing */
.ehv-sections-pricing { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv .ehv-sections-pricing__plan--picked {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-lime);
  stroke-width: 1;
}

/* The picked plan steps forward. */
.ehv--hover .ehv-sections-pricing__picked { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-pricing__picked { transform: translateY(-4px); }

/* sections/stats */
.ehv-sections-stats { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

/* sections/team */
.ehv-sections-team { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv .ehv-sections-team__avatar--on { stroke: var(--ehv-lime); stroke-width: 1.25; }
/* The line colour of lime, so the dot keeps its contrast on the light surface. */
.ehv .ehv-sections-team__dot { fill: var(--ehv-lime); }

.ehv--hover .ehv-sections-team__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-sections-team__card:hover { stroke: var(--ehv-border-strong); }

/* sections/testimonials */
.ehv-sections-testimonials { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv .ehv-sections-testimonials__card--on {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-lime);
  stroke-width: 1;
}

/* The featured quote steps forward. */
.ehv--hover .ehv-sections-testimonials__featured { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-sections-testimonials__featured { transform: translateY(-4px); }

/* The line colour of lime, so the mark keeps its contrast on the light surface. */
.ehv .ehv-sections-testimonials__mark--on { fill: var(--ehv-lime); }

/* security/fingerprint */
.ehv-security-fingerprint { --ehv-max-w: 330px; --ehv-step: 70ms; }

.ehv-security-fingerprint__ridge { fill: none; stroke-width: 2.2; stroke-linecap: round; }
.ehv-security-fingerprint__ridge--scanning { stroke: var(--ehv-ink-3); }
.ehv-security-fingerprint__ridge--verified { stroke: var(--ehv-ink-2); }
.ehv-security-fingerprint__ridge--failed { stroke: var(--ehv-ink-3); }

.ehv-security-fingerprint__line { fill: none; stroke: var(--ehv-lime); stroke-width: 1.5; stroke-linecap: round; }
.ehv-security-fingerprint__beam { fill: var(--ehv-lime-soft); }
.ehv-security-fingerprint__scan--failed .ehv-security-fingerprint__line { stroke: var(--ehv-coral); }
.ehv-security-fingerprint__scan--failed .ehv-security-fingerprint__beam { fill: var(--ehv-coral-soft); }

/* The ring of card colour that lifts the result badge off the ridges. */
.ehv-security-fingerprint__halo { fill: var(--ehv-surface-1); }
.ehv-security-fingerprint__check { fill: none; stroke: var(--ehv-on-lime); stroke-width: 2.25; }

.ehv-security-fingerprint__pill--scanning { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); stroke-width: 1; }
.ehv-security-fingerprint__pill--verified { fill: var(--ehv-lime-soft); }
.ehv-security-fingerprint__pill--failed { fill: var(--ehv-coral-soft); }

.ehv svg .ehv-mono.ehv-security-fingerprint__pill-text--scanning { fill: var(--ehv-ink-2); }
.ehv svg .ehv-mono.ehv-security-fingerprint__pill-text--verified { fill: var(--ehv-lime); }
.ehv svg .ehv-mono.ehv-security-fingerprint__pill-text--failed { fill: var(--ehv-coral); }

.ehv-security-fingerprint__scan { transform-box: view-box; }

/* While scanning, the line travels over the print and back. Once there is a
   result it comes down from the top once and rests at the bottom. */
@keyframes ehv-security-fingerprint-sweep {
  from { transform: translateY(-88px); }
  to { transform: translateY(78px); }
}
@keyframes ehv-security-fingerprint-settle {
  from { transform: translateY(-166px); opacity: 0; }
  12% { opacity: 1; }
}

.ehv--animated .ehv-security-fingerprint__scan--scanning {
  animation: ehv-security-fingerprint-sweep 2.2s ease-in-out infinite alternate;
}
.ehv--animated :is(.ehv-security-fingerprint__scan--verified, .ehv-security-fingerprint__scan--failed) {
  animation: ehv-security-fingerprint-settle 1.5s var(--ehv-ease) backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + 300ms);
}

.ehv--hover .ehv-security-fingerprint__ridge { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-security-fingerprint__ridge { stroke: var(--ehv-ink); }

/* security/lock */
.ehv-security-lock { --ehv-max-w: 370px; }

.ehv-security-lock__body { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; }
.ehv-security-lock__shackle { fill: none; stroke: var(--ehv-ink-2); stroke-width: 5; stroke-linecap: round; }
.ehv-security-lock__pill { fill: var(--ehv-surface-3); stroke: var(--ehv-border-soft); stroke-width: 1; }

.ehv-security-lock__chip--off { fill: none; stroke: var(--ehv-border-strong); stroke-width: 1; stroke-dasharray: 2 3; }
.ehv-security-lock__cross { fill: none; stroke: var(--ehv-ink-4); stroke-width: 1.25; }

/* The shackle clicks shut, or lifts when a role has the lock open. */
@keyframes ehv-security-lock-shut { from { transform: translateY(-8px); } }
@keyframes ehv-security-lock-open { from { transform: translateY(9px); } }

.ehv--animated .ehv-security-lock__latch {
  animation-duration: 500ms;
  animation-timing-function: var(--ehv-ease);
  animation-fill-mode: backwards;
  animation-delay: calc(var(--ehv-delay, 0ms) + 900ms);
}
.ehv--animated .ehv-security-lock__latch--shut { animation-name: ehv-security-lock-shut; }
.ehv--animated .ehv-security-lock__latch--open { animation-name: ehv-security-lock-open; }

.ehv--hover .ehv-security-lock__chip { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-security-lock__chip:hover { stroke: var(--ehv-lime); }

/* security/shield */
.ehv-security-shield { --ehv-max-w: 480px; }

.ehv-security-shield__plate { fill: var(--ehv-surface-3); stroke: var(--ehv-border-strong); stroke-width: 1; stroke-linejoin: round; }
.ehv-security-shield__check { fill: none; stroke: var(--ehv-lime); stroke-width: 3.5; }
.ehv-security-shield__check--off { stroke: var(--ehv-coral); }

.ehv-security-shield__card--off { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; }
.ehv-security-shield__wire--off { stroke-width: 1; }

.ehv--hover .ehv-security-shield__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-security-shield__card:hover { stroke: var(--ehv-lime); }

/* security/two-factor */
.ehv-security-two-factor { --ehv-max-w: 370px; --ehv-step: 110ms; }

.ehv-security-two-factor__shackle { fill: none; stroke: var(--ehv-ink-2); stroke-width: 2.5; stroke-linecap: round; }
.ehv-security-two-factor__shackle--open { stroke: var(--ehv-on-lime); }
.ehv-security-two-factor__body { fill: var(--ehv-on-lime); }
.ehv-security-two-factor__check { fill: none; stroke: var(--ehv-lime-fill); stroke-width: 2; }

.ehv-security-two-factor__caret { fill: none; stroke: var(--ehv-lime); stroke-width: 1.5; stroke-linecap: round; }
.ehv--animated .ehv-security-two-factor__caret { animation-duration: 1.1s; }

.ehv-security-two-factor__outcome--go { fill: var(--ehv-lime-fill); }
.ehv-security-two-factor__outcome--wait { fill: var(--ehv-canvas); stroke: var(--ehv-border-soft); stroke-width: 1; }

.ehv svg .ehv-mono.ehv-security-two-factor__outcome-text--go { fill: var(--ehv-on-lime); }
.ehv svg .ehv-mono.ehv-security-two-factor__outcome-text--wait { fill: var(--ehv-ink-2); }

.ehv--hover .ehv-security-two-factor__box { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-security-two-factor__slot:hover .ehv-security-two-factor__box { stroke: var(--ehv-lime); }

/* states/empty */
.ehv-states-empty { --ehv-max-w: 400px; --ehv-step: 70ms; }

.ehv-states-empty__slot { fill: none; stroke: var(--ehv-border-strong); stroke-width: 1; stroke-dasharray: 3 4; }
.ehv-states-empty__add { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-width: 1.25; }
.ehv .ehv-states-empty__plus { stroke-width: 1.5; }

.ehv--hover .ehv-states-empty__add { transition: fill 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-states-empty__add { fill: var(--ehv-lime-fill); }
.ehv--hover .ehv-states-empty__plus { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-states-empty__plus { stroke: var(--ehv-on-lime); }

/* states/error */
.ehv-states-error { --ehv-max-w: 520px; --ehv-iso-scale: 0.82; }

.ehv-states-error__failed { fill: var(--ehv-surface-1); stroke: var(--ehv-coral); stroke-width: 1.25; }
.ehv-states-error__dependent { opacity: 0.7; }

/* A coral ring leaves the failed card every few seconds. */
@keyframes ehv-states-error-alarm {
  from { opacity: 0.7; transform: scale(1); }
  60%, to { opacity: 0; transform: scale(1.16, 1.26); }
}
.ehv-states-error__alarm {
  fill: none;
  stroke: var(--ehv-coral);
  stroke-width: 1;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.ehv--animated .ehv-states-error__alarm {
  animation: ehv-states-error-alarm 2.4s var(--ehv-ease) infinite;
  animation-delay: calc(var(--ehv-delay, 0ms) + 4 * var(--ehv-step) + var(--ehv-dur));
}

/* The still packet stands in for the travelling ones when nothing moves. */
.ehv--animated .ehv-states-error__packet { display: none; }
@media (prefers-reduced-motion: reduce) {
  .ehv--animated .ehv-states-error__packet { display: inline; }
}

.ehv--hover .ehv-states-error__dependent { transition: opacity 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-states-error__dependent { opacity: 0.85; }

/* states/maintenance */
.ehv-states-maintenance { --ehv-max-w: 400px; }

/* The place the pulled-out tile leaves behind. */
.ehv-states-maintenance__slot { fill: none; stroke: var(--ehv-border-strong); stroke-width: 1; stroke-dasharray: 3 4; }

/* The wrench works back and forth around its own centre. */
@keyframes ehv-states-maintenance-turn {
  from { transform: rotate(-16deg); }
  to { transform: rotate(18deg); }
}
.ehv-states-maintenance__wrench { transform-box: fill-box; transform-origin: center; }
.ehv--animated .ehv-states-maintenance__wrench {
  animation: ehv-states-maintenance-turn 1.1s ease-in-out infinite alternate;
  animation-delay: calc(var(--ehv-delay, 0ms) + 6 * var(--ehv-step) + var(--ehv-dur));
}

.ehv--hover .ehv-states-maintenance__lifted { transition: transform 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-states-maintenance__lifted { transform: translate(8px, -3px); }

/* states/not-found */
.ehv-states-not-found { --ehv-max-w: 440px; }

/* The status code is the backdrop: outlined, in the tone of a surface. */
.ehv svg .ehv-states-not-found__code { fill: var(--ehv-surface-3); stroke: var(--ehv-ink-4); stroke-width: 1; }

.ehv-states-not-found__bar { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; }

/* The still packet stands in for the travelling one when nothing moves. */
.ehv--animated .ehv-states-not-found__packet { display: none; }
@media (prefers-reduced-motion: reduce) {
  .ehv--animated .ehv-states-not-found__packet { display: inline; }
}

.ehv--hover .ehv-states-not-found__action { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-states-not-found__action { stroke: var(--ehv-ink-2); }

/* status/health-check */
.ehv-status-health-check { --ehv-max-w: 360px; }

.ehv-status-health-check__ring { fill: none; stroke: var(--ehv-coral); stroke-width: 1.5; }

.ehv-status-health-check__pill--ok { fill: var(--ehv-lime-soft); }
.ehv-status-health-check__pill--degraded { fill: var(--ehv-coral-soft); }
.ehv-status-health-check__pill--down { fill: var(--ehv-coral-soft); stroke: var(--ehv-coral); stroke-width: 1; }

.ehv-status-health-check__lamp--ok { fill: var(--ehv-lime); }
.ehv-status-health-check__lamp--degraded,
.ehv-status-health-check__lamp--down { fill: var(--ehv-coral); }

.ehv svg .ehv-mono.ehv-status-health-check__word--ok { fill: var(--ehv-lime); }
.ehv svg .ehv-mono.ehv-status-health-check__word--degraded,
.ehv svg .ehv-mono.ehv-status-health-check__word--down { fill: var(--ehv-coral); }

/* status/resource-monitor */
.ehv-status-resource-monitor { --ehv-max-w: 410px; }

/* The first resource is lime, the others step back in ink. */
.ehv-status-resource-monitor__line--0 { fill: none; stroke: var(--ehv-lime); stroke-width: 1.6; }
.ehv-status-resource-monitor__line--1 { fill: none; stroke: var(--ehv-ink-2); stroke-width: 1.25; }
.ehv-status-resource-monitor__line--2 { fill: none; stroke: var(--ehv-ink-4); stroke-width: 1.25; }

.ehv-status-resource-monitor__dot--0 { fill: var(--ehv-lime-fill); }
.ehv-status-resource-monitor__dot--1 { fill: var(--ehv-surface-1); stroke: var(--ehv-ink-2); stroke-width: 1.25; }
.ehv-status-resource-monitor__dot--2 { fill: var(--ehv-surface-1); stroke: var(--ehv-ink-4); stroke-width: 1.25; }

.ehv--hover .ehv-status-resource-monitor__dot--0 { transition: r 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-status-resource-monitor__dot--0 { r: 5; }

/* The grid has to read as a grid on the dark card, so it is a step up from faint. */
.ehv-status-resource-monitor__grid { fill: none; stroke: var(--ehv-border-soft); stroke-width: 1; }

/* status/uptime-bar */
.ehv-status-uptime-bar { --ehv-max-w: 410px; --ehv-step: 28ms; --ehv-dur: 450ms; }

/* A day is lime when the service was up. Any other kind of day is coral. */
.ehv-status-uptime-bar__day { fill: var(--ehv-coral); }
.ehv-status-uptime-bar__day--up { fill: var(--ehv-lime-fill); }
.ehv-status-uptime-bar__day--degraded { fill-opacity: 0.5; }
.ehv-status-uptime-bar__day--down { fill-opacity: 1; }

.ehv--hover .ehv-status-uptime-bar__day { transition: opacity 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-status-uptime-bar__day:not(:hover) { opacity: 0.55; }

/* tasks/checklist */
.ehv-tasks-checklist { --ehv-max-w: 370px; --ehv-step: 120ms; }

/* A completed item is struck through in its own ink. */
.ehv svg .ehv-tasks-checklist__struck { text-decoration: line-through; }

/* The next item: an empty box with an ink ring. On hover it previews the tick. */
.ehv-tasks-checklist__next { fill: var(--ehv-canvas); stroke: var(--ehv-ink); stroke-width: 1.25; }
.ehv--hover .ehv-tasks-checklist__next { transition: stroke 200ms var(--ehv-ease), fill 200ms var(--ehv-ease); }
.ehv--hover:hover .ehv-tasks-checklist__next { stroke: var(--ehv-lime); fill: var(--ehv-lime-soft); }

/* tasks/kanban */
.ehv-tasks-kanban { --ehv-max-w: 480px; --ehv-step: 80ms; --ehv-iso-scale: 0.88; }

.ehv--hover .ehv-tasks-kanban__card { transition: stroke 200ms var(--ehv-ease); }
.ehv--hover .ehv-tasks-kanban__card:hover { stroke: var(--ehv-border-strong); }

/* The card in the air and the place it will land. */
.ehv-tasks-kanban__lifted { fill: var(--ehv-surface-3); stroke: var(--ehv-lime); stroke-width: 1.25; }
.ehv-tasks-kanban__drop { fill: var(--ehv-lime-soft); stroke: var(--ehv-lime); stroke-width: 1; stroke-dasharray: 3 4; }

/* Held, not placed: the card drifts a little, and leans toward its column on hover. */
@keyframes ehv-tasks-kanban-float { 50% { transform: translateY(-3px); } }

.ehv--animated .ehv-tasks-kanban__float {
  animation: ehv-tasks-kanban-float 3.6s ease-in-out infinite;
  animation-delay: calc(var(--ehv-dur) + 10 * var(--ehv-step));
}

.ehv--hover .ehv-tasks-kanban__carry { transition: transform 300ms var(--ehv-ease); }
.ehv--hover:hover .ehv-tasks-kanban__carry { transform: translate(12px, 4px); }

/* tasks/sort-lanes */
.ehv-tasks-sort-lanes { --ehv-max-w: 620px; --ehv-step: 110ms; }
.ehv-tasks-sort-lanes .ehv__glow { background: radial-gradient(46% 40% at 50% 54%, var(--ehv-glow), transparent 72%); }

/* Hairlines stay one pixel wide in the skewed ground plane. */
.ehv-tasks-sort-lanes__plane * { vector-effect: non-scaling-stroke; }

.ehv-tasks-sort-lanes__plate {
  fill: var(--ehv-surface-1);
  stroke: var(--ehv-border-strong);
  stroke-width: 1;
}

.ehv-tasks-sort-lanes__side {
  fill: var(--ehv-surface-2);
  stroke: var(--ehv-border-soft);
  stroke-width: 1;
  stroke-linejoin: round;
}

/* A cube: the top catches the light, the two visible sides step down. */
.ehv-tasks-sort-lanes__top,
.ehv-tasks-sort-lanes__left,
.ehv-tasks-sort-lanes__right {
  stroke: var(--ehv-ink-3);
  stroke-width: 1;
  stroke-linejoin: round;
}
.ehv-tasks-sort-lanes__top { fill: var(--ehv-surface-3); }
.ehv-tasks-sort-lanes__left { fill: var(--ehv-surface-2); }
.ehv-tasks-sort-lanes__right { fill: var(--ehv-surface-1); }

.ehv-tasks-sort-lanes__top--on { fill: var(--ehv-lime-fill); stroke: var(--ehv-lime); }
.ehv-tasks-sort-lanes__left--on { stroke: var(--ehv-lime); }
.ehv-tasks-sort-lanes__right--on { stroke: var(--ehv-lime); }

/* The lit cube is held, not placed: it drifts, and rises further on hover. */
@keyframes ehv-tasks-sort-lanes-float { 50% { transform: translateY(-4px); } }

.ehv--animated .ehv-tasks-sort-lanes__float {
  animation: ehv-tasks-sort-lanes-float 3.6s ease-in-out infinite;
  animation-delay: calc(var(--ehv-dur) + 12 * var(--ehv-step));
}

.ehv--hover .ehv-tasks-sort-lanes__carry { transition: transform 300ms var(--ehv-ease); }
.ehv--hover:hover .ehv-tasks-sort-lanes__carry { transform: translateY(-8px); }
