/* ==========================================================================
   EMC Connect 2027 custom styles
   Tailwind handles utilities. This file holds design tokens, keyframes,
   and the handful of components that utilities express badly.
   ========================================================================== */

:root {
  /* Brand, sampled from EMC_Horizontal_Logo.png */
  --navy: #273c79;
  --navy-900: #0b142e;
  --navy-800: #12224a;
  --navy-700: #1b2d5e;
  --sky: #56aee0;
  --sky-300: #a5d8f2;
  --gold: #fdb43c;

  /* Surfaces */
  --paper: #f5f9fd;
  --ink: #1b2d5e;
  --ink-muted: #4a5b7c;

  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 220ms;

  /* Layout */
  --nav-h: 4.5rem;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

html {
  scroll-behavior: smooth;
  /* Anchor targets clear the fixed navbar */
  scroll-padding-top: calc(var(--nav-h) + 1.5rem);
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--paper);
  color: var(--ink);
  overflow-x: hidden;
  font-synthesis-weight: none;
}

/* Keep the whole page from ever scrolling sideways, even if a decorative
   element overshoots its container. */
main,
section {
  max-width: 100vw;
}

::selection {
  background: var(--sky);
  color: var(--navy-900);
}

/* A single focus treatment for every interactive element, so nothing ever
   loses its keyboard affordance. */
:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Skip link, visible only once focused */
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 90;
  transform: translateY(-160%);
  transition: transform var(--dur) var(--ease-out);
}
.skip-link:focus {
  transform: translateY(0);
}

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

.night-sky {
  background: var(--navy-800);
}

/* Hero photograph. A flat scrim rather than a gradient overlay keeps the
   headline above 4.5:1 against the bright fireworks in the upper half. */
.hero-photo {
  background-color: var(--navy-900);
  background-image: url("https://emarketing-psb.s3.us-west-2.amazonaws.com/assets/connect27/kaleb-tapp-bf19x7hxDy4-unsplash.jpg");
  background-size: cover;
  background-position: center 40%;
  background-repeat: no-repeat;
}

.hero-scrim {
  position: absolute;
  inset: 0;
  background: rgba(11, 20, 46, 0.76);
  pointer-events: none;
}

/* Wave that carries the hero into the section below it. */
.skyline {
  position: absolute;
  bottom: -1px;
  left: 0;
  width: 100%;
  height: clamp(90px, 16vw, 190px);
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Type treatments
   -------------------------------------------------------------------------- */

/* Was a clipped gradient. Now a flat accent colour. */
.text-accent {
  color: var(--gold);
}

.eyebrow {
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 3rem; /* comfortably over the 44px touch target floor */
  padding: 0 1.5rem;
  border-radius: 999px;
  font-family: Lexend, system-ui, sans-serif;
  font-weight: 600;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  text-align: center;
  transition:
    background-color var(--dur) var(--ease-out),
    color var(--dur) var(--ease-out),
    box-shadow var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out);
}

/* Primary: gold on navy. The dark label keeps contrast well past 4.5:1. */
.btn-primary {
  background: var(--gold);
  color: var(--navy-900);
  box-shadow: 0 6px 24px -8px rgba(253, 180, 60, 0.7);
}
.btn-primary:hover {
  background: #ffc45f;
  box-shadow: 0 10px 34px -8px rgba(253, 180, 60, 0.85);
}

.btn-ghost {
  border: 1.5px solid rgba(255, 255, 255, 0.35);
  color: #fff;
  background: rgba(255, 255, 255, 0.06);
}
.btn-ghost:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.6);
}

.btn-navy {
  background: var(--navy);
  color: #fff;
  box-shadow: 0 6px 24px -10px rgba(39, 60, 121, 0.8);
}
.btn-navy:hover {
  background: var(--navy-700);
}

/* --------------------------------------------------------------------------
   Countdown
   -------------------------------------------------------------------------- */

.count-cell {
  min-width: clamp(4.25rem, 17vw, 6.5rem);
  padding: 0.85rem 0.5rem 0.7rem;
  border-radius: 1rem;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(10px);
  text-align: center;
}

.count-num {
  display: block;
  font-family: Lexend, system-ui, sans-serif;
  font-weight: 600;
  font-size: clamp(1.75rem, 6vw, 2.75rem);
  line-height: 1;
  color: #fff;
  /* Digits keep a fixed width so the row never jitters as numbers change */
  font-variant-numeric: tabular-nums;
}

.count-label {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sky-300);
}

/* Seconds tick with a hairline pulse rather than a flip, which would draw the
   eye away from the CTA every single second. */
.count-num.is-ticking {
  animation: tick 380ms var(--ease-out);
}
@keyframes tick {
  0% {
    transform: translateY(-14%);
    opacity: 0.35;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

/* --------------------------------------------------------------------------
   Scroll reveal
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition:
    opacity 620ms var(--ease-out),
    transform 620ms var(--ease-out);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   Cards
   -------------------------------------------------------------------------- */

/* Hover lifts with shadow and border colour, never a scale transform, because scaling
   nudges neighbouring content and makes grids feel unstable. */
.card {
  background: #fff;
  border: 1px solid #dbe5f2;
  border-radius: 1.25rem;
  transition:
    box-shadow var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out);
}
.card:hover {
  border-color: var(--sky);
  box-shadow: 0 18px 40px -24px rgba(27, 45, 94, 0.45);
}

.card-dark {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.13);
  border-radius: 1.25rem;
  transition:
    background-color var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out);
}
.card-dark:hover {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(86, 174, 224, 0.6);
}

/* Speaker portrait placeholder: initials on a flat brand navy. */
.portrait {
  aspect-ratio: 1;
  border-radius: 1rem;
  display: grid;
  place-items: center;
  background: var(--navy);
  color: #fff;
  font-family: Lexend, system-ui, sans-serif;
  font-size: clamp(1.5rem, 4vw, 2rem);
  font-weight: 500;
  letter-spacing: 0.04em;
}

/* --------------------------------------------------------------------------
   Partner marquee
   -------------------------------------------------------------------------- */

/* main.js measures one copy of the list, tiles it enough times to cover the
   container, and sets both properties. If the script never runs, the shift
   falls back to 0px, so the animation is a no-op and the row simply sits
   still rather than sliding into empty space. */
.marquee {
  display: flex;
  width: max-content;
  gap: 2.5rem;
  animation: slide var(--marquee-duration, 38s) linear infinite;
}

/* Display scale for the social-proof rows. Large enough to register as a
   feature rather than a footnote. */
.marquee-lg {
  gap: clamp(1.75rem, 3.5vw, 3.5rem);
  padding: 0.35rem 0;
}

.marquee-name {
  font-family: Lexend, system-ui, sans-serif;
  font-weight: 500;
  font-size: clamp(1.5rem, 4.2vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
  white-space: nowrap;
  user-select: none;
  /* 70% navy on paper is 4.32:1, clearing the large-text bar with room spare. */
  color: rgba(39, 60, 121, 0.7);
}

/* Gold pip between names. Decorative, so it never reaches assistive tech. */
.marquee-dot {
  flex: none;
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  background: var(--gold);
}

/* Second row travels the other way. Same keyframes, played backwards. */
.marquee--reverse {
  animation-direction: reverse;
}
/* The rows deliberately keep moving under the cursor. Alex wants the motion
   uninterrupted, so there is no hover or focus pause here. */

/* Shift by exactly one copy of the list plus one gap, so the loop lands on an
   identical frame and the seam is invisible. main.js computes the pixel value,
   because a percentage cannot express "one copy" once the list is tiled a
   variable number of times. */
@keyframes slide {
  to {
    transform: translateX(calc(-1 * var(--marquee-shift, 0px)));
  }
}

/* --------------------------------------------------------------------------
   Day cards
   -------------------------------------------------------------------------- */

/* Oversized day number sitting behind the content. Very low opacity so it
   reads as texture and never competes with the copy it sits under. */
.day-numeral {
  position: absolute;
  top: -0.28em;
  right: -0.04em;
  font-family: Lexend, system-ui, sans-serif;
  font-weight: 600;
  font-size: clamp(7rem, 16vw, 11rem);
  line-height: 1;
  letter-spacing: -0.04em;
  opacity: 0.05;
  pointer-events: none;
  user-select: none;
}

/* Fixed-width phase label so the three rows align down a common edge. */
.phase-chip {
  flex: none;
  width: 5.75rem;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.3rem 0.5rem;
  border-radius: 0.5rem;
  background: rgba(86, 174, 224, 0.14);
  font-family: Lexend, system-ui, sans-serif;
  font-size: 0.625rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #26719d;
}

/* One variable drives both the stub width and the notch position, so the
   notches always land dead on the dashed rule. */
.ticket-stub {
  --stub-w: 6.75rem;
}
.ticket-stub__count {
  width: var(--stub-w);
}

/* Notches punched out of the ticket edge, filled with the card colour so they
   read as bites rather than dots. */
.ticket-notch {
  position: absolute;
  left: calc(var(--stub-w) - 0.5rem);
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--navy-800);
  pointer-events: none;
}
.ticket-notch--top {
  top: -0.5rem;
}
.ticket-notch--bottom {
  bottom: -0.5rem;
}

/* --------------------------------------------------------------------------
   "Coming soon" panels
   Used where the speaker lineup and schedule will go. Dashed borders read as
   deliberately unfinished rather than broken.
   -------------------------------------------------------------------------- */

.soon {
  border-radius: 1.5rem;
  border: 1.5px dashed #c3d4ea;
  background: #fff;
  padding: clamp(2.5rem, 6vw, 4rem) 1.5rem;
  text-align: center;
}

.soon--dark {
  border-color: rgba(165, 216, 242, 0.32);
  background: rgba(255, 255, 255, 0.04);
}

/* Badge holding the pulsing dot */
.soon-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  font-family: Lexend, system-ui, sans-serif;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* currentColor so the dot matches whichever badge holds it, gold on the dark
   panel and sky on the light one. */
.soon-dot {
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  background: currentColor;
  animation: breathe 2.4s ease-in-out infinite;
}

@keyframes breathe {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.35;
    transform: scale(0.72);
  }
}

/* --------------------------------------------------------------------------
   Agenda tabs
   Kept for when the real schedule lands and the placeholder panel comes out.
   -------------------------------------------------------------------------- */

.tab {
  cursor: pointer;
  padding: 0.7rem 1.25rem;
  border-radius: 999px;
  font-family: Lexend, system-ui, sans-serif;
  font-weight: 500;
  color: var(--ink-muted);
  transition:
    background-color var(--dur) var(--ease-out),
    color var(--dur) var(--ease-out);
}
.tab:hover {
  background: #e6eef9;
  color: var(--navy);
}
.tab[aria-selected="true"] {
  background: var(--navy);
  color: #fff;
}

.tabpanel[hidden] {
  display: none;
}
.tabpanel {
  animation: panel-in 320ms var(--ease-out);
}
@keyframes panel-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* Timeline rail down the left of each agenda row */
.slot {
  position: relative;
  padding-left: 2.25rem;
}
.slot::before {
  content: "";
  position: absolute;
  left: 0.4375rem;
  top: 1.6rem;
  bottom: -1.5rem;
  width: 2px;
  background: #cfdcee;
}
.slot:last-child::before {
  display: none;
}
.slot::after {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55rem;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: #fff;
  border: 3px solid var(--sky);
}

/* --------------------------------------------------------------------------
   FAQ
   -------------------------------------------------------------------------- */

.faq-q {
  cursor: pointer;
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  text-align: left;
  padding: 1.15rem 0;
  font-family: Lexend, system-ui, sans-serif;
  font-weight: 500;
  font-size: 1.0625rem;
  color: var(--navy-700);
  transition: color var(--dur) var(--ease-out);
}
.faq-q:hover {
  color: var(--navy);
}

.faq-a {
  overflow: hidden;
  height: 0;
  transition: height 300ms var(--ease-out);
}
.faq-icon {
  flex: none;
  transition: transform var(--dur) var(--ease-out);
}
.faq-q[aria-expanded="true"] .faq-icon {
  transform: rotate(45deg);
}

/* --------------------------------------------------------------------------
   Navbar
   -------------------------------------------------------------------------- */

/* Floating, inset from the viewport edges rather than pinned flush to 0. */
#nav {
  transition:
    background-color 260ms var(--ease-out),
    box-shadow 260ms var(--ease-out),
    backdrop-filter 260ms var(--ease-out);
}
#nav.is-stuck {
  background: rgba(11, 20, 46, 0.82);
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow: 0 10px 30px -18px rgba(0, 0, 0, 0.8);
}

/* Underline that grows from the left on hover */
.nav-link {
  position: relative;
  padding: 0.35rem 0;
  color: rgba(255, 255, 255, 0.82);
  transition: color var(--dur) var(--ease-out);
}
.nav-link:hover,
.nav-link[aria-current="true"] {
  color: #fff;
}
.nav-link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  height: 2px;
  width: 100%;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur) var(--ease-out);
}
.nav-link:hover::after,
.nav-link[aria-current="true"]::after {
  transform: scaleX(1);
}

/* Mobile sheet */
#mobile-menu {
  transition:
    opacity 260ms var(--ease-out),
    transform 260ms var(--ease-out);
}
#mobile-menu[hidden] {
  display: none;
}
#mobile-menu.is-closed {
  opacity: 0;
  transform: translateY(-8px);
}

/* Scroll progress bar under the navbar */
#progress {
  transform-origin: left;
  transform: scaleX(0);
}

/* --------------------------------------------------------------------------
   Reduced motion
   Anything decorative stops. Reveals resolve to their final state instead of
   staying invisible, and the countdown keeps updating without the tick.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }

  /* Deliberate exception, at Alex's request: the partner and speaker rows keep
     scrolling even here. The blanket rule above would collapse them to 0.01ms,
     so the duration and iteration count are restored with matching !important.
     Everything else on the page still honours the setting. */
  .marquee {
    animation-name: slide !important;
    animation-duration: var(--marquee-duration, 38s) !important;
    animation-iteration-count: infinite !important;
    animation-timing-function: linear !important;
  }
}
