/*
 * Hostile — layer 2: the deployment's own chrome.
 *
 * COUPLED TO THE CORE'S CLASS NAMES, ON PURPOSE. The core's contract covers
 * colour, shape, depth and motion tokens; it does not cover gradients, glass,
 * texture or where a highlight falls, and those are what make a product look
 * like someone's rather than like a template with a hue. Class names are
 * explicitly *not* the contract, so a core MINOR release may move any of
 * them. The whole file is the risk, which is why it is its own file:
 *
 *   after bumping the core, run `make preview` and look at four screens —
 *   sign-in, Home, an artist, and the light theme. That is the check.
 *
 * Classes it depends on: .rail (+ .brand, nav a, [aria-current]), .topbar,
 * .surface, .tile (+ .value, .label), .block-head h2, .page, .page-head,
 * .btn(-primary), .segmented, .chip, .input/.select/.searchfield, .skeleton,
 * .chart, .table-wrap th, .empty, .signin (+ .notice), .rows li, .listbox, .avatar.
 * Pairs with core 0.8.0 or later: the glass tokens it reads exist from there.
 *
 * Direction: a rig at night. Near-black that is lit rather than painted,
 * cold light through glass, hairlines that carry the two brand colours, and
 * motion that behaves like equipment coming online — one shot, quick, then
 * still. Nothing here animates while a manager is trying to read a number.
 */

/* ---- the ground ------------------------------------------------------- */

/* Two lilac fields and one blue one, drifting on a 40-second cycle behind
   everything. This is the thing you notice first and never look at again,
   which is the correct amount of attention for a background. */
body::before {
  content: "";
  position: fixed;
  inset: -12%;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(
      52% 46% at 12% 4%,
      rgba(120, 86, 214, 0.6),
      transparent 64%
    ),
    radial-gradient(
      44% 40% at 92% 12%,
      rgba(54, 145, 198, 0.38),
      transparent 62%
    ),
    radial-gradient(
      60% 50% at 62% 104%,
      rgba(110, 74, 190, 0.45),
      transparent 68%
    );
  /* No blur filter: three radial gradients are already smooth, the grain
     below hides what banding is left, and blurring a fixed, animated,
     full-viewport layer costs a repaint of the whole screen every frame. */
  will-change: transform;
  animation: h-drift 42s var(--ease) infinite alternate;
}

/* Grain, at 4%: it kills the banding three overlapping radial gradients
   produce on a dark panel, and it is why the ground reads as a surface
   rather than as a fill. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

:root[data-theme="light"] body::before {
  background:
    radial-gradient(
      52% 46% at 12% 4%,
      rgba(120, 86, 214, 0.22),
      transparent 64%
    ),
    radial-gradient(
      44% 40% at 92% 12%,
      rgba(54, 145, 198, 0.16),
      transparent 62%
    ),
    radial-gradient(
      60% 50% at 62% 104%,
      rgba(168, 146, 239, 0.24),
      transparent 68%
    );
}
:root[data-theme="light"] body::after {
  opacity: 0.025;
}

/* ---- glass chrome ------------------------------------------------------ */

/* Since core 0.8.0 the glass itself is the core's: the top bar, the dock,
   the palette, the option lists and the sign-in card read the `--glass-*`
   tokens `brand.css` sets, so nothing here repeats a fill or a blur. What
   stays is what the core does not do: the desktop rail becomes glass too
   (on a desktop the core keeps it a panel; here the aurora moves behind
   it, which is most of why the product feels lit), and the edges become
   the brand. */
.rail {
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.4);
  border-color: transparent;
}
.topbar {
  border-color: transparent;
}

/* Their edges are the brand, not a gray line: lilac at the top, blue where
   the eye leaves. */
.rail {
  border-right: 0;
}
.rail::after {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  inline-size: 1px;
  background: linear-gradient(
    180deg,
    transparent,
    rgba(168, 146, 239, 0.55) 14%,
    rgba(127, 198, 242, 0.4) 62%,
    transparent
  );
}
.topbar {
  border-bottom: 0;
}
.topbar::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: linear-gradient(
    90deg,
    rgba(168, 146, 239, 0.5),
    rgba(127, 198, 242, 0.3) 46%,
    transparent 82%
  );
}

/* The wordmark is the logo: no image, so it carries the two colours itself.
   Skipped when a client ships a real logo file. */
.rail .brand:not(:has(img)) {
  font-weight: 700;
  letter-spacing: -0.01em;
  background: linear-gradient(
    100deg,
    var(--h-lilac-200),
    var(--h-blue-300) 52%,
    var(--h-lilac-300)
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The dark theme's gradient is two light tints; on white it disappears, so
   the light theme takes the same two families four steps deeper. */
:root[data-theme="light"] .rail .brand:not(:has(img)),
:root[data-theme="light"] .signin h1 {
  background: linear-gradient(
    100deg,
    var(--h-lilac-700),
    var(--h-blue-700) 52%,
    var(--h-lilac-600)
  );
  -webkit-background-clip: text;
  background-clip: text;
}

/* ---- navigation -------------------------------------------------------- */

.rail nav a {
  position: relative;
  transition:
    background-color var(--motion-fast) var(--ease),
    color var(--motion-fast) var(--ease),
    transform var(--motion-fast) var(--ease);
}
.rail nav a:hover {
  transform: translateX(1px);
}
.rail nav a[aria-current="page"] {
  background: linear-gradient(
    90deg,
    rgba(168, 146, 239, 0.22),
    rgba(127, 198, 242, 0.07) 58%,
    transparent
  );
}
/* The section you are in, as a lit edge. */
.rail nav a[aria-current="page"]::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block: 7px;
  inline-size: 2px;
  border-radius: 2px;
  background: linear-gradient(
    180deg,
    var(--h-lilac-300),
    var(--h-blue-400)
  );
  box-shadow: 0 0 12px 1px rgba(168, 146, 239, 0.6);
}

/* ---- surfaces ---------------------------------------------------------- */

/* Every card gets the light from above that a lit room would give it. */
.surface {
  background:
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.045),
      rgba(255, 255, 255, 0) 38%
    ),
    color-mix(in srgb, var(--surface) 76%, transparent);
}
:root[data-theme="light"] .surface {
  background:
    linear-gradient(
      180deg,
      rgba(109, 79, 196, 0.05),
      rgba(255, 255, 255, 0) 40%
    ),
    color-mix(in srgb, var(--surface) 86%, transparent);
}

/* A tile that goes somewhere: a sheen crosses it once, the ring turns to the
   accent, and it rises a pixel. The sheen is a background on the tile's own
   pseudo-element, clipped by its own radius -- no `overflow: hidden`, which
   would eat the account chips' pop-outs. */
a.tile {
  position: relative;
  isolation: isolate;
}
a.tile::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(
    100deg,
    transparent 30%,
    rgba(168, 146, 239, 0.16) 46%,
    rgba(127, 198, 242, 0.14) 54%,
    transparent 70%
  );
  background-size: 300% 100%;
  background-position: 120% 0;
  opacity: 0;
  transition: opacity var(--motion-fast) var(--ease);
}
a.tile:hover::after {
  opacity: 1;
  animation: h-sheen 620ms var(--ease);
}
a.tile:hover {
  transform: translateY(-2px);
  box-shadow:
    0 0 0 1px rgba(168, 146, 239, 0.45),
    0 14px 30px -16px rgba(120, 86, 214, 0.9);
}

/* A row that goes somewhere says so; `:has`, so the many lists of plain
   readings do not pretend to be clickable. */
.rows li {
  transition: background-color var(--motion-fast) var(--ease);
}
.rows li:has(a, button):hover {
  background: var(--hover);
}

.avatar,
.avatar-lg {
  box-shadow: 0 0 0 1px var(--border-strong);
}

/* ---- type -------------------------------------------------------------- */

/* Section titles become labels: small, tracked, uppercase. The screen's own
   title stays a title, and the numbers get all the weight back. */
.block-head h2 {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
}
.page-head {
  position: relative;
  padding-block-end: 16px;
}
/* A lit rule under the screen's title: the frame the rest of the screen
   hangs from, and the second place after the rail where both brand colours
   appear together. */
.page-head::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: linear-gradient(
    90deg,
    rgba(168, 146, 239, 0.55),
    rgba(127, 198, 242, 0.22) 38%,
    transparent 78%
  );
}
.page-head h1 {
  letter-spacing: -0.025em;
}
.table-wrap th {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
/* Figures line up down a column of a table, where alignment is the point.
   NOT on the big tile values: the display face's tabular period is a full
   digit wide, and `39.6K` came out reading as `39 . 6K`. */
.table-wrap td,
.table-wrap th,
.chart text {
  font-variant-numeric: tabular-nums;
}
.tile .value,
.movers .figure,
.num {
  letter-spacing: -0.03em;
}
.tile .label .name {
  letter-spacing: 0.02em;
}

/* ---- controls ---------------------------------------------------------- */

.btn-primary {
  background: linear-gradient(
    135deg,
    var(--h-lilac-300),
    var(--h-lilac-500) 52%,
    var(--h-blue-500)
  );
  color: var(--h-ink-1000);
  border: 0;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    0 8px 20px -10px rgba(143, 116, 230, 0.95);
}
.btn-primary:hover {
  filter: brightness(1.07);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    0 12px 26px -10px rgba(143, 116, 230, 1);
}
/* Secondary buttons are glass over the ground, like the chrome they sit in.
   `.btn-quiet` is excluded on purpose: it is the core's transparent button —
   the rail's Collapse, the sections toggle — and filling it turns two pieces
   of chrome into two boxes. */
.btn:not(.btn-primary, .btn-quiet) {
  background: color-mix(in srgb, var(--surface-2) 72%, transparent);
}
.btn:not(.btn-primary, .btn-quiet):hover {
  background: color-mix(in srgb, var(--surface-3) 82%, transparent);
  box-shadow: 0 0 0 1px rgba(168, 146, 239, 0.45);
}

.segmented label:has(input:checked) {
  background: linear-gradient(
    135deg,
    rgba(168, 146, 239, 0.28),
    rgba(127, 198, 242, 0.16)
  );
  color: var(--text);
  box-shadow:
    inset 0 0 0 1px rgba(168, 146, 239, 0.4),
    0 2px 10px -6px rgba(120, 86, 214, 0.9);
}

.chip {
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface-2) 70%, transparent);
  box-shadow: inset 0 0 0 1px var(--border);
  transition:
    box-shadow var(--motion-fast) var(--ease),
    color var(--motion-fast) var(--ease);
}
.chip:hover {
  box-shadow: inset 0 0 0 1px rgba(168, 146, 239, 0.55);
  color: var(--text);
}

.input:focus-visible,
.select:focus-visible,
.searchfield:focus-within {
  box-shadow:
    0 0 0 1px rgba(168, 146, 239, 0.6),
    0 0 0 4px rgba(168, 146, 239, 0.14);
}

/* ---- charts ------------------------------------------------------------ */

.chart .grid line {
  stroke-dasharray: 2 5;
  opacity: 0.7;
}
.chart text {
  letter-spacing: 0.06em;
}
/* The line is lit, not drawn. A DJ roster's numbers should look like they
   came off a rig, and this is one CSS filter rather than a chart rewrite. */
.chart path.draw,
.spark path.draw {
  filter: drop-shadow(0 0 5px rgba(168, 146, 239, 0.45));
}
:root[data-theme="light"] .chart path.draw,
:root[data-theme="light"] .spark path.draw {
  filter: none;
}

/* ---- states ------------------------------------------------------------ */

/* A skeleton that is loading looks like it is loading. */
.skeleton {
  background: linear-gradient(
    100deg,
    var(--surface-2) 20%,
    rgba(168, 146, 239, 0.14) 38%,
    var(--surface-2) 56%
  );
  background-size: 300% 100%;
  animation: h-shimmer 1.4s linear infinite;
}
.empty {
  background:
    radial-gradient(
      70% 120% at 50% 0%,
      rgba(168, 146, 239, 0.09),
      transparent 70%
    ),
    var(--surface);
}
.dot {
  animation: h-pulse 2.6s var(--ease) infinite;
}

/* ---- the page itself --------------------------------------------------- */

::selection {
  background: rgba(168, 146, 239, 0.34);
  color: var(--text);
}
* {
  scrollbar-width: thin;
  scrollbar-color: var(--h-lilac-800) transparent;
}
::-webkit-scrollbar {
  inline-size: 11px;
  block-size: 11px;
}
::-webkit-scrollbar-thumb {
  border: 3px solid transparent;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--h-lilac-600), var(--h-lilac-800));
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(180deg, var(--h-lilac-500), var(--h-lilac-700));
  background-clip: content-box;
}

/* ---- sign-in ----------------------------------------------------------- */

/* The first thing anyone sees, and the only screen with room to be a brand
   rather than a tool. */
.signin form,
.signin .notice {
  padding: 30px 28px;
  animation: h-form-in 560ms var(--ease) backwards;
}
/* One screen, one name, one light on it. Stronger than the ground the app
   sits on, because here there is nothing to read over it. */
.signin::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    40% 44% at 50% 46%,
    rgba(168, 146, 239, 0.26),
    transparent 70%
  );
  animation: h-breathe 13s var(--ease) infinite alternate;
}
.signin h1 {
  font-size: 30px;
  letter-spacing: -0.03em;
  background: linear-gradient(
    100deg,
    var(--h-lilac-200),
    var(--h-blue-300) 55%,
    var(--h-lilac-300)
  );
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---- motion ------------------------------------------------------------ */

/* A screen arrives: head, filters and blocks in turn, once, on mount.

   `backwards`, never `both`: a filled transform keeps its element a stacking
   context for good, and then a dropdown opened in the filters section paints
   *under* the tiles section whatever its z-index. Which is precisely what
   happened on Compare. `backwards` covers the delay and lets go at the end. */
.page > * {
  animation: h-rise var(--motion) var(--ease) backwards;
}
.page > *:nth-child(2) {
  animation-delay: 45ms;
}
.page > *:nth-child(3) {
  animation-delay: 90ms;
}
.page > *:nth-child(n + 4) {
  animation-delay: 135ms;
}

/* The rail comes up once, on the first paint of the session. */
.rail nav a {
  animation: h-slide 420ms var(--ease) backwards;
}
.rail nav ul:first-of-type a {
  animation-delay: 60ms;
}
.rail nav ul + ul a {
  animation-delay: 120ms;
}

@keyframes h-drift {
  to {
    transform: translate3d(-2.5%, 2%, 0) scale(1.14);
  }
}
@keyframes h-sheen {
  from {
    background-position: 120% 0;
  }
  to {
    background-position: -60% 0;
  }
}
@keyframes h-shimmer {
  to {
    background-position: -200% 0;
  }
}
@keyframes h-pulse {
  50% {
    opacity: 0.45;
    transform: scale(0.86);
  }
}
@keyframes h-rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}
@keyframes h-slide {
  from {
    opacity: 0;
    transform: translateX(-6px);
  }
}
@keyframes h-breathe {
  to {
    opacity: 0.5;
    transform: scale(1.18);
  }
}
@keyframes h-form-in {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.985);
  }
}

/* Reduce, do not remove: everything that arrives is simply there, the ground
   stops moving, and hover and focus keep working. */
@media (prefers-reduced-motion: reduce) {
  body::before,
  .signin::before,
  .dot,
  .skeleton,
  .page > *,
  .rail nav a,
  .signin form,
  .signin .notice,
  a.tile:hover::after {
    animation: none;
  }
  a.tile:hover {
    transform: none;
  }
  .rail nav a:hover {
    transform: none;
  }
}
