/* ==========================================================================
   Design tokens — sourced from the Figma file "Portfolio website"
   ========================================================================== */
:root {
  --green: #59bf72;
  --pink: #ed83dd;
  --blue: #4b6ae4;
  --gray: #f1f1f1;
  --dark: #1e1e1e;
  --white: #ffffff;

  --ink: var(--dark);
  --muted: rgb(30 30 30 / 0.6);
  --line: rgb(30 30 30 / 0.12);

  --font-sans: "Figtree", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Layout — desktop frame is 1440 wide; content starts at x=160 */
  --frame-max: 1440px;
  --outer-gutter: clamp(12px, 2.8vw, 40px); /* dark band side margin */
  --inner-gutter: clamp(20px, 8.3vw, 120px); /* padding inside light container */
  --page-gutter: calc(var(--outer-gutter) + var(--inner-gutter)); /* = 160 at 1440 */
  --radius-lg: clamp(16px, 2vw, 24px);
  --header-h: 68px;
  --company-head-h: 88px; /* sticky company label in the Work section */
  --work-peek: 32px; /* how much of the dark Work section shows below the hero, above the
                        label's text (Figma 262:117823 shows only its rounded top) */

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

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

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

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

body {
  margin: 0;
  background: var(--gray);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 18px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

::selection {
  background: var(--blue);
  color: var(--white);
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

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

h1,
h2,
h3,
p {
  margin: 0;
}

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

.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 100;
  padding: 10px 16px;
  background: var(--dark);
  color: var(--white);
  border-radius: 8px;
}
.skip-link:focus {
  top: 16px;
}

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

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

/* ==========================================================================
   Header
   ========================================================================== */
/* Scrolls away with the page (not sticky). */
.site-header {
  background: var(--gray);
  /* Subtle stroke under the menu (Figma 285:17823: 1px #1e1e1e, inside; 10% here), drawn as an
     inset shadow so the header keeps its height. */
  box-shadow: inset 0 -1px 0 rgb(30 30 30 / 0.1);
}
/* Homepage: the header shares the hero's white background. */
body:has(.hero) .site-header,
body:has(.hero) main {
  background: var(--white); /* main: white behind the Work section's rounded top corners */
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-h);
}
.site-header__name {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
}
.site-header__flower {
  width: 20px;
  height: 20px;
}
/* One clockwise turn on hovering the name (js/common.js), with a slight playful overshoot. */
.site-header__flower.is-spinning {
  animation: flower-spin 0.6s cubic-bezier(0.34, 1.4, 0.64, 1);
}
@keyframes flower-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .site-header__flower.is-spinning {
    animation: none;
  }
}
.site-nav {
  display: flex;
  gap: clamp(20px, 3vw, 40px);
  font-size: 16px;
}
.site-nav a,
.site-header__name {
  position: relative;
  transition: color 0.2s ease;
}
.site-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.35s var(--ease-out);
}
.site-nav a:hover,
.site-nav a[aria-current="true"],
.site-header__name:hover {
  color: var(--blue);
}
.site-nav a:hover::after,
.site-nav a[aria-current="true"]::after {
  transform: scaleX(1);
  transform-origin: left;
}

/* ==========================================================================
   Hero
   ========================================================================== */
/* White, so the light Work section's rounded top stands out below it (Figma 1:76). */
.hero {
  background: var(--white);
  padding-block: clamp(40px, 5vw, 70px) clamp(64px, 6vw, 80px);
}
/* On desktop the hero fills the first screen so only the rounded top of the dark Work
   section peeks in above the fold — not the company name or dates (nav + hero + peek =
   viewport height). The content sits centred in that space. */
@media (min-width: 768px) and (min-height: 600px) {
  .hero {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: calc(100svh - var(--header-h) - var(--work-peek));
  }
}
.hero__title {
  max-width: 1040px;
  font-size: clamp(30px, 3.4vw, 48px);
  line-height: 1.458; /* 70 / 48 */
  font-weight: 400;
  letter-spacing: -0.005em;
}
.hero__hello {
  display: block;
  font-weight: 600;
}
/* The pink flower after "Hi, I'm Roni." On hover (desktop only) a pepper, a paint brush and
   a diamond fly out from behind it into a fan above the heading (Figma 264:119686) and run
   back into it when the pointer leaves. The motion lives in js/hero-burst.js; this is only
   the layout. Sizes are in em of the 48px heading. */
.hero__burst {
  position: relative;
  display: inline-block;
  margin-left: 0.21em; /* 10 / 48 */
  line-height: 0;
  vertical-align: -0.12em;
}
.hero__flower {
  position: relative;
  z-index: 1; /* the shapes start and end behind it */
  display: block;
  width: 0.833em; /* 40 / 48 */
  height: auto;
}
.hero__sparks {
  display: none;
}
@media (hover: hover) and (min-width: 768px) {
  .hero__sparks {
    display: block;
    position: absolute;
    left: 50%;
    top: 50%;
    pointer-events: none;
  }
  .hero__spark {
    position: absolute;
    left: 0;
    top: 0;
    width: 0.833em;
    height: auto;
    max-width: none;
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.4);
  }
}
.hero__accent {
  color: var(--blue);
}
/* Facts on the left, the green "scroll to Work" arrow on the right (centred on the
   container's edge, as in Figma). */
.hero__bottom {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}
.hero__arrow {
  flex: none;
  display: grid;
  place-items: center;
  margin-right: -22px;
  padding: 0;
  color: var(--green);
  transition: transform 0.3s var(--ease-out);
}
.hero__arrow svg {
  display: block;
  width: 45px;
  height: auto;
}
.hero__arrow:hover {
  transform: translateY(6px);
}
.hero__arrow:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 6px;
  border-radius: 4px;
}
@media (max-width: 767px) {
  .hero__arrow {
    margin-right: 0;
  }
  .hero__arrow svg {
    width: 32px;
  }
}
.hero__facts {
  margin: clamp(36px, 4vw, 56px) 0 0;
  padding: 0;
  list-style: none;
  font-family: var(--font-mono);
  font-size: clamp(13px, 1.1vw, 16px);
  line-height: 2;
}
.hero__facts li {
  display: flex;
  gap: 0.6em;
}
.hero__facts span[aria-hidden] {
  font-family: var(--font-sans);
}
/* Phones, like desktop: the hero fills the first screen and only the Work section's
   rounded top peeks in below it. The text stays centred (equal 1fr rows above and below),
   and the arrow sits halfway between the facts and the Work section. */
@media (max-width: 767px) {
  .hero {
    display: flex;
    flex-direction: column;
    min-height: calc(100svh - var(--header-h) - var(--work-peek));
    padding-bottom: 0;
  }
  .hero > .container {
    flex: 1;
    display: grid;
    /* The last row holds the arrow with at least 24px either side on short phones. */
    grid-template-rows: 1fr auto auto minmax(84px, 1fr);
  }
  .hero__title {
    grid-row: 2;
  }
  .hero__bottom {
    display: contents;
  }
  .hero__facts {
    grid-row: 3;
  }
  .hero__arrow {
    grid-row: 4;
    align-self: center;
    justify-self: end;
  }
}

/* ==========================================================================
   Work — company bands
   ========================================================================== */
/* Work: one solid light container with a rounded top (Figma 20:18906), no dark frame.
   On large screens a single company label sticks to the top of the screen and swaps its text
   as you reach each company (js/home.js), while every project panel sticks below it so the
   next one slides up over the previous one — pure CSS sticky, no scroll hijacking.
   Smaller screens and reduced motion get normal scrolling with inline company labels. */
.work {
  --gutter: 0px; /* no dark frame around the projects */
  --stick-top: var(--company-head-h); /* panels stick just below the company label */
  --panel-h: calc(100svh - var(--stick-top)); /* a project fills the space under the labels */
  --panel-pad-y: clamp(32px, 4.5vh, 56px);
  --work-radius: 40px; /* top corners of the Work section */
  --panel-radius: 40px; /* project panel corners */
  --hold: 55vh; /* scroll distance a project stays fully visible before the next slides over */
  /* Inner padding that lines the label and project content up with the site menu
     (.container: max 1440 wide, --page-gutter each side). Percentages resolve against the
     Work section's inner width, which is 2 × --gutter narrower than the page. */
  --work-pad-x: max(
    20px,
    max(0px, (100% + 2 * var(--gutter) - var(--frame-max)) / 2) + var(--page-gutter) - var(--gutter)
  );
  position: relative;
  z-index: 0;
  padding: 0 var(--gutter);
  background: var(--gray);
  border-radius: var(--work-radius) var(--work-radius) 0 0;
}
.work__stack {
  display: flow-root; /* keeps the panels' hold space inside (no margin collapse) */
}

/* Company label: shared sticky one (large screens) and inline ones (small screens). */
.work__head,
.company__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: var(--company-head-h);
  margin-inline: calc(-1 * var(--gutter));
  /* Lines up with the project text: percentages resolve against the container's inner width. */
  padding: 0 calc(var(--gutter) + var(--work-pad-x));
  background: var(--gray);
  color: var(--ink);
  font-size: 20px;
  line-height: 1.2;
}
.work__head {
  display: none;
  border-radius: var(--work-radius) var(--work-radius) 0 0;
  transition: border-radius 0.2s ease;
}
/* While the label is stuck under the nav its corners are square (set by js/home.js). */
.work.is-stuck .work__head {
  border-radius: 0;
}
/* Once the section fills the screen, a thin dark line (Figma 285:17757) separates the
   stuck label from the projects sliding beneath it. It draws in from left to right. */
.work__head::after {
  content: "";
  position: absolute;
  inset: auto 0 0;
  height: 1px;
  background: var(--dark); /* #1e1e1e */
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left;
  transition: opacity 0.3s ease, transform 0.8s var(--ease-out);
}
.work.is-stuck .work__head::after {
  opacity: 0.4;
  transform: scaleX(1);
}
.company__name {
  display: flex;
  align-items: center;
  font-weight: 600;
  font-size: inherit;
}
.company__logo {
  display: block;
  width: auto;
  filter: brightness(0); /* the wordmarks are white SVGs; black on the light section */
}
.company__years {
  font-family: var(--font-mono);
  font-weight: 400;
  white-space: nowrap;
}
.work__head-label {
  display: contents;
}
/* The new company name fades up into place when the label swaps. */
.work__head.is-swapping .company__name,
.work__head.is-swapping .company__years {
  animation: work-label-in 0.35s var(--ease-out);
}
@keyframes work-label-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* Project panel: opaque light gray so the one underneath never shows through. */
.project-row {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 420fr) minmax(0, 640fr);
  grid-template-areas: "text media";
  column-gap: clamp(40px, 5.6vw, 80px);
  align-items: center;
  padding: clamp(56px, 7vw, 100px) var(--work-pad-x);
  background: var(--gray);
}
.project-row--image-left {
  grid-template-columns: minmax(0, 640fr) minmax(0, 420fr);
  grid-template-areas: "media text";
}
.project-row__text {
  grid-area: text;
}
.project-row__media {
  grid-area: media;
}
/* Each company's projects read as one rounded container: round the top of its first
   panel and the bottom of its last one. */
.company__head + .project-row {
  border-top-left-radius: var(--panel-radius);
  border-top-right-radius: var(--panel-radius);
}
.project-row:has(+ .company__head),
.project-row:last-child {
  border-bottom-left-radius: var(--panel-radius);
  border-bottom-right-radius: var(--panel-radius);
}
.project-row__title {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.2;
}
.project-row__title a {
  transition: color 0.2s ease;
}
.project-row__title a:hover {
  color: var(--blue);
}
.project-row__desc {
  margin-top: 12px;
  font-size: 18px;
  line-height: 1.5;
}
.project-row .cta {
  margin-top: 24px;
}
.project-row__media {
  display: block;
  border-radius: 8px;
  transition: transform 0.6s var(--ease-out);
}
.project-row__media img {
  width: 100%;
  transition: transform 0.6s var(--ease-out);
}
.project-row__media:hover img,
.project-row:has(.cta:hover) .project-row__media img {
  transform: translateY(-6px);
}

/* One sticky company label (with its divider) at every screen size, where motion is welcome.
   On small screens the projects scroll normally beneath it and it swaps at each company
   (js/home.js). */
@media (prefers-reduced-motion: no-preference) {
  .work__head {
    display: flex;
    position: sticky;
    top: 0;
    z-index: 3;
    /* A sticky element keeps its margin box inside the Work section, so this margin makes the
       label let go one screen (less the label) early: as soon as About appears at the bottom
       of the screen, the label scrolls away with the last project instead of staying over
       About. On desktop that's exactly when the last project stops being stuck. The stack's
       negative margin cancels it out in the layout. */
    margin-bottom: var(--panel-h);
  }
  .work__stack {
    margin-top: calc(-1 * var(--panel-h));
  }
  /* The inline labels stay for screen readers but take no space. */
  .company__head {
    position: absolute;
    width: 1px;
    height: 1px;
    min-height: 0;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}

/* Stacked scrolling — only where there's room and motion is welcome. */
@media (min-width: 768px) and (min-height: 600px) and (prefers-reduced-motion: no-preference) {
  .project-row {
    position: sticky;
    top: var(--stick-top);
    height: var(--panel-h);
    padding-block: var(--panel-pad-y);
  }
  /* Stage 2 (hold): the next panel only starts to arrive after this much extra scroll.
     It's space above each later panel (not below each one), so a stuck panel never runs
     out of room in the stack and isn't pushed up while the last one slides in. */
  .project-row ~ .project-row {
    margin-top: var(--hold);
  }
  /* Every panel is a card with rounded top corners that slides over the one before;
     only the very last one is rounded at the bottom. */
  .project-row,
  .project-row:has(+ .company__head) {
    border-radius: var(--panel-radius) var(--panel-radius) 0 0;
  }
  /* The last project doesn't hold: once it reaches the top it scrolls away with About
     right below it (the panel fills the screen under the label, so About starts at the
     bottom edge and never covers it). */
  .project-row:last-child {
    border-radius: var(--panel-radius);
  }
  /* The whole composition always fits in the panel — scale the image down if needed. */
  .project-row__media {
    display: flex;
    justify-content: center;
  }
  .project-row__media img {
    width: auto;
    max-width: 100%;
    max-height: calc(var(--panel-h) - 2 * var(--panel-pad-y));
  }
}

/* "READ CASE STUDY" link — shared */
.cta {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  color: var(--blue);
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 16px;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
.cta__label {
  position: relative;
}
.cta__label::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease-out);
}
.cta__arrow {
  display: inline-block;
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 0.3s ease, transform 0.4s var(--ease-out);
}
.cta:hover .cta__label::after,
.cta:focus-visible .cta__label::after {
  transform: scaleX(1);
  transform-origin: left;
}
.cta:hover .cta__arrow,
.cta:focus-visible .cta__arrow {
  opacity: 1;
  transform: translateX(0);
}
/* Long SVG arrow (homepage "Read case study", case-study Back / Next): always visible,
   nudges in its direction on hover. Back flips it to point left. */
.cta--arrow {
  gap: 0.5em;
}
.cta--arrow .cta__arrow {
  opacity: 1;
  transform: none;
}
.cta--arrow .cta__arrow svg {
  display: block;
  width: 1em;
  height: auto;
}
.cta--arrow:hover .cta__arrow,
.cta--arrow:focus-visible .cta__arrow {
  transform: translateX(4px);
}
.cta--back .cta__arrow svg {
  transform: scaleX(-1);
}
.cta--back:hover .cta__arrow,
.cta--back:focus-visible .cta__arrow {
  transform: translateX(-4px);
}

/* ==========================================================================
   About (dark, per Figma)
   ========================================================================== */
.about {
  background: var(--dark);
  color: var(--white);
  padding-block: clamp(72px, 7vw, 100px);
}
.about__text {
  max-width: 1120px;
  font-size: clamp(22px, 2.8vw, 40px);
  line-height: 1.5; /* 60 / 40 */
}
.about__text p + p {
  margin-top: 1.5em;
}

/* ==========================================================================
   Contact footer
   ========================================================================== */
.contact {
  background: var(--gray);
  padding-block: clamp(48px, 5vw, 72px);
}
.contact__title {
  font-size: clamp(32px, 3.4vw, 48px);
  font-weight: 400;
  line-height: 1.458;
}
.contact__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 32px clamp(48px, 12vw, 180px);
  margin-top: clamp(32px, 3.9vw, 56px);
}
.contact__item {
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: clamp(18px, 1.7vw, 24px);
}
.contact__label {
  font-weight: 700;
}
.contact__link {
  position: relative;
  align-self: flex-start;
  transition: color 0.2s ease;
}
.contact__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease-out);
}
.contact__link:hover {
  color: var(--blue);
}
.contact__link:hover::after {
  transform: scaleX(1);
  transform-origin: left;
}
.contact__missing {
  color: var(--muted);
  font-style: italic;
}

/* ==========================================================================
   Case study — Figma "Beeline" frame (white page, 1200 content, 699 text column)
   ========================================================================== */
.page-case-study {
  --page-bg: var(--white);
  --panel: var(--gray); /* image containers in the case-study frames */
  --cs-gap: clamp(104px, 12.5vw, 180px); /* vertical rhythm between sections */
  background: var(--page-bg);
}
.page-case-study .site-header {
  background: var(--page-bg);
}

/* CaseStudyNavigation */
.cs-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 32px;
}
.cs-nav--top {
  padding-top: clamp(16px, 2.5vw, 32px);
}
.cs-nav--bottom {
  justify-content: flex-start;
  padding-block: clamp(120px, 12vw, 180px) clamp(96px, 10vw, 140px);
}
.cs-nav--split {
  justify-content: space-between;
}
/* Back / Next read as written ("Back: New Home"), not in the shared CTA's all caps. */
.cs-nav .cta {
  text-transform: none;
}
/* Phones: just "Back" / "Next" (the project name is hidden; see ctaLink's suffix). */
@media (max-width: 767px) {
  .cs-nav .cta__suffix {
    display: none;
  }
}

/* CaseStudyLayout */
.cs-body {
  display: flex;
  flex-direction: column;
  gap: var(--cs-gap);
  padding-top: clamp(56px, 7vw, 100px);
}
/* Two text sections in a row sit a little closer (160 vs 180). */
.cs-text + .cs-text {
  margin-top: calc(min(160px, var(--cs-gap) - 20px) - var(--cs-gap));
}

/* Shared two-column grid: section title left, 699px text column right. */
.cs-grid2 {
  display: grid;
  /* The title column never gets narrower than its longest word (e.g. "HoneyBook" at 48px). */
  grid-template-columns: minmax(min-content, 1fr) minmax(0, 699px);
  column-gap: 32px;
  align-items: start;
}
.cs-grid2 > :first-child {
  min-width: 180px;
}
.cs-title {
  font-size: 32px;
  font-weight: 600;
  line-height: 1.2;
}
.cs-copy {
  font-size: 18px;
  line-height: 1.5;
}
.cs-copy p + p {
  margin-top: 1.2em;
}

/* CaseStudyIntro */
.cs-intro .cs-title {
  font-size: 48px;
}

/* Intro: the title takes its natural width (wrapping only when space runs out), the
   intro text sits at the right edge at up to 600px wide, with at least 96px between. */
.cs-grid2.cs-intro {
  grid-template-columns: auto minmax(min(100%, 420px), 600px);
  justify-content: space-between;
  column-gap: 96px;
}
/* Below 1024px there isn't room for that gap: use the regular two-column split. */
@media (max-width: 1023px) {
  .cs-grid2.cs-intro {
    grid-template-columns: minmax(min-content, 1fr) minmax(0, 699px);
    justify-content: normal;
    column-gap: 32px;
  }
}
.cs-title__word {
  white-space: nowrap;
}
/* The company the project was made at: smaller and in the secondary text color. */
.cs-intro__subtitle {
  margin-top: 12px;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 18px;
  line-height: 1.3;
}

/* CaseStudyTextSection with media in the right column */
.cs-text--media {
  align-items: center;
}
.cs-text--media .cs-copy {
  max-width: 403px;
  margin-top: 24px;
}

/* CaseStudyImage */
.cs-image {
  margin: 0;
}
.cs-image img {
  width: 100%;
}
.cs-image--center {
  justify-self: center;
  width: 100%;
  max-width: 687px;
  margin-inline: auto;
}
.cs-panel {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: var(--panel);
  border-radius: 32px;
}
.cs-panel__label {
  font-size: 16px;
  font-weight: 600;
  line-height: 1.2;
}
.cs-panel--labelled {
  gap: 28px;
  padding: 29px 24px 56px;
}
.cs-panel--labelled .cs-zoom {
  width: 74.4%; /* 511 / 687 */
}
.cs-panel--phone {
  padding: 43px 24px;
}
.cs-panel--phone .cs-zoom {
  width: 41.8%; /* 287 / 687 */
}
.cs-panel--phone .cs-phone,
.cs-panel--phone .cs-zoom--video {
  width: 50.2%; /* 20% larger than the 287px Figma phone: 344 / 687 */
}
.cs-zoom--video .cs-phone {
  width: 100%;
}
/* Thin phone bezel for raw screen recordings. */
.cs-phone {
  --phone-radius: clamp(22px, 2.8vw, 40px);
  --bezel: 5px;
  padding: var(--bezel);
  background: #0b0b0d;
  border-radius: var(--phone-radius);
}
.cs-phone video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--phone-radius) - var(--bezel));
  background: var(--white);
}

/* CaseStudyImage — wide panel: full content width, label above a centred screenshot */
.cs-panel--wide {
  gap: 40px;
  padding: 40px 24px;
}
.cs-panel--wide .cs-zoom,
.cs-panel--wide > video,
.cs-panel--wide > .cs-video {
  width: 66.7%; /* 800 / 1200 */
}
/* Screen recordings have square corners with white rounding baked in — clip them to match
   the screenshots' own rounded window corners. */
.cs-panel--wide > video,
.cs-panel--wide .cs-zoom--video > video,
.cs-panel--wide .cs-video video {
  display: block;
  height: auto;
  border-radius: 1.2% / 2.2%;
}

/* CaseStudyVideo — inline product demo with a discreet pause/play button */
.cs-video {
  position: relative;
}
.cs-video video {
  width: 100%;
}
.cs-panel--wide .cs-video > .cs-zoom {
  width: 100%;
}
.cs-zoom--video video {
  display: block;
  width: 100%;
  height: auto;
}
.cs-video__toggle {
  position: absolute;
  right: 12px;
  bottom: 12px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(30 30 30 / 0.72);
  color: var(--white);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.2s ease, background-color 0.2s ease;
}
.cs-video__toggle svg {
  width: 14px;
  height: 14px;
}
.cs-video__toggle:hover {
  background: rgb(30 30 30 / 0.88);
}
/* Shown on hover/focus, whenever it's paused, and always on touch screens. */
.cs-video:hover .cs-video__toggle,
.cs-video__toggle:focus-visible,
.cs-video:not(.is-playing) .cs-video__toggle {
  opacity: 1;
}
@media (hover: none) {
  .cs-video__toggle {
    opacity: 1;
  }
}
.cs-video.is-playing .cs-video__icon--play,
.cs-video:not(.is-playing) .cs-video__icon--pause {
  display: none;
}
.cs-video__icon {
  display: grid;
}
.cs-image--wide + .cs-image--wide {
  margin-top: calc(84px - var(--cs-gap));
}

/* Image buttons — every case-study image opens in the lightbox (js/case-study/lightbox.js). */
.cs-zoom {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}
.cs-zoom img {
  width: 100%;
}
.cs-zoom__icon {
  position: absolute;
  top: 12px;
  right: 12px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgb(30 30 30 / 0.72);
  color: var(--white);
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 0.2s ease, transform 0.2s var(--ease-out);
  pointer-events: none;
}
.cs-zoom__icon svg {
  width: 14px;
  height: 14px;
}
.cs-zoom:hover .cs-zoom__icon,
.cs-zoom:focus-visible .cs-zoom__icon {
  opacity: 1;
  transform: none;
}
@media (hover: none) {
  .cs-zoom__icon {
    display: none;
  }
}

/* CaseStudyTextSection — "balanced": wider text beside a narrower image (546 / 496 in Figma) */
.cs-text--media.cs-text--balanced {
  grid-template-columns: minmax(0, 546fr) minmax(0, 496fr);
  column-gap: clamp(40px, 7.4vw, 107px);
}
.cs-text--balanced .cs-copy {
  max-width: none;
}

/* CaseStudyPanelGallery — labelled images in one gray panel (300 wide, 60 apart in Figma) */
.cs-panel-grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 32px var(--panel-grid-gap, 5.9%);
  width: 100%;
  max-width: var(--panel-grid-max, 1020px);
}
.cs-panel-grid__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
}
.cs-panel--wide .cs-panel-grid .cs-zoom {
  width: 100%;
}
.cs-gallery + .cs-image--wide {
  margin-top: calc(84px - var(--cs-gap));
}

/* imageStroke: a 3px black outline for screenshots exported without one. The radius follows
   the screenshots' own rounded corners (≈1.4% of the width, 2.2% of the height) so it fits
   on the page and at any size in the lightbox. */
.cs-stroke-images .cs-zoom img,
.cs-stroke-images .lightbox__img {
  border: 3px solid #000;
  border-radius: calc(1.4% + 3px) / calc(2.2% + 3px);
}

/* CaseStudyImageGallery — row of phone screens */
.cs-gallery {
  display: grid;
  grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr));
  column-gap: var(--gallery-gap, 6.75%); /* default 81 / 1200 */
  row-gap: 32px;
}
.cs-gallery img {
  width: 100%;
}
/* `widths`: columns follow each screen's Figma width; the row is centred at its total width. */
.cs-gallery--sized {
  grid-template-columns: var(--gallery-cols);
  width: 100%;
  max-width: var(--gallery-max);
  margin-inline: auto;
  align-items: start;
}

/* CaseStudyComparison — before → after */
.cs-compare {
  display: grid;
  grid-template-columns: minmax(0, 503fr) minmax(48px, 102px) minmax(0, 503fr);
  column-gap: clamp(16px, 3.8vw, 46px);
  align-items: center;
  padding-block: clamp(0px, 4.6vw, 66px);
}
.cs-compare img {
  width: 100%;
}
.cs-compare__arrow {
  width: 100%;
  height: auto;
  color: var(--ink);
}

/* Minimal page for case studies that aren't written yet */
.cs-soon {
  color: var(--muted);
}

/* ==========================================================================
   ImageLightbox
   ========================================================================== */
html.lightbox-open {
  overflow: hidden;
}
html.lightbox-open body {
  padding-right: var(--scrollbar-gap, 0px);
}
.lightbox {
  /* Space around the image; never less than the controls need. */
  --lb-pad-y: max(clamp(16px, 4vw, 72px), 68px);
  --lb-pad-x: max(clamp(16px, 4vw, 72px), 76px);
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  background: rgb(241 241 241 / 0.98); /* light gray token; just enough to hint at the page */
  opacity: 0;
  transition: opacity 0.22s ease;
}
.lightbox[hidden] {
  display: none;
}
.lightbox.is-open {
  opacity: 1;
}
.lightbox__stage {
  display: grid;
  place-items: center;
  padding: var(--lb-pad-y) var(--lb-pad-x);
  min-height: 0;
}
.lightbox--single {
  --lb-pad-x: clamp(16px, 4vw, 72px);
}
.lightbox__img {
  max-width: 100%;
  max-height: calc(100dvh - 2 * var(--lb-pad-y));
  width: auto;
  height: auto;
  object-fit: contain; /* screenshots carry their own frames and corners */
  cursor: default;
  transform: scale(0.96);
  transition: transform 0.22s var(--ease-out);
}
.lightbox.is-open .lightbox__img {
  transform: none;
}
/* Videos: the frame holds the player (and the phone bezel for phone recordings). */
.lightbox__frame {
  display: none;
  transform: scale(0.96);
  transition: transform 0.22s var(--ease-out);
}
.lightbox--video .lightbox__img {
  display: none;
}
.lightbox--video .lightbox__frame {
  display: block;
}
.lightbox.is-open .lightbox__frame {
  transform: none;
}
.lightbox__video {
  display: block;
  max-width: 100%;
  max-height: calc(100dvh - 2 * var(--lb-pad-y));
  width: auto;
  height: auto;
  border-radius: 1.2% / 2.2%; /* matches the inline screen recordings */
}
.lightbox__frame--phone {
  --bezel: 5px;
  padding: var(--bezel);
  background: #0b0b0d;
  border-radius: 40px;
}
.lightbox__frame--phone .lightbox__video {
  max-height: calc(100dvh - 2 * var(--lb-pad-y) - 2 * var(--bezel));
  border-radius: calc(40px - var(--bezel));
  background: var(--white);
}
.lightbox__btn {
  position: absolute;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(30 30 30 / 0.06);
  color: var(--ink);
  cursor: pointer;
  transition: background-color 0.2s ease;
}
.lightbox__btn:hover {
  background: rgb(30 30 30 / 0.12);
}
.lightbox__btn svg {
  width: 22px;
  height: 22px;
}
.lightbox__close {
  top: 16px;
  right: 16px;
}
.lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
}
.lightbox__prev {
  left: 16px;
}
.lightbox__next {
  right: 16px;
}
.lightbox__counter {
  position: absolute;
  left: 50%;
  bottom: 20px;
  transform: translateX(-50%);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
}
.lightbox--single .lightbox__nav,
.lightbox--single .lightbox__counter {
  display: none;
}
@media (max-width: 767px) {
  .lightbox__nav {
    top: auto;
    bottom: 8px;
    transform: none;
  }
  .lightbox__counter {
    bottom: 22px;
  }
  .lightbox,
  .lightbox--single {
    --lb-pad-x: 16px;
  }
  .lightbox__stage {
    padding-bottom: 72px; /* arrows + counter sit below the image */
  }
  .lightbox__img,
  .lightbox__video {
    max-height: calc(100dvh - var(--lb-pad-y) - 72px);
  }
  .lightbox__frame--phone .lightbox__video {
    max-height: calc(100dvh - var(--lb-pad-y) - 72px - 2 * var(--bezel));
  }
}
@media (prefers-reduced-motion: reduce) {
  .lightbox,
  .lightbox__img,
  .lightbox__frame,
  .cs-zoom__icon {
    transition: none;
  }
  .lightbox__img,
  .lightbox__frame {
    transform: none;
  }
}

/* ==========================================================================
   Reveal on scroll — subtle
   ========================================================================== */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.8s var(--ease-out), transform 0.8s var(--ease-out);
}
.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .project-row__media img {
    transition: none;
  }
}

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 900px) {
  /* Stack the labelled panel images so their small text stays readable. */
  .cs-panel-grid {
    grid-template-columns: minmax(0, var(--panel-item-max, 300px));
    justify-content: center;
  }
}

/* Single column: title, description, link, then image. */
@media (max-width: 767px) {
  .project-row,
  .project-row--image-left {
    grid-template-columns: 1fr;
    grid-template-areas: "text" "media";
    row-gap: 32px;
  }

}

/* Tablet: give the text beside the "Old design" panel a little more room. */
@media (max-width: 1100px) {
  .cs-text--media {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  }
}

@media (max-width: 767px) {
  .cs-grid2,
  .cs-text--media {
    grid-template-columns: 1fr;
    row-gap: 16px;
  }
  .cs-intro .cs-title {
    font-size: 40px;
  }
  .cs-intro__subtitle {
    margin-top: 8px;
    font-size: 15px;
  }
  .cs-grid2.cs-intro {
    grid-template-columns: 1fr;
  }
  .cs-title {
    font-size: 28px;
  }
  .cs-text--media {
    row-gap: 40px;
  }
  .cs-text--media .cs-copy {
    max-width: none;
    margin-top: 16px;
  }
  .cs-gallery {
    grid-template-columns: repeat(var(--cols-mobile, 2), minmax(0, 1fr));
    column-gap: 16px;
  }
  .cs-gallery--sized {
    justify-items: center;
  }
  .cs-gallery--sized .cs-zoom {
    max-width: 420px;
  }
  .cs-panel--wide {
    gap: 24px;
    padding: 24px 16px;
  }
  .cs-panel--wide .cs-zoom,
  .cs-panel--wide > video,
  .cs-panel--wide > .cs-video {
    width: 100%;
  }
  .cs-image--wide + .cs-image--wide,
  .cs-gallery + .cs-image--wide {
    margin-top: calc(32px - var(--cs-gap));
  }
  .cs-text--media.cs-text--balanced {
    grid-template-columns: 1fr;
  }
  .cs-compare {
    grid-template-columns: 1fr;
    justify-items: center;
    row-gap: 24px;
  }
  .cs-compare__arrow {
    width: 64px;
    transform: rotate(90deg);
  }
  .cs-panel {
    border-radius: 24px;
  }
  .cs-panel--labelled .cs-zoom {
    width: 88%;
  }
  .cs-panel--phone .cs-zoom {
    width: 62%;
  }
  .cs-panel--phone .cs-phone,
  .cs-panel--phone .cs-zoom--video {
    width: 74.4%;
  }
  .cs-panel--phone .cs-zoom--video .cs-phone {
    width: 100%;
  }
}

@media (max-width: 600px) {
  :root {
    --outer-gutter: 12px;
    --inner-gutter: 20px;
    --page-gutter: 16px;
  }
  .site-header__name {
    font-size: 15px;
  }
  .site-nav {
    font-size: 15px;
  }
  .contact__grid {
    flex-direction: column;
  }
}
