/*
 * Design tokens.
 *
 * Deep space, near-monochrome type, one violet light and one warm accent.
 * The palette is inherited from the previous portfolio but stripped back:
 * the universe supplies the colour, the interface stays quiet.
 */
:root {
  --void: #04030a;
  --void-2: #07051230;

  --violet: #a888ff;
  --violet-deep: #7c3aed;
  --violet-pale: #e2d9ff;
  --amber: #f0b45f;
  /* The headline voice: the palette's own light, at full strength. No new
     colours are introduced — this is the violet and the amber already in use. */
  --poster: #f5c67a;
  --poster-bright: #e2d9ff;

  /*
   * Type has roles, not one colour. Titles carry light, body text is a soft
   * tinted white, technologies take the cool accent, warm labels take the
   * amber, and micro-labels stay dim but legible.
   */
  --text: #e7e1fb;
  --text-strong: #ffffff;
  --text-muted: rgba(226, 219, 250, 0.66);
  --text-faint: rgba(214, 206, 244, 0.38);
  --text-accent: #c9b6ff;
  --text-warm: #f3c489;

  /* Light emitted by content. Used sparingly — titles and hovered objects. */
  --glow-soft: 0 0 26px rgba(168, 136, 255, 0.55);
  --glow-warm: 0 0 30px rgba(240, 180, 95, 0.45);

  --hairline: rgba(196, 178, 255, 0.16);
  --hairline-strong: rgba(196, 178, 255, 0.4);

  /*
   * The signature blend.
   *
   * Orange, through a warm intermediate, into violet — the two ends of the
   * palette already in use, joined rather than picked between. The
   * intermediate stops are what stop it reading as a two-colour ramp: amber
   * warms into gold, gold cools through a pale lilac, and only then does it
   * reach the violet. Nothing outside the existing family is introduced.
   *
   *   #e8813a ─ #f5a94e ─ #ffd39a ─ #e6c2ff ─ #a888ff ─ #7c3aed
   *    orange    amber     gold      lilac    violet   deep violet
   */
  --blend: linear-gradient(
    104deg,
    #e8813a 0%,
    #f5a94e 16%,
    #ffd39a 34%,
    #e6c2ff 58%,
    #a888ff 78%,
    #7c3aed 100%
  );
  /* The same blend held tighter, for small type where the full ramp would
     read as a smear rather than as one lit word. */
  --blend-tight: linear-gradient(100deg, #f2a24e 0%, #ffd39a 40%, #b79bff 100%);

  --font-display: "Syne", "Segoe UI", sans-serif;
  /* Heavy condensed display face, used only where a line should hit hard. */
  --font-poster: "Anton", "Syne", "Segoe UI", sans-serif;
  /*
   * The voice of every title in the universe — every region except the
   * entrance, which stays formal so the landing screen reads as a
   * professional introduction rather than a poster.
   */
  --font-title: "Luckiest Guy", "Anton", "Syne", sans-serif;
  --title-ink: #f5c67a;
  --title-ink-bright: #ffe0a8;
  /* Titles carry colour, not light: no shadow on any of them. */
  --glow-title: none;
  --glow-title-near: none;
  --font-body: "DM Sans", "Segoe UI", sans-serif;
  --tracking-label: 0.36em;

  /*
   * The type scale.
   *
   * One ladder for the whole universe, so a project title, an experience
   * title and a certificate title are the same size wherever the camera
   * finds them. Every step is a clamp, so the hierarchy survives a phone as
   * well as a wide desktop.
   *
   * Sizes are set for reading *through perspective*: a place is read at
   * READ (see js/universe/constants.js) and perspective scales it to roughly
   * three quarters of its CSS size, so what looks generous in the stylesheet
   * arrives on screen merely comfortable.
   *
   *   display  a name that owns the frame
   *   title    a section or subject title
   *   subtitle the line directly under a title
   *   lead     the sentence that has to be read
   *   body     everything else that is prose
   *   meta     years, technologies, coordinates
   *   label    the small uppercase eyebrows
   */
  --t-display: clamp(3rem, 7vw, 6.6rem);
  --t-title: clamp(2.2rem, 3.9vw, 3.6rem);
  --t-subtitle: clamp(1.45rem, 2.1vw, 2.1rem);
  --t-lead: clamp(1.3rem, 1.75vw, 1.85rem);
  --t-body: clamp(1.14rem, 1.35vw, 1.42rem);
  /* An entry title: a certificate, a waypoint, a record line. Important, and
     clearly subordinate to the title of the region it sits in. */
  --t-entry: clamp(1.55rem, 2.35vw, 2.35rem);
  --t-meta: clamp(0.92rem, 1.05vw, 1.1rem);
  --t-label: clamp(0.76rem, 0.85vw, 0.9rem);

  --shell: min(1440px, 90vw);
  --gap-sm: 0.75rem;
  --gap-md: 1.5rem;
  --gap-lg: 2.75rem;

  /* Shared with the camera: CSS perspective must match FOCAL in camera.js. */
  --focal: 1000px;

  /* The air of a region; set per region by data-atmosphere on <html>. */
  --air: rgba(88, 52, 172, 0.15);
  --air-warm: rgba(240, 180, 95, 0.05);

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --speed-fast: 0.24s;
  --speed: 0.5s;
  --speed-slow: 0.9s;
}

/*
 * Each region of the universe carries its own light. The starfield changes
 * density and warmth to match (see ATMOSPHERES in js/universe/starfield.js).
 */
html[data-atmosphere="entrance"] {
  --air: rgba(80, 48, 160, 0.14);
  --air-warm: rgba(240, 180, 95, 0.04);
}

html[data-atmosphere="calm"] {
  --air: rgba(64, 46, 138, 0.12);
  --air-warm: rgba(240, 180, 95, 0.03);
}

html[data-atmosphere="network"] {
  --air: rgba(56, 74, 186, 0.16);
  --air-warm: rgba(120, 200, 255, 0.04);
}

html[data-atmosphere="energetic"] {
  --air: rgba(104, 52, 196, 0.2);
  --air-warm: rgba(240, 150, 95, 0.06);
}

html[data-atmosphere="warm"] {
  --air: rgba(120, 62, 140, 0.17);
  --air-warm: rgba(240, 170, 110, 0.11);
}

html[data-atmosphere="structured"] {
  --air: rgba(58, 52, 128, 0.13);
  --air-warm: rgba(220, 190, 140, 0.04);
}

html[data-atmosphere="quiet"] {
  --air: rgba(40, 34, 92, 0.1);
  --air-warm: rgba(240, 180, 95, 0.02);
}

/* The far end: the last of the warmth, and almost none of the violet. */
html[data-atmosphere="afterglow"] {
  --air: rgba(46, 30, 78, 0.13);
  --air-warm: rgba(240, 168, 110, 0.07);
}

/* Events run warmer than the technical regions, in type as well as in air. */
html[data-atmosphere="warm"] {
  --text-accent: #f3c489;
}
