/* ############################################################################
   PART 1 of 3 — Design tokens (formerly css/tokens.css)
   ############################################################################ */

/* ==========================================================================
   Design tokens — mirrors the "Colors" + "Fonts" frames in Figma
   (file XKcjU4rvYiUxGTobyWxgXw, node 267:79)
   Change a value here and it propagates everywhere.
   ========================================================================== */

:root {
  /* ---- Palette ---------------------------------------------------------- */
  --c-white:        #ffffff;
  --c-surface:      #f8fafc;  /* card / image-block fill                     */
  --c-brand-50:     #f0f9ff;  /* secondary button border                     */
  --c-brand-100:    #dff2fe;  /* hero gradient tail                          */
  --c-brand-700:    #0069a8;  /* original Figma "700" swatch — kept for reference, unused in styles.css now that --c-primary covers those roles */
  --c-brand-800:    #00598a;  /* original Figma "800" swatch — same as above */
  --c-brand-950:    #052f4a;  /* primary ink                                 */

  /* Site-wide accent — "product strategy.", "Read more", the CTA heading,
     nav-link hover, the CTA gradient, focus rings, the back-to-top icon.
     A deliberate departure from the Figma palette above, not a Figma swatch. */
  --c-primary:      #0084d1;

  --c-ink:          #0f172a;  /* headings on Work / case-study pages         */
  --c-ink-soft:     #1e293b;  /* secondary button label                      */
  --c-muted:        #64748b;  /* supporting copy                             */
  --c-muted-2:      #4b515a;  /* CTA subtitle                                */
  --c-border:       #f1f5f9;  /* hairlines, card borders                     */
  --c-dot:          #ebebeb;  /* inactive carousel dot                       */

  --grad-cta: linear-gradient(90deg, rgba(0, 132, 209, 0.7) 52.404%, #0084d1 100%);
  --grad-connect: linear-gradient(0deg, rgba(0, 132, 209, 0.2) 10%, rgba(255, 255, 255, 0.2) 100%);

  /* ---- Type ------------------------------------------------------------- */
  /* Display and UI are both Inter. They stay as separate tokens so a distinct
     display face can be reintroduced later by changing one line. */
  --font-display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --fs-display: 64px;  /* Large display — Medium                             */
  --fs-h1:      32px;  /* Headings (H1) — Bold — "Featured Case Studies",
                           "About me", "Recommendations"                     */
  --fs-h1-lg:   48px;  /* Case-study page title — Bold                       */
  --fs-h2:      24px;  /* Card titles (work-card / case-study) — Inter Bold  */
  --fs-h3:      24px;  /* Highlight titles — Bold                            */
  --fs-lead:    24px;  /* Hero body / CTA subtitle                           */
  --fs-body-lg: 20px;  /* About body                                         */
  --fs-body:    18px;  /* Body / buttons                                     */
  --fs-caption: 16px;  /* Captions, tags, footer links                       */
  --fs-note:    14px;  /* Footnotes                                          */

  /* ---- Layout ----------------------------------------------------------- */
  --page-max:   1513px;
  --gutter:     80px;
  --header-h:   75px;

  --r-sm:   6px;
  --r-md:  10px;
  --r-lg:  16px;
  --r-xl:  24px;
  --r-2xl: 28px;
  --r-pill: 999px;

  --gap-3xs: 10px;
  --gap-2xs: 12px;
  --gap-xs:  16px;
  --gap-sm:  24px;
  --gap-md:  40px;
  --gap-lg:  48px;
  --gap-xl:  60px;

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

@media (max-width: 1100px) { :root { --gutter: 48px; --fs-display: 52px; --fs-h1: 30px; --fs-h1-lg: 38px; } }
@media (max-width: 720px)  { :root { --gutter: 24px; --fs-display: 38px; --fs-h1: 26px; --fs-h1-lg: 30px;
                                     --fs-h2: 24px; --fs-lead: 18px; --fs-body-lg: 17px; --fs-body: 16px;
                                     --gap-xl: 40px; --gap-lg: 32px; } }

/* ############################################################################
   PART 2 of 3 — Self-hosted webfonts (formerly css/fonts.css)
   ############################################################################ */

/* ==========================================================================
   Self-hosted webfonts. Files live in assets/fonts/ — see the README there.

   Inter covers the whole site — display, headings, body, buttons, tags,
   footer, work-card and case-study titles. SIL Open Font License, so
   self-hosting is fully permitted. Each face tries the locally installed
   font first, so a visitor who already has Inter downloads nothing.
   ========================================================================== */

/* ---- Inter 400 — body copy, hero paragraph, footer links ---------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: local("Inter Regular"), local("Inter-Regular"),
       url("../assets/fonts/Inter-Regular.woff2") format("woff2");
}

/* ---- Inter 500 — 64px display headings --------------------------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: local("Inter Medium"), local("Inter-Medium"),
       url("../assets/fonts/Inter-Medium.woff2") format("woff2");
}

/* ---- Inter 600 — buttons, "Explore case study" links ------------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: local("Inter SemiBold"), local("Inter-SemiBold"),
       url("../assets/fonts/Inter-SemiBold.woff2") format("woff2");
}

/* ---- Inter 700 — section headings, tags, footer headings --------------- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: local("Inter Bold"), local("Inter-Bold"),
       url("../assets/fonts/Inter-Bold.woff2") format("woff2");
}

/* ############################################################################
   PART 3 of 3 — Site styles
   ############################################################################ */

/* ==========================================================================
   Nare Kosbekian — portfolio
   Landing page  : Figma node 99:1770
   Case study    : Figma node 105:2141 ("Work 2")
   ========================================================================== */

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

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

body {
  margin: 0;
  background: var(--c-white);
  color: var(--c-brand-950);
  font-family: var(--font-display);
  font-size: var(--fs-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, p, figure { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

:focus-visible { outline: 3px solid var(--c-primary); outline-offset: 3px; border-radius: 4px; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ---- Splash / intro overlay (landing page only) -------------------------
   Static in the HTML (not JS-injected) so it paints before landing.js has
   built the page. landing.js removes `.is-loading` from <body> and adds
   `.is-hidden` here once the page is ready and the mark has had its moment;
   the element is then dropped from the DOM on transitionend. The page
   underneath (header + app) starts faded/offset and eases into place on the
   same beat `.is-loading` lifts, so the splash's exit and the page's entrance
   read as one continuous motion instead of a curtain-drop reveal. */
body.is-loading { overflow: hidden; }

#app {
  opacity: 1; transform: translateY(0);
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}
body.is-loading #app { opacity: 0; transform: translateY(20px); }
body.is-loading .site-header { opacity: 0; }

.splash {
  position: fixed; inset: 0; z-index: 999;
  display: flex; align-items: center; justify-content: center;
  background: var(--c-white);
  transition: opacity .6s var(--ease), visibility .6s var(--ease);
}
.splash.is-hidden { opacity: 0; visibility: hidden; pointer-events: none; }

.splash__mark {
  display: flex; align-items: center; gap: var(--gap-2xs);
  opacity: 0; transform: translateY(14px) scale(.94);
  animation: splash-in .8s var(--ease) .1s forwards;
}
.splash__mark img {
  flex: none; width: 56px; height: 56px; border-radius: var(--r-md);
  object-fit: contain; background: var(--c-brand-100);
}
.splash__mark span {
  font-family: var(--font-display); font-weight: 600; font-size: var(--fs-h2);
  color: var(--c-brand-950);
}

/* Name swap — "Nare Kosbekian" slides up and out while "Product Designer"
   slides in from below, both fading as they go. Both strings sit stacked in
   the same grid cell so the container sizes to the wider of the two instead
   of clipping; the slide itself is transform/opacity only. */
.splash__name { display: inline-grid; overflow: hidden; vertical-align: middle; }
.splash__name-text {
  grid-area: 1 / 1; white-space: nowrap;
  transition: transform .5s var(--ease), opacity .5s var(--ease);
}
.splash__name-text--next { transform: translateY(110%); opacity: 0; }
.splash__name.is-swapped .splash__name-text { transform: translateY(-110%); opacity: 0; }
.splash__name.is-swapped .splash__name-text--next { transform: translateY(0); opacity: 1; }

@keyframes splash-in {
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* --------------------------------------------------------------------------
   2. Layout
   -------------------------------------------------------------------------- */
.page { max-width: var(--page-max); margin-inline: auto; }
.section { padding: var(--gap-md) var(--gutter); }
/* Split (not padding-block) — only the top (header-to-title gap on the
   case-study page, its only user) is 50px; bottom stays 100px. */
.section--tall { padding-top: 50px; padding-bottom: 100px; }

.section-header { display: flex; flex-direction: column; gap: var(--gap-xs); }
.section-header h1,
.section-header h2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-h1);
  line-height: 1.1;
  letter-spacing: -1px;
  color: var(--c-ink);
}
.section-header p { font-size: var(--fs-body); line-height: 1.6; color: var(--c-muted); }

/* --------------------------------------------------------------------------
   3. Buttons, links, tags
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--gap-3xs); padding: 12px 30px;
  border-radius: var(--r-sm); border: 1px solid transparent;
  font-family: var(--font-ui); font-weight: 600; font-size: 16px;
  line-height: 1.5; white-space: nowrap;
  transition: opacity .18s var(--ease);
}
/* Hover / press feedback for every button: fade to 50%, nothing else. */
.btn:hover,
.btn:active { opacity: .5; }

.btn--ghost { color: var(--c-brand-950); }
.btn--ghost:hover { color: var(--c-primary); }

.btn--dark { background: var(--c-brand-950); color: var(--c-white); }

.btn--cta {
  padding: 12px 20px; border-radius: var(--r-md);
  background: var(--grad-cta); color: var(--c-white);
}

.btn--secondary {
  padding: 12px 20px; border-radius: var(--r-md);
  background: var(--c-white); border-color: var(--c-brand-50); color: var(--c-ink-soft);
}

.link {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-weight: 600; font-size: var(--fs-caption);
  color: #0084d1;
}
.link__icon { width: 16px; height: 16px; flex: none; transition: transform .18s var(--ease); }
.link:hover .link__icon { transform: translateX(4px); }

.tag {
  display: inline-flex; padding: 8px 16px; border-radius: var(--r-pill);
  background: var(--c-white); color: var(--c-ink);
  font-family: var(--font-ui); font-weight: 700; font-size: 14px;
  letter-spacing: 1px; white-space: nowrap;
  box-shadow: 0 2px 8px rgba(15, 23, 42, .06);
}

/* --------------------------------------------------------------------------
   4. Header
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  transition: background-color .25s var(--ease), backdrop-filter .25s var(--ease),
              box-shadow .25s var(--ease), border-color .25s var(--ease),
              opacity .6s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-scrolled {
  /* Liquid glass: translucent (not flat white) + a saturated blur for the
     vibrancy, a thin light-catching top edge, and a soft lift shadow. */
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border-bottom-color: rgba(255, 255, 255, 0.5);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    0 8px 24px rgba(5, 47, 74, 0.10);
}
.site-header__inner {
  max-width: var(--page-max); margin-inline: auto;
  height: var(--header-h); padding: 20px var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: var(--gap-sm);
}
.wordmark {
  font-family: var(--font-ui); font-weight: 400; font-size: 24px;
  color: var(--c-brand-950); white-space: nowrap;
}
.site-nav { display: flex; align-items: center; gap: 30px; }
.site-nav__links { display: flex; align-items: center; gap: var(--gap-3xs); }
/* Two Résumé buttons exist (see ui.js); only one shows at a time. Above the
   ≤860px breakpoint the header's own copy is the visible one. */
.nav-cta--in-menu { display: none; }
.nav-toggle { display: none; width: 44px; height: 44px; align-items: center; justify-content: center; }
.nav-toggle__bar { display: block; width: 22px; height: 2px; background: var(--c-brand-950); position: relative; }
.nav-toggle__bar::before,
.nav-toggle__bar::after {
  content: ""; position: absolute; left: 0; width: 22px; height: 2px; background: inherit;
}
.nav-toggle__bar::before { top: -7px; } .nav-toggle__bar::after { top: 7px; }

/* --------------------------------------------------------------------------
   5. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  /* 617px = 686px - 10%. */
  height: 617px; margin-top: calc(-1 * var(--header-h));
}
/* Everything that should stay clipped to the hero's box (blob, portrait,
   copy) lives in here; .hero__cursor sits outside it as a direct child of
   .hero instead, specifically so its click-tour (see landing.js) can swing
   below this box without being cut off — see .hero__cursor's z-index. */
.hero__clip { position: absolute; inset: 0; overflow: hidden; }
.hero__blob {
  /* +15% (410→472), re-anchored so the box's centre point doesn't move:
     old centre (17+205, 181+205) = (222,386); new left/top = centre - 236. */
  position: absolute; left: -14px; top: 150px; width: 472px; height: 472px;
  display: flex; align-items: center; justify-content: center; pointer-events: none;
}
.hero__blob img { width: 388px; height: 388px; transform: rotate(-104.34deg); }

.hero__copy {
  /* Centered on the hero's midpoint — except at widths where that would
     drift the text left into the portrait (portrait right edge is
     74+385=459px; copy is 615px wide, so its centered anchor needs to stay
     at 459 + 24px clearance + 307.5 half-width = 790.5px at minimum). Below
     that, "50%" would put the anchor closer than 790.5px, so max() holds it
     there instead — a continuous clamp, not a breakpoint jump, and at the
     1512px Figma width 50% (756px) is within ~35px of that, so wide screens
     are still only nudged slightly, not restructured. */
  position: absolute; left: max(50%, 790.5px); top: 50%; transform: translate(-50%, -50%);
  width: 615px; max-width: calc(100% - var(--gutter) * 2);
  display: flex; flex-direction: column; align-items: center; gap: 20px; text-align: center;
}
.hero__title { font-weight: 600; font-size: 40px; line-height: normal; }
.hero__title em { font-style: normal; color: var(--c-primary); }

/* "product strategy." handwriting — see enhanceHandwriting() in landing.js.
   --len/--dur/--start are set per-path in JS (real glyph geometry); this
   file only owns the actual look of the draw-in and ink-fill. */
.hw { display: inline-block; overflow: visible; height: 1em; vertical-align: -0.08em; }
.hw__fill {
  fill: currentColor; opacity: 0;
  transition: opacity .45s var(--ease);
  transition-delay: var(--start, 0s);
}
.hw__stroke {
  fill: none; stroke: currentColor; stroke-width: 1.8px;
  stroke-linecap: round; stroke-linejoin: round;
  /* Hidden by default (a dash/offset far longer than any real glyph
     contour) until JS measures the path and sets --len to its true length. */
  stroke-dasharray: var(--len, 9999);
  stroke-dashoffset: var(--len, 9999);
  transition: stroke-dashoffset var(--dur, .9s) var(--ease);
  transition-delay: var(--start, 0s);
}
.hw.is-drawn .hw__stroke { stroke-dashoffset: 0; }
.hw.is-drawn .hw__fill { opacity: 1; }
.hero__body { font-size: 20px; line-height: normal; }
.hero__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap-xs); }
/* Scoped to the hero only — .btn--secondary is shared with the Connect
   section's Linkedin/Résumé buttons, which should keep their white background. */
.hero__actions .btn--secondary { background: #f8fafc; }

.hero__portrait {
  /* Explicit px width/height (not bottom + aspect-ratio) — the aspect-ratio
     variant measured correctly via getBoundingClientRect but silently failed
     to paint the image in this environment. Fixed values, same pattern as
     the rest of the hero, render reliably.
     Sized to 70% of the original 441×458, then +15% (bottom stays flush with
     the hero edge: top recalculated as heroHeight - newHeight). */
  position: absolute; left: 74px; top: 217px; width: 385px; height: 400px;
  overflow: hidden; cursor: pointer;
}
.hero__portrait img { width: 100%; height: 100%; object-fit: cover; object-position: center top; }

/* Decorative liquid-glass cursor + "nare" tag, sitting over the lower-left
   of the portrait — position is tied to the desktop portrait's box (left
   74px, top 217px, 385x400), so it's desktop-only (hidden at ≤1200px where
   the portrait becomes a normal-flow tablet/mobile layout instead). */
/* A flat exported image can't have a live blur of what's behind it, so the
   glass spec below (Light -45°/80%, Refraction 70, Depth 23.51,
   Dispersion 80, Frost 3.53, Splay 8) is built as two real backdrop-blur
   layers — matching the source SVG's exact arrow path and tag rect — sitting
   behind the flat asset, which stays on top for its precise shape/text.
     Frost      → backdrop-filter blur amount (3.53px, literal)
     Refraction → backdrop-filter saturate/contrast boost (vibrancy through glass)
     Light      → the -45°, 80%-opacity diagonal highlight on each layer
     Depth      → the drop-shadow blur radius (23.51px, literal)
     Dispersion → a red/blue drop-shadow fringe, opacity scaled from 80/100
     Splay      → the fringe's offset distance (8 ÷ 10 = 0.8px) */
.hero__cursor {
  position: absolute; left: 54px; top: 405px; width: 150px; height: 127px; z-index: 2;
  /* Clickable (see hero() in landing.js) — a click on the portrait or
     directly on this decoration plays the tour below once. Not inside
     .hero__clip (see above), so the tour's bottom stop can swing past the
     hero's own box, in front of the section below, instead of being cut
     off at the hero's edge. */
  pointer-events: auto; cursor: pointer;
  filter:
    drop-shadow(-0.8px 0 0 rgba(255, 70, 130, 0.4))
    drop-shadow(0.8px 0 0 rgba(60, 170, 255, 0.4))
    drop-shadow(0 6px 23.51px rgba(5, 47, 74, 0.28));
}
.hero__cursor.is-touring { animation: hero-cursor-tour 3s var(--ease) 1; }
.hero__cursor img { width: 100%; height: 100%; display: block; position: relative; }
/* A small ring at the arrow's tip, pulsing in sync with each "press" beat
   of hero-cursor-tour below — same duration so the percentages line up in
   wall-clock time even though it's a separate element/animation. */
.hero__cursor__click {
  position: absolute; left: 75px; top: 33px; width: 14px; height: 14px;
  border-radius: 50%; background: rgba(255, 255, 255, .9);
  box-shadow: 0 0 0 1.5px rgba(0, 132, 209, .6);
  opacity: 0; transform: scale(.4);
}
.hero__cursor.is-touring .hero__cursor__click { animation: hero-cursor-click 3s var(--ease) 1; }

/* Three stops over the portrait, a click pulse at each, then home — offsets
   are translate() from the resting left/top above, not new positions, so
   "home" is always exactly translate(0, 0). Plays once per click (see
   .is-touring above), not on a loop. */
@keyframes hero-cursor-tour {
  0%, 18.2%      { transform: translate(0, 0) scale(1); }
  27.3%          { transform: translate(141px, -155px) scale(1); }
  29.1%          { transform: translate(141px, -155px) scale(.86); }
  30.9%, 39.4%   { transform: translate(141px, -155px) scale(1); }
  48.5%          { transform: translate(206px, 25px) scale(1); }
  50.3%          { transform: translate(206px, 25px) scale(.86); }
  52.1%, 60.6%   { transform: translate(206px, 25px) scale(1); }
  69.7%          { transform: translate(36px, 95px) scale(1); }
  71.5%          { transform: translate(36px, 95px) scale(.86); }
  73.3%, 81.8%   { transform: translate(36px, 95px) scale(1); }
  100%           { transform: translate(0, 0) scale(1); }
}
@keyframes hero-cursor-click {
  0%, 28.8%, 31.8%, 50%, 53%, 71.2%, 74.2%, 100% { opacity: 0; transform: scale(.4); }
  29.1%, 50.3%, 71.5% { opacity: 1; transform: scale(.5); }
  31.5%, 52.7%, 73.9% { opacity: 0; transform: scale(1.8); }
}
.hero__cursor__glass {
  position: absolute;
  --glass-tint: rgba(0, 132, 209, 0.4);
  backdrop-filter: blur(3.53px) saturate(170%) contrast(108%);
  -webkit-backdrop-filter: blur(3.53px) saturate(170%) contrast(108%);
  background:
    linear-gradient(-45deg, rgba(255, 255, 255, .8) 0%, rgba(255, 255, 255, 0) 55%),
    var(--glass-tint);
}
.hero__cursor__glass--arrow {
  inset: 0;
  --glass-tint: rgba(0, 132, 209, 0.32);
  clip-path: path('M124.428 29.4803C125.536 24.1865 119.869 20.0691 115.176 22.7584L82.8254 41.2991C78.0677 44.0258 78.8579 51.116 84.0992 52.7283L96.8629 56.6546C98.2682 57.0869 99.4769 57.9995 100.277 59.2327L105.555 67.3625C108.601 72.0549 115.802 70.7091 116.948 65.2333L124.428 29.4803Z');
}
.hero__cursor__glass--tag {
  left: 0.294px; top: 71px; width: 95.227px; height: 55.255px; border-radius: 9.46px;
  --glass-tint: rgba(0, 132, 209, 0.2);
  /* More blur, less tint than the arrow — the reference shows the arm
     clearly blurring through the tag, while the arrow stays fairly solid. */
  backdrop-filter: blur(7px) saturate(170%) contrast(108%);
  -webkit-backdrop-filter: blur(7px) saturate(170%) contrast(108%);
}

/* --------------------------------------------------------------------------
   6. Highlights
   -------------------------------------------------------------------------- */
.highlights { display: flex; gap: 50px; align-items: stretch; }
.highlight { flex: 1 1 0; min-width: 0; display: flex; align-items: flex-start; gap: 20px; }
.highlight__icon {
  /* Height of a 2-line title (20px, line-height: normal): measured 49px. */
  flex: none; width: 49px; height: 49px; border-radius: var(--r-md);
  background: var(--c-surface); overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  font-size: 22px; line-height: 1;
}
.highlight__text { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.highlight__text h3 { font-weight: 700; font-size: 20px; line-height: normal; }
.highlight__text p { font-weight: 400; font-size: 16px; line-height: normal; }

/* --------------------------------------------------------------------------
   7. Work
   -------------------------------------------------------------------------- */
.work { display: flex; flex-direction: column; gap: var(--gap-lg); }
.work-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 48px; }

.work-card { display: flex; flex-direction: column; gap: var(--gap-sm); }
.work-card__media {
  position: relative; aspect-ratio: 664 / 330; border-radius: var(--r-xl);
  background: var(--c-surface); overflow: hidden;
}
.work-card__media img { width: 100%; height: 100%; object-fit: cover; transform: translateX(var(--cover-x, 0px)) scale(var(--cover-scale, 1)); transition: transform .5s var(--ease); }
.work-card:hover .work-card__media img { transform: translateX(var(--cover-x, 0px)) scale(calc(var(--cover-scale, 1) * 1.03)); }
.work-card__media--framed { background: var(--cover-bg); }
.work-card__media--framed img { object-fit: contain; }
.work-card__media--framed.work-card__media--fit-cover img { object-fit: cover; }
.work-card__media .tag { position: absolute; left: 24px; top: 24px; }
.work-card__meta { display: flex; flex-direction: column; gap: var(--gap-2xs); }
.work-card__meta h3 {
  /* Landing-page work-card titles only — sized independently of the
     case-study page's .cs-text h2 (28px, hardcoded to match Figma). */
  font-family: var(--font-display); font-weight: 700; font-size: 20px;
  line-height: normal; color: var(--c-ink);
}
.work-card__meta p { font-size: 16px; line-height: 1.5; color: var(--c-muted); }

/* --------------------------------------------------------------------------
   8. About
   -------------------------------------------------------------------------- */
.about { display: flex; align-items: center; gap: var(--gap-md); padding-block: 166px; }
.about__text { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: var(--gap-md); }
.about__text h2 { font-weight: 700; font-size: var(--fs-h1); line-height: 1.1; letter-spacing: -1px; }
.about__text p { font-size: var(--fs-body-lg); line-height: normal; }

/* A tall "window" the same height as the text column (align-self: stretch),
   masking a slow-scrolling vertical strip of photos — start of the section
   to the end of it. */
.about__gallery {
  flex: none; align-self: stretch; width: 220px;
  position: relative; overflow: hidden; border-radius: 9.883px;
  background: var(--c-surface);
}
.about__gallery-track {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; flex-direction: column; align-items: center; gap: 20px;
  animation: about-gallery-scroll 32s linear infinite;
}
@keyframes about-gallery-scroll {
  from { transform: translateY(-50%); }
  to   { transform: translateY(0); }
}
.about__gallery-item {
  flex: none; width: 180px; height: 180px; border-radius: 16px;
  overflow: hidden; background: var(--c-white); box-shadow: 0 6px 16px rgba(5, 47, 74, .12);
}
.about__gallery-item img { width: 100%; height: 100%; object-fit: cover; }
/* Alternating tilt — 4 of every 6 crooked, 2 left straight — repeats
   identically across the doubled set so the loop reads as one continuous
   strip, not two different ones stitched together. */
.about__gallery-item:nth-child(6n+1) { transform: rotate(-4deg); }
.about__gallery-item:nth-child(6n+2) { transform: rotate(3deg); }
.about__gallery-item:nth-child(6n+4) { transform: rotate(-3deg); }
.about__gallery-item:nth-child(6n+5) { transform: rotate(5deg); }

/* --------------------------------------------------------------------------
   9. Testimonials
   -------------------------------------------------------------------------- */
.testimonials { display: flex; flex-direction: column; gap: var(--gap-lg); }
.testimonials__body { display: flex; flex-direction: column; align-items: center; gap: 30px; }

/* One testimonial at a time — quote, then role/company underneath — swapped
   with a brief fade/blur when a different person is picked below. */
.t-display {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--gap-sm);
  max-width: 760px; text-align: center;
}
.t-display__quote {
  margin: 0; font-weight: 300; font-size: 16px; line-height: 1.6;
  color: var(--c-ink); white-space: pre-wrap;
  transition: opacity .4s var(--ease), filter .4s var(--ease), transform .4s var(--ease);
}
.t-display__role {
  margin: 0; font-family: var(--font-ui); font-weight: 600; font-size: var(--fs-note);
  letter-spacing: .2em; text-transform: uppercase; color: var(--c-muted);
  transition: opacity .4s var(--ease), transform .4s var(--ease);
}
.t-display.is-animating .t-display__quote,
.t-display.is-animating .t-display__role {
  opacity: 0; filter: blur(4px); transform: translateY(4px) scale(.98);
}

/* Avatar "pill" switcher — collapsed to a bare avatar; the active (or
   hovered) pick grows a dark pill and reveals the person's name beside it. */
.t-switcher { display: flex; justify-content: center; align-items: center; gap: var(--gap-3xs); }
.t-switcher__item {
  flex: none; display: flex; align-items: center;
  padding: 3px; border-radius: var(--r-pill);
  background: transparent; border: 0; cursor: pointer;
  transition: background-color .3s var(--ease), padding .3s var(--ease);
}
.t-switcher__item:hover,
.t-switcher__item[aria-current="true"] { padding: 4px 14px 4px 4px; }
.t-switcher__item[aria-current="true"] { background: var(--c-brand-950); }
.t-switcher__item:hover:not([aria-current="true"]) { background: var(--c-border); }

.t-switcher__item img {
  flex: none; width: 32px; height: 32px; border-radius: 50%; object-fit: cover;
  transition: box-shadow .3s var(--ease);
}
.t-switcher__item[aria-current="true"] img { box-shadow: 0 0 0 2px rgba(255, 255, 255, .35); }

.t-switcher__name {
  display: inline-block; max-width: 0; margin-left: 0; overflow: hidden; white-space: nowrap;
  opacity: 0;
  font-family: var(--font-ui); font-weight: 600; font-size: var(--fs-note); color: var(--c-white);
  transition: max-width .3s var(--ease), margin-left .3s var(--ease), opacity .25s var(--ease), color .2s var(--ease);
}
.t-switcher__item:hover .t-switcher__name,
.t-switcher__item[aria-current="true"] .t-switcher__name {
  max-width: 200px; margin-left: 8px; opacity: 1;
}
.t-switcher__item:hover:not([aria-current="true"]) .t-switcher__name { color: var(--c-brand-950); }

/* --------------------------------------------------------------------------
   10. Connect (CTA band)
   -------------------------------------------------------------------------- */
.connect {
  position: relative; overflow: hidden;
  padding: 100px var(--gutter);
  display: flex; flex-direction: column; align-items: center; gap: 30px;
}
.connect__bg { position: absolute; inset: 0; pointer-events: none; }
.connect__bg img { width: 100%; height: 100%; object-fit: cover; opacity: .2; }
.connect__bg::after { content: ""; position: absolute; inset: 0; background: var(--grad-connect); }
.connect__blob { position: absolute; pointer-events: none; }
.connect__blob--1 { left: calc(50% - 756.5px + 133px); top: 53px;   width: 458px; height: 458px; }
.connect__blob--2 { left: calc(50% - 756.5px + 922px); top: -103px; width: 362px; height: 362px; }
.connect__copy {
  position: relative; width: 800px; max-width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: var(--gap-xs); text-align: center;
}
.connect__copy h2 {
  font-weight: 500; font-size: 40px; line-height: normal; letter-spacing: -1.92px;
  color: var(--c-primary);
}
.connect__copy p { font-size: 20px; line-height: 1.6; color: var(--c-muted-2); }
.connect__actions { position: relative; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--gap-xs); }

/* --------------------------------------------------------------------------
   11. Footer
   -------------------------------------------------------------------------- */
.site-footer { border-top: 1px solid var(--c-border); padding: var(--gap-md) var(--gutter); }
.site-footer__inner { max-width: var(--page-max); margin-inline: auto; display: flex; flex-direction: column; gap: var(--gap-xl); }
.footer-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--gap-md); }
.footer-brand { width: 360px; max-width: 100%; display: flex; flex-direction: column; gap: var(--gap-xs); }
.footer-brand__logo { display: flex; align-items: center; gap: var(--gap-3xs); }
.footer-brand__logo img { width: 32px; height: 32px; border-radius: 8px; object-fit: contain; background: var(--c-brand-100); }
.footer-brand p { font-size: var(--fs-caption); line-height: 1.5; }
.footer-links { display: flex; gap: 80px; }
.footer-links__col { display: flex; flex-direction: column; gap: var(--gap-xs); }
.footer-links__col h3 { font-weight: 700; font-size: var(--fs-caption); }
.footer-links__col a,
.footer-links__col span {
  font-family: var(--font-ui); font-weight: 400; font-size: var(--fs-caption); white-space: nowrap;
}
.footer-links__col a:hover { color: var(--c-primary); }
.footer-bottom { font-family: var(--font-ui); font-size: var(--fs-note); }

/* --------------------------------------------------------------------------
   12. Back to top
   -------------------------------------------------------------------------- */
.back-to-top {
  position: fixed; right: 32px; bottom: 32px; z-index: 40;
  width: 52px; height: 52px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  color: var(--c-primary);
  /* Same liquid-glass treatment as the scrolled header: translucent +
     saturated blur, a glassy top edge, a soft lift shadow. */
  background: rgba(255, 255, 255, 0.55);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 8px 24px rgba(5, 47, 74, 0.16);
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity .3s var(--ease), transform .3s var(--ease),
              visibility .3s, box-shadow .18s var(--ease), background-color .18s var(--ease);
}
.back-to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.back-to-top:hover,
.back-to-top:active { opacity: .5; }
.back-to-top svg { width: 20px; height: 20px; display: block; }

/* --------------------------------------------------------------------------
   13. Image stub — shown when a file in assets/images/ is missing
   -------------------------------------------------------------------------- */
.img-stub {
  width: 100%; height: 100%; min-height: 80px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 12px; text-align: center;
  background: var(--c-surface);
  box-shadow: inset 0 0 0 1.5px rgba(100, 116, 139, .25);
  font-family: var(--font-ui); color: var(--c-muted);
}
.img-stub__label { font-size: 13px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; }
.img-stub__path { font-size: 12px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; word-break: break-all; opacity: .8; }
.img-stub--sm .img-stub__label { font-size: 10px; }
.img-stub--sm .img-stub__path { display: none; }

/* --------------------------------------------------------------------------
   14. Case study page (Figma "Work 1", node 105:2141)
   -------------------------------------------------------------------------- */
.case-study { display: flex; flex-direction: column; gap: var(--gap-xl); }
.case-study__header { display: flex; flex-direction: column; gap: 20px; }
/* Two one-off gaps, scoped by adjacency rather than changing .case-study's
   own gap (which spaces every top-level block) — negative margin-top pulls
   the next block in from the default 60px to the requested size. */
.case-study__header + .cs-image { margin-top: -30px; }   /* badges → cover image: 30px */
.case-study__header + .cs-image + .cs-grid { margin-top: -40px; } /* cover image → NDA note: 20px */
.case-study__header + .cs-image + .cs-text { margin-top: -30px; }  /* cover image → first section: 30px */
.case-study__header h1 {
  font-weight: 700; font-size: var(--fs-h1-lg); line-height: 1.1;
  letter-spacing: -1px; color: var(--c-ink);
}
.case-study__header p {
  font-family: var(--font-ui); font-weight: 400; font-size: var(--fs-body);
  line-height: 1.6; color: var(--c-muted);
}
.case-study__link { color: var(--cs-accent, var(--c-primary)); text-decoration: underline; }
.case-study__link:hover { opacity: .7; }
.cs-badges { display: flex; flex-wrap: wrap; gap: 10px; }
.cs-badge {
  background: var(--cs-accent-soft, var(--c-surface)); color: var(--cs-accent, var(--c-primary));
  font-family: var(--font-ui); font-weight: 700; font-size: 11px; letter-spacing: 1px;
  padding: 8px 16px; border-radius: var(--r-pill);
}

.cs-hero {
  position: relative; aspect-ratio: 1353 / 350; border-radius: var(--r-xl);
  background: var(--c-surface); overflow: hidden;
}
.cs-hero img { width: 100%; height: 100%; object-fit: cover; }
.cs-hero .tag { position: absolute; left: 24px; top: 24px; font-size: 11px; }

/* Groups a run of text blocks at a tighter gap than the page's own 60px
   between top-level blocks — Figma's "portfolio-grid" sections. */
.cs-grid { display: flex; flex-direction: column; gap: 30px; width: 100%; }

.cs-text { display: flex; flex-direction: column; gap: var(--gap-2xs); }
.cs-text h2 {
  font-family: var(--font-display); font-weight: 700; font-size: 28px;
  line-height: normal; color: var(--c-ink);
}
.cs-text p {
  font-family: var(--font-ui); font-weight: 400; font-size: var(--fs-caption);
  line-height: 1.5; color: var(--c-muted);
}
.cs-text > * + * { margin-top: var(--cs-text-gap, var(--gap-2xs)); }
.cs-text strong { font-weight: 600; }
.cs-text .cs-list--disc { list-style: disc; }
.cs-text .cs-list--flush { margin-top: calc(-1 * var(--gap-2xs)); }
/* The small italic NDA-style disclaimer — no heading, just one paragraph. */
.cs-text--note p { font-style: italic; color: var(--c-primary); font-size: var(--fs-body); }

.cs-text ol, .cs-text ul { margin: 0; padding-left: 24px; }
.cs-text li { font-family: var(--font-ui); font-size: var(--fs-caption); line-height: 1.5; color: var(--c-muted); }
/* The Impact/Insight callout style — no native marker, an arrow glyph
   instead, bold primary-blue text. */
.cs-list--impact { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.cs-list--impact li { display: flex; align-items: center; gap: 12px; }
.cs-list--impact img { flex: none; width: 20px; height: 9px; }
.cs-list--impact span {
  font-family: var(--font-ui); font-weight: 600; font-size: var(--fs-caption);
  line-height: 1.5; color: var(--c-primary);
}

/* Insight as arrow + accent title + description — the arrow is a mask so it
   takes the page accent colour (--cs-accent). */
.cs-text .cs-list--insights { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.cs-insight__head { display: flex; align-items: center; gap: 11px; }
.cs-arrow {
  flex: none; width: 24px; height: 10.4px; background: var(--cs-accent, var(--c-primary));
  -webkit-mask: url("../assets/icons/arrow-right.svg") center / 100% 100% no-repeat;
          mask: url("../assets/icons/arrow-right.svg") center / 100% 100% no-repeat;
}
.cs-insight__title {
  font-family: var(--font-ui); font-weight: 600; font-size: var(--fs-caption);
  line-height: 1.5; color: var(--cs-accent, var(--c-primary));
}
.cs-list--insights p { padding-left: 35px; }

/* A row of icon+text cards (Impact) — distinct from the arrow-bullet list
   above (Insight uses that one still). */
.cs-cards { display: flex; gap: var(--cs-cards-gap, var(--gap-sm)); width: 100%; }
.cs-card {
  flex: 1 1 0; min-width: 0; background: var(--cs-accent-soft, var(--c-surface)); border-radius: var(--r-lg);
  padding: 20px; display: flex; flex-direction: column; align-items: center; gap: 10px;
  text-align: center;
}
.cs-card img { flex: none; width: 24px; height: 24px; }
.cs-card span {
  font-family: var(--font-ui); font-weight: 600; font-size: 16px;
  line-height: 1.5; color: var(--cs-accent, var(--c-primary));
}

.cs-image {
  aspect-ratio: 1353 / 400; border-radius: var(--r-xl);
  background: var(--c-surface); overflow: hidden;
  /* Only takes effect for a block given a literal `height` (see imageBlock
     in case-study.js) — unset elsewhere, so it falls through to auto and
     leaves the aspect-ratio-driven sizing above alone. */
  height: var(--cs-image-h, auto);
}
.cs-image img { width: 100%; height: 100%; object-fit: cover; }
/* A cover can opt into a solid background instead of cropping to fill — for
   a UI-mockup image with transparent margins rather than a bleed photo
   (same pattern as .work-card__media--framed on the landing page). */
.cs-image--framed { aspect-ratio: 1353 / 350; background: var(--cover-bg); }
.cs-image--framed img { object-fit: contain; }
.cs-image--framed.cs-image--fit-cover img { object-fit: cover; }
.cs-figure { display: flex; flex-direction: column; gap: var(--gap-2xs); }
.cs-figure figcaption {
  font-family: var(--font-ui); font-size: var(--fs-note); color: var(--c-muted);
}

/* Any two blocks side by side (Problem Statement+Goals is text+text;
   Testing Focus is text+image; A/B Test Results is text+image-row). Each
   side shares the row equally unless overridden below. */
.cs-split { display: flex; gap: var(--cs-split-gap, var(--gap-xl)); align-items: flex-start; width: 100%; }
.cs-split .cs-text { flex: 1 1 0; min-width: 0; }
.cs-split .cs-image { flex: 0 0 624px; aspect-ratio: 624 / 478; border-radius: 19px; }
/* A split image given its own literal width/height (see imageBlock). */
.cs-split > .cs-image--fixed-w { flex: 0 0 var(--cs-image-w); aspect-ratio: auto; }

/* Two or more smaller companion images side by side. Sized one way as a
   standalone closing gallery strip (each item hugs its own natural aspect
   ratio at a shared row height — see the `.case-study >` rules below), and
   differently when paired with text in a "split" (A/B Test Results) — see
   .cs-split--gallery, which narrows the text column to make room. */
.cs-image-row { display: flex; gap: var(--gap-sm); width: 100%; }
.cs-image-row .cs-image { flex: 1 1 0; min-width: 0; aspect-ratio: 9 / 10; border-radius: var(--r-xl); }
/* The closing gallery only (a direct child of .case-study — the A/B Test
   Results image-row lives inside a .cs-split, so this doesn't reach it).
   Screen recordings are tall and narrow, the comparison graphic is short
   and wide; forcing them to equal-width squares would crop all of them, so
   instead each hugs its own natural width at one shared height, and the
   framed comparison graphic fills whatever width is left over. */
.case-study > .cs-image-row { height: 380px; }
.case-study > .cs-image-row .cs-image {
  flex: 0 0 auto; width: auto; height: 100%; aspect-ratio: auto; background: none;
}
.case-study > .cs-image-row .cs-image img,
.case-study > .cs-image-row .cs-image video { width: auto; height: 100%; object-fit: contain; display: block; }
.case-study > .cs-image-row .cs-image--framed { flex: 1 1 0; width: auto; background: var(--cover-bg); }
.case-study > .cs-image-row .cs-image--framed img,
.case-study > .cs-image-row .cs-image--framed video { width: 100%; }
.cs-split .cs-image-row { flex: 1 1 0; width: auto; }
.cs-split .cs-image-row .cs-image { flex: 1 1 0; aspect-ratio: 6 / 5; border-radius: 14px; }
/* An item given its own literal width/height (see imageBlock in
   case-study.js) holds that fixed size instead of sharing the row equally —
   both dimensions come from the element's own inline custom properties. */
.cs-split .cs-image-row .cs-image--fixed-w { flex: 0 0 var(--cs-image-w); aspect-ratio: auto; }

/* A text+image-row split specifically (A/B Test Results): the images are
   now a fixed-width vertical stack (see below), so the text column fills
   whatever width is left over instead of sharing the row evenly. */
.cs-split--gallery .cs-text { flex: 1 1 auto; min-width: 0; }
.cs-split--gallery .cs-image-row { flex: 0 0 auto; }
/* A/B Test Results stacks its two images vertically rather than side by
   side (see .cs-image-row above, the standalone closing-gallery strip stays
   a row). flex-basis governs height once the axis flips to column, so the
   fixed-width item needs its width set directly instead. */
.cs-split--gallery .cs-image-row { flex-direction: column; }
.cs-split--gallery .cs-image-row .cs-image--fixed-w { flex: 0 0 auto; width: var(--cs-image-w); }

/* A row of boxed steps joined by arrows (Reflection's roadmap). */
.cs-flow { display: flex; align-items: center; gap: 6px; width: 100%; }
.cs-flow__step {
  flex: 1 1 0; min-width: 0; min-height: 173px; padding: 20px; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center; text-align: center;
  background: var(--cs-accent-soft, var(--c-surface)); border: 2px solid var(--cs-accent, var(--c-primary));
  border-radius: 12px;
}
.cs-flow__step p {
  font-family: var(--font-ui); font-size: 14px; line-height: 1.5;
  color: var(--cs-accent, var(--c-primary));
}
.cs-flow__arrow { flex: none; width: 133px; height: 30px; }

.cs-notfound { display: flex; flex-direction: column; gap: var(--gap-xs); align-items: flex-start; }

/* --------------------------------------------------------------------------
   15. Responsive
   -------------------------------------------------------------------------- */
@media (max-width: 1200px) {
  .hero { height: auto; padding: calc(var(--header-h) + 40px) var(--gutter) 60px; }
  .hero__copy,
  .hero__portrait,
  .hero__blob { position: static; transform: none; }
  .hero__inner {
    /* The .hero__bg overlay is absolutely positioned and would otherwise
       paint over the copy now that it is back in normal flow. */
    position: relative; z-index: 1;
    /* flex-end, not center: the copy block is the taller item here (it
       wraps to several lines), so bottom-aligning sits the portrait flush
       with its last line instead of floating in the middle with a gap
       underneath. */
    display: flex; align-items: flex-end; justify-content: center; gap: var(--gap-md);
    max-width: var(--page-max); margin-inline: auto;
  }
  /* Only the portrait bleeds past the section's own bottom padding, down to
     the hero's true edge — the copy block keeps its normal breathing room
     above it. flex-end above still aligns the portrait with the row's
     bottom first; this then pushes it the padding's own height further. */
  .hero__portrait { width: 306px; height: 319px; flex: none; transform: translateY(60px); }
  .hero__copy { width: auto; flex: 1 1 0; min-width: 0; max-width: 598px; }
  .hero__blob { display: none; }
  .hero__cursor { display: none; }
  /* .hero__clip (position:absolute; inset:0) needs .hero to have a definite
     height to stretch to — true on desktop (.hero has a fixed height) but
     not here, where .hero switches to height:auto. Its own children are
     back in normal flow at this breakpoint too (above), and the cursor
     it exists to let escape is hidden here anyway, so it can just be a
     normal block and size to its content like everything else. Left as
     position:absolute, .hero collapses to its own padding (no in-flow
     content to derive a height from) and clips the entire hero to a sliver. */
  .hero__clip { position: static; overflow: visible; }
  .about { padding-block: 80px; }
  .footer-links { gap: 48px; }
}

@media (max-width: 1000px) {
  .work-grid { grid-template-columns: minmax(0, 1fr); }
  .highlights { flex-direction: column; gap: var(--gap-md); }
  .highlight { max-width: 560px; }
  .t-card { flex-basis: min(620px, calc(100vw - var(--gutter) * 2)); }
  .connect__blob { display: none; }
}

@media (max-width: 860px) {
  .site-nav__links {
    display: none; position: absolute; top: var(--header-h); right: var(--gutter);
    flex-direction: column; align-items: stretch; gap: 4px; padding: 8px;
    background: var(--c-white); border: 1px solid var(--c-border);
    border-radius: var(--r-md); box-shadow: 0 12px 32px rgba(5, 47, 74, .12); min-width: 180px;
  }
  .site-nav__links.is-open { display: flex; }
  .site-nav__links .btn { justify-content: flex-start; height: 44px; padding: 10px 16px; }
  .nav-toggle { display: inline-flex; }
  .site-header {
    background: rgba(255, 255, 255, 0.55);
    -webkit-backdrop-filter: blur(20px) saturate(180%);
    backdrop-filter: blur(20px) saturate(180%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 8px 24px rgba(5, 47, 74, 0.10);
  }
  /* Résumé moves into the menu with the other links; the header's own copy
     (next to the toggle) steps aside so it isn't shown twice. */
  .nav-cta--header { display: none; }
  .nav-cta--in-menu { display: inline-flex; }

  .hero { padding-bottom: 0; }
  /* align-items: center overrides the tablet rule's flex-end — in a row
     that meant "bottom", but in this column layout the same property means
     "horizontal side", which was right-aligning the portrait. */
  .hero__inner { flex-direction: column; align-items: center; text-align: center; }
  /* Text and buttons read first on a stacked layout; the portrait follows,
     flush with the hero's own bottom edge (padding-bottom above is 0). */
  .hero__copy { order: 1; }
  .hero__portrait {
    order: 2; width: min(258px, 64vw); height: auto; aspect-ratio: 450 / 468;
    transform: translateY(-5px); /* mobile only — nudged up 5px */
  }
  .hero__title { font-size: 32px; }
  /* The two sentences are separate <p> elements (block-level), which forces
     a line break between them regardless of font size — the short first
     sentence would always cost its own line. Flowing them inline lets the
     wrap reclaim that space; 12px is the largest size that still lands the
     whole passage in 3 lines at this width. */
  .hero__body p { display: inline; }
  .hero__body p:first-child { margin-right: 0.3em; }
  .hero__body { font-size: 14px; }
  .hero__actions .btn { font-size: 13px; padding: 10px 14px; }
  .about { flex-direction: column; align-items: stretch; gap: var(--gap-md); }
  /* Column layout now — align-self: stretch would fill the width instead of
     the height, so the marquee gets its own fixed-height window here. */
  .about__gallery { align-self: center; width: 100%; max-width: 320px; height: 320px; }
  .footer-top { flex-direction: column; gap: var(--gap-md); }
  .footer-links { gap: 40px; flex-wrap: wrap; }
  .cs-hero { aspect-ratio: 4 / 3; }
  .cs-image { aspect-ratio: 4 / 3; }
  /* Only takes effect where --cs-image-h is actually set (a literal-height
     block); calc() against an unset custom property is invalid, so this
     harmlessly falls back to the rules above for every other .cs-image. */
  .cs-image { height: calc(var(--cs-image-h) * 0.6); }
  .cs-split { flex-direction: column; }
  .cs-split .cs-image { flex-basis: auto; width: 100%; }
  .cs-image-row { flex-direction: column; }
  /* Reset the desktop-only shared-height/natural-width sizing (see the
     `.case-study >` rules above) back to a plain full-width stack. */
  .case-study > .cs-image-row { height: auto; }
  .case-study > .cs-image-row .cs-image--framed { flex: none; }
  .case-study > .cs-image-row .cs-image { width: 100%; height: auto; }
  .case-study > .cs-image-row .cs-image img,
  .case-study > .cs-image-row .cs-image video { width: 100%; height: auto; }
  .cs-split .cs-image-row { width: 100%; }
  .cs-split .cs-image-row .cs-image { flex-basis: auto; width: 100%; }
  .cs-split .cs-image-row .cs-image--fixed-w { flex-basis: auto; width: 100%; }
  .cs-split--gallery .cs-text { flex-basis: auto; width: 100%; }
  .cs-cards { flex-direction: column; }
  .cs-split > .cs-image--fixed-w { flex-basis: auto; width: 100%; }
  .cs-flow { flex-direction: column; }
  .cs-flow__step { width: 100%; flex: none; }
  .cs-flow__arrow { transform: rotate(90deg); margin: 52px 0; }
}

@media (max-width: 560px) {
  .wordmark { font-size: 18px; }
  .site-nav { gap: var(--gap-2xs); }
  .site-header__inner .btn--dark { height: 44px; padding: 10px 18px; }
  .t-card { padding: var(--gap-sm); }
  .connect__actions { gap: var(--gap-xs); flex-direction: column; align-items: stretch; width: 100%; max-width: 320px; }
  .hero__actions { width: 100%; }
  .section--tall { padding-block: 64px; }
  .connect { padding-block: 64px; }
  .back-to-top { right: 16px; bottom: 16px; width: 46px; height: 46px; }
  .back-to-top svg { width: 18px; height: 18px; }
}
