/* ==========================================================================
   DAGLINGS — front page
   Loads after card.css and reuses its tokens. Dark theme only.
   Every corner in the INTERFACE is a chamfer — buttons, panels, pills, the
   pack's bay (see .cut). Cards are the exception: they are rounded like
   die-cut physical cards. Cards are objects, interface is interface.
   ========================================================================== */

:root {
  --void-deep: #070b12; /* hero */
  --panel: #0d1421;
  --panel-2: #111a2a;
  --ink: #eef3fb;
  --muted: rgba(238, 243, 251, 0.62);
  --faint: rgba(238, 243, 251, 0.38);
  --line: rgba(255, 255, 255, 0.12);
  --teal: var(--kaspa-teal);
  /* Red is reserved EXCLUSIVELY for red-chain references (GHOSTDAG reds,
     red/gold finishes). Never use it for errors, accents or emphasis. */
  --chain-red: #ff5a5a;
}

* { box-sizing: border-box; }

img, svg { max-width: 100%; }

/* Grid and flex items default to min-width:auto, so one unbreakable word can
   push a track — and the whole page — wider than the viewport. */
.hero__inner > *,
.steps > *,
.grid > *,
.finishes > * {
  min-width: 0;
}

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* The page is a descent: slightly lighter blue-black at the top, deepening to
   pure void by the bottom. Painted on the body box (the whole document), NOT
   background-attachment: fixed — a fixed attachment repaints the backdrop on
   every scroll frame and is a classic jank source. */
body {
  margin: 0;
  background-color: #05080e;
  background-image: linear-gradient(
    180deg,
    #0d1420 0%,
    #0a1018 26%,
    #070b12 62%,
    #05080e 100%
  );
  color: var(--ink);
  font-family: "IBM Plex Sans", system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* Content sits above the drifting void layer. */
.page-head,
main,
.foot,
.skip { position: relative; z-index: 1; }

/* --- page-wide void ------------------------------------------------------
   Fixed and pointer-events:none, so it never touches text and never
   participates in layout. Only transform and opacity animate, so every block
   stays on the compositor and scrolling never repaints them. */
.pagevoid {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.pagevoid i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  height: var(--s);
  background: rgba(73, 224, 192, 0.14);
  border: 1px solid rgba(73, 224, 192, 0.7);
  opacity: 0;
  will-change: transform, opacity;
  animation: dag-float var(--dur) linear var(--delay) infinite;
}

/* One animation does both jobs: transform drifts the block, opacity blinks it
   in and out of existence. Only those two properties animate, so each block
   lives on the compositor and scrolling never repaints the field.

   The fade percentages are chosen against the duration range: 7% of 18-34s is
   a 1.3-2.4s fade-in, which is the "~1-2s" lifecycle regardless of how fast a
   given block happens to be. Each block is fully absent for the last ~30% of
   its cycle, so the field genuinely thins and refills rather than merely
   sliding — and with randomised durations and negative delays, no two blocks
   ever share a phase. */
@keyframes dag-float {
  0%   { opacity: 0; transform: translate3d(0, 0, 0); }
  7%   { opacity: var(--peak, 0.4); }
  62%  { opacity: var(--peak, 0.4); }
  70%  { opacity: 0; }
  100% { opacity: 0; transform: translate3d(var(--dx), calc(-1 * var(--rise)), 0); }
}

@media (prefers-reduced-motion: reduce) {
  .pagevoid i {
    animation: none;
    opacity: var(--peak, 0.4);
    will-change: auto;
  }
}

h1, h2, h3, .display {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 700;
  line-height: 1.02;
  margin: 0;
}

a { color: inherit; }

/* --- the shared chamfer -------------------------------------------------
   One class, sized by --c. Mirrors the cards' 26px cut. Remember clip-path
   discards borders and box-shadows on the clipped element — anything that
   needs an outline uses the two-layer .framed below. */
.cut {
  --c: 26px;
  clip-path: polygon(
    var(--c) 0,
    calc(100% - var(--c)) 0,
    100% var(--c),
    100% calc(100% - var(--c)),
    calc(100% - var(--c)) 100%,
    var(--c) 100%,
    0 calc(100% - var(--c)),
    0 var(--c)
  );
}

/* Two-layer chamfered panel: outer is the hairline, inner is the fill.
   Inner cut = c - 2t - t*sqrt(2) keeps the line even around the diagonal. */
.framed {
  --c: 26px;
  --t: 1px;
  padding: var(--t);
  background: var(--line);
}
.framed > .framed__in {
  --c: calc(26px - 2 * 1px - 1.41421 * 1px); /* 22.59px */
  background: var(--panel);
  height: 100%;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 12px 18px;
  background: var(--teal);
  color: #04120e;
  font-weight: 600;
  z-index: 100;
}
.skip:focus { left: 0; }

:where(a, button):focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 3px;
}

.wrap {
  width: min(1240px, 100% - clamp(32px, 6vw, 96px));
  margin-inline: auto;
}

/* ==========================================================================
   Nav
   ========================================================================== */

.nav {
  position: relative;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 22px 0;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 700;
  font-size: 19px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
}
/* Realm first, game second — both present, clearly ranked. */
.brand__words {
  display: inline-flex;
  align-items: baseline;
  gap: 9px;
}
.brand__secondary {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--teal);
}
@media (max-width: 560px) {
  .brand__secondary { display: none; }
}
.brand__mark {
  width: 13px;
  height: 13px;
  background: var(--teal);
  flex: none;
}

.nav__links {
  display: flex;
  gap: clamp(6px, 1.4vw, 14px);
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

/* A tab is one line. Two-word labels — Shop Packs, My Deck — were breaking
   once the row grew to six tabs, which made the nav two rows tall on a
   laptop and moved the underline off the bottom of its own link. The row
   tightens instead: the letter-spacing and padding give up the most width
   for the least legibility, in that order. */
.nav__link { white-space: nowrap; }
@media (max-width: 1320px) {
  .nav__links { letter-spacing: 0.1em; gap: 4px; }
  .nav__link { padding-inline: 9px; }
}
@media (max-width: 1140px) {
  .nav__links { font-size: 12px; letter-spacing: 0.06em; }
  .nav__link { padding-inline: 7px; }
  .nav__link.is-current::after { left: 7px; right: 7px; }
}

/* Real page tabs, not scroll anchors. The current page is marked with the
   teal underline as well as color, so it does not rely on hue alone. */
.nav__link {
  --c: 8px;
  position: relative;
  padding: 10px 14px 12px;
  text-decoration: none;
  transition: color 0.16s, background 0.16s;
}
.nav__link:hover { color: var(--ink); background: rgba(255, 255, 255, 0.05); }
.nav__link.is-current { color: var(--ink); }
.nav__link.is-current::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 4px;
  height: 2px;
  background: var(--teal);
}

/* Roster and any other non-hero page: the nav needs its own ground. */
.page-head {
  background: rgba(7, 11, 18, 0.62);
  border-bottom: 1px solid var(--line);
}
.section--top { padding-top: clamp(44px, 6vh, 80px); }

/* ==========================================================================
   1. Hero
   ========================================================================== */

/* Translucent, not opaque: the fixed block field sits behind every section,
   and an opaque ground here would blank it out across the whole hero. Each
   section still reads as its own band, just with the void showing through. */
.hero {
  position: relative;
  z-index: 1;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: rgba(7, 11, 18, 0.5);
  /* The hero card's glow is inset -18% horizontally and bleeds past the
     viewport at narrow widths, giving the page a 20px horizontal scroll.
     Clipping here costs nothing — the glow is decoration — and the drifting
     field is position:fixed, so it is not clipped by this. */
  overflow: hidden;
}

/* The hero has no block layer of its own any more — the page-wide field in
   .pagevoid runs behind it and every other section, as one continuous field. */

.hero__inner {
  flex: 1;
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  align-items: center;
  gap: clamp(32px, 6vw, 88px);
  padding: clamp(32px, 6vh, 80px) 0 clamp(48px, 8vh, 96px);
}
@media (max-width: 900px) {
  .hero__inner { grid-template-columns: 1fr; }
}

.eyebrow {
  margin: 0 0 22px;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--teal);
}

.hero h1 {
  /* The min has to fit the longest line ("IN THE CHAIN.") on one line at the
     narrowest phone, or the headline pushes the grid — and with it the whole
     page — wider than the viewport. Measured at 320vw: 38px renders that line
     at 258px inside a 288px gutter. Re-measure if the headline ever changes. */
  font-size: clamp(38px, 9.6vw, 132px);
  letter-spacing: -0.015em;
  text-transform: uppercase;
}
.hero h1 .thin { color: var(--faint); }

.lede {
  max-width: 47ch;
  margin: 30px 0 0;
  font-size: clamp(16px, 1.5vw, 19px);
  color: var(--muted);
}

/* The one hard product fact in the hero. Set apart from the lede and keyed
   teal, because it is the sentence that has to survive someone reading only
   the top of the page. */
.hero__mint {
  max-width: 47ch;
  margin: 18px 0 0;
  padding-left: 14px;
  border-left: 2px solid var(--teal);
  font-size: clamp(14px, 1.25vw, 16px);
  color: rgba(238, 243, 251, 0.82);
}

/* One CTA. The flex row, wrap and gap were only there to sit two buttons
   side by side; a single inline-flex button needs none of it and keeping
   them would silently stretch it if the container ever changed. */
.cta { margin-top: 40px; }

.btn {
  --c: 8px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 28px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  border: 0;
  background: rgba(255, 255, 255, 0.07);
  color: var(--ink);
  transition: background 0.18s, color 0.18s;
}
.btn:hover { background: rgba(255, 255, 255, 0.13); }
.btn--primary {
  background: var(--teal);
  color: #04120e;
}
.btn--primary:hover { background: #63efd0; }

/* Barely-there teal glow behind the hero card, so it sits in light rather
   than on flat black. Static paint on a pseudo-element; nothing animates. */
.hero__card {
  position: relative;
  justify-self: center;
  width: min(380px, 100%);
}
.hero__card::before {
  content: "";
  position: absolute;
  inset: -22% -18%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    50% 42% at 50% 44%,
    rgba(73, 224, 192, 0.1),
    rgba(63, 217, 255, 0.045) 46%,
    transparent 72%
  );
}
@media (max-width: 900px) {
  .hero__card { margin-top: 8px; }
}
.caption {
  margin: 20px 0 0;
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--faint);
}

/* --- 3D cursor tilt ------------------------------------------------------ */
.tilt-scene { perspective: 1100px; }
.tilt {
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transform-style: preserve-3d;
  transition: transform 0.14s ease-out;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .square { animation: none; opacity: 0.85; }
  .tilt { transform: none; transition: none; }
}

/* ==========================================================================
   Sections
   ========================================================================== */

.section { position: relative; padding: clamp(80px, 12vh, 150px) 0; }
.section--alt { background: rgba(7, 11, 18, 0.55); }

/* The Tangling sits on the same micro-texture language as the card frame:
   a fine diagonal weave, a couple of percent lighter than its ground, plus a
   barely-there teal glow behind the headline. Both are static paint — no
   animation, nothing to recompute on scroll. */
#tangling::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(
      44% 34% at 22% 24%,
      rgba(73, 224, 192, 0.055),
      transparent 72%
    ),
    repeating-linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.017) 0 1px,
      transparent 1px 9px
    ),
    repeating-linear-gradient(
      -45deg,
      rgba(255, 255, 255, 0.012) 0 1px,
      transparent 1px 9px
    );
}

/* --- the width line ------------------------------------------------------
   The 1-16 block-width scale as environmental graphic, echoing the footer's.
   Pure CSS: a rule plus 16 ticks from a repeating gradient. */
.widthline {
  position: relative;
  height: 30px;
  margin: clamp(34px, 4.5vw, 56px) 0 0;
}
.widthline::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(73, 224, 192, 0.26) 6%,
    rgba(73, 224, 192, 0.26) 94%,
    transparent
  );
}
.widthline::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: calc(50% - 5px);
  height: 11px;
  /* 100/16 = 6.25% per tick. */
  background: repeating-linear-gradient(
    90deg,
    rgba(73, 224, 192, 0.3) 0 1px,
    transparent 1px 6.25%
  );
}
.widthline__n {
  position: absolute;
  top: calc(50% + 10px);
  font-size: 10px;
  letter-spacing: 0.18em;
  color: rgba(73, 224, 192, 0.32);
}
.widthline__n--lo { left: 0; }
.widthline__n--hi { right: 0; }

/* --- the chain, running -------------------------------------------------
   js/dag-flow.js paints it, up in the Tangled section; the ruler above reads
   its width from a distance over the `dagwidth` event. The canvas sets its
   own width and height in JS from data-height, so nothing
   here may size it — a stylesheet height that disagreed with the backing
   store would stretch the drawing. */
.dag-flow {
  display: block;
  margin: clamp(26px, 3.6vw, 44px) 0 0;
  /* Full bleed: it sits outside .wrap, under the Tangled paragraph, because
     this is the net being cast forward rather than a figure inside the text
     column. The mask is what makes it arrive and leave — hard edges would
     read as a diagram with a frame around it. */
  -webkit-mask: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
  mask: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}

/* The marker. --w is the live width, 1-16, written by js/home.js; the ticks
   are one per 6.25%, so the centre of width n sits at (n - 0.5) x 6.25%.
   The transition on `left` is the whole point — it slides between widths
   instead of teleporting, which is what ties it to the chain above. */
.widthline__mark {
  position: absolute;
  top: calc(50% - 9px);
  left: calc((var(--w, 1) - 0.5) * 6.25%);
  width: 2px;
  height: 19px;
  background: var(--teal);
  box-shadow: 0 0 10px rgba(73, 224, 192, 0.55);
  transform: translateX(-1px);
  transition: left 420ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.widthline__mark b {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 5px);
  transform: translateX(-50%);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--teal);
}
@media (prefers-reduced-motion: reduce) {
  .widthline__mark { transition: none; }
}

.section__head { max-width: 62ch; margin-bottom: clamp(38px, 5vw, 62px); }
.kicker {
  margin: 0 0 16px;
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--teal);
}
.section h2 {
  font-size: clamp(30px, 4.4vw, 52px);
  letter-spacing: -0.01em;
}
.section__head p {
  margin: 20px 0 0;
  color: var(--muted);
  font-size: clamp(15px, 1.4vw, 18px);
}

/* --- 2. How mining works ------------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: clamp(16px, 2.2vw, 26px);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: step;
}
.step { height: 100%; }
.step .framed__in {
  padding: clamp(28px, 3vw, 40px);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.step__icon { color: var(--teal); }
.step__n {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 12px;
  letter-spacing: 0.26em;
  color: var(--faint);
}
.step h3 { font-size: clamp(20px, 2vw, 25px); }
.step p { margin: 0; color: var(--muted); font-size: 15px; }
.step__tag {
  margin-top: auto;
  padding-top: 18px;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--teal);
  border-top: 1px solid var(--line);
}

/* The plain-spoken line under the lore. Deliberately quiet, deliberately
   present: the tangle is the story, the card game is the product. */
.note {
  max-width: 68ch;
  margin: clamp(30px, 4vw, 46px) 0 0;
  padding-left: 16px;
  border-left: 2px solid var(--teal);
  color: var(--faint);
  font-size: 14.5px;
}

/* --- 3. Roster ----------------------------------------------------------- */

.filters {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: clamp(30px, 4vw, 48px);
}
.filters__row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
.filters__label {
  font-size: 11px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--faint);
  width: 68px;
  flex: none;
}

/* --- finish tabs (roster) ------------------------------------------------ */

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.tab {
  --c: 10px;
  padding: 13px 26px;
  border: 0;
  background: rgba(255, 255, 255, 0.06);
  color: var(--muted);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.16s, background 0.16s;
}
.tab:hover { color: var(--ink); background: rgba(255, 255, 255, 0.12); }
.tab.is-current {
  color: #04120e;
  background: var(--teal);
}
.tabs__note {
  max-width: 68ch;
  margin: 0 0 clamp(26px, 3.5vw, 40px);
  font-size: 14px;
  color: var(--faint);
}

/* Chamfered like everything else, so no border: clip-path would cut its
   corners off and leave slivers. State is carried by fill and text color. */
.pill {
  --c: 9px;
  padding: 10px 18px;
  border: 0;
  background: rgba(255, 255, 255, 0.06);
  color: var(--muted);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.16s, background 0.16s;
}
.pill:hover { color: var(--ink); background: rgba(255, 255, 255, 0.12); }
.pill[aria-pressed="true"] {
  color: var(--pill, var(--teal));
  background: color-mix(in srgb, var(--pill, var(--teal)) 20%, transparent);
}

/* A type or class with nothing surfaced yet is DIMMED, never hidden. The
   roster should read as a world with room to grow, not as a complete set —
   twelve classes exist whether or not we have mined one of each. */
.pill.is-empty {
  color: rgba(238, 243, 251, 0.22);
  background: rgba(255, 255, 255, 0.025);
  cursor: default;
}
.pill.is-empty:hover {
  color: rgba(238, 243, 251, 0.22);
  background: rgba(255, 255, 255, 0.025);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: clamp(20px, 2.6vw, 34px);
}
.grid .tilt-scene { max-width: 400px; }

/* --- pager ---------------------------------------------------------------
   Drawn above and below the grid, because a list 50 cards tall is a list you
   reach the bottom of and then have to scroll back up to leave. Chamfered
   like the rest of the interface; cards are the only rounded things here. */

.pager {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 22px 0;
}
.pager__nums { display: flex; flex-wrap: wrap; gap: 6px; }

.pager__step,
.pager__num {
  --c: 7px;
  min-width: 38px;
  padding: 8px 12px;
  border: 0;
  background: rgba(255, 255, 255, 0.07);
  color: var(--ink);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.1em;
  cursor: pointer;
  transition: background 0.16s, color 0.16s;
}
.pager__step { text-transform: uppercase; letter-spacing: 0.15em; }
.pager__step:hover:not(:disabled),
.pager__num:hover:not(.is-current) { background: rgba(255, 255, 255, 0.14); }
.pager__step:disabled { opacity: 0.35; cursor: not-allowed; }

.pager__num.is-current {
  background: var(--teal);
  color: #04120e;
  cursor: default;
}
.pager__gap { padding: 0 2px; color: var(--faint); }

/* Pushed to the far end: it is a readout, not a control. */
.pager__count {
  margin-left: auto;
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--faint);
}
@media (max-width: 620px) {
  .pager__count { margin-left: 0; width: 100%; }
}

.empty {
  padding: 60px 0;
  color: var(--faint);
  font-size: 15px;
}

/* ==========================================================================
   Daglabs — the catalogue
   Every species keeps its cell whether it is lit or dark, so a dark entry has
   to be the same SIZE as a lit one. The chips and the width scale sit in the
   cell under the card and are simply absent on a dark one; the hint line
   takes their place, which is why it is given the same margin.
   ========================================================================== */

.labcount {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal);
}

.labcell { display: flex; flex-direction: column; gap: 10px; }
.labcell .tilt-scene { max-width: 400px; }

/* NO filter on a dark cell. The silhouette is produced by a filter plus a
   mix-blend-mode INSIDE the card (see .dc-card--silhouette in card.css), and
   a filter on an ancestor creates a containing block that changes what that
   blend composites against — the shape washes out or disappears entirely.
   The silhouette is already colourless; it needs no help sitting back. */
.labcell__hint {
  margin: 0;
  font-size: 12.5px;
  font-style: italic;
  letter-spacing: 0.04em;
  color: var(--faint);
}

/* --- finishes held ------------------------------------------------------- */

.labchips { display: flex; flex-wrap: wrap; gap: 6px; }
.labchip {
  --c: 5px;
  padding: 4px 9px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  clip-path: polygon(
    var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c),
    100% calc(100% - var(--c)), calc(100% - var(--c)) 100%,
    var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c)
  );
}
/* Held chips carry the finish's own colour. Red and gold are chain colours
   here in the sense CLAUDE.md protects — they name the red/gold FINISHES,
   which is exactly what that reservation is for. */
.labchip.is-held { color: var(--ink); border-color: currentColor; }
.labchip--plain.is-held { color: #6ab6ff; background: rgba(106, 182, 255, 0.12); }
.labchip--holo.is-held { color: #7fe9d6; background: rgba(127, 233, 214, 0.12); }
.labchip--red.is-held { color: var(--chain-red); background: rgba(255, 90, 90, 0.12); }
.labchip--gold.is-held { color: #f2c94c; background: rgba(242, 201, 76, 0.13); }

/* --- widths held --------------------------------------------------------
   The same 1–16 scale the footer draws, at cell scale. Bars are sized by
   level so the shape of the scale is the same object in both places. */

.labscale {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 26px;
}
.labscale__n {
  flex: 1;
  height: var(--h);
  min-width: 3px;
  background: rgba(238, 243, 251, 0.07);
  border: 1px solid rgba(238, 243, 251, 0.1);
}
/* Outside the species' band: not "not yet", but "never". Drawn as a floor
   mark so the gap is visible without reading as something still to collect. */
.labscale__n.is-out {
  height: 12%;
  background: none;
  border-color: rgba(238, 243, 251, 0.06);
}
.labscale__n.is-held {
  background: rgba(73, 224, 192, 0.55);
  border-color: var(--teal);
  box-shadow: 0 0 6px rgba(73, 224, 192, 0.4);
}

/* --- connect prompt ------------------------------------------------------
   Sits above a grid that is already full of silhouettes, so it explains
   rather than apologises: the page is working, nothing is lit yet. */

.labprompt { max-width: 640px; margin: 0 0 clamp(22px, 3vw, 34px); }
.labprompt .framed__in { padding: clamp(20px, 3vw, 30px); }
.labprompt h3 { margin: 0 0 8px; font-size: clamp(18px, 2.2vw, 22px); }
.labprompt p { margin: 0 0 18px; color: var(--muted); font-size: 14.5px; }

/* --- the reveal ----------------------------------------------------------
   The card's own bloom is dc-surface, in card.css — the component owns its
   art. These are the flecks coming off it: the same square block, teal and
   glowing, as the pack opening's embers (css/open.css), falling away instead
   of rising. Same vocabulary, opposite direction. */

.labreveal {
  position: absolute;
  inset: 0;
  z-index: 3;
  overflow: visible;
  pointer-events: none;
}
.labcell { position: relative; }
.labreveal i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  height: var(--s);
  background: #9ffbe6;
  box-shadow: 0 0 6px rgba(73, 224, 192, 0.9);
  animation: labs-fleck var(--dur) ease-out var(--delay) both;
}
@keyframes labs-fleck {
  0%   { opacity: 0; transform: translate(0, 0) scale(0.5); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--dx), var(--dy)) scale(0.25); }
}
@media (prefers-reduced-motion: reduce) {
  .labreveal { display: none; }
}

/* --- 4. Finishes --------------------------------------------------------- */

.finishes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: clamp(20px, 2.4vw, 32px);
}
/* Direct children only. A descendant selector here reaches INSIDE the card
   component — the card's name is an h3 and its subtitle a p, and `.finish h3`
   outranks `.dc-name__name`, which silently resized and re-margined the card
   until the panel overflowed. Page CSS must never style card internals. */
.finish > h3 {
  margin: 22px 0 8px;
  font-size: 18px;
  letter-spacing: 0.04em;
}
.finish > p { margin: 0; color: var(--muted); font-size: 14.5px; }
.finish--red h3 { color: var(--chain-red); }
.finish--gold h3 { color: #f2c94c; }

/* --- 5. The tangle ------------------------------------------------------- */

.strip {
  position: relative;
  overflow: hidden;
  /* Darker band, still translucent so the field carries through it. */
  background: rgba(4, 7, 12, 0.72);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: clamp(76px, 11vh, 132px) 0;
}
.strip__copy { position: relative; z-index: 2; max-width: 68ch; }
.strip p {
  margin: 0 0 20px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: clamp(20px, 2.5vw, 31px);
  line-height: 1.35;
  letter-spacing: -0.005em;
}
.strip p:last-child {
  margin: 0;
  font-family: "IBM Plex Sans", system-ui, sans-serif;
  font-size: clamp(15px, 1.4vw, 17px);
  line-height: 1.6;
  color: var(--muted);
}

/* The red hint: the blocks the chain nearly threw away. This is the ONLY red
   on the page — the chain's warning colour, and it drifts rather than
   flickers so it reads as part of the same void, just the wrong colour. */
.glitch { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.glitch i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--s);
  height: var(--s);
  background: rgba(255, 90, 90, 0.09);
  border: 1px solid rgba(255, 90, 90, 0.42);
  opacity: 0;
  will-change: transform, opacity;
  animation: reddrift var(--dur) linear var(--delay) infinite;
}
@keyframes reddrift {
  0%   { opacity: 0; transform: translate3d(0, 30px, 0); }
  22%  { opacity: 0.5; }
  78%  { opacity: 0.5; }
  100% { opacity: 0; transform: translate3d(var(--dx), -70px, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .glitch i { animation: none; opacity: 0.45; }
}

/* ==========================================================================
   6. Footer
   ========================================================================== */

.foot { padding: clamp(60px, 8vh, 96px) 0 48px; }

.scale__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 16px;
}
.scale__head h3 {
  font-size: 13px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}
.scale__note { font-size: 13px; color: var(--faint); }

.scale {
  display: flex;
  align-items: flex-end;
  gap: clamp(3px, 0.7vw, 8px);
  height: 92px;
}
.scale div {
  flex: 1;
  background: linear-gradient(
    to top,
    rgba(73, 224, 192, 0.5),
    rgba(73, 224, 192, 0.14)
  );
  border-top: 2px solid var(--teal);
  height: var(--h);
  position: relative;
}
.scale div::after {
  content: attr(data-n);
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--faint);
}
.scale div:not(:first-child):not(:last-child)::after { content: ""; }

.foot__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-top: 58px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}
.foot__links { display: flex; gap: 26px; }
.foot__links a { text-decoration: none; }
.foot__links a:hover { color: var(--teal); }
.foot__built { color: var(--teal); }

/* ==========================================================================
   Wallet control + My Deck
   "Wallet" is product vocabulary, not lore — this is the one corner of the
   site that talks about owning, not about the tangle.
   ========================================================================== */

.nav__end {
  display: flex;
  align-items: center;
  gap: clamp(10px, 2vw, 26px);
}

.wallet { display: flex; align-items: center; gap: 10px; }

.wallet__btn {
  --c: 8px;
  padding: 11px 20px;
  border: 0;
  background: var(--teal);
  color: #04120e;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 0.16s, opacity 0.16s;
}
.wallet__btn:hover { background: #63efd0; }
.wallet__btn:disabled { opacity: 0.6; cursor: default; }

.wallet__addr {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--teal);
  padding: 8px 12px;
  background: color-mix(in srgb, var(--teal) 12%, transparent);
}
.wallet__off {
  border: 0;
  background: none;
  padding: 6px 4px;
  color: var(--faint);
  font: inherit;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
}
.wallet__off:hover { color: var(--ink); }

@media (max-width: 720px) {
  .nav__links { display: none; }
  .wallet__off { display: none; }
}

/* ==========================================================================
   Card viewer stage (js/card-viewer.js)
   The showcase's fly-in measures where a card IS and transforms back to
   there, so a card built for looking at needs somewhere real to start from.
   Invisible, inert, and at the middle of the viewport so the fly-in reads as
   the card growing rather than arriving from a corner.
   ========================================================================== */

.cardviewer-stage {
  position: fixed;
  left: 50%;
  top: 50%;
  width: 220px;
  transform: translate(-50%, -50%);
  opacity: 0;
  pointer-events: none;
  z-index: 1;
}

/* ==========================================================================
   Sort control
   ========================================================================== */

.sortbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 18px;
}
.sortbar__group { display: flex; flex-wrap: wrap; gap: 6px; }
.sortbar__label {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faint);
}
.sortbar .pill { padding: 7px 14px; font-size: 11px; }

/* ==========================================================================
   Deck builder
   ========================================================================== */

.builder__bar { margin-bottom: 18px; }
.builder__bar .framed__in {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: clamp(16px, 2.2vw, 22px);
}
/* A column flex container stretches its children, which turns the one CTA in
   the empty state into a bar across the panel. The rows below still want the
   full width, so this is per-button rather than align-items on the column. */
.builder__bar .framed__in > .btn { align-self: flex-start; }
.builder__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.builder__row--status { justify-content: space-between; }
.builder__actions { display: flex; flex-wrap: wrap; gap: 6px; }
.builder__note { margin: 0; color: var(--muted); font-size: 14px; }

.builder__select {
  --c: 8px;
  flex: 1 1 260px;
  min-width: 0;
  padding: 11px 14px;
  border: 1px solid var(--line);
  background: var(--panel-2);
  color: var(--ink);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 14px;
}

/* The count and the verdict read as one object: a number and what it means. */
.builder__status {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 13.5px;
  color: var(--muted);
}
.builder__count {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 22px;
  letter-spacing: 0.04em;
}
.builder__status.is-ok .builder__count { color: var(--teal); }
/* Amber, not chain red — an unfinished deck is a work in progress, not an
   error, and red is reserved for chain references. */
.builder__status.is-bad .builder__count { color: var(--t-surge); }

.btn.is-on { background: var(--teal); color: #04120e; }

/* --- panes --------------------------------------------------------------- */

.builder__panes {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(18px, 2.4vw, 30px);
  align-items: start;
}
.pane { min-width: 0; }
.pane__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.pane__head h3 { font-size: clamp(17px, 2vw, 21px); }
.pane__count {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 14px;
  letter-spacing: 0.06em;
  color: var(--faint);
}
.pane__count.is-ok { color: var(--teal); }
.pane__count.is-bad { color: var(--t-surge); }

/* The sticky count only exists for the stacked layout, where the deck pane
   is a scroll away from the collection you are adding from. */
.builder__sticky { display: none; }

@media (max-width: 1080px) {
  .builder__panes { grid-template-columns: 1fr; }
  .builder__sticky {
    position: sticky;
    top: 0;
    z-index: 6;
    display: flex;
    align-items: baseline;
    gap: 10px;
    margin-bottom: 14px;
    padding: 10px 14px;
    background: rgba(7, 11, 18, 0.92);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border-bottom: 1px solid var(--line);
  }
  .builder__sticky b {
    font-family: "Chakra Petch", system-ui, sans-serif;
    font-size: 20px;
  }
  .builder__sticky span { font-size: 13px; color: var(--muted); }
  .builder__sticky.is-ok b { color: var(--teal); }
  .builder__sticky.is-bad b { color: var(--t-surge); }
}

/* --- cards in the panes -------------------------------------------------- */

.dkgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(clamp(104px, 13vw, 150px), 1fr));
  gap: 12px;
}

.dkcard { position: relative; min-width: 0; }
.dkcard .tilt-scene { position: relative; }
.dkcard__serial {
  margin: 5px 0 0;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 9.5px;
  letter-spacing: 0.1em;
  color: var(--faint);
  text-align: center;
}
/* A card already in the deck stays VISIBLE in the collection — hiding it
   makes "where did that card go" unanswerable — and is marked instead. */
.dkcard.is-in .tilt-scene { opacity: 0.55; }
.dkcard__in,
.dkcard__trade {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  padding: 3px 8px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}
/* Sits low, over the stats block: the name chip at the top of a card this
   small is the only thing making it identifiable, and covering that to say
   "in deck" trades the answer for the label. */
.dkcard__in {
  bottom: 26%;
  background: var(--teal);
  color: #04120e;
}
.dkcard__trade {
  bottom: 8px;
  background: rgba(7, 11, 18, 0.9);
  border: 1px solid var(--line);
  color: var(--muted);
}
.dkcard__view {
  position: absolute;
  top: 4px;
  right: 4px;
  z-index: 5;
  padding: 2px 7px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(6, 10, 18, 0.88);
  color: var(--ink);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.dkcard .tilt-scene:hover .dkcard__view,
.dkcard__view:focus-visible { opacity: 1; }
.dkcard__view:hover { background: rgba(73, 224, 192, 0.2); }
/* No hover on touch, so the control has to be permanently visible there. */
@media (hover: none) {
  .dkcard__view { opacity: 0.85; }
}
.dkcard--gone {
  display: grid;
  place-items: center;
  aspect-ratio: 5 / 7;
  border: 1px dashed var(--line);
  color: var(--faint);
  font-size: 11px;
}

/* --- cards the wallet no longer holds ------------------------------------ */

.dkgone {
  margin-bottom: 18px;
  padding: 14px 16px;
  border-left: 2px solid var(--t-surge);
  background: rgba(255, 210, 63, 0.07);
}
.dkgone h4 {
  margin: 0 0 4px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 14px;
  color: #ffe9a8;
}
.dkgone p { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.dkgone__list { display: flex; flex-direction: column; gap: 6px; }
.dkgone__row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 7px 10px;
  background: rgba(255, 255, 255, 0.03);
}
.dkgone__name { flex: 1 1 auto; font-size: 13px; }
.dkgone__serial {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--faint);
}

/* --- grouped deck pane --------------------------------------------------- */

.dkgroup {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 18px 0 10px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.dkgroup__n {
  padding: 1px 7px;
  background: rgba(255, 255, 255, 0.07);
  font-size: 11px;
  letter-spacing: 0.06em;
}

/* --- summary ------------------------------------------------------------- */

.dksummary { margin-top: 20px; }
.dksummary .framed__in {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: clamp(16px, 2.2vw, 22px);
}
.dksummary h4 {
  margin: 0;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 13px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}
.dkstat__title {
  margin: 0 0 8px;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--faint);
}
.dkstat__row {
  display: grid;
  grid-template-columns: 72px 1fr 28px;
  align-items: center;
  gap: 10px;
  margin-bottom: 5px;
  font-size: 12.5px;
}
.dkstat__key { color: var(--muted); }
.dkstat__bar {
  height: 9px;
  background: linear-gradient(
    90deg,
    var(--tone) 0 var(--w),
    rgba(255, 255, 255, 0.05) var(--w) 100%
  );
}
.dkstat__n {
  font-family: "Chakra Petch", system-ui, sans-serif;
  text-align: right;
  color: var(--ink);
}

/* The same 1-16 scale as the footer and Daglabs, at summary scale. */
.dkcurve {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 52px;
}
.dkcurve i {
  flex: 1;
  height: var(--h);
  background: rgba(255, 255, 255, 0.06);
}
.dkcurve i.is-on {
  background: rgba(73, 224, 192, 0.5);
  border-top: 1px solid var(--teal);
}
.dkcurve__ends {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--faint);
}

.dkshape { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.dkshape__cell {
  padding: 10px;
  background: rgba(255, 255, 255, 0.03);
  border-top: 2px solid var(--tone);
  text-align: center;
}
.dkshape__cell b {
  display: block;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 22px;
  color: var(--ink);
}
.dkshape__cell span { font-size: 11px; color: var(--faint); }

/* --- empty state --------------------------------------------------------- */

.deck-empty { max-width: 640px; }
.deck-empty .framed__in {
  padding: clamp(32px, 4vw, 52px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 18px;
}
.deck-empty h3 { font-size: clamp(19px, 2vw, 24px); max-width: 26ch; }
.deck-empty p { margin: 0; color: var(--muted); font-size: 15px; max-width: 46ch; }
.deck-empty .btn { margin-top: 6px; }

.deck-empty__mark {
  width: 18px;
  height: 18px;
  background: var(--teal);
  box-shadow: 0 0 16px rgba(73, 224, 192, 0.55);
}

/* --- holdings ------------------------------------------------------------ */

.deck-cell { max-width: 400px; }
.deck-cell__serial {
  margin: 12px 0 0;
  text-align: center;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--faint);
}
/* Dev-only banner: the derivatives on disk are older than their source art,
   so the page is showing something stale. Only ever appears when served by
   tools/serve.py, which is the only thing that answers /__assets.json. */
.stalebar {
  position: relative;
  z-index: 80;
  padding: 10px 18px;
  background: #3a2a06;
  border-bottom: 1px solid #7a5c10;
  color: #ffe3a3;
  font-size: 13px;
  letter-spacing: 0.02em;
  text-align: center;
}
.stalebar strong { color: #ffd166; }
.stalebar code {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  background: rgba(0, 0, 0, 0.35);
  padding: 2px 7px;
}
/* ==========================================================================
   Trading
   Copy rule: offers and swaps. Neither side pays; nothing is bought or sold.
   ========================================================================== */

.tradebar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
  margin-bottom: clamp(24px, 3vw, 36px);
}
.tradebar__mine { font-size: 13px; color: var(--faint); }

/* Dev-only: stands in for a second person. Never ships. */
.devbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 22px;
  padding: 9px 14px;
  background: rgba(73, 224, 192, 0.07);
  border-left: 2px solid var(--teal);
  font-size: 12px;
  color: var(--muted);
}
.devbar strong { color: var(--teal); letter-spacing: 0.16em; font-size: 11px; }
.devbar__btn {
  --c: 6px;
  border: 0;
  padding: 5px 12px;
  background: rgba(255, 255, 255, 0.07);
  color: var(--muted);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}
.devbar__btn.is-current { background: var(--teal); color: #04120e; font-weight: 600; }
.devbar__note { color: var(--faint); }

/* --- board --------------------------------------------------------------- */

.listings { display: grid; gap: clamp(16px, 2vw, 24px); }
.listing .framed__in {
  padding: clamp(20px, 2.4vw, 30px);
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(18px, 2.4vw, 32px);
}
@media (max-width: 860px) {
  .listing .framed__in { grid-template-columns: 1fr; }
}
.listing__head {
  grid-column: 1 / -1;
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--faint);
}
.listing__who { font-family: ui-monospace, Consolas, monospace; color: var(--teal); }
.listing__cards { display: flex; flex-wrap: wrap; gap: 12px; }
.listing__seeking p { margin: 4px 0 0; color: var(--ink); font-size: 15px; }
.listing__label {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--faint);
}

/* --- mini cards ---------------------------------------------------------- */

.mini { width: 118px; }
.mini .dc-card { width: 118px; }
.mini__serial {
  margin: 6px 0 0;
  text-align: center;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 9px;
  letter-spacing: 0.08em;
  color: var(--faint);
}
.mini--gone {
  width: 118px;
  padding: 20px 8px;
  background: rgba(255, 255, 255, 0.04);
  font-size: 10px;
  color: var(--faint);
  text-align: center;
}
.mini[role="button"] { cursor: pointer; }
.mini[role="button"] .dc-card { transition: transform 0.14s ease-out; }
.mini[role="button"]:hover .dc-card { transform: translateY(-4px); }
.mini.is-selected .dc-card { outline: 2px solid var(--teal); outline-offset: 3px; }
.mini.is-selected .mini__serial { color: var(--teal); }

.picker {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: clamp(22px, 3vw, 32px);
}

/* The picker pages, but a selection does not — so say how many are held,
   or paging away from your chosen cards reads as losing them. */
.picker__tally {
  margin: 0 0 4px;
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--teal);
}

/* --- create -------------------------------------------------------------- */

.createform { max-width: 620px; }
.createform .framed__in { padding: clamp(22px, 2.6vw, 32px); }
.createform__label {
  display: block;
  margin-bottom: 10px;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}
.createform__input {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--line);
  background: rgba(0, 0, 0, 0.35);
  color: var(--ink);
  font: inherit;
}
.createform__input:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }
.createform__count {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  color: var(--faint);
}
.createform__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }

/* --- trade room ---------------------------------------------------------- */

.statusbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: clamp(20px, 2.6vw, 30px);
  padding: 13px 18px;
  background: rgba(255, 255, 255, 0.045);
  border-left: 3px solid var(--faint);
  font-size: 14.5px;
}
.statusbar__dot { width: 8px; height: 8px; background: currentColor; flex: none; }
.statusbar--good { border-left-color: var(--teal); color: var(--teal); }
.statusbar--act { border-left-color: var(--teal); color: var(--teal); }
.statusbar--warn { border-left-color: #ffd166; color: #ffd166; }
.statusbar--bad { border-left-color: var(--chain-red); color: var(--chain-red); }
.statusbar--good span:last-child,
.statusbar--act span:last-child,
.statusbar--warn span:last-child,
.statusbar--bad span:last-child { color: var(--ink); }

.room {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 2vw, 26px);
}
@media (max-width: 800px) { .room { grid-template-columns: 1fr; } }

.sidepanel .framed__in { padding: clamp(18px, 2.2vw, 26px); height: 100%; }
.sidepanel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.sidepanel__head h3 { font-size: 15px; letter-spacing: 0.2em; text-transform: uppercase; }
.sidepanel__who {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 11px;
  color: var(--faint);
}
.sigstate {
  margin: 12px 0 16px;
  display: inline-block;
  padding: 5px 12px;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: rgba(255, 255, 255, 0.05);
  color: var(--faint);
}
.sigstate.is-signed { background: color-mix(in srgb, var(--teal) 18%, transparent); color: var(--teal); }
.sidepanel__cards { display: flex; flex-wrap: wrap; gap: 14px; }
.sidepanel__none { margin: 0; color: var(--faint); font-size: 14px; }
.sidepanel__slot { display: flex; flex-direction: column; align-items: center; gap: 6px; }

.chipbtn {
  --c: 5px;
  border: 0;
  padding: 4px 10px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--muted);
  font: inherit;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}
.chipbtn:hover { background: rgba(255, 255, 255, 0.16); color: var(--ink); }

.room__actions,
.room__done { display: flex; flex-wrap: wrap; gap: 14px; margin-top: clamp(22px, 3vw, 32px); }

.attach { margin-top: clamp(28px, 3.5vw, 44px); }
.attach__title {
  margin-bottom: 14px;
  font-size: 13px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}

/* The settlement moment: both sides visibly cross before the panels
   re-render with the cards swapped. */
.room--swapping .sidepanel--maker { animation: swap-left 720ms ease-in-out; }
.room--swapping .sidepanel--taker { animation: swap-right 720ms ease-in-out; }
@keyframes swap-left {
  0% { transform: translate3d(0, 0, 0); }
  45% { transform: translate3d(14%, -8px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}
@keyframes swap-right {
  0% { transform: translate3d(0, 0, 0); }
  45% { transform: translate3d(-14%, 8px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .room--swapping .sidepanel--maker,
  .room--swapping .sidepanel--taker { animation: none; }
}

/* --- My Deck: in-trade badge --------------------------------------------- */

.deck-cell--locked .tilt-scene { position: relative; }
.intrade {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  padding: 5px 12px;
  background: rgba(10, 14, 22, 0.92);
  border: 1px solid var(--teal);
  color: var(--teal);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  pointer-events: none;
}
.deck-cell--locked .dc-card { opacity: 0.82; }
/* ==========================================================================
   THE STORY — the scrolling lore below the hero.

   Every section is translucent so the one shared block field carries through
   all of them; the colour story is a tint laid OVER that field, not a
   replacement ground. void -> void -> red -> gold -> violet -> void, so the
   scroll itself tells you where you are before you read a word.

   Voice rule these carry: the chain mechanics are all here and all true, and
   none of them are named. A Kaspa reader recognises consensus, orphaned
   blocks and block width; everyone else just hears a world.
   ========================================================================== */

.story { position: relative; overflow: hidden; }

/* Card one side, story the other. The CARD IS FIRST IN THE DOM on purpose:
   mobile stacks card-above-copy, and source order is what gives that for
   free. Desktop alternation is done by placing the grid items instead of by
   reordering, so the reading order never depends on the viewport. */
.story__split {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(30px, 5vw, 76px);
  align-items: center;
}
.story__card { grid-column: 1; grid-row: 1; margin: 0; justify-self: center; width: min(360px, 100%); }
.story__copy { grid-column: 2; grid-row: 1; max-width: 58ch; }
.story--flip .story__card { grid-column: 2; }
.story--flip .story__copy { grid-column: 1; }

.story__copy h2 { margin: 0 0 22px; }
.story__copy p {
  margin: 0 0 18px;
  color: var(--muted);
  font-size: clamp(15px, 1.35vw, 17.5px);
  line-height: 1.65;
}
.story__copy p:last-child { margin-bottom: 0; }
/* The line that lands the section. Lifted out of the body colour so it reads
   as the closing beat rather than another paragraph. */
/* The beat after "almost". A link, because it is pointing somewhere — the
   underline is the only thing saying so, since the line is one word. */
.story__link {
  color: var(--ink);
  text-decoration-color: rgba(176, 140, 240, 0.7);
  text-underline-offset: 0.22em;
  transition: color 0.16s, text-decoration-color 0.16s;
}
.story__link:hover {
  color: #c9a6ff;
  text-decoration-color: #b08cf0;
}

.story__close {
  color: var(--ink);
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: clamp(17px, 1.7vw, 21px) !important;
  line-height: 1.4 !important;
}

/* --- the tints ---------------------------------------------------------- */

/* Red: the void running the wrong colour. Sits under the content, over the
   field, and is pure paint -- nothing here animates. */
.story--red::before,
.story--gold::before,
.story--rumor::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}
.story--red::before {
  background:
    radial-gradient(120% 90% at 50% 40%, rgba(255, 64, 64, 0.11), transparent 62%),
    linear-gradient(180deg, rgba(60, 6, 10, 0.34), rgba(28, 4, 8, 0.5));
}
.story--gold::before {
  background:
    radial-gradient(110% 85% at 50% 38%, rgba(242, 201, 76, 0.1), transparent 60%),
    linear-gradient(180deg, rgba(48, 36, 6, 0.3), rgba(24, 18, 4, 0.46));
}
/* Violet at the EDGES only, so the middle stays genuinely dark and the
   section reads as mostly nothing -- which is the point of it. */
.story--rumor::before {
  background:
    radial-gradient(70% 60% at 50% 50%, transparent 38%, rgba(140, 72, 220, 0.14) 100%),
    linear-gradient(180deg, rgba(10, 4, 20, 0.62), rgba(6, 3, 14, 0.78));
}
.story > .wrap { position: relative; z-index: 1; }
.story--red .glitch { z-index: 0; }

/* --- the rumor ----------------------------------------------------------- */

.story--rumor { padding: clamp(150px, 26vh, 300px) 0; }
/* --- the names -----------------------------------------------------------
   A short block directly under the hero, answering the two words the hero
   just used. Set quieter and narrower than a section head on purpose: it is
   a footnote to the hero, not the page's second argument. */
.names-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: center;
}
.names { max-width: 58ch; }
.names__line {
  margin: 0;
  color: var(--muted);
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.7;
}

/* ==========================================================================
   The chain record — a card and its on-chain record, wired together
   ========================================================================== */

.mined-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
/* The head's own bottom margin is the gap between a section head and its
   content; inside this grid the gap does that job. */
.mined-grid .section__head { margin-bottom: 0; }

.record {
  position: relative;
  display: grid;
  grid-template-columns: clamp(124px, 14vw, 172px) minmax(0, 1fr);
  gap: clamp(26px, 3.4vw, 54px);
  align-items: center;
}
/* Slightly off-square, so it reads as a specimen laid on a bench rather than
   a product shot. The pointer tilt still runs inside it — separate element,
   separate transform. */
.record__card { transform: rotate(-4deg); }

/* The wires sit over everything and catch nothing. overflow:visible so a line
   that leaves the box on its way round is not clipped. */
.record__wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 2;
  overflow: visible;
  pointer-events: none;
}
.record__wire {
  fill: none;
  stroke: rgba(73, 224, 192, 0.26);
  stroke-width: 1;
}
.record__dot { fill: var(--teal); }

/* One pulse, once, after the rows have finished typing. The dash is a short
   segment chased along the whole path by its offset; --len is the path's own
   length, measured in js/home.js. */
.record__pulse {
  fill: none;
  stroke: var(--teal);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-dasharray: 16 9999;
  opacity: 0;
}
#mined.is-in .record__pulse {
  animation: record-pulse 1100ms ease-out 980ms both;
}
@keyframes record-pulse {
  0% { opacity: 0; stroke-dashoffset: 16px; }
  10% { opacity: 1; }
  88% { opacity: 1; }
  100% { opacity: 0; stroke-dashoffset: calc(var(--len, 400px) * -1); }
}

/* --- the panel ----------------------------------------------------------- */

.record__side { min-width: 0; }
.record__panel .framed__in { padding: clamp(14px, 1.7vw, 20px) clamp(15px, 1.9vw, 22px); }
.record__title {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 14px;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}
/* The same block the void field and the footer scale are made of, at the
   size of a bullet. */
.record__hex {
  flex: 0 0 auto;
  width: 10px;
  height: 11px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.record__rows {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 7px clamp(14px, 1.6vw, 22px);
  margin: 0;
  /* Monospace is not decoration here: the type-in below is a width animation
     in `ch`, which is only exact in a fixed-pitch font. */
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(10.5px, 1vw, 12.5px);
  line-height: 1.5;
}
.record__rows dt {
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
}
.record__rows dd {
  margin: 0;
  min-width: 0;
  color: var(--ink);
}
/* Not wired to a chain yet — dimmed and italic so it cannot be mistaken for
   a live reading. See the TODO in js/home.js. */
.record__rows dd.is-todo { color: var(--faint); font-style: italic; }

.record__val {
  display: inline-block;
  width: var(--ch);
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
}
/* Typed in on arrival, once. The width is already --ch without the
   animation, so switching it off leaves the rows simply present. */
#mined.is-in .record__val {
  animation: record-type 360ms steps(20, end) both;
  animation-delay: calc(140ms + var(--i, 0) * 95ms);
}
@keyframes record-type {
  from { width: 0; }
  to { width: var(--ch); }
}

.record__note {
  margin: 12px 0 0;
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: var(--faint);
}

@media (max-width: 1040px) {
  .mined-grid { grid-template-columns: 1fr; }
  .mined-grid .section__head { margin-bottom: 0; }
  /* Stacked: card above panel, and the wires go — there is nothing to run
     between when the two are one above the other. */
  .record {
    grid-template-columns: 1fr;
    justify-items: start;
    gap: clamp(20px, 4vw, 30px);
  }
  .record__wires { display: none; }
  .record__card { width: clamp(140px, 38vw, 190px); }
  /* The card shrinks to its own width; the panel must not — `justify-items:
     start` would otherwise leave it shrink-wrapped to the longest row. */
  .record__side { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  #mined.is-in .record__val { animation: none; }
  .record__pulse { display: none; }
}

/* --- the name fan --------------------------------------------------------
   Three real cards, overlapped and splayed. The species and finishes are
   fixed in index.html; this only places them.

   THREE TRANSFORM LAYERS, and they have to stay separate or the last one
   declared wins: the SLOT carries the fan (rotate + offset), the FLOAT
   carries the idle drift, and .tilt inside carries the pointer tilt. Putting
   any two on one element means the tilt cancels the fan, or the float does.
   The rotation is a custom property so the stacked layout can flatten it
   without !important. */
.namefan {
  --fan-w: clamp(116px, 13vw, 184px);
  display: flex;
  justify-content: center;
  align-items: center;
  /* Rotated boxes still occupy their unrotated footprint, so the corners
     need somewhere to go. */
  padding: clamp(16px, 2.6vw, 34px) 0;
}
.namefan__slot {
  flex: 0 0 auto;
  width: var(--fan-w);
  transform: rotate(var(--fan-rot, 0deg)) translateY(var(--fan-y, 0px));
}
.namefan__slot + .namefan__slot { margin-left: calc(var(--fan-w) * -0.4); }

/* Source order is blue, holo, red — so the holo sits in the middle and on
   top, and the colour split reads outward from it. */
.namefan__slot:nth-child(1) { --fan-rot: -8deg; --fan-y: 12px; z-index: 1; }
.namefan__slot:nth-child(2) { --fan-rot: 0deg;  --fan-y: -10px; z-index: 3; }
.namefan__slot:nth-child(3) { --fan-rot: 8deg;  --fan-y: 12px; z-index: 2; }

/* A few pixels over six seconds. The negative delays start the three at
   different points in the same cycle, so the fan breathes instead of the
   whole thing moving as one slab. */
.namefan__float { animation: namefan-float 6s ease-in-out infinite; }
.namefan__slot:nth-child(1) .namefan__float { animation-delay: -0.4s; }
.namefan__slot:nth-child(2) .namefan__float { animation-delay: -2.6s; }
.namefan__slot:nth-child(3) .namefan__float { animation-delay: -4.4s; }
@keyframes namefan-float {
  50% { transform: translateY(-7px); }
}

/* Stacked: the fan becomes a row under the text, smaller and flat. The
   overlap drops to a hair so it reads as three cards side by side rather
   than a splayed hand. */
@media (max-width: 900px) {
  .names-grid { grid-template-columns: 1fr; }
  .namefan {
    --fan-w: clamp(86px, 26vw, 130px);
    justify-content: flex-start;
    padding-bottom: 0;
  }
  .namefan__slot { --fan-rot: 0deg; --fan-y: 0px; }
  .namefan__slot + .namefan__slot { margin-left: calc(var(--fan-w) * -0.12); }
}

/* The float goes, and js/tilt.js already declines to attach the pointer tilt
   under the same query — so both halves of the movement stop together. */
@media (prefers-reduced-motion: reduce) {
  .namefan__float { animation: none; }
}

.rumor { max-width: 60ch; margin-inline: auto; text-align: center; }
.rumor .kicker { color: #b08cf0; }
.rumor__line {
  margin: 0;
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-size: clamp(21px, 2.8vw, 36px);
  line-height: 1.32;
  letter-spacing: -0.01em;
  color: rgba(238, 243, 251, 0.9);
}
.rumor__sig {
  margin: clamp(34px, 5vw, 60px) 0 0;
  font-size: 12.5px;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: rgba(176, 140, 240, 0.62);
}

/* --- the landing --------------------------------------------------------- */

.enter { max-width: 64ch; }
.enter h2 { margin: 0 0 20px; }
.enter__lede { margin: 0 0 30px; color: var(--muted); font-size: clamp(15px, 1.4vw, 18px); }
.enter .cta { display: flex; flex-wrap: wrap; gap: 14px; }

/* --- reveal on scroll ---------------------------------------------------- */

/* Opacity + a short lift, nothing that moves layout. The `.is-in` class is
   added by an IntersectionObserver; under reduced motion home.js adds it to
   everything up front and never observes, so there is no scroll coupling at
   all rather than a faster version of it. */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 620ms ease-out, transform 620ms ease-out;
}
[data-reveal].is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

@media (max-width: 880px) {
  .story__split { grid-template-columns: 1fr; }
  .story__card,
  .story__copy,
  .story--flip .story__card,
  .story--flip .story__copy { grid-column: 1; }
  .story__card { grid-row: 1; margin-bottom: clamp(24px, 5vw, 40px); }
  .story__copy { grid-row: 2; }
}

/* --- the evolution bands, under the width chart --------------------------
   One lineage shown against the 1-16 scale: the same creature surfacing from
   deeper tangles as something greater. The COLUMN WIDTHS ARE THE BANDS
   THEMSELVES -- 4fr / 5fr / 7fr for widths 1-4, 5-9, 10-16 -- so the chips
   line up with the chart above by construction and cannot drift from the
   data. home.js writes the template from each species' band.

   The accent warms as the bands deepen (cool teal -> amber -> hot), which is
   the progression cue: you can read the direction of the line from the colour
   before you read the labels. */
.bands__copy {
  max-width: 72ch;
  margin: clamp(26px, 3.4vw, 40px) 0 clamp(22px, 3vw, 34px);
  color: var(--muted);
  font-size: clamp(15px, 1.35vw, 17.5px);
  line-height: 1.65;
}

.bands {
  display: grid;
  gap: clamp(10px, 1.4vw, 20px);
  align-items: start;
}

.band {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: clamp(14px, 1.6vw, 20px) 10px 16px;
  background: none;
  border: 0;
  border-top: 1px solid var(--band-accent);
  color: inherit;
  font: inherit;
  text-align: center;
  cursor: pointer;
  transition: background 200ms ease;
}
.band::before {
  /* The tick that ties this band back to the scale: a short riser at the
     band's own left edge, i.e. the block it starts at. */
  content: "";
  position: absolute;
  left: 0;
  top: -1px;
  width: 1px;
  height: 11px;
  background: var(--band-accent);
}
.band:hover,
.band:focus-visible { background: rgba(255, 255, 255, 0.035); }
.band:focus-visible { outline: 2px solid var(--band-accent); outline-offset: 3px; }

/* --- lit by the chain above ---------------------------------------------
   Whichever stage covers the DAG's current width comes up; the other two go
   back. Opacity and a faint wash only — nothing that moves, because three
   chips shifting every couple of seconds beside a running animation is too
   much going on. Which stage is lit is decided in js/home.js from each
   chip's own band, never from a hardcoded range. */
.band {
  opacity: 1;
  transition: background 200ms ease, opacity 320ms ease;
}
.band.is-dim { opacity: 0.38; }
.band.is-lit { background: rgba(255, 255, 255, 0.04); }
.band.is-lit .band__chip {
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.5),
    0 0 18px color-mix(in srgb, var(--band-accent) 45%, transparent),
    0 10px 26px rgba(0, 0, 0, 0.45);
}
@media (prefers-reduced-motion: reduce) {
  .band { transition: none; }
}

.band__chip {
  position: relative;
  width: clamp(64px, 7vw, 92px);
  aspect-ratio: 1;
  border-radius: 12px;
  overflow: hidden;
  background: #05070c;
  border: 1px solid var(--band-accent);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5), 0 10px 26px rgba(0, 0, 0, 0.45);
}
.band__chip img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The real card, parked at the chip's exact box so the showcase's fly-in
   measures the chip and the card appears to grow out of it. Invisible while
   parked -- the showcase MOVES it into the overlay, out of this opacity, so
   it is only ever unseen here. pointer-events off: the button is the target
   and the click is forwarded in code. (opacity < 1 flattens preserve-3d, but
   only while parked, where nothing is drawn.) */
.band__host {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}

.band__name {
  font-family: "Chakra Petch", system-ui, sans-serif;
  font-weight: 700;
  font-size: clamp(13px, 1.25vw, 16px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--band-accent);
}
.band__w {
  font-size: 11px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--faint);
}

/* Mobile: chart above, chips stacked below in band order. The grid template
   is overridden here rather than in JS so the source order still carries it. */
@media (max-width: 720px) {
  .bands { grid-template-columns: 1fr !important; }
  .band {
    grid-template-columns: auto 1fr;
    justify-items: start;
    align-items: center;
    gap: 6px 16px;
    text-align: left;
    padding: 14px 0 16px;
  }
  .band__chip { grid-row: span 2; }
  .band__name { align-self: end; }
  .band__w { align-self: start; }
}
