/* ============================================================
   MIRRORLESS — project showcases: Cop&Drop, Sherbet, Nati Republic
   Layered on assets/proj.css (the dark project stage). Read that header
   first: 1em is 16 design px inside a stage, and every --x/--y/--w/--h
   below is a Figma coordinate from "New Mirrorless Website" with the unit
   swapped to em.

   FIRST VERSION, 2026-09-18
   All imagery is pulled out of Figma (exports and raw fills), so it is
   Figma-resolution, not master resolution. Aurobind is supplying the
   high-res masters once the layout is approved; the files are swapped in
   place, the markup does not change.

   WHAT THIS FILE ADDS TO THE STAGE
   - per-card radius (--r) and rotation (--rot), both off Figma
   - several stages per page (.proj--seg), so the Nati menus can pin
   - .rail      Cop&Drop: rows that drift with the scroll and can be dragged,
                swiped, trackpad-scrolled or arrowed left and right
   - .can       Sherbet: cans you can grab, throw and shake (fizz on release)
   - .duo       Sherbet: a panel with a can standing inside it
   - .barrage   Nati: the menus, and the social posts, land on a stack one
                by one, then split out into the full scattered spread
   - .run       Nati: the sketch sheets come in one after another, in a row
   ============================================================ */

/* the stages stack as a column so margins add, never collapse — the Nati
   menu block hands its overflow to the next stage with a negative margin */
.proj-canvas--show {
  display: flex;
  flex-direction: column;
}
.proj-canvas--show > * { flex: none; }

/* Sideways clip on every stage: the rails, the badge and the tilted sheets all
   run past the edges. body's clip is not enough on phones — the overflow still
   widens the layout viewport and the whole page renders zoomed out. `clip`
   (not `hidden`) so no scroll container is made and sticky still works. */
.proj--seg { overflow-x: clip; overflow-y: visible; }
.proj--clip { overflow: clip; }

/* ---------- card extensions ---------- */
.proj--show .card--proj {
  border-radius: var(--r, 0.6em);
  transform: rotate(var(--rot, 0deg)) translateZ(0);
  z-index: var(--z, auto);
}
.card--flat { background: none; }
.card--square { border-radius: 0 !important; }
/* Nati's black swatch is #111110 — a hairline keeps its edge on the #0F0E0E ground */
.card--ring { box-shadow: 0 0 0 1px var(--hairline); }

/* a cutout sitting straight on the ground: no frame, no clip */
.card--bare {
  background: none !important;
  border-radius: 0 !important;
  overflow: visible !important;
}
.card--bare > img { object-fit: contain; }

/* a frame whose top layer is allowed to hang over its edges */
.card--open { overflow: visible !important; background: none !important; }
.card--open > .card__bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.card--open > .layer { pointer-events: none; }

/* the lemon-chilli totem hangs off its string */
.layer--sway { transform-origin: 50% 0; will-change: transform; }

/* a video playing inside a phone mockup */
.card--phone { overflow: visible !important; background: none !important; border-radius: 0 !important; }
.card--phone > .phone__body { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: contain; }
.card--phone > .phone__screen {
  position: absolute;
  z-index: 2;
  left: var(--sx); top: var(--sy);
  width: var(--sw); height: var(--sh);
  object-fit: cover;
}

/* live text set into the stage (Nati's story panel) */
.proj__copy {
  position: absolute;
  left: var(--x); top: var(--y); width: var(--w);
  margin: 0;
  font-family: 'Akshar', var(--sans);
  font-weight: 400;
  font-size: 1.0143em;                     /* 16.228 */
  line-height: 1.2;
  letter-spacing: 0;
  text-align: center;
  color: #FFFCEE;                          /* Nati's own white, for their #311B0F ink */
}
.proj__copy p { margin: 0 0 1.2em; }

/* ============================================================
   COP&DROP — rails
   The Figma rows run off both edges of the frame. Here each row drifts
   sideways as it passes up the screen (alternate rows opposite ways) and
   can be pushed the rest of the way by hand: drag, swipe, trackpad,
   shift+wheel, or arrow keys once focused. The drift and the hand add up,
   clamped so the first and last slide can always reach the page gutter.
   ============================================================ */
.rail {
  position: absolute;
  left: 0; top: var(--y);
  width: 100%; height: var(--h);
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  outline: none;
}
.rail:focus-visible { box-shadow: inset 0 0 0 2px var(--yellow); }
.rail__track {
  position: absolute;
  inset: 0;
  will-change: transform;
}
.rail__item {
  position: absolute;
  left: var(--x); top: var(--t, 0);
  width: var(--w); height: var(--ih, 100%);
  margin: 0;
  overflow: hidden;
  background: var(--ink-3);
  border-radius: var(--r, 0);
  z-index: var(--z, auto);
}
.rail__item > img,
.rail__item > video {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
  pointer-events: none;
}
.rail__item.card--phone { background: none; overflow: visible; }
.rail.is-dragging { cursor: grabbing; }

/* ============================================================
   SHERBET — cans
   The three cans are cut out of their shots and sit loose on the page.
   Idle, they bob. Hover and they lean to the pointer. Grab one (mouse or
   pen) and it follows you, tilting with your swing; shake it and let go
   and it springs home and fizzes, harder the more you shook it. On touch,
   or from the keyboard (Enter/Space), a tap shakes it in place.
   ============================================================ */
.can {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  touch-action: pan-y;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  z-index: var(--z, 1);
  will-change: transform;
}
.can > img {
  display: block;
  width: 100%; height: 100%;
  object-fit: contain;
  -webkit-user-drag: none;
  pointer-events: none;
  filter: drop-shadow(0 1.4em 1.6em rgba(0, 0, 0, 0.42));
  transition: filter 0.4s var(--ease);
}
.can.is-held { z-index: 30; }
.can.is-held > img { filter: drop-shadow(0 3em 3em rgba(0, 0, 0, 0.5)); }
.can:focus-visible { outline: 2px solid var(--yellow); outline-offset: 0.5em; border-radius: 1em; }

.fizz {
  position: fixed;
  inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  z-index: 60;
}

/* 2026-09-19 (Aurobind): the mango can used to hang over the top and bottom
   of the brand-typeface panel and cover its left edge. It now stands inside
   the panel, in the empty grey half, so the type specimens on the right read
   clean. .duo is the panel's box; the can inside is placed in % of it
   (--cx, --cy, --ch), so it keeps its spot in the panel at every width. It
   can still be grabbed and thrown out of it. */
.duo {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
}
.duo__bg {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  background: var(--ink-3);
}
.can--in {
  left: var(--cx); top: var(--cy);
  width: auto; height: var(--ch);
  aspect-ratio: var(--ar);
}

/* 2026-09-24 Sherbet rebuild (Figma 130:916): the typeface panel. Yellow
   for Figma's 737 of the 878 box, the pattern strip under it, the specimen
   column as an image, and the big can hanging off the top-left. */
.duo--sherbet {
  background: linear-gradient(#FED04A, #FED04A) top / 100% 83.94% no-repeat;
}
.duo__type,
.duo__strip {
  position: absolute;
  display: block;
  height: auto;
  max-width: none;
  pointer-events: none;
}
.duo__type { left: var(--lx); top: var(--ly); width: var(--lw); }
.duo__strip { left: 0; bottom: 0; width: 100%; height: 16.29%; object-fit: cover; }
/* 2026-09-25 (Aurobind): the whole can should be on screen at the typeface
   panel. The panel scales with the width, so on a wide, short screen 86% of
   it can still be taller than the window; the cap holds it inside. */
.can--big { height: min(var(--ch), 84svh); }
/* 09-26: Sherbet's --cx/--cy are the can's centre, so it stays centred in
   the yellow even when the 84svh cap makes it shorter */
.duo--sherbet .can--big { translate: -50% -50%; }
/* Figma's drop shadow on the can: 53 · 11, blur 78.9, 25% black */
.can--big > img { filter: drop-shadow(3.3125em 0.6875em 2.5em rgba(0, 0, 0, 0.25)); }
.can--big.is-held > img { filter: drop-shadow(4.5em 2em 3.5em rgba(0, 0, 0, 0.35)); }

/* ============================================================
   NATI — the barrages: the menus, and the social posts
   A block of its own between two stages. With JS it pins for --pin of
   scroll: the pieces drop onto one pile in the middle of the screen, in
   markup order, then the pile splits and every piece flies out to its
   place in the spread. The menus' spread is Figma's (Frame 25); the posts'
   spread is a 3 x 3 laid out here in the same field, since Figma only has
   them as a heap. The pin lets go exactly as the spread settles, so the
   rest of it scrolls up like the page. Without JS, or with reduced motion,
   the spread simply sits there.

   --fh is the field's height in cqw (its design height / 1440). --band is
   the strip at the top that holds the small label; the field starts under
   it, so the label never sits on the spread.
   ============================================================ */
.barrage {
  --band: clamp(56px, 6.6vw, 104px);
  position: relative;
  z-index: 2;
  width: 100%;
  height: calc(var(--band) + var(--fh, 137.5cqw));
}
.barrage.is-live {
  height: calc(var(--pin, 260svh) + 100svh);
  /* the spread's overflow below the pin */
  margin-bottom: calc(var(--band) + var(--fh, 137.5cqw) - 100svh);
}
.barrage__stage {
  position: relative;
  height: 100%;
  overflow-x: clip;
  overflow-y: visible;
}
.barrage.is-live .barrage__stage {
  position: sticky;
  top: 0;
  height: 100svh;
}
/* 2026-09-19 (Aurobind): "small text" over each barrage, saying what it is */
.barrage__label {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: var(--band);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  margin: 0;
  padding: 0 16px calc(var(--band) * 0.2);
  font-size: clamp(11px, 0.95vw, 14px);
  color: var(--dim);
  text-align: center;
}
.barrage__field {
  position: absolute;
  top: var(--band);
  left: -5.0694%;                           /* -73 / 1440 */
  width: 111.5236%;                         /* 1606 / 1440 */
  aspect-ratio: var(--far, 1605.94 / 1980.04);
}
.barrage__menu {
  position: absolute;
  left: var(--l); top: var(--t);
  width: var(--mw); height: var(--mh);
  margin: 0;
  transform: rotate(var(--rot));
  will-change: transform;
}
.barrage__menu > img {
  display: block;
  width: 100%; height: 100%;
  filter: drop-shadow(0 1.2vw 1.6vw rgba(0, 0, 0, 0.45));
}
/* the stage after the menus slides up under the spread's last row */
.proj--after-barrage { margin-top: -35.6944cqw; }   /* (9106 - 8592) / 1440 */

/* ============================================================
   NATI — the sheet run
   2026-09-19 (Aurobind): the four sketch sheets were a scatter over the
   story poster, each hiding part of the next. Now they come in one after
   another. With JS the block pins for --pin of scroll; each sheet flies in
   big to the middle of the screen while the ones before it slide left, a
   small gap between each, and once all four are in, the row pulls back so
   the whole set fits the screen (two by two on a phone). The pin lets go
   there, and the next stage comes up right under the row (--tail, set from
   JS, is how much of the pinned screen is left under it).

   The files are the Figma exports cut down to the paper
   (tools/trim-nati-sheets.py), so each image's box is its sheet and the
   gaps come out even. Without JS, or with reduced motion, the four simply
   sit in that finished row.
   ============================================================ */
.run {
  position: relative;
  z-index: 2;
  width: 100%;
  padding: clamp(24px, 4cqw, 64px) 0;
  overflow-x: clip;
}
.run__stage { position: relative; }
.run__track {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 1.6cqw;
  width: 90%;
  margin: 0 auto;
}
.run__sheet {
  flex: calc(var(--ar)) 1 0;              /* width by aspect: equal heights */
  margin: 0;
}
.run__sheet > img {
  display: block;
  width: 100%; height: auto;
  -webkit-user-drag: none;
}
.run.is-live {
  height: calc(var(--pin, 240svh) + 100svh);
  padding: 0;
  margin-bottom: calc(var(--tail, 0px) * -1);
}
.run.is-live .run__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  pointer-events: none;    /* its empty lower part overlaps the next stage */
}
.run.is-live .run__track {
  display: block;
  position: absolute;
  inset: 0;
  width: auto;
  margin: 0;
}
.run.is-live .run__sheet {
  position: absolute;
  left: 0; top: 0;
  will-change: transform;
}
.run.is-live .run__sheet > img { height: 100%; }

/* ============================================================
   COP&DROP, 2026-09-24 REBUILD (Figma 205:113)
   ============================================================ */

/* ---------- palette: four swatches edge to edge ---------- */
.swatches {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: 0; padding: 0;
  list-style: none;
}
.swatch {
  position: relative;
  background: var(--c);
  color: var(--fg);
  padding: 21.2em 0 0 1.728em;             /* label at 339 · 27.65 */
}
/* the black swatch is #0B0B0B on the #0F0E0E page: a hairline keeps its edge */
.swatch--edge { box-shadow: inset 0 0 0 1px var(--hairline); }
.swatch__name {
  margin: 0 0 1.7em;
  font-family: 'Bakbak One', var(--sans);
  font-size: 1.5721em;                     /* 25.15 */
  line-height: 1.2;
  text-transform: uppercase;
}
.swatch__vals {
  display: grid;
  gap: 0.84em;
  width: 8.06em;                           /* 108.8 at 13.5 */
  margin: 0;
  font-family: 'Plus Jakarta Sans', var(--sans);
  font-weight: 600;
  font-size: 0.8437em;                     /* 13.5 */
  line-height: 0.9;
}
.swatch__vals > div { display: flex; justify-content: space-between; gap: 1em; white-space: nowrap; }
.swatch__vals dt, .swatch__vals dd { margin: 0; }

/* ---------- mission / core promise / vision ----------
   The card is Figma's 1314 x 623, radius 30. The portrait inside is sized as
   Figma sizes it (1707 wide, 393 off the left) and only slides up and down.
   With JS the block pins for --pin of scroll (.is-live): showcase.js moves
   the portrait between Figma's three crops, holding at each, and swaps the
   words at the midpoints. The negative margins let the card sit at its
   Figma gaps (57 above, 70 below) while its stage is a full screen tall; the
   stage's empty parts let clicks through. */
.mission {
  position: relative;
  z-index: 1;
  font-size: 1.1111cqw;
  padding: 3.5625em 0 4.375em;
}
.mission.is-live {
  height: calc(100svh + var(--pin, 190svh));
  padding: 0;
  margin: calc((38.9375em - 100svh) / 2 + 3.5625em) 0 calc((38.9375em - 100svh) / 2 + 4.375em);
}
.mission.is-live .mission__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  pointer-events: none;
}
.mission__card {
  position: relative;
  width: 82.125em;                          /* 1314 */
  height: 38.9375em;                        /* 623 */
  margin: 0 3.875em;
  border-radius: 1.875em;                   /* 30 */
  overflow: hidden;
  background: #9E1015;
  transform: translateZ(0);
  pointer-events: auto;
}
.mission__img {
  position: absolute;
  left: -24.5625em;                         /* -393 */
  top: 0;
  width: 106.6875em;                        /* 1707 */
  height: auto;
  max-width: none;
  transform: translate3d(0, -5.025em, 0);   /* Figma's Mission crop, -80 */
  will-change: transform;
}
.mission__panel {
  position: absolute;
  left: var(--tx); top: var(--ty);
  width: var(--tw);
  color: #C5FD50;
  opacity: 0;
  transform: translateY(1.25em);
  transition: opacity 0.5s var(--ease), transform 0.8s var(--ease);
}
.mission__panel.is-on { opacity: 1; transform: none; }
.mission__panel.is-past { transform: translateY(-1.25em); }
.mission__title {
  margin: 0;
  font-family: 'Bakbak One', var(--sans);
  font-weight: 400;
  font-size: 6em;                           /* 96 */
  line-height: var(--lh, 1.5);
  text-transform: uppercase;
  white-space: nowrap;
}
.mission__panel--big .mission__title { font-size: 8em; }   /* Vision is set at 128 */
.mission__body {
  margin: 0;
  font-family: 'Cardo', Georgia, serif;
  font-weight: 700;
  font-size: 1.5em;                         /* 24 */
  line-height: 1.25;                        /* 30 */
}

/* ---------- we made them social ----------
   Figma Frame 43, 1440 x 761: the heading and the five icons across the
   top, the stage under it at 237. The fan and the five campaign rails share
   the stage; one of them shows at a time (showcase.js, initSocial). */
.social {
  position: relative;
  z-index: 1;
  font-size: 1.1111cqw;
  padding-bottom: 2.4375em;                 /* 39 */
  overflow-x: clip;
}
.social__head {
  display: flex;
  align-items: flex-start;
  gap: 0.5em;                               /* 745 -> 753 */
  box-sizing: border-box;
  height: 14.8125em;                        /* the stage starts at 237 */
  padding: 0.625em 3.875em 0;               /* 10 · 62 */
}
.social__title {
  flex: none;
  max-width: 7.1146em;                      /* 683 at 96 */
  margin: 0;
  font-family: 'Georama', var(--sans);
  font-weight: 900;
  font-size: 6em;
  line-height: 0.96;
  text-transform: uppercase;
  color: var(--paper);
}
.social__nav { margin-top: 2.375em; }       /* the icons sit at 48 */
.social__picks {
  display: flex;
  gap: 2.0625em;                            /* 33 */
  margin: 0; padding: 0;
  list-style: none;
}
.social__pick {
  position: relative;
  display: block;
  width: 5.5574em; height: 5.5574em;        /* 88.9 */
  padding: 0;
  border: 0;
  border-radius: 50%;
  overflow: hidden;
  background: var(--ink-3);
  cursor: pointer;
  transform: translateZ(0);
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease), opacity 0.35s var(--ease);
}
.social__pick > img {
  position: absolute;
  left: var(--ix); top: var(--iy);
  width: var(--iw); height: auto;
  max-width: none;
  pointer-events: none;
}
.social__pick:hover { transform: scale(1.07); }
.social__pick:focus-visible { outline: 2px solid var(--yellow); outline-offset: 4px; }
.social__pick[aria-pressed="true"] { box-shadow: 0 0 0 0.1875em var(--ink), 0 0 0 0.375em #C5FD50; }
.social.is-open .social__pick[aria-pressed="false"] { opacity: 0.55; }
.social.is-open .social__pick[aria-pressed="false"]:hover { opacity: 1; }
.social__now {
  display: flex;
  align-items: baseline;
  gap: 1em;
  min-height: 1.5em;
  margin: 1em 0 0;
  font-size: 1em;
  line-height: 1.5;
  color: var(--dim);
}
.social__all {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--smoke);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}
.social__all:hover { color: var(--paper); }

.social__stage {
  position: relative;
  height: 30.3125em;                        /* 485 */
}
.social__fan { position: absolute; inset: 0; }
.social__card {
  position: absolute;
  left: calc(3.875em + var(--x)); top: 0;
  width: var(--w); height: 100%;
  padding: 0; border: 0;
  overflow: hidden;
  background: var(--ink-3);
  cursor: pointer;
  transition: transform 0.45s var(--ease), opacity 0.45s var(--ease), visibility 0s linear 0s;
}
/* coming back from a campaign, the fan deals back in left to right */
.social.is-back .social__card {
  transition:
    transform 0.7s var(--ease) calc(var(--i) * 50ms + 120ms),
    opacity 0.5s var(--ease) calc(var(--i) * 50ms + 120ms),
    visibility 0s linear 0s;
}
.social__card > img { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.social__card:hover { transform: translateY(-0.75em); z-index: 6; }
.social__card:focus-visible { outline: 2px solid var(--yellow); outline-offset: -2px; z-index: 6; }
.social.is-open .social__card {
  opacity: 0;
  visibility: hidden;
  transform: translateY(2.5em) scale(0.97);
  transition:
    transform 0.5s var(--ease) calc(var(--i) * 35ms),
    opacity 0.35s var(--ease) calc(var(--i) * 35ms),
    visibility 0s linear 0.55s;
}

.social .rail {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0s linear 0.4s;
}
.social .rail.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.2s var(--ease) 0.15s;
}
.social .rail__item {
  opacity: 0;
  transform: translateX(5em);
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.social .rail.is-active .rail__item {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.55s var(--ease) calc(var(--i, 0) * 55ms + 180ms),
    transform 0.9s var(--ease) calc(var(--i, 0) * 55ms + 180ms);
}

/* ---------- the strip: a row your scroll moves ----------
   Figma Frame 249: tops aligned, 51 between, radius 35 unless set.
   2026-09-25 (Aurobind): it used to run on its own. Now, with JS
   (.is-live), the block pins for --pin of scroll (set from the row's
   length) and showcase.js slides the row from its first slide at the left
   gutter to its last at the right one; then the pin lets go. The row is
   never taller than 84% of the screen (--sh is its tallest slide, 695).
   The negative margins keep Figma's gaps above and below while the stage
   is a full screen tall. Without JS, or with reduced motion, the row
   scrolls sideways by hand. */
.strip {
  --sh: 43.4375em;
  position: relative;
  z-index: 1;
  font-size: min(1.1111cqw, calc(84svh / 43.4375));
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.strip::-webkit-scrollbar { display: none; }
.strip.is-live {
  height: calc(100svh + var(--pin, 300svh));
  margin-block: calc((var(--sh) - 100svh) / 2);   /* block only: .proj-bleed owns the sides */
  overflow: visible;
}
.strip.is-live .strip__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow-x: clip;
  pointer-events: none;                     /* its empty top and bottom overlap the blocks around it */
}
.strip.is-live .strip__item { pointer-events: auto; }
.strip__track {
  display: flex;
  width: max-content;
  margin-left: 0.6875em;                    /* 62 - 51: first slide at the gutter */
  padding-right: 3.875em;                   /* and the last one ends at the other */
}
.strip.is-live .strip__track { will-change: transform; }
/* full width since the 09-26 side padding, first slide still at the cards' edge */
@media (min-width: 901px) {
  .strip.proj-bleed .strip__track {
    margin-left: calc(0.6875em + var(--pad));
    padding-right: calc(3.875em + var(--pad));
  }
}
.strip__set {
  display: flex;
  align-items: flex-start;
  gap: 3.1875em;                            /* 51 */
  margin: 0;
  padding: 0 0 0 3.1875em;
  list-style: none;
}
.strip__item {
  flex: none;
  width: var(--w); height: var(--h);
  border-radius: var(--r, 2.1875em);        /* 35 */
  overflow: hidden;
  background: var(--ink-3);
  transform: translateZ(0);
}
.strip__item > img,
.strip__item > video {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  -webkit-user-drag: none;
}

/* ============================================================
   NATI REPUBLIC, 2026-09-24 REBUILD (Figma 205:114); cream that day,
   black again from 2026-09-25 (the rules below serve both)
   ============================================================ */
/* the story panel: grungy wall, the logo, Nati's own text */
.nstory__logo {
  position: absolute;
  left: 40.68%; top: 21.02%;
  width: 32.18%; height: auto;
  mix-blend-mode: darken;          /* Figma sets it on the wall; the export's cream drops out */
}
.nstory__text {
  position: absolute;
  left: 25.44%; top: 43.84%;
  width: 62.72%;
  font-family: 'Akshar', var(--sans);
  font-size: 1.0143em;              /* 16.228 */
  line-height: 1.22;
  color: #311B0F;
  text-align: center;
}
.nstory__text p { margin: 0 0 1.22em; }
/* the second story block, beside the type specimen */
.nstory2 {
  position: absolute;
  left: var(--x); top: var(--y); width: var(--w);
}
.nstory2 > img { display: block; width: 73.94%; height: auto; }
.nstory2 > p {
  margin: 1.25em 0 0;
  font-family: 'Akshar', var(--sans);
  font-size: 0.9438em;              /* 15.1 */
  line-height: 1.22;
  color: #111110;
}

/* 2026-09-25, black again: the story block keeps Figma's 10px corners on
   its outer edges (the photo's card is open so the sticker can hang over) */
.nati .nstory-photo { border-radius: 0.625em 0 0 0.625em !important; }
.nati .nstory { border-radius: 0 0.625em 0.625em 0; overflow: hidden; }

/* ---------- "We launched them!" (2026-09-25) ----------
   Figma 229:778 + Frame 272. The title is an image (Monkstead Round is not
   a web font), then the launch shots in one row that runs leftwards on its
   own, forever. Two copies side by side (the second from showcase.js); the
   track slides one copy's width and starts over. 97 above, 142 below, as
   Figma spaces it. */
.nlaunch {
  position: relative;
  z-index: 1;
  font-size: 1.1111cqw;
  padding: 6.0625em 0 7.375em;
}
.nlaunch__title { width: 34.98em; margin: 0 auto; font-size: 1em; }
.nlaunch__title > img { display: block; width: 100%; height: auto; }
.nlaunch__run {
  margin-top: 3.5em;
  padding: 1.5em 0;
  overflow: hidden;
}
.nlaunch__track {
  display: flex;
  width: max-content;
  animation: nlaunch-run var(--dur, 90s) linear infinite;
}
.nlaunch__set {
  display: flex;
  align-items: center;
  gap: 1.25em;
  margin: 0;
  padding: 0 1.25em 0 0;
  list-style: none;
}
.nlaunch__item {
  flex: none;
  width: var(--w); height: 21.5em;
  overflow: hidden;
  border-radius: 0.3125em;
  background: var(--ink-3);
  transform: translateY(var(--dy, 0)) rotate(var(--rot, 0deg));
}
.nlaunch__item > img { display: block; width: 100%; height: 100%; object-fit: cover; }
@keyframes nlaunch-run { to { transform: translate3d(-50%, 0, 0); } }

/* ---------- the badge and the menus (2026-09-25) ----------
   Figma Frame 277, 1281 x 1231, centred on the page. The badge turns on its
   own, always. With JS (.is-live) the block pins for --pin of scroll and
   showcase.js (natiRing) flies the menus in from their sides; the field is
   never taller than 88% of the screen. Without JS, or with reduced motion,
   the finished ring sits there and the badge is still. */
.nring {
  --fw: 80.0825em;
  --fh: 76.925em;
  position: relative;
  z-index: 1;
  overflow-x: clip;                         /* the menus come in from off the page */
  font-size: min(1.1111cqw, calc(88svh / 76.925));
  padding: 5.125em 0 2.25em;                /* 82 above, 36 below */
}
.nring__stage { position: relative; }
.nring__field {
  position: relative;
  width: var(--fw); height: var(--fh);
  margin: 0 auto;
}
.nring.is-live {
  height: calc(100svh + var(--pin, 200svh));
  padding: 0;
  margin-block: calc((var(--fh) - 100svh) / 2 + 5.125em) calc((var(--fh) - 100svh) / 2 + 2.25em);
}
.nring.is-live .nring__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  display: flex;
  align-items: center;
  overflow-x: clip;
  pointer-events: none;
}
.nring__badge {
  position: absolute;
  left: 19.92em; top: 17.977em;             /* 318.7 · 287.6: the ring's centre, as Figma's */
  width: 39.47em; height: 39.47em;          /* 631.5 */
  animation: nring-spin 26s linear infinite;
}
@keyframes nring-spin { to { transform: rotate(360deg); } }
.nring__menu {
  position: absolute;
  left: var(--l); top: var(--t);
  width: var(--w); height: var(--h);
  transform: rotate(var(--rot));
  filter: drop-shadow(0 0.5em 1em rgba(0, 0, 0, 0.45));
}
.nring.is-live .nring__menu { will-change: transform; }

/* "We made them social": the pinned piles (showcase.js, natiSocial).
   The field is Figma's y 6120-6760 at the stage unit; while pinned, the
   stage is a screen tall and the field sits in its middle (or, on a short
   screen, pins with its bottom on the screen's bottom — its top is only
   margin). The negative margins keep Figma's gaps above and below. */
.nsoc {
  --fh: 40em;
  position: relative;
  z-index: 1;
  font-size: 1.1111cqw;
  overflow-x: clip;
}
.nsoc__stage { position: relative; }
.nsoc__field { position: relative; width: 100%; height: var(--fh); }
.nsoc.is-live {
  height: calc(max(100svh, var(--fh)) + var(--pin, 240svh));
  margin-block: calc((var(--fh) - max(100svh, var(--fh))) / 2);
}
.nsoc.is-live .nsoc__stage {
  position: sticky;
  top: min(0px, calc(100svh - var(--fh)));
  height: max(100svh, var(--fh));
  display: flex;
  align-items: center;
  pointer-events: none;
}
.nsoc__title {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  margin: 0;
  font-size: 1em;                   /* the site's h2 size would scale these em placements */
}
.nsoc__line {
  position: absolute;
  left: 0; top: var(--y);
  width: 100%; height: var(--h);
  overflow: hidden;
  display: block;
}
.nsoc__line > img { display: block; width: 100%; height: 100%; }
.nsoc__post {
  position: absolute;
  left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  max-width: none;
}
.nsoc.is-live .nsoc__post,
.nsoc.is-live .nsoc__line > img { will-change: transform; }

/* ---------- below 900px proj.css reflows each stage to one column ---------- */
@media (max-width: 900px) {
  .proj--show .card--proj { transform: none; }
  /* cutouts keep roughly their design size instead of filling the column */
  .proj--show .card--bare {
    transform: rotate(var(--rot, 0deg));
    width: min(86%, calc(var(--w) * 0.6));
    justify-self: center;
  }
  /* reading order where the desktop DOM order is set by layering (Sherbet) */
  .proj--show > [style*="--o:"] { order: var(--o); }
  .proj--seg { padding-top: 16px; padding-bottom: 16px; }
  .proj--seg:first-child { padding-top: 8px; }   /* under the sticky nav, 09-26 */

  .rail {
    position: relative;
    left: auto; top: auto;
    font-size: 10px;                        /* a slide is ~270px wide on a phone */
    height: var(--h);
    width: auto;
    margin: 8px -20px;
  }
  .can {
    position: relative;
    left: auto; top: auto;
    justify-self: center;
    width: min(62vw, calc(var(--w) * 0.55));
    height: auto;
    aspect-ratio: var(--ar);
  }
  .proj__copy { position: static; width: auto; font-size: 16px; }
  .proj--after-barrage { margin-top: 0; }

  /* the panel is a column item; the can stays where it stands inside it */
  .duo {
    position: relative;
    left: auto; top: auto;
    width: 100%; height: auto;
    aspect-ratio: var(--ar);
  }
  .proj--show .can--in {
    position: absolute;
    left: var(--cx); top: var(--cy);
    width: auto; height: var(--ch);
    justify-self: auto;
  }
}
/* Cop&Drop rebuild, phones */
@media (max-width: 900px) {
  .swatches {
    position: relative;
    left: auto; top: auto;
    width: 100%; height: auto;
    grid-template-columns: repeat(2, 1fr);
  }
  /* the values were 11px on a phone; 12px now, and the column takes the
     swatch's width so "197, 253, 80" has room */
  .swatch { font-size: 14px; padding: 6.5em 1.3em 1.5em; }
  .swatch__vals { width: auto; font-size: 0.8572em; }

  .mission { font-size: 16px; padding: 16px 0 24px; }
  .mission.is-live { margin: calc((min(125vw, 78svh) - 100svh) / 2 + 16px) 0 calc((min(125vw, 78svh) - 100svh) / 2 + 24px); }
  .mission__card {
    width: calc(100% - 40px);             /* a flex item with only absolute children would shrink to 0 */
    height: min(125vw, 78svh);
    margin: 0 20px;
    border-radius: 20px;
  }
  .mission__card::after {
    content: '';
    position: absolute; inset: 45% 0 0;
    background: linear-gradient(transparent, rgba(40, 0, 2, 0.55));
    pointer-events: none;
  }
  .mission__img { left: -45%; width: 190%; transform: none; }
  .mission__panel { left: 20px; right: 20px; top: auto; bottom: 22px; width: auto; z-index: 1; }
  .mission__title,
  .mission__panel--big .mission__title { font-size: clamp(38px, 11.5vw, 60px); line-height: 1.05; white-space: normal; }
  .mission__body { font-size: 17px; line-height: 1.3; margin-top: 8px; }

  .social { font-size: 16px; padding: 24px 0 8px; }
  .social__head { flex-direction: column; gap: 18px; height: auto; padding: 0 20px; }
  .social__title { font-size: clamp(36px, 11vw, 64px); max-width: none; }
  .social__nav { margin: 0; }
  .social__picks { gap: 10px; }
  .social__pick { width: 54px; height: 54px; }
  .social__now { font-size: 14px; margin-top: 10px; }
  /* closed: the fan fits the width; open: the rail's slides are ~234px wide */
  .social__stage {
    margin-top: 12px;
    height: calc((100cqw - 40px) / 82.125 * 30.3125);
    transition: height 0.5s var(--ease);
  }
  .social.is-open .social__stage { height: 303px; }
  .social__fan { font-size: calc((100cqw - 40px) / 82.125); }
  .social__card { left: calc(20px + var(--x)); }
  .social .rail {
    position: absolute;
    left: 0; top: 0;
    width: 100%;
    margin: 0;
    font-size: 10px;
  }

  /* 2026-09-26 mobile sweep: at 10px the slides were ~240px posters in a
     screen of black. Now the tallest is 70% of the screen (a 1:1.25 post is
     ~330px wide on a 390 phone, one and a bit in view), at the page's 20px
     gutter with 16px between, and showcase.js runs the row 1.6px per scroll
     px here, so the pin is no longer than it was. */
  .strip { font-size: min(14px, calc(70svh / 43.4375)); }
  .strip__track { margin-left: 20px; padding-right: 20px; }
  .strip.proj-bleed .strip__track { margin-left: 20px; padding-right: 20px; }
  .strip__set { gap: 16px; padding-left: 0; }
}

/* Nati rebuild, phones: the story panel and its twin go into the column */
@media (max-width: 900px) {
  .proj--show .nstory { aspect-ratio: auto; height: auto; padding: 36px 20px 28px; overflow: hidden; }
  .nstory > .duo__bg { position: absolute; inset: 0; }
  .nstory__logo { position: relative; left: auto; top: auto; display: block; width: 46%; margin: 0 auto 20px; }
  .nstory__text { position: relative; left: auto; top: auto; width: auto; font-size: 14px; }
  .nstory2 { position: static; width: auto; padding: 8px 4px 16px; }
  .nstory2 > img { width: 60%; }
  .nstory2 > p { font-size: 14px; }
  /* the field is only ~45% of a phone's width tall: pin a shorter stage in
     the middle of the screen so there is less empty cream around it */
  /* 2026-09-26 (Aurobind): on a phone the spread was a thin band, the piles
     either side of a small title, and most of the pinned screen was empty.
     Now it stacks, and the whole of it fits one screen: the left pile at
     the top, the right pile at the bottom, the title in the middle. The
     title comes in 2.9x; as the posts start landing showcase.js shrinks it
     to ~2.2x (--shrink) and the piles overlap its top and bottom edges.
     Piles are 1.35x, slid into place with `translate` (the JS flies them in
     with `transform`, so the two add up). The unit is the smaller of the
     width's and 1/190 of the screen's height, so short phones fit too;
     the field is then narrower than the screen and centred. */
  .nsoc { --fh: 180em; --pin: 170svh; --shrink: 0.23; font-size: min(1.1111cqw, calc(100svh / 190)); }
  .nsoc__field { width: 90em; margin: 0 auto; flex: none; }
  .nsoc__title {
    font-size: 2.9em;
    left: 50%;
    top: 33.45em;                          /* 97em of the field: the gap's middle */
    translate: -50% -50%;
    scale: var(--ts, 1);
    z-index: 0;
  }
  .nsoc__post { font-size: 1.35em; z-index: 1; }
  .nsoc__post[data-side="L"] { translate: 14.36em 10.4em; }     /* pile's top at 16em */
  .nsoc__post[data-side="R"] { translate: -38.09em 91.35em; }   /* pile's foot at 176.6em */

  /* black again, 09-25: stacked, each block keeps all four corners */
  .nati .nstory-photo { border-radius: 0.625em !important; }
  .nati .nstory { border-radius: 0.625em; }
  /* the launch row a third of the screen tall, the ring a little wider than
     the phone (its outer menus run off the edges) */
  .nlaunch { font-size: 2.4cqw; padding: 40px 0 36px; }
  .nlaunch__run { margin-top: 20px; }
  .nring { font-size: min(calc(100cqw / 70), calc(88svh / 76.925)); padding: 24px 0 16px; }
  /* the field is wider than the phone, so `margin: auto` fell to 0 and the
     ring sat ~26px right of centre (and as a flex item it could shrink).
     Keep its width and put the badge's centre (39.655em in) on the
     screen's centre. 2026-09-26, Aurobind. */
  .nring__field { flex: none; margin: 0 0 0 calc(50% - 39.655em); }
}

/* the finished row goes two by two where four across would be too small */
@media (max-width: 700px) {
  .run__track { flex-wrap: wrap; gap: 12px; width: auto; margin: 0 20px; }
  .run__sheet { flex: 0 0 calc(50% - 6px); }
}

@media (prefers-reduced-motion: reduce) {
  .rail__track, .can, .barrage__menu, .layer--sway, .run__sheet { will-change: auto; }
  /* the strip is a row you scroll by hand (showcase.js leaves it unpinned) */
  .strip__track { will-change: auto; }
  .mission__panel, .social__card, .social .rail, .social .rail__item { transition-duration: 0.01s !important; transition-delay: 0s !important; }
  .nsoc__post, .nsoc__line > img, .nring__menu { will-change: auto; }
  .nlaunch__track, .nring__badge { animation: none; }
  .nlaunch__run { overflow-x: auto; }
  .mission__panel { transform: none !important; }
}

/* ============================================================
   COP&DROP — the logo in the sky (2026-09-25)
   The film is sky and logo baked together; this adds a little tooth on top.
   The page grain is fixed and faint, so the card carries its own, same
   generated texture (--grain-url, site.js), finer and a touch stronger.
   ============================================================ */
.card--sky .card__grain {
  position: absolute; inset: 0;
  pointer-events: none;
  background-image: var(--grain-url);
  background-size: 140px 140px;
  mix-blend-mode: soft-light;
  opacity: 0.55;
}
