/* ==========================================================================
   responsive.css — cross-browser responsive layer
   --------------------------------------------------------------------------
   Load this AFTER normalize.css, webflow.css and diagnostic-evidence.webflow.css
   on every page.

   The export contains a handful of constructs that cannot shrink, plus a few that
   Blink (Chrome/Edge) resolves favourably while WebKit (Safari, and every browser
   on iOS, since they all use WebKit) does not. Measured in WKWebView at 320–1440px:

     1. `.text-align_center` — a text-centering utility — also carries
        `padding-left/right: 220px` at every breakpoint, with border-box sizing.
        440px of padding cannot shrink, so on a 390px phone the hero headline's
        used width bottoms out at 440px and its text wraps at roughly one
        character per line. Biggest single cause of the broken mobile layout.
     2. `aspect-ratio: 3 / 2` left on the project-card grid at every breakpoint.
        Once the grid stacks to one column the content is far taller than 3:2, and
        WebKit resolves the box's *width* back out of that height: the card's
        inner grid computed 1361px wide inside a 320px card, then got clipped by
        `.card { overflow: hidden }`. Blink keeps the width and grows the height,
        which is why this looked fine in Chrome and broken in Safari.
     3. An invalid `grid-template` shorthand on `.work-experience-grid`
        (four area columns against a five-track list) — the whole declaration is
        discarded and the grid silently falls back to two columns.
     4. Grid items placed past the end of the explicit grid (the bio heading ends
        at column 7 in a 5-column grid), which spawns implicit columns and
        squeezes its siblings down to a fraction of their intended width.
     5. Container-query length units (`3cqw` / `12cqw`) on the hero headline with
        no `container-type` ancestor anywhere on the page.
     6. `grid-auto-rows: 1fr` under overlapping hero grid areas.
     7. Small ergonomic issues that read as "broken" on a phone: `white-space:
        nowrap` on buttons, 14px form inputs (iOS auto-zooms below 16px), and no
        safe-area padding on notched iPhones.

   Everything below replaces those with deterministic equivalents that compute
   the same way in WebKit, Blink and Gecko. Desktop rendering is unchanged.

   Specificity note: the export places rules like
       #w-node-abc.w-node-def { ... }
   at (1,1,0). Overrides of those are written with the same #id.class pair and
   win on source order, since this file is loaded last.
   ========================================================================== */


/* ==========================================================================
   0. Baseline / WebKit hardening
   ========================================================================== */

html {
  /* iOS Safari inflates text in landscape without this. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  /* `clip`, not `hidden`: it contains stray horizontal overflow without turning
     <body> into a scroll container, which would break `position: sticky` on the
     project cards. Ignored harmlessly where unsupported. */
  overflow-x: clip;
  max-width: 100%;
}

/* Flex and grid items default to `min-width: auto`, which refuses to shrink below
   their content and is the usual cause of a phone layout that scrolls sideways. */
.w-layout-grid > *,
.w-layout-vflex > *,
.w-layout-hflex > *,
.flex_horizontal > *,
.flex_vertical > *,
.button-group > *,
.card > *,
.card_body {
  min-width: 0;
}

img,
svg,
video,
canvas,
iframe {
  max-width: 100%;
}

img,
svg,
video {
  height: auto;
}

/* `.image_cover` is meant to fill its ratio box — don't let the rule above
   collapse it. */
.image_cover,
.image.image_cover {
  height: 100%;
}

p,
h1,
h2,
h3,
h4,
h5,
h6,
li,
dd,
dt,
blockquote,
a {
  overflow-wrap: break-word;
  word-wrap: break-word;
}


/* ==========================================================================
   1. Fluid typography without container-query units
   --------------------------------------------------------------------------
   `.heading-responsive_xlarge` (the home hero) sizes itself in `cqw`, but
   index.html has no `.heading-responsive_wrapper`, so there is no query
   container to resolve against. Viewport-based `clamp()` reproduces the size
   Chrome renders at desktop widths while staying well-defined everywhere.
   ========================================================================== */

.heading-responsive_xlarge {
  font-size: clamp(2rem, 12vw, 9rem);
  line-height: 1.1;
}

/* The four-class variant is the one that actually wins in the cascade on the
   home page. 3vw matches Chrome's current desktop rendering. */
.heading-responsive_xlarge.text_all-caps.margin-bottom_none.text-align_center {
  font-size: clamp(1.5rem, 3vw, 3.25rem);
  line-height: 1.1em;
}

/* The style guide does supply `.heading-responsive_wrapper`, so container units
   are legitimate there. Keep them, with a viewport fallback if unsupported. */
.heading-responsive_wrapper {
  container-type: inline-size;
}

@supports not (container-type: inline-size) {
  .heading-responsive_large {
    font-size: clamp(2rem, 10vw, 7.5rem);
  }

  .heading-responsive {
    font-size: clamp(1.5rem, 7vw, 5rem);
  }
}


/* ==========================================================================
   2. Containers, sections and safe areas
   ========================================================================== */

/* Scale the design tokens down on small screens rather than overriding dozens of
   individual spacing rules. */
@media screen and (max-width: 767px) {
  :root {
    --ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---card--card-padding: 1.5rem;
    --ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---gap--xxl-gap: 2rem;
    --ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---gap--xl-gap: 1.75rem;
    --ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---gap--lg-gap: 1.5rem;
  }
}

@media screen and (max-width: 479px) {
  :root {
    --ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---card--card-padding: 1.25rem;
    --ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---card--card-radius: .75rem;
  }
}

.container,
.container.is-max,
.container.is-large,
.container.is-small {
  width: 100%;
}

/* Respect the notch and rounded corners in iOS landscape. Kept behind @supports
   so an engine without env()/max() still gets the plain padding above. */
@supports (padding: max(0px, env(safe-area-inset-left))) {
  .container,
  .container.is-max,
  .container.is-large,
  .container.is-small {
    padding-left: max(
      var(--ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---container--container-padding-horizontal),
      env(safe-area-inset-left, 0px)
    );
    padding-right: max(
      var(--ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---container--container-padding-horizontal),
      env(safe-area-inset-right, 0px)
    );
  }
}

@media screen and (max-width: 767px) {
  /* The export gives `.section` 15px side margins here but resets them to 0 on
     the header, so page edges don't line up. Let the container own the
     horizontal rhythm instead. */
  .section {
    margin-left: 0;
    margin-right: 0;
  }

  /* ...and it centres every string inside `.container`, which makes long body
     copy hard to read. Centring is re-applied only where it's asked for. */
  .container {
    text-align: left;
  }

  .container .text-align_center,
  .container .brix---text-center,
  .container .brix---text-center-2,
  .container .brix---text-center-3 {
    text-align: center;
  }
}


/* --------------------------------------------------------------------------
   `.text-align_center` is a text-centering utility, but the export also gives it
       padding-left: 220px; padding-right: 220px;
   at every breakpoint, and it is `box-sizing: border-box`. 440px of padding
   cannot shrink, so on a 390px phone the used width bottoms out at 440px: the
   element is wider than the viewport and its text renders roughly one character
   per line. This is the single largest cause of the broken mobile layout.

   Desktop keeps the intended 220px inset; below the tablet breakpoint it
   becomes proportional and then disappears.
   -------------------------------------------------------------------------- */

@media screen and (max-width: 991px) {
  .text-align_center {
    padding-left: 6vw;
    padding-right: 6vw;
  }
}

@media screen and (max-width: 479px) {
  .text-align_center {
    padding-left: 0;
    padding-right: 0;
  }
}


/* ==========================================================================
   3. Buttons and form controls
   ========================================================================== */

@media screen and (max-width: 479px) {
  /* `white-space: nowrap` at this breakpoint pushes long labels
     ("Say Hello on LinkedIn!") straight off the screen. */
  .button {
    white-space: normal;
  }
}

@media screen and (max-width: 991px) {
  /* Horizontal rows of buttons/chips push past the edge rather than wrapping. */
  .flex_horizontal {
    flex-wrap: wrap;
  }
}

@media screen and (max-width: 767px) {
  .button-group {
    flex-wrap: wrap;
  }

  .button-group > .button {
    max-width: 100%;
  }

  /* iOS Safari zooms the page in when a focused control is under 16px, and does
     not zoom back out on blur — which is what makes a page feel like it lost its
     responsiveness after tapping a field. */
  .w-input,
  .w-select,
  input[type="text"],
  input[type="email"],
  input[type="tel"],
  input[type="number"],
  input[type="password"],
  input[type="search"],
  textarea,
  select {
    font-size: 16px;
  }
}


/* ==========================================================================
   4. Home — hero
   --------------------------------------------------------------------------
   Desktop keeps the overlay (three photos layered around the headline). At
   991px and below it becomes a deterministic stack: headline, then the three
   photos in a single row.
   ========================================================================== */

@media screen and (max-width: 991px) {
  header .grid_1-col {
    grid-auto-rows: auto;
    grid-row-gap: var(--ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---gap--md-gap);
  }

  /* Headline block — out of the overlay, into normal flow. */
  #w-node-_82998fb8-9f40-04b9-baa5-0c9d5cc9b009-5cc9b004.w-node-c9b43fbe-36d1-660b-98c7-5e3a7710ad2a-96912bf5 {
    grid-area: auto;
  }

  /* Photo strip — was spanning rows 1-4 underneath the headline. */
  #w-node-_82998fb8-9f40-04b9-baa5-0c9d5cc9b015-5cc9b004.w-node-c9b43fbe-36d1-660b-98c7-5e3a7710ad3d-96912bf5 {
    grid-area: auto;
    place-self: auto stretch;
  }

  /* The three photos sit side by side instead of at hand-placed 12-column
     positions that no longer make sense once the grid narrows. */
  header .grid_12-col {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-column-gap: var(--ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---gap--xs-gap);
  }

  #w-node-_82998fb8-9f40-04b9-baa5-0c9d5cc9b016-5cc9b004.w-node-c9b43fbe-36d1-660b-98c7-5e3a7710ad34-96912bf5,
  #w-node-_82998fb8-9f40-04b9-baa5-0c9d5cc9b019-5cc9b004.w-node-c9b43fbe-36d1-660b-98c7-5e3a7710ad36-96912bf5,
  #w-node-_82998fb8-9f40-04b9-baa5-0c9d5cc9b01c-5cc9b004.w-node-c9b43fbe-36d1-660b-98c7-5e3a7710ad38-96912bf5 {
    grid-area: auto;
    align-self: stretch;
  }

  header .grid_12-col .image_cover {
    aspect-ratio: 1;
    height: auto;
    border-radius: var(--ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---image--image-radius, .5rem);
  }

  /* A readable, flowing headline instead of five hard-broken lines. */
  .heading-responsive_xlarge {
    text-align: center;
    word-break: normal;
    white-space: normal;
    -webkit-hyphens: none;
    hyphens: none;
  }

  .heading-responsive_xlarge br {
    display: none;
  }

  .heading-responsive_xlarge.text_all-caps.margin-bottom_none.text-align_center {
    font-size: clamp(1.25rem, 3.6vw, 1.75rem);
    line-height: 1.4;
    margin-bottom: 0;
  }
}

@media screen and (max-width: 479px) {
  .heading-responsive_xlarge.text_all-caps.margin-bottom_none.text-align_center {
    font-size: 1.375rem;
    line-height: 1.45;
  }
}


/* ==========================================================================
   5. Home — project cards
   --------------------------------------------------------------------------
   `.ratio_3x2` pins the card's inner grid to a 3:2 box at every width. Once the
   grid stacks, the content is several times taller than 3:2 and is clipped by
   `.card { overflow: hidden }`. Release the ratio as soon as the grid stops
   being two columns.
   ========================================================================== */

@media screen and (max-width: 991px) {
  .card .ratio_3x2,
  .w-layout-grid.ratio_3x2 {
    aspect-ratio: auto;
  }

  /* Sticky stacking cards pile onto each other on a short viewport; read them as
     a plain vertical list instead. */
  .ix_sticky-card {
    position: relative;
    top: auto;
  }
}

/* The project images are 2:3 illustrations with their title along the top edge,
   and `.image_cover` crops with `object-fit: cover`. `.ratio_1x1_mobile-l` squares
   the box off below 768px, which lops the top third — and the title — off every
   one of them. Keep the native ratio wherever the card is stacked. */
@media screen and (max-width: 991px) {
  .card .ratio_2x3,
  .card .ratio_2x3.ratio_1x1_mobile-l {
    aspect-ratio: 2 / 3;
  }
}


/* ==========================================================================
   6. Home — bio block and experience grid
   ========================================================================== */

@media screen and (max-width: 991px) {
  /* The bio grid is `.grid_2-col.grid_5-col`. Its heading was placed 1 → 7 in a
     5-track grid, which generates implicit columns and squeezes the portrait
     down to roughly a sixth of the container. Stack them instead. */
  .grid_2-col.grid_5-col {
    grid-template-columns: minmax(0, 1fr);
    grid-row-gap: var(--ai-gen-82921b10-4b39-48f0-b346-808cf4903d29-1754513569336_sizes---gap--sm-gap);
  }

  #w-node-dcd735a2-427a-f1ea-a792-0e8ce4d38538-e4d38534.w-node-_7a3e8daa-3e9b-2dbb-203f-9f211f975cb6-96912bf5 {
    grid-area: auto;
    justify-self: start;
    width: 100%;
    max-width: 22rem;
    height: auto;
  }

  #w-node-dcd735a2-427a-f1ea-a792-0e8ce4d3853c-e4d38534.w-node-_7a3e8daa-3e9b-2dbb-203f-9f211f975cba-96912bf5 {
    grid-area: auto;
    place-self: auto start;
  }

  /* On desktop this heading sits over the portrait; on mobile it reads as its
     own block. */
  .heading_h2.margin-bottom_none.position_relative {
    position: static;
    text-align: left;
  }

  .carrer-headline-wrap {
    width: 100%;
  }
}

/* The export's base rule is
       grid-template: ". . . ." / 1fr 1fr 1fr 1fr 1fr;
   — four area columns against five tracks, which is invalid, so the declaration
   is discarded and the grid silently falls back to the two columns inherited
   from `.w-layout-grid`. Replace it with a valid, self-adjusting track list:
   five across on desktop, fewer as the viewport narrows. */
.work-experience-grid {
  grid-template: none;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  grid-template-rows: auto;
  align-items: start;
}

@media screen and (max-width: 991px) {
  /* Neutralise the hand-placed positions so auto-fit can do its job. */
  #w-node-_556cee0c-2d26-795c-0fb6-720c5f482e41-96912bf5,
  #w-node-_556cee0c-2d26-795c-0fb6-720c5f482e49-96912bf5,
  #w-node-_556cee0c-2d26-795c-0fb6-720c5f482e51-96912bf5,
  #w-node-_556cee0c-2d26-795c-0fb6-720c5f482e59-96912bf5 {
    grid-area: auto;
  }
}

@media screen and (max-width: 767px) {
  /* Undo the `display: flex` fallback so the auto-fit grid keeps working: two
     columns on a large phone, one on a small one. */
  .work-experience-grid {
    grid-column-gap: 1.25rem;
    grid-row-gap: 1.75rem;
    display: grid;
  }

  .work-experience-grid > * {
    text-align: left;
    margin-bottom: 0;
  }

  .work-position-wrap {
    margin-bottom: 0;
  }
}


/* ==========================================================================
   7. Home — closing call to action
   --------------------------------------------------------------------------
   Image and copy deliberately share grid cell 1/1. Keep the overlay, but make
   sure the image can never be shorter than the copy stacked on top of it.
   ========================================================================== */

@media screen and (max-width: 991px) {
  #w-node-a1262d2f-8cd2-1596-8d06-40c9def4af52-def4af4f.w-node-_216b3fb4-dcd4-8b1f-c236-528e259ee9a8-96912bf5 {
    height: 100%;
  }

  .position_relative > .image.image_cover {
    min-height: 100%;
    object-fit: cover;
  }

  .card_body.max-width_large {
    max-width: 100%;
  }
}


/* ==========================================================================
   8. Case study / suspect sources pages (BRIX blocks)
   ========================================================================== */

.brix---container-default,
.brix---container-default-2,
.brix---container-default-3,
.brix---container-default-4 {
  width: 100%;
}

@supports (padding: max(0px, env(safe-area-inset-left))) {
  .brix---container-default,
  .brix---container-default-2,
  .brix---container-default-3,
  .brix---container-default-4 {
    padding-left: max(24px, env(safe-area-inset-left, 0px));
    padding-right: max(24px, env(safe-area-inset-right, 0px));
  }
}

.brix---inner-container-1068px-center,
.brix---inner-container-1068px-center-2,
.brix---inner-container-600px---center,
.brix---inner-container-640px---center,
.brix---inner-container-640px---center-2,
.brix---inner-container-640px---center-3 {
  max-width: 100%;
}

.brix---image,
.brix---image-2 {
  max-width: 100%;
  height: auto;
}

@media screen and (max-width: 991px) {
  /* The decorative rotated blob sits at `left: -21%` with a 600px max-width; on a
     phone it's the single biggest source of horizontal overflow. It is
     `z-index: -1` decoration, so scale it into the section. */
  .brix---floating-image-hero-v2---1 {
    max-width: 60vw;
  }

  .brix---section-hero-v4 {
    overflow: hidden;
  }

  .brix---grid-hero-v4,
  .brix--grid-2-columns-text-right,
  .brix---grid-content-section-v6 {
    grid-template-columns: minmax(0, 1fr);
    grid-column-gap: 0;
  }

  /* The nav collapses to the hamburger here (`data-collapse="medium"`). Make
     sure the open panel can scroll on a short landscape viewport. */
  .nav_menu.w-nav-menu {
    max-height: calc(100vh - 4rem);
    max-height: calc(100dvh - 4rem);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
}

@media screen and (max-width: 767px) {
  .brix---grid-4-columns,
  .brix---grid-stats-v4,
  .brix---grid-2-stats-v4,
  .brix---3-columns-1-col-tablet {
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  }

  .brix---section,
  .brix---section-2,
  .brix---section-3,
  .brix---section-4 {
    padding-bottom: 88px;
  }
}

@media screen and (max-width: 479px) {
  .brix---grid-4-columns,
  .brix---grid-stats-v4,
  .brix---grid-2-stats-v4,
  .brix---3-columns-1-col-tablet {
    grid-template-columns: minmax(0, 1fr);
  }
}


/* ==========================================================================
   9. Utility page (401)
   ========================================================================== */

.utility-page-wrap {
  width: 100%;
  min-height: 100vh;
  /* iOS Safari's `100vh` is the *largest* viewport, so the bottom sits under the
     URL bar. These two lines progressively correct it. */
  min-height: -webkit-fill-available;
  min-height: 100dvh;
  height: auto;
  max-height: none;
  padding: 2rem 1rem;
}

@supports (padding: max(0px, env(safe-area-inset-left))) {
  .utility-page-wrap {
    padding: 2rem max(1rem, env(safe-area-inset-right, 0px))
             calc(2rem + env(safe-area-inset-bottom, 0px))
             max(1rem, env(safe-area-inset-left, 0px));
  }
}

.utility-page-content {
  width: 100%;
  max-width: 26rem;
}


/* ==========================================================================
   10. Motion
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}
