/* ===========================================================================
   Fidha Fathima — portfolio
   Plain CSS version. Everything you'd normally want to change lives in the
   :root token block directly below.

   Breakpoints used throughout:
     sm  640px   md  768px   lg 1024px   xl 1280px
   =========================================================================== */

:root {
  /* --- Colour ----------------------------------------------------------- */
  --bg: #0a0a0b;
  --fg: #f2f1ec;
  --muted: #a5a3ae;
  --accent: #6c5ce7;
  /* Lighter accent for small text on the dark bg — #6c5ce7 alone is ~3.9:1,
     below AA for the 12px eyebrows. */
  --accent-text: #a99cff;
  --card: #141418;
  --line: rgba(242, 241, 236, 0.09);

  /* --- Type ------------------------------------------------------------- */
  --font-display: "New Title", sans-serif;   /* hero only */
  /* Greycliff CF is a licensed font — add its webfont files (Light, 300) and
     it takes over every section title; until then this falls through to
     Space Grotesk, which is far closer to it than Khand */
  --font-heading: "Greycliff CF", "Space Grotesk", sans-serif;
  /* Greycliff CF is a licensed font — drop its webfont files in and it
     takes over; until then this falls through to Space Grotesk */
  --font-body: "Greycliff CF", "Space Grotesk", sans-serif;

  /* --- Layout ----------------------------------------------------------- */
  --container-max: 80rem;   /* home page */
  --container-narrow: 64rem; /* case-study pages */
  --gutter: 1.5rem;
  --section-pad: 6rem;      /* vertical padding per section */

  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);

  color-scheme: dark;
}

/* Light theme. Dark is the default; this applies only once the toggle in the
   header sets data-theme="light" on <html>. Everything downstream reads these
   five colours, so nothing else needs a light-specific rule. */
:root[data-theme="light"] {
  --bg: #faf9f6;
  --fg: #14141a;
  --muted: #56545f;
  --accent: #5b4bd6;
  --accent-text: #4a3ab8;
  --card: #ffffff;
  --line: color-mix(in srgb, var(--fg) 13%, transparent);

  color-scheme: light;
}

@media (min-width: 768px) {
  :root {
    --gutter: 2.5rem;
    --section-pad: 8rem;
  }
}

/* ---------------------------------------------------------------------------
   Reset + base
   --------------------------------------------------------------------------- */

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

* { margin: 0; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 {
  font-family: var(--font-heading);
  line-height: 1.16;
  font-weight: 300;              /* Greycliff Light */
  letter-spacing: -0.02em;
}

h4 { font-weight: 600; }

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

a { color: inherit; }

button, input, textarea { font: inherit; color: inherit; }

ul, ol { list-style: none; padding: 0; }

::selection {
  background: var(--accent);
  color: var(--fg);
}

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

/* ---------------------------------------------------------------------------
   Utilities
   --------------------------------------------------------------------------- */

.container {
  margin-inline: auto;
  width: 100%;
  max-width: var(--container-max);
  padding-inline: var(--gutter);
}

.container--narrow { max-width: var(--container-narrow); }

.sr-only {
  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;
  inset-inline-start: -9999px;
  top: 0;
  z-index: 60;
}
.skip-link:focus {
  inset-inline-start: 1rem;
  top: 1rem;
  position: fixed;
  background: var(--accent);
  color: var(--fg);
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  text-decoration: none;
}

/* Small uppercase label above section headings */
.eyebrow {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--accent-text);
}

/* Scroll-reveal — JS adds .is-in when the element enters the viewport */
.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.8s var(--ease-out-quint), transform 0.8s var(--ease-out-quint);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

.section {
  padding-block: var(--section-pad);
  scroll-margin-top: 6rem;
}
.section--ruled { border-top: 1px solid var(--line); }

.section-title {
  font-family: var(--font-heading);
  font-size: clamp(1.875rem, 4.2vw, 3rem);
  text-wrap: balance;
}
.eyebrow + .section-title { margin-top: 1rem; }

.link-underline {
  color: var(--fg);
  text-decoration: underline;
  text-decoration-color: rgba(108, 92, 231, 0.6);
  text-underline-offset: 4px;
  transition: text-decoration-color 0.2s;
}
.link-underline:hover { text-decoration-color: var(--accent-text); }

/* ---------------------------------------------------------------------------
   Header / navigation
   --------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 40;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 1rem;
}

.nav__logo {
  display: flex;
  align-items: center;
  color: var(--fg);
  text-decoration: none;
  transition: color 0.25s var(--ease-out-quint);
}
.nav__logo:hover { color: var(--accent-text); }

.nav__mark {
  /* the mark sits on its corner, so its box carries less ink than a
     square one — it needs a little more size to match the nav's weight */
  width: 2rem;
  height: 2rem;
  display: block;
}
@media (min-width: 768px) {
  .nav__mark { width: 2.25rem; height: 2.25rem; }
}

.nav__links {
  display: none;
  align-items: center;
  gap: 2.5rem;
}
.nav__links a {
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}
.nav__links a:hover { color: var(--fg); }

/* Theme toggle — moon in dark, sun in light */
.theme-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  margin-inline-start: 1.25rem;
  border: 1px solid var(--line);
  border-radius: 9999px;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}
.theme-toggle:hover { color: var(--fg); border-color: color-mix(in srgb, var(--fg) 35%, transparent); }
.theme-toggle svg { width: 1.0625rem; height: 1.0625rem; }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: none; }

/* On phones the toggle lives in the menu instead of the bar, as its last item */
.theme-toggle--menu {
  width: 100%;
  height: auto;
  margin: 0;
  padding-block: 0.75rem;
  justify-content: flex-start;
  gap: 0.75rem;
  border: 0;
  border-top: 1px solid var(--line);
  border-radius: 0;
  margin-top: 0.5rem;
  font-size: 1rem;
  text-align: start;
}
@media (max-width: 767px) {
  .nav > .theme-toggle { display: none; }
}
@media (min-width: 768px) {
  .theme-toggle--menu { display: none; }
}

.nav__toggle {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  width: 2.5rem;
  height: 2.5rem;
  background: none;
  border: 0;
  cursor: pointer;
}
.nav__toggle span {
  display: block;
  width: 1.5rem;
  height: 1px;
  background: var(--fg);
  transition: transform 0.2s;
}
.nav__toggle[aria-expanded="true"] span:first-child { transform: translateY(3.5px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

/* The menu carries its own surface now: the bar is a transparent pill, so
   there is nothing behind it to hide the page. */
.nav__mobile {
  margin: 0.75rem var(--gutter) 0;
  padding: 0.5rem 1.25rem 1rem;
  border: 1px solid var(--line);
  border-radius: 1.25rem;
  background: var(--card);
  backdrop-filter: blur(18px);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.95);
}
.nav__mobile[hidden] { display: none; }
.nav__mobile a {
  display: block;
  padding-block: 0.75rem;
  color: var(--muted);
  text-decoration: none;
}
.nav__mobile a:hover { color: var(--fg); }

@media (min-width: 768px) {
  .nav__links { display: flex; }
  .nav__toggle { display: none; }
  .nav__mobile { display: none !important; }
}


/* --- The bar as a floating pill, which the gradient hero needs ----------- */
.site-header {
  top: 1rem;
  background: none;
  border-bottom: 0;
  backdrop-filter: none;
}
.site-header .nav {
  max-width: fit-content;
  margin-inline: auto;
  gap: 1.5rem;
  padding: 0.5rem 0.75rem 0.5rem 1.25rem;
  border-radius: 9999px;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--card) 84%, transparent);
  backdrop-filter: blur(14px);
  box-shadow: 0 20px 50px -28px rgba(0, 0, 0, 0.9);
}
@media (min-width: 768px) {
  .site-header .nav { gap: 2rem; padding-left: 1.5rem; }
  .nav__links { gap: 1.5rem; }
}
.site-header.is-scrolled .nav {
  background: color-mix(in srgb, var(--card) 94%, transparent);
}

/* ---------------------------------------------------------------------------
   Media sections are identical in both themes
   The hero and the work cards put their type on imagery rather than on the
   page, so they keep the dark palette whatever the theme is. Overriding the
   tokens on the two elements is enough — the hero's dim layer, headline,
   eyebrow, clock and second beat, and each card's title, category, blurb,
   status chip and arrow all read them and inherit.
   --------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   Selected work
   Landscape cards, two per row, an odd last one centred. The project name is
   a small pill that grows on hover, with the arrow arriving alongside it.
   Below 768px the cards become a swipeable stack.
   --------------------------------------------------------------------------- */

/* the wrapper carries the gap under the heading */
.work { margin-top: 2.5rem; }
@media (min-width: 768px) { .work { margin-top: 3rem; } }

.work__row { display: grid; gap: 1.5rem; justify-items: center; }
/* width at every size, not just desktop: with justify-items: center a card
   with no width sizes to its image's intrinsic 1100px and overflows the row */
.work__row > .work__card { width: 100%; }
@media (min-width: 768px) {
  .work__row { grid-template-columns: repeat(2, 1fr); }
  /* an odd card at the end centres rather than hanging on the left */
  .work__row > .work__card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    width: calc(50% - 0.75rem);     /* one column, minus half the gap */
  }
}

.work__card {
  position: relative; display: block;
  text-decoration: none; color: var(--fg);
  transition: transform 0.4s var(--ease-out-quint), opacity 0.6s var(--ease-out-quint);
}
.work__card:hover { transform: translateY(-5px); }

.work__media {
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 4 / 3; border-radius: 1.5rem; background: var(--card);
}
.work__media img { width: 100%; height: 100%; object-fit: cover;
                   transition: transform 0.7s var(--ease-out-quint); }
.work__card:hover .work__media img { transform: scale(1.04); }
.work__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(10, 10, 11, 0.62), transparent 55%);
}

/* the name: small at rest, growing into the large pill on hover. Size and
   padding are tweened rather than scaled, so the text stays crisp. */
.work__pill {
  position: absolute; z-index: 2; left: 1rem; bottom: 1rem;
  display: inline-flex; align-items: center;
  padding: 0.5rem 1rem; border-radius: 9999px;
  background: #0a0a0b; color: #f2f1ec;
  font-family: var(--font-heading); font-weight: 300; letter-spacing: -0.01em;
  font-size: 0.9375rem; line-height: 1.2; white-space: nowrap;
  transition: font-size 0.35s var(--ease-out-quint), padding 0.35s var(--ease-out-quint);
}
:root[data-theme="light"] .work__pill { background: #14141a; }
.work__card:hover .work__pill,
.work__card:focus-visible .work__pill { font-size: 1.375rem; padding: 0.7rem 1.4rem; }

.work__arrow {
  position: absolute; z-index: 2; top: 1rem; right: 1rem;
  display: grid; place-items: center; width: 2.5rem; height: 2.5rem;
  border-radius: 9999px; background: #0a0a0b; color: #f2f1ec;
  box-shadow: 0 6px 18px -10px rgba(0, 0, 0, 0.9);
  opacity: 0; transform: translate(-4px, 4px) scale(0.9);
  transition: opacity 0.3s var(--ease-out-quint), transform 0.35s var(--ease-out-quint);
}
:root[data-theme="light"] .work__arrow { background: #14141a; }
.work__arrow svg { width: 1rem; height: 1rem; }
.work__card:hover .work__arrow,
.work__card:focus-visible .work__arrow { opacity: 1; transform: none; }

/* what kind of product it is: the tags slide in from the right under the
   arrow, each a moment after the last. Nothing else on the card moves. */
.work__tags {
  position: absolute; z-index: 2; top: 4.2rem; right: 1rem;
  display: flex; flex-direction: column; align-items: flex-end; gap: 0.4rem;
}
.work__tag {
  display: inline-flex; align-items: center;
  padding: 0.33rem 0.75rem; border-radius: 9999px;
  font-size: 0.75rem; font-weight: 400; letter-spacing: 0.02em; white-space: nowrap;
  /* These land on anything — a bright dashboard, a pale wall, a dark desk.
     A translucent tint alone fails on light artwork, so the chip carries its
     own dark surface and blurs and darkens what is behind it. */
  background: rgba(10, 10, 11, 0.62);
  border: 1px solid rgba(242, 241, 236, 0.22);
  backdrop-filter: blur(14px) saturate(1.2) brightness(0.55);
  -webkit-backdrop-filter: blur(14px) saturate(1.2) brightness(0.55);
  color: #f7f6f2;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
  box-shadow: 0 6px 18px -10px rgba(0, 0, 0, 0.9);
  opacity: 0; transform: translateX(0.75rem);
  transition: opacity 0.3s var(--ease-out-quint), transform 0.4s var(--ease-out-quint);
}
/* where backdrop-filter is unsupported the tint alone has to hold up */
@supports not (backdrop-filter: blur(1px)) {
  .work__tag { background: rgba(10, 10, 11, 0.85); }
}
.work__card:hover .work__tag,
.work__card:focus-visible .work__tag { opacity: 1; transform: none; }
.work__card:hover .work__tag:nth-child(2) { transition-delay: 0.06s; }
.work__card:hover .work__tag:nth-child(3) { transition-delay: 0.12s; }

/* the blurb is for screen readers, not the card face */
.work__blurb { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* --- Mobile: a swipeable stack ----------------------------------------- */
@media (max-width: 767px) {
  .work__row {
    display: block; position: relative;
    height: 20rem;
  }
  .work__row > .work__card {
    position: absolute; inset-inline: 0; bottom: 0;
    transform-origin: 50% 0%;
    touch-action: pan-y;            /* the page still scrolls vertically */
    will-change: transform;
  }
  .work__row > .work__card:hover { transform: none; }   /* the deck owns transform */
  .work__media { box-shadow: 0 30px 60px -32px rgba(0, 0, 0, 0.9); }
}

.work__controls {
  display: flex; align-items: center; justify-content: center;
  gap: 1.5rem; margin-top: 2rem;
}
.work__nav {
  display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem; border-radius: 9999px;
  border: 1px solid var(--line); background: none; color: var(--muted);
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}
.work__nav:hover { color: var(--fg); border-color: color-mix(in srgb, var(--accent-text) 50%, transparent); }
.work__nav svg { width: 1.125rem; height: 1.125rem; }
.work__img { display: block; }
@media (min-width: 768px) { .work__controls { display: none; } }

@media (prefers-reduced-motion: reduce) {
  .work__card, .work__media img, .work__arrow, .work__pill, .work__tag { transition: none; }
  /* never hidden behind motion */
  .work__arrow, .work__tag { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   Hero — sticky backdrop, two scroll beats
   The gradient and the contour field hold still at 100svh while the headline
   beat and the statement beat scroll over them.
   --------------------------------------------------------------------------- */

.hero { position: relative; min-height: 145svh; }

.hero__backdrop {
  position: sticky; top: 0;
  height: 100svh;
  margin-bottom: -100svh;        /* the beats sit over it */
  overflow: hidden;
  z-index: 0;
  pointer-events: none;
}
.hero__backdrop::after {
  content: "";
  position: absolute; inset-inline: 0; bottom: 0; height: 30%;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--bg) 94%);
}

.hero__beat1 {
  position: relative; z-index: 1;
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: flex-end;
  padding-bottom: 2.5rem;
}
.hero__beat2 {
  position: relative; z-index: 1;
  min-height: 45svh;
  display: flex; align-items: center;
  padding-block: 3rem 6rem;
}

/* the dusk palette, sampled from the hero video this replaced */
:root {
  --dusk-1: #457cc7;
  --dusk-2: #6a96dd;
  --dusk-3: #c2a7d4;
  --dusk-4: #f4bdbe;
  --dusk-5: #32456e;
}
.hero__wash {
  position: absolute; inset: -12%; pointer-events: none;
  background:
    radial-gradient(46% 40% at 26% 22%, color-mix(in srgb, var(--dusk-1) 55%, transparent), transparent 70%),
    radial-gradient(40% 36% at 70% 32%, color-mix(in srgb, var(--dusk-2) 45%, transparent), transparent 72%),
    radial-gradient(44% 40% at 52% 58%, color-mix(in srgb, var(--dusk-3) 42%, transparent), transparent 70%),
    radial-gradient(34% 30% at 78% 66%, color-mix(in srgb, var(--dusk-4) 34%, transparent), transparent 70%),
    radial-gradient(60% 50% at 40% 92%, color-mix(in srgb, var(--dusk-5) 60%, transparent), transparent 74%);
  filter: blur(26px); opacity: 0.72; will-change: transform;
}
:root[data-theme="light"] .hero__wash { opacity: 0.45; }

/* contour field — drawn everywhere, shown only around the cursor */
.topo {
  position: absolute; inset: 0; pointer-events: none;
  opacity: 0; filter: blur(0.3px);
  transition: opacity 0.5s var(--ease-out-quint);
  -webkit-mask-image: radial-gradient(circle var(--spot, 280px) at var(--mx, 50%) var(--my, 50%),
                      #000 0%, rgba(0,0,0,0.55) 45%, transparent 72%);
  mask-image: radial-gradient(circle var(--spot, 280px) at var(--mx, 50%) var(--my, 50%),
              #000 0%, rgba(0,0,0,0.55) 45%, transparent 72%);
}
.hero.is-lit .topo { opacity: 1; }

/* headline — behind the portrait */
.hero__name {
  position: absolute; inset-inline: 0; top: 16%; z-index: 2;
  margin: 0; text-align: center; white-space: nowrap;
  will-change: transform;
  transition: filter 0.45s var(--ease-out-quint);
}
.hero__name:hover { filter: brightness(1.12) saturate(1.06); }
.hero__line {
  display: block; overflow: hidden;
  padding-bottom: 0.08em; margin-bottom: -0.08em;
  font-family: var(--font-display);
  font-weight: 500; text-transform: uppercase; line-height: 0.95;
  font-size: clamp(4rem, 20vw, 18rem);
}
.hero__line.is-open { overflow: visible; }
.hero__word { display: inline-block; }
.hero__word + .hero__word { margin-left: 0.22em; }
.hero__letter { display: inline-block; transform: translateY(115%); will-change: transform; }
.hero.is-ready .hero__letter {
  animation: letter-rise 0.7s var(--ease-out-quint) forwards;
  animation-delay: var(--d, 0s);
}
.hero__line.is-open .hero__letter {
  animation: none; transform: none;
  transition: transform 0.25s var(--ease-out-quint);
}
.hero__line.is-open .hero__letter:hover { transform: translateY(-4%) scale(1.16); }
.hero__word--gradient .hero__letter {
  background: linear-gradient(to bottom, var(--accent-text), var(--accent) 50%, rgba(108, 92, 231, 0.7));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* portrait — in front of the headline */
.hero__photo {
  position: relative; z-index: 3;
  height: clamp(21rem, 40vw, 36rem);
  margin: 0 auto;
  display: flex; justify-content: center; align-items: flex-end;
  will-change: transform;
}
.hero__photo img {
  width: auto; height: 100%; max-width: 100%;
  object-fit: contain; object-position: bottom center;
  -webkit-mask-image: linear-gradient(to bottom, #000 54%, rgba(0,0,0,0.55) 78%, transparent 97%);
  mask-image: linear-gradient(to bottom, #000 54%, rgba(0,0,0,0.55) 78%, transparent 97%);
}

/* the sector tags sit under the paragraph in the second beat */
.hero__beat2 .tags {
  margin-top: 1.5rem;
  display: flex; flex-wrap: wrap; gap: 0.5rem;
}
.hero__beat2 .tags span {
  font-size: 0.8125rem; padding: 0.4rem 0.85rem; border-radius: 9999px;
  border: 1px solid var(--line);
  color: color-mix(in srgb, var(--fg) 82%, transparent);
  transition: color 0.25s var(--ease-out-quint), border-color 0.25s var(--ease-out-quint);
}
.hero__beat2 .tags span:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--accent-text) 55%, transparent);
}

/* --- Mobile: the headline centres and the portrait anchors the foot -------
   On a phone the hero is tall and narrow, so a headline pinned near the top
   leaves a void between it and the portrait. ------------------------------ */
@media (max-width: 767px) {
  .hero__name {
    /* high in the frame, so the portrait owns everything below it */
    top: 31%;
    /* the pointer parallax only runs on hover devices, so transform is free */
    transform: translateY(-50%);
  }
  /* 24vw is the most it takes before the line reaches the screen edge */
  .hero__line { font-size: clamp(4rem, 24vw, 7rem); }

  .hero__photo {
    height: clamp(26rem, 86vw, 34rem);
    margin-top: auto;
  }

  .hero__beat1 { padding-bottom: 0.75rem; }
}

/* second beat */
.hero__statement {
  margin: 0;
  font-family: var(--font-body); font-weight: 600; letter-spacing: -0.02em;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
}
.hero__blurb {
  margin: 1.5rem 0 0; max-width: 46ch;
  font-size: 1.0625rem; line-height: 1.7;
  color: color-mix(in srgb, var(--fg) 90%, transparent);
}
.hero__credit { margin: 1.5rem 0 0; font-size: 0.875rem; color: var(--muted); }

/* splash */
.splash {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center; background: var(--bg);
  transition: opacity 0.7s ease, visibility 0s linear 0.7s;
}
.splash.is-done { opacity: 0; visibility: hidden; }
.splash__inner { text-align: center; }
.splash__name {
  margin: 0;
  font-family: var(--font-display); font-weight: 500;
  text-transform: uppercase; line-height: 0.9;
  font-size: clamp(2.75rem, 9vw, 7rem);
  background: linear-gradient(100deg, var(--fg), var(--accent-text) 55%, var(--accent));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  clip-path: inset(0 100% 0 0);
  animation: wipe 1.1s var(--ease-out-quint) 0.2s forwards;
}
@keyframes wipe { to { clip-path: inset(0 0 0 0); } }
.splash__role {
  margin: 0.75rem 0 0; font-size: clamp(0.8125rem, 1.6vw, 1rem);
  letter-spacing: 0.42em; text-transform: uppercase; color: var(--muted);
  opacity: 0; animation: splash-fade 0.7s ease 1.1s forwards;
}
@keyframes splash-fade { to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .splash__name, .splash__role { animation: none; opacity: 1; clip-path: none; }
  .topo { display: none; }
}

/* Decorative cursor ring — fine pointers only */
.cursor-ring {
  position: fixed;
  left: -12px;
  top: -12px;
  z-index: 30;
  width: 1.5rem;
  height: 1.5rem;
  border: 1px solid rgba(242, 241, 236, 0.6);
  border-radius: 9999px;
  mix-blend-mode: difference;
  pointer-events: none;
  opacity: 0;
  display: none;
  transition: opacity 0.25s ease-out, width 0.25s ease-out, height 0.25s ease-out;
}
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .cursor-ring { display: block; }
  .hero { cursor: none; }
}
.cursor-ring.is-active { opacity: 1; }
.cursor-ring.is-big { transform: scale(1.7); }


@keyframes letter-rise { to { transform: translateY(0); } }

/* ---------------------------------------------------------------------------
   About
   --------------------------------------------------------------------------- */

.split {
  display: grid;
  gap: 3.5rem;
}
@media (min-width: 1024px) {
  .split { grid-template-columns: 1fr 1.2fr; }
}

.prose p {
  font-weight: 300;
  line-height: 1.5;
  color: var(--muted);
}
.prose p + p { margin-top: 1.5rem; }
@media (min-width: 768px) {
  .prose p { font-size: 1.125rem; }
}

.philosophy {
  margin-top: 3rem;
  display: grid;
  gap: 1.5rem;
}
@media (min-width: 640px) {
  .philosophy { grid-template-columns: repeat(3, 1fr); }
}
.philosophy .reveal { height: 100%; }

.card {
  height: 100%;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
  background: var(--card);
  padding: 1.5rem;
}
.card h4 {
  font-family: var(--font-body);
  font-size: 1.125rem;
  letter-spacing: -0.02em;
}
.card p {
  margin-top: 0.75rem;
  font-size: 0.875rem;
  font-weight: 300;
  line-height: 1.5;
  color: var(--muted);
}

/* ---------------------------------------------------------------------------
   Capabilities filmstrip
   Large screens: the section pins for one viewport and vertical scroll pushes
   the card track sideways. Small screens: a plain vertical stack.
   --------------------------------------------------------------------------- */

.caps {
  position: relative;
  overflow-x: clip;
  border-top: 1px solid var(--line);
}

.caps__pin {
  display: flex;
  flex-direction: column;
  gap: 3rem;
  padding-block: var(--section-pad);
}

.caps__track {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding-inline: var(--gutter);
  will-change: transform;
}

.caps__card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.25rem;
  align-items: flex-start;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--card);
  padding: 1.5rem;
  transition: opacity 0.35s ease, transform 0.35s ease, border-color 0.35s ease;
}
@media (min-width: 768px) { .caps__card { padding: 1.75rem; } }

.caps__num {
  position: absolute;
  /* hangs off the corner and is clipped by the card edge — deliberate */
  top: -0.16em;
  inset-inline-end: -0.05em;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1;
  font-size: clamp(5rem, 9vw, 8rem);
  color: var(--fg);
  opacity: 0.1;
  pointer-events: none;
  transition: color 0.35s ease, opacity 0.35s ease;
}

.caps__card h3 {
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.caps__card p {
  margin-top: 0.5rem;
  max-width: 34ch;
  font-weight: 300;
  line-height: 1.5;
  color: var(--muted);
}

/* HUD — only visible in filmstrip mode */
.caps__hud { display: none; }

@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  .caps__pin {
    position: sticky;
    top: 0;
    height: 100svh;
    justify-content: space-between;
    gap: 0;
    padding-block: 5vh;
  }

  .caps__track {
    flex-direction: row;
    align-items: stretch;
    width: max-content;
  }

  .caps__card {
    height: min(42vh, 360px);
    width: clamp(280px, 42vw, 460px);
    flex-shrink: 0;
    opacity: 0.45;
  }
  .caps__card.is-active {
    opacity: 1;
    transform: translateY(-8px);
    border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  }
  .caps__card.is-active .caps__num {
    color: var(--accent-text);
    opacity: 0.16;
  }

  .caps__hud {
    display: flex;
    width: 100%;
    align-items: flex-end;
    gap: 2rem;
    padding-inline: var(--gutter);
  }
}

.caps__counter {
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1;
  color: var(--accent-text);
  font-variant-numeric: tabular-nums;
  font-size: clamp(2rem, 4vw, 3.25rem);
  white-space: nowrap;
}
.caps__counter span { color: var(--muted); }

.caps__bar {
  margin-bottom: 0.5rem;
  height: 2px;
  flex: 1;
  overflow: hidden;
  border-radius: 9999px;
  background: var(--line);
}
.caps__fill {
  height: 100%;
  width: 100%;
  transform-origin: left;
  transform: scaleX(var(--caps-progress, 0));
  background: var(--accent);
  will-change: transform;
}

.caps__scroll-hint {
  margin-bottom: 0.25rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  color: var(--muted);
  white-space: nowrap;
  transition: opacity 0.5s;
}
.caps__scroll-hint.is-hidden { opacity: 0; }

/* ---------------------------------------------------------------------------
   Experience — the credits
   Roles as end credits; hovering a row draws an outline, then sweeps the fill
   in from the left.
   --------------------------------------------------------------------------- */

.credits__head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 2rem; flex-wrap: wrap;
}
.credits__actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }

.btn {
  display: inline-flex; align-items: center; gap: 0.75rem;
  padding: 0.7rem 0.7rem 0.7rem 1.1rem; border-radius: 0.75rem;
  font-size: 0.9375rem; text-decoration: none; cursor: pointer;
  border: 1px solid var(--line); color: var(--fg); background: var(--card);
  transition: transform 0.25s var(--ease-out-quint);
}
.btn:hover { transform: translateY(-1px); }
.btn--primary {
  background: linear-gradient(120deg, var(--accent), #8b7bf0);
  border-color: transparent; color: #fff;
}
.btn span {
  display: grid; place-items: center; width: 1.75rem; height: 1.75rem;
  border-radius: 0.4rem; background: rgba(0, 0, 0, 0.18); font-size: 0.8rem;
}
.btn--primary span { background: rgba(0, 0, 0, 0.22); }

.reel {
  position: relative; margin-top: 2.5rem;
  border: 1px solid var(--line); border-radius: 1.5rem;
  background: radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 60%), var(--card);
  padding: 2.5rem 1.5rem; overflow: hidden;
}
@media (min-width: 768px) { .reel { padding: 3rem; } }

/* corner brackets, like a film frame */
.reel::before, .reel::after {
  content: ""; position: absolute; width: 2rem; height: 2rem;
  border: 1px solid color-mix(in srgb, var(--fg) 28%, transparent);
  pointer-events: none;
}
.reel::before { top: 1.25rem; left: 1.25rem; border-right: 0; border-bottom: 0; border-radius: 0.5rem 0 0 0; }
.reel::after { bottom: 1.25rem; right: 1.25rem; border-left: 0; border-top: 0; border-radius: 0 0 0.5rem 0; }

.reel__title { text-align: center; margin-top: 1rem; }
.reel__years {
  margin: 0;
  font-family: var(--font-heading); font-weight: 300; letter-spacing: -0.03em;
  font-size: clamp(1.75rem, 4.4vw, 3rem); line-height: 1.1;
}

.divider {
  display: flex; align-items: center; justify-content: center; gap: 1.25rem;
  margin: 3.5rem 0 2rem;
  font-size: 0.6875rem; letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--accent-text);
}
.divider::before, .divider::after {
  content: ""; height: 1px; width: min(9rem, 18vw);
  background: color-mix(in srgb, var(--accent) 45%, transparent);
}

.credit {
  position: relative; z-index: 0;
  display: grid; gap: 0.35rem 2rem; grid-template-columns: 1fr;
  padding: 1.1rem 1.5rem;
  transition: color 0.2s var(--ease-out-quint);
}
@media (min-width: 768px) { .credit { padding-inline: 2rem; } }
@media (min-width: 760px) {
  /* the pair sits around the centre line rather than spanning the full
     width — otherwise the role drifts to the far left of the panel */
  .credit {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    /* centred against each other: the role block is two lines and the name
       one, so a shared baseline leaves them looking misaligned */
    align-items: center;
    max-width: 52rem;
    margin-inline: auto;
    gap: 0.35rem 2.5rem;
  }
}
.credit__left { text-align: left; }
@media (min-width: 760px) { .credit__left { text-align: right; } }
.credit__role {
  margin: 0; font-size: 0.75rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--muted);
}
.credit__years {
  margin: 0.3rem 0 0; font-size: 0.75rem; letter-spacing: 0.16em;
  color: color-mix(in srgb, var(--fg) 55%, transparent);
  font-variant-numeric: tabular-nums;
}
.credit__name {
  margin: 0;
  font-family: var(--font-heading); font-weight: 300; letter-spacing: -0.02em;
  font-size: clamp(1.5rem, 3.2vw, 2.25rem); line-height: 1.1;
}
.credit__note {
  grid-column: 1 / -1; margin: 0;
  font-size: 0.9375rem; line-height: 1.5;
  max-height: 0; opacity: 0; overflow: hidden;
  transition: max-height 0.4s var(--ease-out-quint), opacity 0.3s var(--ease-out-quint),
              margin 0.4s var(--ease-out-quint);
}
@media (min-width: 760px) { .credit__note { text-align: center; } }

/* hover in two beats: the outline draws, then the fill sweeps from the left */
.credit::before, .credit::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 0.25rem; pointer-events: none;
}
.credit::before {
  z-index: -2; border: 1px solid var(--accent);
  opacity: 0; transition: opacity 0.18s var(--ease-out-quint) 0.06s;
}
.credit::after {
  z-index: -1; background: var(--accent);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 0.45s var(--ease-out-quint) 0.16s;
}
.credit:hover::before { opacity: 1; transition-delay: 0s; }
.credit:hover::after { transform: scaleX(1); }
.credit:hover { color: #0a0a0b; transition: color 0.25s var(--ease-out-quint) 0.22s; }
.credit:hover .credit__role,
.credit:hover .credit__years {
  color: rgba(10, 10, 11, 0.75);
  transition: color 0.25s var(--ease-out-quint) 0.22s;
}
.credit:hover .credit__note {
  max-height: 6rem; opacity: 1; margin-top: 0.6rem;
  color: rgba(10, 10, 11, 0.85);
  transition: max-height 0.4s var(--ease-out-quint) 0.2s, opacity 0.3s var(--ease-out-quint) 0.3s,
              margin 0.4s var(--ease-out-quint) 0.2s, color 0.25s var(--ease-out-quint) 0.22s;
}

.reel__foot {
  margin-top: 3.5rem; padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  display: flex; justify-content: center; gap: 1rem; flex-wrap: wrap;
  font-size: 0.6875rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--muted);
}

@media (prefers-reduced-motion: reduce) {
  .credit::before, .credit::after, .btn { transition: none; }
}

/* ---------------------------------------------------------------------------
   Contact
   --------------------------------------------------------------------------- */

.contact__links {
  margin-top: 2.5rem;
  display: grid;
  gap: 1rem;
  justify-items: start;
}

.form { display: grid; gap: 1.25rem; }
.form__pair { display: grid; gap: 1.25rem; }
@media (min-width: 640px) {
  .form__pair { grid-template-columns: 1fr 1fr; }
}
.form label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: 0.875rem;
  color: var(--muted);
}
.form input,
.form textarea {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: 0.5rem;
  background: var(--card);
  padding: 0.75rem 1rem;
  font-size: 1rem;
}
.form input:focus,
.form textarea:focus {
  border-color: var(--accent);
  outline: none;
}
.form textarea { resize: vertical; }

.form__sent {
  border: 1px solid rgba(108, 92, 231, 0.4);
  border-radius: 0.5rem;
  background: var(--card);
  padding: 1.5rem 1.25rem;
}

/* ---------------------------------------------------------------------------
   Closing block
   Contact and footer merged into one: a statement, the links, and the
   sign-off. Sits on the page's own surface with a violet glow rising from the
   bottom edge, so it reads as a close rather than a separate panel.
   --------------------------------------------------------------------------- */

.closing {
  position: relative;
  border-top: 1px solid var(--line);
  background:
    radial-gradient(85% 130% at 50% 100%, color-mix(in srgb, var(--accent) 20%, transparent), transparent 70%);
}

.closing__inner {
  padding-block: 4rem 2.5rem;
  text-align: center;
}
@media (min-width: 768px) {
  .closing__inner { padding-block: 8rem 3.5rem; }
}

.closing__statement {
  margin-inline: auto;
  /* the measure, not the font size, is what decides the line count — 34ch
     puts this statement on two lines and keeps it there */
  max-width: 34ch;
  font-family: var(--font-heading);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: 0;
  font-size: clamp(1.75rem, 6.4vw, 3.5rem);
  text-wrap: balance;
}

.grad-text {
  background: linear-gradient(to bottom right, var(--accent-text), var(--accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.closing__social {
  margin: 2.25rem auto 0;
  display: flex;
  justify-content: center;
  gap: 1rem;
}
.closing__social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.625rem;
  height: 2.625rem;
  border: 1px solid var(--line);
  border-radius: 9999px;
  color: var(--muted);
  transition: color 0.2s, border-color 0.2s, transform 0.25s var(--ease-out-quint);
}
.closing__social a:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--accent-text) 55%, transparent);
  transform: translateY(-2px);
}
.closing__social svg { width: 1.125rem; height: 1.125rem; }

.closing__rule {
  margin: 2.25rem auto 0;
  max-width: 56rem;
  border: 0;
  border-top: 1px solid var(--line);
}

.closing__note {
  margin-top: 2rem;
  font-size: 0.875rem;
  font-weight: 300;
  color: var(--muted);
}
.closing__meta {
  margin-top: 0.75rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--muted);
}

/* back to top — appears once you're past the first screen */
.to-top {
  position: fixed;
  inset-inline-end: 1.5rem;
  bottom: 1.5rem;
  z-index: 35;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.875rem;
  height: 2.875rem;
  border: 1px solid var(--line);
  border-radius: 9999px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(10px);
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity 0.3s, transform 0.3s var(--ease-out-quint), color 0.2s, border-color 0.2s;
}
.to-top.is-visible { opacity: 1; pointer-events: auto; transform: none; }
.to-top:hover { color: var(--fg); border-color: color-mix(in srgb, var(--accent-text) 55%, transparent); }
.to-top svg { width: 1.125rem; height: 1.125rem; }
@media (min-width: 768px) {
  .to-top { inset-inline-end: 2.5rem; bottom: 2.5rem; }
}

/* ---------------------------------------------------------------------------
   Case-study page
   Sized from the small screen up: the title's floor is 32px rather than 44,
   and the blocks use 3rem of vertical padding until there's room for 5.
   --------------------------------------------------------------------------- */

.cs-main { padding-top: 4rem; }

/* .cs-layout is itself a padded container, so the containers nested inside it
   must not add a second inset — that doubled the gutter on phones */
.cs-sections .container { padding-inline: 0; }

.cs-back {
  position: sticky;
  top: 4rem;
  z-index: 30;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: blur(12px);
}
.cs-back .container { padding-block: 0.75rem; }
.cs-back a {
  font-size: 0.875rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s;
}
.cs-back a:hover { color: var(--fg); }

.cs-header { padding-block: 3rem; }
@media (min-width: 768px) { .cs-header { padding-block: 6rem; } }

.cs-header__tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
}

.badge {
  border: 1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-radius: 9999px;
  padding: 0.3rem 0.85rem;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--accent-text);
}

.cs-title {
  margin-top: 1.25rem;
  font-size: clamp(1.875rem, 7vw, 4rem);
  line-height: 1.12;
  text-wrap: balance;
}
.cs-subtitle {
  margin-top: 1.25rem;
  max-width: 42rem;
  font-size: 1.0625rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--muted);
}
@media (min-width: 768px) {
  .cs-title { margin-top: 1.5rem; }
  .cs-subtitle { margin-top: 1.5rem; font-size: 1.125rem; }
}

.cs-meta {
  margin-top: 2rem;
  display: grid;
  gap: 1.25rem;
  max-width: 42rem;
}
@media (min-width: 640px) { .cs-meta { grid-template-columns: 1fr 1fr; gap: 1.5rem; } }
.cs-meta dt {
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.28em;
  color: var(--accent-text);
}
.cs-meta dd {
  margin: 0.5rem 0 0;
  font-size: 0.875rem;
  font-weight: 300;
  line-height: 1.6;
  color: var(--muted);
}

.cs-block {
  border-top: 1px solid var(--line);
  padding-block: 3rem;
}
@media (min-width: 768px) { .cs-block { padding-block: 5rem; } }

.cs-block .eyebrow { margin-bottom: 1rem; }
.cs-block__title {
  font-size: clamp(1.5rem, 6vw, 2.125rem);
  line-height: 1.2;
  text-wrap: balance;
}
.cs-block__body { margin-top: 1.5rem; }
@media (min-width: 768px) { .cs-block__body { margin-top: 2.5rem; } }

.grid-2, .grid-3 { display: grid; gap: 2rem; }
@media (min-width: 768px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); gap: 2.5rem; }
  .grid-3 { grid-template-columns: repeat(3, 1fr); gap: 2.5rem; }
}

.field h3,
.dashlist h3 {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.field p {
  margin-top: 0.5rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--muted);
}

.dashlist ul { margin-top: 1rem; display: grid; gap: 0.75rem; }
.dashlist li {
  display: flex;
  gap: 0.75rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--muted);
}
.dashlist li::before {
  content: "—";
  color: var(--accent-text);
  flex-shrink: 0;
}

.cs-next {
  display: block;
  border-top: 1px solid var(--line);
  padding-block: 3rem;
  text-decoration: none;
  transition: background-color 0.2s;
}
@media (min-width: 768px) { .cs-next { padding-block: 5rem; } }
.cs-next:hover { background: var(--card); }
.cs-next p:last-child {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.5rem;
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(1.75rem, 6.4vw, 3rem);
  text-wrap: balance;
}
.cs-next span {
  color: var(--muted);
  transition: transform 0.3s;
}
.cs-next:hover span { transform: translateX(0.5rem); }

/* ---------------------------------------------------------------------------
   Case study — tags, prose, full-width media, and gap markers
   --------------------------------------------------------------------------- */

.cs-tags {
  margin-top: 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.cs-tags li {
  border: 1px solid var(--line);
  border-radius: 9999px;
  padding: 0.3rem 0.85rem;
  font-size: 0.75rem;
  color: var(--muted);
}

.cs-prose {
  max-width: 62ch;
}
.cs-prose p {
  font-weight: 300;
  line-height: 1.5;
  color: var(--muted);
}
.cs-prose p + p { margin-top: 1.25rem; }
@media (min-width: 768px) {
  .cs-prose p { font-size: 1.0625rem; line-height: 1.75; }
}
.cs-prose + .cs-prose { margin-top: 2.5rem; }

.cs-media {
  margin-top: 2.5rem;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
}
.cs-header .cs-media { margin-top: 2.5rem; }
@media (min-width: 768px) { .cs-header .cs-media { margin-top: 3.5rem; } }

/* [Bracketed gaps] — visible while drafting, delete this rule to hide them */
.gap {
  background: rgba(108, 92, 231, 0.16);
  color: var(--accent-text);
  border-radius: 3px;
  padding: 0 0.15em;
}

/* ---------------------------------------------------------------------------
   Screen galleries
   A stage panel holds one or more shots. Desktop shots get a browser frame,
   mobile shots get a device frame — so individual frame exports can be dropped
   in without compositing anything beforehand.
   --------------------------------------------------------------------------- */

.stage {
  margin-top: 3rem;
  border: 1px solid var(--line);
  border-radius: 1.25rem;
  padding: clamp(1.25rem, 4vw, 3rem);
  background:
    radial-gradient(120% 100% at 78% 0%, color-mix(in srgb, var(--accent) 18%, transparent), transparent 62%),
    linear-gradient(180deg, color-mix(in srgb, var(--card) 92%, var(--bg)), var(--bg));
}

.stage__row {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
}

/* --- browser frame ----------------------------------------------------- */

.browser {
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  background: var(--card);
  box-shadow: 0 40px 80px -45px rgba(108, 92, 231, 0.55), 0 12px 30px -18px rgba(0, 0, 0, 0.8);
}
.browser__bar {
  display: flex;
  gap: 0.4rem;
  align-items: center;
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}
.browser__bar i {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 9999px;
  background: color-mix(in srgb, var(--fg) 22%, transparent);
}
.browser img {
  width: 100%;
  display: block;
  /* very tall screens crop rather than dominate the page */
  max-height: 44rem;
  object-fit: cover;
  object-position: top;
}

/* --- device frame ------------------------------------------------------ */

.phone {
  border: 9px solid #1b1b21;
  border-radius: 2.1rem;
  overflow: hidden;
  background: #1b1b21;
  box-shadow:
    0 0 0 1px rgba(242, 241, 236, 0.07),
    0 30px 60px -30px rgba(0, 0, 0, 0.9);
}
.phone img {
  display: block;
  width: 100%;
  aspect-ratio: 375 / 812;
  object-fit: cover;
  object-position: top;
  background: var(--card);
}

/* --- shots and captions ------------------------------------------------ */

.shot { margin: 0; min-width: 0; }
.shot figcaption {
  margin-top: 0.9rem;
  font-size: 0.8125rem;
  font-weight: 300;
  line-height: 1.5;
  color: var(--muted);
}
.shot--phone figcaption { text-align: center; }

/* --- phone row: staggered, scrollable on small screens ----------------- */

.stage--phone .stage__row {
  grid-auto-flow: column;
  grid-auto-columns: min(190px, 46vw);
  justify-content: start;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 0.5rem;
  scrollbar-width: none;
}
.stage--phone .stage__row::-webkit-scrollbar { display: none; }
.stage--phone .shot { scroll-snap-align: center; }

@media (min-width: 768px) {
  .stage--phone .stage__row {
    justify-content: center;
    overflow-x: visible;
    grid-auto-columns: minmax(0, 1fr);
  }
  /* a gentle stagger so a row of screens doesn't read as a spec sheet */
  .stage--phone .shot:nth-child(even) { transform: translateY(1.75rem); }
  .stage--phone .shot:nth-child(even) figcaption { margin-top: 0.9rem; }
}
@media (prefers-reduced-motion: reduce) {
  .stage--phone .shot:nth-child(even) { transform: none; }
}

/* --- desktop columns --------------------------------------------------- */

@media (min-width: 900px) {
  .stage--cols-2 .stage__row { grid-template-columns: repeat(2, 1fr); }
  .stage--cols-3 .stage__row { grid-template-columns: repeat(3, 1fr); }
  .stage--cols-2 .browser img,
  .stage--cols-3 .browser img { max-height: 22rem; }
}

.cs-header .stage { margin-top: 3.5rem; }



/* ---------------------------------------------------------------------------
   Off the clock — the personal grid under About
   --------------------------------------------------------------------------- */

.brewing {
  margin-top: 3.5rem;
  display: grid;
  gap: 2.5rem 2rem;
}
@media (min-width: 560px) { .brewing { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .brewing { grid-template-columns: repeat(3, 1fr); } }

.brewing__item { text-align: center; }
.brewing__item p {
  margin-top: 1rem;
  font-size: 0.9375rem;
  font-weight: 300;
  line-height: 1.65;
  color: var(--muted);
  text-wrap: pretty;
}
.brewing__item strong { color: var(--fg); font-weight: 500; }

/* Full-colour stickers sit on the page itself — no tile behind them, or the
   artwork ends up competing with its own container. A small alternating tilt
   keeps a row of six from lining up like a toolbar. */
.brewing__icon {
  display: inline-block;
  line-height: 0;
  transition: transform 0.35s var(--ease-out-quint), filter 0.35s;
}
.brewing__icon img {
  width: 5rem;
  height: 5rem;
  object-fit: contain;
}
@media (min-width: 900px) {
  .brewing__icon img { width: 5.5rem; height: 5.5rem; }
}

.brewing__item:nth-child(odd) .brewing__icon { transform: rotate(-5deg); }
.brewing__item:nth-child(even) .brewing__icon { transform: rotate(5deg); }

.brewing__item:hover .brewing__icon {
  transform: rotate(0deg) translateY(-4px) scale(1.06);
  filter: drop-shadow(0 12px 22px rgba(0, 0, 0, 0.55));
}

@media (prefers-reduced-motion: reduce) {
  .brewing__icon,
  .brewing__item:nth-child(odd) .brewing__icon,
  .brewing__item:nth-child(even) .brewing__icon { transform: none; transition: none; }
}

/* ---------------------------------------------------------------------------
   About
   One column. The body sits in muted grey so the bolded phrases carry the
   claims — promote a phrase by wrapping it in <strong>.
   --------------------------------------------------------------------------- */

.about-body { max-width: 56rem; }

/* Two columns, and the portrait's baseline lands on the Sectors rule rather
   than the section floor — Sectors is a row of the grid, not part of the text
   column, so row 1 ends exactly where that rule begins. */
.about-grid {
  display: grid;
  gap: 3rem;
  grid-template-areas:
    "body"
    "portrait"
    "sectors";
}
.about-body { grid-area: body; }
.about-portrait { grid-area: portrait; }
.about-sectors { grid-area: sectors; }

@media (min-width: 1100px) {
  .about-grid {
    grid-template-columns: minmax(0, 1fr) clamp(15rem, 27vw, 27rem);
    grid-template-areas:
      "body portrait"
      "sectors .";
    column-gap: 1rem;
    /* no row gap: the Sectors rule then sits directly on the bottom of row 1,
       so the photo's base lands exactly on the line. The breathing room the
       gap used to give the text is a margin on the text column instead. */
    row-gap: 0;
    align-items: end;
  }
  .about-body { margin-bottom: 2.5rem; }
}

.about-portrait {
  margin: 0;
  align-self: end;
}
.about-portrait img {
  width: 100%;
  height: auto;
  display: block;
  /* nudged against the scroll — see main.js */
  transform: translateY(var(--portrait-shift, 0px));
  will-change: transform;

  /* fade the base into the page instead of cutting it off on the rule */
  -webkit-mask-image: linear-gradient(to bottom, #000 62%, rgba(0, 0, 0, 0.35) 85%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 62%, rgba(0, 0, 0, 0.35) 85%, transparent 100%);
}

@media (min-width: 1100px) {
  /* Extend past the container to the viewport edge. The 50% in a percentage
     margin resolves against this column, not the container, so the distance
     has to be worked out from the container's own max-width and gutter. */
  .about-portrait {
    /* The bleed is capped: without a limit it grows with the viewport, so on
       a wide screen the photo drifts to the far edge and leaves a void. -8rem
       is the most it will ever reach past the container. */
    margin-right: max(-8rem, calc(-1 * ((100vw - min(80rem, 100vw)) / 2 + var(--gutter))));
    /* measured from the reference: ~694px tall at a 1440 frame */
    height: clamp(24rem, 48vw, 44rem);
  }
  .about-portrait img {
    width: auto;
    max-width: 100%;
    height: 100%;
    object-fit: contain;
    /* anchored bottom right: base on the Sectors rule, flush to the edge */
    object-position: bottom right;
    margin-left: auto;
  }
}

@media (max-width: 1099px) {
  .about-portrait { max-width: 20rem; margin-inline: auto; }
}

/* --- restored: lede and paragraph rhythm --------------------------------- */

.about-lede {
  margin-top: 1rem;
  font-size: 1.25rem;
  font-weight: 300;
  line-height: 1.45;
  color: color-mix(in srgb, var(--fg) 88%, transparent);
}
@media (min-width: 768px) {
  .about-lede { font-size: 1.5rem; }
}

.about-prose { margin-top: 2.5rem; }
.about-prose p {
  font-size: 1.0625rem;
  font-weight: 300;
  line-height: 1.75;
  color: var(--muted);
  text-wrap: pretty;
}
.about-prose p + p { margin-top: 1.75rem; }
@media (min-width: 768px) {
  .about-prose p { font-size: 1.1875rem; }
}

/* Bold phrases are the skim path — hovering one draws its underline in */
.about-prose strong {
  color: var(--fg);
  font-weight: 500;
  background-image: linear-gradient(var(--accent-text), var(--accent-text));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1px;
  transition: background-size 0.45s var(--ease-out-quint), color 0.25s;
}
.about-prose strong:hover {
  color: var(--accent-text);
  background-size: 100% 1px;
}
@media (prefers-reduced-motion: reduce) {
  .about-prose strong { transition: none; }
}

.about-sectors {
  border-top: 1px solid var(--line);
  padding-top: 2rem;
}
.about-sectors__list {
  margin-top: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 0;
  font-size: 1.0625rem;
  font-weight: 300;
  color: rgba(242, 241, 236, 0.9);
}
.about-sectors__list span {
  transition: color 0.25s var(--ease-out-quint);
}
.about-sectors__list span:hover { color: var(--accent-text); }
/* the separators are decoration, so they live in CSS rather than the markup */
.about-sectors__list span + span::before {
  content: "\00b7";
  margin: 0 0.5rem;
  color: var(--line);
}

/* ---------------------------------------------------------------------------
   Case study — contents rail
   A sticky list of the sections beside the body, with the current one lit.
   Below 1100px there isn't room for it, so it's removed entirely — the page
   reads top to bottom without it.
   --------------------------------------------------------------------------- */

.cs-layout { display: block; }
.cs-toc { display: none; }

@media (min-width: 1100px) {
  .cs-layout {
    display: grid;
    grid-template-columns: 11rem minmax(0, 1fr);
    column-gap: 4rem;
    align-items: start;
  }
  @media (min-width: 1400px) {
    .cs-layout { grid-template-columns: 13rem minmax(0, 1fr); column-gap: 5rem; }
  }

  .cs-toc {
    display: block;
    position: sticky;
    top: 8.5rem;
  }
  .cs-toc ul { display: grid; gap: 0.7rem; }
  .cs-toc a {
    display: block;
    font-size: 0.9375rem;
    font-weight: 400;
    line-height: 1.3;
    color: color-mix(in srgb, var(--fg) 38%, transparent);
    text-decoration: none;
    transition: color 0.25s var(--ease-out-quint);
  }
  .cs-toc a:hover { color: color-mix(in srgb, var(--fg) 78%, transparent); }
  .cs-toc a.is-current { color: var(--accent-text); }

  /* the sections already sit in a narrow container — inside the layout the
     grid column does that job instead */
  .cs-sections .container { max-width: none; margin-inline: 0; }
  .cs-sections .cs-block:first-child { border-top: 0; padding-top: 0; }
}

/* ---------------------------------------------------------------------------
   Worked with
   A static row of logos, wrapping on narrow screens.
   --------------------------------------------------------------------------- */

.marquee {
  border-bottom: 1px solid var(--line);
  padding-block: 3.25rem;
}
@media (min-width: 768px) { .marquee { padding-block: 4.5rem; } }

/* the logos sit on a common centre line, so the row needs more breathing
   room than a line of text would */
.marquee__viewport {
  margin-top: 1.5rem;
  overflow: hidden;
  /* fade the ends so logos enter and leave rather than being clipped */
  mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}
@media (min-width: 768px) { .marquee__viewport { margin-top: 2rem; } }

.marquee__track {
  display: flex;
  flex-wrap: nowrap;
  width: max-content;
  align-items: center;
  gap: 3rem;
  animation: strip-slide var(--strip-duration, 50s) linear infinite;
}
@media (min-width: 768px) { .marquee__track { gap: 4.5rem; } }
.marquee:hover .marquee__track { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; flex-wrap: wrap; width: auto; }
  .marquee__viewport { mask-image: none; -webkit-mask-image: none; }
}

.marquee__item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  font-size: 1.0625rem;
  font-weight: 300;
  white-space: nowrap;
  color: color-mix(in srgb, var(--fg) 82%, transparent);
  transition: color 0.25s var(--ease-out-quint), opacity 0.25s;
}
@media (min-width: 768px) { .marquee__item { font-size: 1.25rem; } }
.marquee__item:hover { color: var(--accent-text); }

.marquee__item img {
  height: calc(var(--logo-h, 2rem) * var(--logo-scale, 0.82));
  width: auto;
  filter: brightness(0) invert(1);     /* any source colour becomes white */
  opacity: 0.72;
  transition: opacity 0.25s;
}
:root[data-theme="light"] .marquee__item img {
  filter: brightness(0);               /* and black on the light theme */
  opacity: 0.68;
}
.marquee__item:hover img { opacity: 1; }

@media (min-width: 768px) { .marquee__track { --logo-scale: 1; } }

.marquee__item[data-logo="tamm"] img { --logo-h: 2rem; }
.marquee__item[data-logo="pcfc-dubai"] img { --logo-h: 1.75rem; }
.marquee__item[data-logo="moj-saudi"] img { --logo-h: 2.375rem; }
.marquee__item[data-logo="najiz"] img { --logo-h: 2.5rem; }
.marquee__item[data-logo="shory"] img { --logo-h: 2.0625rem; }
.marquee__item[data-logo="slashdata"] img { --logo-h: 1.25rem; }
.marquee__item[data-logo="landmark-group"] img { --logo-h: 1.875rem; }

@media (prefers-reduced-motion: reduce) {
  .marquee__track { animation: none; }
  .marquee__viewport { overflow-x: auto; }
}



/* ---------------------------------------------------------------------------
   Ask-me widget
   Bubble bottom right, panel above it. The back-to-top button moves up to
   make room rather than overlapping.
   --------------------------------------------------------------------------- */

.ask {
  position: fixed;
  inset-inline-end: 1.25rem;
  bottom: 1.25rem;
  z-index: 45;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.75rem;
}
@media (min-width: 768px) {
  .ask { inset-inline-end: 2.5rem; bottom: 2.5rem; }
}

.ask__toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border: 1px solid color-mix(in srgb, var(--accent-text) 45%, transparent);
  border-radius: 9999px;
  background: color-mix(in srgb, var(--accent) 22%, var(--bg));
  backdrop-filter: blur(10px);
  color: var(--fg);
  cursor: pointer;
  box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.9);
  transition: transform 0.25s var(--ease-out-quint), background-color 0.25s;
}
.ask__toggle:hover { transform: translateY(-2px); }
.ask__toggle svg { width: 1.375rem; height: 1.375rem; }
.ask__icon-close { display: none; }
.ask.is-open .ask__icon-open { display: none; }
.ask.is-open .ask__icon-close { display: block; }

.ask__panel {
  width: min(22rem, calc(100vw - 2.5rem));
  max-height: min(30rem, calc(100vh - 8rem));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 1.25rem;
  background: var(--card);
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.95);
  animation: ask-in 0.25s var(--ease-out-quint) both;
}
@keyframes ask-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
}
@media (prefers-reduced-motion: reduce) {
  .ask__panel { animation: none; }
}

.ask__head {
  padding: 1.125rem 1.25rem 0.875rem;
  border-bottom: 1px solid var(--line);
}
.ask__title {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--fg);
}
.ask__sub {
  margin: 0.35rem 0 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--muted);
}

.ask__log {
  flex: 1;
  overflow-y: auto;
  padding: 1rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}

.ask__msg {
  max-width: 85%;
  padding: 0.625rem 0.875rem;
  border-radius: 0.875rem;
  font-size: 0.875rem;
  line-height: 1.55;
  white-space: pre-wrap;
}
.ask__msg--bot {
  align-self: flex-start;
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  color: color-mix(in srgb, var(--fg) 92%, transparent);
  border-end-start-radius: 0.25rem;
}
.ask__msg--user {
  align-self: flex-end;
  background: color-mix(in srgb, var(--accent) 30%, transparent);
  color: var(--fg);
  border-end-end-radius: 0.25rem;
}
.ask__msg.is-thinking { opacity: 0.6; letter-spacing: 0.15em; }

.ask__suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.25rem;
}
.ask__suggestions button {
  font: inherit;
  font-size: 0.75rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 9999px;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s;
}
.ask__suggestions button:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--accent-text) 50%, transparent);
}

.ask__form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem;
  border-top: 1px solid var(--line);
}
.ask__form input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: none;
  padding: 0.5rem;
  font-size: 0.875rem;
  color: var(--fg);
}
.ask__form input::placeholder { color: var(--muted); }
.ask__form input:focus { outline: none; }
.ask__form button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.125rem;
  height: 2.125rem;
  flex: 0 0 auto;
  border: 0;
  border-radius: 9999px;
  background: var(--accent);
  color: var(--fg);
  cursor: pointer;
}
.ask__form button svg { width: 1rem; height: 1rem; }



/* links the assistant returns, and the fixed row above the input */
.ask__msg a {
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.ask__msg a:hover { color: var(--fg); }

.ask__links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0 0.75rem 0.5rem;
}
.ask__links a {
  font-size: 0.75rem;
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--line);
  border-radius: 9999px;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s, border-color 0.2s;
}
.ask__links a:hover {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--accent-text) 50%, transparent);
}

/* ---------------------------------------------------------------------------
   Capability icons
   The SVGs are solid white shapes, so they're used as masks rather than
   images — that way the colour comes from CSS and follows the theme, the
   active state and the hover.
   --------------------------------------------------------------------------- */

.caps__icon {
  width: clamp(7rem, 11vw, 9rem);
  height: clamp(7rem, 11vw, 9rem);
  flex: 0 0 auto;
  display: block;

  /* the SVGs are inline and painted with currentColor — no mask, no external
     request, nothing for a browser to resolve differently once deployed */
  color: var(--muted);
  opacity: 0.45;
  transform: translateY(6px) scale(0.96);
  transition:
    color 0.4s var(--ease-out-quint),
    opacity 0.4s var(--ease-out-quint),
    transform 0.5s var(--ease-out-quint);
}

/* Light mode needs its own pair. The resting grey and the light accent sit at
   almost the same lightness, so the change between them was happening but
   barely visible — resting goes lighter, lit takes the stronger accent. */
:root[data-theme="light"] .caps__icon {
  color: color-mix(in srgb, var(--fg) 42%, transparent);
  opacity: 0.55;
}
:root[data-theme="light"] .caps__card:hover .caps__icon,
:root[data-theme="light"] .caps__card:focus-visible .caps__icon,
:root[data-theme="light"] .caps__card.is-active .caps__icon {
  color: var(--accent);
  opacity: 1;
}

/* the numeral too — near-invisible grey on a white card */
:root[data-theme="light"] .caps__card .caps__num { opacity: 0.1; }
:root[data-theme="light"] .caps__card.is-active .caps__num {
  color: var(--accent);
  opacity: 0.22;
}

/* lit when the card is the active one in the filmstrip, or on hover */
.caps__card:hover .caps__icon,
.caps__card:focus-visible .caps__icon,
.caps__card.is-active .caps__icon {
  color: var(--accent-text);
  opacity: 1;
  transform: none;
}

/* and the active one drifts, so the strip has something alive in it */
@media (prefers-reduced-motion: no-preference) {
  .caps__card.is-active .caps__icon { animation: caps-float 5s ease-in-out infinite 0.4s; }
}
@keyframes caps-float {
  50% { transform: translateY(-5px); }
}

/* the numeral steps back now that there's an icon carrying the card */
.caps__card .caps__num { opacity: 0.08; }
.caps__card.is-active .caps__num { opacity: 0.17; }

/* ---------------------------------------------------------------------------
   What I do — cards stack as you scroll
   Below the filmstrip breakpoint each card sticks a little lower than the one
   before it, so scrolling piles them up rather than replacing them. No swipe,
   no buttons — the page scroll is the interaction.
   --------------------------------------------------------------------------- */

.caps__controls { display: none; }

@media (max-width: 1023px) {
  .caps__track {
    display: flex;
    flex-direction: column;
    gap: 1.25rem;
    padding-inline: var(--gutter);
    /* room under the last card so it can reach its sticky position */
    padding-bottom: 6rem;
  }

  .caps__card {
    position: sticky;
    /* each one parks 0.75rem below the previous, leaving the stack visible */
    top: calc(5.5rem + (var(--i, 0) * 0.75rem));
    /* matches the Figma card: 256px tall, icon pinned top, text on the
       baseline. A floor plus space-between gives the deliberate gap — the
       earlier 19rem floor just made it a void. */
    min-height: 16rem;
    justify-content: space-between;
    gap: 1.25rem;
    background: var(--card);
    box-shadow: 0 -14px 40px -24px rgba(0, 0, 0, 0.9);
  }

  .caps__card:nth-child(1) { --i: 0; }
  .caps__card:nth-child(2) { --i: 1; }
  .caps__card:nth-child(3) { --i: 2; }
  .caps__card:nth-child(4) { --i: 3; }
  .caps__card:nth-child(5) { --i: 4; }
  .caps__card:nth-child(6) { --i: 5; }
  .caps__card:nth-child(7) { --i: 6; }
}

/* video behaves like a still in the device and browser frames */
.phone video,
.browser video {
  display: block;
  width: 100%;
  background: var(--card);
}
.phone video {
  aspect-ratio: 375 / 812;
  object-fit: cover;
}
video.cs-media {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
}

/* the section intro above the bento */
.process__head { max-width: 46rem; }

/* ---------------------------------------------------------------------------
   How I work — bento
   Film full width on top; below it the skills marquee takes the width it
   needs and the toolkit sits beside it as a logo grid.
   --------------------------------------------------------------------------- */

.bento { margin-top: 2.5rem; display: grid; gap: 1rem; }
@media (min-width: 900px) {
  .bento { margin-top: 3rem; grid-template-columns: minmax(0, 1fr) 15rem; }
  .bento__film { grid-column: span 2; }
  .bento__skills { grid-column: 1; }
  .bento__tools { grid-column: 2; }
}

.bento__film {
  position: relative;
  overflow: hidden;
  border-radius: 1.5rem;
  background: #000;
  aspect-ratio: 1.791;
}
@media (min-width: 768px) { .bento__film { border-radius: 2rem; } }
.bento__film wistia-player {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%;
}

.bento__tile {
  border-radius: 1.5rem;
  background: var(--card);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  overflow: hidden;
}
@media (min-width: 768px) { .bento__tile { border-radius: 2rem; padding: 1.75rem; } }

/* the tile labels are titles now, not eyebrows */
.bento__title {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: -0.02em;
  font-size: 1.125rem;
  color: var(--fg);
}

/* ---- both strips move ---- */
.skills,
.tools {
  margin-top: auto;
  overflow: hidden;
  /* fade the ends so things enter and leave rather than being cut */
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}

.skills__track,
.tools__track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  width: max-content;
  align-items: center;
  animation: strip-slide var(--strip-duration, 40s) linear infinite;
}
.bento__tile:hover .skills__track,
.bento__tile:hover .tools__track { animation-play-state: paused; }
@keyframes strip-slide { to { transform: translate3d(-50%, 0, 0); } }

@media (prefers-reduced-motion: reduce) {
  .skills__track, .tools__track { animation: none; flex-wrap: wrap; width: auto; }
  .skills, .tools { mask-image: none; -webkit-mask-image: none; }
}

.skills__track { gap: 0.625rem; }
.skills__track li {
  flex: 0 0 auto;
  font-size: 0.875rem;
  padding: 0.5rem 1rem;
  border-radius: 9999px;
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  color: var(--accent-text);
  white-space: nowrap;
}

/* ---- toolkit: logos only, monochrome, tighter and larger ---- */
.tools__track { gap: 1.125rem; }
/* The tools keep their own colours; hover just lifts them. */
.tool {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  transition: transform 0.3s var(--ease-out-quint), filter 0.3s var(--ease-out-quint);
}
.tool:hover,
.tool:focus-visible { transform: translateY(-2px); filter: brightness(1.08); }

.tool img { width: 2.25rem; height: 2.25rem; object-fit: contain; }
.tool__slot {
  width: 2.25rem; height: 2.25rem; border-radius: 0.5rem;
  border: 1px dashed color-mix(in srgb, var(--accent-text) 45%, transparent);
}
/* Two exceptions: these ship as flat black marks with no colour of their own,
   so on a dark tile they need inverting to be visible at all. */
.tool[data-tool="framer"] img,
.tool[data-tool="genspark"] img { filter: invert(1); }
:root[data-theme="light"] .tool[data-tool="framer"] img,
:root[data-theme="light"] .tool[data-tool="genspark"] img { filter: none; }
