/* Satoshi (Fontshare, ITF Free Font License), self-hosted */
@font-face{font-family:"Satoshi";font-style:normal;font-weight:300;font-display:swap;src:url("/assets/fonts/satoshi-300.woff2") format("woff2");}
@font-face{font-family:"Satoshi";font-style:normal;font-weight:400;font-display:swap;src:url("/assets/fonts/satoshi-400.woff2") format("woff2");}
@font-face{font-family:"Satoshi";font-style:normal;font-weight:700;font-display:swap;src:url("/assets/fonts/satoshi-700.woff2") format("woff2");}

  :root{
    --ink:        #f4f4f5;
    --ink-soft:   #d5d5d8;
    --ink-mute:   #a7a7ac;
    --ink-faint:  #7c7c83;
    --ground:     #1b1b1e;
    --ground-up:  #232327;
    --rule:       rgba(255,255,255,.11);

    /* one spacing scale — every vertical gap comes from here, which is
       what the old hero was missing */
    --s1: .35rem;
    --s2: .75rem;
    --s3: 1.25rem;
    --s4: 2rem;
    --s5: 3rem;

    --narrow: 58ch;
    --wide: 74rem;
    --pad: clamp(1.5rem, 5vw, 5rem);
    --font: "Satoshi", "Satoshi-Variable", sans-serif;

    /* the one knob for grain intensity */
    --grain: .06;
  }

  /* site-wide film grain. fixed, so it stays put while the page scrolls
     rather than sliding with the content. */
  body::after{
    content:"";
    position:fixed; inset:0;
    z-index:9999;
    pointer-events:none;
    opacity:var(--grain);
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23g)'/%3E%3C/svg%3E");
    background-size:200px 200px;
  }

  *,*::before,*::after{ box-sizing:border-box; }
  html{ -webkit-text-size-adjust:100%; }

  /* Lenis drives scrolling once it initialises; native smooth-scroll is
     left on as the fallback when it doesn't. */
  html.lenis, html.lenis body{ height:auto; }
  html:not(.lenis){ scroll-behavior:smooth; }
  .lenis.lenis-smooth{ scroll-behavior:auto !important; }
  .lenis.lenis-stopped{ overflow:hidden; }

  body{
    margin:0;
    background:var(--ground);
    color:var(--ink-soft);
    font-family:var(--font);
    font-weight:300;
    font-synthesis:none;
    font-size:clamp(1rem, .95rem + .3vw, 1.125rem);
    line-height:1.6;
    -webkit-font-smoothing:antialiased;
  }

  a{ color:var(--ink); text-decoration:none; border-bottom:1px solid var(--rule); }
  a:hover{ border-bottom-color:var(--ink); }
  a:focus-visible, button:focus-visible, summary:focus-visible{
    outline:2px solid var(--ink); outline-offset:4px; border-radius:2px;
  }

  .skip{ position:absolute; left:-9999px; top:0; z-index:99;
         background:var(--ink); color:#111; padding:.6rem 1rem; border:0; }
  .skip:focus{ left:.5rem; top:.5rem; }

  p{ margin:0 0 1.15rem; }
  p:last-child{ margin-bottom:0; }

  /* =====================================================
     HERO — layered: base wash, drifting mesh, grain, vignette
     ===================================================== */
  .hero{
    position:relative;
    min-height:100svh;
    display:grid;
    place-items:center;
    padding:calc(var(--pad) + 1rem) var(--pad);
    overflow:hidden;
    isolation:isolate;
    /* Fitted by least squares to the original design (pure neutral greys,
       rmse ~6/255). Light across the top, darkness rising from the bottom-left,
       light holding longest centre-right. The pool behind the lockup is NOT in
       the original — it's there so the white wordmark clears contrast. */
    background-color:#3a3a3a;
    background-image:
      /* resolves the last band onto --ground so there's no seam */
      linear-gradient(to bottom, rgba(27,27,30,0) 80%, #1b1b1e 100%),
      /* contrast pool behind the lockup */
      radial-gradient(62% 50% at 50% 45%, rgba(14,14,14,.40) 0%, rgba(14,14,14,0) 100%),
      /* shadow rising from the bottom-left */
      radial-gradient(89.6% 60.2% at -24.0% 79.4%, rgba(0,0,0,1) 0%, rgba(0,0,0,0) 100%),
      /* light pool, holds longest centre-right */
      radial-gradient(48.6% 35.8% at 63.3% 54.2%, rgba(255,255,255,.577) 0%, rgba(255,255,255,0) 100%),
      /* base ramp */
      linear-gradient(163.6deg,
        #c8c8c8 0%, #b0b0b0 16.7%, #9e9e9e 33.3%, #898989 50%,
        #494949 66.7%, #242424 83.3%, #242424 100%);
  }

  /* held back until fonts have loaded and GSAP has taken over — see the
     inline script in <head>. The gradient still paints immediately, so
     the page never looks blank. */
  .is-loading .lockup > *{ opacity:0; }

  /* ---- lockup: one unit, tight internal spacing ---- */
  .lockup{
    position:relative; z-index:1;
    display:flex; flex-direction:column; align-items:center;
    width:fit-content; max-width:100%;
  }

  .pin{
    width:clamp(1.5rem, 2.9vw, 3.4rem); height:auto; display:block;
    margin-bottom:clamp(.85rem, 2.2vw, 2.25rem);
  }
  /* semi-transparent so the gradient reads through it, with the inner
     dot brighter than the body — as in the reference */
  .pin-body{ fill:rgba(255,255,255,.44); }
  .pin-dot{ fill:rgba(255,255,255,.58); }

  .wordmark{
    margin:0; font-weight:700;
    font-size:clamp(3.1rem, 13vw, 15rem);
    line-height:.9; letter-spacing:-.034em;
    color:var(--ink); white-space:nowrap;
  }

  /* 'hackathons' belongs to the name, so it sits tight under the
     wordmark: its baseline lines up with the bottom of the 'p'. */
  .lockup-suffix{
    align-self:flex-end;
    margin-top:.3rem;
    font-weight:300;
    font-size:clamp(1rem, 2.35vw, 2.2rem);
    line-height:1;
    letter-spacing:-.014em;
    color:var(--ink-soft);
    white-space:nowrap;
  }

  /* event facts: their own group, clearly separated from the name */
  .event-meta{
    margin:var(--s4) 0 0;
    display:flex; flex-wrap:wrap; justify-content:center;
    gap:var(--s1) var(--s3);
    font-weight:300;
    font-size:clamp(.85rem, 1.5vw, 1.1rem);
    color:var(--ink);
    text-align:center;
  }
  .event-meta .lead{ color:var(--ink); }
  .event-meta .sep{ color:var(--ink-faint); }

  .actions{ display:flex; flex-wrap:wrap; justify-content:center; gap:var(--s2) var(--s3); }
  .hero .actions{ margin-top:var(--s5); }

  .btn{
    display:inline-block; padding:.72rem 1.65rem;
    border:1px solid rgba(255,255,255,.55); border-radius:999px;
    background:transparent; color:var(--ink);
    font-family:var(--font); font-weight:300; font-size:1rem; cursor:pointer;
    transition:background .2s ease, color .2s ease, border-color .2s ease;
  }
  .btn:hover{ background:var(--ink); color:#1a1a1c; border-color:var(--ink); }
  .btn-quiet{ border-color:var(--rule); color:var(--ink-mute); }
  .btn-quiet:hover{ background:transparent; color:var(--ink); border-color:var(--ink); }

  @media (max-width: 620px){
    .lockup{ width:100%; }
    .wordmark{ font-size:clamp(2.9rem, 15.5vw, 5rem); text-align:center; align-self:center; }
    .lockup-suffix{ align-self:center; margin-top:clamp(.85rem, 2.3vw, 2.4rem); font-size:clamp(1.05rem, 4.6vw, 1.6rem); }
    .event-meta{ flex-direction:column; gap:var(--s1); }
    .event-meta .sep{ display:none; }
    .actions .btn{ flex:1 1 auto; text-align:center; }
  }


  /* =====================================================
     TOP NAV — sits over the hero, out of the layout flow so it
     can't move anything. The scrim keeps the white links legible
     on the light top of the hero.
     ===================================================== */
  .topnav{
    position:absolute; top:0; left:0; right:0; z-index:20;
    display:flex; flex-wrap:wrap; justify-content:space-between; align-items:baseline;
    gap:var(--s1) var(--s4);
    padding:1.1rem var(--pad) 2.25rem;
    background:linear-gradient(to bottom, rgba(14,14,14,.58), rgba(14,14,14,0));
    font-size:.9rem; line-height:1.4;
  }
  .topnav ul{ list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:var(--s1) var(--s3); }
  .topnav a{ color:var(--ink); border-bottom:1px solid transparent; }
  .topnav a:hover, .topnav a[aria-current]{ border-bottom-color:var(--ink); }
  @media (max-width: 620px){
    .topnav{ font-size:.85rem; }
  }

  /* =====================================================
     SHARED
     ===================================================== */
  .wrap-wide{ max-width:var(--wide); margin-inline:auto; }

  .h-section{
    margin:0 0 var(--s3); font-weight:300;
    font-size:clamp(1.55rem, 3.2vw, 2.3rem);
    line-height:1.15; letter-spacing:-.022em; color:var(--ink);
  }
  .kicker{ margin:0; color:var(--ink-faint); font-size:.92rem; line-height:1.5; }

  /* =====================================================
     INTRO
     ===================================================== */
  .intro{ padding:clamp(4.5rem, 15vh, 10rem) var(--pad) clamp(3.5rem, 9vh, 6rem); }
  .intro-lede{
    max-width:20ch; margin:0 0 clamp(2.25rem, 6vh, 3.25rem);
    font-weight:300; font-size:clamp(2.15rem, 6.5vw, 4.4rem);
    line-height:1.04; letter-spacing:-.032em; color:var(--ink);
  }
  .intro-cols{
    display:grid; grid-template-columns:repeat(auto-fit, minmax(17rem, 1fr));
    gap:0 clamp(2rem, 6vw, 5rem); max-width:54rem;
  }
  .intro-cols p{
    margin:0; padding-top:var(--s3);
    border-top:1px solid var(--rule);
  }
  @media (max-width: 620px){
    .intro-cols{ gap:var(--s3) 0; }
  }

  /* =====================================================
     THEME
     ===================================================== */
  .theme{ padding:clamp(3.5rem, 9vh, 6rem) var(--pad); border-top:1px solid var(--rule); }
  .theme-grid{
    display:grid; grid-template-columns:minmax(0, 15rem) minmax(0, 1fr);
    gap:var(--s4) clamp(2rem, 7vw, 6rem);
  }
  .theme-head{ position:sticky; top:clamp(1.5rem, 6vh, 4rem); align-self:start; }
  .theme-head .h-section{ margin-bottom:var(--s2); }
  .theme-body{ max-width:var(--narrow); }

  .directions{ list-style:none; margin:var(--s4) 0; padding:0; }
  .directions li{
    padding:var(--s3) 0 var(--s3) 2.25rem;
    border-top:1px solid var(--rule);
    position:relative; color:var(--ink);
  }
  .directions li:last-child{ border-bottom:1px solid var(--rule); }
  .directions li::before{
    content:""; position:absolute; left:.4rem; top:1.85rem;
    width:.42rem; height:.42rem; border-radius:50%; background:var(--ink-faint);
  }
  @media (max-width: 780px){
    .theme-grid{ grid-template-columns:1fr; gap:var(--s3); }
    .theme-head{ position:static; }
  }

  /* =====================================================
     SCHEDULE
     ===================================================== */
  .schedule{
    padding:clamp(3.5rem, 9vh, 6rem) var(--pad);
    border-top:1px solid var(--rule);
    background:var(--ground-up);
  }
  .sched{ list-style:none; margin:var(--s4) 0; padding:0; }
  .sched-rule{ display:block; height:1px; background:var(--rule); transform-origin:left center; }
  .sched-row{
    display:grid;
    grid-template-columns:minmax(10rem,13rem) minmax(0,1fr) minmax(9rem,12rem);
    gap:var(--s1) var(--s4); align-items:baseline; padding:var(--s3) 0;
  }
  .sched-when{ color:var(--ink); font-weight:300; }
  .sched-what{ color:var(--ink-soft); }
  .sched-else{ color:var(--ink-faint); font-size:.9rem; }
  .sched-note{ max-width:var(--narrow); color:var(--ink-mute); }

  @media (max-width: 820px){
    /* on narrow screens the time becomes the anchor and the row reads
       top-down: when, what, elsewhere */
    .sched-row{ grid-template-columns:1fr; gap:var(--s1); padding:var(--s3) 0; }
    .sched-when{ font-size:1.1rem; letter-spacing:-.01em; }
    .sched-what{ font-size:.98rem; }
    .sched-else{ order:3; font-size:.82rem; }
  }

  /* =====================================================
     PRIZES
     ===================================================== */
  .prizes{
    padding:clamp(3.5rem, 9vh, 6rem) var(--pad);
    border-top:1px solid var(--rule); text-align:center;
  }
  .prizes .h-section{ margin-bottom:var(--s2); }
  .prizes p{ margin-inline:auto; max-width:46ch; color:var(--ink-mute); }
  /* prizes grouped by who wins them: four blocks, each under a hairline
     rule like the stats on /sponsors/. One column, then 2x2 from 900px. */
  .prize-groups{
    display:grid; grid-template-columns:minmax(0,1fr); gap:var(--s4);
    max-width:52rem; margin:var(--s4) auto 0; text-align:left;
  }
  .prize-group{ border-top:1px solid var(--rule); padding-top:var(--s3); }
  /* the kicker's small letter-spaced label, but in --ink-mute: --ink-faint
     is only 4.15:1 on the ground, --ink-mute is 7.2:1 */
  .prize-group h3{
    margin:0 0 var(--s2);
    font-size:.82rem; font-weight:300; letter-spacing:.1em; line-height:1.4;
    color:var(--ink-mute);
  }
  .prize-group ul{ list-style:none; margin:0; padding:0; max-width:36ch; }
  .prize-group li{ color:var(--ink); }
  .prize-group li + li{ margin-top:.6rem; }
  @media (min-width: 900px){
    .prize-groups{ grid-template-columns:repeat(2, minmax(0,1fr)); gap:var(--s5) clamp(2.5rem, 6vw, 5rem); }
  }

  /* sponsor logos — normalised to a single optical height and forced to
     flat white, so mixed source files sit together consistently */
  .sponsors-label{
    margin:clamp(2.5rem,6vh,4rem) 0 var(--s3);
    font-size:.82rem; letter-spacing:.1em; color:var(--ink-faint);
  }
  .sponsors{
    --logo-gap:clamp(1.75rem,5vw,3.75rem);
    display:flex; flex-wrap:wrap; justify-content:center; align-items:center;
    gap:var(--logo-gap);
  }
  .sponsors a{ display:block; border:0; line-height:0; }
  .sponsors img{
    height:clamp(1.4rem,2.8vw,2rem);
    width:auto; max-width:10rem;
    object-fit:contain;
    /* brightness(0) flattens any colour to black while keeping the alpha
       channel, then invert(1) makes it white — works on any source logo */
    filter:brightness(0) invert(1);
    opacity:.72;
    transition:opacity .25s ease;
  }
  .sponsors a:hover img{ opacity:1; }
  /* this file carries more internal whitespace than the others, so it needs
     a larger box to sit at the same optical size */
  .sponsors .logo-1p img,
  .sponsors .logo-cp img,
  .sponsors .logo-cc img,
  .sponsors .logo-fl img,
  .sponsors .logo-hcl img{ height:clamp(2.85rem,5.7vw,4.05rem); max-width:20rem; }
  /* Formaloo: plain invert instead of flattening to white, so the coloured
     mark in the middle of the logo stays distinct from the wordmark */
  .sponsors .logo-fl img{ filter:invert(1); }
  /* CleanShot is trimmed to its wordmark, so it needs a smaller box than the
     base one to sit at the same optical size as the others */
  .sponsors .logo-cs img{ height:clamp(.67rem,1.34vw,.95rem); }

  /* ---- sponsor carousel ----
     Progressive enhancement over the wrapping row above. js/marquee.js
     adds .is-marquee, moves the logos into a .marquee-set and clones that
     set into aria-hidden copies; the track then slides left by exactly
     one set width per loop. With no JS or with reduced motion, none of
     this applies and the row wraps as written. */
  .sponsors.is-marquee{
    display:block;
    width:0; min-width:100%; /* fill the column without the track widening it */
    overflow:hidden; overflow:clip; /* clip: focus can't scroll the viewport */
    -webkit-mask-image:linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
    mask-image:linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  }
  /* where scripting is on, lay the row out as one clipped line from the
     first paint, so its height doesn't change when the script takes over */
  @media (scripting: enabled) and (prefers-reduced-motion: no-preference){
    .sponsors{
      flex-wrap:nowrap; justify-content:flex-start !important;
      width:0; min-width:100%;
      overflow:hidden; overflow:clip;
      -webkit-mask-image:linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
      mask-image:linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
    }
    .sponsors > a{ flex:none; }
  }
  .is-marquee .marquee-track{
    display:flex; width:max-content;
    animation:sponsor-marquee var(--marquee-duration, 30s) linear infinite;
  }
  /* the trailing padding is the gap after the last logo, so one set width
     is exactly one loop and the seam doesn't jump */
  .is-marquee .marquee-set{
    display:flex; flex:none; align-items:center;
    gap:var(--logo-gap); padding-right:var(--logo-gap);
  }
  .is-marquee:hover .marquee-track,
  .is-marquee:focus-within .marquee-track,
  .is-marquee.is-offscreen .marquee-track{ animation-play-state:paused; }
  .is-marquee:not(.is-offscreen):not(:hover):not(:focus-within) .marquee-track{ will-change:transform; }
  @keyframes sponsor-marquee{
    to{ transform:translate3d(var(--marquee-shift, -50%), 0, 0); }
  }

  /* =====================================================
     PRESS — "as featured in"
     ===================================================== */
  .press{
    padding:clamp(2.5rem, 6vh, 4rem) var(--pad);
    border-top:1px solid var(--rule); text-align:center;
  }
  /* the label and link margins are small on purpose: the text's own
     line-height adds ~7px under the label and ~14px above each link, so
     these leave about 1rem of visible space either side of the logo */
  .press-label{
    margin:0 0 .6rem;
    font-size:.82rem; letter-spacing:.1em; color:var(--ink-faint);
  }
  .press-logo{ display:inline-block; border:0; line-height:0; }
  /* the file is trimmed to the mark, so the box height is the visible height:
     sized so the wordmark matches the sponsor row's */
  .press-logo img{
    height:clamp(1.55rem,3.1vw,2.2rem); width:auto; max-width:100%;
    object-fit:contain;
    filter:brightness(0) invert(1);
    opacity:.72; transition:opacity .25s ease;
  }
  .press-logo:hover img{ opacity:1; }
  .press-link{ margin:.2rem auto 0; color:var(--ink-mute); font-size:.95rem; }

  /* =====================================================
     FAQ
     ===================================================== */
  .faq{ padding:clamp(3.5rem, 9vh, 6rem) var(--pad); border-top:1px solid var(--rule); }
  .faq-grid{
    display:grid; grid-template-columns:minmax(0, 15rem) minmax(0, 1fr);
    gap:var(--s4) clamp(2rem, 7vw, 6rem);
  }
  .faq-head{ position:sticky; top:clamp(1.5rem, 6vh, 4rem); align-self:start; }
  .faq-head .h-section{ margin-bottom:var(--s2); }
  .faq-list{ max-width:var(--narrow); }

  .faq-list details{ border-top:1px solid var(--rule); padding-block:var(--s3); }
  .faq-list details:last-of-type{ border-bottom:1px solid var(--rule); }
  .faq-list summary{
    cursor:pointer; font-weight:300; color:var(--ink); list-style:none;
    display:flex; justify-content:space-between; align-items:flex-start; gap:var(--s3);
    font-size:1.05rem; line-height:1.45;
  }
  .faq-list summary::-webkit-details-marker{ display:none; }

  .faq-mark{ position:relative; width:.8rem; height:.8rem; flex:none; margin-top:.3rem; }
  .faq-mark::before,
  .faq-mark::after{
    content:""; position:absolute; left:0; right:0; top:50%;
    height:1px; background:var(--ink-faint);
    transition:transform .5s cubic-bezier(.22,1,.3,1), background-color .2s ease;
  }
  .faq-mark::after{ transform:rotate(90deg); }
  .faq-list details[open] .faq-mark::after{ transform:rotate(0deg); }
  .faq-list summary:hover .faq-mark::before,
  .faq-list summary:hover .faq-mark::after{ background:var(--ink); }

  .faq-body{ overflow:hidden; }
  .faq-list details p{ margin:var(--s2) 0 0; color:var(--ink-soft); }

  @media (max-width: 780px){
    .faq-grid{ grid-template-columns:1fr; gap:var(--s3); }
    .faq-head{ position:static; }
  }

  /* =====================================================
     CLOSER
     ===================================================== */
  .closer{
    position:relative; overflow:hidden;
    padding:clamp(4.5rem, 15vh, 9rem) var(--pad); text-align:center;
    border-top:1px solid var(--rule);
    background-image:radial-gradient(ellipse 85% 130% at 50% 122%, rgba(198,200,210,.17) 0%, rgba(198,200,210,0) 66%);
  }
  .closer-line{
    margin:0 auto var(--s3); max-width:18ch;
    font-weight:300; font-size:clamp(1.9rem, 5vw, 3.4rem);
    line-height:1.08; letter-spacing:-.03em; color:var(--ink);
  }
  .closer p{ color:var(--ink-mute); }
  .closer .actions{ margin-top:var(--s4); }
  .closer .closer-note{ margin:var(--s4) 0 0; font-size:.95rem; }

  /* =====================================================
     FOOTER
     ===================================================== */
  footer{
    border-top:1px solid var(--rule); background:var(--ground-up);
    padding:clamp(2.5rem, 6vh, 4rem) var(--pad);
    font-size:.9rem; color:var(--ink-faint);
  }
  .foot-inner{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:var(--s4) 3rem; }
  .foot-inner p{ margin:0 0 var(--s1); }
  footer a{ color:var(--ink-mute); }

  @media (prefers-reduced-motion: reduce){
    html{ scroll-behavior:auto; }
    *{ transition:none !important; }
  }
