/* tokens.css — design tokens, fonts, reset, base page + app-shell scaffolding.
   Cartographic Nocturne visual system for "Our First Year". */

/* ---- Self-hosted fonts ---------------------------------------------------
   Every face is served from ../fonts (relative to this stylesheet) so the
   embed makes NO external font requests — no CDN, no CORS. Trajan Pro is the
   Society's own already-deployed asset; Cinzel/Fraunces/Source Sans 3 are OFL
   and freely hostable. Cinzel/Fraunces/Source Sans 3 are variable fonts, so a
   single file covers the whole declared weight range. */

/* Display face: Trajan Pro (Society asset) */
@font-face {
  font-family: 'Trajan Pro';
  src: url('../fonts/TrajanPro-Regular.ttf') format('truetype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Trajan Pro';
  src: url('../fonts/TrajanPro-Bold.otf') format('opentype');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Trajan fallback: Cinzel (variable 400–600) */
@font-face {
  font-family: 'Cinzel';
  src: url('../fonts/Cinzel.latin.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

/* Numerals: Fraunces (variable, optical + weight axes) */
@font-face {
  font-family: 'Fraunces';
  src: url('../fonts/Fraunces.latin.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

/* UI: Source Sans 3 (variable 300–600) */
@font-face {
  font-family: 'Source Sans 3';
  src: url('../fonts/SourceSans3.latin.woff2') format('woff2');
  font-weight: 300 600;
  font-style: normal;
  font-display: swap;
}

/* ---- Tokens -------------------------------------------------------------- */
:root {
  --bg: #002147;
  --bg-dark: #00172f;
  --bg-deepest: #000f1f;
  --panel: #001a38;
  --accent: #BD2E43;
  --accent-sec: #d69da3;
  --gold: #E4C580;
  --text: #F7F7F3;
  --green: #6dbb86;

  /* Event-type colours (pins, card chips, legend). Gold = our own marquee
     "Silver Sword" events; rose = "Collab"; steel = "Popup" appearances. */
  --type-sword: #E4C580;
  --type-collab: #d69da3;
  --type-popup: #9db8d8;

  --font-display: 'Trajan Pro', 'Cinzel', Georgia, serif;
  --font-numeral: 'Fraunces', Georgia, serif;
  --font-ui: 'Source Sans 3', system-ui, -apple-system, sans-serif;

  --header-h: clamp(84px, 12vh, 132px);
  --timeline-h: clamp(72px, 12vh, 116px);
  --rail-w: clamp(0px, 18vw, 240px);
  --sidebar-w: clamp(280px, 24vw, 340px);
}

/* ---- Minimal reset ------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  padding: 0;
  font-family: var(--font-ui);
  color: var(--text);
  background: var(--bg-deepest);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
h1, p { margin: 0; }
svg { display: block; }

/* Visually-hidden (screen-reader-only) live regions / labels. */
.sss-visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- App shell ----------------------------------------------------------- */
.sss-app {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  background:
    radial-gradient(120% 90% at 50% 0%, #01203f 0%, var(--bg-deepest) 70%);
  overflow: hidden;
}

/* Header / wordmark */
.sss-header {
  flex: 0 0 auto;
  min-height: var(--header-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 1.1rem 1rem 0.6rem;
  text-align: center;
}
.sss-eyebrow {
  font-family: var(--font-ui);
  font-weight: 600;
  letter-spacing: 0.32em;
  font-size: clamp(0.62rem, 1.1vw, 0.78rem);
  color: var(--accent-sec);
  text-transform: uppercase;
  opacity: 0.9;
}
.sss-wordmark {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: 0.12em;
  line-height: 1.05;
  font-size: clamp(1.05rem, 3vw, 2.1rem);
  color: var(--text);
  text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5), 0 0 22px rgba(228, 197, 128, 0.12);
}

/* Body = stage + right rail */
.sss-body {
  flex: 1 1 auto;
  display: flex;
  min-height: 0;
}

/* Map stage fills most of the viewport */
.sss-stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}
.sss-map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Left sidebar (persistent event panel) */
.sss-sidebar {
  flex: 0 0 var(--sidebar-w);
  width: var(--sidebar-w);
  border-right: 1px solid rgba(214, 157, 163, 0.10);
  background: linear-gradient(180deg, rgba(0, 26, 56, 0.42), rgba(0, 15, 31, 0.18));
  padding: 1.3rem 1.25rem;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow-y: auto;
}

/* Right rail (tallies) */
.sss-rail {
  flex: 0 0 var(--rail-w);
  width: var(--rail-w);
  border-left: 1px solid rgba(214, 157, 163, 0.10);
  background: linear-gradient(180deg, rgba(0, 26, 56, 0.35), rgba(0, 15, 31, 0.15));
  padding: 1rem;
  display: flex;
  flex-direction: column;
}

/* Bottom timeline (later slice) */
.sss-timeline {
  flex: 0 0 auto;
  min-height: var(--timeline-h);
  border-top: 1px solid rgba(214, 157, 163, 0.10);
  background: linear-gradient(180deg, rgba(0, 15, 31, 0.15), rgba(0, 9, 20, 0.55));
  padding: 0.8rem 1.2rem;
  display: flex;
  align-items: center;
}

.sss-placeholder-note {
  font-family: var(--font-ui);
  font-size: 0.68rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-sec);
  opacity: 0.35;
}

/* Sample-data chip */
.sss-chip {
  position: absolute;
  left: 14px;
  bottom: 14px;
  z-index: 5;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.34rem 0.7rem;
  border-radius: 999px;
  background: rgba(0, 15, 31, 0.55);
  border: 1px solid rgba(214, 157, 163, 0.18);
  color: var(--accent-sec);
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  backdrop-filter: blur(4px);
}
.sss-chip__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 8px rgba(228, 197, 128, 0.7);
}

/* Pins (SVG) */
.sss-pin__node {
  fill: var(--accent-sec);
  transition: fill 300ms ease, r 300ms ease;
}
.sss-pin__halo {
  stroke: var(--accent-sec);
  stroke-width: 1;
  stroke-opacity: 0.25;
  transition: stroke 300ms ease, stroke-opacity 300ms ease;
}
/* Labels on demand: the whole label wrapper (pill + text) is hidden by default
   so the dense central-London cluster shows only tidy coloured dots. It is
   revealed only on hover, keyboard focus, or when the pin is the active venue
   (rules below). */
.sss-pin__labelwrap {
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease;
}
.sss-pin__label {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  fill: var(--text);
  fill-opacity: 1;
  paint-order: stroke;
  dominant-baseline: middle;
}
.sss-pin__label--halo {
  stroke: #000f1f;
  stroke-width: 3.5;
  stroke-opacity: 0.85;
  fill: none;
  paint-order: stroke;
}
/* Rounded backing pill behind the label for contrast above other pins. Sized
   in map.js from the text bbox when the label is revealed. */
.sss-pin__label-bg {
  fill: #071a2e;
  fill-opacity: 0.82;
  stroke: var(--gold);
  stroke-width: 0.75;
  stroke-opacity: 0.35;
}
/* Reveal triggers: hover, keyboard focus, or the active venue. */
.sss-pin:hover .sss-pin__labelwrap,
.sss-pin:focus-visible .sss-pin__labelwrap,
.sss-pin--active .sss-pin__labelwrap {
  opacity: 1;
}

/* Unreached = dim (this slice renders all pins here) */
.sss-pin--unreached .sss-pin__node { fill: var(--accent-sec); fill-opacity: 0.45; }
.sss-pin--unreached .sss-pin__halo { stroke-opacity: 0.16; }

/* Reached = brighter node + glow, tinted by the venue's most-recent event type.
   Default (no type class) falls back to claret. */
.sss-pin--reached .sss-pin__node { fill: var(--accent); fill-opacity: 1; }
.sss-pin--reached .sss-pin__halo { stroke: var(--gold); stroke-opacity: 0.6; }
.sss-pin--reached .sss-pin__label { fill: var(--text); fill-opacity: 1; }

/* Type-tinted reached pins. */
.sss-pin--reached.sss-pin--type-sword .sss-pin__node { fill: var(--type-sword); }
.sss-pin--reached.sss-pin--type-sword .sss-pin__halo { stroke: var(--type-sword); }
.sss-pin--reached.sss-pin--type-collab .sss-pin__node { fill: var(--type-collab); }
.sss-pin--reached.sss-pin--type-collab .sss-pin__halo { stroke: var(--type-collab); }
.sss-pin--reached.sss-pin--type-popup .sss-pin__node { fill: var(--type-popup); }
.sss-pin--reached.sss-pin--type-popup .sss-pin__halo { stroke: var(--type-popup); }

/* Upcoming (future) venues: a ghosted, hollow outline so they read as "not yet
   visited" but still discoverable + clickable. */
.sss-pin--upcoming .sss-pin__node {
  fill: var(--bg-deepest);
  fill-opacity: 0.55;
  stroke: var(--gold);
  stroke-width: 1.4;
  stroke-opacity: 0.7;
  stroke-dasharray: 2 2;
}
.sss-pin--upcoming .sss-pin__halo { stroke: var(--gold); stroke-opacity: 0.28; }
.sss-pin--upcoming .sss-pin__label { fill: var(--gold); fill-opacity: 1; }

/* Reached-but-future ("estimated") venues: the head has passed them, so they
   light in their type colour (via the reached + type-* rules above), but a
   subtle DASHED halo keeps them marked as planned/estimated rather than a
   recorded visit. */
.sss-pin--estimated .sss-pin__halo {
  stroke-dasharray: 2 2;
  stroke-opacity: 0.75;
}
.sss-pin--estimated .sss-pin__node {
  stroke: var(--gold);
  stroke-width: 1;
  stroke-opacity: 0.6;
  stroke-dasharray: 2 2;
}

/* Graceful error state */
.sss-error {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-align: center;
  padding: 2rem;
}
.sss-error__title {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2.4vw, 1.6rem);
  letter-spacing: 0.08em;
  color: var(--gold);
}
.sss-error__body {
  font-family: var(--font-ui);
  color: var(--accent-sec);
  max-width: 36ch;
}

/* ---- Responsive: stack on narrow screens --------------------------------- */
@media (max-width: 760px) {
  /* Stack: header, MAP, event panel (as a normal block below the map), then the
     tallies row. Nothing overlays the map. Explicit flex `order` because the
     sidebar is the first DOM child of the body. */
  .sss-body { flex-direction: column; }
  .sss-stage {
    order: 1;
    flex: 0 0 auto;
    height: 46vh;
    min-height: 240px;
  }
  .sss-sidebar {
    order: 2;
    flex: 0 0 auto;
    width: 100%;
    border-right: none;
    border-top: 1px solid rgba(214, 157, 163, 0.10);
    padding: 1rem 1.1rem;
    overflow-y: visible;
  }
  .sss-rail {
    order: 3;
    flex-basis: auto;
    width: 100%;
    border-left: none;
    border-top: 1px solid rgba(214, 157, 163, 0.10);
    flex-direction: row;
    align-items: center;
    padding: 0.6rem 1rem;
  }
  .sss-pin__label { font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .sss-pin__node, .sss-pin__halo, .sss-pin__labelwrap { transition: none; }
}
