/* ===================================================================
   48.studio — v1.0 (Figma-driven layout)

   Typeface: "BB Modern Trial" (trial license — swap for the licensed
   webfont once that's sorted). Served as woff2, converted from the
   .otf in assets/fonts/. Falls back to Georgia/Times if it fails to
   load for any reason.
=================================================================== */

@font-face {
  font-family: 'BB Modern Trial';
  src: url('../assets/fonts/BBModernTrial-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #ffffff;
  --fg: #111111;
  --fg-dim: #cccccc;
  --fg-faint: #dddddd;

  --font-body: 'BB Modern Trial', Georgia, 'Times New Roman', serif;

  --pad: clamp(16px, 3vw, 40px);
  --topbar-h: 28px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  height: 100%;
  color: var(--fg);
  /* Single fixed-viewport page (see .wrap min-height:100dvh below) --
     touch-action:none stops mobile browsers from panning/rubber-
     banding or pinch-zooming while a finger drags across the page to
     paint the trail (see js/trail.js touchmove handler). */
  touch-action: none;
  overscroll-behavior: none;
}

body {
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

.wrap {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--pad);
  padding-top: calc(var(--pad) + var(--topbar-h));
}

/* ---- Top utility bar ----
   Fixed to the viewport (not part of .wrap's flow) so it stays put
   regardless of scroll or hero content height. .wrap's padding-top
   above reserves --topbar-h so hero content never sits under it. */

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  display: grid;
  /* Equal 1fr side columns keep the middle (time) column centered on
     the page regardless of how long the date/location text is —
     flex's justify-content: space-between can't guarantee that when
     the two outer items are different widths. */
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: var(--pad);
}

.topbar-item {
  font-size: clamp(11px, 1.1vw, 14px);
  letter-spacing: -0.01em;
  color: var(--fg-dim);
  white-space: nowrap;
}

.topbar-time {
  font-variant-numeric: tabular-nums;
}

.topbar-location {
  text-align: right;
}

/* ---- Hero ---- */

.hero {
  flex: 1;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(12px, 2vh, 24px);
  text-align: center;
}

/* The wordmark is rendered in flat white then run through
   mix-blend-mode: difference against whatever is actually behind it
   (the plain page background, or a trail square). White-on-white
   differences to black — the normal look on the page background —
   and flips to white the instant a dark trail square passes behind,
   so it's always legible no matter what's underneath. (Requires .wrap
   and its ancestors to stay out of their own stacking context — see
   #page-bg / #trail-layer below — or the blend can't see past them to
   the trail.) The copy and CTA intentionally opt out of this and just
   sit at the same flat --fg-dim gray as the header content instead. */

.wordmark {
  width: min(60vw, 720px);
  height: auto;
  display: block;
  filter: brightness(0) invert(1);
  mix-blend-mode: difference;
}

.copy {
  max-width: 760px;
  font-size: clamp(14px, 1.4vw, 20px);
  line-height: 1.35;
  color: var(--fg-dim);
  padding: 0 var(--pad);
  text-wrap: pretty;
}

.cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--fg-dim);
  text-decoration: none;
  font-size: clamp(14px, 1.4vw, 20px);
  transition: color 0.25s ease;
}

.cta-arrow {
  transition: transform 0.25s ease;
}

.cta:hover {
  color: var(--fg);
}

.cta:hover .cta-arrow {
  transform: translate(2px, -2px);
}

/* ---- Bottom mark ---- */

.mark {
  padding-top: clamp(24px, 4vh, 48px);
}

.symbol {
  width: clamp(28px, 3.4vw, 44px);
  height: auto;
  display: block;
  filter: brightness(0) invert(1);
  mix-blend-mode: difference;
}

/* ---- Responsive ---- */

@media (max-width: 560px) {
  :root {
    --topbar-h: 76px;
  }

  .topbar {
    grid-template-columns: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
  }

  .topbar-location {
    text-align: center;
  }
}

/* ---- Page background + mouse trail ----
   #page-bg carries the white fill that used to live on html/body.
   It has to live here, as its own element, rather than as a
   background on html/body: a background declared directly on
   html/body gets promoted to paint the document canvas itself, which
   sits *below* even negative-z-index children — it would swallow
   #trail-layer entirely instead of letting it stack above.

   #trail-layer holds the squares that spawn along the cursor's path
   (see js/trail.js — the grow/shrink easing is driven entirely by JS,
   no CSS transition/animation here on purpose). Both this and
   #page-bg sit at negative z-index, and neither .wrap nor any of its
   ancestors are positioned/z-indexed — so both stay in the page's one
   shared (root) stacking context. That's what lets the hero content's
   mix-blend-mode: difference (see .wordmark/.copy/.cta/.symbol above)
   actually see and react to the squares behind it: blending can only
   "see" content painted within the same stacking context, and a
   positioned ancestor in between would wall that off. Plain in-flow
   content always paints above negative-z-index content regardless of
   DOM order, so this also keeps the trail visually behind everything
   without any extra z-index needed on the content side. Neither layer
   blocks clicks. */

#page-bg {
  position: fixed;
  inset: 0;
  z-index: -2;
  background: var(--bg);
  pointer-events: none;
}

#trail-layer {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: hidden;
}

.particle {
  position: absolute;
  top: 0;
  left: 0;
  border-radius: 0;
  background: var(--fg);
  overflow: hidden;
  will-change: transform, opacity;
  box-shadow: none;
  opacity: 0;
}

.particle img,
.particle video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
