/*
  Home page background: a hexagon grid with glints of light that run its borders.
  Loaded only on the home page, alongside static/js/hex-background.js.
  Colours come from the theme tokens, so light and dark mode both work.
*/

/* The grid sits behind the page, so the body lets it show through. */
body.has-hex-bg {
  background: transparent;
}

#hexagon-container {
  position: fixed;
  top: -30px;
  left: -30px;
  width: calc(100% + 60px);
  height: calc(100lvh + 60px);
  z-index: -1; /* below the page, so it never blocks clicks; JS finds hexagons under empty spots */
  overflow: hidden;
  background:
    linear-gradient(
      135deg,
      color-mix(in oklab, var(--color-primary) 12%, transparent) 0%,
      color-mix(in oklab, var(--color-secondary) 12%, transparent) 100%
    ),
    var(--color-base-200);
}

/* A haze over the middle of the window, where the page's text sits. The grid
   and the glints stay lively around the edges but read as quiet behind content.
   Raise --hex-scrim for a calmer background, lower it for a busier one. */
#hexagon-container::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  --hex-scrim: 46%;
  background: radial-gradient(
    120% 90% at 50% 30%,
    color-mix(in oklab, var(--color-base-200) var(--hex-scrim), transparent) 0%,
    color-mix(in oklab, var(--color-base-200) calc(var(--hex-scrim) * 0.55), transparent) 58%,
    transparent 100%
  );
}

/* Soft darkening at the edges of the window */
body.has-hex-bg::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 60;
  box-shadow: inset 0 0 160px rgb(0 0 0 / 0.1);
}

/* ---- Hexagons ---- */

/* Hex SVGs live in this layer so the entrance can fade one element instead of
   hundreds of per-hexagon opacities on the hammer slam (see animateEntrance). */
.hex-grid-layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  contain: paint;
}
/* Rasterize the grid during the hammer's swing-in (html.anvil-intro is on
   from first paint) so the slam only fades a layer that's already composited.
   0.001 is invisible but not skippable the way opacity: 0 is. */
html.anvil-intro .hex-grid-layer:not(.is-in) {
  opacity: 0.001;
  will-change: opacity;
}
.hex-grid-layer.is-in {
  opacity: 1;
  transition: opacity 0.5s ease-out;
  will-change: opacity;
}

.hexagon {
  position: absolute;
  opacity: 0;
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
  contain: layout style;
}
/* How a hexagon looks at rest. Raise these for a more present grid. */
#hexagon-container {
  --hex-fill: 0.12;
  --hex-stroke: 0.32;
}
/* On the light theme white-on-grey needs more strength to show at all. */
[data-theme="emerald"] #hexagon-container,
:root:not([data-theme]) #hexagon-container {
  --hex-fill: 0.26;
  --hex-stroke: 0.55;
}

.hexagon polygon {
  fill: var(--color-base-100);
  fill-opacity: var(--hex-fill);
  stroke: var(--color-base-100);
  stroke-opacity: var(--hex-stroke);
  stroke-width: 1.15;
}

/* A blow on the anvil sends a ring out through the grid (see shockwave in
   static/js/hex-background.js): each hexagon catches the light on its border
   as the wave reaches it, then cools back to rest. It stays the grid's own
   colour and only brightens — a shimmer running outwards, not a colour
   sweeping over the page. */
.hex-shock-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.hex-shock-ring {
  fill: none;
  stroke: color-mix(in oklab, var(--color-primary) 45%, var(--color-base-100));
  stroke-width: 2.2;
  opacity: 0;
  transition: opacity 1.1s ease-out;
}
.hex-shock-ring.is-lit {
  opacity: 1;
  transition: none;
}

/* Entrance: hexes are marked ready ahead of the slam; .hex-grid-layer.is-in
   fades them up as one paint, and the border shockwave is the motion. */
.hexagon.hex-entered {
  opacity: 1;
  transform: none;
}

/* Clicked: fade out, then respawn */
.hexagon.clicked {
  opacity: 0;
  transform: translate3d(0, 0, 0) scale(0.8);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.hexagon.respawning {
  opacity: 0;
  transform: translate3d(0, 0, 0) scale(0.3);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.hexagon.fade-in { animation: hexagon-fade-in 0.6s ease-out forwards; }

@keyframes hexagon-fade-in {
  0% { opacity: 0; transform: translate3d(0, 0, 0) scale(0.3); }
  60% { opacity: 0.8; transform: translate3d(0, 0, 0) scale(1.05); }
  100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

/* ---- Glints ---- */
/* Points of light that run the hexagons' borders, each a bright head with a
   short tail behind it (static/js/hex-background.js). */

/* Every glint lives in this one layer, so the whole effect is a single element
   for the compositor however many are running. */
.glint-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* The tail: one stroke in the theme colours, faded along its length by the
   mask below rather than by its own gradient, so the fade follows the path. */
.glint-tail {
  fill: none;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The mask's slices: wider than the tail, so their edges fall outside it. */
.glint-mask-slice {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* The head, and the soft halo carrying it. */
.glint-head { stroke: none; }
.glint-halo { stroke: none; }
/* The flash left behind when a glint crosses a corner of the lattice. */
.glint-spark {
  fill: none;
  stroke-width: 1.6;
}

@media (prefers-reduced-motion: reduce) {
  .hex-grid-layer { opacity: 1; transition: none; }
  .hexagon { opacity: 1; transform: none; }
  .glint-layer { display: none; }
}
