/* Stations, cards and the hero. A station is one scroll stop; the 3D
   camera keyframe with the same index lives in src/data/keyframes.js. */
/* ── Content ─────────────────────────────────────────────────── */
  main { position: relative; z-index: 3; }
  .station { min-height: 100svh; display: flex; align-items: center; padding: 96px 30px; pointer-events: none; }
  .station > * { pointer-events: auto; }
  .st-hero  { justify-content: center; text-align: center; }

  /* While the page is still in space the type has to invert. Remapping the
     tokens covers the hero and the bar in one go, and the transition keeps
     it from snapping as the sky whitens on the way down. */
  /* The frosted panel belongs to the white part of the page — over space it
     has nothing to pick up and reads as a grey slab. The name itself stays;
     it just sits straight on the sky, and over-space already lightens it. */
  :root.over-space .hud-bar.scrolled {
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  :root.over-space .hud-name { text-shadow: 0 1px 12px rgba(0, 0, 0, .55); }

  :root.over-space {
    --ink:       #f5f5f7;
    --ink-soft:  #b9bec9;
    --ink-faint: #7e8492;
    --accent:    #6cb2ff;
    --hair:      rgba(255,255,255,.16);
    --bar:       rgba(10,12,24,.72);
  }
  .hud-name, .hero h1, .hero p, .hud-bl {
    transition: color .5s ease;
  }
  /* The type sits straight on the planet, and a lit continent behind a line
     of body copy will swallow it — so it gets a shadow while it is up there. */
  :root.over-space .hero h1,
  :root.over-space .hero p {
    text-shadow: 0 1px 3px rgba(0,0,0,.45), 0 4px 30px rgba(0,0,0,.55);
  }
  /* The imagery credit, in the HUD's mono caps, bottom right so it mirrors the scroll
     cue. The loop owns its opacity: up while the plates are on screen, gone with them. */
  .hero-credit { position: absolute; right: 30px; bottom: 28px; margin: 0;
                 font-family: ui-monospace, "SF Mono", "Roboto Mono", Menlo, monospace;
                 font-size: var(--fs-cap); letter-spacing: .075em; text-transform: uppercase;
                 color: rgba(255, 255, 255, .38); opacity: 0; pointer-events: none;
                 white-space: nowrap; }
  :root.no-gl .hero-credit, :root.no-motion .hero-credit { display: none; }
  .st-left  { justify-content: flex-start; }
  .st-right { justify-content: flex-end; }
  /* The globe holds, then the descent needs scroll room to breathe. The copy
     is pinned for that whole stretch, because it has somewhere to go: it
     travels down onto the planet as the planet zooms in. Scrolling it off the
     top instead wasted the hold. */
  .station[data-station="0"] { align-items: stretch; padding: 0; min-height: 200svh; }
  .hero-sticky {
    position: sticky; top: 0; height: 100svh; width: 100%;
    display: flex; align-items: center; justify-content: center; padding: 0 30px;
    pointer-events: none;
  }
  .hero-sticky > * { pointer-events: auto; }

  /* Cards animate opacity/transform only — never display — so find-in-page
     and screen readers always reach the text. */
  .card {
    max-width: 400px;
    background: var(--card-solid);
    border-radius: 24px;
    padding: 28px 30px 30px;
    box-shadow: var(--shadow);
    opacity: 0; transform: translateY(20px) scale(.985);
    transition: opacity .5s ease, transform .55s cubic-bezier(.32,.9,.24,1);
    will-change: opacity, transform;
  }
  .card.in { opacity: 1; transform: none; }
  :root.no-motion .card, :root.no-gl .card { opacity: 1; transform: none; }
  /* The page is held still while the opening plays — see src/scene/intro.js.
     Dormant: the opening is shelved (CFG.intro.enabled), so the class is never added. */
  :root.intro-lock, :root.intro-lock body { overflow: hidden; height: 100%; }
  /* The hero planet drags (src/scene/index.js, heroDrag). The loop sets the class
     while the page is on the hero and the opening is over; links keep their own
     cursor. pan-y leaves vertical scrolling to the browser on touch, so a sideways
     swipe turns the planet and an up-and-down one still scrolls. */
  :root.globe-grab { cursor: grab; }
  :root.globe-grabbing { cursor: grabbing; }
  :root.globe-grab body { touch-action: pan-y; }
  .st-hero { -webkit-user-select: none; user-select: none; }


  .card h2 { font-size: var(--fs-title); font-weight: 600;
             letter-spacing: var(--ls-title); line-height: var(--lh-title); margin: 0 0 4px; }
  /* Employer -> role -> what you did. Warsaw is two separate companies and
     the other two are one each; a flat list of roles couldn't say who you
     worked for, so the company anchors every block. */
  .job { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--hair); }
  .job-h { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
  .job-h b { font-size: var(--fs-body); font-weight: 600; letter-spacing: var(--ls-body); }
  .job-h span { flex: none; font-size: 11.5px; color: var(--ink-faint); white-space: nowrap; }
  .job-role { margin-top: 2px; font-size: var(--fs-sub); font-weight: 500;
              letter-spacing: var(--ls-body); color: var(--accent); }
  .job ul { margin: 9px 0 0; padding: 0; list-style: none; }
  .job li { position: relative; padding-left: 15px; margin-top: 5px;
            font-size: var(--fs-sub); line-height: 1.5; color: var(--ink-soft); }
  .job li::before { content: ""; position: absolute; left: 3px; top: .62em;
                    width: 4px; height: 4px; border-radius: 50%; background: var(--ink-faint); }
  .note { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--hair);
          font-size: var(--fs-body); line-height: var(--lh-body); letter-spacing: var(--ls-body); }
  .note em { font-style: normal; font-weight: 600; }

  .chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 15px; }
  .chips i { font-style: normal; font-size: 12px; letter-spacing: -.008em;
             padding: 5px 11px; border-radius: 980px;
             background: var(--surface); color: var(--ink-soft); }

  /* Hero */
  /* Full width, not shrink-to-fit: the lead paragraph is capped at 620px and
     was running wider than the shrink-to-fit box, which nothing showed until
     the box became a mask — then it clipped the first and last glyph. */
  .hero { width: 100%; max-width: 880px; background: none; box-shadow: none; padding: 0; }
  /* Scroll writes this transform every frame, so it must not be transitioned:
     a transition here trails the wheel instead of tracking it. The in/out
     state changes opacity only, or the copy would jump on the class flip. */
  /* The planet's disc, punched out of the type. Both radii come from the same
     projection the planet is drawn with, so the edge lands exactly on the
     limb. Unset — no WebGL — the circle sits off the card and nothing is cut.
     No transition on any of it: scroll writes these every frame, and a
     transition would trail the wheel instead of tracking it. */
  .hero, .hero.in {
    transform: translate(var(--heroX, 0px), var(--heroY, 0px));
    opacity: var(--heroFade, 0);   /* the loop owns it; no-gl/no-motion override below */
    transition: none;
    -webkit-mask-image: radial-gradient(circle at var(--mx, 50%) var(--my, -99999px),
                        transparent var(--mr0, 0px), #000 var(--mr1, 0px));
            mask-image: radial-gradient(circle at var(--mx, 50%) var(--my, -99999px),
                        transparent var(--mr0, 0px), #000 var(--mr1, 0px));
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  }
  .hero h1 { font-size: clamp(34px, 6.4vw, 66px); font-weight: 600;
             letter-spacing: var(--ls-display); line-height: var(--lh-display);
             min-height: 1.06em; }        /* holds the line while it retypes */
  /* Placed against the h1 and moved by transform, so it glides along the line
     as it types instead of hopping a character at a time. Step timing on the
     blink, because a fade reads as a glow rather than a cursor. */
  .hero h1 { position: relative; }
  .hero .caret {
    position: absolute; left: 0; top: 0;
    width: .07em; height: .88em; margin-left: .06em;
    background: currentColor;
    transform: translate(var(--cx, 0px), calc(var(--cy, 0px) - 50%));
    will-change: transform;
  }
  .hero .caret.idle { animation: caret 1.05s steps(1) infinite; }
  @keyframes caret { 0%, 50% { opacity: 1 } 50.01%, 100% { opacity: 0 } }

  /* The loader (src/load.js): the orb over the count in the hero's own line —
     its type, its ink over space — on the sky's black, above the page and
     below the cursor. The orb is thinking-orbs' "solving" state
     (vendor/thinking-orbs) in the closing planet's own light, drawn on the
     canvas at the size its dots were tuned for — 300 px, or 60 vmin on a
     small screen — with the line under it; the two are centred as one stack.
     The page holds still under it (html.loading). At 100 the number becomes
     the headline's first line in place: the two zeros close up (.load-z, an
     inline box whose width eases down to a space's while its ink goes), so
     "100%" reads "1 %", and the rest of the line types on after it. Then
     the whole panel — black, orb and line — fades out gently (.fade, 1 s)
     over the scene as the planet comes in; the headline types at the top
     only once it has gone. */
  html.loading { overflow: hidden; }
  .load { position: fixed; inset: 0; z-index: 30; display: grid; justify-items: center;
          align-content: center; row-gap: clamp(18px, 3.4vmin, 32px);
          background: #000011; color: #f5f5f7;
          transition: opacity 1s ease; }
  .load-orb { display: block; width: min(300px, 60vmin); height: min(300px, 60vmin); }
  .load.fade { opacity: 0; pointer-events: none; }
  .load[hidden] { display: none; }
  .load-line { position: relative; font-size: clamp(34px, 6.4vw, 66px); font-weight: 600;
               letter-spacing: var(--ls-display); line-height: var(--lh-display);
               font-variant-numeric: tabular-nums; white-space: nowrap;
               text-shadow: 0 1px 3px rgba(0,0,0,.45), 0 4px 30px rgba(0,0,0,.55); }
  .load-n { display: inline-block; min-width: 1.7ch; text-align: right; }
  .load.done .load-n { min-width: 0; }
  /* the zeros' box: top-aligned so the digits keep the line's baseline while
     the box shrinks; the script sets --zw (their width) and --sw (a space's) */
  .load-z { display: inline-block; vertical-align: top; overflow: hidden; width: var(--zw);
            transition: width .5s cubic-bezier(.32, .9, .24, 1), opacity .32s ease; }
  .load.done .load-z { width: var(--sw); opacity: 0; }
  .hero p { margin: 22px auto 0; max-width: 620px; font-size: var(--fs-lead);
            line-height: var(--lh-lead); letter-spacing: var(--ls-lead);
            font-weight: 400; color: var(--ink-soft); }

  /* Outro */
