/* ==========================================================================
   KØMNATA
   Monochrome. Rounded surfaces, pill controls, large light uppercase headings.
   No accent colour, no glows, no filters. Onest and JetBrains Mono only,
   used as supplied: size and weight do the work, nothing is treated.
   ========================================================================== */

@font-face{
  font-family:'Onest';
  src:url('../assets/fonts/Onest-VariableFont_wght.woff2') format('woff2'),
      url('../assets/fonts/Onest-VariableFont_wght.ttf') format('truetype');
  font-weight:100 900;font-style:normal;font-display:swap;
}
@font-face{
  font-family:'JetBrains Mono';
  src:url('../assets/fonts/JetBrainsMono-VariableFont_wght.woff2') format('woff2'),
      url('../assets/fonts/JetBrainsMono-VariableFont_wght.ttf') format('truetype');
  font-weight:100 800;font-style:normal;font-display:swap;
}

:root{
  --night:#0B0C0D;      /* page */
  --raised:#141618;     /* cards */
  --raised-2:#1A1D1F;   /* card hover */
  --bone:#EFECE6;       /* type */
  --mute:#8C908E;       /* body copy */
  --mute-2:#636866;     /* small labels */
  --cyan:#8DEEED;       /* brand accent, used once: the pin on the map */
  --line:rgba(239,236,230,.09);
  --line-2:rgba(239,236,230,.18);

  --sans:'Onest',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;

  --r:24px;             /* cards */
  --r-s:16px;           /* images, wells */
  --pill:999px;

  --gutter:clamp(20px,5vw,80px);
  --max:1360px;
  --bay:clamp(88px,11vw,164px);

  color-scheme:dark;
}

*,*::before,*::after{box-sizing:border-box;}

/* --- INPUT LOCKDOWN ----------------------------------------------------- */
/* This page is a poster, not a document. No pinch zoom, no double-tap zoom,
   no rubber band, no selecting the copy, no dragging an image out of it.

   touch-action:manipulation removes double-tap zoom and nothing else: panning
   on both axes survives, so the record rail still swipes. The effective value
   is the intersection down the tree, so .vinyl__disc keeps its own
   touch-action:none and its drag is untouched.

   The meta tag carries maximum-scale=1 and user-scalable=no, which Android
   honours. iOS Safari has ignored user-scalable since iOS 10, so the pinch is
   stopped there by the gesture handlers in main.js instead. */
html{
  -webkit-text-size-adjust:100%;background:var(--night);
  overscroll-behavior:none;
  touch-action:manipulation;
}
/* set while the popup is open. Lenis is stopped alongside it: this alone does
   not hold the page, because Lenis moves it with a transform of its own. */
html.is-locked{overflow:hidden;}
body{
  margin:0;background:transparent;color:var(--bone);
  font-family:var(--sans);font-size:16px;line-height:1.7;font-weight:400;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overflow-x:hidden;
  overscroll-behavior:none;
  -webkit-user-select:none;user-select:none;
  -webkit-touch-callout:none;   /* no long-press menu on links or images */
}
img,svg,video,canvas{-webkit-user-drag:none;}
img{max-width:100%;display:block;}
a{color:inherit;text-decoration:none;}
:focus-visible{outline:1px solid var(--bone);outline-offset:4px;}
::selection{background:var(--bone);color:var(--night);}

.shell{max-width:var(--max);margin-inline:auto;padding-inline:var(--gutter);width:100%;}

/* --- BEAMS -------------------------------------------------------------- */
.backdrop{
  position:fixed;inset:0;z-index:-1;pointer-events:none;
  opacity:0;                       /* JS scrubs this in across the Social section */
}
.backdrop canvas{display:block;width:100%;height:100%;}
/* No DOM edge-fade any more. The old beams needed one because the beam field
   was finite and stopped dead mid-screen; this shader vignettes itself in the
   last line of its own fragment pass, which also means the fade follows the
   colour instead of painting flat page-black over it. */

/* --- TYPE --------------------------------------------------------------- */
/* Onest, uppercase, one weight above body. Large and quiet, not shouted. */
.h2{
  margin:0;font-size:clamp(30px,4.4vw,62px);font-weight:500;
  line-height:1.06;letter-spacing:.004em;text-transform:uppercase;
}
.lede{
  margin:0;color:var(--mute);font-size:15.5px;line-height:1.75;max-width:52ch;
}

/* --- DRAWN HEADINGS ----------------------------------------------------- */
/* The section titles are artwork in the brand's own lettering, not type, so
   they ship as images cropped to their ink with nothing around it. Height is
   what drives the size and width follows: all five were exported at one
   shared scale, so a line of caps measures 115 to 118px in every file and a
   single height value reads the same across them. The 3px spread is the
   drawing's own, it is in the source artwork too.

   alt carries the words, so the heading is still a heading to a screen reader
   and to search. The reveal in main.js wraps whatever is inside and animates
   it, which works on an image exactly as it did on text. */
.h2--art{line-height:0;}
.h2--art img{
  display:block;width:auto;max-width:100%;
  height:clamp(24px,3.3vw,46px);
}
/* Two lines of lettering. Measured at 2.63x the one-line block, not guessed. */
.h2--art-2 img{height:clamp(63px,8.7vw,121px);}

.lede--sm{font-size:14.5px;max-width:42ch;}

.head{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(240px,340px);
  align-items:end;gap:clamp(20px,4vw,64px);
  margin-bottom:clamp(36px,4.6vw,64px);
}
.head .lede{padding-bottom:6px;}
@media (max-width:900px){
  .head{grid-template-columns:1fr;align-items:start;}
}

/* --- CONTROLS ----------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  padding:15px 30px;border-radius:var(--pill);border:1px solid transparent;
  background:var(--bone);color:var(--night);
  font-size:13.5px;font-weight:500;letter-spacing:.005em;white-space:nowrap;
  transition:background .25s ease,color .25s ease,border-color .25s ease;
}
.btn:hover{background:#fff;}
.btn--ghost{background:transparent;color:var(--bone);border-color:var(--line-2);}
.btn--ghost:hover{background:rgba(239,236,230,.06);border-color:var(--bone);}
.btn--sm{padding:11px 22px;font-size:13px;}
.btn--lg{padding:21px 56px;font-size:15px;}
.btn--wide{width:100%;}
.btn__dot{
  width:20px;height:20px;border-radius:50%;border:1px solid currentColor;
  display:grid;place-items:center;flex:none;opacity:.7;
}
.btn__dot::after{content:"";width:5px;height:5px;border-radius:50%;background:currentColor;}

/* --- NAV ---------------------------------------------------------------- */
/* Nothing but the links. The mark is already the size of the page below it
   and the ticket button lives in the hero, so neither is repeated up here. */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:60;height:72px;
  display:flex;align-items:center;justify-content:center;
  padding-inline:var(--gutter);background:transparent;
  transition:background .3s ease;
}
/* The bar itself stays transparent. The blur and the wash live on a pseudo
   behind the links, so the mask can fade them out without touching the type.
   It extends 26px past the bar's own box, which is where the fade happens:
   a mask that stopped at the bar's edge would just move the hard line down.
   The eased stops matter, a straight ramp leaves a visible knee. */
.nav::before{
  content:"";position:absolute;inset:0 0 -26px 0;z-index:-1;pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(11,12,13,.86) 0%, rgba(11,12,13,.72) 52%, rgba(11,12,13,0) 100%);
  -webkit-backdrop-filter:blur(16px) saturate(120%);
          backdrop-filter:blur(16px) saturate(120%);
  -webkit-mask-image:linear-gradient(to bottom,
    #000 0%, #000 44%, rgba(0,0,0,.82) 62%, rgba(0,0,0,.45) 80%, rgba(0,0,0,0) 100%);
          mask-image:linear-gradient(to bottom,
    #000 0%, #000 44%, rgba(0,0,0,.82) 62%, rgba(0,0,0,.45) 80%, rgba(0,0,0,0) 100%);
  opacity:0;transition:opacity .35s ease;
}
.nav.is-stuck::before{opacity:1;}
.nav__links{display:flex;gap:clamp(30px,6vw,90px);justify-content:center;}
.nav__links a{
  font-size:15.5px;color:var(--mute);padding:6px 2px;
  transition:color .25s ease;
}
.nav__links a:hover,.nav__links a[aria-current="true"]{color:var(--bone);}
@media (max-width:760px){
  /* 44px tap targets. These links are the only navigation on a phone and at
     6px of padding they measured 35px tall. The padding grows and the gap
     shrinks by the same amount, so the row is no wider than it was. */
  .nav__links{gap:clamp(6px,2vw,18px);}
  .nav__links a{font-size:13.5px;padding:13px 6px;}
}

/* --- HERO --------------------------------------------------------------- */
/* The mark sits at reading size in the middle of the page with one line under
   it. It is a wordmark, not a billboard. */
.hero{
  position:relative;min-height:100svh;
  display:grid;place-items:center;
  padding:110px var(--gutter) 90px;
  overflow:hidden;
}
.hero__video{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  /* The source is already graded dark and blurred. Dimming it again here
     would make it invisible. */
}
.hero__scrim{
  position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(11,12,13,.42) 0%,
    rgba(11,12,13,.10) 38%,
    rgba(11,12,13,.82) 88%,
    rgba(11,12,13,1) 100%);
}

/* The hero's bottom edge was a visible line, and darkening the video there did
   not fix it, because the problem is occlusion rather than colour. The video is
   an opaque rectangle sitting on top of a FIXED backdrop layer, so the backdrop
   was hidden for exactly the hero's height and then appeared, in full, along a
   perfectly straight edge. A step of only 4/765 still reads as a hard line when
   it runs the whole width at a fixed position.

   So the hero's own bottom is masked away instead. The video and its scrim fade
   their alpha out over the last 45%, which lets the backdrop come through
   gradually and makes the two cross-fade. The stops are eased rather than
   linear: a straight ramp puts a visible knee at each end. */
.hero__video,
.hero__scrim{
  -webkit-mask-image:linear-gradient(to bottom,
    #000 0%, #000 55%,
    rgba(0,0,0,.93) 66%, rgba(0,0,0,.74) 76%,
    rgba(0,0,0,.44) 86%, rgba(0,0,0,.17) 94%, rgba(0,0,0,0) 100%);
          mask-image:linear-gradient(to bottom,
    #000 0%, #000 55%,
    rgba(0,0,0,.93) 66%, rgba(0,0,0,.74) 76%,
    rgba(0,0,0,.44) 86%, rgba(0,0,0,.17) 94%, rgba(0,0,0,0) 100%);
}
.hero__inner{
  position:relative;display:flex;flex-direction:column;align-items:center;
  text-align:center;width:100%;
}
.hero__mark{width:min(66vw,430px);height:auto;}
.hero__slogan{
  margin:clamp(11px,1.3vw,17px) 0 0;
  font-size:clamp(14px,1.3vw,17px);color:var(--mute);letter-spacing:.005em;
}
.hero__buy{margin-top:clamp(34px,4.2vw,54px);}
.hero__meta{
  margin:clamp(16px,1.8vw,22px) 0 0;
  font-size:13px;color:var(--mute-2);letter-spacing:.01em;
}

.hero__down{
  position:absolute;left:50%;bottom:34px;translate:-50% 0;
  width:26px;height:26px;border-radius:50%;border:1px solid var(--line-2);
  display:grid;place-items:center;transition:border-color .25s ease;
}
.hero__down::after{
  content:"";width:6px;height:6px;
  border-right:1px solid var(--mute);border-bottom:1px solid var(--mute);
  rotate:45deg;translate:0 -1px;
}
.hero__down:hover{border-color:var(--bone);}

/* --- Ø2  SOCIAL --------------------------------------------------------- */
.social{padding-block:var(--bay);}
.cards{display:grid;grid-template-columns:1fr 1fr;gap:clamp(12px,1.5vw,20px);}
.card{
  display:flex;flex-direction:column;
  background:var(--raised);border-radius:var(--r);padding:clamp(24px,2.4vw,34px);
  transition:background .3s ease;
}
.card:hover{background:var(--raised-2);}
.chip{
  width:46px;height:46px;border-radius:50%;background:rgba(239,236,230,.07);
  display:grid;place-items:center;color:var(--bone);margin-bottom:22px;
}
.chip svg{width:21px;height:21px;}
.card__name{margin:0;font-size:20px;font-weight:500;}
.card__note{margin:8px 0 0;color:var(--mute);font-size:14.5px;max-width:32ch;}
.card__slot{
  margin-top:24px;min-height:330px;border-radius:var(--r-s);
  background:rgba(239,236,230,.03);overflow:hidden;position:relative;
}
.card__slot iframe{width:100%;height:100%;min-height:230px;border:0;display:block;}
.card__slot--light{background:#fff;}
/* Telegram's dark embed sits on its own near-black, so the slot matches it and
   nothing flashes a different colour while the iframe loads.

   The ratio is header-plus-photo at the render width, 340 x 390, measured. The
   iframe is scaled into it by main.js at EVERY width, not only on a phone like
   Instagram, because that render height is what keeps the post's text out of
   frame. Let it lay out at its own width and the text reappears and gets cut
   off mid-sentence. */
/* Telegram's dark embed sits on its own near-black, so the slot matches it and
   nothing flashes a different colour while the iframe loads. The frame is
   positioned and scaled by main.js at every width, not only on a phone: given
   its real width the embed centres a max-width bubble and paints the rest
   white, which is glaring here. */
.card__slot--tg{
  background:#17212B;
  /* Telegram leaves a 7px white gutter down the left of its embed, where the
     channel avatar sits outside the bubble. Measured at the render width, so
     it is a constant there whatever the slot ends up being. The frame is made
     that much wider and pushed left by the same amount: translate comes after
     scale in the list, so it applies BEFORE it and gets scaled with the rest,
     which is what keeps the crop exact at every width. */
  --tg-gutter:7px;
}
.card__slot--tg iframe{
  position:absolute;top:0;left:0;
  width:calc(var(--ig-w,100%) + var(--tg-gutter));
  height:var(--ig-h,100%);min-height:0;border:0;display:block;
  transform-origin:top left;
  transform:scale(var(--ig-scale,1)) translateX(calc(var(--tg-gutter) * -1));
}
.card__slot--light iframe{
  width:100%;height:100%;min-height:330px;border:0;display:block;
}
.slot__empty{
  position:absolute;inset:0;display:grid;place-items:center;
  font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--mute-2);
}
.card__go{
  margin-top:24px;align-self:flex-start;font-size:13.5px;color:var(--mute);
  padding-bottom:3px;border-bottom:1px solid var(--line-2);
  transition:color .25s ease,border-color .25s ease;
}
.card:hover .card__go{color:var(--bone);border-color:var(--bone);}

/* --- Ø3  MUSIC ---------------------------------------------------------- */
.music{padding-block:var(--bay);}
.records{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,2.4vw,34px);}
.record{
  display:flex;flex-direction:column;align-items:center;text-align:center;
  background:var(--raised);border-radius:var(--r);
  padding:clamp(26px,2.6vw,38px) clamp(20px,2vw,30px) clamp(24px,2.4vw,34px);
  transition:background .3s ease;
}
.record:hover{background:var(--raised-2);}
.record [data-vinyl]{--v-size:min(300px,26vw);--v-cyan:rgba(239,236,230,.5);}
.record__name{margin:26px 0 0;font-size:19px;font-weight:500;}
.record__note{margin:6px 0 0;font-size:14px;color:var(--mute);}
.record__link{
  margin-top:20px;font-size:13.5px;color:var(--mute);
  padding-bottom:3px;border-bottom:1px solid var(--line-2);
  transition:color .25s ease,border-color .25s ease;
}
.record__link:hover{color:var(--bone);border-color:var(--bone);}
.record__link--soon{color:var(--mute-2);border-color:transparent;cursor:default;}
/* The deck wrapper is inert on desktop: no positioning context is needed
   until the arrows exist, and the arrows only exist below 980px. */
.deck__arr,.deck__dots{display:none;}

@media (max-width:980px){
  /* The old one-column rule capped the records at 460px and centred them.
     Keep that: without it a tablet gets a 750px wide card around a 300px
     vinyl. Below the phone gutter the cap never binds, so this is inert there. */
  .deck{position:relative;max-width:460px;margin-inline:auto;}
  .records{
    display:flex;gap:clamp(12px,3vw,20px);
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;
    scrollbar-width:none;max-width:none;margin-inline:0;
    /* the rail is scrolled by the arrows and by the finger, so it must take
       pointer input even though the vinyl inside it does not */
    padding-bottom:2px;
  }
  .records::-webkit-scrollbar{display:none;}
  .record{flex:0 0 100%;scroll-snap-align:center;scroll-snap-stop:always;}
  .record [data-vinyl]{--v-size:min(300px,64vw);}

  /* Beside the vinyl, not beside the card, which is far taller than the
     artwork. Both numbers are already in this stylesheet, so this is plain
     arithmetic rather than a measurement: the card's own padding-top, plus
     half the vinyl. Measuring it in JS raced the vinyl's own sizing and left
     the arrows 26px low, because the first reading caught it at 300px.
     64vw of vinyl in a full width card leaves ~50px a side, so 44px clears. */
  .deck__arr{
    display:grid;place-items:center;
    position:absolute;left:0;
    top:calc(clamp(26px,2.6vw,38px) + min(300px,64vw) / 2);translate:0 -50%;
    width:44px;height:44px;padding:0;border-radius:50%;
    background:rgba(11,12,13,.8);border:1px solid var(--line-2);
    color:var(--bone);z-index:3;cursor:pointer;
    transition:opacity .25s ease,border-color .25s ease;
  }
  .deck__arr--next{left:auto;right:0;}
  .deck__arr svg{
    width:18px;height:18px;fill:none;stroke:currentColor;
    stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;
  }
  .deck__arr[disabled]{opacity:.25;cursor:default;}

  .deck__dots{display:flex;justify-content:center;gap:7px;margin-top:18px;}
  .deck__dots i{
    width:6px;height:6px;border-radius:50%;background:var(--line-2);
    transition:background .25s ease,transform .25s ease;
  }
  .deck__dots i.is-on{background:var(--bone);transform:scale(1.25);}
}

/* --- Ø4  GALLERY -------------------------------------------------------- */
.gallery{padding-block:var(--bay);overflow:hidden;}
/* One CSS transform on one element. No per-frame JavaScript anywhere here:
   that is what was making this section crawl. */
.strip{
  margin-top:clamp(4px,1vw,12px);
  display:flex;flex-direction:column;gap:clamp(12px,1.4vw,20px);
}
.strip__track{
  display:flex;align-items:center;gap:clamp(12px,1.4vw,20px);width:max-content;
  /* Durations are scaled to the tile count, not fixed. The row went from 11
     tiles to 18, and leaving the clock alone would have sped the scroll up by
     64% because the track got that much longer over the same period.
     74s x 18/11 = 121, 91s x 18/11 = 149, delay -37 x 18/11 = -61. */
  animation:strip 121s linear infinite;
}
/* the lower row runs the other way, and on a different clock so the two never
   line up and read as one block sliding */
.strip__track--b{animation-duration:149s;animation-direction:reverse;animation-delay:-61s;}
@keyframes strip{from{transform:translate3d(0,0,0);}to{transform:translate3d(-50%,0,0);}}
/* One height for the whole strip. Width comes from each shot's own
   aspect-ratio, set inline from the source file, so nothing is ever cropped.
   The strip takes no pointer input: no hover, no pause, no cursor change. */
.strip,.strip *{pointer-events:none;}
.shot{
  flex:none;margin:0;height:clamp(150px,17vw,260px);aspect-ratio:1;
  border-radius:var(--r-s);overflow:hidden;background:var(--raised);
}
.shot img{width:100%;height:100%;object-fit:cover;display:block;}

/* --- Ø5  MAP ------------------------------------------------------------ */
.venue{padding-block:var(--bay);}
.venue__name{margin:0;font-size:clamp(24px,2.6vw,34px);font-weight:500;line-height:1.1;}
.venue__addr{margin:14px 0 0;color:var(--mute);font-size:15px;}
.rows{list-style:none;margin:auto 0 0;padding:28px 0 0;display:grid;gap:2px;}
.rows li{
  display:flex;align-items:baseline;justify-content:space-between;gap:18px;
  padding:13px 0;border-top:1px solid var(--line);font-size:14px;
}
.rows span{color:var(--mute-2);}
.rows b{font-weight:400;}
.venue__map{
  position:relative;border-radius:var(--r);overflow:hidden;background:var(--raised-2);
  /* Google's embed draws an "Open in Maps" chip in its top-left corner. The
     whole iframe is pointer-events:none, so that chip is dead: it looks like a
     button and does nothing. It cannot be removed from a cross-origin frame,
     so the frame is pulled up by exactly its height and the top is clipped.

     Cropping only the TOP is deliberate. The Google logo and the "Map data
     ©2026" line sit along the bottom and are required by the embed terms, so
     they stay. The pin moves up by half the crop to stay on the venue: the
     frame's centre, which is where the venue is, moves up by that much. */
  --map-top-crop:48px;
}
.venue__frame{position:absolute;inset:0;}
.venue__map iframe{
  position:absolute;left:0;right:0;
  top:calc(var(--map-top-crop) * -1);
  width:100%;height:calc(100% + var(--map-top-crop));border:0;
  filter:grayscale(1) invert(.92) contrast(.86) brightness(.94);
  pointer-events:none;
}
/* The only colour on the page, and it is the brand cyan. It is a sibling of
   the iframe, never a child, so the grayscale filter cannot reach it. Its tip
   sits on the centre of the frame, which is the venue, because the embed is
   centred with ll= . */
.pin{
  position:absolute;left:50%;
  top:calc(50% - var(--map-top-crop) / 2);
  width:26px;height:35px;
  translate:-50% -100%;fill:var(--cyan);pointer-events:none;
}
.pin circle{fill:var(--night);}
.venue__map-wait{
  position:absolute;inset:0;display:grid;place-items:center;
  font-family:var(--mono);font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--mute-2);
}

/* --- TICKETS + FOOTER --------------------------------------------------- */
.close{padding-block:var(--bay);}
/* ONE frame. The surface, the radius and the clip live here, so the ticket
   card and the tabs read as two halves of the same object rather than two
   boxes with a gap between them. */
.ticket{
  display:grid;grid-template-columns:minmax(300px,420px) minmax(0,1fr);
  gap:0;align-items:stretch;
  background:var(--raised);border-radius:var(--r);overflow:hidden;
}
.ticket__side{
  background:none;border-radius:0;
  border-left:1px solid var(--line);
  padding:clamp(24px,2.4vw,34px);display:flex;flex-direction:column;
}
.ticket__concept{margin:0;color:var(--mute);font-size:15.5px;line-height:1.75;max-width:48ch;}
.ticket__concept--last{margin-top:14px;color:var(--bone);}
.ticket__side .rows{margin-top:auto;padding-top:30px;}
.ticket__side .btn{margin-top:26px;}
.ticket__card{
  background:none;border-radius:0;overflow:hidden;
  display:flex;flex-direction:column;
}
/* The poster keeps its own 1200/630 and the COUNTDOWN takes the slack instead,
   centred in whatever is left below it. Letting the poster fill the column was
   the obvious move and it was wrong: the artwork is wide, the column is tall
   and narrow, so object-fit:cover sliced it down to "7 FRAME" with the line-up
   and the prices cut off either side. The ratio of the box has to match the
   ratio of the source or cover quietly destroys it. */
.ticket__card .ticket__foot{margin-block:auto;}
.ticket__poster{width:100%;height:auto;aspect-ratio:1200/630;object-fit:cover;}
.ticket__foot{padding:clamp(22px,2.2vw,30px);}
.ticket__until{
  margin:0;font-family:var(--mono);font-size:10px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--mute-2);
}
.count{
  display:flex;gap:clamp(14px,1.6vw,24px);margin:14px 0 24px;
  font-size:13px;color:var(--mute-2);
}
.count span{display:flex;align-items:baseline;gap:3px;}
.count b{
  font-size:clamp(26px,2.6vw,36px);font-weight:500;color:var(--bone);
  font-variant-numeric:tabular-nums;letter-spacing:-.01em;
}
@media (max-width:900px){
  .ticket{grid-template-columns:1fr;}
  .ticket__side{border-left:0;border-top:1px solid var(--line);}
}

.close__mail{
  margin:clamp(34px,4vw,52px) 0 0;font-size:13.5px;color:var(--mute-2);text-align:center;
}
.close__mail a{color:var(--mute);border-bottom:1px solid var(--line-2);padding-bottom:2px;}
.close__mail a:hover{color:var(--bone);}

.foot{border-top:1px solid var(--line);padding-block:clamp(34px,4vw,52px);}
.foot__grid{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:20px 32px;font-size:13px;color:var(--mute-2);
}
.foot__mark{
  width:132px;height:29px;opacity:1;
  background:url('../assets/img/wordmark-tight.png') center/100% auto no-repeat;
}
.foot__nav{display:flex;gap:clamp(16px,2vw,28px);flex-wrap:wrap;}
.foot__nav a:hover{color:var(--bone);}
.foot__sign{margin:0;}

/* --- NEXT NIGHT TABS ----------------------------------------------------- */
/* Three panes in the left frame of Next Night. Added 21 Sep 2026; the state
   before, and the steps to undo it, are in "Rollback points/01 - Find Us as
   its own section/". */
.tabs{
  display:flex;gap:6px;margin-bottom:clamp(22px,2.4vw,30px);
  border-bottom:1px solid var(--line);padding-bottom:14px;
}
.tabs__btn{
  appearance:none;background:transparent;border:1px solid var(--line-2);
  color:var(--mute);font:inherit;font-size:13px;letter-spacing:.01em;
  padding:9px 18px;border-radius:var(--pill);cursor:pointer;
  transition:color .25s ease,border-color .25s ease,background .25s ease;
}
.tabs__btn:hover{color:var(--bone);border-color:var(--bone);}
.tabs__btn.is-on{background:var(--bone);border-color:var(--bone);color:var(--night);}

/* Every pane occupies the SAME grid cell, so the stack is always as tall as
   the tallest one and switching a tab cannot resize the frame. That is the
   whole point, and it is why the inactive ones are hidden with visibility
   instead of [hidden] or display:none, either of which would take them out of
   the grid and let the height jump again. */
.tab__stack{display:grid;flex:1;}
.tab__stack > .tab__pane{grid-area:1 / 1;}
.tab__pane{
  visibility:hidden;opacity:0;pointer-events:none;
  transform:translateY(6px);
  transition:opacity .3s ease,transform .3s ease,visibility 0s linear .3s;
}
.tab__pane.is-on{
  visibility:visible;opacity:1;pointer-events:auto;transform:none;
  transition:opacity .35s ease,transform .35s ease,visibility 0s;
}
@media (prefers-reduced-motion:reduce){
  .tab__pane{transition:none;}
}

/* The music pane: the record beside its details, stacking on a phone. The link
   sits under the RECORD, not under the table, because it opens the record.

   The record is big here on purpose. Every pane shares one grid cell so the
   stack is as tall as the tallest, which is Map, and Music only reached 239px
   of 434: 195px of dead air under it. A bigger record takes most of that, and
   centring the block spreads what is left above and below instead of leaving
   it all in a hole at the bottom. */
.setlist{
  display:flex;gap:clamp(24px,3vw,44px);align-items:center;
  height:100%;
}
.setlist__side{flex:none;display:flex;flex-direction:column;align-items:center;gap:20px;}
.setlist__side .record__link{display:inline-block;}
.setlist__side [data-vinyl]{--v-size:min(300px,30vw);}
.setlist__meta{min-width:0;}
.setlist__meta .rows{margin-top:24px;}

/* The map pane. A strip rather than a panel: at 300px tall it made the left
   frame 841px on Map against 438px on Music, a 403px jump between two buttons
   sitting side by side, which is what the brief objected to.

   The 48px top crop that hides Google's dead "Open in Maps" chip stays, and it
   is a FIXED pixel amount because the chip is fixed inside the iframe, so at
   this height it is a large share of the box. That is what drives the numbers
   below: the venue ends up at (height/2 - 24) from the top, so the pin is
   shrunk to keep its point there without its head being clipped off. */
/* 18+ as a mark beside the venue name rather than a row of its own: it is one
   fact and it does not need a whole line in a table. */
.badge{
  display:inline-block;vertical-align:middle;margin-left:10px;
  font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  color:var(--mute);border:1px solid var(--line-2);border-radius:var(--pill);
  padding:4px 9px;translate:0 -2px;
}

/* The strip crops SIDEWAYS, not from the top, and that is what puts the pin in
   the middle. Google's dead "Open in Maps" chip sits in the iframe's top-left
   corner, so the old fix pulled the frame up 48px, which pushed the venue 24px
   above centre. Widening the frame and pulling it left by the same amount on
   both sides takes the chip out through the left edge while leaving the
   iframe's centre, which is the venue, exactly on the container's centre both
   ways. The Google logo and the "Map data ©2026" line sit along the middle of
   the bottom edge and survive the crop, which the embed terms require. */
.venue__map--tab{
  min-height:0;height:112px;
  margin-bottom:clamp(20px,2.2vw,26px);
  --map-x-crop:150px;
}
.venue__map--tab iframe{
  top:0;left:calc(var(--map-x-crop) * -1);
  width:calc(100% + var(--map-x-crop) * 2);
  height:100%;
}
.venue__map--tab .pin{width:20px;height:27px;top:50%;}
.tab__pane .venue__name{font-size:clamp(22px,2.2vw,28px);}
.tab__pane .venue__addr{margin-top:10px;}
.tab__pane .rows{padding-top:22px;}
.tab__pane .btn{margin-top:24px;}

@media (max-width:760px){
  /* No rule under the pills on a phone. .ticket__side already draws one right
     above them, and two hairlines 60px apart with three pills trapped between
     them read as a broken table rather than a control. Spacing separates them
     here instead. */
  .tabs{gap:6px;padding-bottom:0;margin-bottom:18px;border-bottom:0;}
  /* 44px tall, like every other control on a phone */
  .tabs__btn{font-size:12px;padding:13px 14px;flex:1;}
  .setlist{flex-direction:column;align-items:center;text-align:center;height:auto;}
  /* the phone pane is already the tallest of the three, so the record stays
     small there: making it bigger would just grow the frame for all of them.
     Every pane shares one grid cell, so this number sets the height of the
     whole card on a phone. 168 -> 150 takes 18px off all three at once. */
  .setlist__side{gap:14px;}
  .setlist__side [data-vinyl]{--v-size:min(150px,39vw);}
  .venue__map--tab{height:104px;}
}

/* --- POPUP --------------------------------------------------------------- */
/* Opens 3s after load. Sits above the nav (z 60) and below nothing else. */
.pop[hidden]{display:none;}
.pop{
  position:fixed;inset:0;z-index:90;
  display:grid;place-items:center;padding:var(--gutter);
}
.pop__scrim{
  position:absolute;inset:0;background:rgba(6,7,8,.72);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  opacity:0;transition:opacity .4s ease;
}
.pop.is-on .pop__scrim{opacity:1;}
.pop__card{
  position:relative;width:min(420px,100%);
  background:var(--raised);border:1px solid var(--line);border-radius:var(--r);
  overflow:hidden;
  opacity:0;transform:translateY(14px) scale(.985);
  transition:opacity .45s ease,transform .45s cubic-bezier(.2,.7,.3,1);
}
.pop.is-on .pop__card{opacity:1;transform:none;}
.pop__poster{width:100%;height:auto;aspect-ratio:1200/630;object-fit:cover;display:block;}
.pop__body{padding:clamp(22px,2.4vw,30px);}
.pop__eyebrow{
  margin:0;font-family:var(--mono);font-size:10px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--mute-2);
}
.pop__title{margin:10px 0 0;font-size:26px;font-weight:500;letter-spacing:.005em;}
.pop__rows{padding-top:18px;}
.pop__rows li{padding:11px 0;font-size:13.5px;}
.pop__body .btn{margin-top:22px;}
.pop__later{
  display:block;width:100%;margin-top:14px;padding:10px 0;
  appearance:none;background:none;border:0;cursor:pointer;
  font:inherit;font-size:12.5px;color:var(--mute-2);
  transition:color .25s ease;
}
.pop__later:hover{color:var(--mute);}

/* The cross. 44px of target around a 14px mark, same rule as every other
   control on a phone. */
.pop__x{
  position:absolute;top:12px;right:12px;z-index:2;
  width:38px;height:38px;display:grid;place-items:center;
  appearance:none;padding:0;cursor:pointer;border-radius:50%;
  background:rgba(11,12,13,.66);border:1px solid var(--line-2);color:var(--bone);
  -webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);
  transition:background .25s ease,border-color .25s ease;
}
.pop__x::before{content:"";position:absolute;inset:-4px;border-radius:50%;}
.pop__x:hover{background:rgba(11,12,13,.9);border-color:var(--bone);}
.pop__x svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;}

@media (max-width:760px){
  .pop{padding:16px;align-items:end;}
  .pop__card{width:100%;}
  .pop__title{font-size:23px;}
  .pop__x{top:10px;right:10px;width:40px;height:40px;}
}
@media (prefers-reduced-motion:reduce){
  .pop__scrim,.pop__card{transition:none;}
}

/* --- MASKED LINES ------------------------------------------------------- */
/* Split by JS on <br>. Padding stops the mask shaving descenders, the negative
   margin hands the space straight back to the layout. */
.ln{display:block;overflow:hidden;padding-bottom:.1em;margin-bottom:-.1em;}
.ln i{display:block;font-style:normal;}

/* --- REDUCED MOTION ----------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;}
  .strip{overflow-x:auto;}
}

/* --- NARROW ------------------------------------------------------------- */
@media (max-width:720px){
  .head{align-items:flex-start;}
  .hero__mark{width:min(78vw,340px);}
  .hero .pills{gap:6px;}
  .pills li{font-size:12px;padding:7px 14px;}
}

/* --- PHONE LAYOUT ------------------------------------------------------- */
/* Everything below is phone only and additive: no rule here exists above
   760px, so the desktop layout is untouched by all of it. The brief was that
   the page reads as one big block after another on a phone, so the moves are
   all the same move: less air between sections, and panels that belong
   together share one frame instead of stacking as separate cards. */
@media (max-width:760px){

  /* 88px top AND bottom on every section is 176px of nothing between them on
     a 844px screen. This is the single biggest reason the page felt oversized. */
  :root{--bay:clamp(56px,14vw,72px);}

  /* --- SOCIAL: two up, and much shorter ---------------------------------- */
  /* Side by side on the phone too. The sentence under each name goes, the
     handle stays: at 165px of card width the sentence wrapped to five lines
     and the handle is the only part anyone needs. */
  .cards{gap:10px;}
  .card{padding:14px;border-radius:18px;}
  .chip{width:34px;height:34px;margin-bottom:12px;}
  .chip svg{width:17px;height:17px;}
  .card__name{font-size:15px;}
  .card__note{margin-top:5px;}
  .card__desc{display:none;}
  .card__handle{
    font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;
    color:var(--mute-2);
  }
  /* Square, not 3:4. Instagram's embed is a header plus a 3-up grid: at 340px
     of render width that is ~320px tall, so a 3:4 slot left a band of bare
     white under the last row. A square slot is ~340px of render height at the
     same scale, which lands on the bottom of the second row. */
  .card__slot{margin-top:12px;min-height:0;aspect-ratio:1;border-radius:12px;}
  .card__go{margin-top:12px;font-size:12px;}

  /* Instagram's embed has a minimum sensible width, well above the ~140px of
     slot it now gets. So it is rendered at its own width and scaled down to
     fit. --ig-w/--ig-h/--ig-scale are resolved px written by main.js from the
     measured slot, never a clamp(), because a transform cannot read one. */
  .card__slot--light iframe{
    position:absolute;top:0;left:0;
    width:var(--ig-w,100%);height:var(--ig-h,100%);min-height:0;
    transform-origin:top left;transform:scale(var(--ig-scale,1));
  }

  /* --- NIGHTS: bigger tiles ---------------------------------------------- */
  /* 150px squares on a 390px screen read as thumbnails. 52vw is ~203px. */
  .shot{height:clamp(190px,52vw,232px);}

  /* The Find Us section's own phone rules used to live here. They went when
     that section folded into the Map tab, and one of them mattered: it set
     .venue__map to 168px and sat LATER in the file than .venue__map--tab, so
     it silently won and the map strip stayed 168px on a phone instead of 104.
     The two that are still needed are kept, scoped to the tab. */
  .tab__pane .venue__name{font-size:23px;}
  .tab__pane .venue__addr{margin-top:8px;font-size:14px;}

  /* --- NEXT NIGHT: no frame above the countdown -------------------------- */
  /* The concept was in a card of its own stacked on top of the ticket card,
     which is the block-on-block the brief objected to. On a phone it becomes
     plain copy under the heading and the countdown card follows it directly.
     The rows go: the lede above already gives date, doors and venue, and the
     poster carries the line-up, so every row was a duplicate here. */
  .ticket{gap:18px;}
  /* 18px, the same number as .ticket__foot below, so the tabs, the copy, the
     table and the Buy button all hang off ONE vertical line. This was 0, which
     put every word hard against the card's 24px radius and clipped the tab
     pills at both ends: measured at 390px, every block sat at x=20 and x=370,
     which is the card's own edge. */
  .ticket__side{background:none;padding:16px 18px 18px;}
  .ticket__side:hover{background:none;}
  /* The table used to be hidden here, because the line under the heading
     already gave date, doors and venue. With tabs it goes back: the pane is
     called Summary, and without it the pane was 246px against Music's 422,
     which is the height jump between buttons the brief objected to. */
  .ticket__concept{font-size:15px;line-height:1.7;max-width:none;}
  .ticket__concept--last{margin-top:12px;}
  .ticket__foot{padding:18px;}
  .count{margin:10px 0 15px;}

  /* The table was four full-width rows, each with its own hairline, 51px tall:
     231px spent on four short facts, and it read as a wall rather than a
     spec list. Two columns with the label over the value, and ONE rule above
     the group instead of four through it, carries the same four facts in about
     half the height. The label takes the mono treatment already used by
     "DOORS IN" above it, so the two blocks read as one family.

     Scoped to .tab__pane so the desktop table, which has the width for full
     rows, is untouched. */
  .tab__pane .rows{
    grid-template-columns:1fr 1fr;gap:15px 18px;
    margin-top:20px;padding-top:18px;border-top:1px solid var(--line);
  }
  .tab__pane .rows li{display:block;padding:0;border-top:0;gap:0;}
  .tab__pane .rows span{
    display:block;font-family:var(--mono);font-size:10px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--mute-2);
  }
  .tab__pane .rows b{display:block;margin-top:5px;font-size:15px;color:var(--bone);}

  /* Music keeps its layout, it only gets the tighter table and a smaller gap. */
  .setlist{gap:18px;}
}

/* --- TOUCH TARGETS ------------------------------------------------------ */
/* Measured on a 390x844 phone: these sat between 20px and 27px tall against a
   44px finger. The small round and underlined ones grow through a transparent
   ::before so the drawn mark keeps its size; the rest take vertical padding. */
@media (max-width:760px){
  .hero__down::before{content:"";position:absolute;inset:-10px;border-radius:50%;}

  .record__link{position:relative;}
  .record__link::before{content:"";position:absolute;inset:-10px -14px;}

  .foot__nav a,
  .close__mail a{display:inline-block;padding-block:11px;}
  .foot__grid{gap:8px 32px;}
}
