:root{
  /* Palette adopted from musichubwest.com — this site is a continuation of it */
  --black:#0d0d0d;--bg-2:#111111;
  --lime:#ccff00;         /* signature acid lime — fills/buttons (always with dark text) */
  --lime-dim:#ccff00;     /* small text on black: lime reads ~15:1 here */
  --white:#fff;
  --gray:rgba(255,255,255,.55);--gray-2:rgba(255,255,255,.34);
  --line:rgba(255,255,255,.22);--line-2:rgba(255,255,255,.12);
  /* Syne Mono is the primary typeface, Outfit for body — same as Music Hub West */
  --disp:"Syne Mono",monospace;--mono:"Syne Mono",monospace;
  --num:"Syne Mono",monospace;--body:"Outfit",sans-serif;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{background:var(--black);color:var(--white);font-family:var(--body);line-height:1.5;-webkit-font-smoothing:antialiased;overflow-x:hidden}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
.wrap{max-width:1280px;margin:0 auto;padding:0 32px}
.mono{font-family:var(--mono);letter-spacing:.06em}
.eyebrow{font-family:var(--mono);font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:var(--gray)}
h1,h2,h3{font-family:var(--disp);font-weight:800;letter-spacing:-.01em;line-height:1;text-transform:uppercase}
.box{border:1px solid var(--line);font-family:var(--mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase;padding:8px 14px;display:inline-flex;align-items:center;gap:8px;background:var(--black)}
.btn{font-family:var(--mono);font-size:13px;letter-spacing:.1em;text-transform:uppercase;border:1px solid var(--white);background:transparent;color:var(--white);padding:15px 30px;cursor:pointer;transition:.2s;display:inline-flex;align-items:center;gap:10px}
.btn:hover{background:var(--white);color:var(--black)}
.btn-blue{border-color:var(--lime);background:var(--lime);color:var(--black)}
.btn-blue:hover{background:var(--white);color:var(--black);border-color:var(--white)}
section{position:relative}
.pad{padding:120px 0}
.page-top{padding:160px 0 20px}
.sec-head{max-width:760px;margin-bottom:64px}
.sec-head h2{font-size:clamp(34px,5.5vw,64px);margin:18px 0 16px}
.sec-head p{font-family:var(--body);font-size:17px;color:rgba(255,255,255,.72);line-height:1.6;max-width:520px}

/* reveal */
.js .rv{opacity:0;transform:translateY(28px);transition:opacity .7s ease,transform .7s ease}
.js .rv.in{opacity:1;transform:none}

/* TOP BAR */
header.top{position:fixed;top:0;left:0;right:0;z-index:60;display:flex;align-items:center;justify-content:space-between;padding:16px 24px;background:linear-gradient(180deg,rgba(0,0,0,.92),rgba(0,0,0,.35));backdrop-filter:blur(6px)}
.wordmark{display:flex;align-items:center;gap:10px;font-family:var(--disp);font-weight:800;font-size:22px;text-transform:none;letter-spacing:-.02em;flex-shrink:0}
.wordmark__mark{display:block;width:28px;height:auto;flex-shrink:0}
/* The footer sets the brand on one line, same as the header, but uses the full
   three-card logo rather than the single-card favicon: at 30px the favicon's
   22/1818 border renders under half a pixel and the card edge disappears. */
.foot-mark{display:block;width:44px;height:auto;flex-shrink:0}
.wm-br{display:none}
/* Grouped nav — one container, dead-centred, instead of separate boxes */
.navgroup{position:absolute;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:2px;padding:4px;border:1px solid var(--line-2);background:rgba(255,255,255,.04)}
.navgroup a{font-family:var(--mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--gray);padding:9px 14px;white-space:nowrap;transition:color .18s,background .18s}
.navgroup a:hover{color:var(--white);background:rgba(255,255,255,.07)}
.navgroup a.active{background:var(--white);color:var(--black)}
/* Right-hand actions: language switcher + lime CTA */
.top-actions{display:flex;align-items:center;gap:10px;flex-shrink:0}
.top-actions .reg{font-family:var(--mono);font-size:12px;letter-spacing:.06em;text-transform:uppercase;border:1px solid var(--lime);background:var(--lime);color:var(--black);padding:10px 15px;display:inline-flex;align-items:center;gap:9px;white-space:nowrap;transition:.2s}
.top-actions .reg:hover{background:var(--white);border-color:var(--white);color:var(--black)}
.burger{display:none;flex-direction:column;gap:5px;cursor:pointer;padding:8px;margin-left:10px;background:none;border:0}
.burger span{width:24px;height:2px;background:var(--white);transition:.25s}
.top.open .burger span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.top.open .burger span:nth-child(2){opacity:0}
.top.open .burger span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
.mobile-menu{position:fixed;inset:0;z-index:55;background:var(--black);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;opacity:0;pointer-events:none;transition:opacity .3s}
.top.open ~ .mobile-menu{opacity:1;pointer-events:auto}
.mobile-menu a{font-family:var(--disp);font-weight:800;font-size:32px;text-transform:uppercase;padding:8px}
.mobile-menu a.reg{color:var(--lime-dim)}
@media(max-width:1180px){.navgroup{display:none}.burger{display:flex}}
@media(min-width:1181px){.mobile-menu{display:none}}

/* HERO */
.hero{
  position:relative;min-height:100vh;display:flex;flex-direction:column;
  justify-content:center;text-align:center;overflow:hidden;
  /* Same two-layer ground as the .tba panel — a lime wash out of one corner
     over a near-black gradient — so the homepage opens in the same visual
     language the programme page speaks. */
  background:
    radial-gradient(90% 110% at 8% 8%,rgba(204,255,0,.09),transparent 58%),
    linear-gradient(180deg,#111110,#0b0b0a 62%,var(--black));
}
/* Graph paper. Bigger cells than the panel's 34px: at hero size a fine grid
   turns into moiré, and the lines have to stay a texture behind the title
   rather than a pattern competing with it. The diagonal mask keeps it out of
   the centre, where the type is. */
.hero-grid{
  position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.6;
  background-image:
    linear-gradient(rgba(255,255,255,.04) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.04) 1px,transparent 1px);
  background-size:64px 64px;
  mask-image:linear-gradient(155deg,#000,transparent 78%);
  -webkit-mask-image:linear-gradient(155deg,#000,transparent 78%);
}
/* Kept, but dimmer and tighter than when it sat over the canvas wave: beside a
   crisp grid a wide soft blob reads as an unresolved smudge rather than light. */
.hero .glow{position:absolute;right:-16%;bottom:-24%;width:70%;height:70%;z-index:0;background:radial-gradient(closest-side,rgba(204,255,0,.13),transparent 70%);filter:blur(40px)}
.hero .inner{position:relative;z-index:2;padding-top:80px;min-width:0;max-width:100%}
.hero .eyebrow{margin-bottom:26px}
h1.hero-title{font-size:clamp(40px,6.4vw,96px);line-height:.94;margin-bottom:26px;overflow-wrap:break-word}
.hero-sub{font-family:var(--body);font-size:clamp(15px,1.4vw,18px);color:rgba(255,255,255,.72);max-width:520px;margin:0 auto 34px;line-height:1.6}
/* The primary action and an escape hatch beside it. While registration is
   still closed, "Anmälan öppnar snart" is a dead end — the second link is the
   only thing a visitor can actually do today. Used by the hero and the
   countdown, so both offer a way forward rather than a closed door. */
.cta-row{display:flex;align-items:center;justify-content:center;gap:12px 26px;flex-wrap:wrap}
.cta-row .lnk{font-family:var(--mono);font-size:13px;letter-spacing:.08em;text-transform:uppercase;color:var(--white);border-bottom:1px solid var(--line);padding-bottom:3px;transition:.2s;white-space:nowrap}
.cta-row .lnk:hover{border-bottom-color:var(--lime);color:var(--lime)}


/* PAGE HEADER (subpages) */
.phead h1{font-size:clamp(44px,8vw,104px);margin:16px 0 18px;overflow-wrap:break-word}
.phead p{font-family:var(--body);font-size:17px;color:rgba(255,255,255,.72);max-width:560px;line-height:1.6;text-wrap:pretty}

/* INTERSTITIAL */
.interstitial{background:var(--lime);min-height:60vh;display:flex;align-items:center;justify-content:center;text-align:center;padding:40px}
.interstitial .line{font-family:var(--disp);font-weight:800;font-size:clamp(24px,4vw,52px);text-transform:uppercase;background:var(--black);color:var(--white);padding:6px 14px;line-height:1.25;box-decoration-break:clone;-webkit-box-decoration-break:clone}

/* STATS */
.statsrow{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border:1px solid var(--line-2)}
@media(max-width:760px){.statsrow{grid-template-columns:minmax(0,1fr)}}
.statcell{padding:48px 40px;border-right:1px solid var(--line-2)}
.statcell:last-child{border-right:0}
.statcell .n{font-family:var(--num);font-weight:800;font-size:clamp(44px,6vw,72px);line-height:1}
.statcell .n .p{color:var(--lime-dim)}
.statcell .cap{font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--gray);margin-top:14px}
.statcell .desc{font-family:var(--body);font-size:14px;color:rgba(255,255,255,.6);margin-top:12px;line-height:1.55}

/* TOPICS */
.topics{border-top:1px solid var(--line-2)}
.topic{display:grid;grid-template-columns:3rem minmax(0,17.5rem) minmax(0,1fr);gap:6px 32px;align-items:baseline;padding:22px 8px;border-bottom:1px solid var(--line-2);transition:background .25s}
.topic:hover{background:rgba(204,255,0,.06)}
.topic__n{font-family:var(--mono);font-size:13px;letter-spacing:.08em;color:var(--lime-dim)}
.topic h3{font-size:clamp(19px,1.7vw,24px);overflow-wrap:break-word}
.topic .d{font-family:var(--body);font-size:15px;color:rgba(255,255,255,.66);line-height:1.55;max-width:52ch}
@media(max-width:820px){
  .topic{grid-template-columns:2.6rem minmax(0,1fr);padding:18px 4px}
  .topic .d{grid-column:2}
}

/* SPEAKERS */
.speakers{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:2px}
@media(max-width:980px){.speakers{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:520px){.speakers{grid-template-columns:minmax(0,1fr)}}
.spk{position:relative;aspect-ratio:3/4;overflow:hidden;display:flex;align-items:flex-end;background:#0e0e0e}
.spk .duo{position:absolute;inset:0;opacity:.85}
.spk .ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-family:var(--disp);font-weight:800;font-size:40px;color:rgba(255,255,255,.16)}
.spk .info{position:relative;z-index:2;padding:22px;width:100%;background:linear-gradient(180deg,transparent,rgba(0,0,0,.9))}
.spk .info h3{font-size:21px;text-transform:none;letter-spacing:-.01em}
.spk .info .role{font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--white);margin-top:8px}
.spk .info .cap{font-family:var(--body);font-size:13px;color:rgba(255,255,255,.7);margin-top:10px;line-height:1.5}
.duo-o{background:linear-gradient(160deg,#3d4a00,#0d0d0d)}
.duo-b{background:linear-gradient(160deg,#242424,#0d0d0d)}
.duo-y{background:linear-gradient(160deg,#556600,#0d0d0d)}
.duo-g{background:linear-gradient(200deg,#1c2400,#0d0d0d)}
.duo-p{background:linear-gradient(120deg,#47590a,#0d0d0d)}
.duo-r{background:linear-gradient(200deg,#2c2c2c,#0d0d0d)}

/* SCHEDULE */
.sched-wrap{position:relative}
.sched-sticky{position:sticky;top:0;min-height:100vh;display:flex;flex-direction:column;justify-content:center;padding:120px 0;overflow:hidden}
.sched-bg{position:absolute;inset:0;z-index:0;background:radial-gradient(70% 90% at 78% 50%,rgba(255,255,255,.05),transparent 60%),linear-gradient(180deg,#050505,#000)}
.sched-bg::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,transparent 40%,rgba(204,255,0,.06))}
.sched-inner{position:relative;z-index:2}
.sched-top{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:40px;flex-wrap:wrap;gap:16px}
.day-nav{display:flex;flex-direction:column;gap:8px;font-family:var(--mono);font-size:15px}
.day-nav .d{color:var(--gray-2);display:flex;gap:10px;align-items:center;transition:.2s;cursor:pointer}
.day-nav .d.on{color:var(--white)}
.day-nav .d .arrow{opacity:0;color:var(--lime-dim)}
.day-nav .d.on .arrow{opacity:1}
.day-title{font-family:var(--body);font-weight:500;font-size:clamp(26px,3.6vw,44px);margin:20px 0 28px;letter-spacing:-.01em}
.sched-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 60px}
@media(max-width:760px){.sched-grid{grid-template-columns:minmax(0,1fr)}}
.slot{padding:22px 0;border-top:1px solid var(--line-2)}
.slot .t{font-family:var(--mono);font-size:13px;color:var(--lime-dim);letter-spacing:.08em}
.slot .ti{font-family:var(--body);font-size:19px;font-weight:500;color:var(--white);margin-top:10px;line-height:1.3}
.slot .meta-line{display:flex;gap:10px;align-items:center;margin-top:10px}
.slot .sp{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--lime-dim);border:1px solid rgba(204,255,0,.5);padding:3px 8px}
.slot .rm{font-family:var(--mono);font-size:12px;color:var(--gray-2);text-transform:uppercase;letter-spacing:.06em}
.day-panel{display:none}
.day-panel.on{display:block}

/* TICKETS */
.ticket-single{max-width:480px;margin:0 auto}
.stub{position:relative;color:var(--black);padding:30px 30px 0;overflow:hidden;border:2px dashed rgba(13,13,13,.35);background:var(--lime)}
.stub::before,.stub::after{content:"";position:absolute;top:0;bottom:0;width:10px;background-image:radial-gradient(circle,currentColor 2px,transparent 2.6px);background-size:10px 16px;background-repeat:repeat-y;opacity:.5}
.stub::before{left:6px}.stub::after{right:6px}
.stub .in{position:relative;z-index:2;padding:0 10px}
/* One 24px rhythm through the whole stub, instead of 26/22/14/24/20. */
.stub-brand{display:flex;justify-content:space-between;align-items:center;padding-bottom:18px;margin-bottom:24px;border-bottom:1px solid rgba(13,13,13,.28)}
.stub-brand .bm{font-family:var(--disp);font-weight:800;font-size:14px;letter-spacing:.02em}
.stub-brand .sq{display:flex;gap:4px}
.stub-brand .sq i{width:8px;height:8px;background:currentColor;display:block}

/* Name and price were both display-size and stacked, so they competed for the
   same job. The name leads; the price is a figure beside it, baseline-aligned
   to the name rather than to its own qualifier. */
.stub-top{display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap}
.stub-top h2{font-size:clamp(26px,3vw,32px);line-height:1;overflow-wrap:break-word}
.stub .price{font-family:var(--num);font-weight:800;font-size:clamp(30px,3.4vw,38px);line-height:1;white-space:nowrap}

/* Labels are already uppercase and dimmed; the underline made a third signal
   and read as a link inside a card whose CTA is also a bordered box. */
.stub .meta{margin:24px 0;font-family:var(--mono);font-size:12px;letter-spacing:.03em;display:grid;gap:1px;background:rgba(13,13,13,.22);border-top:1px solid rgba(13,13,13,.22);border-bottom:1px solid rgba(13,13,13,.22)}
.stub .meta .row{background:var(--lime);display:grid;grid-template-columns:5.5rem minmax(0,1fr);gap:14px;padding:9px 0}
.stub .meta .row .k{text-transform:uppercase;opacity:.65}
.stub .inc{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;opacity:.65;margin-bottom:12px}
.stub ul{list-style:none}
.stub li{font-family:var(--body);font-size:14px;line-height:1.45;padding:5px 0;display:flex;gap:10px;align-items:flex-start}
.stub li::before{content:"";width:5px;height:5px;background:currentColor;display:block;flex:none;margin-top:.5em}
/* The only action on the ticket. As a small inline-flex chip it read as a
   caption on a lime field — the one dark element on the card was also the
   quietest thing on it. Full width of the stub, one step up in size, with the
   label and arrow are one string, so the bar is simply left-aligned. The
   bottom margin clears the tear line: a 4px gap made the dashed perforation
   look like an underline on the button rather than the ticket's fold. */
.stub .cta{margin:26px 0 30px}
.stub .cta a{font-family:var(--mono);font-size:14px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;background:var(--black);color:var(--lime);padding:17px 22px;display:flex;align-items:center;gap:8px;transition:.2s}
.stub .cta a:hover{background:var(--white);color:var(--black)}
.stub .tear{border-top:2px dashed currentColor;opacity:.5;margin:0 -10px}
.stub .foot{padding:20px 0 24px;text-align:center}
.stub .foot .note{font-family:var(--body);font-size:12px;line-height:1.55;opacity:.8;margin:0 auto 16px;max-width:42ch}
.barcode{height:44px;background:repeating-linear-gradient(90deg,currentColor 0 2px,transparent 2px 4px,currentColor 4px 7px,transparent 7px 9px,currentColor 9px 11px,transparent 11px 16px)}
.steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;background:var(--line-2);border:1px solid var(--line-2);margin-top:64px}
@media(max-width:820px){.steps{grid-template-columns:minmax(0,1fr)}}
.step{background:var(--black);padding:34px 30px}
.step .sn{font-family:var(--num);font-weight:800;font-size:34px;color:var(--lime-dim)}
.step h3{font-size:22px;text-transform:none;margin:16px 0 12px}
.step p{font-family:var(--body);font-size:15px;color:rgba(255,255,255,.72);line-height:1.6}
.step p b{color:var(--white)}

/* FAQ */
.faq{border-top:1px solid var(--line-2);max-width:820px}
.faq details{border-bottom:1px solid var(--line-2)}
.faq summary{list-style:none;cursor:pointer;padding:24px 4px;font-family:var(--disp);font-weight:700;font-size:clamp(18px,2.2vw,24px);text-transform:uppercase;display:flex;justify-content:space-between;align-items:center;gap:20px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";color:var(--lime-dim);font-family:var(--mono)}
.faq details[open] summary::after{content:"–"}
.faq p{font-family:var(--body);font-size:16px;color:rgba(255,255,255,.72);line-height:1.6;padding:0 4px 24px;max-width:720px}

/* BLOG */
.blog{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:2px}
@media(max-width:900px){.blog{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.blog{grid-template-columns:minmax(0,1fr)}}
.post{position:relative;aspect-ratio:4/5;overflow:hidden;display:flex;flex-direction:column;justify-content:flex-end;background:#0e0e0e;transition:.25s}
.post:hover{transform:translateY(-4px)}
.post .cover{position:absolute;inset:0;opacity:.9}
.post .tags{position:absolute;top:16px;left:16px;right:16px;z-index:2;display:flex;justify-content:space-between;gap:8px}
.post .tags .cat,.post .tags .dt{font-family:var(--mono);font-size:11px;letter-spacing:.04em;text-transform:uppercase;background:rgba(0,0,0,.7);border:1px solid var(--line);padding:5px 9px}
.post .body{position:relative;z-index:2;padding:22px;background:linear-gradient(180deg,transparent,rgba(0,0,0,.92) 55%)}
.post .body h3{font-size:21px;text-transform:none;letter-spacing:-.01em;line-height:1.15}
.post .body p{font-family:var(--body);font-size:14px;color:rgba(255,255,255,.72);margin-top:10px;line-height:1.5}
.cov-1{background:linear-gradient(150deg,#49590a,#0d0d0d)}
.cov-2{background:linear-gradient(150deg,#2a2a2a,#0d0d0d)}
.cov-3{background:linear-gradient(150deg,#5c7000,#0d0d0d)}
.cov-4{background:linear-gradient(150deg,#1f2600,#0d0d0d)}
.cov-5{background:linear-gradient(150deg,#333333,#0d0d0d)}
.cov-6{background:linear-gradient(150deg,#3d4a00,#0d0d0d)}

/* CONTACT */
.contact-split{display:grid;grid-template-columns:1fr 1fr;min-height:600px}
@media(max-width:860px){.contact-split{grid-template-columns:1fr}}
.contact-left{background:var(--lime);color:var(--black);padding:70px 56px;display:flex;flex-direction:column;justify-content:space-between;gap:40px}
.contact-left h2{font-size:clamp(34px,4.4vw,58px)}
.contact-left .sub{font-family:var(--body);font-size:16px;color:rgba(13,13,13,.75);line-height:1.6;margin-top:18px;max-width:360px}
/* No rules between the rows. Each row is a label above or beside its value and
   the links are already underlined, so a rule per row plus two on the block
   made eight lines for four facts. Spacing separates them. */
.contact-left .info{display:grid;gap:22px}
.info-row{display:grid;grid-template-columns:6.6rem minmax(0,1fr);gap:6px 22px;align-items:baseline}
.info-row dt{font-family:var(--mono);font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:rgba(13,13,13,.6)}
.info-row dd{margin:0;font-family:var(--disp);font-weight:700;font-size:clamp(16px,1.4vw,20px);line-height:1.4;min-width:0}
.info-row dd a{border-bottom:1px solid rgba(13,13,13,.3)}
.info-row dd a:hover{border-bottom-color:var(--black)}
@media(max-width:640px){
  .contact-left .info{gap:20px}
  .info-row{grid-template-columns:1fr;gap:2px}
}
.contact-right{padding:70px 56px}
/* The submit is lime and the panel to its left is lime, so at the column's
   leading edge the two read as one shape with a 56px slot cut out of it. It
   sits at the form's trailing edge instead — away from the panel, and level
   with the end of the fields it submits. */
@media(min-width:861px){
  .contact-right form{display:flex;flex-direction:column;align-items:flex-end}
  .contact-right .field{width:100%}
  .contact-right .form-note{align-self:flex-end;text-align:right}
}
.field{margin-bottom:28px}
.field label{font-family:var(--disp);font-weight:800;font-size:clamp(18px,1.6vw,22px);text-transform:uppercase;display:block;margin-bottom:8px}
.field input,.field textarea{width:100%;background:transparent;border:0;border-bottom:1px solid var(--line);color:var(--white);font-family:var(--mono);font-size:14px;padding:8px 0;outline:none}
.field input:focus,.field textarea:focus{border-color:var(--lime-dim)}
.field textarea{resize:vertical;min-height:70px}
.form-note{font-family:var(--body);font-size:13px;color:var(--gray);margin-top:14px}

/* SPONSORS */
.sponsors{display:flex;flex-wrap:wrap;gap:2px;justify-content:center}
.sp-logo{border:1px solid var(--line-2);padding:30px 44px;font-family:var(--disp);font-weight:700;font-size:20px;color:var(--gray);flex:1 1 220px;text-align:center;text-transform:none;transition:.2s}
.sp-logo:hover{color:var(--white);border-color:var(--line)}

/* FINAL CTA */
.final{position:relative;min-height:90vh;padding:96px 0 72px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;overflow:hidden}
.final .bg{position:absolute;inset:0;z-index:0;background:radial-gradient(60% 60% at 50% 40%,rgba(255,255,255,.06),transparent 65%),#040404}
.final .inner{position:relative;z-index:2;min-width:0;max-width:100%}
.final .eyebrow{margin-bottom:24px}
.clock{font-family:var(--num);font-weight:800;font-size:clamp(34px,min(9vw,11vh),110px);letter-spacing:.02em;line-height:1;margin-bottom:14px;font-variant-numeric:tabular-nums}
.clock-units{font-family:var(--mono);font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:var(--gray-2);margin-bottom:34px}
.final-foot{position:absolute;bottom:0;left:0;right:0;z-index:2;display:flex;justify-content:space-between;gap:12px;padding:20px 32px;border-top:1px solid var(--line-2);font-family:var(--mono);font-size:13px;color:var(--gray)}
.final-foot .mid{color:var(--white)}
@media(max-width:680px){.final-foot .side{display:none}}

/* FOOTER */
footer.site{border-top:1px solid var(--line-2);padding:56px 0 36px}
/* Brand block left, the three link columns grouped right. The old
   2fr 1fr 1fr 1fr grid gave the brand a column too narrow for a 60px mark
   stacked above the wordmark, so it grew downwards while the row beside it
   sat half empty — that is what read as cramped. */
.foot-top{display:flex;justify-content:space-between;align-items:flex-start;gap:48px;flex-wrap:wrap;margin-bottom:44px}
.foot-brand{min-width:0;max-width:34ch}
.foot-cols{display:flex;gap:56px;flex-wrap:wrap}
.foot-cols h4{font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--gray);margin-bottom:16px}
.foot-cols a{display:block;font-family:var(--mono);font-size:13px;color:var(--gray);padding:6px 0}
.foot-cols a:hover{color:var(--white)}
.foot-lead{font-family:var(--body);font-size:14px;color:var(--gray);margin-top:16px;line-height:1.6}
@media(max-width:640px){.foot-cols{gap:30px}.foot-top{gap:36px}}
.foot-bottom{display:flex;justify-content:space-between;flex-wrap:wrap;gap:12px;padding-top:26px;border-top:1px solid var(--line-2);font-family:var(--mono);font-size:12px;color:var(--gray-2)}
.foot-bottom a{color:var(--lime-dim)}

/* ── Sticky reveal footer ──────────────────────────────
   Timer + footer sit pinned behind the page; the content
   slides up over them and uncovers them at the bottom.
   Progressive enhancement: only active when JS is on. */
.reveal-zone { background: var(--black); }
/* Reveal effect only on tablet+ — on mobile the stacked footer is taller
   than the viewport, so a fixed zone clips. Mobile uses normal flow. */
@media (min-width: 768px) {
  html.js .flow { position: relative; z-index: 2; background: var(--black); }
  html.js .reveal-zone { position: fixed; left: 0; right: 0; bottom: 0; z-index: 1; width: 100%; }
  /* The zone is capped to one viewport because it is position:fixed — anything
     taller cannot be scrolled to. The timer therefore has to fit in whatever
     the footer leaves, so it gets the remaining space and centres in it. */
  html.js .reveal-zone:has(.final) { height: 100vh; height: 100dvh; display: flex; flex-direction: column; }
  html.js .reveal-zone:has(.final) .final { min-height: 0; flex: 1 1 auto; }
  html.js .reveal-zone:has(.final) footer.site { flex: 0 0 auto; }
  /* Two things were clipping the clock: it was sized from viewport WIDTH while
     its box was constrained by HEIGHT, and .final centres its content under
     overflow:hidden — so when the content outgrew the shrunk box it was cut off
     at BOTH ends, taking the eyebrow with it. Scrolling the overflow is not an
     option inside a fixed zone, so the content is scaled to fit instead. */
  /* Room above the numbers. The nav is fixed and overlays the top of this zone,
     so without it the eyebrow sat tight under the nav bar. */
  html.js .reveal-zone:has(.final) .final { padding: 104px 0 68px; }
  html.js .reveal-zone:has(.final) .clock { font-size: clamp(30px, min(8vw, 9vh), 96px); margin-bottom: min(14px, 1.6vh); }
  html.js .reveal-zone:has(.final) .clock-units { margin-bottom: min(34px, 3.2vh); }
  html.js .reveal-zone:has(.final) .final .eyebrow { margin-bottom: min(24px, 2.4vh); }
}

/* ── Mobile polish (≤640px) ─────────────────────────── */
@media (max-width: 640px) {
  .wrap { padding: 0 20px; }
  header.top { padding: 12px 16px; }
  /* Two-line logo on phones: "Music Tech" / "Summit" */
  .wordmark { font-size: 17px; line-height: 1.02; gap: 8px; }
  .wordmark__mark { width: 24px; }
  .foot-mark { width: 38px; }
  .wm-br { display: inline; }
  /* On phones the header is logo + burger, nothing else. Both the REGISTER
     button and the language switcher already exist inside the burger menu, so
     repeating them here left four competing elements in a 375px-wide bar. */
  .top-actions .reg { display: none; }
  .top-actions > .langsw { display: none; }
  .top-actions { gap: 6px; }
  .burger { margin-left: 0; }

  /* Display type. The old floor of 24px was set to stop long words breaking,
     but it was far too cautious: "TECHNOLOGY" is ten monospace characters, so
     at 335px of usable width roughly 50px still fits. 12vw lands at 45px on a
     375px phone — a hero title rather than a caption. */
  h1.hero-title { font-size: clamp(34px, 12vw, 96px); overflow-wrap: break-word; }
  .hero .inner { padding-top: 40px; }
  /* svh, not vh: on a phone vh is the height with the browser chrome hidden,
     so 100vh left the CTA under the address bar on first load. 88svh also
     lets the next section's top edge show, which says the page continues. */
  .hero { min-height: 88svh; }
  /* 64px cells across 375px is barely six lines — the grid stops reading as
     graph paper and starts reading as three stripes. */
  .hero-grid { background-size: 40px 40px; }
  /* Long enough to wrap to two lines, which reads better than one cramped
     line at 11px across the full width. */
  .hero .eyebrow { font-size: 12px; letter-spacing: .08em; line-height: 1.5; }
  .hero-sub { font-size: 16px; text-wrap: pretty; }

  /* Both actions full width and stacked. They were wrapping into an accidental
     two-row layout where the button was 231px and the link sat under it. */
  .hero .cta-row { flex-direction: column; align-items: stretch; gap: 12px; }
  .hero .cta-row .btn { justify-content: center; }
  .hero .cta-row .lnk { text-align: center; align-self: center; }

  /* Two columns for speaker cards. One column meant four 3:4 portraits stacked
     — 1790px, more than two screens of placeholders before anything else. */
  .speakers { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .speakers--placeholder { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spk .info { padding: 14px; }
  .spk .info h3 { font-size: 16px; }
  .spk .info .role { font-size: 10px; margin-top: 6px; }
  .spk .info .cap { font-size: 11px; margin-top: 6px; }

  /* 60vh for a single line of text is a whole screen spent on one sentence. */
  .interstitial { min-height: 40vh; padding: 32px 20px; }

  .phead h1 { font-size: clamp(23px, 6.8vw, 104px); overflow-wrap: break-word; }
  .page-top { padding: 120px 0 10px; }
  .clock { font-size: clamp(26px, 8.6vw, 110px); overflow-wrap: anywhere; }
  .pad { padding: 80px 0; }

  .sec-head h2 { font-size: clamp(24px, 7vw, 64px); overflow-wrap: break-word; }
  .final .eyebrow { overflow-wrap: break-word; }
  .interstitial .line { font-size: clamp(20px, 6vw, 52px); }

  /* Contact page */
  .contact-split { min-height: 0; }
  .contact-split > * { min-width: 0; }
  .contact-left, .contact-right { padding: 48px 20px; }
  .contact-left h2 { font-size: clamp(22px, 6.6vw, 58px); overflow-wrap: break-word; }
  .contact-left .info { overflow-wrap: anywhere; }
}
@media (max-width: 380px) {
  .wordmark { font-size: 15px; }
  .top nav a.reg { padding: 6px 9px; }
}

/* ── Language switcher (segmented toggle) ───────────── */
.langsw { position: relative; display: inline-flex; border: 1px solid var(--line); background: var(--black); overflow: hidden; flex-shrink: 0; }
.langsw a { position: relative; z-index: 2; font-family: var(--mono); font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: var(--gray); padding: 8px 13px; transition: color .28s ease; }
.langsw a.on { color: var(--black); }
.langsw a:not(.on):hover { color: var(--lime-dim); }
.langsw__pill { position: absolute; top: 0; bottom: 0; left: 0; width: 50%; background: var(--lime); z-index: 1; transition: transform .32s cubic-bezier(.5,0,.15,1); }
.langsw.is-en .langsw__pill { transform: translateX(100%); }
/* Bigger variant inside the mobile menu */
.mobile-menu .langsw { margin-top: 28px; }
.mobile-menu .langsw a { font-size: 15px; padding: 12px 22px; }

/* ── Programme page (rebuilt: both days visible, no scroll switcher) ── */
.prog{padding:0 0 120px}
.prog .wrap{display:flex;flex-direction:column;gap:72px}

/* Two days side by side */
.days{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:56px}
.day{min-width:0}
.day__head{border-top:2px solid var(--lime);padding-top:20px;margin-bottom:8px}
.day__kicker{font-family:var(--mono);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--lime-dim);margin:0 0 12px}
.day__venue{font-family:var(--body);font-weight:500;font-size:clamp(24px,3vw,34px);letter-spacing:-.01em;color:var(--white);margin:0 0 14px}
.day__tag{margin-bottom:16px}
.day__lead{color:var(--gray);font-size:15px;line-height:1.7;margin:0;max-width:44ch}
.day__list{list-style:none;margin:0;padding:0}
/* .slot / .t / .ti / .sp are shared with the old schedule styling */
.day__list .slot:first-child{border-top:1px solid var(--line-2)}

/* Practical details */
.facts{border-top:1px solid var(--line);padding-top:44px}
.facts__title{font-family:var(--body);font-weight:500;font-size:clamp(22px,2.6vw,30px);margin:0 0 28px;color:var(--white)}
.facts__list{margin:0 0 36px;display:grid;grid-template-columns:1fr}
/* One column on purpose: a two-column grid fills row-first, so "Dag 1" landed
   beside "När" and "Dag 2" below it — the order stopped reading top to bottom. */
.facts__row{display:grid;grid-template-columns:9rem 1fr;gap:16px;padding:14px 0;border-top:1px solid var(--line-2);min-width:0}
.facts__row dt{font-family:var(--mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--gray-2);padding-top:3px}
.facts__row dd{margin:0;color:var(--white);font-size:16px;line-height:1.6}
.facts__note{color:var(--gray-2);font-size:14px;line-height:1.7;margin:16px 0 0;max-width:52ch}
.facts__ask{color:var(--gray);font-size:15px;line-height:1.7;margin:20px 0 0;padding-top:20px;border-top:1px solid var(--line-2);max-width:52ch}
.facts__ask a{color:var(--lime-dim);text-decoration:none;border-bottom:1px solid rgba(204,255,0,.35);white-space:nowrap}
.facts__ask a:hover{border-bottom-color:var(--lime)}

@media (max-width:900px){
  .prog .wrap{gap:56px}
  .days{grid-template-columns:1fr;gap:48px}
}
@media (max-width:640px){
  .facts__row{grid-template-columns:1fr;gap:4px}
}

/* ── Tickets: stub beside the FAQ on wide screens ── */
.tickets__grid{display:grid;gap:56px}
.tickets__stub{max-width:480px}
.faq-head{font-family:var(--body);font-weight:500;font-size:clamp(22px,2.4vw,28px);letter-spacing:-.01em;text-transform:none;color:var(--white);margin:0 0 22px}
/* The FAQ's own max-width fought the column, so drop it here and let the
   column decide; the answers keep a readable measure of their own. */
.tickets__faq .faq{max-width:none}
.tickets__faq .faq p{max-width:62ch}
/* Contact block: closes the right column and gives the page a CTA that is not
   buried inside the ticket illustration. */
.ask{margin-top:44px;padding-top:30px;border-top:1px solid var(--line)}
.ask__title{font-family:var(--body);font-weight:500;font-size:20px;letter-spacing:-.01em;text-transform:none;color:var(--white);margin:0 0 12px}
.ask__body{font-family:var(--body);font-size:15px;color:rgba(255,255,255,.7);line-height:1.7;margin:0 0 18px;max-width:56ch}
.ask__mail{font-family:var(--mono);font-size:14px;letter-spacing:.04em;color:var(--lime-dim);border-bottom:1px solid rgba(204,255,0,.35);white-space:nowrap}
.ask__mail:hover{border-bottom-color:var(--lime)}
.ask__second{font-family:var(--body);font-size:14px;color:var(--gray);margin:22px 0 0;padding-top:18px;border-top:1px solid var(--line-2)}
.ask__second a{color:var(--lime-dim);border-bottom:1px solid rgba(204,255,0,.35);white-space:nowrap}
.ask__second a:hover{border-bottom-color:var(--lime)}

@media(min-width:1000px){
  /* The left column is auto, not a fixed 480px: the stub is zoomed below, and
     zoom changes layout size, so a fixed track would let a scaled-up ticket
     bleed across the gap into the FAQ. Auto measures whatever the zoom made. */
  .tickets__grid{grid-template-columns:auto minmax(0,1fr);gap:80px;align-items:start}
  .tickets__stub{width:480px}
  /* The stub is the reference the answers refer to, so it stays in view while
     the FAQ is read. 96px clears the fixed nav. */
  .tickets__stub{position:sticky;top:96px;align-self:start}

  /* Sticky only holds an element that fits: once the ticket is taller than the
     window, its top never reaches 96px before the column beside it runs out,
     and it scrolls away instead of pinning. That is exactly what happens on a
     laptop — the ticket is ~710px and a 13" window has roughly 700px of page
     under the browser chrome.

     So the ticket scales to the window's height. `zoom` and not `transform:
     scale()` on purpose: zoom shrinks the box in layout, so the sticky
     wrapper gets shorter too and the FAQ beside it gains real travel to
     scroll past. A transform would leave a 710px hole behind. Browsers that
     ignore zoom fall back to today's behaviour, not to a broken layout.

     It scales in both directions, in steps of window height, so a tall screen
     gets a bigger ticket rather than the same one with empty space under it.
     The ticket is ~710px unscaled, and the budget is the window minus the
     96px nav and a little air. The floor is .82 and not lower: below that the
     12px monospace rows in the ticket stop being comfortably readable, and a
     ticket you cannot read is worse than one you have to scroll past. */
  @media (max-height:900px){ .tickets__stub .stub{zoom:.88} }
  @media (max-height:790px){ .tickets__stub .stub{zoom:.82} }
  @media (min-height:1000px){ .tickets__stub .stub{zoom:1.12} }
  @media (min-height:1120px){ .tickets__stub .stub{zoom:1.24} }
  @media (min-height:1300px){ .tickets__stub .stub{zoom:1.4} }
}

/* ── Programme not announced yet ── */
/* Reads as a placeholder on purpose: dashed edge, faint grid, and a pulsing
   marker — the visual language of something still being assembled rather than
   an error or a warning. */
.tba{
  position:relative;overflow:hidden;
  display:grid;grid-template-columns:auto 1fr;gap:28px;align-items:center;
  padding:40px 40px;
  border:1px dashed var(--line-firm);
  background:
    radial-gradient(120% 140% at 0% 0%,rgba(204,255,0,.07),transparent 55%),
    linear-gradient(180deg,#111110,#0b0b0a);
}
/* Faint graph paper — suggests a plan being drawn */
.tba::before{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.5;
  background-image:
    linear-gradient(rgba(255,255,255,.035) 1px,transparent 1px),
    linear-gradient(90deg,rgba(255,255,255,.035) 1px,transparent 1px);
  background-size:34px 34px;
  mask-image:linear-gradient(105deg,#000,transparent 72%);
  -webkit-mask-image:linear-gradient(105deg,#000,transparent 72%);
}
.tba > *{position:relative;z-index:1}

.tba__label{
  font-family:var(--mono);font-size:12px;letter-spacing:.2em;
  color:var(--lime-dim);border:1px solid rgba(204,255,0,.4);
  padding:10px 14px;white-space:nowrap;
  display:inline-flex;align-items:center;gap:10px;
  background:rgba(204,255,0,.05);
}
/* Small blinking dot: work in progress, not a failure */
.tba__label::before{
  content:"";width:7px;height:7px;border-radius:50%;
  background:var(--lime);flex:none;
  animation:tba-pulse 2.4s ease-in-out infinite;
}
@keyframes tba-pulse{
  0%,100%{opacity:1;box-shadow:0 0 0 0 rgba(204,255,0,.45)}
  50%{opacity:.45;box-shadow:0 0 0 7px rgba(204,255,0,0)}
}
@media (prefers-reduced-motion:reduce){
  .tba__label::before{animation:none}
}

.tba__title{
  font-family:var(--disp);font-weight:400;
  font-size:clamp(22px,3.2vw,32px);line-height:1.15;letter-spacing:-.01em;
  color:var(--white);margin:0 0 12px;text-wrap:balance;
}
.tba__body{color:var(--gray);font-size:16px;line-height:1.75;margin:0;max-width:56ch}


@media (max-width:640px){
  .tba{grid-template-columns:1fr;gap:20px;padding:28px 22px;align-items:start}
  .tba__label{justify-self:start}
}

/* Contact form states + honeypot */
.hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0;pointer-events:none}
.form-note--ok{color:var(--lime-dim)}
.form-note--err{color:#ff8f8f}

/* ── Programme items ─────────────────────────────────────────────────────
   The .slot styles above date from the old invented schedule; these add what
   the Sanity-backed items need on top. */
.day__list{list-style:none;margin:24px 0 0;padding:0}
.slot__who{font-family:var(--body);font-size:14px;color:var(--lime-dim);margin:8px 0 0;line-height:1.5}
.slot__desc{font-family:var(--body);font-size:14px;color:var(--gray);margin:8px 0 0;line-height:1.6;max-width:52ch}
/* Breaks and registration are the frame of the day, not its content. */
.slot--quiet .ti{color:var(--gray);font-weight:400;font-size:16px}
.slot--quiet .t{color:var(--gray-2)}

/* Per-day placeholder, shown when a day has no published items yet. Returned
   after the schedule became CMS-driven: a day can now be empty while the other
   one already has a programme. */
.day__tba{
  font-family:var(--mono);font-size:12px;letter-spacing:.2em;color:var(--gray-2);
  border-top:1px dashed var(--line);padding:26px 0 0;margin:26px 0 0;
  display:flex;align-items:center;gap:10px;
}
.day__tba::before{content:"";width:5px;height:5px;border-radius:50%;background:var(--gray-2);flex:none}

/* Part of the day as a heading over its slots, rather than repeated on every
   row. Until exact times exist this is the only ordering the reader sees, so
   it has to read as structure. */
.day__group{margin-top:28px}
.day__slot{
  font-family:var(--mono);font-size:12px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--lime-dim);margin:0 0 2px;padding-bottom:10px;border-bottom:1px solid var(--lime);
}
.day__group .day__list{margin-top:0}
.day__group .slot:first-child{border-top:0}

/* The "filling up" state. Same panel, but solid rather than dashed and with a
   lime edge: dashed reads as a gap waiting to be filled, and once real content
   exists below it the panel is a status line, not a placeholder. */
.tba--filling{
  border-style:solid;
  border-color:var(--line-2);
  border-left:2px solid var(--lime);
}
.tba--filling .tba__label{border-color:rgba(204,255,0,.55)}
