/* Druk (OneMovie's title face), used by the typography specimen in the
   case study */
@font-face {
  font-family: "Druk";
  src: url("assets/fonts/Druk-Heavy.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

/* ---- Tokens (inspired by Apple: neutral, light, spacious) ---- */
:root {
  --white: #ffffff;
  --mist: #f5f5f7;
  --frost: #fafafc;
  --hairline: #d6d6d6;
  --control-gray: #e6e6e8;
  --ink: #1d1d1f;
  --slate: #6e6e73;
  --steel: #86868b;

  --tone-1: #e4e2dd;
  --tone-2: #dfe3e6;
  --tone-3: #e6ded9;
  --tone-4: #dde3df;

  --radius-panel: 32px;
  --radius-card: 16px; /* every asset card in a case study (the tile-shaped ones use --tile-radius) */
  --radius-pill: 9999px;
  --asset-shadow: 0 12px 52px 0 rgba(0, 0, 0, 0.07); /* the app screenshots in the gallery */
  --tile-radius: 5.8% / 5.3%; /* = TILE_RADIUS_K in sphere.js (x 0.92 vertically) */

  --section-gap: 24px;
  --page-gutter: 24px;
  --nav-offset: 24px;
  /* nav's own inset from the panel edge it floats over — separate from
     the panel's own margin to the viewport (--page-gutter) */
  --nav-inset: 48px;
  --nav-height: 52px;

  /* type scale: caption / body / h2 (section titles) / lead / h1 (project title) */
  --fs-caption: 12px;
  --fs-body: 15px;
  --fs-h2: clamp(24px, 2.8vw, 34px);
  --fs-lead: clamp(28px, 4vw, 40px);
  --fs-h1: clamp(32px, 4vw, 48px);
  /* case-study type system, from the Figma artboard (SF Pro Text): H1 56 / H2 32 / H3 24 / body 15 */
  --cs-h1: clamp(36px, 5vw, 56px);
  --cs-h2: clamp(26px, 2.8vw, 32px);
  --cs-h3: clamp(20px, 2.2vw, 24px);
  --cs-body: 15px; /* Figma says 14, kept at 15 on purpose */

  --font: "SF Pro Text", -apple-system, BlinkMacSystemFont, "SF Pro Display",
    "Inter", "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

/* All type is SF Pro Text, Light — headings included, since the UA
   stylesheet's own font-weight:bold on h1-h6 would otherwise win over
   whatever body inherits. */
body, h1, h2, h3, h4, h5, h6 {
  font-family: var(--font);
  font-weight: 300;
}

/* NOT scroll-behavior:smooth globally — that intercepts every wheel/trackpad
   tick with the browser's own easing, which is exactly what made scrolling
   feel heavy. Anchor/nav clicks ask for smooth scrolling explicitly in JS
   (scrollIntoView({behavior:'smooth'})) instead, so normal scrolling stays
   native and 1:1 with the input. */
html { scroll-behavior: auto; }

body {
  margin: 0;
  background: #f5f6f6;
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

main {
  display: flex;
  flex-direction: column;
  gap: var(--section-gap);
  padding: var(--section-gap) var(--page-gutter);
  /* room under the last card so the fixed navbar (96px from the bottom) never covers it */
  padding-bottom: calc(var(--page-gutter) + 96px);
}

.panel {
  border-radius: var(--radius-panel);
  position: relative;
}

/* ---- Nav ----
   Compact centered pill at the bottom of the screen (like a mobile tab bar): translucent glass, fully rounded, items
   inline with the current one (the name) in a lighter inner pill. */
.nav {
  position: fixed;
  bottom: calc(var(--page-gutter) + 24px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 100;
  display: flex;
  align-items: center;
  height: 48px;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: rgba(72, 72, 76, 0.5);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  font-size: var(--fs-body);
  white-space: nowrap;
}

.nav a {
  display: block;
  padding: 12px 16px;
  line-height: 16px;
  border-radius: var(--radius-pill);
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
  font-weight: 300;
  transition: color 0.2s ease, background 0.2s ease;
}

.nav a { position: relative; }
/* the link under the pill (hovered, else the section in view) lights up */
.nav a.is-on { color: rgba(255, 255, 255, 0.92); }

/* one light pill that glides between the links (placed by script.js) */
.nav__pill {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 100%;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.08);
  pointer-events: none;
  transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1), width 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.nav__pill.no-anim { transition: none; }

.nav__links { display: flex; gap: 4px; }

/* Over the white hero the pill goes light with dark text */
body.hero-light .nav { background: rgba(0, 0, 0, 0.08); }
body.hero-light .nav a { color: rgba(0, 0, 0, 0.78); font-weight: 400; }
body.hero-light .nav a.is-on { color: #000; }
body.hero-light .nav__pill { background: rgba(0, 0, 0, 0.1); }

.nav { transition: background 0.3s ease, height 0.45s cubic-bezier(0.22, 0.61, 0.36, 1); }

.nav__items {
  position: relative;
  display: flex;
  align-items: center;
  gap: 4px;
  max-width: 720px;
  overflow: hidden;
  transition: max-width 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.25s ease;
}

/* while a project is open the navbar turns into a close button: the items
   fold away and a bigger round ✕ takes their place */
.nav__close {
  width: 0;
  height: 48px;
  display: grid;
  place-items: center;
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: 50%;
  background: none;
  color: #000;
  opacity: 0;
  visibility: hidden;
  cursor: pointer;
  transition: width 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.25s ease, background 0.2s ease, visibility 0s linear 0.45s;
}
.nav__close:hover { background: rgba(0, 0, 0, 0.08); }
.case-open .nav { height: 56px; }
.case-open .nav__items { max-width: 0; opacity: 0; pointer-events: none; }
.case-open .nav__close { width: 48px; opacity: 1; visibility: visible; transition-delay: 0s; }

/* ---- Hero: a pinned box, the stage stays sticky and inset by the same margin on all sides ---- */
.stage-pin {
  position: relative;
}

.stage {
  position: sticky;
  top: var(--page-gutter);
  height: calc(100vh - var(--page-gutter) * 2);
  /* deep dark instead of a flat fill — keeps the mockups discreet/moody
     rather than the loud focal point, with a faint cool vignette for depth */
  background: #ffffff;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.hero-spacer { height: 260vh; }

/* grey backdrop behind the case-study card (the hero itself is white) */
.stage::before {
  content: "";
  position: absolute;
  inset: 0;
  background: #f5f6f6;
  opacity: 0;
  transition: opacity 0.45s ease;
  pointer-events: none;
}
.case-open .stage::before { opacity: 1; }

/* -- hero phase -- */
.hero__field {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- Sphere hero: mockups arranged on a draggable 3D sphere (WebGL,
   see sphere.js), with a soft glow behind it for depth. The "MOBILE
   PRODUCT DESIGNER" title is drawn INTO the same canvas (as a fixed
   depth plane the sphere can pass in front of/behind) rather than as
   an HTML overlay — see .hero__copy below for the accessible fallback. ---- */
.hero__glow {
  display: none; /* the v2 hero is white */
  position: absolute;
  inset: -10%;
  pointer-events: none;
  /* faint cool highlight instead of a bright halo — just enough lift to
     read as depth on the deep-dark background, without competing with
     the (now discreet, blended-in) phones */
  background: radial-gradient(
    closest-side,
    rgba(255, 255, 255, 0.16) 0%,
    rgba(120, 160, 200, 0.08) 45%,
    rgba(120, 160, 200, 0) 72%
  );
  filter: blur(30px);
}

/* Tagline at the top left. Fades out when the visuals leave
   (script.js, --hero-fade); the inner span handles the focus recede. */
.hero__tagline {
  position: absolute;
  left: 40px;
  top: 40px;
  width: min(336px, calc(100% - 80px));
  margin: 0;
  text-align: left;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.35;
  color: #1d1d1f;
  opacity: calc(var(--hero-fade, 1) * 0.5);
  pointer-events: none;
  z-index: 3; /* above the tiles (the canvas layer is z-index 3 too, earlier in the DOM) */
}

/* language switch, top right: mirrors the tagline (shows the language you can switch to) */
.hero__lang {
  position: absolute;
  right: 32px;
  top: 32px;
  z-index: 4;
  margin: 0;
  padding: 8px;
  border: 0;
  background: none;
  font: inherit;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.35;
  color: #1d1d1f;
  opacity: calc(var(--hero-fade, 1) * 0.5);
  cursor: pointer;
}
.hero__lang:hover { opacity: var(--hero-fade, 1); }
body.case-open .hero__lang { opacity: 0; pointer-events: none; }

/* the card covers that area: the text steps aside while it is open */
body.case-open .hero__tagline {
  opacity: 0;
  transition: opacity 0.25s;
}
.hero__tagline-text > span { display: block; }
.hero__tagline-text > span + span { margin-top: 8px; }

/* When a mockup is focused the description steps back in depth, like the
   other phones do: smaller, dimmer, slightly out of focus. */
.hero__tagline-text {
  display: block;
  transition: transform 0.9s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.9s ease, filter 0.9s ease;
}

.stage:has(.sphere-stage.is-focus) .hero__tagline-text {
  transform: scale(0.82);
  filter: blur(2px);
  opacity: 0.3;
}

.sphere-stage {
  position: absolute;
  inset: 0;
  cursor: grab;
  touch-action: none;
}

.sphere-stage.is-dragging { cursor: grabbing; }
.sphere-stage.is-focus { cursor: pointer; }
.sphere-stage.is-hover { cursor: none; }

/* the "See more" disc that replaces the cursor over a visual */
.see-more {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 400;
  width: 0;
  height: 0;
  pointer-events: none;
}
.see-more span {
  position: absolute;
  left: -48px;
  top: -48px;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: #000;
  color: #fff;
  font-size: var(--fs-body);
  transform: scale(0);
  transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.see-more.is-on span { transform: scale(1); }
.see-more--next { z-index: 1000; }
.see-more--project span { padding: 0 16px; text-align: center; line-height: 1.2; }
@media (hover: none) { .see-more { display: none; } }

.sphere-stage canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* The visible title now lives inside the WebGL canvas (drawn as a fixed
   depth plane the sphere can pass in front of / behind — see sphere.js).
   This element stays in the DOM, real text, for screen readers and SEO,
   but is visually hidden (standard "sr-only" clip pattern) rather than
   removed. */
.hero__copy {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.stage__track { display: flex; flex-direction: column; }

/* ---- Case study card ----
   Embedded INSIDE .stage (absolute, not a fixed viewport overlay) so it
   shares the sphere canvas's stacking context — see .hero__field's
   z-index:3 above, which is what lets the focused phone (still the real
   3D model, never swapped for a flat image) render on top of this card
   in its empty center slot (.case-study__screen--slot) as it glides up
   into place while scrolling. Everything else here is plain HTML
   underneath that phone. The backdrop stays transparent — the dark stage
   shows through around the white card. Opacity/transform are driven
   directly (no CSS transition) by wheel delta while revealing (see
   sphere.js) so the card tracks the scroll 1:1; pointer-events only turn
   on once fully revealed. */
.case-study {
  /* fixed to the screen: the white card scrolls through it edge to edge, it
     is no longer a window pinned inside the stage */
  position: fixed;
  inset: 0;
  z-index: 1;
  visibility: hidden;
  pointer-events: none;
}

/* the sphere layer sits above the card (so the focused phone can render on
   top of it) and would swallow every click on the card, close button
   included — let clicks fall through to the card while it is open */
.case-open .hero__field { pointer-events: none !important; }

.case-study__morph {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  background: #f3f3f3;
  opacity: 0;
  pointer-events: none;
}

/* the scroller: transparent, the full screen, with the page gutter around the
   cards; the white backgrounds are the cards themselves and scroll with it */
.case-study__panel {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  padding: var(--page-gutter) var(--page-gutter) 128px; /* the bottom room keeps the last card clear of the close button */
  color: #000;
  opacity: 0;
  /* opacity/clip-path set inline during the reveal, no transition here */
}
.case-study__panel::-webkit-scrollbar { display: none; }

.cs-card,
.cs-next {
  max-width: 1104px;
  margin: 0 auto;
  background: #ffffff;
  border-radius: var(--radius-panel);
}
.cs-card { padding: 48px 40px 48px; }

/* closing card: the next project, same header as a project intro */
.cs-next {
  margin-top: var(--page-gutter);
  padding: 40px 40px 56px;
  cursor: pointer;
}
.cs-next:focus-visible { outline: 2px solid #000; outline-offset: 2px; }
@media (hover: hover) { .cs-next { cursor: none; } } /* the "next project" disc takes over */
.cs-next__title {
  margin: 56px 0 0;
  max-width: 18em;
  font-size: var(--cs-h1);
  font-weight: 400;
  line-height: 1.2;
}

.case-study__screens {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin: 40px 0 48px;
}

/* All three slots (the two flat screenshots and the empty center slot
   the 3D phone occupies) share one size — same width, same aspect ratio
   — so nothing pops or resizes when the phone settles into place. */
.case-study__screen {
  border-radius: var(--tile-radius);
  width: 100%;
  aspect-ratio: 0.92; /* same ratio as the hero tiles (TILE_ASPECT) */
  display: block;
  object-fit: contain;
  padding: 8.7%; /* same margin as the 3D tile (PAD in sphere.js); % padding = share of the tile's width */
  box-sizing: border-box;
  background: var(--tile, #ececec);
  opacity: 0;
}
.case-study { --tile: #f3f3f3; } /* same light tile as the hero */

.case-study__screen--slot {
  /* purely a layout placeholder — stays transparent forever, the visible
     "content" here is the real 3D phone rendered above it (see .hero__field
     z-index), so it never gets an opacity/1 like the two <img> siblings */
  padding: 0;
  background: transparent;
}

/* Project content, in the style of a clean list card: a small status row, a
   large light title, then hairline-separated rows (label left, text right). */
.cs-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: var(--cs-body);
  color: #000;
}
.cs-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #2e8b4d;
  flex-shrink: 0;
}
.cs-head__right { margin-left: auto; }
/* the app icon replaces the dot when a project has one */
.cs-dot--icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--icon) center / cover no-repeat;
}

.cs-title {
  margin: 0 0 56px;
  max-width: 18em;
  font-size: var(--cs-h1);
  font-weight: 400;
  line-height: 1.2;
  color: #000;
}

.cs-meta {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.cs-meta h3,
.cs-scope h3 { margin: 0 0 16px; font-size: var(--cs-body); font-weight: 600; line-height: 1.2; }
.cs-meta p { margin: 0; font-size: var(--cs-body); font-weight: 400; line-height: 1.2; }
.cs-meta a { color: #000; text-decoration: none; }
.cs-meta a:hover { text-decoration: underline; }
.cs-scope { margin-top: 40px; }
.cs-scope h3 { margin-bottom: 24px; }
.cs-scope ul { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.cs-scope li {
  padding: 8px 16px;
  border-radius: 999px;
  background: #f3f3f3;
  font-size: var(--cs-body);
  line-height: 1.2;
}

.cs-list { margin-top: 48px; padding-top: 48px; border-top: 1px solid #e6e6e6; }

.cs-row {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr); /* the text column starts 280px from the card edge, as in Figma */
  gap: 0;
  padding: 0 0 96px;
}
.cs-row:last-child { padding-bottom: 0; }
.cs-row:has(+ .cs-soon[hidden]) { padding-bottom: 0; } /* a project whose later sections are still hidden ends on its last visible row */

.cs-row__label {
  padding-top: 6px;
  font-size: var(--cs-body);
  font-weight: 600;
  line-height: 1.2;
  color: #000;
}

.cs-row__body { min-width: 0; } /* lets wide children (the screen gallery) scroll instead of stretching the column */

.cs-row__title {
  margin: 0;
  font-size: var(--cs-h2);
  font-weight: 400;
  line-height: 1.27;
  color: #000;
}
/* H3: sub-sections inside a row */
.cs-row__title--sm { margin-top: 56px; font-size: var(--cs-h3); }
.cs-caption + .cs-row__title--sm, .cs-gallery + .cs-row__title--sm { margin-top: 80px; }
.cs-gallery + .cs-row__title--sm { margin-top: 24px; } /* the strip already has 56px of padding below */
.cs-row__title a { color: #000; }

.cs-row__sub {
  margin: 8px 0 0;
  font-size: var(--cs-body);
  font-weight: 400;
  line-height: 1.2;
  color: #000;
}
.cs-row__sub strong { font-weight: 600; }
.cs-row__title + .cs-row__sub { margin-top: 32px; }
.cs-row__title--sm + .cs-row__sub { margin-top: 24px; }
.cs-row__gap { margin-top: 32px; }
/* italic caption under a figure, right-aligned on the text column's edge */
.cs-caption { margin: 16px 0 0; text-align: right; font-size: var(--cs-body); font-style: italic; line-height: 1.2; color: #000; }

/* the three figures of the context section */
.cs-stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 16px 24px;
  margin: 32px 0 32px;
  padding: 0;
  list-style: none;
  font-size: var(--cs-body);
  font-weight: 600;
}
.cs-stats li { display: flex; align-items: center; gap: 8px; }
.cs-stats i { width: 10px; height: 10px; border-radius: 50%; background: #2e8b4d; flex: none; }

/* the survey result, drawn in code */
.cs-chart {
  margin: 24px 0 0;
  padding: 24px 24px 16px;
  border: 1px solid #000; /* the figures are outlined frames in Figma */
  border-radius: var(--radius-card);
  background: #fff;
}
.cs-chart__q { display: flex; gap: 8px; align-items: flex-start; padding-bottom: 16px; border-bottom: 1px solid #ececec; }
.cs-chart__q p { margin: 0; font-size: var(--fs-body); }
.cs-chart__q small { color: #7a7a7a; font-size: var(--fs-caption); }
.cs-chart__badge { padding: 4px 8px; border-radius: 5px; background: #ebe3f7; color: #5a3b9a; font-size: var(--fs-caption); }
.cs-chart__plot {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: end;
  gap: 24px;
  height: 180px;
  margin-top: 24px;
  padding: 0 16px;
  background: repeating-linear-gradient(to top, transparent 0, transparent calc(25% - 1px), #ececec calc(25% - 1px), #ececec 25%);
}
.cs-chart__plot i {
  position: relative;
  display: block;
  height: calc(var(--h) * 1%);
  border-radius: 2px 2px 0 0;
  background: #9d6bb8;
}
.cs-chart__plot b { position: absolute; left: 0; right: 0; top: -16px; text-align: center; color: #5a3b9a; font-size: var(--fs-caption); font-weight: 600; }
.cs-chart__x { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; padding: 8px 16px 0; color: #666; font-size: var(--fs-caption); text-align: center; }
.cs-row__sub + .cs-row__title { margin-top: 40px; }

/* images of a project row: full width of the text column; the branding
   elements (.cs-bleed) run on to the left edge of the card content */
.cs-fig { display: block; width: 100%; height: auto; margin-top: 24px; padding: 24px; box-sizing: border-box; background: #fff; border-radius: var(--radius-card); }
.cs-row__body .cs-bleed { margin-left: -240px; width: calc(100% + 240px); }

/* one content block per project (sphere.js sets data-project on #caseStudy); Surfrider, Pony, Arclib and Satio have none yet and show a "work in progress" line */
.cs-proj { display: contents; }
.cs-proj:not(.cs-proj--onemovie) { display: none; }
:is([data-project="discover"], [data-project="squadeasy"], [data-project="cashbee"], [data-project="surfrider"], [data-project="pony"], [data-project="arclib"], [data-project="satio"]) .cs-proj--onemovie { display: none; }
[data-project="discover"] .cs-proj--discover,
[data-project="squadeasy"] .cs-proj--squadeasy,
[data-project="cashbee"] .cs-proj--cashbee,
[data-project="surfrider"] .cs-proj--wip,
:is([data-project="pony"], [data-project="arclib"], [data-project="satio"]) .cs-proj--wip { display: contents; }

/* design system: the UI components laid out in three columns */
.cs-system {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  margin-top: 24px;
}
.cs-system__col { display: flex; flex-direction: column; gap: 24px; align-items: flex-start; }
.cs-system img {
  display: block;
  width: 100%;
  height: auto;
  filter: drop-shadow(0 12px 52px rgba(0, 0, 0, 0.07)); /* drop-shadow follows each component's outline; same look as --asset-shadow */
}
.cs-row__sub + .cs-fig { margin-top: 24px; }
.cs-fig--funnel, .cs-fig--img { margin-top: 24px; padding: 0; overflow: hidden; }
.cs-fig--funnel { border: 1px solid #000; }
.cs-fig--funnel img, .cs-fig--img img { display: block; width: 100%; height: auto; }
.cs-fig + .cs-fig { margin-top: 16px; }

.cs-fig + .cs-row__title,
.cs-fig + .cs-row__sub { margin-top: 40px; }

/* Horizontal gallery of app screens: spans the whole card width (the
   screens run out to both card edges as it scrolls) but rests with the first
   screen on the card's left padding line. Finite: scrolls freely from the first
   screen to the last with trackpad / shift+wheel / drag + momentum (script.js). */
.cs-gallery {
  --gallery-left: calc(40px + 240px); /* card padding + label column */
  --card-h: 520px; /* height of every screen / card in the strip */
  width: calc(100% + var(--gallery-left) + 40px);
  margin: 0 -40px -16px calc(-1 * var(--gallery-left));
  padding: 32px 0 56px; /* breathing room around the screens */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  cursor: grab;
}
.cs-gallery::-webkit-scrollbar { display: none; }
.cs-gallery.is-dragging { cursor: grabbing; }
@media (hover: hover) { .cs-gallery li:has(img:hover, .cs-bcard:hover) { cursor: none; } } /* the "Next" disc takes over */
.cs-gallery:focus-visible { outline: 2px solid #000; outline-offset: -2px; border-radius: 8px; }
.cs-gallery ul {
  display: flex;
  gap: 24px;
  margin: 0;
  padding: 0 40px 0 var(--gallery-left); /* the first screen rests on the text column (the grid); 40px of room after the last one */
  list-style: none;
  width: max-content;
}
.cs-gallery li { flex: none; }
/* nothing left of the text column until the first scroll (see script.js) */
.cs-gallery:not(.is-started) {
  clip-path: inset(0 0 0 max(0px, calc(var(--gallery-left) - var(--reveal, 0px))));
}
/* the app screens (and the branding cards, at the same height) are sized so the last visible screen is cut in half at the card edge: it shows there is more to scroll.
   n screens fit whole between the text column and the edge, plus half of the next; 2.21 = average height / width of the screens. */
@supports (width: 1cqw) {
  .cs-card { container-type: inline-size; }
  .cs-gallery {
    --n: 3;
    --pad2: 80px; /* the card's padding, both sides */
    --card-h: calc((100cqw + var(--pad2) - var(--gallery-left) - 24px * var(--n)) / (var(--n) + 0.5) * 2.21);
  }
}
.cs-gallery img {
  display: block;
  height: var(--card-h);
  width: auto;
  border-radius: var(--radius-card);
  box-shadow: var(--asset-shadow);
  user-select: none;
  -webkit-user-drag: none;
}

/* identity cards in the same strip: stacked small cards (colours, type, icon); drop-shadow follows their outline, gaps included */
.cs-bcard {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: calc(var(--card-h) * 0.74);
  height: var(--card-h);
  user-select: none;
  filter: drop-shadow(0 12px 52px rgba(0, 0, 0, 0.07)); /* same look as --asset-shadow */
}
.cs-bc {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-height: 0;
  padding: 7cqw;
  border-radius: var(--radius-card);
  background: var(--tile, #f3f3f3);
}
.cs-bc--main { flex: 1; }
/* typography specimen, back as a wide card: name | Aa | sample, one row per face, all aligned on the baseline */
.cs-bcard--type {
  width: calc(var(--card-h) * 1.92);
  gap: 0;
  border-radius: var(--radius-card);
  background: #fff;
}
.cs-type__row {
  flex: 1;
  display: grid;
  grid-template-columns: 20.6cqw 28cqw minmax(0, 1fr);
  align-items: end;
  padding: 3.5cqw 4.4cqw 3.5cqw 5.4cqw;
}
.cs-type__name { font-size: clamp(11px, 1.45cqw, 15px); line-height: 1.2; }
.cs-type__aa { font-size: 20cqw; line-height: 0.8; }
.cs-type__sample { margin: 0; min-width: 0; }
.cs-type__row--druk .cs-type__name,
.cs-type__row--druk .cs-type__aa,
.cs-type__row--druk .cs-type__sample {
  font-family: "Druk", "Arial Narrow", Impact, sans-serif;
  font-weight: 800;
  text-transform: uppercase;
}
.cs-type__row--druk .cs-type__aa { text-transform: none; }
.cs-type__row--druk .cs-type__sample { font-size: 5.4cqw; line-height: 0.98; }
.cs-type__row--sf .cs-type__name,
.cs-type__row--sf .cs-type__aa,
.cs-type__row--sf .cs-type__sample {
  font-family: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Helvetica, Arial, sans-serif;
  font-weight: 400;
}
.cs-type__row--sf .cs-type__aa { font-size: 20.5cqw; }
.cs-type__row--sf .cs-type__sample { font-size: 2.7cqw; line-height: 1.25; }
/* app icon on a bare light "home screen": no device, just a grid of quiet squares running off the card */
.cs-bc--phone { position: relative; overflow: hidden; padding: 0; background: var(--tile, #f3f3f3); }
.cs-ph { position: absolute; left: 11cqw; top: 22cqw; display: grid; grid-template-columns: repeat(4, 22cqw); gap: 9cqw; }
.cs-ph__app { position: relative; display: block; }
.cs-ph__app i, .cs-ph__app img { display: block; width: 22cqw; height: 22cqw; border-radius: 5cqw; }
.cs-ph__app i { background: #e4e4e8; }
.cs-ph__app b { position: absolute; top: 100%; left: 0; right: 0; margin-top: 2cqw; color: #1d1d1f; font-size: 3.6cqw; font-weight: 400; text-align: center; white-space: nowrap; }

@media (max-width: 860px) {
  .cs-card { padding: 40px 24px 56px; }
  .cs-next { padding: 32px 24px 40px; }
  .case-study__screens { gap: 8px; }
  .cs-row { grid-template-columns: 112px minmax(0, 1fr); gap: 0 16px; padding: 0 0 64px; }
  .cs-gallery { --gallery-left: calc(24px + 112px + 16px); width: calc(100% + var(--gallery-left) + 24px); margin-right: -24px; }
  .cs-gallery { --n: 2; --pad2: 48px; }
  .cs-meta { grid-template-columns: 1fr 1fr; }
}

/* phones: the label column would squeeze the content to ~150px, so the label
   goes on top and everything gets the full card width */
@media (max-width: 560px) {
  .cs-meta { grid-template-columns: 1fr; }
  .cs-row { grid-template-columns: 1fr; gap: 16px; }
  .cs-gallery { --gallery-left: 24px; }
  .cs-gallery { --n: 1; }
}


/* ---- About + Contact: white cards on the grey page ---- */
.about,
.contact-card {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}
/* a lot of air between the hero and the first section after it */
.about { margin-top: clamp(96px, 16vh, 184px); }

.about__card {
  background: #fff;
  border-radius: var(--radius-panel);
  padding: 48px 40px 72px;
  color: #000;
}

.about__eyebrow {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 16px;
  font-size: var(--fs-body);
  font-weight: 400;
}

.about__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #1f8f4e;
}

.about__lead {
  margin: 0;
  padding: 0 10% 40px 0; /* text on 90% of the card, the hairline below stays full width */
  border-bottom: 1px solid #ececec;
  font-size: var(--fs-lead);
  font-weight: 300;
  line-height: 1.2;
}

.about__rows { margin-top: 48px; }

.about__group {
  display: grid;
  grid-template-columns: 23% 1fr;
  gap: 24px;
}
.about__group + .about__group { margin-top: 72px; }

.about__label {
  margin: 0;
  font-size: var(--fs-body);
  font-weight: 600;
}

.about__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 32px;
}

.about__list li {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 24px;
  font-size: var(--fs-body);
  line-height: 1.45;
}

.about__who { display: grid; gap: 4px; }
.about__who strong { font-weight: 600; }
.about__who span,
.about__list p { color: #1d1d1f; font-weight: 400; }
.about__list p { margin: 0; }

.contact-card { padding-bottom: 40px; }
.contact-card h2 {
  margin: 32px 0 48px;
  font-size: var(--fs-lead);
  font-weight: 300;
  line-height: 1.2;
}
.contact-card__mail {
  color: #000;
  font-size: var(--fs-body);
  font-weight: 600;
  text-decoration: none;
}
.contact-card__mail:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .about__card { padding: 24px 24px 40px; }
  .about__lead { padding-right: 0; } /* the 90% measure is for wide cards only */
  .about__group { grid-template-columns: 1fr; gap: 16px; }
  .about__list li { grid-template-columns: 1fr; gap: 8px; }
}

/* the user journey sits in the text column like everything else */
/* the user journey is too wide for the text column: it spans the whole card
   content width (label column included), like the gallery does */
.cs-row__body .om-j { margin: 24px 0 0 -240px; width: calc(100% + 240px); border: 1px solid #000; }
@media (max-width: 860px) {
  .cs-row__body .om-j { margin-left: -128px; width: calc(100% + 128px); }
  .cs-row__body .cs-bleed { margin-left: -128px; width: calc(100% + 128px); }
}
@media (max-width: 560px) {
  .cs-system { grid-template-columns: 1fr; }
  .cs-row__body .om-j,
  .cs-row__body .cs-bleed { margin-left: 0; width: auto; }
}

/* ---- user flow (UX section): one long left-to-right flow in a sideways scroller.
   Its drawing is scrubbed by the scroll (script.js): it rises into view, then
   keeps drawing as you scroll right; drag or swipe to move along it. ---- */
.uf {
  margin: 24px 0 0;
  --uf-left: calc(40px + 240px); /* the first node sits on the text column (card padding + label column) */
}
/* no card of its own: it sits straight on the project card and runs on to its edges */
.cs-row__body .uf { margin: 24px -40px 0 -280px; width: calc(100% + 320px); }
.uf__scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  cursor: grab;
  /* at rest the flow starts on the start line and nothing shows to its left;
     the clip opens by as many pixels as you have scrolled (like the screens gallery) */
  clip-path: inset(0 0 0 max(0px, calc(var(--uf-left) - var(--reveal, 0px))));
}
.uf.is-started .uf__scroll { clip-path: none; }
/* the right edge fades out while there is more to see: what comes next is hinted, not cut dead */
.uf__scroll {
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 96px), transparent);
  mask-image: linear-gradient(90deg, #000 calc(100% - 96px), transparent);
}
.uf.is-end .uf__scroll { -webkit-mask-image: none; mask-image: none; }
.uf__scroll::-webkit-scrollbar { display: none; }
.uf__scroll.is-dragging { cursor: grabbing; user-select: none; }
.uf__scroll:focus-visible { outline: 2px solid #000; outline-offset: -2px; }
.uf__stage { position: relative; margin-left: calc(var(--uf-left) - 32px); } /* the first node is at x = 32 */
.uf__lines { position: absolute; left: 0; top: 0; }
.uf__lines path {
  fill: none;
  stroke: #d2d2d7;
  stroke-width: 1.2;
  stroke-dasharray: 1;
  stroke-dashoffset: 1; /* drawn by script.js as you scroll (scrubbed, no transition) */
}
/* the arrow head appears once the line has been drawn (script.js adds .is-done) */
.uf__lines path[data-arrow].is-done { marker-end: url(#ufArrow); }
.uf__node, .uf__edge { opacity: 0; } /* faded in by script.js as you scroll */
.uf__node { position: absolute; transform: translateY(-50%) scale(0.96); }
.uf__edge { position: absolute; transform: translate(-50%, -50%); }
/* quiet shapes: soft grey for what the user sees and does, an outline for the
   questions, black for the end; no icons, no colour accents */
.uf__node {
  box-sizing: border-box;
  height: 104px; /* every node has the same height */
  padding: 16px;
  /* same layout as the user journey cards: the icon top left, the label bottom left */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  border-radius: 16px;
  background: #f5f5f7;
  color: #1d1d1f;
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.2;
  text-align: left;
}
.uf__node--question { background: #fff; border: 1px solid #d2d2d7; } /* a real border: an inset shadow got cut on some edges */
.uf__node--end { background: #1d1d1f; color: #fff; }
/* Oui / Non sit ON the line: the white behind them cuts the stroke */
.uf__edge { padding: 4px 8px; background: #fff; font-size: var(--fs-caption); line-height: 1; color: #86868b; }
/* filled SF Symbols above the label, tinted with the text colour through a mask:
   iphone (screens), questionmark.app (questions), hand.point.up (actions) */
.uf__node--screen::before, .uf__node--question::before, .uf__node--action::before {
  content: "";
  display: block;
  width: 24px;
  height: 24px;
  margin: 0;
  flex: none;
  background: #1d1d1f;
  opacity: 0.7;
  -webkit-mask: center / contain no-repeat;
  mask: center / contain no-repeat;
}
.uf__node--end { justify-content: flex-end; }
.uf__node--end::before { content: none; }
.uf__node--screen::before { -webkit-mask-image: url(assets/icons/platter.filled.bottom.iphone.svg); mask-image: url(assets/icons/platter.filled.bottom.iphone.svg); }
.uf__node--question::before { -webkit-mask-image: url(assets/icons/questionmark.app.svg); mask-image: url(assets/icons/questionmark.app.svg); }
.uf__node--action::before { -webkit-mask-image: url(assets/icons/hand.point.up.svg); mask-image: url(assets/icons/hand.point.up.svg); }
@media (max-width: 860px) {
  .cs-row__body .uf { margin: 24px -24px 0 -152px; width: calc(100% + 176px); }
  .uf { --uf-left: calc(24px + 112px + 16px); }
}
@media (max-width: 560px) {
  .uf { --uf-left: 24px; }
  .cs-row__body .uf { margin: 24px -24px 0; width: calc(100% + 48px); }
}

/* small screens: the navbar must fit (the name goes, the links tighten) and the
   intro text steps back a size so it covers less of the sphere */
@media (max-width: 860px) {
  .hero__tagline { left: 24px; top: 24px; width: min(300px, calc(100% - 48px)); font-size: var(--fs-body); }
  .hero__lang { right: 16px; top: 16px; font-size: var(--fs-body); }
}
@media (max-width: 560px) {
  .nav .nav__name { display: none; }
  .nav a { padding: 12px 10px; }
}

/* line breaking: balanced lines in headings (progressive enhancement). No text-wrap: pretty on paragraphs: next to the
   no-break spaces it pulled words down before every <br>, leaving short lines. */
h1, h2, h3, .cs-title, .cs-row__title, .hero__tagline-text { text-wrap: balance; }
