/* ==========================================================================
   Jessica Bulinski — portfolio
   Rebuilt to match the original site. Written from scratch; nothing is
   copied from the previous host's stylesheet.
   ========================================================================== */

:root {
  /* 1vw / 1vh, unless the page is scaled up for a very wide screen — then the
     head script sets them so everything keeps the proportions of a 1440px
     laptop layout. Every vw/vh size in this file goes through these. */
  --vw: 1vw;
  --vh: 1vh;
}

:root {
  --brand: #6965ff;          /* periwinkle — sidebar, links, captions */
  --ink: #0500a3;            /* deep blue — the big display headings */
  --ink-nav: #000020;        /* almost-black — the active nav item */
  --paper: #ffffff;
  --rule: #e6e5f7;

  --sidebar-w: 297px;
  /* The original insets its content by a percentage of the column, not a fixed
     max-width, so the margins grow with the window. Measured off the live site
     at two different widths: 10.35% each side. */
  --content-pad: 10.35%;
  --bar-h: 56px;            /* the phone top bar */

  /* The banner strip's own left-to-right run, sampled off the artwork:
     light periwinkle on the left, deep indigo on the right. */
  --bar-from: #8c88ff;
  --bar-mid:  #635ffa;
  --bar-to:   #3e38d9;

  /* Confetti shapes for the poster hover. Four-point stars and kites with
     their corners rounded off, drawn once here as data URLs so the browser
     never asks the network for them. Colours: the site periwinkle, the aqua
     that runs through her Trollhunters and Dragons art, white, and one warm
     coral for contrast. */
  --sp-star4-aq: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%238ff2ff%22%20stroke%3D%22%238ff2ff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200C53.6%2033%2067%2046.4%20100%2050C67%2053.6%2053.6%2067%2050%20100C46.4%2067%2033%2053.6%200%2050C33%2046.4%2046.4%2033%2050%200Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-star4-wh: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%23ffffff%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200C53.6%2033%2067%2046.4%20100%2050C67%2053.6%2053.6%2067%2050%20100C46.4%2067%2033%2053.6%200%2050C33%2046.4%2046.4%2033%2050%200Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-star4-pw: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%23b3afff%22%20stroke%3D%22%23b3afff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200C53.6%2033%2067%2046.4%20100%2050C67%2053.6%2053.6%2067%2050%20100C46.4%2067%2033%2053.6%200%2050C33%2046.4%2046.4%2033%2050%200Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-star4-co: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%23ffb0a3%22%20stroke%3D%22%23ffb0a3%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200C53.6%2033%2067%2046.4%20100%2050C67%2053.6%2053.6%2067%2050%20100C46.4%2067%2033%2053.6%200%2050C33%2046.4%2046.4%2033%2050%200Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-kite-co: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%23ffb0a3%22%20stroke%3D%22%23ffb0a3%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200L71%2050L50%20100L29%2050Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-kite-aq2: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%234ec9e8%22%20stroke%3D%22%234ec9e8%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200L71%2050L50%20100L29%2050Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-kite-pw2: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%236965ff%22%20stroke%3D%22%236965ff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200L71%2050L50%20100L29%2050Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-kite-wh: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%23ffffff%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200L71%2050L50%20100L29%2050Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-kite-aq: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%238ff2ff%22%20stroke%3D%22%238ff2ff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200L71%2050L50%20100L29%2050Z%22%2F%3E%3C%2Fsvg%3E");
  --sp-kite-pw: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-12%20-12%20124%20124%22%3E%3Cpath%20fill%3D%22%23b3afff%22%20stroke%3D%22%23b3afff%22%20stroke-width%3D%2220%22%20stroke-linejoin%3D%22round%22%20d%3D%22M50%200L71%2050L50%20100L29%2050Z%22%2F%3E%3C%2Fsvg%3E");

  --font-display: "Quicksand", "Trebuchet MS", "Segoe UI", sans-serif;
  --font-nav: "Work Sans", "Helvetica Neue", Arial, sans-serif;

  --gap: 40px;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--brand);
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
video { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
  border-radius: 2px;
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute;
  top: -999px; left: 8px;
  z-index: 200;
  background: var(--paper);
  color: var(--ink);
  padding: 10px 16px;
  border-radius: 0 0 8px 8px;
  font-weight: 600;
}
.skip-link:focus { top: 0; }

/* ---------- shell ---------------------------------------------------- */

.shell {
  display: block;
  min-height: calc(100 * var(--vh));
}

/* ---------- sidebar -------------------------------------------------- */

/* The purple column is a phone-only bar now. On a wide screen the menu sits
   in the page and in the bar that slides down on scroll, and this whole
   element is hidden. Everything below still describes the phone. */
.sidebar { display: none; }

.navtoggle { display: none; }
.scrollhint { display: none; }

.sidebar__panel {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

/* The icons and the copyright line, at the foot of every page. */
.site-foot {
  display: block;
  text-align: center;
  padding: 44px var(--content-pad) 48px;
}
.site-foot__social {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 18px;
  color: var(--brand);
  margin-bottom: 10px;
}
.site-foot__social a { display: inline-flex; align-items: center; line-height: 1; color: var(--brand); }
.site-foot__social a:hover { opacity: 0.65; }
.site-foot__social svg { display: block; }
.site-foot__social .imdb {
  font-family: var(--font-nav);
  font-weight: 700;
  font-size: 15px;
  line-height: 1;
  letter-spacing: -0.02em;
}
.site-foot__copy { font-size: 12px; color: var(--brand); margin: 0; }

.sidebar__home {
  font-family: var(--font-nav);
  font-size: 32px;
  line-height: 1;
  letter-spacing: -0.09em;
  font-weight: 400;
  color: #fff;
  margin: 0 0 40px;
}

.sidebar__nav ul,
.sidebar__projects ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.sidebar__nav a,
.sidebar__projects a {
  display: block;
  color: #fff;
  transition: opacity 0.18s var(--ease);
}

.sidebar__nav a {
  font-size: 14px;
  font-weight: 400;
  line-height: 1.25;
  margin-bottom: 5px;
}
.sidebar__nav a[aria-current="page"] { font-weight: 500; }

.sidebar__nav a[aria-current="page"],
.sidebar__projects a[aria-current="page"] { color: var(--ink-nav); }

.sidebar__rule {
  width: 20px;
  height: 0;
  border: 0;
  border-top: 1px solid rgba(255, 255, 255, 0.85);
  margin: 30px 0;
}

/* 11.62px is what the original uses. It is the size at which the longest
   title — How to Train Your Dragon: Flight Academy — still fits the column
   on a single line. */
.sidebar__projects a {
  font-size: 11.62px;
  line-height: 1.25;
  margin-bottom: 5px;
}

@media (hover: hover) {
  .sidebar__nav a:hover,
  .sidebar__projects a:hover { opacity: 0.62; }
}

.sidebar__foot { margin-top: auto; padding-top: 40px; }

.sidebar__social {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 10px;
}
.sidebar__social a {
  display: inline-flex;
  align-items: center;
  color: var(--ink-nav);
  transition: opacity 0.18s var(--ease);
}
.sidebar__social a:hover { opacity: 0.65; }
.sidebar__social svg { display: block; }
.sidebar__social .imdb {
  font-family: var(--font-nav);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: -0.02em;
}

.sidebar__copy {
  font-size: 12px;
  color: var(--ink-nav);
  margin: 0;
}

/* ---------- menu ------------------------------------------------------ */

/* At rest the menu sits in the page, above everything, centred over the
   content the way the title block is. Phone widths hide it and use the
   bar and full-screen menu instead. */
.pagemenu {
  display: flex;
  justify-content: center;
  padding: 20px var(--content-pad) 4px;
}

/* On every page that opens on a banner, the menu sits on top of the arch
   rather than above it, so the artwork runs to the very top of the screen
   with no white strip and no seam at the corners. The 404 has no banner,
   so there the menu stays in the flow. */
.main--overbanner,
.main--overhero,
.main--underbanner { position: relative; }

.main--overbanner .pagemenu {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  padding-bottom: 0;
}

/* A project page opens on its own banner footage, which can be anything — a
   bright sky, a dark interior. Rather than fight that with a wash, the menu
   gets its own white strip above the footage and reads as the header of the
   section, in the site's own periwinkle. */
.main--overhero .pagemenu {
  position: static;
  background: var(--paper);
  padding: 22px var(--content-pad) 20px;
}

/* Same again at the foot: on the pages that close on the bottom arch the
   footer floats over it, so that arch runs to the bottom of the page with
   no white strip under it. */
.main--underbanner .site-foot {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 40;
  padding-top: 0;
  padding-bottom: 26px;
}

.sitemenu__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 36px;
}

.sitemenu__item {
  position: relative;
  display: flex;
  align-items: center;
}

.sitemenu__link {
  font-family: var(--font-nav);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: 0.02em;
  color: var(--brand);
  position: relative;
  padding: 8px 0;
  transition: color 0.18s var(--ease);
}

/* The line under a link draws itself in from the left, as on the rest of
   the site's hovers. */
.sitemenu__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.24s var(--ease);
}
@media (hover: hover) {
  .sitemenu__link:hover { color: var(--ink-nav); }
  .sitemenu__link:hover::after { transform: scaleX(1); }
}
.sitemenu__link[aria-current="page"] { color: var(--ink-nav); }
.sitemenu__link[aria-current="page"]::after {
  transform: scaleX(1);
  animation: menu-underline 0.42s var(--ease) both;
}
@keyframes menu-underline {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

/* the chevron beside Work */
.sitemenu__toggle {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 6px 2px;
  border: 0;
  background: none;
  color: var(--brand);
  cursor: pointer;
}
.sitemenu__chev { transition: transform 0.22s var(--ease); }
.sitemenu__item.is-open .sitemenu__chev { transform: rotate(180deg); }
.sitemenu__item.is-open .sitemenu__toggle { color: var(--ink-nav); }

/* the drop-down itself */
.sitemenu__drop {
  position: absolute;
  top: 100%;
  left: -22px;
  z-index: 60;
  min-width: 292px;
  background: var(--paper);
  border: 1px solid var(--rule);
  box-shadow: 0 22px 44px -26px rgba(5, 0, 163, 0.5);
  padding: 12px 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease),
    visibility 0s linear 0.2s;
}
.sitemenu__item.is-open .sitemenu__drop {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0s;
}
.sitemenu__drop ul { list-style: none; margin: 0; padding: 0; }
.sitemenu__drop a {
  display: block;
  font-family: var(--font-nav);
  font-size: 12.5px;
  line-height: 1.3;
  color: var(--brand);
  padding: 9px 22px;
  white-space: nowrap;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
@media (hover: hover) {
  .sitemenu__drop a:hover { background: var(--rule); color: var(--ink-nav); }
}
.sitemenu__drop a[aria-current="page"] { color: var(--ink-nav); }

/* ---------- the bar that arrives on scroll ---------------------------- */

/* Out of sight at rest and while the visitor is reading downward. The
   moment they scroll back up it drops in, so the whole site is one click
   away wherever they are. Back at the top it tucks away again. */
.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background: linear-gradient(
    90deg,
    var(--bar-from) 0%,
    var(--bar-mid) 52%,
    var(--bar-to) 100%
  );
  box-shadow: 0 8px 20px -12px rgba(5, 0, 163, 0.45);
  transform: translateY(-104%);
  /* Hinted to the compositor so the slide runs on the graphics card rather
     than being repainted each frame — that repaint is what made it stutter. */
  will-change: transform;
  backface-visibility: hidden;
  transition: transform 0.3s var(--ease);
}

/* Arriving gets a longer, softer ease-out than leaving: it glides to a stop
   instead of arriving at full speed and halting. */
.topbar.is-shown {
  transform: none;
  transition: transform 0.46s cubic-bezier(0.16, 0.84, 0.28, 1);
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 30px;
  height: 62px;
  padding: 0 var(--content-pad);
}

/* Her name in the bar is the page title shrunk down — same face, weight
   and spacing as the big one on the home page, painted the paper white so
   it reads against the gradient. */
.topbar__name {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1;
  letter-spacing: 0.07em;
  font-weight: 600;
  color: var(--paper);
  white-space: nowrap;
  transition: opacity 0.18s var(--ease);
}
.topbar__name:hover { opacity: 0.72; }

.topbar .sitemenu__list { gap: 30px; }
.topbar .sitemenu__link {
  font-size: 15px;
  color: var(--paper);
}
.topbar .sitemenu__toggle { color: var(--paper); }
.topbar .sitemenu__link[aria-current="page"] { color: var(--paper); }
.topbar .sitemenu__item.is-open .sitemenu__toggle { color: var(--paper); }
@media (hover: hover) {
  .topbar .sitemenu__link:hover { color: var(--paper); opacity: 0.78; }
}

/* ---------- main column ---------------------------------------------- */

.main {
  min-width: 0;
  background: var(--paper);
}

.block { width: 100%; }

.block__inner {
  margin: 0 auto;
  padding: 0 var(--content-pad);
}

.block--banner { width: 100%; overflow-x: clip; }
.block--banner img {
  width: 100%;
  height: auto;
  transform: translateZ(0);
  will-change: transform;
}

/* The ribbon is set 3% wider than the page and nudged left by the same
   amount, so its left end runs off the screen past the corner instead of
   landing exactly on it. The right edge stays where it was. */
.block--banner img.arch-wipe {
  width: 103%;
  max-width: none;
  margin-left: -3%;
}

/* ---------- the arch entrance ------------------------------------------
   Each arch is uncovered left to right rather than moved: a soft-edged mask
   travels across it, so the traced artwork never shifts a pixel and the
   curve stays exactly where it was drawn. --arch-wipe is where that edge
   has got to; the 13% gap behind it is the feather, which is the whole
   difference between this and a hard wipe.

   @property is what makes it animate at all — a plain custom property jumps
   from one value to the next instead of transitioning. Where it isn't
   supported the arch simply appears, which is a fine place to land.

   Only armed under .js-arch, set by an inline script in the head, so with
   JavaScript off the arches draw normally. --------------------------------- */
@property --arch-wipe {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 118%;
}

.js-arch .arch-wipe {
  --arch-wipe: 0%;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(var(--arch-wipe) - 13%), rgba(0, 0, 0, 0) var(--arch-wipe));
          mask-image: linear-gradient(90deg, #000 calc(var(--arch-wipe) - 13%), rgba(0, 0, 0, 0) var(--arch-wipe));
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

.js-arch .arch-wipe.is-drawn {
  --arch-wipe: 118%;
  transition: --arch-wipe 860ms cubic-bezier(0.34, 0.03, 0.16, 1);
}

@media (prefers-reduced-motion: reduce) {
  .js-arch .arch-wipe,
  .js-arch .arch-wipe.is-drawn {
    --arch-wipe: 118%;
    transition: none;
  }
}

.block--title {
  padding: 21px 0 26px;
  text-align: center;
  /* Lifts the name and tagline so they sit centred between the bottom of the
     ribbon and the top of the banner video. The ribbon grows with the window
     and the gap under the tagline doesn't, so the lift grows with it too.
     Layout is untouched — the video below doesn't move. */
  position: relative;
  top: calc(2.7px - calc(1.73 * var(--vw)));
}

/* Every page title is filled with a top-to-bottom run of the site's own blues
   instead of one flat ink. Typeface, weight, size and letter-spacing are
   untouched — only the fill. The plain colour underneath is kept as a fallback
   for anything that can't clip a background to text. */
.display-name,
.project-title,
.contact h1 {
  background-image: linear-gradient(180deg, #0500a3 0%, #3e38d9 55%, #8c88ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.display-name {
  font-family: var(--font-display);
  font-size: clamp(2rem, calc(5.3 * var(--vw)), 64px);
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.07em;
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}

.display-tagline {
  font-size: clamp(0.96rem, calc(2.77 * var(--vw)), 17px);
  line-height: 1.55;
  letter-spacing: 0.09em;
  font-weight: 600;
  color: var(--brand);
  margin: 10px 0 0;
  text-wrap: balance;
}

/* Phones: the tagline is wider than her name on one line, so it stacks into
   two lines at the dash ("Art Director" / "Visual Development Artist") and
   the dash itself is hidden. Same size and style; wide screens unchanged. */
@media (max-width: 900px) {
  .display-tagline .tg-sep { display: block; height: 0; overflow: hidden; }
}

/* ---------- banner video --------------------------------------------- */

/* The original holds this to a 330px strip on a wide screen and scales it
   down in step with the window on narrower ones. */
.banner-video {
  width: 100%;
  height: clamp(84px, calc(20.6 * var(--vw)), 330px);
  object-fit: cover;
  background: var(--brand);
}

.block--hero { width: 100%; }

/* Curved top for the home banner video ("curve-v01"). The frame is made a
   little taller and pulled up by the same amount, then a smooth arc is cut
   out of its top, so the edge rises at both sides to echo the ribbon above.
   At the centre the video's top edge lands exactly where it was before.
   Turned off by setting HOME_BANNER_SHAPE to "original-v01" in build.mjs. */
.block--hero-curve {
  --hero-rise: clamp(12px, calc(4.5 * var(--vw)), 72px);
  margin-top: calc(-1 * var(--hero-rise));
}
.block--hero-curve .banner-video {
  height: calc(clamp(84px, calc(20.6 * var(--vw)), 330px) + var(--hero-rise));
  object-position: 50% 35%;
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%201000%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M0%200Q500%20358.6%201000%200L1000%201000L0%201000Z%22%2F%3E%3C%2Fsvg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%201000%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M0%200Q500%20358.6%201000%200L1000%201000L0%201000Z%22%2F%3E%3C%2Fsvg%3E");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

/* ---------- home poster grid ------------------------------------------ */

.block--portfolio {
  /* clears the bar that can be sitting over the top of the page */
  scroll-margin-top: 72px;
  background-image: linear-gradient(
    0deg,
    #ffffff 0%,
    #9e7fff 33%,
    #6a80ff 66%,
    #ffffff 100%
  );
  padding: 39px 0 15px;
}

.poster-grid {
  margin: 0 auto;
  padding: 0 var(--content-pad);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 40px;
}

.poster {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: 18px;  /* softened corners on the poster tiles */
}

/* Hovering a tile drifts a handful of soft confetti shapes up across the
   artwork. Two layers, half a cycle apart, so the field never all blinks at
   once. Both sit over the artwork and under the title label.

   This replaced the flat purple wash the tiles used to fade up. */
.poster::before,
.poster::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  background-repeat: no-repeat;
  filter: drop-shadow(0 0 7px rgba(190, 180, 255, 0.9));
}

.poster::before {
  background-image:
    var(--sp-star4-aq), var(--sp-kite-co), var(--sp-star4-pw), var(--sp-kite-aq2),
    var(--sp-star4-wh), var(--sp-kite-pw2), var(--sp-star4-co);
  background-size: 21px 21px, 14px 14px, 28px 28px, 16px 16px, 11px 11px, 19px 19px, 24px 24px;
  background-position: 18% 20%, 68% 32%, 41% 63%, 84% 73%, 9% 80%, 55% 91%, 92% 45%;
}

.poster::after {
  background-image:
    var(--sp-kite-wh), var(--sp-star4-pw), var(--sp-kite-aq), var(--sp-star4-co),
    var(--sp-kite-pw), var(--sp-star4-aq), var(--sp-kite-co);
  background-size: 15px 15px, 26px 26px, 12px 12px, 20px 20px, 14px 14px, 23px 23px, 17px 17px;
  background-position: 62% 14%, 12% 46%, 87% 24%, 29% 88%, 74% 57%, 33% 30%, 50% 40%;
}

@media (hover: hover) {
  .poster:hover::before,
  .poster:focus-visible::before { animation: poster-drift 2.2s ease-in-out infinite; }

  .poster:hover::after,
  .poster:focus-visible::after { animation: poster-drift 2.2s ease-in-out 1.1s infinite; }
}

@keyframes poster-drift {
  0%   { opacity: 0; transform: translateY(7%) scale(0.88); }
  35%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-9%) scale(1.06); }
}

@media (prefers-reduced-motion: reduce) {
  .poster::before,
  .poster::after { animation: none !important; opacity: 0 !important; }
}

.poster img {
  width: 100%;
  height: auto;              /* beat the img height attribute */
  aspect-ratio: 2 / 3;
  object-fit: cover;
  transition: transform 0.45s var(--ease), filter 0.3s var(--ease);
}

@media (hover: hover) {
  .poster:hover img,
  .poster:focus-visible img { transform: scale(1.02); filter: brightness(1.05); }
}

.poster__label {
  position: absolute;
  z-index: 3;
  inset: auto 0 0 0;
  padding: 10px 12px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: linear-gradient(
    0deg,
    rgba(5, 0, 163, 0.94) 0%,     /* --ink, the heading indigo */
    rgba(56, 50, 205, 0.72) 45%,
    rgba(105, 101, 255, 0) 100%   /* --brand, faded out */
  );
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
/* "View project" button at the end of each poster's title bar. On desktop
   it arrives with the bar on hover; on a phone the bar is always showing. */
.poster__label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* The poster art already carries the title, so the words are hidden from
     sight (screen readers still hear them) and only the button shows. */
  font-size: 0;
}
.poster__label::after {
  content: "View project \203A";
  flex: 0 0 auto;
  font: 600 11px/1 var(--font-nav);
  letter-spacing: 0.06em;
  background: rgba(255, 255, 255, 0.95);
  color: #3e38d9;
  border-radius: 99px;
  padding: 6px 10px;
  white-space: nowrap;
}
@media (hover: hover) {
  .poster:hover .poster__label,
  .poster:focus-visible .poster__label { opacity: 1; }
}

/* ---------- project pages -------------------------------------------- */

.project-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, calc(5.3 * var(--vw)), 64px);
  line-height: 1;
  font-weight: 600;
  letter-spacing: 0.07em;
  color: var(--ink);
  text-align: center;
  text-wrap: balance;
  margin: 0;
  padding: 46px 0 34px;
}

.project-meta {
  display: grid;
  grid-template-columns: 33.33% 1fr;
  gap: 0;
  padding: 8px 0 44px;
}

.project-meta h2 {
  font-size: 12.8px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--brand);
  margin: 0 0 1px;
}

/* the About column's heading sits at body size on the original */
.project-meta__col--about h2 {
  font-size: 16px;
  letter-spacing: 0.04em;
  line-height: 1.55;
  margin-bottom: 0;
}

/* Role lines sit on consecutive lines, not as separated paragraphs. */
.project-meta p {
  margin: 0;
  font-size: 16px;
  line-height: 1.25;
  letter-spacing: 0.04em;
}
.project-meta__col--about p {
  line-height: 1.55;
  margin-bottom: 20px;
}
.project-meta p:last-child { margin-bottom: 0; }
.project-meta__col > *:last-child { margin-bottom: 0; }

/* The line under each video. On the original it sits below the player, left
   aligned across the full grid width, at 19px. */
.project-tagline {
  font-size: 19px;
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--brand);
  text-align: left;
  margin: 0;
  padding: 21px 0 44px;
}

.project-note {
  text-align: center;
  font-size: 17px;
  padding: 6px 0 40px;
  margin: 0;
}
.project-note a { text-decoration: underline; text-underline-offset: 3px; }

/* Artwork. Each project uses the arrangement the original uses: a masonry of
   two or three columns, or — on Mickey — justified rows where the pictures in
   a row share a height. The column count and the gutter come through as
   custom properties from image-layout.json. */
.art-grid {
  display: grid;
  grid-template-columns: repeat(var(--art-cols, 3), minmax(0, 1fr));
  gap: var(--art-gap, 20px);
  align-items: start;
  padding-bottom: 20px;
}

.art-col {
  display: flex;
  flex-direction: column;
  gap: var(--art-gap, 20px);
}

.art-rows {
  display: flex;
  flex-direction: column;
  gap: var(--art-gap, 20px);
  padding-bottom: 20px;
}

.art-row {
  display: flex;
  gap: var(--art-gap, 20px);
  align-items: flex-start;
}
.art-row .art { min-width: 0; }

figure.art { margin: 0; }

.art__frame {
  display: block;
  width: 100%;
  border: 0;
  padding: 0;
  background: none;
  cursor: zoom-in;
  overflow: hidden;
}

.art__frame img {
  width: 100%;
  height: auto;
}

/* The original prints nothing under a picture; the description lives in the
   alt text and appears in the lightbox. */

/* ---------- prev / next ---------------------------------------------- */

.project-nav {
  border-top: 1px solid var(--rule);
  margin-top: 26px;
  padding: 34px 0 60px;
  display: grid;
  gap: 28px;
}

.project-nav__link {
  display: flex;
  align-items: center;
  gap: 14px;
}
.project-nav__link--next { justify-content: flex-end; text-align: right; }

.project-nav__label {
  display: block;
  font-size: 12px;
  letter-spacing: 0.16em;
  font-weight: 600;
  color: rgba(105, 101, 255, 0.55);
  margin-bottom: 2px;
}

.project-nav__title {
  font-size: clamp(1.4rem, calc(3.6 * var(--vw)), 36px);
  line-height: 1.1;
  font-weight: 400;
  color: var(--brand);
  transition: color 0.18s var(--ease);
}
.project-nav__link:hover .project-nav__title { color: var(--ink); }

.project-nav__chev { flex: 0 0 auto; opacity: 0.55; }

/* ---- Project pages, Oct 2026 redesign ----------------------------------
   Banner with the home page's curve flipped to its bottom edge; title and
   Role / Created For / About in a white card on a soft Pipelines-colour
   band; the artwork as a mosaic of rounded tiles; Prev / Next on one line. */

/* The banner's bottom edge arches up in the middle. */
.block--hero-dip { --hero-dip: clamp(12px, calc(4.5 * var(--vw)), 72px); }
.block--hero-dip .banner-video {
  height: calc(clamp(84px, calc(20.6 * var(--vw)), 330px) + var(--hero-dip));
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%201000%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M0%200L1000%200L1000%201000Q500%20641.4%200%201000Z%22%2F%3E%3C%2Fsvg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%201000%201000%22%20preserveAspectRatio%3D%22none%22%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M0%200L1000%200L1000%201000Q500%20641.4%200%201000Z%22%2F%3E%3C%2Fsvg%3E");
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}
.block--hero-dip + .block { margin-top: calc(-0.6 * var(--hero-dip)); position: relative; }

/* Header band: white at the top, Pipelines blue behind the card, then a
   long soft fade that runs on behind the first row of art. */
.pj-head {
  position: relative;
  isolation: isolate;
  padding: 18px 0 150px;
}
.pj-head::before {
  content: "";
  position: absolute;
  inset: 0 -13.05%;      /* back out to the window edge: 10.35% of the page is 13.05% of the column */
  z-index: -1;
  background: linear-gradient(180deg, #fff 0%, #c9d1ff 26%, #8d9dff 50%, #a593ff 64%, #d9d0ff 80%, #f4f1ff 91%, #fff 100%);
}
.pj-head + * { margin-top: -96px; }

.pj-head .project-title {
  background-image: linear-gradient(180deg, #0500a3 0%, #3e38d9 55%, #8c88ff 100%);
  line-height: 1.08;
  padding: 34px 0 30px;
}
.pj-head .project-meta {
  grid-template-columns: minmax(0, 0.8fr) minmax(0, 2fr);
  gap: 0 48px;
  padding: 36px 44px 34px;
  border-radius: 30px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.9), 0 24px 50px -34px rgba(62, 56, 217, 0.5);
}
.pj-head .project-meta h2,
.pj-head .project-meta__col--about h2 {
  font-family: var(--font-nav);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--brand);
  line-height: 1.2;
  margin: 0 0 8px;
}
.pj-head .project-meta h2[style] { margin-top: 24px !important; }
.pj-head .project-meta__col:first-child p {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  line-height: 1.35;
  letter-spacing: 0.03em;
  color: #3e38d9;
}
.pj-head .project-meta__col--about { border-left: 1.5px solid #e6e5f7; padding-left: 48px; }
.pj-head .project-meta__col--about p { font-size: 17.5px; line-height: 1.65; letter-spacing: 0.02em; }

/* Mosaic: 12 columns, rows as tall as a column is wide times --mk (set per
   project in build.mjs). The cells carry their own start lines. */
.pj-bento {
  container-type: inline-size;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: calc(6vw * var(--mk, 0.95));
  grid-auto-rows: calc((100cqw - 11 * 14px) / 12 * var(--mk, 0.95));
  gap: 14px;
  padding: 8px 0 30px;
}
.pj-bento figure.art { min-height: 0; }
.pj-bento .art__frame,
.pj-bento .art__frame picture { height: 100%; }
.pj-bento .art__frame {
  border-radius: 12px;
  background: #f4f3ff;
  box-shadow: 0 14px 34px -20px rgba(62, 56, 217, 0.55);
}
.pj-bento .art__frame img { display: block; height: 100%; object-fit: cover; }

/* Prev / Next on one line, at the same height. */
.project-nav { grid-template-columns: 1fr 1fr; align-items: start; gap: 24px; }
.project-nav__link--next { grid-column: 2; }

/* The small labels (Role, Created For, About, Prev / Next Project) all take
   the warm orange from the Pipelines page so they stand out. */
.pj-head .project-meta h2,
.pj-head .project-meta__col--about h2 { color: #b5622c; }
.project-nav__label { font-size: 13.5px; letter-spacing: 0.2em; margin-bottom: 6px; color: #b5622c; }
.project-nav__chev { color: #b5622c; opacity: 0.8; }

@media (max-width: 1100px) {
  .pj-head::before { inset: 0 -6.82%; }
}
@media (max-width: 900px) {
  .pj-head::before { inset: 0 -20px; }
  .pj-head .project-meta { grid-template-columns: 1fr; padding: 26px 22px; border-radius: 22px; gap: 20px; }
  .pj-head .project-meta__col--about { border-left: 0; padding-left: 0; border-top: 1.5px solid #e6e5f7; padding-top: 18px; }
  /* phones: one piece per row, whole, no cropping */
  .pj-bento { grid-template-columns: 1fr; grid-auto-rows: auto; }
  .pj-bento figure.art { grid-column: auto !important; grid-row: auto !important; }
  .pj-bento .art__frame,
  .pj-bento .art__frame picture,
  .pj-bento .art__frame img { height: auto; }
}
@media (max-width: 600px) {
  .project-nav { grid-template-columns: 1fr; }
  .project-nav__link--next { grid-column: 1; }
}

/* ---------- about ----------------------------------------------------- */

/* Oct 2026 redesign (version "D"): her photo and intro on the poster-section
   gradient band, then the story in three cards, the availability panel,
   Awards as cards and Skills as tags.
   Built only from the site's own pieces: Quicksand + Work Sans, the
   periwinkle / ink blues, the title gradient, the banner-strip blue run,
   the poster-section gradient, the 6px tile corner and the sparkle shapes. */

.abx { padding: 34px 0 60px; color: var(--brand); }

/* Greeting — the same treatment as her name on the home page. */
.abx__hi {
  font-family: var(--font-display);
  font-size: clamp(2rem, calc(4.2 * var(--vw)), 54px);
  line-height: 1.08;
  font-weight: 600;
  letter-spacing: 0.05em;
  margin: 0;
  color: var(--ink);
  background-image: linear-gradient(180deg, #0500a3 0%, #3e38d9 55%, #8c88ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  text-wrap: balance;
}

.abx__welcome {
  font-family: var(--font-nav);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 14px 0 0;
}

.abx__lead {
  font-size: clamp(1.2rem, calc(1.75 * var(--vw)), 25px);
  line-height: 1.42;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: #3e38d9;
  margin: 26px 0 0;
}

.abx__body p {
  font-size: 18px;
  line-height: 1.6;
  letter-spacing: 0.02em;
  margin: 0 0 18px;
}
.abx__body p:last-child { margin-bottom: 0; }

/* Portrait: her circle photo inside a ring of the title gradient. */
.abx__portrait {
  position: relative;
  width: 100%;
  max-width: 440px;
  aspect-ratio: 1;
}
.abx__ring {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  padding: 7px;
  background: linear-gradient(150deg, #8c88ff 0%, #635ffa 45%, #0500a3 100%);
  box-shadow: 0 18px 50px rgba(99, 95, 250, 0.28);
}
.abx__ring picture,
.abx__ring img {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  border: 5px solid #fff;
}

/* A few still sparkles around the photo, drifting very gently. */
.abx__spark {
  position: absolute;
  width: var(--s, 22px);
  height: var(--s, 22px);
  background: var(--img) center / contain no-repeat;
  pointer-events: none;
  animation: abx-float 6s ease-in-out infinite;
  animation-delay: var(--d, 0s);
}
@keyframes abx-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-8px) rotate(12deg); }
}
@media (prefers-reduced-motion: reduce) { .abx__spark { animation: none; } }

/* Availability — her own sentence, given a soft panel and a way to act on it. */
.abx__cta {
  display: flex;
  align-items: center;
  gap: 24px;
  margin: 30px 0 0;
  padding: 22px 26px;
  border-radius: 6px;
  background: linear-gradient(90deg, rgba(140, 136, 255, 0.12), rgba(62, 56, 217, 0.08));
  border: 1.5px solid #e6e5f7;
}
.abx__cta p { margin: 0; font-size: 17px; line-height: 1.55; flex: 1 1 auto; }
.abx__btn {
  flex: none;
  display: inline-block;
  font-family: var(--font-nav);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #fff !important;
  background: linear-gradient(90deg, var(--bar-from) 0%, var(--bar-mid) 50%, var(--bar-to) 100%);
  border-radius: 999px;
  padding: 14px 32px 14px calc(32px + 0.24em);
  box-shadow: 0 6px 18px rgba(99, 95, 250, 0.28);
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
@media (hover: hover) {
  .abx__btn:hover { transform: translateY(-1px); box-shadow: 0 9px 24px rgba(99, 95, 250, 0.36); }
}

.abx__thanks {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: 0.06em;
  margin: 26px 0 0;
  color: var(--brand);
}

/* Section headings (Awards, Skills) */
.abx__h2 {
  font-family: var(--font-nav);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 0 0 18px;
  display: flex;
  align-items: center;
  gap: 16px;
}
.abx__h2::after { content: ""; flex: 1; height: 1.5px; background: #e6e5f7; }

/* Awards as two cards, each with the Emmy statuette already in the site. */
.abx__awards { margin-top: 64px; }
.abx__awardlist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
}
.abx__award {
  display: flex;
  gap: 18px;
  align-items: center;
  padding: 20px 22px;
  border-radius: 6px;
  background: #fff;
  border: 1.5px solid #e6e5f7;
  box-shadow: 0 8px 26px rgba(5, 0, 163, 0.06);
}
.abx__award img { width: 26px; height: auto; flex: none; }
.abx__year {
  font-family: var(--font-nav);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2em;
  display: block;
  margin-bottom: 4px;
}
.abx__award b { display: block; font-weight: 600; color: #3e38d9; font-size: 17px; line-height: 1.35; }
.abx__award span.abx__cite { display: block; font-size: 15px; line-height: 1.45; margin-top: 2px; }

/* Skills as chips. */
.abx__skills { margin-top: 56px; }
.abx__chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.abx__chips li {
  font-size: 16px;
  font-weight: 500;
  line-height: 1;
  padding: 10px 16px;
  border-radius: 999px;
  border: 1.5px solid #d6d4f7;
  background: #fff;
  transition: transform 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
}
@media (hover: hover) {
  .abx__chips li:hover { transform: translateY(-2px); border-color: var(--brand); background: #f6f5ff; }
}

/* The intro sits on the poster-section gradient band; the rest is centred. */
.abx { padding-top: 0; }
.abx .abx__band {
  margin: 0 -13.05%;
  padding: 70px 13.05%;
  background: linear-gradient(0deg, #fff 0%, #9e7fff 33%, #6a80ff 66%, #fff 100%);
}
.abx .abx__bandin {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1.38fr);
  gap: clamp(40px, calc(5 * var(--vw)), 90px);
  align-items: center;
}
.abx .abx__hi { background-image: none; -webkit-text-fill-color: #fff; color: #fff; text-shadow: 0 2px 18px rgba(5, 0, 163, 0.25); }
.abx .abx__welcome { color: #fff; opacity: 0.92; }
.abx .abx__lead { color: #fff; text-shadow: 0 1px 12px rgba(5, 0, 163, 0.18); }
.abx .abx__ring { background: #fff; box-shadow: 0 18px 50px rgba(5, 0, 163, 0.3); padding: 0; }
.abx .abx__ring img { border: 7px solid #fff; }
.abx .abx__portrait { max-width: 300px; justify-self: center; }
.abx .abx__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  margin: 30px 0 0;
}
.abx .abx__card {
  position: relative;
  padding: 28px 24px 24px;
  border-radius: 6px;
  background: #fff;
  border: 1.5px solid #e6e5f7;
  box-shadow: 0 8px 26px rgba(5, 0, 163, 0.06);
  overflow: hidden;
}
.abx .abx__card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 5px;
  background: linear-gradient(90deg, var(--bar-from), var(--bar-mid), var(--bar-to));
}
.abx .abx__card p { margin: 0; font-size: 17px; line-height: 1.6; }
.abx .abx__cta { max-width: 820px; margin: 40px auto 0; }
.abx .abx__thanks { text-align: center; }
.abx .abx__h2::before { content: ""; flex: 1; height: 1.5px; background: #e6e5f7; }
.abx .abx__chips { justify-content: center; }

/* Order: intro band, awards, the three titled cards, skills, then the
   availability panel and thanks at the very end. */
.abx .abx__awards { margin-top: 56px; }
.abx .abx__cards { margin-top: 44px; }
.abx .abx__cta { margin-top: 56px; }

/* Card titles take the three Pipelines-page colours (gold, green, orange),
   with the same short colour rule under each title. */
.abx .abx__card--1 { --ca: #9c7426; --cb: #d8ad5c; }
.abx .abx__card--2 { --ca: #2e8558; --cb: #86cfa5; }
.abx .abx__card--3 { --ca: #b5622c; --cb: #f0b07f; }
.abx .abx__card::before { background: linear-gradient(90deg, var(--ca, var(--bar-from)), var(--cb, var(--bar-to))); }
.abx__cardtitle {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: 0.04em;
  color: var(--ca, #3e38d9);
}
.abx__cardtitle::after {
  content: "";
  display: block;
  width: 56px;
  height: 3px;
  margin-top: 10px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--ca, #3e38d9), var(--cb, #8c88ff));
}

@media (max-width: 1100px) {
  .abx .abx__band { margin: 0 -6.82%; padding: 56px 6.82%; }
}
@media (max-width: 900px) {
  .abx .abx__bandin { display: block; }
  .abx .abx__hi, .abx .abx__welcome { text-align: center; }
  .abx .abx__cards { grid-template-columns: 1fr; }
  /* the purple runs further down on phones so the last lines of the
     intro stay on colour instead of fading into the white */
  .abx .abx__band {
    margin: 0 -20px; padding: 44px 20px 96px;
    background: linear-gradient(0deg, #fff 0%, #b8a2ff 9%, #9e7fff 20%, #6a80ff 58%, #fff 100%);
  }
  .abx .abx__portrait { max-width: 230px; }
  .abx .abx__lead { text-align: center; }
  .abx .abx__cards { margin-top: 32px; }
  .abx .abx__awards { margin-top: 36px; }
}

/* ---- phones ---------------------------------------------------------- */
@media (max-width: 900px) {
  .abx { padding-top: 20px; }
  .abx__portrait { max-width: 300px; margin: 0 auto 28px; }
  .abx__awardlist { grid-template-columns: 1fr; }
  .abx__cta { flex-direction: column; align-items: stretch; text-align: center; }
  .abx__btn { text-align: center; }
}

/* ---------- contact --------------------------------------------------- */

/* Tightened from the original's very tall well of empty space so the whole
   of Contact lands on screen the moment the menu item is clicked. */
.contact {
  text-align: center;
  padding: clamp(30px, calc(5 * var(--vh)), 56px) 0 clamp(38px, calc(6 * var(--vh)), 68px);
}
/* Contact keeps its own treatment: small and widely tracked, the way it was
   drawn. At the size the other page titles use it dwarfs the three lines of
   detail underneath it. */
.contact h1 {
  font-size: clamp(1.4rem, calc(4 * var(--vw)), 30px);
  letter-spacing: 0.22em;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 34px;
}
.contact p { font-size: clamp(1.15rem, calc(3 * var(--vw)), 28px); margin: 0 0 4px; }
.contact a { transition: opacity 0.18s var(--ease); }
.contact a:hover { opacity: 0.7; }

/* ---------- contact form ----------------------------------------------
   Visitors write to Jessica from the page; her address is never shown.
   Built only from the site's own pieces: Quicksand for what people type,
   Work Sans small caps for the labels (as in the menu), the periwinkle and
   ink blues, the pale rule colour for the field edges, the 6px corner of
   the poster tiles, and the banner strip's blue run on the Send button. */

.cform {
  width: 100%;
  max-width: 620px;
  margin: 44px auto 0;
  text-align: left;
}

.cform__field { margin: 0 0 22px; }

.cform__label {
  display: block;
  font-family: var(--font-nav);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand);
  margin: 0 0 8px;
}

.cform__req {
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: none;
  opacity: 0.7;
}

.cform__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.cform__sub {
  display: block;
  font-family: var(--font-nav);
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--brand);
  opacity: 0.8;
  margin-top: 6px;
}

.cform input,
.cform textarea {
  display: block;
  width: 100%;
  font-family: var(--font-display);
  font-size: 17px;          /* 16px or more, or iPhones zoom in on tap */
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink);
  background: var(--paper);
  border: 1.5px solid #d6d4f7;
  border-radius: 6px;
  padding: 12px 14px;
  margin: 0;
  outline: none;
  -webkit-appearance: none;
          appearance: none;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}

.cform textarea {
  min-height: 170px;
  resize: vertical;
}

.cform input:hover,
.cform textarea:hover { border-color: #b3afff; }

.cform input:focus,
.cform textarea:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(105, 101, 255, 0.16);
}

/* Only after a send was tried, so nothing is red before anyone has typed. */
.cform.was-tried input:invalid,
.cform.was-tried textarea:invalid { border-color: #e06d5c; }

.cform__actions {
  display: flex;
  justify-content: center;
  margin-top: 30px;
}

.cform__send {
  font-family: var(--font-nav);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(90deg, var(--bar-from) 0%, var(--bar-mid) 50%, var(--bar-to) 100%);
  border: 0;
  border-radius: 999px;
  padding: 15px 46px 15px calc(46px + 0.26em);
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(99, 95, 250, 0.28);
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease), opacity 0.18s var(--ease);
}

@media (hover: hover) {
  .cform__send:hover {
    transform: translateY(-1px);
    box-shadow: 0 9px 24px rgba(99, 95, 250, 0.36);
  }
}

.cform__send:active { transform: translateY(0); }
.cform__send[disabled] { opacity: 0.6; cursor: default; transform: none; }

.cform__status {
  min-height: 1.5em;
  text-align: center;
  line-height: 1.5;
  color: var(--brand);
}

.cform__status.is-error {
  color: #b42a3c;
}

.cform__trap {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* .contact p sets the big 28px line size; the status line keeps its own. */
.cform .cform__status { font-size: 16px; margin: 18px 0 0; }

@media (max-width: 900px) {
  .cform { margin-top: 34px; }
  .cform__row { grid-template-columns: 1fr; gap: 14px; }
  .cform__send { width: 100%; }
}

/* ---- Contact page layout (Oct 2026) ------------------------------------
   Matched to the Pipelines page: the same band colours, measured in px from
   the top so the titles sit on the same near-white part of it, the same title
   type, and the same rounded white card. Selectors carry .contact.contact--page
   so the older .contact h1 / .contact p rules above don't reach in. */
.contact.contact--page {
  position: relative;
  isolation: isolate;
  padding: 64px 0 90px;
  text-align: center;
}
.contact.contact--page::before {
  content: "";
  position: absolute;
  inset: 0 -13.05%;      /* back out to the window edge: 10.35% of the page is 13.05% of the column */
  z-index: -1;
  background: linear-gradient(180deg, #fff 0px, #6a80ff 475px, #9e7fff calc(100% - 420px), #fff 100%);
}
.contact.contact--page .cband { padding: 0 0 44px; }

.contact.contact--page .ct-title {
  display: inline-block;
  position: relative;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.07rem, calc(5.4855 * var(--vw)), 66.24px);
  line-height: 1.08;
  letter-spacing: 0.07em;
  padding-bottom: 0.14em;
  color: var(--ink);
  background-image: linear-gradient(180deg, #0500a3 0%, #3e38d9 55%, #8c88ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}
/* the thin flat line under "Contact" */
.contact.contact--page .ct-title::after {
  content: "";
  position: absolute;
  left: 3%;
  right: 3%;
  bottom: 0;
  height: 2px;
  border-radius: 1px;
  background: #3e38d9;
}
.contact.contact--page .ct-name {
  margin: 14px 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.07rem, calc(5.4855 * var(--vw)), 66.24px);
  line-height: 1.12;
  letter-spacing: 0.07em;
  color: var(--ink);
  /* darker run than the title: it sits lower, on stronger colour */
  background-image: linear-gradient(180deg, #0500a3 0%, #2b25b8 60%, #4b46d6 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  text-wrap: balance;
}
.contact.contact--page .ct-role {
  margin: 14px 0 0;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1rem, calc(1.3 * var(--vw)), 17.6px);
  line-height: 1.55;
  letter-spacing: 0.09em;
  color: #3e38d9;
  text-wrap: balance;
}
.contact.contact--page .cform {
  position: relative;
  max-width: 680px;
  margin: 0 auto;
  padding: 44px 46px 34px;
  border: 0;
  border-radius: 30px;
  background: rgba(255, 255, 255, 0.96);
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.9), 0 24px 50px -34px rgba(62, 56, 217, 0.5);
}

@media (max-width: 1100px) {
  .contact.contact--page::before { inset: 0 -6.82%; }
}
@media (max-width: 900px) {
  .contact.contact--page { padding: 44px 0 60px; }
  .contact.contact--page::before {
    inset: 0 -20px;
    background: linear-gradient(180deg, #fff 0px, #6a80ff 420px, #9e7fff calc(100% - 300px), #fff 100%);
  }
  .contact.contact--page .cform { border-radius: 22px; padding: 28px 20px 24px; }
}

/* ---------- 404 -------------------------------------------------------- */

.notfound { text-align: center; padding: clamp(60px, calc(16 * var(--vh)), 170px) 0 130px; }
.notfound h1 {
  font-family: var(--font-display);
  font-size: clamp(2rem, calc(5.3 * var(--vw)), 64px);
  line-height: 1;
  letter-spacing: 0.07em;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 18px;
}
.notfound p { font-size: 19px; margin: 0 0 30px; }
.notfound a { text-decoration: underline; text-underline-offset: 4px; font-weight: 600; }

/* ---------- ring cursor over the artwork ------------------------------- */
/* The original replaces the pointer with a thin circle carrying a plus when
   you are over something that will open larger. Pointer devices only. */

.ringcursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 130;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  border: 1px solid currentColor;
  border-radius: 50%;
  color: #fff;
  pointer-events: none;
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
  mix-blend-mode: difference;
}
.ringcursor::before,
.ringcursor::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  background: currentColor;
}
.ringcursor::before { width: 11px; height: 1px; transform: translate(-50%, -50%); }
.ringcursor::after { width: 1px; height: 11px; transform: translate(-50%, -50%); }
.ringcursor.is-on { opacity: 1; transform: scale(1); }

@media (hover: hover) and (pointer: fine) {
  body.has-ring .art__frame { cursor: none; }
}

/* ---------- lightbox --------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 120;
  background: rgba(6, 4, 40, 0.94);
  display: grid;
  place-items: center;
  padding: 3vmin;
}
.lightbox[hidden] { display: none; }
.lightbox img {
  max-width: 100%;
  max-height: calc(88 * var(--vh));
  width: auto;
  object-fit: contain;
  cursor: zoom-out;
}
.lightbox__caption {
  color: #fff;
  text-align: center;
  font-size: 14px;
  padding-top: 12px;
  min-height: 1em;
}
.lightbox__close {
  position: absolute;
  top: 16px; right: 18px;
  width: 44px; height: 44px;
  border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.lightbox__close:hover { background: rgba(255, 255, 255, 0.26); }

/* ---------- About page, desktop only -----------------------------------
   Sizes matched to Judge's mockup of 27 Aug. The phone layout is untouched:
   everything here sits behind a min-width guard. */
@media (min-width: 901px) {
  /* the three section headings all read at one size */
  .about__label,
  .awards h2,
  .skills h2 { font-size: 35px; }

  /* the lead sits directly over the writing it introduces, same column,
     same size */
  .about__lead {
    align-self: start;
    grid-column: 3 / -1;
    font-size: 24px;
    line-height: 1.18;
  }

  .about__body p {
    font-size: 24px;
    line-height: 1.18;
    margin-bottom: 28px;
  }

  .awards p {
    font-size: 24px;
    line-height: 1.46;
    margin-bottom: 28px;
  }

  .skills li { font-size: 24px; line-height: 30px; }
}

/* ---------- responsive ------------------------------------------------- */

/* Between the sidebar and the phone bar: keep the sidebar, tighten the gaps. */
@media (max-width: 1100px) {
  :root { --content-pad: 6%; }
  .art-grid { grid-template-columns: repeat(min(var(--art-cols, 2), 2), minmax(0, 1fr)); }
}

/* ---------- phone: bar + drop-down menu, as on the original ------------- */

@media (max-width: 900px) {
  /* Home page, phone only: posters show they can be tapped. The title bar
     stays on with a "View project" button, and the poster nearest the middle
     of the screen plays the same confetti the desktop shows on hover. */
  .poster__label {
    opacity: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-size: 0;
    padding: 26px 16px 14px;
  }
  .poster__label::after {
    font-size: 12px;
    padding: 7px 12px;
  }
  .poster.is-lit::before { animation: poster-drift 2.2s ease-in-out infinite; }
  .poster.is-lit::after  { animation: poster-drift 2.2s ease-in-out 1.1s infinite; }
  .poster.is-lit img { transform: scale(1.02); filter: brightness(1.05); }

  /* Home page, phone only: a small white circle with the same chevron as
     "Next project", floating at the foot of the screen so first-time
     visitors know there are posters below. It bobs gently, jumps to the
     posters when tapped, and fades away for good once they scroll. */
  .scrollhint {
    display: flex;
    align-items: center;
    justify-content: center;
    position: fixed;
    left: 50%;
    bottom: calc(22px + env(safe-area-inset-bottom, 0px));
    z-index: 70;
    width: 46px;
    height: 46px;
    margin-left: -23px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.94);
    color: var(--brand);
    box-shadow: 0 6px 18px rgba(5, 0, 120, 0.28);
    animation: scrollhint-bob 1.8s ease-in-out infinite;
    transition: opacity 0.35s var(--ease), visibility 0s linear 0.35s;
  }
  .scrollhint.is-gone { opacity: 0; visibility: hidden; }
  @keyframes scrollhint-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(5px); }
  }
  @media (prefers-reduced-motion: reduce) {
    .scrollhint { animation: none; }
  }

  :root { --content-pad: 20px; }

  /* A short page — Contact especially — used to leave the footer band floating
     in the middle of the screen with white underneath. The page is held to at
     least the height of the window and the band pushed to the bottom of it. */
  .shell {
    display: flex;
    flex-direction: column;
    min-height: calc(100 * var(--vh));
  }
  .main {
    flex: 1 0 auto;
    display: flex;
    flex-direction: column;
  }
  .main > .site-foot { margin-top: auto; }

  /* Where the page ends on the arch, the arch and the band travel together —
     the slack goes above the arch, so the two stay joined even on a page too
     short to fill the screen. */
  .main--underbanner > .site-foot { margin-top: -1px; }
  .main--underbanner > .block--banner:last-of-type { margin-top: auto; }

  /* the desktop menu and its scroll bar step aside for the phone bar */
  .pagemenu,
  .topbar { display: none; }

  /* The phone's bar carries the same gradient and the same name as the bar
     that slides down on a wide screen, and it stays put the whole way down
     the page rather than appearing and disappearing. */
  .sidebar {
    position: sticky;
    top: 0;
    z-index: 90;
    width: 100%;
    min-height: 0;
    background: linear-gradient(
      90deg,
      var(--bar-from) 0%,
      var(--bar-mid) 52%,
      var(--bar-to) 100%
    );
    color: var(--paper);
    padding: 0;
    display: block;
  }

  .sidebar__bar {
    display: flex;
    align-items: center;
    height: var(--bar-h);
    padding: 0 20px;
    background: none;
  }

  .sidebar__name {
    font-family: var(--font-display);
    font-size: min(18px, calc(4.6 * var(--vw)));
    line-height: 1;
    letter-spacing: 0.07em;
    font-weight: 600;
    color: var(--paper);
    white-space: nowrap;
  }

  /* The menu button: the word "Menu" in an outlined pill, which reads as
     tappable to first-time visitors in a way the three-line icon didn't.
     Once the menu is open it reads "Close". */
  .navtoggle {
    display: flex;
    align-items: center;
    position: fixed;
    top: 11px;
    right: 14px;
    z-index: 95;
    height: 34px;
    padding: 0 16px;
    border: 1.5px solid rgba(255, 255, 255, 0.9);
    border-radius: 99px;
    background: none;
    cursor: pointer;
    color: var(--paper);
  }
  .navtoggle__label {
    font-family: var(--font-nav);
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.04em;
  }
  .navtoggle__label--close { display: none; }
  .navtoggle[aria-expanded="true"] { color: #fff; }
  .navtoggle[aria-expanded="true"] .navtoggle__label--open { display: none; }
  .navtoggle[aria-expanded="true"] .navtoggle__label--close { display: inline; }

  /* the menu itself: a full-screen wash of the deep blue, links centred */
  .sidebar__panel {
    position: fixed;
    inset: 0;
    z-index: 80;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 0;
    padding: 78px 16px 40px;
    background: #090091;   /* solid, not see-through */
    overflow-y: auto;
    overscroll-behavior: contain;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.28s var(--ease), visibility 0s linear 0.28s;
  }
  .sidebar__panel.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.28s var(--ease), visibility 0s;
  }

  .sidebar__nav,
  .sidebar__projects { width: 100%; }

  .sidebar__nav ul,
  .sidebar__projects ul {
    display: block;
    text-align: center;
    margin: 0;
    padding: 0;
  }

  .sidebar__nav a,
  .sidebar__projects a {
    display: block;
    color: #fff;
    font-size: min(20px, calc(5.1 * var(--vw)));
    font-weight: 400;
    line-height: 45px;
    margin: 0;
  }
  /* Every item in the main list reads the same white — nothing is dimmed
     for being the page you are already on. */
  .sidebar__nav a[aria-current="page"] { color: #fff; opacity: 1; }

  .sidebar__rule { display: none; }
  .sidebar__foot { display: none; }

  /* Work opens the project list in place rather than the titles sitting
     loose at the bottom of the menu. */
  .sidebar__group { width: 100%; }

  .sidebar__groupbtn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 0 0 0 19px;   /* 11px chevron + the 8px gap */
    border: 0;
    background: none;
    cursor: pointer;
    font-family: inherit;
    font-size: min(20px, calc(5.1 * var(--vw)));
    font-weight: 400;
    line-height: 45px;
    color: #fff;
  }
  .sidebar__groupbtn .sitemenu__chev { transition: transform 0.26s var(--ease); }
  .sidebar__groupbtn[aria-expanded="true"] .sitemenu__chev { transform: rotate(180deg); }

  .sidebar__sub {
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.34s var(--ease);
  }
  .sidebar__sub.is-open { max-height: 560px; }
  .sidebar__sub ul { list-style: none; margin: 0; padding: 0; text-align: center; }
  .sidebar__sub a {
    display: block;
    color: #fff;
    font-size: min(16px, calc(4.3 * var(--vw)));
    line-height: 38px;
    opacity: 0.82;
  }
  .sidebar__sub a[aria-current="page"] { opacity: 0.5; }

  /* body scroll lock while the menu is open */
  body.nav-open { overflow: hidden; }

  /* On a phone the footer is a band of the same gradient the bar at the top
     carries, so the page is bookended by it. It sits in the normal flow
     directly under the arch — the arch's own bottom edge is the join, the
     same way the bar meets the arch at the top of the page. */
  /* The desktop rule floats this footer over the arch with no padding on top.
     On a phone it is a band in the flow like every other page's, so the
     padding is restored here — otherwise the arch pages get a shorter band
     with the marks jammed against the top edge. */
  .main--underbanner .site-foot {
    position: static;
    padding-top: 17px;
    padding-bottom: 17px;
  }

  .site-foot {
    display: block;
    text-align: center;
    margin-top: -1px;          /* closes the hairline the scaled arch can leave */
    padding: 17px 20px;        /* equal top and bottom — the marks sit centred in the band */
    /* Runs the other way to the bar at the top — deep on the left, light on
       the right — so the two bands mirror each other down the page. */
    background: linear-gradient(
      90deg,
      var(--bar-to) 0%,
      var(--bar-mid) 48%,
      var(--bar-from) 100%
    );
  }
  .site-foot__social {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 18px;
    color: var(--paper);
    margin-bottom: 6px;
  }
  .site-foot__social a {
    display: inline-flex;
    align-items: center;
    line-height: 1;
    color: var(--paper);
  }
  .site-foot__social .imdb {
    font-family: var(--font-nav);
    font-weight: 700;
    font-size: 15px;
    line-height: 1;
    letter-spacing: -0.02em;
  }
  .site-foot__copy { font-size: 12px; color: var(--paper); margin: 0; }

  /* The arch sits flush on the footer with nothing between them. */
  .main--underbanner .block--banner:last-of-type { margin-bottom: 0; }
  .main--underbanner .block--banner:last-of-type img { display: block; }

  /* one column of everything */
  .poster-grid { grid-template-columns: 1fr; gap: 40px; }
  .art-grid { grid-template-columns: 1fr; }
  .art-row { flex-direction: column; }
  .project-meta { grid-template-columns: 1fr; gap: 18px; }
  .project-meta__col--about h2 { margin-top: 6px; }

  .about,
  .awards {
    grid-template-columns: 1fr;
    column-gap: 0;
    row-gap: 18px;
  }
  .about { padding-top: 20px; }
  .about__lead,
  .about__portrait,
  .about__portrait-missing,
  .about__body,
  .awards h2,
  .awards__list { grid-column: 1; grid-row: auto; }
  .about__portrait { width: 100%; max-width: 380px; margin: 0 auto; }
  .about__portrait-missing { width: 100%; max-width: 380px; margin: 0 auto; }
  .skills ul { grid-template-rows: repeat(10, auto); }
  /* the skills read at the same size as an award line on a phone */
  .skills li { font-size: 16px; line-height: 23.2px; }

  .project-title { padding: 30px 0 22px; }
  .project-nav { padding: 28px 0 10px; }
}

@media (max-width: 480px) {
  .about__body p { font-size: 18px; }
  .skills ul { grid-template-columns: 1fr; grid-template-rows: repeat(20, auto); }
}

/* Respect the visitor's motion preference. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

@media print {
  .sidebar, .topbar, .pagemenu, .lightbox, .banner-video { display: none; }
}

/* ---------- video embed (loads nothing until asked) -------------------- */

.video-embed {
  max-width: none;      /* the original runs it the full width of the grid */
  margin: 0 auto;
}

.video-embed__button,
.video-embed iframe {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: 3px;
  background: #0b0930;
}

.video-embed__button {
  position: relative;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
}

.video-embed__button img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease);
}

.video-embed__play {
  position: absolute;
  inset: 50% auto auto 50%;
  transform: translate(-50%, -50%);
  width: 76px;
  height: 54px;
  border-radius: 12px;
  background: rgba(5, 0, 60, 0.72);
  transition: background 0.25s var(--ease), transform 0.25s var(--ease);
}
.video-embed__play::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  transform: translate(-42%, -50%);
  border-style: solid;
  border-width: 11px 0 11px 18px;
  border-color: transparent transparent transparent #fff;
}

@media (hover: hover) {
  .video-embed__button:hover img { transform: scale(1.02); opacity: 0.88; }
  .video-embed__button:hover .video-embed__play {
    background: var(--brand);
    transform: translate(-50%, -50%) scale(1.06);
  }
}

.video-embed__credit {
  font-size: 13px;
  line-height: 1.4;
  color: rgba(105, 101, 255, 0.8);
  text-align: center;
  margin: 10px 0 0;
}

/* ======================================================================
   Motion layer (public/js/motion.js). Everything here is switched on by
   classes that script adds, so with the script off the site looks exactly
   as it did before. Phones follow MOBILE_MODE in scripts/build.mjs.
   ====================================================================== */

/* Held back for a moment until the page is ready, then shown with a quick
   fade — no half-built first frame. If the script never runs, the page
   appears anyway after 2s. */
@media (min-width: 901px) {
  html.js-motion body { opacity: 0; animation: cx-failsafe 0s linear 1s forwards; }
}
/* Phones never wait: the page shows straight away and the 3D parts swap in
   as soon as they are ready. */
@media (max-width: 900px) {
  html.js-motion .block--portfolio .poster-grid { visibility: hidden; }
  html.cx-on .cx-rib:not(.cx-live) img.arch-wipe { visibility: visible !important; }
}
html.js-motion.cx-ready body { opacity: 1; animation: none; transition: opacity 0.08s ease; }
@keyframes cx-failsafe { to { opacity: 1; } }
.cx-veil { position: fixed; inset: 0; z-index: 200; background: #fff; opacity: 0; pointer-events: none; transition: opacity 0.1s cubic-bezier(0.4, 0, 0.2, 1); }
html.cx-leaving .cx-veil { opacity: 1; pointer-events: auto; transition-duration: 0.085s; }

/* ---- ribbons (header and footer arches) drawn in 3D ---- */
html.cx-on .cx-rib { position: relative; overflow: visible; }
html.cx-on .cx-rib img.arch-wipe { visibility: hidden; position: absolute; left: 0; top: 0; }
.cx-rib__host { position: absolute; left: 0; top: 0; width: 100%; z-index: 1; pointer-events: none; }
.cx-rib__host canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
html.cx-on .cx-rib--top,
html.cx-on .cx-rib--bottom { height: calc(18.05 * var(--vw) + 8px); }
html.cx-on .block--title { z-index: 2; }
html.cx-on .block--hero { position: relative; z-index: 3; }
@media (max-width: 900px) {
  .cx-rib__host { pointer-events: auto; touch-action: pan-y; }
}

/* ---- home: header spacing as approved in the concept ---- */
html.cx-on .main:has(.cx-work) .cx-rib--top { height: calc(17.1 * var(--vw)); }
html.cx-on .main:has(.cx-work) .block--title {
  padding: 0 0 calc(clamp(12px, calc(4.5 * var(--vw)), 72px) - 0.4 * var(--vw));
  top: 0;
}
html.cx-on .main:has(.cx-work) .cx-rib--bottom { height: calc(17.67 * var(--vw) + 30px); }

/* ---- home: the 3D carousel replaces the poster grid ---- */
html.cx-on .cx-work { padding: 0 0 clamp(24px, 4vh, 48px); }
html.cx-on .cx-work .poster-grid { display: none; }
.cx-arc__host { position: relative; width: 100%; }
.cx-arc__host > canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.cx-pill {
  position: absolute; left: 0; top: 0; z-index: 4;
  transform: translate(-50%, -50%) scale(0.9); opacity: 0;
  font-family: var(--font-nav); font-size: 14px; font-weight: 500; letter-spacing: 0.03em; white-space: nowrap;
  color: #fff; padding: 10px 18px; border-radius: 999px;
  background: rgba(5, 0, 163, 0.55); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.55);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease); pointer-events: none;
}
.cx-pill.on { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.cx-cap { position: absolute; left: 0; right: 0; bottom: -1%; z-index: 4; text-align: center; pointer-events: none; padding: 0 16px; }
.cx-cap__main { transition: opacity 0.25s; }
.cx-cap__title {
  font-family: var(--font-display); font-weight: 700; font-size: clamp(20px, calc(2.05 * var(--vw)), 29px);
  letter-spacing: 0.07em; line-height: 1.15; margin: 0; color: #0500a3;
  background-image: linear-gradient(180deg, #0500a3 0%, #0a04a8 55%, #1c16bd 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.cx-cap__roles {
  font-family: var(--font-display); font-weight: 600; font-size: clamp(0.96rem, calc(2.77 * var(--vw)), 17px);
  letter-spacing: 0.09em; line-height: 1.55; color: var(--brand); margin: 6px 0 0;
}
/* "Desktop site" switched on in a phone browser: the desktop layout on a tall, narrow touch screen. Short pages
   left a big white gap under the footer there, so (like the phone site) the page fills the screen and the
   footer band sits at the bottom. Real desktops (mouse) and the normal phone site don't match this rule. */
@media (min-width: 901px) and (hover: none) and (pointer: coarse) and (orientation: portrait) {
  .shell { display: flex; flex-direction: column; min-height: 100vh; min-height: 100svh; }
  .main { flex: 1 0 auto; display: flex; flex-direction: column; }
  .main > .site-foot { margin-top: auto; }
  .main--underbanner > .site-foot { margin-top: 0; }
  /* the spare height goes into the footer band itself: it grows upward, the ribbon stays at the bottom and its
     sparkles drift through the extra space, so there is no empty white gap anywhere */
  .main--underbanner > .block--banner:last-of-type { flex: 1 0 auto; display: flex; flex-direction: column; justify-content: flex-end; }
  html.cx-on .main--underbanner > .cx-rib--bottom img.arch-wipe { top: auto; bottom: 0; }
}

/* desktop: her name + tagline at the top of the home page, and the carousel caption (15% larger, then 10% smaller = 3.5% over the original) */
@media (min-width: 901px) {
  .display-name { font-size: clamp(2.07rem, calc(5.4855 * var(--vw)), 66.24px); }
  .display-tagline { font-size: clamp(0.9936rem, calc(2.867 * var(--vw)), 17.6px); }
  .cx-cap__title { font-size: clamp(20.7px, calc(2.1218 * var(--vw)), 30.02px); }
  .cx-cap__roles { font-size: clamp(0.9936rem, calc(2.867 * var(--vw)), 17.6px); }
}
.cx-arrows { position: absolute; left: 0; right: 0; top: 48%; z-index: 4; display: flex; justify-content: space-between; padding: 0 calc(3 * var(--vw)); transform: translateY(-50%); pointer-events: none; }
.cx-arrow {
  pointer-events: auto; width: 48px; height: 48px; border-radius: 50%;
  border: 1.5px solid var(--brand); background: rgba(255, 255, 255, 0.8); color: var(--brand);
  font-size: 22px; line-height: 1; cursor: pointer; display: grid; place-items: center; transition: background 0.2s, color 0.2s;
}
.cx-arrow:hover { background: var(--brand); color: #fff; }

/* ---- home on phones: one 3D poster after another ---- */
.cx-pl { position: relative; width: 100%; }
.cx-pl__canvas { position: absolute; top: 0; left: 0; width: 100%; display: block; will-change: transform; }
.cx-pl .cx-pill { font-size: 12px; padding: 7px 12px; pointer-events: auto; }

/* ---- project pages ---- */
html.cx-proj .lightbox { display: none !important; }
html.cx-proj .block--hero { overflow: hidden; }
html.cx-proj .block--hero .banner-video { transform: scale(1.06); filter: blur(10px); opacity: 0; transition: transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), filter 0.6s ease, opacity 0.5s ease; }
html.cx-proj.cx-ready .block--hero .banner-video { transform: none; filter: none; opacity: 1; }
html.cx-proj .project-title,
html.cx-proj .project-meta__col { opacity: 0; transform: translateY(18px); transition: opacity 0.45s ease, transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1); }
html.cx-proj .project-title { transition-delay: 0.12s; }
html.cx-proj .project-meta__col:nth-child(1) { transition-delay: 0.2s; }
html.cx-proj .project-meta__col:nth-child(2) { transition-delay: 0.26s; }
html.cx-proj.cx-ready .project-title,
html.cx-proj.cx-ready .project-meta__col { opacity: 1; transform: none; }
html.cx-proj figure.art { opacity: 0; transform: perspective(1400px) translate3d(0, 36px, -60px) rotateX(6deg); transform-origin: 50% 100%; transition: opacity 0.4s ease, transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1); }
html.cx-proj figure.art.cx-in { opacity: 1; transform: none; }
html.cx-proj .art__frame { transform: translate3d(var(--cx-x, 0px), var(--cx-y, 0px), 0) scale(var(--cx-s, 1)); transition: transform 0.7s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.7s ease; will-change: transform; }
html.cx-proj figure.art.cx-hot { position: relative; z-index: 3; }
html.cx-proj figure.art.cx-hot .art__frame { --cx-s: 1.035; box-shadow: 0 18px 40px rgba(5, 0, 163, 0.18); }
html.cx-proj .project-nav__link { opacity: 0; transition: opacity 0.45s ease, transform 0.55s cubic-bezier(0.2, 0.7, 0.2, 1); }
html.cx-proj .project-nav__link--prev { transform: translateX(-40px); }
html.cx-proj .project-nav__link--next { transform: translateX(40px); }
html.cx-proj .project-nav { overflow-x: hidden; overflow-x: clip; }   /* the slide-in start position must not widen the page on phones */
html.cx-proj .project-nav.cx-in .project-nav__link { opacity: 1; transform: none; }
html.cx-proj .project-nav__chev { transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1); }
html.cx-proj .project-nav__link--next:hover .project-nav__chev { transform: translateX(6px); }
html.cx-proj .project-nav__link--prev:hover .project-nav__chev { transform: translateX(-6px); }

/* the zoom view */
html.cx-lb-open .topbar { visibility: hidden; }   /* the scroll bar stays out of the zoom view's dimmed background */
.cxlb { position: fixed; inset: 0; z-index: 120; background: rgb(6, 4, 40); opacity: 0; pointer-events: none; transition: opacity 0.41s ease; }
.cxlb.on { opacity: 0.94; pointer-events: auto; cursor: zoom-out; }
.cxlb-img { position: fixed; z-index: 121; margin: 0; display: block; max-width: none; max-height: none; object-fit: contain; transform-origin: 0 0; cursor: zoom-out; will-change: transform; transition: transform 0.41s cubic-bezier(0.2, 0.7, 0.2, 1); box-shadow: 0 30px 80px rgba(0, 0, 0, 0.35); }
.cxlb-cap { position: fixed; left: 0; right: 0; z-index: 122; text-align: center; color: #fff; font: 14px/1.4 var(--font-display); opacity: 0; transition: opacity 0.35s ease; pointer-events: none; padding: 0 16px; }
.cxlb-cap.on { opacity: 1; transition-delay: 0.2s; }
.cxlb-x { position: fixed; top: 16px; right: 18px; z-index: 123; width: 44px; height: 44px; border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.14); color: #fff; font-size: 22px; line-height: 1; cursor: pointer; opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
.cxlb-x.on { opacity: 1; pointer-events: auto; transition-delay: 0.17s; }
.cxlb-x:hover { background: rgba(255, 255, 255, 0.26); }
.cxlb.cxlb-closing { pointer-events: auto; cursor: zoom-in; }
.cxlb-closing, .cxlb-closing .cxlb-img, .cxlb-img.cxlb-closing { transition-duration: 0.125s !important; }

@media (prefers-reduced-motion: reduce) {
  html.cx-proj * { transition: none !important; }
  html.cx-proj figure.art, html.cx-proj .project-title, html.cx-proj .project-meta__col,
  html.cx-proj .project-nav__link, html.cx-proj .block--hero .banner-video { opacity: 1 !important; transform: none !important; filter: none !important; }
}
