/* ═══════════════════════════════════════════════════════════════════
   LANDING — Figma `Portfolio-work` tGkoQ6Ihr858AKBwWVtx0Z,
   frame `Desktop - 18` (1:12), 1440 × 10057 on #efefef.

   ONE rule governs this file: no number is invented. Everything is a
   literal inspector value carried inline on --x/--y/--w/--h and
   multiplied by --u, so any element can be diffed against Figma by
   reading its style attribute. Colours are the file's own hex.
   ═══════════════════════════════════════════════════════════════════ */

:root{
  /* design unit — 1 Figma px. JS re-derives this from clientWidth so
     the scrollbar never shifts it; this is the no-JS fallback. */
  --u: calc(100vw / 1440);

  --page:   #efefef;   /* 1:12 frame fill */
  --accent: #e8a567;   /* 1:56 card base, and both hero text lines */
  --ink:    #0e0c0b;   /* nav labels */
  --chip:   #e1e1e1;   /* 1:611/620/626/632/638 pill fill */
  --pale:   #f2efe9;   /* wordmark + masthead, at their own alphas */
  --rule:   #666666;   /* 1:93-1:98 */
  --mid:    #8a8785;   /* the fall-back grey for rows not being pointed at:
                          a mid grey carrying the ink's warm cast */
  --ease-out: cubic-bezier(.22,.61,.36,1);
  /* about: scroll consumed per handoff, and in total (5 handoffs plus a
     short lead-in and a hold on the last bar before it releases) */
  --about-step: 90vh;
  --about-d: calc(var(--about-step) * 5.8);
}

*,*::before,*::after{ box-sizing:border-box; }

html{ background:var(--page); }
body{
  margin:0;
  background:var(--page);
  font-family:"Geist",system-ui,sans-serif;
  font-synthesis-weight:none;       /* never fake a Geist weight */
  /* The arrow everywhere. Without this the browser swaps in the text
     I-beam over the hero's live type (the transparent <h1>, tagline,
     status line). Links still get the hand from the UA stylesheet. */
  cursor:default;
  -webkit-font-smoothing:antialiased;
  text-rendering:geometricPrecision;
}

/* The frame is the positioning context for every literal coordinate.
   Its height grows as sections are added: currently it ends at the
   about bars' foot (y2874 + their drawn height, 700·k) + 97 of air for
   their shadows, plus the scroll the pinned about section consumes
   (--about-d).
   overflow:CLIP, not hidden: hidden makes the frame a scroll container,
   and position:sticky inside it would then pin to the frame (which never
   scrolls) instead of the viewport — the about bars would never stick. */
.frame{
  position:relative;
  width:100%;
  /* ends 97 under the about bars' foot: room for their shadows (the
     deepest falls ~94 below them, and overflow:clip would cut it), and
     with the lead's ink 31 into its box, a 128 gap to the footer — one
     rhythm with the rest of the page */
  height:calc(var(--u) * (2874 + 700 * var(--about-k, 1) + 97) + var(--about-d));
  overflow:clip;
}

/* ─── the coordinate primitive ─────────────────────────────────────
   --x/--y are the frame (or card) origin, --w/--h the node's box.
   Height is optional: text that hugs omits it. */
.n{
  position:absolute;
  left:calc(var(--u) * var(--x));
  top: calc(var(--u) * var(--y));
  width:calc(var(--u) * var(--w));
  height:calc(var(--u) * var(--h));
  margin:0;
}

/* ═══ chrome — 3:27 ════════════════════════════════════════════════ */
.chrome{ position:absolute; inset:0; height:calc(var(--u) * 41); z-index:20; }

/* 1:606 — Geist Regular 15 / ls -0.45px / #f2efe9, line-height normal */
.wordmark{
  height:auto;
  font-size:calc(var(--u) * 15);
  font-weight:400;
  letter-spacing:calc(var(--u) * -0.45);
  line-height:normal;
  color:var(--pale);
  white-space:nowrap;
}

.mark{ display:block; }
.mark img{ display:block; width:100%; height:100%; }

/* The fixed layer: logo + the four pills. Full-width but click-through,
   so only the controls themselves catch the pointer. */
.chrome__fixed{
  position:fixed;
  left:0; top:0;
  width:100%;
  height:calc(var(--u) * 41);
  z-index:40;
  pointer-events:none;
}
.chrome__fixed a{ pointer-events:auto; }

/* ── grey liquid glass ─────────────────────────────────────────────
   1:611 / 620 / 626 / 632 / 638 were a flat #e1e1e1, h28, r4. Now:
   · a grey tint, tuned so that over the #efefef page (the top of the
     site, where Figma draws it) the pill still lands on ~#e1e1e1 —
     239 × .53 + 205 × .47 ≈ 223;
   · a strong backdrop blur with a little extra light, so whatever
     scrolls under it turns to frost rather than showing through, and the
     ink label keeps a light enough ground even over the dark hero;
   · the rim: a bright specular line along the top edge, a faint
     hairline all round, a whisper of shade on the bottom edge, and a
     soft contact shadow — the edge-lighting that makes glass read as a
     thick, rounded pane rather than a flat tint. */
.pill,
.mark__glass,
.work__pill,
.cursor-pill,
.rail__exp{
  background:
    linear-gradient(180deg, rgba(255,255,255,.34) 0%, rgba(255,255,255,0) 52%),
    rgba(205,203,201,.52);
  /* saturation held near 1: more pulled the hero's sunset into the
     pills and they read brown; Arnav asked for a GREY tint */
  -webkit-backdrop-filter:blur(14px) saturate(1.1) brightness(1.08);
          backdrop-filter:blur(14px) saturate(1.1) brightness(1.08);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.72),
    inset 0 0 0 .5px rgba(255,255,255,.38),
    inset 0 -1px 0 rgba(14,12,11,.06),
    0 1px 2px rgba(14,12,11,.07),
    0 6px 16px -6px rgba(14,12,11,.16);
}
.pill{
  display:block;
  border-radius:calc(var(--u) * 4);
  text-decoration:none;
}
/* the logo's disc: the same glass, invisible at the top of the page */
.mark{ position:absolute; }
.mark img{ position:relative; }
.mark__glass{
  position:absolute; inset:calc(var(--u) * -3);
  border-radius:50%;
  opacity:0;
  transition:opacity .35s var(--ease-out);
}
[data-chrome].is-scrolled .mark__glass{ opacity:1; }
/* the logo is a button too (home): the disc comes up under it on hover,
   it lifts a pixel, and sinks when pressed, like the pills */
.mark{ transition:transform .35s var(--ease-out); }
.mark:hover{ transform:translateY(-1px); }
.mark:hover .mark__glass{ opacity:1; }
.mark:active{ transform:scale(.95); transition-duration:.12s; }
@media (prefers-reduced-motion: reduce){ .mark:hover, .mark:active{ transform:none; } }
/* No white rim on the disc (Arnav, 2026-09-22). The specular top line and
   the white hairline that give the pills their glass edge read, on a small
   circle hugging the logo's black ring, as a stray white ring. The disc
   keeps the frosted grey and the contact shadow only. */
.mark__glass{
  background:rgba(205,203,201,.52);
  box-shadow:
    0 1px 2px rgba(14,12,11,.07),
    0 6px 16px -6px rgba(14,12,11,.16);
}
/* The label is NOT padding — it is its own node, carried on the pill
   as (label − pill) so the absolute result is the inspector's. */
.pill__t{
  position:absolute;
  font-size:calc(var(--u) * 20);
  font-weight:400;
  letter-spacing:calc(var(--u) * -0.6);
  /* Figma REPORTS lineHeight 99.945% on every one of these nodes but
     lays the glyphs out on Geist's natural line box (1.3172em) and
     only shrinks the reported node height. Honouring the reported
     value puts every label exactly 3px high; `normal` lands it. */
  line-height:normal;
  color:var(--ink);
  white-space:nowrap;
}
.pill__t--auto{ width:auto; }

/* 1:635 — the clock. Right edge pinned where Figma has it (1314 + 85 =
   1399, i.e. 41 from the frame's right), 7px padding both sides, the
   label centred on both axes. Tabular numerals so the pill does not
   twitch wider and narrower every second as the digits change. */
.pill--clock{
  position:absolute;
  top:calc(var(--u) * 6);
  right:calc(var(--u) * 41);
  height:calc(var(--u) * 28);
  padding:0 calc(var(--u) * 7);
  display:flex;
  align-items:center;
  justify-content:center;
}
.pill__clock{
  font-size:calc(var(--u) * 20);
  font-weight:400;
  letter-spacing:calc(var(--u) * -0.6);
  line-height:1;
  font-variant-numeric:tabular-nums;
  color:var(--ink);
  white-space:nowrap;
}

/* ═══ hero — 1:54 ══════════════════════════════════════════════════
   Three layers, first to last paint:
     1. the card's own background — a gradient sampled from the poster
        (top → horizon → ground), so even the instant before the poster
        arrives shows the right light, never a flat block;
     2. the poster — a 2× still of the shader at rest; the first real
        paint, and the whole hero if WebGL is unavailable;
     3. the shader canvas (js/hero-fx.js), faded in over the poster once
        its image and font are ready. The two match, so the fade is a
        quiet hand-off, not a change of picture. */
.hero{ position:absolute; inset:0; height:calc(var(--u) * 1000); }

.hero__card{
  background:linear-gradient(180deg,
    #56402d 0%, #7c5035 20%, #c38240 40%, #52290d 55%, #0c0b0a 70%, #0d0c0b 100%);
  border-radius:calc(var(--u) * 13);
  overflow:hidden;
  isolation:isolate;
}
.hero__poster{
  position:absolute; inset:0;
  display:block;
  width:100%; height:100%;
  pointer-events:none;
}
.hero__fx{
  position:absolute;
  left:0; top:0;
  display:block;
  pointer-events:none;
  opacity:0;
  transition:opacity .45s var(--ease-out);
}
.hero__fx.is-ready{ opacity:1; }

/* 1:59 — the name. Both the poster and the canvas draw it, so the live
   <h1> stays in the DOM for search and screen readers but paints
   nothing. Its box keeps Figma's metrics so selection lands sensibly. */
.hero__name{
  font-size:calc(var(--u) * 270);
  font-weight:400;
  letter-spacing:calc(var(--u) * -21.6);
  line-height:calc(var(--u) * 355.632);
  color:transparent;
  white-space:nowrap;
}

/* 1:64 / 1:66 — Geist Regular 20 / ls -0.6px / #e8a567, centred */
.hero__tagline,.hero__status{
  font-size:calc(var(--u) * 20);
  font-weight:400;
  letter-spacing:calc(var(--u) * -0.6);
  color:var(--accent);
  text-align:center;
  line-height:normal;          /* same natural-line-box rule as above */
}
/* 1:64's string ends in a space. Figma counts it when centring, CSS
   would drop it — which walks the visible ink 2.3px right. `pre`
   keeps the trailing space in the line, so the centring matches. */
.hero__tagline{ white-space:pre; }
.hero__status { white-space:nowrap; }
/* Geist ships no italic on Google Fonts; the file's slant on this one
   word is reproduced obliquely, which is what Figma is drawing too. */
.hero__status em{ font-style:italic; }

/* ═══ masthead — 1:75 / 1:76 ═══════════════════════════════════════
   Geist Mono Medium 11 / lh 130% / ls 1.32px / rgba(242,239,233,.4) */
.masthead{
  font-family:"Geist Mono",ui-monospace,monospace;
  font-size:calc(var(--u) * 11);
  font-weight:500;
  letter-spacing:calc(var(--u) * 1.32);
  line-height:1.3;
  color:rgba(242,239,233,0.4);
  white-space:nowrap;
}
.masthead--r{ text-align:right; }

/* ═══ intro — 1:77 + 1:138 ═════════════════════════════════════════ */
/* Geist Medium 40 / lh 130% / ls -0.8px / #0e0c0b, centred. Figma's
   1.3 is a real line height here (2 lines × 52 = the node's 104), unlike
   the 99.945% it reports elsewhere, so it is honoured. */
.intro__line{
  font-size:calc(var(--u) * 40);
  font-weight:500;
  letter-spacing:calc(var(--u) * -0.8);
  line-height:1.3;
  color:var(--ink);
  text-align:center;
}
/* the reveal (js/intro-reveal.js): pale → ink as you scroll, the letters
   being inked right now glowing in the accent. The copies sit exactly on
   the original (same class, same coordinates). */
.intro__line--base{ color:rgba(14,12,11,.2); }
.intro__line--reveal,
.intro__line--flash{ pointer-events:none; user-select:none; }
.intro__line--reveal{ clip-path:inset(0 100% 0 0); }
.intro__line--flash{
  --fw:calc(var(--u) * 64);                  /* about two letters of glow */
  color:var(--accent);
  opacity:0;
  -webkit-mask-image:linear-gradient(90deg, transparent calc(var(--fx, 0px) - var(--fw)),
                     #000 calc(var(--fx, 0px) - var(--fw) * .3), #000 calc(var(--fx, 0px) - 1px),
                     transparent calc(var(--fx, 0px) + 1px));
          mask-image:linear-gradient(90deg, transparent calc(var(--fx, 0px) - var(--fw)),
                     #000 calc(var(--fx, 0px) - var(--fw) * .3), #000 calc(var(--fx, 0px) - 1px),
                     transparent calc(var(--fx, 0px) + 1px));
}

/* The system cursor is hidden only while the intro's arrow is actually
   being your cursor — js/intro-cursor.js sets this class from the same
   hit-test that moves the arrow (intro band → last work rule), so a
   failed script never leaves the page cursorless. */
html.cursor-yours,
html.cursor-yours *{ cursor:none !important; }

.intro__cursor{
  display:block;
  z-index:30;
  pointer-events:none;
  user-select:none;
  will-change:transform;
}
/* while it IS your pointer it rides above everything you can point at,
   the nav's glass pills included (40); at rest it's part of the page
   and scrolls under the nav like the rest, and a case study covers it */
html.cursor-yours:not(.detail-open) .intro__cursor{ z-index:41; }

/* annotation marks over "Research" / "Building" / "fast"
   (js/intro-marks.js). Every path carries pathLength="1", so a dash of
   1 offset by 1 is fully hidden and offset 0 is fully drawn. */
.intro__marks{
  position:absolute;
  left:0; top:0;
  overflow:visible;
  pointer-events:none;
}
.intro__marks path{
  fill:none;
  stroke:var(--accent);
  stroke-width:var(--sw, 2.25px);
  stroke-linecap:round;
  stroke-linejoin:round;
  stroke-dasharray:1;
  stroke-dashoffset:1;
}
.intro__marks.is-drawn path{ stroke-dashoffset:0; }
.intro__marks path.is-on{ stroke-dashoffset:0; }   /* per word, as the reveal reaches it */

/* ═══ selected work — 1:113 + 4:91 ═════════════════════════════════ */
.anchor{ position:absolute; left:0; top:calc(var(--u) * var(--y)); width:1px; height:1px; }

/* 1:114 — r4; 1:115 — Geist Medium 20 / 130% / -0.4px. The surface is
   the nav's grey liquid glass (Arnav, 2026-09-23), which over the page
   lands on the same ~#e1e1e1 as Figma's flat rgba(14,12,11,.06). */
.work__pill{
  border-radius:calc(var(--u) * 4);
}
.work__pill-t{
  width:auto;
  font-size:calc(var(--u) * 20);
  font-weight:500;
  letter-spacing:calc(var(--u) * -0.4);
  line-height:1.3;
  color:var(--ink);
  white-space:nowrap;
}

.work__rule{ background:var(--rule); }

/* A row is its band, rule to rule. Everything in it is positioned
   relative to the band, so the band itself is the hover target. */
.wrow{ margin:0; }
.wrow__name,.wrow__role,.wrow__desc{
  margin:0;
  height:auto;
  color:var(--ink);
  transition:color .45s var(--ease-out);
}
/* 1:82 etc — Geist Medium 20 / 130% / -0.4px */
.wrow__name{ font-size:calc(var(--u) * 20); font-weight:500; letter-spacing:calc(var(--u) * -0.4); line-height:1.3; }
/* 1:83 etc — Geist Light 20 / 130% / -0.4px */
.wrow__role{ font-size:calc(var(--u) * 20); font-weight:300; letter-spacing:calc(var(--u) * -0.4); line-height:1.3; }
/* 1:78 etc — Geist Light 14 / 150% / -0.14px */
.wrow__desc{ font-size:calc(var(--u) * 14); font-weight:300; letter-spacing:calc(var(--u) * -0.14); line-height:1.5; }

/* swatches r6, tiles r5; media fills its box unless Figma crops it */
.wrow__sw,.wrow__tile{
  display:block;
  overflow:hidden;
  transition:filter .45s var(--ease-out), opacity .45s var(--ease-out);
}
.wrow__sw  { border-radius:calc(var(--u) * 6); }
.wrow__tile{ border-radius:calc(var(--u) * 5); }
.wrow__sw img,.wrow__tile img,.wrow__tile video{
  display:block; width:100%; height:100%; object-fit:cover;
}
/* 1:187 / 1:120 / 1:121 / 1:186 carry explicit fill crops — the
   percentages sit inline, straight from the inspector */
.wrow__tile--crop{ position:absolute; }
.wrow__tile--crop img{ position:absolute; max-width:none; object-fit:fill; }

/* ── the hover: point at one row, the rest fall back ────────────────
   Pure CSS. While any row is hovered, every OTHER row's type drops to
   mid grey and its media goes monochrome and recedes. Nothing happens
   to the row you are on — it stays exactly as designed, so the
   contrast does the pointing. The intro's arrow stays your cursor
   through the rows (Arnav, 2026-09-23). */
.work:has(.wrow:hover) .wrow:not(:hover) .wrow__t{ color:var(--mid); }
.work:has(.wrow:hover) .wrow:not(:hover) .wrow__m{ filter:grayscale(1); opacity:.5; }

/* ═══ about — 51:74 / 51:78 / 85:24 / 85:54 ═══════════════════════
   The track is where the bars would sit (y2874), stretched by the scroll
   the piece consumes. The stage inside it is sticky, centred in the
   viewport, so the bars ride up, pin, play, and release.

   Widths are flex-grow set by js/about.js from scroll position — no CSS
   transitions, the scroll IS the timeline. One container means the bar
   opening and the bar closing always sum to exactly 1242.
     rest   all grow 1, 37 apart   → 218.8 each          (51:74)
     open   6.574 / 1, 18.4 apart  → 726.4 / 110.5       (51:78…)
   6.574 = 726.4 / 110.5, Figma's open-to-closed ratio. */
.about-track{
  position:absolute;
  left:0; width:100%;
  top:calc(var(--u) * var(--y));
  height:calc(var(--u) * 700 * var(--about-k, 1) + var(--about-d));
}
/* Pinned in the space BELOW the fixed nav, never the whole viewport:
   centred on the whole viewport, a laptop-height window (~740px) put the
   bars' top ~20px down — under the 41px nav. js/about.js computes
   --about-top (the pin) and --about-k (a uniform scale ≤ 1 so the 700
   bars always fit between the nav and the bottom edge); bars, gaps and
   labels shrink together, so the composition is the design, smaller.
   The fallback values are the full-size, nav-safe pin. */
.about{
  position:sticky;
  top:var(--about-top, calc(var(--u) * 41 + (100vh - var(--u) * 741) / 2));
  margin-left:calc(var(--u) * 99);
  width:calc(var(--u) * 1242);
  /* the stage's LAYOUT height is the bars' drawn height: scaled with a
     transform alone, it kept a full 700 in the flow, and un-pinned with
     700·(1−k) of dead space under the bars (~84px on a laptop) */
  height:calc(var(--u) * 700 * var(--about-k, 1));
}
.about__bars{
  position:absolute; left:0; right:0; top:0;
  height:calc(var(--u) * 700);
  transform:scale(var(--about-k, 1));
  transform-origin:50% 0;
  display:flex;
  column-gap:calc(var(--u) * var(--gap, 37));
}

.abar{
  position:relative;
  flex:1 1 0;
  min-width:0;
  margin:0;
  border-radius:calc(var(--u) * 13);
  overflow:hidden;               /* clips the label — see index.html */
  background:var(--c);
  isolation:isolate;             /* keeps the grain's blend inside the bar */
  /* Depth (Arnav, 2026-09-22) — lit from above, like the nav glass but
     heavier, because these are slabs, not chips: a tight contact shadow
     where the bar meets the page, then two soft falls beneath it. The
     overflow clip doesn't touch a box's own outer shadow. */
  box-shadow:
    0 calc(var(--u) * 1)  calc(var(--u) * 2)  rgba(14,12,11,.12),
    0 calc(var(--u) * 6)  calc(var(--u) * 12) calc(var(--u) * -3)  rgba(14,12,11,.16),
    0 calc(var(--u) * 22) calc(var(--u) * 40) calc(var(--u) * -14) rgba(14,12,11,.30),
    0 calc(var(--u) * 44) calc(var(--u) * 80) calc(var(--u) * -30) rgba(14,12,11,.26);
}
/* The slab's edge light. It has to sit ABOVE the textures (an inset
   shadow on the bar itself paints underneath its children, so the
   textures would bury it) and below the label: a lit top edge, a faint
   hairline all round, a shaded bottom edge, and a soft top-to-bottom
   sheen that rounds the face. */
.abar::after{
  content:"";
  position:absolute; inset:0;
  border-radius:inherit;
  pointer-events:none;
  background:linear-gradient(180deg,
    rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 22%,
    rgba(0,0,0,0) 72%, rgba(0,0,0,.10) 100%);
  box-shadow:
    inset 0 calc(var(--u) * 1) 0 rgba(255,255,255,.22),
    inset 0 0 0 calc(var(--u) * .5) rgba(255,255,255,.07),
    inset 0 calc(var(--u) * -1) 0 rgba(0,0,0,.28);
}

/* the texture, flipped as Figma flips it, locked at the OPEN bar's cover
   scale (658×987 → 726.4×1089.6) and centred, so it never zooms */
.abar__tex{
  position:absolute;
  left:50%; top:50%;
  width:calc(var(--u) * 726.4);
  height:calc(var(--u) * 1089.6);
  max-width:none;
  transform:translate(-50%,-50%) scaleY(-1);
  opacity:var(--tex);
  pointer-events:none;
}
.abar__tex--b{ opacity:.45; }
/* The grain: tex-b again, soft-light. Soft-light pivots on mid-grey, so a
   texture averaging near it darkens and lightens in equal measure — the
   bar shows grain everywhere but keeps its Figma tone.
   It is MIRRORED (both axes flipped relative to the base layer) so the
   two grains never line up, and drawn 18% oversize so no edge of it can
   ever fall inside the open bar. An earlier version offset it instead,
   which left a ~29px ungrained strip down the open bar's left side. */
.abar__grain{
  width:calc(var(--u) * 726.4 * 1.18);
  height:calc(var(--u) * 1089.6 * 1.18);
  opacity:var(--grain, .55);
  mix-blend-mode:soft-light;
  /* tex-b averages ~180, well above soft-light's 128 pivot, so on its
     own it lightens every bar ~16 levels. Dimming it by 128/180 centres
     it on the pivot: same grain, zero net shift in tone. */
  filter:brightness(.71);
  transform:translate(-50%,-50%) scaleX(-1);
}

/* The label turns -90° about its own top-left, which is parked on the
   bar's bottom-right corner, so it reads upward from the bar's foot.
   --lx pulls it back in so the baseline sits just inside the edge;
   calibrated against Figma's render of 51:74 (baselines match exactly). */
.abar__label{
  --lx:140.9;
  position:absolute;
  left:100%; top:100%;
  margin:0;
  font-size:calc(var(--u) * 128);
  font-weight:400;
  line-height:1.5;
  letter-spacing:calc(var(--u) * -1.28);
  color:#efefef;
  white-space:nowrap;
  transform-origin:0 0;
  transform:translateX(calc(var(--u) * var(--lx) * -1)) rotate(-90deg);
  z-index:1;
}
/* a closed slab is a button (js/about.js): a click opens it */
.abar:not(.is-open){ cursor:pointer; }
.abar{ transition:filter .35s var(--ease-out); }
.abar:not(.is-open):hover{ filter:brightness(1.08); }
.abar:focus-visible{ outline:2px solid var(--accent); outline-offset:4px; }
.abar:focus:not(:focus-visible){ outline:none; }
/* art isn't ready: a black banner of "coming soon" runs across the open slab */
.abar__soon{
  position:absolute; top:0; left:50%;
  width:calc(var(--u) * 726.4);
  height:100%;
  display:flex; align-items:center;
  overflow:hidden;
  pointer-events:none;
}
.soon__track{
  display:flex; flex:none;
  white-space:nowrap;
  font-family:"Geist",system-ui,sans-serif;
  font-size:calc(var(--u) * 72);
  font-weight:400;
  letter-spacing:-.02em;                /* the text's own spacing */
  line-height:1;
  color:#efefef;
  align-items:center;
  /* the banner is a black band across the slab with the words on it
     (Arnav's mock); the band travels with the words, and being one flat
     colour it never shows a seam */
  background:#0e0c0b;
  padding:.34em 0;
  animation:soon 18s linear infinite;
}
/* "coming soon ● coming soon ●": a real circle in the text's colour,
   a word space either side (Arnav's mock) */
.soon__track i{
  flex:none;
  width:.22em; height:.22em;
  margin:.1em .3em 0;                   /* sits on the x-height's middle */
  border-radius:50%;
  background:currentColor;
}
@keyframes soon{ to{ transform:translateX(-50%); } }   /* two identical halves: seamless */
.abar:not(.is-open) .soon__track{ animation-play-state:paused; }
@media (prefers-reduced-motion: reduce){ .soon__track{ animation:none; } }

/* ── the slabs' objects only come out in the spotlight ─────────────────
   js/about.js sets --open (0 closed → 1 open) on each slab. Its objects
   fade in over the second half of its opening (45% → 90%) with a slight
   settle in scale, and fade out the same way as it closes — at rest, and
   on every slab but the open one, there is only stone. Hidden means gone:
   no clicks, no hovers (.is-open is set from the same 45%). */
.abar__globe,
.abar__music,
.abar__life,
.abar__about,
.abar__soon{
  --shine:clamp(0, calc((var(--open, 0) - .45) / .45), 1);
  opacity:var(--shine);
  transform:translateX(-50%) scale(calc(.965 + .035 * var(--shine)));
  transform-origin:50% 45%;
}
.abar:not(.is-open) .abar__globe,
.abar:not(.is-open) .abar__music,
.abar:not(.is-open) .abar__life,
.abar:not(.is-open) .abar__about,
.abar:not(.is-open) .abar__soon{ visibility:hidden; }

/* ── about: one engraved plate (js/about-words.js) ────────────────────
   Brushed steel — the grain runs vertically, the light falls across it
   from the upper left — with the text ENGRAVED: every letter a dark cut
   with a lit lower lip; the key words cut and filled with the accent.
   When the slab opens the plate drops onto the stone: its shadow
   tightens as it meets the slab, it settles, and one glint crosses the
   metal as it comes to rest. */
.abar__about{
  position:absolute; top:0; left:50%;
  width:calc(var(--u) * 726.4);
  height:100%;
  display:flex; align-items:center; justify-content:center;   /* the plate, centred in the slab */
}
@property --lift{ syntax:"<number>"; inherits:false; initial-value:0; }
.plaque{
  position:relative;
  width:calc(var(--u) * 480);
  padding:calc(var(--u) * 46) calc(var(--u) * 44) calc(var(--u) * 50);
  border-radius:calc(var(--u) * 5);
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='1200' preserveAspectRatio='none'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.3 .003' numOctaves='2' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5  0 0 0 0 .5  0 0 0 0 .5  1.4 0 0 0 -.45'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E"),
    radial-gradient(120% 90% at 18% 8%, rgba(255,255,255,.34), rgba(255,255,255,0) 60%),
    linear-gradient(168deg, #d7d9db 0%, #bfc2c5 38%, #a9adb1 72%, #9b9fa3 100%);
  background-size:300px 100%, 100% 100%, 100% 100%;         /* the grain runs the plate's full height: no seam */
  background-blend-mode:soft-light, normal, normal;
  box-shadow:
    inset 0 calc(var(--u) * 1) 0 rgba(255,255,255,.7),
    inset calc(var(--u) * 1) 0 0 rgba(255,255,255,.35),
    inset 0 calc(var(--u) * -1.5) 0 rgba(0,0,0,.28),
    inset calc(var(--u) * -1) 0 0 rgba(0,0,0,.14),
    0 calc(var(--u) * (1 + var(--lift) * 18)) calc(var(--u) * (2 + var(--lift) * 18)) rgba(0,0,0,calc(.55 - var(--lift) * .3)),
    0 calc(var(--u) * (14 + var(--lift) * 40)) calc(var(--u) * (30 + var(--lift) * 30)) calc(var(--u) * -8) rgba(0,0,0,calc(.55 - var(--lift) * .2));
  overflow:hidden;
  --lift:1;
  opacity:0;
  transform:translateY(calc(var(--u) * -90)) rotate(-1.2deg) scale(1.025);
}
/* the glint that crosses the metal as it lands */
.plaque::after{
  content:""; position:absolute; inset:-20% -60%;
  background:linear-gradient(100deg, rgba(255,255,255,0) 40%, rgba(255,255,255,.38) 50%, rgba(255,255,255,0) 60%);
  mix-blend-mode:soft-light;
  transform:translateX(-60%);
  pointer-events:none;
}
.abar__about.is-dropped .plaque{
  opacity:1; transform:none; --lift:0;
  transition:
    transform 1.05s cubic-bezier(.3, 1.1, .4, 1),
    --lift 1s cubic-bezier(.45, 0, .2, 1),
    opacity .35s ease-out;
}
.abar__about.is-dropped .plaque::after{
  transform:translateX(60%);
  transition:transform 1.6s cubic-bezier(.45, 0, .25, 1) .75s;
}
/* engraved: a dark cut, its top wall in shadow, its lower lip catching
   the light */
.plaque__text{
  margin:0;
  font-family:"Geist",system-ui,sans-serif;
  font-size:calc(var(--u) * 25);
  font-weight:600;                       /* a cut needs some width to read */
  letter-spacing:-.02em;
  line-height:1.36;
  color:#2a2d31;
  text-shadow:
    0 calc(var(--u) * -1) 0 rgba(0,0,0,.45),          /* the top wall, in shadow */
    0 calc(var(--u) * 1.2) 0 rgba(255,255,255,.85),   /* the lower lip, catching the light */
    0 calc(var(--u) * 1.8) calc(var(--u) * 1) rgba(255,255,255,.25);
}
.plaque__text b{ font-weight:inherit; color:#b4632a; }   /* cut, and filled with the accent */
@media (prefers-reduced-motion: reduce){
  .plaque{ opacity:1; transform:none; --lift:0; }
}

/* ── life: the photo trail ──────────────────────────────────────────────
   js/life.js deals the photos; each is a print on the stone: a hair of
   white edge, a soft shadow. They stay inside the slab (it clips). */
.abar__life{
  position:absolute; top:0; left:50%;
  width:calc(var(--u) * 726.4);
  height:100%;
}
.life__shot{
  position:absolute; left:0; top:0;
  border-radius:calc(var(--u) * 3);
  object-fit:cover;
  pointer-events:none;
  user-select:none;
  will-change:transform, opacity;
  box-shadow:
    0 0 0 calc(var(--u) * .5) rgba(255,255,255,.18),
    0 calc(var(--u) * 2) calc(var(--u) * 4) rgba(0,0,0,.25),
    0 calc(var(--u) * 16) calc(var(--u) * 30) calc(var(--u) * -10) rgba(0,0,0,.5);
}
.life__hint{
  position:absolute; left:0; right:0; top:50%;
  margin:0;
  transform:translateY(-50%);
  text-align:center;
  font-family:"Geist",system-ui,sans-serif;
  font-size:calc(var(--u) * 44);        /* big and clear (Arnav) */
  font-weight:400;
  letter-spacing:-.04em;
  color:rgba(239,239,239,.9);
  text-shadow:0 calc(var(--u) * 3) calc(var(--u) * 10) rgba(0,0,0,.35);
  pointer-events:none;
  transition:opacity .6s var(--ease-out);
}
.life__hint.is-away{ opacity:0; }

/* ── visited: the steel globe ─────────────────────────────────────────
   js/globe.js draws it (WebGL). The layer is the open slab's size, centred
   like the others; the globe stands on the slab's centre line, clear of
   the label's column, with a soft shadow on the stone below it. */
.abar__globe{
  position:absolute; top:0; left:50%;
  width:calc(var(--u) * 726.4);
  height:100%;
}
.globe__cv{
  position:absolute;
  left:calc(var(--u) * (363 - 235)); top:calc(var(--u) * (330 - 235));
  width:calc(var(--u) * 470); height:calc(var(--u) * 470);
  cursor:grab;
  touch-action:pan-y;
}
.abar__globe.is-over .globe__cv{ cursor:none; }
.abar__globe.is-dragging .globe__cv{ cursor:grabbing; }
.globe__shadow{
  position:absolute;
  left:calc(var(--u) * (363 - 190)); top:calc(var(--u) * 545);
  width:calc(var(--u) * 380); height:calc(var(--u) * 70);
  border-radius:50%;
  background:radial-gradient(closest-side, rgba(10,9,8,.42), rgba(10,9,8,.16) 55%, rgba(10,9,8,0));
  filter:blur(calc(var(--u) * 6));
}

/* the cursor over a visited country: a nav pill, glass and all, reading the name.
   The outer box follows the pointer exactly (no easing — a cursor must
   never trail); only the pill inside eases in and out. */
.cursor-pill-at{
  position:fixed; left:0; top:0;
  z-index:60;
  width:0; height:0;
  pointer-events:none;
  transform:translate3d(var(--px, -200px), var(--py, -200px), 0);
}
.cursor-pill{
  position:absolute; left:0; top:0;
  display:flex; align-items:center;
  height:calc(var(--u) * 28);
  padding:0 calc(var(--u) * 7);
  border-radius:calc(var(--u) * 4);
  font-family:"Geist",system-ui,sans-serif;
  font-size:calc(var(--u) * 20);
  font-weight:400;
  letter-spacing:calc(var(--u) * -0.6);
  line-height:normal;
  color:var(--ink);
  white-space:nowrap;
  opacity:0;
  transform:translate(-50%, -50%) scale(.7);
  transition:opacity .16s var(--ease-out), transform .22s cubic-bezier(.22,1.3,.36,1);
}
.cursor-pill-at.is-on .cursor-pill{ opacity:1; transform:translate(-50%, -50%) scale(1); }

/* ── music: the orange record ─────────────────────────────────────────
   Like the globe: the open slab's size, CENTRED in the slab, so it's
   uncovered from the middle out with the texture. Everything sits on the
   slab's centre line (x 363): the record, the words, the buttons. The
   tonearm stands to the record's upper right, above the label's column.
   Geometry (layer units) is shared with js/music.js: record centre
   (363, 262), r 210; tonearm pivot (617, 84), 330 to the stylus. The vinyl is the site's orange (#e8a567), coloured vinyl, with
   real grooves, lighter bands between the three songs, and a sheen that
   does NOT turn with the disc (it's the room's light). */
.abar__music{
  position:absolute; top:0; left:50%;   /* centred by the spotlight rule's translate */
  width:calc(var(--u) * 726.4);
  height:100%;
  z-index:1;
  color:#efefef;
}
.vinyl{
  position:absolute;
  left:calc(var(--u) * 153); top:calc(var(--u) * 52);
  width:calc(var(--u) * 420); height:calc(var(--u) * 420);
  border-radius:50%;
  filter:drop-shadow(0 calc(var(--u) * 12) calc(var(--u) * 18) rgba(0,0,0,.5))
         drop-shadow(0 calc(var(--u) * 2) calc(var(--u) * 3) rgba(0,0,0,.35));
}
.vinyl__disc{
  position:absolute; inset:0;
  border-radius:50%;
  transform:rotate(var(--spin, 0deg));
  background:radial-gradient(circle closest-side,
    #c98446 0 36.5%, #e3a063 38%, #e8a567 55%, #de9657 82%, #c97f40 97%, #b06a2f 100%);
  box-shadow:inset 0 0 0 calc(var(--u) * 1.5) rgba(60,25,5,.35);
}
/* the grooves, and the smooth bands between songs */
.vinyl__disc::before{
  content:""; position:absolute; inset:0; border-radius:50%;
  background:
    radial-gradient(circle closest-side, transparent 0 48%, rgba(255,235,210,.16) 48.4% 49.4%,
                    transparent 49.8% 63%, rgba(255,235,210,.16) 63.3% 64.3%,
                    transparent 64.7% 80.4%, rgba(255,235,210,.16) 80.8% 81.8%, transparent 82.2%),
    /* ~3px pitch: finer beats against the pixel grid (moiré), worst when
       the slab is scaled down to fit a laptop */
    repeating-radial-gradient(circle closest-side, rgba(70,30,5,.12) 0 .7%, rgba(255,230,200,.04) .7% 1.4%);
  -webkit-mask:radial-gradient(circle closest-side, transparent 0 47%, #000 47.5% 96.6%, transparent 97.2%);
          mask:radial-gradient(circle closest-side, transparent 0 47%, #000 47.5% 96.6%, transparent 97.2%);
}
/* a little irregularity in the pressing, so the turning is visible */
.vinyl__disc::after{
  content:""; position:absolute; inset:0; border-radius:50%;
  /* starts and ends on the same value: no seam */
  background:conic-gradient(from 40deg, rgba(0,0,0,.04), rgba(0,0,0,0) 20%, rgba(255,255,255,.035) 40%,
                            rgba(0,0,0,0) 60%, rgba(0,0,0,.035) 80%, rgba(0,0,0,.04));
  -webkit-mask:radial-gradient(circle closest-side, transparent 0 37%, #000 38%);
          mask:radial-gradient(circle closest-side, transparent 0 37%, #000 38%);
}
.vinyl__label{
  position:absolute; inset:32%;
  width:36%; height:36%;
  border-radius:50%;
  object-fit:cover;
  box-shadow:0 0 0 calc(var(--u) * 1) rgba(40,15,0,.35), inset 0 0 0 calc(var(--u) * 1) rgba(0,0,0,.2);
  z-index:1;
}
/* the room's light: two soft wedges across the grooves, fixed */
.vinyl__sheen{
  position:absolute; inset:0; border-radius:50%;
  /* long, soft ramps — a sheen, not a wedge — and low enough that the
     orange stays one orange */
  background:conic-gradient(from 0deg,
    rgba(255,255,255,0) 0deg, rgba(255,250,240,.03) 12deg, rgba(255,250,240,.09) 24deg,
    rgba(255,250,240,.14) 34deg, rgba(255,250,240,.09) 44deg, rgba(255,250,240,.03) 56deg,
    rgba(255,255,255,0) 70deg, rgba(255,255,255,0) 180deg, rgba(255,250,240,.02) 192deg,
    rgba(255,250,240,.07) 204deg, rgba(255,250,240,.1) 214deg, rgba(255,250,240,.07) 224deg,
    rgba(255,250,240,.02) 236deg, rgba(255,255,255,0) 250deg, rgba(255,255,255,0) 360deg);
  -webkit-mask:radial-gradient(circle closest-side, transparent 0 38%, #000 42% 95%, transparent 97.5%);
          mask:radial-gradient(circle closest-side, transparent 0 38%, #000 42% 95%, transparent 97.5%);
  mix-blend-mode:soft-light;
  pointer-events:none;
}
.vinyl__spindle{
  position:absolute; left:50%; top:50%;
  width:calc(var(--u) * 11); height:calc(var(--u) * 11);
  margin:calc(var(--u) * -5.5) 0 0 calc(var(--u) * -5.5);
  border-radius:50%;
  background:radial-gradient(circle at 38% 34%, #eef0f2, #9a9da1 55%, #55585c);
  box-shadow:0 calc(var(--u) * 1) calc(var(--u) * 2) rgba(0,0,0,.5);
  z-index:2;
}

/* the tonearm — the globe's steel. The beam turns about the pivot; the
   transition is only on while it swings in or out (.is-moving), so the
   slow creep across a song follows the music exactly. */
.arm{ position:absolute; left:calc(var(--u) * 617); top:calc(var(--u) * 84); width:0; height:0; z-index:2; }
.arm__base{
  position:absolute;
  left:calc(var(--u) * -30); top:calc(var(--u) * -30);
  width:calc(var(--u) * 60); height:calc(var(--u) * 60);
  border-radius:50%;
  background:
    radial-gradient(circle at 50% 50%, #3a3c3f 0 18%, transparent 19%),
    radial-gradient(circle at 36% 30%, #c9ccd0, #85888c 50%, #505357 100%);
  box-shadow:
    inset 0 calc(var(--u) * 1) 0 rgba(255,255,255,.4),
    0 calc(var(--u) * 6) calc(var(--u) * 10) rgba(0,0,0,.45);
}
.arm__beam{
  position:absolute; left:0; top:0; width:0; height:0;
  transform:rotate(var(--arm, 8deg));
  filter:drop-shadow(calc(var(--u) * -5) calc(var(--u) * 11) calc(var(--u) * 5) rgba(0,0,0,.42));
}
.arm__beam.is-moving{ transition:transform 1s cubic-bezier(.45,.05,.25,1); }
.arm__tube{
  position:absolute;
  left:calc(var(--u) * -3.5); top:calc(var(--u) * -6);
  width:calc(var(--u) * 7); height:calc(var(--u) * 302);
  border-radius:calc(var(--u) * 3.5);
  background:linear-gradient(90deg, #5d6064, #d7dadd 42%, #9ea1a5 62%, #55585c);
}
.arm__weight{
  position:absolute;
  left:calc(var(--u) * -13); top:calc(var(--u) * -66);
  width:calc(var(--u) * 26); height:calc(var(--u) * 34);
  border-radius:calc(var(--u) * 5);
  background:linear-gradient(90deg, #3e4044, #9a9da1 40%, #6b6e72 65%, #35373a);
}
.arm__head{
  position:absolute;
  left:calc(var(--u) * -12); top:calc(var(--u) * 292);
  width:calc(var(--u) * 24); height:calc(var(--u) * 40);
  border-radius:calc(var(--u) * 3) calc(var(--u) * 3) calc(var(--u) * 5) calc(var(--u) * 5);
  background:linear-gradient(90deg, #26282b, #4a4d51 45%, #2a2c2f);
  transform:rotate(-16deg);
  transform-origin:50% 0;
  box-shadow:inset 0 calc(var(--u) * 1) 0 rgba(255,255,255,.15);
}

/* now playing — set like the masthead and the hero, on dark stone */
.player{
  position:absolute;
  left:calc(var(--u) * 113); top:calc(var(--u) * 506);
  width:calc(var(--u) * 500);                 /* centred on x 363 */
  text-align:center;
  font-family:"Geist",system-ui,sans-serif;
}
.player p{ margin:0; }
.player__now{
  font-size:calc(var(--u) * 14);
  font-weight:400;
  letter-spacing:-.01em;
  color:rgba(239,239,239,.5);
}
.player__now span::before{ content:"·"; margin:0 .45em 0 .2em; }   /* + the space before it = .45em each side */
.player__title{
  margin-top:calc(var(--u) * 8) !important;
  font-size:calc(var(--u) * 40);
  font-weight:400;
  letter-spacing:-.045em;
  line-height:1.1;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.player__meta{
  margin-top:calc(var(--u) * 4) !important;
  font-size:calc(var(--u) * 15);
  font-weight:300;
  letter-spacing:-.01em;
  color:rgba(239,239,239,.62);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.player__ctrl{
  display:flex; align-items:center; justify-content:center; gap:calc(var(--u) * 10);
  margin-top:calc(var(--u) * 18);
}
.player__btn{
  display:grid; place-items:center;
  width:calc(var(--u) * 40); height:calc(var(--u) * 40);
  padding:0; border:0; border-radius:50%;
  cursor:pointer;
  color:#efefef;
  background:
    linear-gradient(180deg, rgba(255,255,255,.16), rgba(255,255,255,0) 60%),
    rgba(239,239,239,.1);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.28),
    inset 0 0 0 .5px rgba(255,255,255,.14),
    0 calc(var(--u) * 4) calc(var(--u) * 10) calc(var(--u) * -4) rgba(0,0,0,.55);
  transition:transform .25s var(--ease-out), background-color .25s var(--ease-out);
}
.player__btn:hover{ transform:translateY(-1px); }
.player__btn:active{ transform:translateY(0) scale(.96); }
.player__btn:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }
.player__btn svg{ width:46%; height:46%; fill:currentColor; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.player__btn--play{
  width:calc(var(--u) * 52); height:calc(var(--u) * 52);
  color:var(--ink);
  background:
    linear-gradient(180deg, rgba(255,255,255,.35), rgba(255,255,255,0) 60%),
    var(--accent);
}
.player__btn--play .i-pause{ display:none; }
.abar__music.is-playing .player__btn--play .i-play{ display:none; }
.abar__music.is-playing .player__btn--play .i-pause{ display:block; fill:none; }

/* Reduced motion: no pin, no scroll-jacked choreography — the bars sit
   at rest where Figma draws them and the page scrolls straight past. */
@media (prefers-reduced-motion: reduce){
  :root{ --about-d: 0px; }
  .about{ position:relative; top:0; }
}

/* ═══ work detail (Figma 1:641 "detail — 01 olos (v3)") ═══════════════
   An overlay with its own scroll (js/detail.js gives it its own Lenis),
   under the fixed nav, laid out on the frame's coordinates: 1440 × 4650
   on #efefef, the sheet #fafafa x360 w1040 with r13 top corners running
   off the frame's foot. The rail is sticky so the projects stay at hand.
   Type is the frame's, in Geist everywhere; the "all" / "close" buttons
   are the nav's glass pills. */
.detail{
  position:fixed; inset:0;
  z-index:35;                           /* under the nav (40) */
  background:transparent;
}
.detail[hidden]{ display:none; }
.detail__scroll{
  position:absolute; inset:0;
  overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain;
  background:#efefef;
}
.detail__frame{
  position:relative;
  width:100%;
  display:flow-root;                    /* as tall as its case study (css .dsheet) */
  overflow:clip;
  color:#0e0c0b;
}
.detail .pill--clock{ z-index:1; }
.detail__sheet{
  background:#fafafa;
  border-radius:calc(var(--u) * 13) calc(var(--u) * 13) 0 0;
}

/* the rail */
.rail-col{ bottom:0; pointer-events:none; }   /* full height, so the rail can stay pinned all the way down */
.rail{
  /* pinned while the case study scrolls beside it, never past Partiful
     (Arnav) — js/detail.js lowers --rail-top if the rail is taller than
     the screen, so its last row always shows */
  position:sticky;
  top:var(--rail-top, calc(var(--u) * 72));
  width:100%;
  height:calc(var(--u) * 548);
  pointer-events:auto;
}
.rail__row{ position:static; }
.rail__plate{ background:rgba(14,12,11,.06); border-radius:calc(var(--u) * 5); }
.rail__cat{
  font-family:"Geist",system-ui,sans-serif; font-weight:500;
  font-size:calc(var(--u) * 11); line-height:1.3; letter-spacing:-.02em;   /* the text's own spacing (Arnav) */
}
/* + / − : the nav's glass pill, small */
.rail__exp{
  display:flex; align-items:center; justify-content:center;
  padding:0; border:0; cursor:pointer;
  font-family:"Geist",system-ui,sans-serif; font-weight:400;
  font-size:calc(var(--u) * 15); line-height:1;
  color:#0e0c0b;
}
.rail__exp[data-soon]{ cursor:none; }
.rail__sw{ border-radius:calc(var(--u) * 5); overflow:hidden; }
.rail__sw img{ display:block; width:100%; height:100%; object-fit:cover; }
.rail__name{
  font-family:"Geist",system-ui,sans-serif; font-weight:500;
  font-size:calc(var(--u) * 15); line-height:1.3; letter-spacing:-.02em;
  white-space:nowrap;
}
.rail__desc{
  font-family:"Geist",system-ui,sans-serif; font-weight:300;
  font-size:calc(var(--u) * 12.5); line-height:1.5; letter-spacing:-.01em;
  white-space:nowrap;
}
.rail__rule{ background:var(--rule); }
/* every other project's whole row opens it, not only its + (Arnav);
   the row's type lets the click through to this */
.rail__hit{
  padding:0; border:0; background:transparent;
  border-radius:calc(var(--u) * 5);
  cursor:pointer;
  transition:background .3s var(--ease-out);
}
.rail__hit:hover{ background:rgba(14,12,11,.03); }
.rail__hit[data-soon]{ cursor:none; }
.rail__cat, .rail__sw, .rail__name, .rail__desc, .rail__rule{ pointer-events:none; }

/* buttons: the nav's glass pill, with the frame's 15px label */
.dpill{
  display:flex; align-items:center; justify-content:center;
  padding:0; border:0; cursor:pointer;
  color:#0e0c0b; text-decoration:none;
}
.dpill__t em{ font-style:italic; }
.dpill__t{
  font-family:"Geist",system-ui,sans-serif; font-weight:400;
  font-size:calc(var(--u) * 15); line-height:1.3; letter-spacing:-.02em;
}
/* the nav's rule: the pill hugs its label, 7 either side */
.dpill--hug{ width:auto; padding:0 calc(var(--u) * 7); }
/* Everything pressable in glass reacts (Arnav: "all buttons that are
   pressable in the entire website need to react"): on hover the pane
   catches more light and lifts a pixel, its shadow opening under it;
   pressed, it sinks. The light is a layer under the label, so the type
   never washes out. Tags and the clock aren't buttons, so they don't. */
:is(a.pill, button.pill){
  position:relative;
  transition:transform .35s var(--ease-out), box-shadow .35s var(--ease-out);
}
:is(a.pill, button.pill).n{ position:absolute; }
:is(a.pill, button.pill)::before{
  content:""; position:absolute; inset:0; z-index:-1;
  border-radius:inherit;
  background:linear-gradient(180deg, rgba(255,255,255,.55), rgba(255,255,255,.18));
  opacity:0;
  transition:opacity .35s var(--ease-out);
  pointer-events:none;
}
:is(a.pill, button.pill):hover{
  transform:translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.85),
    inset 0 0 0 .5px rgba(255,255,255,.45),
    inset 0 -1px 0 rgba(14,12,11,.06),
    0 2px 4px rgba(14,12,11,.08),
    0 10px 22px -8px rgba(14,12,11,.24);
}
:is(a.pill, button.pill):hover::before{ opacity:1; }
:is(a.pill, button.pill):active{ transform:translateY(0) scale(.96); transition-duration:.12s; }
@media (prefers-reduced-motion: reduce){
  :is(a.pill, button.pill):hover, :is(a.pill, button.pill):active{ transform:none; }
}
.dpill:focus-visible, .rail__exp:focus-visible{ outline:2px solid rgba(14,12,11,.35); outline-offset:2px; }   /* keyboard only; never on a click */

/* the sheet's type */
.d-name{
  font-family:"Geist",system-ui,sans-serif; font-weight:500;
  font-size:calc(var(--u) * 40); line-height:1.3; letter-spacing:-.02em;
  white-space:nowrap;
}
.d-thesis{
  font-family:"Geist",system-ui,sans-serif; font-weight:400;
  font-size:calc(var(--u) * 44); line-height:1.22; letter-spacing:-.04em;
}
.d-meta-l{
  font-family:"Geist",system-ui,sans-serif; font-weight:500;
  font-size:calc(var(--u) * 15); line-height:1.3; letter-spacing:-.02em;
}
.d-meta-v{
  font-family:"Geist",system-ui,sans-serif; font-weight:300;
  font-size:calc(var(--u) * 15); line-height:1.5; letter-spacing:-.02em;
}
.d-media{ border-radius:calc(var(--u) * 13); overflow:hidden; }
.d-media img{ display:block; width:100%; height:100%; object-fit:cover; }
.d-rule{ background:var(--rule); }
.d-label{
  font-family:"Geist",system-ui,sans-serif; font-weight:500;
  font-size:calc(var(--u) * 11); line-height:normal; letter-spacing:-.02em;   /* the text's own spacing (Arnav) */
}
.d-label--lh{ line-height:1.5; }
.d-head{
  font-family:"Geist",system-ui,sans-serif; font-weight:500;
  font-size:calc(var(--u) * 40); line-height:1.3; letter-spacing:-.02em;
}
.d-head em{ font-style:italic; }
.d-body{
  font-family:"Geist",system-ui,sans-serif; font-weight:300;
  font-size:calc(var(--u) * 18); line-height:1.72; letter-spacing:-.02em;
}
.d-body p{ margin:0 0 1.72em; }         /* the frame's blank line between paragraphs */
.d-body p:last-child{ margin-bottom:0; }
.d-reflect{
  font-family:"Geist",system-ui,sans-serif; font-weight:300;
  font-size:calc(var(--u) * 22); line-height:1.6; letter-spacing:-.03em;
}

/* the homepage row that opens it */
.wrow[data-open]{ cursor:pointer; }
.wrow[data-open]:focus-visible{ outline:2px solid rgba(14,12,11,.35); outline-offset:-2px; }

/* ─── the case study page (tools/case_studies.py) ─────────────────────
   One layout for all five, in flow, since each one's text runs to its
   own length. The gaps are olos's as first built off Figma 1:641:
   header rule → thesis 64, → meta 57, → chips 41.5, → hero 48; media →
   rule 72; rule → label 55; label / head → text 28; text → text 24;
   text → media 48; the last line 79 above the foot, where the sheet
   runs off. */
.dsheet{
  position:relative;
  margin:calc(var(--u) * 110) 0 0 calc(var(--u) * 360);
  width:calc(var(--u) * 1040);
  min-height:calc(100vh - var(--u) * 110);
  padding:0 calc(var(--u) * 40) calc(var(--u) * 79);
}
.dsheet > .detail__sheet{ position:absolute; inset:0; }
.dsheet > :not(.detail__sheet){ position:relative; }
.dsheet :is(h2, h3, dl, dt, dd, .d-thesis, .d-label){ margin:0; }
/* the header bar (Arnav): the title and close on a band as tall as a
   rail row, its rule (.dsheet__rule) across the sheet level with the
   rail's first rule,
   so the page lines up with the list beside it */
.dsheet__top{
  display:flex; align-items:center; justify-content:space-between;
  height:calc(var(--u) * 84);
}
.dsheet__top .dpill{ width:calc(var(--u) * 60); height:calc(var(--u) * 28); }
.dsheet .d-thesis{ margin-top:calc(var(--u) * 64); }
/* the details take the whole width, like olos's: first column on the
   left margin, last on the right, the rest spaced evenly between */
.dsheet .d-meta{ display:flex; justify-content:space-between; margin-top:calc(var(--u) * 56.7); }
.d-meta__col{ width:calc(var(--u) * 220); flex:none; }
.d-meta__col .d-meta-v{ margin-top:calc(var(--u) * 4.5); }
.d-chips{ display:flex; gap:calc(var(--u) * 10); margin-top:calc(var(--u) * 41.5); }
.d-chips .dpill{ height:calc(var(--u) * 28); }
.dpill--tag{ cursor:default; }         /* facts, not actions: glass like the buttons, but nothing to press */
.dpill--go .dpill__t{ color:var(--accent); }
.dsheet > .d-media{ display:block; width:calc(var(--u) * 960); height:calc(var(--u) * 540); margin-top:calc(var(--u) * 48); }
.dsheet > .d-media--hero{ height:calc(var(--u) * 440); }
.dsheet > .d-rule{ display:block; height:calc(var(--u) * 1); margin:calc(var(--u) * 72) 0 0 calc(var(--u) * -40); width:calc(var(--u) * 1040); }
/* the header's rule is its own element (not the header's border) so it
   fades in with the page instead of standing there from the first frame */
.dsheet > .dsheet__rule{ margin-top:0; }
.dsec{ margin-left:calc(var(--u) * 160); width:calc(var(--u) * 640); }
.dsec .d-label{ margin-top:calc(var(--u) * 55); }
.dsec .d-label + *, .dsec .d-head + .d-body{ margin-top:calc(var(--u) * 28); }
.dsec .d-body + .d-body{ margin-top:calc(var(--u) * 24.4); }
.d-reflect p{ margin:0 0 1.6em; }        /* the frame's blank line */
.d-reflect p:last-child{ margin-bottom:0; }

/* the transition (js/detail.js): ghosts fly on a layer between the
   detail and the nav; the real pieces wait, hidden, until they land */
.dfx{ position:fixed; inset:0; z-index:38; pointer-events:none; }
.dfx > *{ position:fixed; margin:0; transform-origin:0 0; will-change:transform, opacity; }
.is-parked{ visibility:hidden !important; }

/* ═══ contact — the cards ═══════════════════════════════════════════
   One base, four materials. Every size inside a card is in cqw — the
   card is its own container — so each is authored at a 280 × 160
   business-card size and scales as one piece (1cqw = 2.8px at 280).
   The card's OWN radius can't use cqw (container units resolve against
   an ancestor container), so it is computed from --card-w. */
/* ── the footer — Figma Desktop-18 (Arnav, updated 2026-09-23) ──────────
   Straight from the frame (y in frame px):
     lead   85:86  Geist 400 80 / 1.5, −6.4 (−.08em), #0e0c0b, centred,
            box 9471–9591
     big    99:36  Geist 400 120 / 1.5, −9.6 (−.08em), centred (ink, not
            Figma's #242221 — Arnav: the sky's colour), box 9531–9711
     board  99:29  a full-width band, 9695–10014 (319), #0e0c0b; it bleeds
            past both frame edges, so no visible radius
     panel  100:18 on it, same box, r13, clipped. Its ground is now ink
            (#0e0c0b) under Figma's grain texture (105:24, 40%) —
            Arnav's call over Figma's dither image, 2026-09-23
     cards  three 315 cards (Instagram removed), centred on the band
     colo   99:47  Geist 400 30 / 1.5, −2.4 (−.08em), ink, centred,
            box 10014–10059, straight under the board; the frame ends at
            10057, 2 inside that box
   Figma doesn't track after a line's last glyph; CSS does. So each line
   is centred as if its box were .08em wider on the right (margin-right),
   which puts the ink where Figma puts it (checked against its render). */
.contact{
  --card-w: calc(var(--u) * 315);
  /* a screen of its own (Arnav): at the end of the page only the footer
     shows. The block sits on the bottom edge, as Figma ends it (the
     colophon's box runs to the frame's end); any spare height goes above
     the headline, never below the colophon */
  min-height:100vh;
  display:flex; flex-direction:column; align-items:center; justify-content:flex-end;
  /* no top padding: the page frame already leaves 97 under the about
     bars (room for their shadows), and the lead's ink starts 31 into
     its box — 128 in all, the page's section gap */
  padding:calc(var(--u) * 41) calc(var(--u) * 41) 0;
  overflow:hidden;                    /* the colophon's box runs 2 past the end */
}
.contact__head{
  position:relative; z-index:1;
  width:calc(var(--u) * 1358);
  margin:0;
  display:flex; flex-direction:column; align-items:center;
  font-family:"Geist",system-ui,sans-serif;
  font-weight:400;
  line-height:1.5;
  text-align:center;
}
/* letter-spacing sits on each line, not the h2: an em value is computed
   at the element that declares it, then inherited as px */
.contact__lead{
  font-size:calc(var(--u) * 80);
  letter-spacing:-.08em;
  /* no .08em here: Figma's text for this line ends in a space, and that
     space's width in its box cancels the missing trailing tracking */
  color:#0e0c0b;                        /* ink now, like the big line (Figma 85:86) */
  white-space:nowrap;
}
.contact__big{
  font-size:calc(var(--u) * 120);
  letter-spacing:-.08em;
  margin:calc(var(--u) * -60) .08em 0 0;
  color:#0e0c0b;                        /* the sky's ink, so the line and the board are one (Arnav) */
  white-space:nowrap;
}
.contact__board{
  position:relative; z-index:2;
  /* a full-width band (99:29 bleeds past both frame edges) */
  width:calc(var(--u) * 1440);
  height:calc(var(--u) * 319);
  margin-top:calc(var(--u) * -16);     /* meets the foot of the big line */
  border-radius:0;
  background:#0e0c0b;
}
.contact__panel{
  position:absolute; left:0; top:0;
  width:100%;
  height:100%;
  border-radius:0;
  overflow:hidden;
  isolation:isolate;
  background:#0e0c0b;                 /* ink, like the slab (Arnav) */
  display:flex; align-items:center; justify-content:center;   /* cards centred (Arnav) */
}

/* the band's texture (Figma 105:24): the grain image turned a quarter
   clockwise and mirrored (baked into band.webp), covering the band,
   centred, at 40% over the ink — matched to Figma's render (r = .996) */
.contact__tex{
  position:absolute; inset:0;
  overflow:hidden;
  opacity:.4;
  pointer-events:none;
}
.contact__tex img{
  position:absolute; inset:0;
  width:100%; height:100%;
  max-width:none;
  object-fit:cover;
  object-position:50% 50%;
}
.contact__cards{
  position:relative;
  display:flex;
  gap:calc(var(--u) * 14);
  perspective:900px;                     /* the tilt reads as depth, not skew */
}
.contact__colophon{
  margin:0 .08em calc(var(--u) * -2) 0;
  font-family:"Geist",system-ui,sans-serif;
  font-weight:400;
  font-size:calc(var(--u) * 30);
  letter-spacing:-.08em;
  line-height:1.5;
  color:var(--ink);
  white-space:nowrap;
}

/* one stock for all four cards (Arnav, 2026-09-23): the site's own cream,
   --pale #f2efe9 — the wordmark and masthead's warm off-white — lit a touch
   from the top-left. Each card keeps its own material on top of it: the
   email's grain, the X card's satin and glint, LinkedIn's cotton fibre,
   the print's photo. */
:root{ --card-stock:linear-gradient(160deg, #f6f4ef 0%, var(--pale) 46%, #ebe7df 100%); }
.pcard{
  --mx:.5; --my:.5;                      /* pointer, 0–1 across the card */
  --rx:0deg; --ry:0deg; --lift:0px; --rz:0deg;
  --radius:calc(var(--card-w) * 6 / 280);
  position:relative;
  display:block;
  flex:none;
  width:var(--card-w);
  aspect-ratio:280 / 160;
  container-type:inline-size;
  border-radius:var(--radius);
  text-decoration:none;
  color:inherit;
  cursor:pointer;
  transform:translateY(var(--lift)) rotateX(var(--rx)) rotateY(var(--ry)) rotate(var(--rz));
  transform-style:preserve-3d;
  transition:transform .6s cubic-bezier(.22,1,.36,1), box-shadow .5s var(--ease-out),
             translate .45s cubic-bezier(.22,1,.36,1), scale .3s var(--ease-out);
  box-shadow:
    inset 0 0 0 .5px rgba(14,12,11,.10),
    inset 0 1px 0 rgba(255,255,255,.75),
    inset 0 -1px 0 rgba(14,12,11,.06),
    0 1px 2px rgba(14,12,11,.06),
    0 10px 22px -12px rgba(14,12,11,.28);
}
.pcard.is-live{ transition:transform .14s linear, box-shadow .5s var(--ease-out),
                           translate .45s cubic-bezier(.22,1,.36,1), scale .3s var(--ease-out); }

/* ── rearranging (js/swap.js) ─────────────────────────────────────────
   Position lives in `translate` / `scale`, apart from the tilt in
   `transform`, so the two never fight. A neighbour making room glides
   on translate; the card in hand follows the pointer instantly (no
   translate transition), and on release drops into its slot with a
   little overshoot. */
.contact__cards{ user-select:none; -webkit-user-select:none; }
.pcard{ -webkit-touch-callout:none; }
.pcard.is-dragging{
  z-index:3;
  scale:1.045;
  cursor:grabbing;
  transition:transform .12s linear, box-shadow .3s var(--ease-out), scale .35s cubic-bezier(.2,1.5,.4,1);
  box-shadow:
    inset 0 0 0 .5px rgba(14,12,11,.10),
    inset 0 1px 0 rgba(255,255,255,.75),
    0 6px 12px -4px rgba(0,0,0,.25),
    0 34px 50px -18px rgba(0,0,0,.6);
}
.pcard.is-dropping{
  z-index:2;
  transition:translate .55s cubic-bezier(.3,1.25,.5,1), scale .4s var(--ease-out),
             transform .5s var(--ease-out), box-shadow .5s var(--ease-out);
}
html.is-card-dragging, html.is-card-dragging *{ cursor:grabbing !important; }

.sr-only{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip-path:inset(50%); white-space:nowrap; border:0;
}
.pcard:hover,
.pcard:focus-visible{
  --lift:-3px;
  box-shadow:
    inset 0 0 0 .5px rgba(14,12,11,.10),
    inset 0 1px 0 rgba(255,255,255,.75),
    inset 0 -1px 0 rgba(14,12,11,.06),
    0 2px 4px rgba(14,12,11,.06),
    0 22px 36px -16px rgba(14,12,11,.42);
}
.pcard:focus-visible{ outline:2px solid var(--accent); outline-offset:4px; }

.pcard__face,.pcard__grain{
  position:absolute; inset:0;
  border-radius:inherit;
  overflow:hidden;
  pointer-events:none;
}
/* paper grain, multiplied in so ink and foil sit IN the stock */
.pcard__grain{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .55  0 0 0 0 .5  0 0 0 0 .44  0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:240px 240px;
  mix-blend-mode:multiply;
  opacity:.28;
}

/* ── EMAIL: letterpress on warm cream, printed in black ─────────────── */
.pcard--mail{ background:var(--card-stock); }
.pcard--mail .pcard__face{ color:#0e0c0b; }

/* the hero, typeset: 66 × 23 of Geist Mono, sized so the 66 columns
   fill the width exactly (advance .6em → 100 / 66 / .6 = 2.525cqw) */
.pcard__ascii{
  position:absolute; inset:0;
  display:flex; flex-direction:column; justify-content:flex-end;
  font-family:"Geist Mono",ui-monospace,monospace;
  font-weight:600;
  font-size:2.525cqw;
  line-height:2.4845cqw;                 /* 23 rows → 160 at 280 */
  white-space:pre;
  user-select:none;
}
.pcard__ascii span{ display:block; }
/* With the headline gone the address is the card: centred in the clear
   sky above the palms (which start ~43% down). */
.pcard__line{
  position:absolute; left:0; right:0; top:9.6cqw;
  display:flex; align-items:center; justify-content:center; gap:1.9cqw;
  font-family:"Geist",system-ui,sans-serif;
  font-weight:500;
  font-size:4.6cqw;                      /* 13px at 280 */
  letter-spacing:-.02em;
  color:#0e0c0b;
}
.pcard__icon{ width:4.5cqw; height:4.5cqw; flex:none; color:#0e0c0b; }

/* the print and the foil SWAP on hover — left underneath, the black
   would show through the foil's translucent gradient and dirty it */
.pcard__foil{ opacity:0; transition:opacity .45s var(--ease-out); }
.pcard__face:not(.pcard__foil) .pcard__ascii{ transition:opacity .45s var(--ease-out); }
.pcard:hover .pcard__foil,
.pcard:focus-visible .pcard__foil{ opacity:1; }
.pcard:hover .pcard__face:not(.pcard__foil) .pcard__ascii,
.pcard:focus-visible .pcard__face:not(.pcard__foil) .pcard__ascii{ opacity:0; }
/* the sunset foil: gold → #e8a567 → coral → dusk magenta → indigo under
   a sheen, both riding the pointer so the foil catches the light */
.pcard__foil .pcard__ascii{
  color:transparent;
  background-image:
    linear-gradient(115deg, rgba(255,255,255,0) 38%, rgba(255,250,240,.7) 48%, rgba(255,255,255,0) 58%),
    repeating-linear-gradient(110deg,
      #f4c56b 0%, #e8a567 8%, #de7a4f 16%, #c2566c 24%, #8a4f93 32%, #4d5aa8 40%, #f4c56b 48%);
  background-size:260% 260%, 220% 220%;
  background-position:
    calc(var(--mx) * 100%) calc(var(--my) * 100%),
    calc(var(--mx) * 60%)  calc(var(--my) * 60%);
  -webkit-background-clip:text;
          background-clip:text;
}

/* ── X: satin titanium ───────────────────────────────────────────────
   Modelled on a real titanium card (bead-blasted, satin), not polished
   steel. Arnav rejected a glare-disc + streak as fake, and the physics
   agree: satin titanium has no hotspot, and on brushed metal a streak
   runs ACROSS the grain, not along it. What such a card really does:
     · at rest, one even warm-grey tone with a fine ISOTROPIC matte
       grain (bead-blast), not directional brushing;
     · tilted, a single broad soft band of light glides across the
       whole face with the pointer, the opposite side dimming — a wide
       gradient, no edge, no point. */
.pcard--x{
  background:var(--card-stock);
  box-shadow:
    inset 0 0 0 .5px rgba(24,24,22,.24),
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(24,24,22,.22),
    0 1px 2px rgba(14,12,11,.10),
    0 12px 24px -12px rgba(14,12,11,.40);
}
.pcard--x:hover,.pcard--x:focus-visible{
  box-shadow:
    inset 0 0 0 .5px rgba(24,24,22,.24),
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(24,24,22,.22),
    0 2px 4px rgba(14,12,11,.10),
    0 26px 40px -16px rgba(14,12,11,.50);
}
.pcard__metal{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='s'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.6' numOctaves='2' seed='9' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5  0 0 0 0 .5  0 0 0 0 .5  0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23s)'/%3E%3C/svg%3E");
  background-size:200px 200px;
  mix-blend-mode:soft-light;
  opacity:.42;
}
/* the band: 3× the card wide so it can travel; its centre follows the
   pointer across and, a little, down (the tilt changes both) */
.pcard__shine{
  position:absolute; inset:0;
  border-radius:inherit;
  pointer-events:none;
  opacity:0;
  transition:opacity .6s var(--ease-out);
  /* overlay, not soft-light: soft-light on a mid-grey barely moves, and
     the band read as nothing. Overlay gives the lit side a real sheen
     and lets the far side drop, still with no edge anywhere. */
  background-image:linear-gradient(104deg,
    rgba(20,20,18,.30) 0%,
    rgba(20,20,18,.10) 26%,
    rgba(255,255,255,.18) 38%,
    rgba(255,255,255,.62) 50%,
    rgba(255,255,255,.18) 62%,
    rgba(20,20,18,.10) 74%,
    rgba(20,20,18,.30) 100%);
  background-size:300% 130%;
  background-position:calc(100% - var(--mx) * 100%) calc(var(--my) * 100%);
  mix-blend-mode:overlay;
}
.pcard--x:hover .pcard__shine,
.pcard--x:focus-visible .pcard__shine{ opacity:1; }

/* engraved: a cut darker than the metal, lit on its lower lip */
.pcard--x .pcard__name,
.pcard--x .pcard__handle,
.pcard--x .pcard__tag{
  position:absolute; left:6.8cqw;
  font-family:"Geist",system-ui,sans-serif;
  color:rgba(38,42,47,.74);
  text-shadow:0 .09cqw 0 rgba(255,255,255,.8), 0 -.07cqw 0 rgba(0,0,0,.18);
  white-space:nowrap;
}
.pcard--x .pcard__name  { top:23.5cqw; font-weight:600; font-size:6.1cqw; letter-spacing:-.035em; }
.pcard--x .pcard__handle{ top:31.4cqw; font-weight:400; font-size:4.1cqw; letter-spacing:-.01em; color:rgba(38,42,47,.52); }
.pcard--x .pcard__tag   { top:47.6cqw; font-weight:500; font-size:2.9cqw; letter-spacing:.02em; color:rgba(38,42,47,.46); }
.pcard__mark{
  position:absolute; left:6.8cqw; top:6.2cqw;
  width:10.7cqw; height:10.7cqw;
  opacity:.72;
  filter:grayscale(1) drop-shadow(0 .09cqw 0 rgba(255,255,255,.85));
}
/* the X at 75% of its first size, set into the bottom-right corner */
.pcard__xmark{
  position:absolute; right:5cqw; bottom:4.4cqw;
  width:48cqw; height:48cqw;
  fill:rgba(96,103,110,.30);
  filter:drop-shadow(0 .14cqw 0 rgba(255,255,255,.8)) drop-shadow(0 -.1cqw 0 rgba(0,0,0,.22));
}

/* ── LINKEDIN: letterpress on heavy cotton ───────────────────────────
   After the Pierce & Pierce card: bone cotton stock, type pressed into
   it, small caps and old-style figures in a Garamond. The two things
   that make letterpress read as letterpress are both here:
     · the STOCK — fibre at a fine scale and a soft mottle at a large
       one, multiplied into a warm bone base, so the card has tooth;
     · the IMPRESSION — each letter is a shallow cut: a lit lower lip
       (the light catching the far wall) and a thin shadow along the top.
   Hover rakes the light from the pointer's side: the lips brighten and
   shift the way they do when you tilt a real card toward a lamp. */
.pcard--in{
  --lx:calc(var(--mx) - .5);
  --ly:calc(var(--my) - .5);
  background:var(--card-stock);
  box-shadow:
    inset 0 0 0 .5px rgba(60,50,35,.14),
    inset 0 1px 0 rgba(255,255,255,.8),
    inset 0 -1.5px 0 rgba(60,50,35,.10),   /* the thickness of heavy stock */
    0 1px 2px rgba(14,12,11,.08),
    0 10px 22px -12px rgba(14,12,11,.32);
}
.pcard__cotton{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.72' numOctaves='4' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .52  0 0 0 0 .48  0 0 0 0 .42  0 0 0 1.2 -.35'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.016' numOctaves='3' seed='12' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .55  0 0 0 0 .5  0 0 0 0 .43  0 0 0 .9 -.25'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");
  background-size:220px 220px, 420px 420px;
  mix-blend-mode:multiply;
  opacity:.5;
}
.pcard__press{ color:#262422; }
.lp{
  position:absolute;
  font-family:"EB Garamond",Garamond,Georgia,serif;
  font-weight:500;
  font-variant-numeric:oldstyle-nums;
  line-height:1.05;
  white-space:nowrap;
  /* the impression: lit lower lip, shadowed top edge */
  text-shadow:
    calc(var(--lx) * -.14cqw) calc(.13cqw - var(--ly) * .08cqw) 0 rgba(255,255,255,.72),
    0 -.06cqw 0 rgba(40,32,20,.16);
  transition:text-shadow .5s var(--ease-out);
}
.lp--tl  { left:6.6cqw; top:7.2cqw; font-size:3.4cqw; font-variant-caps:small-caps; letter-spacing:.03em; }
.lp--firm{ right:6.6cqw; top:6.4cqw; text-align:right; display:flex; flex-direction:column; align-items:flex-end; gap:.35cqw; }
.lp__blue{ font-size:4.5cqw; font-variant-caps:small-caps; letter-spacing:.02em; color:#1a5fa6; }
.lp--name{ left:0; right:0; top:23.2cqw; text-align:center; font-size:4.9cqw; letter-spacing:.015em; }
.lp__sc  { font-variant-caps:small-caps; }
.lp--title{ left:0; right:0; top:29.6cqw; text-align:center; font-size:3.7cqw; font-variant-caps:small-caps; letter-spacing:.025em; }
.lp--addr{ left:6.6cqw; bottom:6.6cqw; font-size:3.25cqw; font-variant-caps:small-caps; letter-spacing:.035em; }
/* raking light: a low, broad light from the pointer's side, and the
   impressions deepening under it */
.pcard__rake{
  background:linear-gradient(calc(90deg + var(--lx) * 60deg),
    rgba(255,255,255,.0) 0%, rgba(255,255,255,.22) calc(var(--mx) * 100%), rgba(60,50,35,.10) 100%);
  mix-blend-mode:soft-light;
  opacity:0;
  transition:opacity .5s var(--ease-out);
}
.pcard--in:hover .pcard__rake,
.pcard--in:focus-visible .pcard__rake{ opacity:1; }
.pcard--in:hover .lp,
.pcard--in:focus-visible .lp{
  /* deepened only slightly: at 2–3cqw type, a lip anywhere near the
     stroke width smears the letters (the first pass made "Professional
     Network" unreadable). Brighter, barely larger, shifted with the light. */
  text-shadow:
    calc(var(--lx) * -.1cqw) calc(.15cqw - var(--ly) * .05cqw) 0 rgba(255,255,255,.88),
    0 -.07cqw 0 rgba(40,32,20,.2);
}


/* ── INSTAGRAM: a retro instant print ─────────────────────────────────
   Instax Wide is landscape, so it shares the card footprint. Straight
   (Arnav). The retro is in the print itself: a slightly yellowed frame,
   a faded warm film grade, a light leak bleeding in from the left edge,
   grain, and the orange date stamp a film camera burns into the corner.
   Hover develops it to full colour — still warm — and the gloss moves. */
.pcard--ig{ background:var(--card-stock); }
.pcard__photo{
  position:absolute; left:3.8cqw; right:3.8cqw; top:3.8cqw; height:40.4cqw;
  overflow:hidden;
  border-radius:.4cqw;
  box-shadow:inset 0 0 0 .5px rgba(0,0,0,.25);
  background:#1c1a18;
}
.pcard__photo img{
  width:100%; height:100%; display:block; object-fit:cover; object-position:50% 58%;
  filter:saturate(.62) contrast(.88) brightness(1.08) sepia(.26) hue-rotate(-6deg);
  transition:filter 1.4s cubic-bezier(.22,1,.36,1);
}
.pcard--ig:hover .pcard__photo img,
.pcard--ig:focus-visible .pcard__photo img{ filter:saturate(1) contrast(1.03) brightness(1.02) sepia(.12) hue-rotate(-4deg); }
.pcard__leak{
  position:absolute; inset:0;
  background:
    radial-gradient(55% 95% at -4% 18%, rgba(255,112,40,.55), rgba(255,112,40,0) 62%),
    radial-gradient(30% 70% at -2% 85%, rgba(255,60,70,.28), rgba(255,60,70,0) 70%);
  mix-blend-mode:screen;
}
/* the date stamp: orange, slightly bloomed, bottom-right of the frame */
.pcard__date{
  position:absolute; right:2.6cqw; bottom:1.9cqw;
  font-family:"Geist Mono",ui-monospace,monospace;
  font-weight:700;
  font-size:3.1cqw;
  letter-spacing:.08em;
  color:#ffab4a;
  text-shadow:0 0 .5cqw rgba(255,122,30,.85), 0 0 1.4cqw rgba(255,90,20,.45);
  opacity:.92;
  mix-blend-mode:screen;
}
.pcard__gloss{
  position:absolute; left:3.8cqw; right:3.8cqw; top:3.8cqw; height:40.4cqw;
  border-radius:.4cqw;
  background:
    linear-gradient(115deg, rgba(255,255,255,0) 30%, rgba(255,255,255,.22) 45%, rgba(255,255,255,0) 58%),
    radial-gradient(120% 90% at 50% 120%, rgba(0,0,0,.28), rgba(0,0,0,0) 60%);
  background-size:260% 100%, 100% 100%;
  background-position:calc(var(--mx) * 100%) 0, 0 0;
  mix-blend-mode:screen;
  opacity:.9;
}
/* the handle, in Geist (not the handwriting face) */
.pcard__caption{
  position:absolute; left:5.4cqw; top:47.6cqw;
  font-family:"Geist",system-ui,sans-serif;
  font-weight:500;
  font-size:4.6cqw;
  letter-spacing:-.02em;
  line-height:1;
  color:#2b2926;
}
.pcard__ig{
  position:absolute; right:5.4cqw; top:47.2cqw;
  width:5cqw; height:5cqw;
  color:#9a958d;
}

@media (prefers-reduced-motion: reduce){
  .pcard{ transform:none !important; transition:box-shadow .3s; }
  .pcard__photo img{ transition:none; }
}
