/* Page-level tweaks that apply at every width (loaded right after the Webflow stylesheet). */

/* Resume: contacts are just email + LinkedIn now — one column, flush right under the
   name row (the old 2×2 column-flow grid was built for four entries) */
.resume-contact { grid-template-columns: 1fr; grid-template-rows: auto auto; justify-items: end; text-align: right; }
/* Resume: skills flow as chips that never break inside an item; the two skill columns
   were 4px apart (fine for the old short lines, not for full lines) */
.skill { white-space: nowrap; display: inline-block; margin-right: 8px; }
.grid-60-4-3 { grid-column-gap: 40px; }

/* Resume: tagline under the name (added with the Sep 2026 resume copy) */
.resume-heading { display: flex; flex-direction: column; }
.resume-tagline { color: var(--purplegrey-5-tertiarytext); font-family: Palanquin, sans-serif; font-size: 18px; line-height: 28px; font-weight: 400; margin-top: 2px; }

/* About: copy stays left-aligned at every width (the template centres it below 991px);
   when the grid stacks, the photo shares the same left edge */
.about-intro-grid, .about-intro-grid.about-intro-grid, .self-intro, .about-head-text-wrap { text-align: left; }
@media screen and (max-width: 991px) { .about-intro-grid { justify-items: start; } }

/* Images carry width/height attributes (added at build time) so space is reserved before they
   load; keep the ratio when max-width: 100% shrinks them. Class rules (e.g. .titleimage) still win. */
img { height: auto; }

/* ---- Top nav: "Work" menu panel (markup added by tools/patches.mjs, behaviour in src/nav.js).
   Horizontal cards (thumb left, name + subtitle right), three per row; the panel's side padding
   equals the homepage section padding, so the rows share the edges of the home card grid. ---- */
.tt-workpanel{position:fixed;top:80px;left:0;right:0;z-index:999;padding:32px 140px 40px;
  background:rgba(12,13,18,.78);-webkit-backdrop-filter:blur(28px) saturate(140%);backdrop-filter:blur(28px) saturate(140%);
  border-bottom:1px solid rgba(255,255,255,.06);box-shadow:0 24px 48px rgba(0,0,0,.25);
  opacity:0;visibility:hidden;transform:translateY(-8px);transition:opacity .2s ease,transform .2s ease,visibility 0s linear .2s}
.tt-workpanel.is-open{opacity:1;visibility:visible;transform:none;transition:opacity .2s ease,transform .2s ease,visibility 0s}
.tt-workpanel-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));column-gap:60px;row-gap:16px}
.tt-workcard{display:grid;grid-template-columns:120px minmax(0,1fr);column-gap:18px;align-items:center;align-self:stretch;
  margin:-10px;padding:10px;border-radius:16px;text-decoration:none;color:#fff;transition:background-color .2s ease}
.tt-workcard:hover,.tt-workcard:focus-visible{color:#fff;background:rgba(255,255,255,.06)}   /* Webflow's a:hover would turn it #32343a */
.tt-workthumb{display:block;aspect-ratio:3/2;border-radius:8px;overflow:hidden;background:rgba(255,255,255,.06)}
.tt-workthumb img{display:block;width:100%;height:100%;object-fit:cover;transition:transform .3s ease}
.tt-workcard:hover .tt-workthumb img,.tt-workcard:focus-visible .tt-workthumb img{transform:scale(1.04)}
.tt-worktext{display:block;min-width:0}
.tt-workname{display:block;font-family:"Palanquin Dark",sans-serif;font-size:18px;line-height:24px;font-weight:500}
.tt-worksub{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;margin-top:2px;font-family:Palanquin,sans-serif;font-size:15px;line-height:20px;color:rgba(225,232,242,.7)}
.tt-workcard.is-current .tt-workthumb{box-shadow:0 0 0 2px rgba(255,255,255,.7)}
body.body-light .tt-workpanel{background:rgba(255,255,255,.98);border-bottom-color:rgba(0,0,0,.06);box-shadow:0 24px 48px rgba(0,0,0,.08)}
body.body-light .tt-workcard{color:#1a1b1f}
body.body-light .tt-workcard:hover,body.body-light .tt-workcard:focus-visible{color:#1a1b1f;background:rgba(0,0,0,.04)}
body.body-light .tt-worksub{color:#5b667d}
body.body-light .tt-workcard.is-current .tt-workthumb{box-shadow:0 0 0 2px rgba(26,27,31,.6)}
@media screen and (max-width:1279px){.tt-workpanel{padding:28px 80px 36px}.tt-workpanel-grid{column-gap:40px}.tt-workcard{grid-template-columns:96px minmax(0,1fr);column-gap:14px}
  .tt-workname{font-size:16px;line-height:22px}.tt-worksub{font-size:14px;line-height:19px}}
@media screen and (max-width:991px){.tt-workpanel{padding:24px 40px 32px}.tt-workpanel-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (hover:none),screen and (max-width:767px){.tt-workpanel{display:none}}

/* ---- Project pages: vertical elevator nav (>= 1280px) sits on a translucent, blurred "glass" card
   whose left edge lines up with the header logo (x = 140). The page's inline CSS centres the list on
   50% - 240px, which pushed long lists (AutoMeetic: 10 items) above the viewport; the card's top edge
   is pinned instead: 24px under the header, or where short lists used to start on tall screens. ---- */
@media screen and (min-width:1280px){
  ul.nav.nav-stacked.affix{left:140px;right:auto;top:max(104px,calc(50vh - 340px));margin:0;transform:none;
    width:max-content;height:auto;padding:18px 20px;border-radius:16px;
    background:rgba(28,28,28,.5);-webkit-backdrop-filter:blur(20px) saturate(140%);backdrop-filter:blur(20px) saturate(140%);
    border:1px solid rgba(255,255,255,.08)}
  ul.nav.nav-stacked.affix li:last-child{margin-bottom:0}
  body.body-light ul.nav.nav-stacked.affix{background:rgba(255,255,255,.62);border-color:rgba(0,0,0,.06);box-shadow:0 8px 30px rgba(0,0,0,.06)}
  ul.nav.nav-stacked.affix{transition:opacity .2s ease,visibility 0s}
  ul.nav.nav-stacked.affix.tt-away{opacity:0;visibility:hidden;pointer-events:none;transition:opacity .2s ease,visibility 0s linear .2s}
  /* XCUBE "Impact" stats ran edge to edge (x = 80 at 1440) under the card; they start where the
     other sections' content starts (class added in tools/patches.mjs) */
  ._1280.tt-impact{width:auto;max-width:1280px;margin-left:400px;margin-right:100px}
  ._1280.tt-impact > .grid-80-80-2{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* From 1920px Webflow centres the 1280px content column, so it starts at (100vw - 1280px) / 2 — only
   320px at 1920. Until the column clears the card (card right edge + 24px = 362px), nudge the
   sections right by the difference (translate, so IX2's inline transforms are untouched). */
@media screen and (min-width:1920px){
  body:has(ul.nav.affix) ._1280:not(._1280 ._1280):not(._1720 ._1280):not(.tt-impact){translate:max(0px,calc(362px - (100vw - 1280px) / 2)) 0}
  ._1280.tt-impact{margin-left:max(362px,calc((100vw - 1280px) / 2))}
  /* full-width images / sliders placed directly in a section (FitU, Power Spot) start at the
     section's 140px padding, under the card; align them with the centred content column instead */
  body:has(ul.nav.affix) .main-section > .imagelightbox,body:has(ul.nav.affix) .main-section > .w-slider{
    margin-left:calc(max(362px,(100vw - 1280px) / 2) - 140px);max-width:1280px}
}
/* Every elevator label is as wide as its bold (active) version: a hidden, zero-height bold copy
   (data-label, added in tools/patches.mjs) sits under the text, so neither the card (>= 1280)
   nor the bottom-bar pills (< 1280) change width when the active section changes. Active labels
   are bold (700) on every project (BioMatrix / TMO used 600). */
ul.nav.nav-stacked.affix li a[data-label]{display:flex;flex-direction:column;align-items:flex-start;width:fit-content}
ul.nav.nav-stacked.affix li a[data-label]::after{content:attr(data-label);font-weight:700;height:0;overflow:hidden;visibility:hidden;pointer-events:none;user-select:none}
ul.nav.nav-stacked.affix li.active a{font-weight:700}
@media screen and (max-width:1279px){ul.nav.nav-stacked.affix li a[data-label]{display:flex;align-items:center}}
@media screen and (min-width:1280px){ul.nav.nav-stacked.affix li a[data-label]{padding-top:0;padding-bottom:0}}   /* the embed's 4px was inert on inline links */
/* Elevator labels that are not the current section: palette neutrals, one for light pages and one for
   dark pages (the current section keeps each project's accent colour) */
ul.nav.nav-stacked.affix li:not(.active) a{color:var(--purplegrey-5-tertiarytext)}
ul.nav.nav-stacked.affix li:not(.active) a:hover{color:var(--purplegrey-6-light)}
body.body-light ul.nav.nav-stacked.affix li:not(.active) a{color:var(--purplegrey-4-secondarytext)}
body.body-light ul.nav.nav-stacked.affix li:not(.active) a:hover{color:var(--purplegrey-3-primarytext)}

/* "Work" is the active nav item on the homepage and inside projects (own class: Webflow's runtime
   strips w--current from links whose href is not the current URL) */
.navlink.tt-worklink.tt-current{font-weight:700;color:#fff}
body.body-light .navlink.tt-worklink.tt-current{color:#1a1b1f}

/* Headings wrapped in .section-title show their own (sentence-case) text: the template forced them
   to capitals, and .bold-text-11 (TMO, XCUBE, BioMatrix headings) capitalised every word. The small
   eyebrow labels ("01 AI shopping") stay in capitals on every project; the homepage "Work" title does not. */
.section-title,.section-title.heading-planet,.section-title.heading-syncdance,.section-title.heading-kuri,
.section-title.heading-fitu,.section-title.heading-brand{text-transform:none}
.bold-text-11{text-transform:none}
.section-title:not(.heading-brand) h5,.section-title:not(.heading-brand) h5 *{text-transform:uppercase}

/* AutoMeetic: an inline-block lightbox sized to its image's intrinsic width (889px) overflowed its
   740px column at 1280, and a long survey URL in its citations did the same (9px horizontal scroll) */
.lightbox-link-13{max-width:min(1600px,100%)}
.text-block-54{overflow-wrap:anywhere}

/* Project pages (body.tt-nosave, added in tools/patches.mjs): images are not offered for saving —
   no drag, no iOS long-press menu; right-click is handled in src/nosave.js */
.tt-nosave img{-webkit-user-drag:none;user-drag:none;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}

/* BioMatrix's full-width sections kept the 360 / 100px side padding meant for the inset white-card
   sections (which sit 40px in from the page edge), so between 1280 and 1919px its content ran
   360 → W−100 instead of 400 → W−140 like every other project, 24px from the elevator card.
   Same padding as Meican's full-width sections. */
@media screen and (min-width:1280px) and (max-width:1919px){
  .main-section.biomatrix,.main-section.biomatrixlight{padding-left:400px;padding-right:140px}
}

/* ---- Project image viewer (src/viewer.js; replaces Webflow's lightbox). Every colour is one of the
   palette's neutral variables (no blue tint): one set for light projects (body.body-light), one for
   dark projects. ---- */
.tt-viewer{--v-overlay:color-mix(in srgb,var(--greybackground) 88%,transparent);--v-full:var(--dim-grey);
  --v-btn:var(--white);--v-btn-hover:var(--greybackground);--v-icon:var(--darkbluegrey);
  --v-active:var(--darkbluegrey);--v-active-icon:var(--white);--v-text:var(--dim-grey);
  --v-shadow:color-mix(in srgb,var(--black) 16%,transparent)}
body:not(.body-light) .tt-viewer{--v-overlay:color-mix(in srgb,var(--darkbluegrey) 88%,transparent);--v-full:var(--darkbluegrey);
  --v-btn:color-mix(in srgb,var(--white) 14%,transparent);--v-btn-hover:color-mix(in srgb,var(--white) 24%,transparent);--v-icon:var(--white);
  --v-active:var(--white);--v-active-icon:var(--darkbluegrey);--v-text:var(--grey);
  --v-shadow:color-mix(in srgb,var(--black) 45%,transparent)}
.tt-viewer.is-full{--v-text:var(--light-grey)}
html.tt-viewer-open{overflow:hidden}
a.w-lightbox.tt-v-return,a.w-lightbox.tt-v-return:focus,a.w-lightbox.tt-v-return:focus-visible{outline:none;box-shadow:none}   /* no ring after closing the viewer */
html.tt-viewer-open ul.nav.nav-stacked.affix{visibility:hidden}   /* the page's anchor bar / card would sit under the counter */
.tt-viewer{position:fixed;inset:0;z-index:3000;background:var(--v-overlay);opacity:0;transition:opacity .2s ease,background-color .25s ease}
.tt-viewer.is-open{opacity:1}
.tt-viewer.is-full{background:var(--v-full)}
.tt-viewer[hidden]{display:none}
.tt-viewer-stage{position:absolute;inset:0;touch-action:none;overflow:hidden}
.tt-viewer-img{position:absolute;max-width:none;transform-origin:50% 50%;cursor:zoom-in;
  filter:drop-shadow(0 24px 48px var(--v-shadow));transition:transform .2s ease;will-change:transform}
.tt-viewer.is-max .tt-viewer-img{cursor:grab}   /* below the maximum a click zooms in further; drag still pans */
.tt-viewer-img.is-dragging{transition:none;cursor:grabbing}
.tt-viewer-tools{position:absolute;top:24px;right:24px;display:flex;gap:12px;z-index:1}
.tt-vbtn{display:flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:0;border-radius:50%;
  background:var(--v-btn);color:var(--v-icon);box-shadow:0 4px 14px var(--v-shadow);cursor:pointer;
  transition:background-color .15s ease,color .15s ease}
.tt-vbtn:hover{background:var(--v-btn-hover)}
.tt-vbtn:focus-visible{outline:2px solid var(--v-active);outline-offset:2px}
.tt-vbtn[hidden]{display:none}
.tt-vbtn svg{width:20px;height:20px}
.tt-vbtn[aria-pressed="true"],.tt-vbtn[aria-pressed="true"]:hover{background:var(--v-active);color:var(--v-active-icon)}
.tt-v-prev,.tt-v-next{position:absolute;top:50%;transform:translateY(-50%);z-index:1}
.tt-v-prev{left:24px}.tt-v-next{right:24px}
.tt-viewer.is-single .tt-v-prev,.tt-viewer.is-single .tt-v-next,.tt-viewer.is-single .tt-viewer-count{display:none}
.tt-viewer-count{position:absolute;left:50%;bottom:24px;transform:translateX(-50%);color:var(--v-text);
  font-size:13px;line-height:20px;letter-spacing:.04em;pointer-events:none;font-variant-numeric:tabular-nums}
@media screen and (max-width:767px){
  .tt-viewer-tools{top:16px;right:16px;gap:8px}
  .tt-vbtn{width:40px;height:40px}.tt-vbtn svg{width:18px;height:18px}
  .tt-v-prev{left:8px}.tt-v-next{right:8px}
  .tt-viewer-count{bottom:16px}
}
