/* ==========================================================================
   style.css  -  the look of the website
   --------------------------------------------------------------------------
   How CSS works, in one sentence:
     You pick something on the page (a "selector", like .button) and then
     describe how it should look inside { curly brackets }.

   "Mobile first" means: the rules at the top are made for a PHONE.
   At the bottom, a "@media (min-width: ...)" block adds changes that
   only apply when the screen is wider (tablet / computer).

   Sections in this file:
     1. Colors and settings (easy to change in one place)
     2. Basic page setup
     3. Header (logo)
     4. Buttons
     5. Upcoming event
     6. stay.connect.ed
     7. Footer, 7b. Sound on/off button
     9. Visual effects (grain, glow, flash, scroll reveal)
     8. Wider screens (700px+), 8b. Two-column event layout (900px+)
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. COLORS AND SETTINGS
   Variables are named boxes for values. Write them once here, use them
   everywhere with var(--name). To change the palette, edit only this block.
   -------------------------------------------------------------------------- */
:root {
  /* Backgrounds. (The pure black of the page itself is written out directly
     as #000000 wherever it is used: see section 2.) */
  --color-background-raised: #171717;/* very slightly lighter, used for the button */

  /* Text (all pass the readability test on the black background) */
  --color-text: #f5f5f5;             /* off-white for all main text */
  --color-text-muted: #b8b8b8;       /* slightly quieter text (still very readable) */

  /* Thin lines and borders */
  --color-line: #2e2e2e;             /* faint divider lines between sections */
  --color-border: #6e6e6e;           /* button border (subtle grey) */


  /* Maximum width of the text column, so lines never get too long */
  --content-width: 38rem;

  /* Maximum width shared by the logo and the flyer, so both line up.
     Change this one number to resize both together. */
  --flyer-max-width: 520px;
}


/* --------------------------------------------------------------------------
   2. BASIC PAGE SETUP
   -------------------------------------------------------------------------- */

/* Make width calculations predictable: padding and borders count inside
   an element's width instead of being added on top of it. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The HTML "hidden" attribute must always win over other display rules.
   (Our script uses it to show or hide the upcoming event.) */
[hidden] {
  display: none !important;
}

/* The page background is set on BOTH "html" (the whole browser window,
   including areas beyond the content) and "body", as solid pure black
   (#000000), written out directly with no transparency. */
html {
  background: #000000;

  /* Always keep room for the scrollbar, even when the page is not scrollable
     (which is the case while the entry screen shows). Without this, going back
     to the entry screen would remove the scrollbar and make everything shift
     sideways by its width, so the logo would jump at the start of its glide. */
  scrollbar-gutter: stable;
}

body {
  margin: 0;                        /* remove the browser's default outer gap */
  background: #000000;
  color: var(--color-text);

  /* THE font of the whole site: Carlito (loaded from Google Fonts in the HTML
     file, weights 400 = regular and 700 = bold). The browser tries the fonts
     in this order: Carlito first; if that is not available, Calibri (which
     looks almost identical, and many computers have it); if that is not
     available either, the computer's standard sans-serif font.
     Every element inside the body inherits this, so headings, paragraphs,
     buttons and the footer all use it. */
  font-family: 'Carlito', Calibri, sans-serif;

  font-size: 1rem;                  /* 1rem = the visitor's default size (usually 16px) */
  line-height: 1.7;                 /* space between lines, for easy reading */

  /* Make the page at least as tall as the screen, so the footer
     stays at the bottom even if the content is short. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;

  /* No text selection anywhere by default: dragging the mouse or
     long-pressing on a phone does not highlight text. Everything inside
     the body inherits this. The "-webkit-" line is the same rule for
     Safari, which needs its own version. The one exception (the address)
     is set in section 5. */
  -webkit-user-select: none;
  user-select: none;

  /* Ordinary arrow cursor over text (no I-beam) */
  cursor: default;
}

/* Links and buttons keep the pointing-hand cursor, so it is clear they
   can be clicked. (This only changes the cursor, not selection.) */
a,
button {
  cursor: pointer;
}

/* Form controls, including <button> elements (the ENTER buttons and the sound
   button), do NOT take the page's font by default: browsers give them their own
   system font. This rule tells them to use the same font as everything else
   (Carlito). */
button,
input,
select,
textarea {
  font-family: inherit;
}

/* The main content grows to fill the free space (pushes footer down) */
main {
  flex: 1;
}

/* All headings (h1 to h4): bold (Carlito 700). The font itself is inherited. */
h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.15;
  margin: 0 0 1rem;
}

p {
  margin: 0 0 1rem;
}

/* Links: same color as the text, with an underline, so they are obvious */
a {
  color: inherit;
  text-underline-offset: 0.2em;
}

/* Keyboard users see a clear outline on whatever is selected */
a:focus-visible {
  outline: 2px solid var(--color-text);
  outline-offset: 4px;
}

/* A reusable "container": centers content and adds side space on phones */
.container {
  width: 100%;
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 0 1.5rem;
  text-align: center;               /* everything on this page is centered */
}


/* --------------------------------------------------------------------------
   3. HEADER
   Just the logo, centered. White logo on black: always visible.
   -------------------------------------------------------------------------- */
.site-header {
  padding: 2rem 1.5rem 1.5rem;
  text-align: center;

  /* Keeps the logo drawn ABOVE the red glow that spreads out from behind
     the flyer (see section 5). */
  position: relative;
  z-index: 1;
}

/* The logo link: a box as wide as the flyer's box (never wider than the
   screen), centered with "auto" side margins. */
.site-logo {
  display: block;
  max-width: var(--flyer-max-width);
  margin: 0 auto;
}

/* The logo image fills its box. The height follows automatically, so the
   wordmark keeps its proportions (wide and thin) at every screen size. */
.site-logo img {
  display: block;
  width: 100%;
  height: auto;
}


/* --------------------------------------------------------------------------
   3b. ENTRY SCREEN
   A full-screen black cover shown when the page opens. The logo starts in
   the middle of it, with the ENTER button below. Pressing it glides the
   logo up into the header and fades the cover away. The cover is then
   hidden but kept in the page, because clicking the logo in the header
   brings it back (see STEP 7 in script.js).

   Classes that script.js and the inline script in the HTML put on the
   whole page ("html"):
     js-enabled  = JavaScript is running
     is-entry    = the entry screen is active (page hidden, no scrolling)
     is-entering = the logo is on its way between the middle and the header
   -------------------------------------------------------------------------- */

/* Without JavaScript: the entry screen is just an ordinary block at the top
   of the page holding the logo, and the ENTER buttons are hidden. */
.entry-screen {
  padding: 2rem 1.5rem 1.5rem;
  text-align: center;
}

.entry-button-wrap {
  display: none;
}

/* With JavaScript: a black cover over the whole screen. Its z-index (40) is
   above the page, and below the film grain (50), so the grain also covers it. */
.js-enabled .entry-screen {
  position: fixed;
  inset: 0;                         /* shorthand for top, right, bottom, left = 0 */
  z-index: 40;
  display: flex;
  align-items: center;              /* centered up-down ... */
  justify-content: center;          /* ... and left-right */
  /* The whole block (logo + buttons together) is centered in the space above
     this padding. 10vh of empty padding at the bottom (10% of the screen
     height) pushes the middle of the block up by half of that, so it sits
     with its center at about 45% from the top instead of 50%: slightly above
     the true middle, which looks more balanced to the eye. To change it,
     change the 10vh (0 = exactly centered, 20vh = center at 40%). */
  padding: 0 0 10vh;
  background: #000000;
  transition: opacity 0.5s ease;    /* the fade-out at the end (keep in sync with PAGE_REVEAL_MS in script.js) */
}

/* The logo's holder has the same side spacing as the header (1.5rem), so the
   logo is exactly the same width here as in the header. */
.js-enabled .entry-logo-slot {
  position: relative;
  width: 100%;
  padding: 0 1.5rem;
}

/* The ENTER button sits BELOW the logo, as part of the normal layout, so
   the cover centers the logo and the button TOGETHER as one block. (An
   earlier version let the button hang below without taking up room, which
   centered only the logo and left the whole block too low.)
   When the button is pressed, script.js hides it with "visibility: hidden"
   instead of removing it, so it keeps taking up its room and the logo does
   not jump before it glides to the header.

   - "margin: 2.5rem -1.5rem 0" = 2.5rem of space between logo and button,
     and -1.5rem on the left and right. The logo's holder has 1.5rem of side
     spacing that the button cannot use (on a 320px phone it needs every
     pixel), so the negative margins give that room back and the button may
     use the full screen width.
   - "display: flex" + "justify-content: center" centers the button under
     the logo at every screen width.
   - The side padding is small (0.5rem = 8px) because on a 320px phone every
     pixel counts. It grows back to 1.5rem on wide screens (see the media
     query further down). */
.js-enabled .entry-button-wrap {
  display: flex;
  justify-content: center;
  margin: 2.5rem -1.5rem 0;
  padding: 0 0.5rem;
}

/* "position: relative" makes each button the anchor for its splatter layer. */
.entry-button-wrap .entry-button {
  position: relative;
}

/* SIZE OF THE BUTTON. The label stays on ONE line on every phone from about
   320px wide upward. To make that possible the text, the letter spacing and
   the padding all shrink together on narrow screens:

   - font-size: "clamp(smallest, preferred, largest)". The preferred size is
     3.5vw (3.5% of the screen width), so the text grows and shrinks with the
     screen. It never goes below 0.7rem (11.2px, still readable in bold
     capitals), and never above 1.2rem (19.2px, the size on big screens).
     Examples: 320px wide -> 11.2px, 360px -> 12.6px, 390px -> 13.7px, and
     from about 550px upward -> 19.2px.
   - letter-spacing: 0.06em (a little tighter than on big screens).
   - padding: written in "em", which means "times the button's own text
     size", so the padding shrinks in proportion to the text. Left and right
     0.6em; top 0.9em; bottom 0.9em plus the 18px room for the splatter
     (see the next note).
   - white-space: nowrap = never break the label onto a second line.

   NOTE: these rules are written with THREE classes, on purpose. The general
   ".button.button-ticket" rule (two classes) is further down in this file,
   and would win a tie. Three classes always win. (An earlier version of this
   font-size lost that tie, so it never applied.) */
.button.button-ticket.entry-button {
  font-size: clamp(0.7rem, 3.5vw, 1.2rem);
  letter-spacing: 0.06em;
  white-space: nowrap;
  padding: 0.9em 0.6em calc(0.9em + 18px);
}

/* BLOOD SPLATTER BUTTONS. The button's red shape is not a rectangle: its top
   and sides are straight and clean (so the text stays easy to read), but its
   bottom edge is an uneven splatter, with rounded blobs and sharper drips.

   How it is built:
   - The button itself is see-through (no background, invisible border). It
     keeps its normal rectangle, so the keyboard focus outline (drawn around
     the whole box) is not cut off, and clicking works everywhere on it.
   - The red shape is a separate layer BEHIND the text: the "::before"
     (a box that CSS creates inside the button, filling all of it, drawn
     under the text thanks to "z-index: -1"). That layer is what gets cut
     into the splatter shape with "clip-path".
   - Extra room at the bottom: "padding-bottom" adds 18px under the text.
     The splatter's body ends 18px above the box's bottom, and only the
     drips and blobs reach into those last 18px. So the text has the same
     space above and below it as before.
   - The outline: "clip-path: polygon(...)" is a list of points; everything
     outside the outline is cut away. Each point is "how far across (as a
     percentage of the width)" and "how far down". The down values are
     written as "calc(100% - 9px)" = "9 pixels above the bottom", so the
     drips reach the same number of pixels on any button width. The outline
     is deliberately uneven and NOT symmetric (see the note above the
     polygon below).
   - Depth: the fill is brick red (#9e2b24) with two soft shadings laid over
     it. One darkens the edges, the other darkens toward the bottom, so the
     drips and tips look deeper and thicker.
   - On hover / keyboard focus the fill sinks to the darker red (#6e1e19),
     with the same slow 0.5 second change as GET YOUR TICKET.
   - The two rules with ":hover" and ":focus-visible" are needed to stop the
     general button styles from painting a plain rectangle on hover.
   - The falling drops (script.js) start from the tips of the outline: the
     places listed in SPLATTER_TIPS (in script.js) match the
     drip tips of the outline. If you change the outline, change that
     list. */
.button.button-ticket.entry-button,
.button.button-ticket.entry-button:hover,
.button.button-ticket.entry-button:focus-visible {
  background: transparent;
  border-color: transparent;
}

.button.button-ticket.entry-button::before {
  content: "";
  position: absolute;
  inset: -2px;                       /* also covers the 2px invisible border, so the shape fills the whole box */
  z-index: -1;                       /* behind the button's text */
  pointer-events: none;
  background-color: #9e2b24;
  background-image:
    radial-gradient(ellipse at 50% 30%, transparent 55%, rgba(0, 0, 0, 0.28) 100%),
    linear-gradient(to bottom, transparent 62%, rgba(0, 0, 0, 0.4) 100%);
  transition: background-color 0.5s ease;
}

.button.button-ticket.entry-button:hover::before,
.button.button-ticket.entry-button:focus-visible::before {
  background-color: #6e1e19;
}

/* THE OUTLINE. The bottom edge is random-looking on purpose, so it does not
   look copied or mirrored:
   - It is made of a mix of short sharp drips, rounded blobs and calm flat
     stretches, placed at uneven spots along the width. The drips are all
     SHORT (the deepest reaches about 8px below the body of the button) and
     each has its own length.
   - It was made once by a small random-number script (the same "seed" always
     gives the same shape), then pasted in here as fixed numbers. It does
     NOT change on every page load: the shape you see is always the same.
   - The five drip tips are the places listed in SPLATTER_TIPS in script.js,
     which is where the falling drops start.
   - Both top corners are ROUNDED, with a 10px radius. The first five
     points of the list trace the top-left corner (a quarter circle drawn
     as a short staircase of points), and the next five trace the
     top-right corner. To make the rounding bigger or smaller, scale those
     ten pairs of numbers (10px is the radius; e.g. 14px would turn
     "0.8px 6.2px" into roughly "1.1px 8.6px", and so on).
   - "-webkit-clip-path" is the same rule for older Safari browsers, so the
     list of points appears twice (keep both identical). */
.button.button-ticket.entry-button::before {
  -webkit-clip-path: polygon(0px 10px, 0.8px 6.2px, 2.9px 2.9px, 6.2px 0.8px, 10px 0px, calc(100% - 10px) 0px, calc(100% - 6.2px) 0.8px, calc(100% - 2.9px) 2.9px, calc(100% - 0.8px) 6.2px, 100% 10px, 100% calc(100% - 15.5px), 98.3% calc(100% - 15.5px), 97.5% calc(100% - 13.9px), 96.6% calc(100% - 13.9px), 95.7% calc(100% - 15.4px), 94.8% calc(100% - 16.5px), 93.4% calc(100% - 9.7px), 92% calc(100% - 16.1px), 89.7% calc(100% - 16.1px), 86.3% calc(100% - 14.6px), 85.3% calc(100% - 12.3px), 84.3% calc(100% - 12.8px), 83.3% calc(100% - 14.4px), 79.9% calc(100% - 17.7px), 77.6% calc(100% - 15.7px), 76.8% calc(100% - 11.4px), 76% calc(100% - 15.1px), 73.7% calc(100% - 17.1px), 70.4% calc(100% - 14.1px), 69.3% calc(100% - 11.9px), 68.1% calc(100% - 11.7px), 67% calc(100% - 14.2px), 65.9% calc(100% - 16.2px), 64.8% calc(100% - 10.4px), 63.7% calc(100% - 15.7px), 61.4% calc(100% - 16.1px), 56.9% calc(100% - 15.9px), 53.4% calc(100% - 15.5px), 52.2% calc(100% - 14.1px), 50.9% calc(100% - 14.2px), 49.7% calc(100% - 15.7px), 47.6% calc(100% - 15.7px), 46.8% calc(100% - 14.5px), 45.9% calc(100% - 14.3px), 45.1% calc(100% - 15.8px), 44.3% calc(100% - 17.2px), 42.9% calc(100% - 10.4px), 41.6% calc(100% - 17px), 40.3% calc(100% - 14.9px), 39% calc(100% - 12.8px), 37.8% calc(100% - 12.8px), 36.5% calc(100% - 14.6px), 34.4% calc(100% - 16px), 33.5% calc(100% - 14.7px), 32.6% calc(100% - 14.5px), 31.7% calc(100% - 16.2px), 29.4% calc(100% - 17.4px), 25.8% calc(100% - 15.9px), 22.3% calc(100% - 15.7px), 21.2% calc(100% - 14.4px), 20% calc(100% - 14.4px), 18.9% calc(100% - 15.6px), 17.8% calc(100% - 17px), 16.9% calc(100% - 11px), 16% calc(100% - 16.8px), 15.2% calc(100% - 14.8px), 14.4% calc(100% - 13.3px), 13.6% calc(100% - 12.9px), 12.8% calc(100% - 15.1px), 10.9% calc(100% - 15.7px), 9.8% calc(100% - 13.9px), 8.6% calc(100% - 13.8px), 7.5% calc(100% - 15.7px), 5.1% calc(100% - 14.9px), 3.9% calc(100% - 12.7px), 2.6% calc(100% - 12.7px), 1.3% calc(100% - 14.7px), 0% calc(100% - 17.5px));
  clip-path: polygon(0px 10px, 0.8px 6.2px, 2.9px 2.9px, 6.2px 0.8px, 10px 0px, calc(100% - 10px) 0px, calc(100% - 6.2px) 0.8px, calc(100% - 2.9px) 2.9px, calc(100% - 0.8px) 6.2px, 100% 10px, 100% calc(100% - 15.5px), 98.3% calc(100% - 15.5px), 97.5% calc(100% - 13.9px), 96.6% calc(100% - 13.9px), 95.7% calc(100% - 15.4px), 94.8% calc(100% - 16.5px), 93.4% calc(100% - 9.7px), 92% calc(100% - 16.1px), 89.7% calc(100% - 16.1px), 86.3% calc(100% - 14.6px), 85.3% calc(100% - 12.3px), 84.3% calc(100% - 12.8px), 83.3% calc(100% - 14.4px), 79.9% calc(100% - 17.7px), 77.6% calc(100% - 15.7px), 76.8% calc(100% - 11.4px), 76% calc(100% - 15.1px), 73.7% calc(100% - 17.1px), 70.4% calc(100% - 14.1px), 69.3% calc(100% - 11.9px), 68.1% calc(100% - 11.7px), 67% calc(100% - 14.2px), 65.9% calc(100% - 16.2px), 64.8% calc(100% - 10.4px), 63.7% calc(100% - 15.7px), 61.4% calc(100% - 16.1px), 56.9% calc(100% - 15.9px), 53.4% calc(100% - 15.5px), 52.2% calc(100% - 14.1px), 50.9% calc(100% - 14.2px), 49.7% calc(100% - 15.7px), 47.6% calc(100% - 15.7px), 46.8% calc(100% - 14.5px), 45.9% calc(100% - 14.3px), 45.1% calc(100% - 15.8px), 44.3% calc(100% - 17.2px), 42.9% calc(100% - 10.4px), 41.6% calc(100% - 17px), 40.3% calc(100% - 14.9px), 39% calc(100% - 12.8px), 37.8% calc(100% - 12.8px), 36.5% calc(100% - 14.6px), 34.4% calc(100% - 16px), 33.5% calc(100% - 14.7px), 32.6% calc(100% - 14.5px), 31.7% calc(100% - 16.2px), 29.4% calc(100% - 17.4px), 25.8% calc(100% - 15.9px), 22.3% calc(100% - 15.7px), 21.2% calc(100% - 14.4px), 20% calc(100% - 14.4px), 18.9% calc(100% - 15.6px), 17.8% calc(100% - 17px), 16.9% calc(100% - 11px), 16% calc(100% - 16.8px), 15.2% calc(100% - 14.8px), 14.4% calc(100% - 13.3px), 13.6% calc(100% - 12.9px), 12.8% calc(100% - 15.1px), 10.9% calc(100% - 15.7px), 9.8% calc(100% - 13.9px), 8.6% calc(100% - 13.8px), 7.5% calc(100% - 15.7px), 5.1% calc(100% - 14.9px), 3.9% calc(100% - 12.7px), 2.6% calc(100% - 12.7px), 1.3% calc(100% - 14.7px), 0% calc(100% - 17.5px));
}

/* BIG SCREENS (800px wide and up): plenty of room, so the buttons go back to
   the full size: 1.2rem text, wide letter spacing, and generous padding
   (1.75rem at the sides), and the side margins grow back to 1.5rem. Below
   800px the smaller, screen-relative values further up apply. */
@media (min-width: 800px) {
  .js-enabled .entry-button-wrap {
    padding: 0 1.5rem;
  }

  .button.button-ticket.entry-button {
    font-size: 1.2rem;
    letter-spacing: 0.1em;
    padding: 1rem 1.75rem calc(1rem + 18px);
  }
}

/* FALLING DROPS. script.js creates one of these <div>s at one of the tips of
   a button's splatter edge, makes it fall, and removes it again when it has
   faded out. Only the LOOKS are here; the movement, the stretching and the
   fading are done by script.js.

   - A teardrop shape: the rounded corners are smaller at the top and much
     rounder at the bottom ("border-radius: horizontal / vertical").
   - Same reds as the buttons: brick red at the top, the deeper red at the
     bottom.
   - "position: absolute" inside the entry cover, which fills the screen, so
     the numbers script.js gives (left and top) are screen positions.
   - "transform-origin: 50% 0" = stretch downward from the top of the drop.
   - "pointer-events: none": drops can never be clicked or block a click.
   - Layering: a drop has z-index 0 and the button has z-index 1 (next
     rule). So as a drop breaks away from the button's splatter edge, it
     starts out BEHIND the button's own red shape and text, instead of
     briefly showing in front of them, and then emerges below it as it
     falls. */
.blood-drop {
  position: absolute;
  z-index: 0;
  background: linear-gradient(to bottom, #9e2b24, #6e1e19);
  border-radius: 50% 50% 50% 50% / 30% 30% 70% 70%;
  transform-origin: 50% 0;
  pointer-events: none;
  will-change: transform, opacity;   /* tells the browser this will move, so it prepares to animate smoothly */
}

.entry-button-wrap .entry-button {
  z-index: 1;
}

/* The cover fades out, and only AFTER the fade (the 0.5 second delay on
   'visibility') is it hidden completely, so nothing on it can be reached with
   a click or the keyboard. It stays in the page, so it can fade back in when
   the visitor returns: taking this class off makes it visible again at once and
   the opacity transition of '.js-enabled .entry-screen' fades it in. */
.entry-screen.is-leaving {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.5s ease, visibility 0s linear 0.5s;   /* keep in sync with PAGE_REVEAL_MS in script.js */
}

/* While the logo is inside the cover it is just a picture: clicking it does
   nothing. (This stops applying once the logo moves to the header.) */
.entry-screen .site-logo {
  pointer-events: none;
}

/* The ENTER buttons: a quick fade-out (0.25 seconds) when one is pressed.
   (Their red splatter shape and its color change are described above, in the
   "BLOOD SPLATTER BUTTONS" note.) */
.button.button-ticket.entry-button {
  transition: opacity 0.25s ease;
}

.entry-button.is-leaving {
  opacity: 0;
  pointer-events: none;
}

.entry-button:focus-visible {
  outline: 2px solid var(--color-text);
  outline-offset: 4px;
}

/* While the entry screen is active, the rest of the page exists but is
   invisible ("visibility: hidden" also hides it from keyboards and screen
   readers), and the page cannot be scrolled. When "is-entry" is removed,
   the content fades in (the opacity transition below). */
main,
.site-footer {
  transition: opacity 0.5s ease;    /* keep in sync with PAGE_REVEAL_MS in script.js */
}

.is-entry main,
.is-entry .site-footer {
  opacity: 0;
  visibility: hidden;

  /* When the visitor goes back to the entry screen, the page fades out first
     and is hidden only after the fade (0.5 second delay on 'visibility'). On
     the very first load this changes nothing: the page is hidden from the
     start, and no transition runs on the first paint. */
  transition: opacity 0.5s ease, visibility 0s linear 0.5s;   /* keep in sync with PAGE_REVEAL_MS in script.js */
}

.is-entry,
.is-entry body {
  overflow: hidden;
}

/* The sound button stays out of sight until the visitor has entered */
.is-entry .sound-toggle {
  opacity: 0;
  visibility: hidden;
}

/* While the logo glides to the header, the header must be drawn ABOVE the
   black cover (40), otherwise the logo would be hidden behind it. It stays
   below the film grain (50). The header itself is see-through, so the cover
   still shows around the logo. */
.is-entering .site-header {
  z-index: 45;
}

/* The logo in the header is a button back to the entry screen, so it shows a
   small cue that it can be clicked: the hand cursor (from the general link
   rule near the top), and a slight fade when the mouse is over it or when it
   has keyboard focus. The hover fade is only for devices that really have a
   mouse, so on a phone it cannot 'stick' after a tap. (On the cover the logo
   is not clickable, and these rules do not apply.) */
.site-header .site-logo {
  transition: opacity 0.2s ease;
}

@media (hover: hover) {
  .site-header .site-logo:hover {
    opacity: 0.7;
  }
}

/* (The keyboard outline itself comes from the general 'a:focus-visible' rule.) */
.site-header .site-logo:focus-visible {
  opacity: 0.7;
}


/* --------------------------------------------------------------------------
   4. BUTTONS
   Used for "GET YOUR TICKET" and "Follow on Instagram". Same font as the rest
   of the page (Carlito), in bold.
   Restrained look: dark grey fill, thin grey border. No bright colors.
   -------------------------------------------------------------------------- */
.button {
  display: inline-block;
  font-weight: 700;                 /* bold: Carlito has only 400 and 700, so 700 is stated outright */
  font-size: 0.95rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.95rem 2.25rem;
  background: var(--color-background-raised);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  transition: background 0.2s, border-color 0.2s;
}

/* On hover / keyboard focus: the border turns white and the fill lightens */
.button:hover,
.button:focus-visible {
  background: #262626;
  border-color: var(--color-text);
}


/* The ticket button: a muted brick red, and the ONE strong color on the page.
   It is written as ".button.button-ticket" (both classes together) so that
   these rules win over the plain ".button" rules above. */
.button.button-ticket {
  background: #9e2b24;              /* muted brick red */
  border: 2px solid #9e2b24;        /* same color, so there is no visible outline */
  color: #ffffff;
  font-weight: 700;                 /* bold */
  font-size: 1.2rem;                /* larger and bold: keeps white-on-red easy to read */
  letter-spacing: 0.1em;
  padding: 1rem 1.75rem;
  max-width: 100%;                  /* never wider than the screen */
  transition: background 0.5s ease, border-color 0.5s ease;   /* slow, "sinking" change */
}

/* Hover / keyboard focus: the brick red sinks into a darker, deeper red */
.button.button-ticket:hover,
.button.button-ticket:focus-visible {
  background: #6e1e19;
  border-color: #6e1e19;
  color: #ffffff;
}


/* --------------------------------------------------------------------------
   5. UPCOMING EVENT
   The flyer, the description, the address, and the ticket button.
   The top padding also gives some breathing room under the logo.
   -------------------------------------------------------------------------- */
/* The top padding (2rem = 32px) leaves room for the flyer's red glow, which
   reaches at most about 28px above the flyer. Nothing here is clipped, so
   the glow simply fades out on its own. */
.upcoming-event {
  padding: 2rem 0 4rem;
}

/* This section's container is wider than the others, to leave room for
   two columns on big screens. */
.upcoming-event .container {
  max-width: 68rem;
}

/* The box holding flyer + text. On phones it is a single narrow column,
   the same width as before. (The two-column version is in section 8.) */
.event-layout {
  max-width: var(--content-width);
  margin: 0 auto;
}

/* The flyer: never wider than --flyer-max-width (520px, set at the top),
   centered, and it shrinks proportionally on small screens so it can
   never overflow. */
.event-flyer {
  max-width: var(--flyer-max-width);
  margin: 0 auto 2rem;              /* "auto" on the sides = centered */

  /* Needed for the glow below: "relative" lets us place the glow relative
     to the flyer; "isolate" keeps the glow tucked BEHIND the image. */
  position: relative;
  isolation: isolate;
}

.event-flyer img {
  display: block;
  width: 100%;                      /* fill the box (capped by --flyer-max-width) */
  height: auto;                     /* keep the flyer's proportions */
}

/* AMBIENT RED GLOW behind the flyer.
   This is its own element (the <div class="flyer-glow"> in the HTML). The
   flyer image itself has NO glow styling: no shadow, no border, nothing.

   The glow follows the flyer's straight edges: a soft red light that is
   brightest right at the edge and fades away over a short distance, evenly
   along the top, bottom and sides, and rounded off slightly at the corners.

   How it is made:
     The .flyer-glow box sits behind the flyer, a little SMALLER than it
     (inset: 6px pulls every side 6px inward, so the box is completely
     hidden behind the image). Around that box, "box-shadow" draws the red
     light. A shadow with a blur fades smoothly to fully transparent, so it
     has no hard edge of its own. The syntax is:
       box-shadow: sideways up-down blur spread color
     - blur: how far the fade reaches (the light is gone about that far out)
     - spread: pushes the whole shadow outward before it fades

   Why the box is tucked in behind the flyer:
     A shadow has no soft fade-in right at the box's own edge, only fading
     OUTWARD from it. Keeping the box 6px inside the flyer's edge hides that
     edge behind the picture, so only the soft, fading part shows.

   Size of the light: about 20 to 28px past the flyer's edge. --glow-blur
   shrinks on narrow screens ("clamp(smallest, preferred, largest)" with
   5vw, 5% of the screen width), so on a phone the light stays inside the
   space around the flyer and never reaches the screen edge or the text.

   To make the glow tighter or wider, change --glow-blur (and the 8px
   spread) below. */
.event-flyer {
  --glow-blur: clamp(16px, 5vw, 26px);
}

/* The flyer itself and the base glow are perfectly still. The base glow is
   a soft, steady red at 0.5 opacity - deliberately a bit dimmer than a
   fully lit glow, so the brighter travelling light below stands out
   against it. */
.flyer-glow {
  position: absolute;
  inset: 6px;                                   /* 6px inside the flyer's edges: hidden behind it */
  z-index: -1;                                  /* behind the flyer image */
  box-shadow: 0 0 var(--glow-blur) 8px rgba(158, 43, 36, 0.9);   /* the button's brick red */
  pointer-events: none;
  opacity: 0.5;
}

/* THE TRAVELLING LIGHT. A brighter patch of red light that slowly circles
   the flyer's edge, like a spotlight going round a stage. Only the LIGHT
   moves: the flyer and the base glow above stay perfectly still.

   How it works:
   - "::after" is an extra box that CSS creates inside .flyer-glow. It is a
     little BIGGER than the flyer (a negative "inset" pushes each side
     outward), and it sits behind the picture, so only the part sticking
     out past the flyer's edges can be seen.
   - Its background is a "conic-gradient": a colour that changes as you go
     ROUND a centre point, like the slices of a pie (not from the centre out
     to the edge). Here it is one bright slice (about 110 degrees wide,
     brightest in the middle, fading to nothing at both sides) and
     transparent for the rest of the circle.
   - "from var(--glow-orbit-angle)" says where the slice starts. The
     animation below changes that angle from 0 to 360 degrees, so the
     slice turns once all the way round the flyer - which is what makes the
     light travel around the edge.
   - "filter: blur(...)" softens everything, so the light has no hard edges
     and looks like a glow rather than a coloured shape. */

/* CSS normally cannot animate a number inside a gradient. Declaring the
   angle as a proper "angle" custom property (@property) tells the browser
   it can smoothly animate it. */
@property --glow-orbit-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

.flyer-glow::after {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--glow-blur));           /* a bit bigger than the box, so the light reaches past the flyer's edge */
  background: conic-gradient(
    from var(--glow-orbit-angle) at 50% 50%,
    rgba(232, 70, 55, 0) 0deg,
    rgba(232, 70, 55, 0.95) 55deg,              /* brightest point of the light */
    rgba(232, 70, 55, 0) 110deg,
    rgba(232, 70, 55, 0) 360deg                 /* the rest of the circle: no light */
  );
  filter: blur(calc(var(--glow-blur) * 0.6));
  animation: glow-orbit 8s linear infinite;
}

/* One full lap in 8 seconds. "linear" = constant speed all the way round
   (an "ease" would make it slow down and speed up on each lap). Change
   8s to make it faster or slower. */
@keyframes glow-orbit {
  to { --glow-orbit-angle: 360deg; }
}

/* The text column. "relative" + z-index keeps the text drawn above the glow. */
.event-text {
  position: relative;
  z-index: 1;
}

/* The box around the ticket button. Centering is set here, so the button
   sits in the middle of the text column even on desktop, where the
   paragraphs around it are left-aligned. On phones everything is already
   centered, so nothing changes there. */
.event-cta {
  text-align: center;
}

/* The dinner / bottles paragraph, just below the ticket button */
.event-description {
  margin: 2rem 0 0;                 /* space above (after the button), none below */
}

/* The event description block, just above the ticket button */
.event-about {
  margin-bottom: 2rem;              /* space between the text and the button */
}

.event-about p {
  margin: 0 0 1rem;                 /* space between its paragraphs */
}

/* Each line of a paragraph is its own block (script.js splits the text at every
   \n from content.js), so a new line always starts on a new row. */
.event-about .about-line {
  display: block;
}

/* No extra gap under the last paragraph (the box adds its own gap) */
.event-about p:last-child {
  margin-bottom: 0;
}

/* The FIRST paragraph ("Some nights ask for a costume...") works like a
   subtitle: bigger and bolder than the paragraphs below it.
   (It applies to whatever is the first line in aboutParagraphs in content.js.)
   clamp(smallest, preferred, largest) makes it grow with the screen but
   stay small enough that it does not wrap awkwardly on a phone. */
.event-about p:first-child {
  font-size: clamp(1.1rem, 4.6vw, 1.5rem);
  font-weight: 700;
  line-height: 1.3;
  margin-bottom: 1.5rem;            /* a bit more air between subtitle and body */
  text-wrap: balance;               /* evens out line lengths where supported */
}

/* The two lines of that subtitle are staggered: the first sits against the left
   edge, the second against the right edge, for a slight diagonal. (Both are
   stated outright, so it looks the same on phones, where the rest of the page
   is centered, and on computers, where the text column is left-aligned.) */
.event-about p:first-child .about-line:nth-child(1) {
  text-align: left;
}

.event-about p:first-child .about-line:nth-child(2) {
  text-align: right;
}

/* BODY TEXT ALIGNMENT: justified on wider screens, left-aligned on narrow ones.
   This covers the paragraphs of the description (including the dress code line)
   and the dinner paragraph. The two-line opening statement above is not part of
   it: it keeps its left / right alignment (that is why the first paragraph is
   excluded: ':not(:first-child)').

   - 480px wide and up: straight edges on BOTH sides (justified). The gaps between
     words stay small there (7px at most, against 3.6px normally).
   - 479px and narrower (phones): plain left-aligned text. In a narrow column,
     justified text stretched the gaps to 2.5 to 3.5 times their normal size
     (up to about 12px), which looks uneven. Left alignment is the safety net:
     it does not depend on the phone's browser being able to hyphenate.

   The two rules are written as a pair on purpose, so each width is stated
   outright: there is no gap and no overlap at the 480px line.

   Hyphenation goes with the justified version: 'hyphens: auto' lets the
   browser split long words at their natural syllable breaks (adding a hyphen),
   using the language set on the page (lang="en" on the <html> element). The
   '-webkit-' and '-ms-' lines are the same rule for Safari and older Edge,
   which need their own versions. (Some browsers only hyphenate once their
   language data is available, and simply skip it otherwise: nothing breaks,
   the text just is not hyphenated.) The last line of each paragraph is not
   stretched: it stays at the start. */
@media (max-width: 479px) {
  .event-about p:not(:first-child),
  .event-description {
    text-align: left;
  }
}

@media (min-width: 480px) {
  .event-about p:not(:first-child),
  .event-description {
    text-align: justify;
    -webkit-hyphens: auto;
    -ms-hyphens: auto;
    hyphens: auto;
  }
}

/* The small "Location:" label: smaller, uppercase, spaced-out letters and
   a quieter grey, so it reads as a label and not as content. */
.event-location-label {
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin: 2.5rem 0 0.25rem;         /* big gap above (after the button), small gap below */
}

/* The address itself: normal off-white text, so it stands out more than the label */
.event-address {
  font-size: 0.95rem;
  margin: 0;
  white-space: pre-line;            /* shows each \n from content.js as a line break */

  /* The ONE exception to "no selection": visitors can select and copy the
     address (to paste into Maps or a note). The text cursor over it hints
     that it can be selected. */
  -webkit-user-select: text;
  user-select: text;
  cursor: text;
}

/* The address is really a link to the map, but it must look exactly like
   the plain text around it until someone clicks it:
   - no underline (links normally have one),
   - "inherit" = take the colour of the text around it (never a link colour),
   - the same rules again for hover, so nothing changes when the mouse is over
     it. (The pointing-hand cursor comes from the general rule for links and
     is the one thing that does change: that is expected for a clickable area.)
   Keyboard users still see the general focus outline from "a:focus-visible",
   on purpose: without it, they could not tell where they are on the page. */
.event-address-link,
.event-address-link:hover {
  color: inherit;
  text-decoration: none;
}

/* Shown when no event is planned */
.event-empty h2 {
  font-size: clamp(1.9rem, 7vw, 3rem);
}


/* --------------------------------------------------------------------------
   6. STAY.CONNECT.ED
   No divider line: the spacing alone separates it from the event above.
   The bottom padding is small on purpose, so the footer follows closely.

   IF SECTIONS EVER FEEL LIKE THEY BLUR TOGETHER, here is a ready-made
   alternative: a very faint line that fades out at both ends. To use it,
   copy these two lines into the ".stay-connected" rule below and again
   into the ".site-footer" rule (one copy in each):

   border-top: 1px solid transparent;
   border-image: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.18), transparent) 1;
   -------------------------------------------------------------------------- */
.stay-connected {
  padding: 3.5rem 0 2rem;
}

.stay-connected h2 {
  font-size: clamp(1.7rem, 6vw, 2.4rem);
}


/* --------------------------------------------------------------------------
   7. FOOTER
   -------------------------------------------------------------------------- */
.site-footer {
  text-align: center;
  padding: 1.5rem 1.5rem 2rem;      /* small top padding: it follows the button closely */
}

/* "join.the.community" */
.footer-title {
  font-size: 1.25rem;
  font-weight: 700;
  margin: 0 0 1rem;
}

.footer-links {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  display: flex;
  justify-content: center;
  gap: 1.75rem;
}

.footer-links a {
  font-size: 0.9rem;
  letter-spacing: 0.08em;
}

/* The email, written as plain text */
.footer-email {
  font-size: 0.85rem;
  color: var(--color-text-muted);
  margin-bottom: 2rem;
  overflow-wrap: anywhere;          /* if the screen is very narrow, allow it to wrap */
}

.footer-copyright {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin: 0;
}


/* --------------------------------------------------------------------------
   7b. SOUND ON/OFF BUTTON
   Small, quiet, fixed in the bottom-right corner. z-index 70 keeps it above
   the grain (50) and the flash (60) layers so it can always be clicked.
   -------------------------------------------------------------------------- */
.sound-toggle {
  position: fixed;
  right: max(1rem, env(safe-area-inset-right));    /* stay clear of phone notches */
  bottom: max(1rem, env(safe-area-inset-bottom));
  z-index: 70;

  width: 2.75rem;                   /* 44px: comfortable to tap with a thumb */
  height: 2.75rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;

  background: rgba(0, 0, 0, 0.6);
  color: var(--color-text);
  border: 1px solid var(--color-line);
  opacity: 0.6;                     /* understated until you point at it */
  transition: opacity 0.2s, border-color 0.2s;
}

.sound-toggle:hover,
.sound-toggle:focus-visible {
  opacity: 1;
  border-color: var(--color-border);
}

.sound-toggle:focus-visible {
  outline: 2px solid var(--color-text);
  outline-offset: 3px;
}

/* Icon: waves while sound and effects are playing; a cross while paused */
.sound-toggle .icon-cross {
  display: none;
}

.sound-toggle.is-paused .icon-waves {
  display: none;
}

.sound-toggle.is-paused .icon-cross {
  display: inline;
}


/* --------------------------------------------------------------------------
   9. VISUAL EFFECTS
   All effects use only CSS animation ("keyframes") and are kept light:
   they only change "transform" and "opacity", which the browser can
   animate smoothly without redoing the page layout.

   An animation is defined in two steps:
     a) @keyframes name { ... }   describes WHAT changes over time
     b) animation: name 5s ...    applies it to an element
   -------------------------------------------------------------------------- */

/* ---- Film grain --------------------------------------------------------
   A fixed layer covering the whole screen, filled with fine noise.
   The noise picture is generated by the browser from a tiny SVG recipe
   (the long "data:image/svg+xml..." line), so there is no image file to
   download. The layer is twice the screen size and is nudged around in
   small jumps, which makes the grain look alive.
   pointer-events: none = clicks pass straight through it. */
.film-grain {
  position: fixed;
  top: -50%;
  left: -50%;
  width: 200%;
  height: 200%;
  z-index: 50;
  pointer-events: none;
  opacity: 0.08;                    /* very faint: texture, not static */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n' x='0' y='0'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 200px 200px;     /* the noise tile repeats like wallpaper */
  animation: grain-shift 3s steps(1) infinite;
}

/* "steps(1)" makes the layer JUMP between positions instead of sliding.
   Each jump is tiny (about 1% of the layer) and they happen a few times a
   second, like real film grain. */
@keyframes grain-shift {
  0%   { transform: translate(0, 0); }
  12%  { transform: translate(-1.2%, 0.8%); }
  25%  { transform: translate(0.9%, -1.1%); }
  37%  { transform: translate(-0.6%, -0.9%); }
  50%  { transform: translate(1.1%, 0.7%); }
  62%  { transform: translate(-1%, 1.2%); }
  75%  { transform: translate(0.7%, -0.6%); }
  87%  { transform: translate(-0.9%, 0.4%); }
  100% { transform: translate(0, 0); }
}

/* ---- Screen flash ------------------------------------------------------
   A layer over the whole screen, normally invisible (opacity 0).
   Its light is a soft radial gradient: brightest at one point (where the
   lightning seems to come from) and fading to transparent away from it.
   The colour is a cool white with a hint of blue: #eaf0ff, which in the
   "rgba" notation below is rgba(234, 240, 255, ...).

   Two variables, --flash-x and --flash-y, hold the position of that bright
   point. script.js gives them NEW random values at every flash, so the
   light comes from a different place each time. (The values after the comma
   in var(...) are the defaults if the script has not set them yet.)
   The flicker itself (pulses, timing, strength) is also created by
   script.js at every flash. */
.screen-flash {
  position: fixed;
  inset: 0;                         /* shorthand for top, right, bottom, left = 0 */
  z-index: 60;
  pointer-events: none;
  background: radial-gradient(
    circle at var(--flash-x, 50%) var(--flash-y, 0%),
    rgba(234, 240, 255, 1) 0%,      /* full strength at the source ... */
    rgba(234, 240, 255, 0.55) 30%,  /* ... softer around it ... */
    rgba(234, 240, 255, 0) 80%      /* ... and gone before the far edges */
  );
  opacity: 0;
}

/* ---- Scroll reveal -----------------------------------------------------
   Blocks marked class="reveal" start invisible and 16px lower than their
   final place. When script.js adds "is-visible" (the moment they scroll
   into view), they fade in and slide up.
   The rule only applies when the script has confirmed it is running
   (the "js-enabled" class on the page), so that if the script ever fails,
   the text is never left invisible. */
.js-enabled .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.9s ease, transform 0.9s ease;
}

.js-enabled .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* ---- Respect visitors who prefer less motion ---------------------------
   Many phones and computers have a "reduce motion" setting (helpful for
   people with motion sensitivity or migraines). If it is on, we switch
   off the moving effects: no grain movement, no glow sway, no flash, and
   content simply appears without sliding. (The flyer itself is already
   still at all times, so there is nothing to switch off for it.) */
@media (prefers-reduced-motion: reduce) {
  .film-grain,
  .flyer-glow::after {
    animation: none;
  }

  /* The entry screen's fades become instant */
  main,
  .site-footer,
  .is-entry main,
  .is-entry .site-footer,
  .js-enabled .entry-screen,
  .entry-screen.is-leaving,
  .site-header .site-logo,
  .button.button-ticket.entry-button,
  .button.button-ticket.entry-button::before {
    transition: none;
  }

  .screen-flash {
    display: none;
  }

  .js-enabled .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}


/* --------------------------------------------------------------------------
   8. WIDER SCREENS (tablet and computer: 700px and up)
   Only the things that need to change are listed here.
   -------------------------------------------------------------------------- */
@media (min-width: 700px) {

  .site-header {
    padding-top: 2.5rem;
  }

  .upcoming-event {
    padding: 2rem 0 5.5rem;
  }

  .stay-connected {
    padding: 5rem 0 2.5rem;
  }
}

/* --------------------------------------------------------------------------
   8b. DESKTOP TWO-COLUMN EVENT LAYOUT (900px and up)
   All the text on the left, flyer on the right, vertically centered
   next to the flyer. Below 900px nothing here applies, so phones and
   small tablets keep the single stacked column.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {

  /* "display: grid" lays children out in rows and columns. Here: two
     columns of equal width ("1fr 1fr"), with a gap between them.
     minmax(0, 1fr) stops a long word from stretching a column.
     align-items: center = vertically centers the text next to the flyer. */
  .event-layout {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 4rem;
    align-items: center;
  }

  /* The flyer fills its column (still never wider than 520px) and no longer
     needs the space underneath or the auto-centering.
     "order: 2" = show this item second, so the flyer goes on the RIGHT. */
  .event-flyer {
    margin: 0;
    order: 2;
  }

  /* Text reads better left-aligned in a column next to an image.
     "order: 1" = show this item first, so the text goes on the LEFT.
     (In the HTML the flyer still comes first, so on phones, where this
     block does not apply, the flyer stays on top.) */
  .event-text {
    text-align: left;
    order: 1;
  }
}
