/* ==========================================================================
   Blush Hour — landing page

   One screen, never scrolls, two layouts:

   1. Phone (below 900px) — logo with the text links beneath it. No imagery,
      no ticker, no glows.

   2. Desktop (900px and up) — the scattered composition from
      layout-editor.html. Everything is positioned in percentages inside a
      box of fixed 1440 x 740 proportions, and that box is sized to fit the
      viewport in BOTH directions, so the whole arrangement scales as one
      piece and always lands on a single screen.

   Desktop coordinates come straight out of the layout editor:
   left = x / 1440, top = y / 740, width = w / 1440.

   Stacking, back to front: ticker, pink diamonds, carousel frames, logo,
   nav.
   ========================================================================== */

:root {
  /* Palette */
  --white: #ffffff;
  --blue:  #233dff;
  --pink:  #fbbfff;
  --red:   #ff0b09;
  --ink:   #141414;

  /* Type */
  --font: 'Space Grotesk', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --script: 'Snell Roundhand', 'Apple Chancery', 'Brush Script MT', cursive;
  --mono: 'Anonymous Pro', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* The design canvas the desktop percentages are derived from */
  --art-w: 1440;
  --art-h: 740;

  /* Breathing room between the composition and the edge of the screen */
  --pad: clamp(1rem, 2.5vw, 2.5rem);

  /* Width of the text panel that slots in beside a hovered poster */
  --panel-w: clamp(11rem, 60vw, 15rem);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;          /* single page — nothing scrolls */
}

img { display: block; width: 100%; height: auto; }

/* ==========================================================================
   Shared shell — one full screen, contents centred
   ========================================================================== */

.page {
  height: 100vh;
  height: 100dvh;            /* accounts for mobile browser chrome */
  padding: var(--pad);
  display: grid;
  place-items: center;
  overflow: hidden;
}

/* ==========================================================================
   1. PHONE — logo, links below it, nothing else
   ========================================================================== */

.posters,
.glows,
.ticker,
.events,
.about,
.contact,
.newsletter { display: none; }

/* Past Events replaces the home imagery entirely. */
body[data-view="past"] .ticker,
body[data-view="past"] .glows,
body[data-view="past"] .posters { display: none; }

body[data-view="past"] .events { display: block; }

/* About Us keeps the two right-hand frames and drops the three on the
   left, along with their diamonds. The ticker fades away behind it. */
/* .about lays out as a flex row on desktop, so it must not be forced to
   block here — that would beat the layout rule on specificity. */
body[data-view="about"] .about { display: flex; }
body[data-view="contact"] .contact { display: block; }
body[data-view="newsletter"] .newsletter { display: block; }

/* The text views drop the ticker so the copy stays readable. */
body[data-view="about"] .ticker,
body[data-view="contact"] .ticker,
body[data-view="newsletter"] .ticker { opacity: 0; }

body[data-view="about"] .ticker__track,
body[data-view="contact"] .ticker__track,
body[data-view="newsletter"] .ticker__track { animation-play-state: paused; }

.board {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.75rem, 7vh, 3rem);
  width: 100%;
  max-width: 26rem;
}

.logo {
  margin: 0;
  line-height: 0;
  width: 100%;
}

.logo a {
  display: block;
  outline-offset: 6px;
}

.logo a:focus-visible { outline: 2px solid var(--red); }

.nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.7rem, 2.4vh, 1.15rem);
}

.nav a {
  display: flex;
  align-items: center;
  gap: 0.4em;
  color: var(--blue);
  text-decoration: none;
  font-family: var(--mono);
  font-weight: 700;
  font-size: clamp(1rem, 4.4vw, 1.4rem);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  white-space: nowrap;
  transition: color 120ms ease;
}

/* Underline sits on the label only, so the star stays clear of it. */
.nav__label {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 0.08em;
  transition: text-decoration-color 120ms ease;
}

.nav a:hover .nav__label,
.nav a:focus-visible .nav__label,
.nav a.is-current .nav__label { text-decoration-color: currentColor; }

.star {
  font-size: 1.05em;
  line-height: 1;
  transform: translateY(-0.04em);
}

.nav a:hover,
.nav a:focus-visible { color: var(--red); }

.nav a:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 4px;
}

.nav a.is-current { color: var(--red); }

/* ---- Past Events strip (phone) -------------------------------------------
   Full-bleed out of the centred column so posters can run off both edges. */

/* .board centres its children, so a 100vw child is already full bleed —
   adding a negative margin on top of that drags the row off to the left. */
.events {
  width: 100vw;
}

.events__strip {
  display: flex;
  align-items: center;
  gap: 1rem;
  height: 34vh;
  overflow-x: auto;
  overflow-y: hidden;
  padding-inline: var(--pad);
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;

  /* no visible scrollbar — the row still scrolls */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.events__strip::-webkit-scrollbar { display: none; }

.event {
  margin: 0;
  flex: 0 0 auto;
  height: 100%;
}

.event__open {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  display: block;
  height: 100%;
  cursor: pointer;
}

.event__open:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 4px;
}

/* Hovering does the selecting on desktop, so a click cursor would mislead. */
@media (hover: hover) and (pointer: fine) and (min-width: 900px) {
  .event__open { cursor: default; }
}

.event img {
  height: 100%;
  width: auto;
  display: block;
}

/* ---- one poster opened, inline ------------------------------------------
   The panel slots in beside the hovered poster and pushes the rest of the
   row along. Nothing is hidden, so the row still scrolls normally. */

.detail {
  flex: 0 0 auto;
  max-width: 0;
  opacity: 0;
  overflow: hidden;
  align-self: center;
  margin-inline: 0;

  /* Closing is quicker than opening, so moving between posters feels
     responsive rather than laboured. OUT_MS in views.js matches the 180ms. */
  transition: max-width 180ms ease, opacity 140ms ease, margin-inline 180ms ease;
}

.detail.is-open {
  max-width: var(--panel-w);
  opacity: 1;
  margin-inline: clamp(0.9rem, 2vw, 2rem);
  transition: max-width 300ms ease, opacity 220ms ease, margin-inline 300ms ease;
}

/* Fixed width inside the collapsing box, so the text never reflows
   while the panel is opening. */
.detail__inner { width: var(--panel-w); }

.detail__heading {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  color: var(--blue);
}

.detail__sub {
  margin: 0.4em 0 0.9em;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--red);
}

.detail__body {
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--ink);
}

.detail__body p { margin: 0 0 0.8em; }
.detail__body p:last-child { margin-bottom: 0; }

/* ---- Newsletter ---------------------------------------------------------- */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.newsletter__intro {
  margin: 0 0 1.1em;
  font-family: var(--mono);
  font-size: clamp(0.8rem, 2.4vw, 0.95rem);
  line-height: 1.5;
  letter-spacing: -0.02em;
  color: var(--blue);
  max-width: 46ch;
}

.newsletter__form {
  display: flex;
  align-items: stretch;
  gap: 0;
  max-width: 34rem;
}

.newsletter__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0.62em 0.85em;
  border: 1px solid var(--red);
  background: var(--white);
  font-family: var(--mono);
  font-size: clamp(0.8rem, 2.4vw, 0.95rem);
  color: var(--blue);
}

.newsletter__input::placeholder { color: #9aa0b8; }

.newsletter__input:focus {
  outline: 2px solid var(--blue);
  outline-offset: -2px;
}

.newsletter__submit {
  flex: 0 0 auto;
  margin-left: -1px;               /* share the border with the field */
  padding: 0.62em 1.1em;
  border: 1px solid var(--red);
  background: var(--white);
  font-family: var(--mono);
  font-weight: 700;
  font-size: clamp(0.75rem, 2.2vw, 0.9rem);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--red);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}

.newsletter__submit:hover,
.newsletter__submit:focus-visible { background: var(--red); color: var(--white); }

.newsletter__note {
  margin: 0.9em 0 0;
  font-family: var(--mono);
  font-size: clamp(0.72rem, 2.1vw, 0.82rem);
  line-height: 1.5;
  color: var(--red);
  max-width: 46ch;
  min-height: 1.2em;
}

/* ---- Contact ------------------------------------------------------------
   The nav bar's starred-text treatment, in pink. */

.contact__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(0.55rem, 2vh, 0.9rem);
}

.contact__list a {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  color: var(--pink);
  text-decoration: none;
  font-family: var(--mono);      /* mirrors the nav bar, as it was specified to */
  font-weight: 700;
  font-size: clamp(1rem, 4.2vw, 1.4rem);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1.15;
  white-space: nowrap;
  transition: color 120ms ease;
}

.contact__list a:hover,
.contact__list a:focus-visible { color: var(--red); }

.contact__list a:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 4px;
}

/* ---- About Us ------------------------------------------------------------ */

/* No `display` here on purpose: the hide rule near the top of this file has
   the same specificity, so declaring one would show the panel on every view.
   The view rule turns it into a flex container instead. */
.about {
  width: 100%;
  max-height: 52vh;
  overflow-y: auto;
  flex-direction: column;
  gap: clamp(1rem, 4vw, 1.75rem);
}

.about__figure {
  margin: 0;
  flex: 0 0 auto;
}

.about__figure img {
  width: 100%;
  height: auto;
  display: block;
}

.about__body {
  font-family: var(--mono);
  font-size: clamp(0.8rem, 2.4vw, 0.95rem);
  line-height: 1.4;
  letter-spacing: -0.035em;
  color: var(--blue);
  text-align: justify;
  hyphens: auto;
}

.about__body p { margin: 0 0 1em; }
.about__body p:last-child { margin-bottom: 0; }

.events__strip--empty {
  display: block;
  height: auto;
  padding: 1.5rem var(--pad);
  font-size: 0.9rem;
  color: var(--blue);
}


/* ==========================================================================
   2. DESKTOP — the scattered composition, 900px and up
   ========================================================================== */

@media (min-width: 900px) {

  :root { --panel-w: clamp(11rem, 15vw, 16rem); }

  .board {
    position: relative;
    container-type: inline-size;
    display: block;
    max-width: none;

    /* Fit the artboard inside the viewport width AND height at once, so the
       page never scrolls and never crops. */
    width: min(
      100%,
      1440px,
      calc((100dvh - (var(--pad) * 2)) * var(--art-w) / var(--art-h))
    );
    aspect-ratio: var(--art-w) / var(--art-h);
  }

  /* lets the children be positioned against .board, not their wrapper */
  .posters,
  .glows { display: contents; }

  .glow,
  .poster,
  .logo {
    position: absolute;
    margin: 0;
  }

  /* --- ticker ------------------------------------------------------------ */

  .ticker {
    display: block;
    position: absolute;
    left: 50%;
    width: 100vw;              /* full bleed, past the board's own margins */
    transform: translateX(-50%);

    /* Spans the whole artboard so each line can be placed by its own
       percentage rather than stacked with margins. */
    top: 0;
    bottom: 0;
    z-index: 0;
    pointer-events: none;
    transition: opacity 700ms ease;
  }

  .ticker__line {
    position: absolute;
    left: 0;
    right: 0;
    overflow: hidden;
    white-space: nowrap;
    font-family: var(--script);
    line-height: 1.35;
    color: rgba(35, 61, 255, 0.32);

    /* Words surface in the middle of the line and dissolve again at either
       end, so the text scrolls in and out of visibility rather than being
       cut off by the edge of the screen. */
    -webkit-mask-image: linear-gradient(
      to right,
      transparent 0%,
      rgba(0, 0, 0, 0.35) 12%,
      #000 32%,
      #000 68%,
      rgba(0, 0, 0, 0.35) 88%,
      transparent 100%
    );
    mask-image: linear-gradient(
      to right,
      transparent 0%,
      rgba(0, 0, 0, 0.35) 12%,
      #000 32%,
      #000 68%,
      rgba(0, 0, 0, 0.35) 88%,
      transparent 100%
    );
  }

  .ticker__line--a { top: 31.081%; font-size: 2.92cqw; }
  .ticker__line--b { top: 35.135%; font-size: 3.90cqw; }

  .ticker__track {
    display: inline-flex;
    will-change: transform;
  }

  /* Two identical runs, shifted from 0 to -50% — the seam never shows. */
  /* Travel speed is (track width / duration), and the track scales with the
     font size — so 44s vs 61s across two different sizes worked out to the
     same speed. Line A is shortened to 38s, which puts it ~20% faster than
     line B: visibly different without either looking hurried. */
  .ticker__line--a .ticker__track { animation: ticker-left 38s linear infinite; }

  /* different speed AND a head start, so the two lines never read as one */
  .ticker__line--b .ticker__track {
    animation: ticker-left 61s linear infinite;
    animation-delay: -26s;
  }

  /* right to left */
  @keyframes ticker-left {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
  }

  /* --- pink diamonds ----------------------------------------------------- */

  /* Centred on the same points as the frames, but a FIXED size — they stay
     put while the media above them changes shape. A square rotated 45° and
     blurred gives the diamond falloff. */
  .glows { display: contents; }

  .glow {
    aspect-ratio: 1;
    background: var(--pink);
    border-radius: 8%;
    transform: translate(-50%, -50%) rotate(45deg);
    filter: blur(26px);        /* fallback */
    filter: blur(1.9cqw);      /* soft, but not so soft the diamond is lost */
    opacity: 0.45;
    z-index: 1;
  }

  .glow--1 { left: 10.069%; top: 53.378%; width: 13.903%; }
  .glow--2 { left: 30.521%; top: 25.608%; width: 18.097%; }
  .glow--3 { left: 51.042%; top: 44.595%; width: 14.597%; }
  .glow--4 { left: 71.875%; top: 29.730%; width: 15.201%; }
  .glow--5 { left: 92.014%; top: 39.865%; width: 11.403%; }

  /* --- carousel frames --------------------------------------------------- */

  .poster {
    overflow: hidden;
    background: var(--white);
    z-index: 2;

    /* left/top below are the CENTRE of each frame, not its corner, so a
       frame grows and shrinks evenly in every direction as the media
       changes shape — it stays pinned to the same point on the page. */
    transform: translate(-50%, -50%);
  }

  /* Each frame's HEIGHT comes from whatever it is currently showing —
     carousel.js sets aspect-ratio per item — so the proportions change as
     the media changes. The ratios below are only starting shapes, used
     before the first item lands.

     Centres are the middles of the boxes from layout-editor.html; widths
     are those boxes 8% wider, which tightens the gaps between frames. */
  .poster--1 { left: 10.069%; top: 53.378%; width: 17.014%; aspect-ratio: 190 / 230; }
  .poster--2 { left: 30.521%; top: 25.608%; width: 17.924%; aspect-ratio: 239 / 299; }
  .poster--3 { left: 51.042%; top: 44.595%; width: 19.097%; aspect-ratio: 170 / 240; }
  .poster--4 { left: 71.875%; top: 29.730%; width: 19.097%; aspect-ratio: 200 / 250; }
  .poster--5 { left: 92.014%; top: 39.865%; width: 13.889%; aspect-ratio: 150 / 188; }

  /* Two stacked layers per frame. The incoming item is loaded on the hidden
     layer, then both swap at once — a hard cut, no crossfade. */
  .layer {
    position: absolute;
    inset: 0;
    opacity: 0;
  }

  .layer.on { opacity: 1; }

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

  /* --- About Us (desktop) ------------------------------------------------ */

  /* The three left-hand frames and their diamonds step aside for the text;
     frames 4 and 5 stay where they are and keep cycling. */
  /* About now runs the full width — image left, copy right — so every
     frame and diamond steps aside for it. */
  body[data-view="about"] .posters,
  body[data-view="about"] .glows { display: none; }

  body[data-view="contact"] .poster--1,
  body[data-view="contact"] .poster--2,
  body[data-view="contact"] .poster--3,
  body[data-view="contact"] .glow--1,
  body[data-view="contact"] .glow--2,
  body[data-view="contact"] .glow--3 { display: none; }

  .about {
    position: absolute;
    left: 6.597%;
    top: 4%;
    width: 86.8%;
    max-height: none;
    overflow: visible;
    z-index: 2;

    flex-direction: row;
    align-items: flex-start;
    gap: 4.5cqw;
  }

  .about__figure { width: 38%; }

  .about__body {
    flex: 1 1 auto;
    font-size: 1cqw;
    line-height: 1.45;
    max-width: 70ch;
  }

  .contact {
    position: absolute;
    left: 2.778%;
    top: 9%;
    width: 44%;
    z-index: 2;
  }

  body[data-view="newsletter"] .poster--1,
  body[data-view="newsletter"] .poster--2,
  body[data-view="newsletter"] .poster--3,
  body[data-view="newsletter"] .glow--1,
  body[data-view="newsletter"] .glow--2,
  body[data-view="newsletter"] .glow--3 { display: none; }

  .newsletter {
    position: absolute;
    left: 1.5%;
    top: 52%;
    width: 52%;
    z-index: 2;
  }

  .newsletter__intro { font-size: 1cqw; max-width: 52ch; }
  .newsletter__input,
  .newsletter__submit { font-size: 1cqw; }
  .newsletter__note { font-size: 0.85cqw; }

  .contact__list {
    gap: 1.35cqw;
  }

  .contact__list a {
    font-size: 1.7cqw;
  }

  /* --- Past Events strip (desktop) --------------------------------------- */

  /* Sits where the cycling frames sit on the home view, full bleed so the
     row runs off both edges of the screen. Logo and nav stay below it. */
  .events {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: 100vw;
    top: 0;
    height: 60%;
    z-index: 2;
    margin-left: 0;
  }

  .events__strip {
    height: 100%;
    gap: 1.8cqw;
    padding-block: 1.5cqw;
    padding-inline: var(--pad);
    scroll-padding-inline: var(--pad);
  }

  /* The panel is deliberately small — it sits inside the row, not instead
     of it. */
  .detail__heading { font-size: 1.35cqw; }
  .detail__sub     { font-size: 0.95cqw; }
  .detail__body    { font-size: 0.88cqw; }

  /* --- logo -------------------------------------------------------------- */

  .logo {
    left: 47.917%;
    top: 64.189%;
    width: 49.306%;
    z-index: 3;
  }

  /* --- nav — a row, evenly spaced, as laid out ---------------------------- */

  .nav {
    position: absolute;
    left: 1.5%;
    top: 85.811%;
    z-index: 3;
    flex-direction: row;
    align-items: baseline;
    gap: 2.375rem;                                  /* fallback */
    gap: clamp(1.25rem, 2.639cqw, 2.375rem);
  }

  .nav a {
    align-items: baseline;
    font-size: 1.3rem;                              /* fallback */
    font-size: clamp(0.9rem, 1.45cqw, 1.3rem);
  }
}

/* ==========================================================================
   3. PHONE — an opened poster stacks instead of sitting side by side
   ========================================================================== */

@media (max-width: 899px) {

  /* The row stays a row on touch too — the panel just slots in beside the
     tapped poster, exactly as on desktop. */
  .detail.is-open { margin-inline: 0.75rem; }
}

/* ==========================================================================
   Preferences
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
  .ticker__track { animation: none !important; }
}
