/* ==========================================================
   DAS PORTFOLIO — v2
   Cinematic dark / bold-type direction inspired by Anamorph
   ========================================================== */

/* ==========================================================
   PALETTE — the whole site's colour comes from these four values.
   Every page, every component. Change one here and it propagates.

     white  #ffffff
     black  #2d2d2d
     grey   #afafaf
     pink   #ff97fa

   The semantic tokens below (--bg, --fg, --line…) are all derived from
   them, so nothing anywhere should hardcode a colour.

   Why some tokens are mixes rather than the raw four: grey on white is
   only about a 2.3:1 contrast ratio, well under the 4.5:1 minimum for
   body text, so secondary copy on light pages uses a black tint that
   reads grey but stays legible. Grey itself is used where it belongs —
   hairlines, borders, and dimmed text on dark backgrounds, where it has
   plenty of contrast. Each mix is preceded by a plain hex fallback for
   browsers without color-mix().
   ========================================================== */
:root{
  --white: #ffffff;
  --black: #2d2d2d;
  --grey:  #afafaf;
  --pink:  #ff97fa;

  /* ---- dark theme (default) ---- */
  --bg: var(--black);
  --bg-soft: #3a3a3a;
  --bg-soft: color-mix(in srgb, var(--white) 8%, var(--black));
  --fg: var(--white);
  --fg-dim: var(--grey);
  --line: #4a4a4a;
  --line: color-mix(in srgb, var(--white) 18%, var(--black));
  --accent: var(--white);

  --ease: cubic-bezier(.16,1,.3,1);
  --display: "Switzer", "Helvetica Neue", Arial, sans-serif;
  --body: "Switzer", "Helvetica Neue", Arial, sans-serif;
}

/* ---- light theme, shared by every light page ---- */
body.tag-mode,
body.light-page,
body.white-page{
  --bg: var(--white);
  --bg-soft: #f0f0f0;
  --bg-soft: color-mix(in srgb, var(--grey) 22%, var(--white));
  --fg: var(--black);
  /* readable secondary text — see the contrast note above */
  --fg-dim: #6f6f6f;
  --fg-dim: color-mix(in srgb, var(--black) 72%, var(--white));
  --line: #d7d7d7;
  --line: color-mix(in srgb, var(--grey) 60%, var(--white));
}
/* header normally uses difference blending so it reads over the shifting
   3D canvas on the landing page — on a flat-colored page like this one
   that just inverts the nav text too, so render it at face value instead
   (the logo mark gets its own fix below). */
body.light-page .site-header{ mix-blend-mode: normal; }

/* .white-page's colours are already covered by the shared light-theme rule
   above; only its header behaviour is specific to it */
body.white-page .site-header{ mix-blend-mode: normal; }

/* the logo SVG asset is solid white; on these flat light/white pages
   mix-blend-mode is set to normal above (no auto-inverting), so the
   mark needs an explicit invert to stay dark-on-cream instead of
   vanishing.
   Tried mix-blend-mode:difference on just the mark first, so it'd
   dynamically adapt as gallery photos scroll underneath the fixed
   header on project pages — reverted that. mix-blend-mode combined
   with position:fixed is unreliable across browsers (notably Safari,
   which frequently just fails to blend against scrolled content at
   all and shows the raw unblended color — exactly the "shows solid
   white" bug this replaced). filter:invert is plain, well-supported,
   and has none of that fixed-position baggage. */
body.light-page .logo-mark img,
body.white-page .logo-mark img{
  filter: invert(1);
}
/* toggled by main.js: swaps back to the mark's native white (no invert)
   when a sampled-dark gallery image is actually sitting behind the
   header on a project page. Selector is deliberately scoped under the
   body classes too (not just .logo-mark img.on-dark) so its specificity
   beats the plain invert rule above regardless of source order. */
body.light-page .logo-mark img.on-dark,
body.white-page .logo-mark img.on-dark{
  filter: none;
}

/* small, thin social links tucked in the bottom-right corner */
.social-dock{
  position: fixed;
  right: clamp(20px,4vw,56px);
  bottom: 24px;
  z-index: 70;
  display: flex;
  gap: 18px;
}
.social-dock a{
  font-size: 11px;
  font-weight: 300;
  letter-spacing: .08em;
  color: var(--fg-dim);
  transition: color .3s ease;
}
.social-dock a:hover{ color: var(--fg); }
/* flipped dark by JS when the mint contact band is behind the dock — mint
   is bright, so dark text reads far better here than white would */
.social-dock.on-pink a{ color: color-mix(in srgb, var(--black) 75%, transparent); }
.social-dock.on-pink a:hover{ color: var(--black); }
@media (max-width: 640px){ .social-dock{ display:none; } }

*{ margin:0; padding:0; box-sizing:border-box; }

html{
  scroll-behavior: smooth;
  background: var(--bg);
}

/* used on the 3D hero landing page — there's nothing to scroll to,
   scroll/wheel input is only used to drive the 3D rotation instead */
body.no-scroll-page,
html:has(body.no-scroll-page){
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
}

body{
  background: var(--bg);
  color: var(--fg);
  font-family: var(--body);
  overflow-x: hidden;
  cursor: none;
  transition: background-color .6s var(--ease), color .6s var(--ease);
}

a{ color: inherit; text-decoration: none; }
ul{ list-style: none; }
button, input, textarea{ font-family: inherit; color: inherit; }

::selection{ background: var(--fg); color: var(--bg); }

/* film grain overlay */
.grain{
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 9998;
  opacity: .035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* custom cursor */
/* Glass at every size, all the time: the cursor is one material that only
   changes scale, rather than a grey dot that becomes a different object on
   hover. No outline, so the edge is held by refraction and a soft shadow
   instead of a drawn line. The blur is deliberately shallow, enough to bend
   what is underneath without hiding it, so the dot reads as a lens rather
   than a frosted plug. */
.cursor-dot{
  position: fixed;
  top:0; left:0;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--fg) 7%, transparent);
  -webkit-backdrop-filter: blur(2px) saturate(1.8) brightness(1.05);
  backdrop-filter: blur(2px) saturate(1.8) brightness(1.05);
  /* The ring is drawn as an inset shadow rather than a border so it costs no
     box size and animates on the same property as everything else here.
     It exists because at 10px there is barely enough area for refraction to
     read, and without it the resting dot goes missing on flat backgrounds. */
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--fg) 40%, transparent),
    inset 0 1px 1px color-mix(in srgb, var(--white) 38%, transparent),
    0 2px 6px color-mix(in srgb, var(--black) 16%, transparent);
  pointer-events: none;
  z-index: 9999;
  /* js/main.js writes the full transform, translate3d for the position plus
     the -50% centring. Moving it on the transform rather than left/top keeps
     it on the compositor, which matters more now that the backdrop-filter is
     always on: it has to resample the page behind the dot every frame. */
  will-change: transform;
  transition: width .3s var(--ease), height .3s var(--ease),
              background .3s var(--ease), box-shadow .3s var(--ease),
              opacity .25s var(--ease);
  /* Deliberately not mix-blend-mode: difference. Difference blending renders
     whatever the inverse of the backdrop happens to be, which is never one
     of the four palette colours: over the pink panel it turned green.
     backdrop-filter gets the same "responds to what is behind it" quality
     honestly, by bending and brightening the real backdrop rather than
     inventing a colour, and it stacks with blend modes badly anyway. */
  mix-blend-mode: normal;
}

/* Hover: the same glass, larger, and the ring comes off.
   Losing the outline is the point rather than a side effect. At rest the dot
   has to announce itself against a page that is doing nothing, so it needs
   the drawn edge. Over something interactive the element is already
   responding (type goes pink, cards scale, images lift), so the cursor can
   drop its hard edge and become purely a lens: at 22px there is enough area
   for the refraction to carry it on its own. Bigger and softer at once, so
   the cursor recedes exactly where the page speaks up. */
.cursor-dot.hovering{
  width: 22px; height: 22px;
  box-shadow:
    inset 0 1px 1px color-mix(in srgb, var(--white) 38%, transparent),
    0 2px 6px color-mix(in srgb, var(--black) 16%, transparent);
}
/* Without backdrop-filter there is no glass to see and no outline to fall
   back on, so the fill has to carry the shape on its own. */
@supports not (backdrop-filter: blur(1px)){
  .cursor-dot{ background: color-mix(in srgb, var(--fg) 45%, transparent); }
}
@media (hover:none){ .cursor-dot{ display:none; } body{ cursor:auto; } }

/* floating image preview panel that follows cursor over project rows */
.preview-panel{
  position: fixed;
  top:0; left:0;
  width: 280px;
  height: 190px;
  border-radius: 4px;
  overflow: hidden;
  pointer-events: none;
  z-index: 60;
  opacity: 0;
  transform: translate(-50%,-50%) scale(.9);
  transition: opacity .35s var(--ease), transform .35s var(--ease);
  background: var(--bg-soft);
}
.preview-panel.active{ opacity: 1; transform: translate(-50%,-50%) scale(1); }
.preview-panel img{
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(15%) contrast(1.05);
}

/* ---------- header ---------- */
.site-header{
  position: fixed;
  top:0; left:0; right:0;
  display:flex; align-items:center; justify-content:space-between;
  padding: 28px clamp(20px,4vw,56px);
  z-index: 100;
  mix-blend-mode: difference;
}
.logo{
  font-family: var(--display);
  font-weight: 300;
  font-size: 22px;
  letter-spacing: .05em;
}
.logo-mark{ display: flex; align-items: center; }
.logo-mark img{
  height: 45px;
  width: auto;
  display: block;
  /* the SVG is solid white; .site-header's mix-blend-mode: difference
     (same as the rest of the header) keeps it readable on any background */
}
.main-nav{ display:flex; gap: clamp(20px,3vw,44px); }
.main-nav a{
  font-size: 13px;
  letter-spacing: .12em;
  font-weight: 500;
  position: relative;
  padding-bottom: 2px;
}
.main-nav a::after{
  content:"";
  position:absolute; left:0; bottom:0;
  width:0; height:1px;
  background: var(--fg);
  transition: width .35s var(--ease);
}
.main-nav a:hover::after{ width:100%; }

.nav-toggle{
  display:none;
  background:none; border:none; cursor:pointer;
  width: 28px; height: 18px;
  flex-direction: column; justify-content: space-between;
  z-index: 110;
}
.nav-toggle span{
  display:block; height:1px; width:100%; background: var(--fg);
}

.mobile-nav{
  position: fixed; inset:0;
  background: var(--bg);
  z-index: 99;
  display:flex; flex-direction:column;
  align-items:flex-start; justify-content:center;
  gap: 18px;
  padding: 0 32px;
  transform: translateY(-100%);
  transition: transform .5s var(--ease);
}
.mobile-nav.open{ transform: translateY(0); }
.mobile-nav a{
  font-family: var(--display);
  font-weight: 600;
  font-size: 40px;
}

@media (max-width: 700px){
  .main-nav{ display:none; }
  .nav-toggle{ display:flex; }
}

/* ---------- preloader ---------- */
.preloader{
  position: fixed; inset: 0;
  z-index: 10000;
  background: var(--bg);
  display: flex;
  align-items: center;
  /* same side padding as .hero, so the grid below lines up exactly */
  padding: 0 clamp(20px,4vw,56px);
}
/* floating dot field, drawn behind the images/counter — see the
   preloader-dots canvas logic in hero-split.js. Comes first in the
   markup so it sits behind .preloader-layout without needing z-index. */
.preloader-dots{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}
.preloader-dots.pop{
  transform: scale(1.15);
  opacity: 0;
}
/* centered, matching the hero's tag now sitting dead-center too — the
   dot field converges on wherever #preloaderImages actually sits (see
   the preloader-dots logic in hero-split.js), so keeping this centered
   is what makes the collecting dots land in the middle of the screen */
.preloader-layout{
  position: relative;
  z-index: 1;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.preloader-inner{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.preloader-images{
  position: relative;
  width: min(260px, 40vw);
  aspect-ratio: 4/3;
  flex: none;
  margin: 0 auto;
}
.preloader-images img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .2s ease;
}
.preloader-images img.active{ opacity: 1; }
.preloader-count{
  position: absolute;
  top: -10px; right: -10px;
  font-family: var(--display);
  font-weight: 600;
  font-size: 20px;
  line-height: 1;
  color: var(--pink);
}
.preloader-label{
  position: absolute;
  bottom: 40px; left: 50%;
  transform: translateX(-50%);
  font-size: 11px;
  letter-spacing: .2em;
  color: var(--fg-dim);
}
.preloader.is-done{
  opacity: 0;
  pointer-events: none;
  transition: opacity .7s var(--ease);
}

/* ---------- hero ---------- */
.hero{
  min-height: 100vh;
  display:flex; flex-direction:column; justify-content:center;
  padding: 0 clamp(20px,4vw,56px);
  position: relative;
}

/* ---------- hero 3d ---------- */
.hero-3d{
  align-items: center;
  overflow: hidden;
}
.hero-canvas{
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  display: block;
}
/* ---------- hero split (index2) — DAS tag dead center as a 3D dot
   cloud, project thumbnails floating around it as real DOM cards that
   drift horizontally (idle + scroll-boosted, same accumulator the tag
   itself uses) and loop from the right edge back in on the left. All
   direct children here are position:absolute (out of flow), so the
   parent's own display mode doesn't matter — .hero's flex/centering
   rules just don't apply to anything inside .hero-split anymore. ---------- */
.hero-split{
  position: relative;
  overflow: hidden;
}
.hero-split-left{
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(46vh, 460px);
  aspect-ratio: 1;
  z-index: 3;
}
.hero-split .scroll-cue{
  position: absolute;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  align-items: flex-end;
  z-index: 4;
}

/* floating project cards — scattered around the tag, drifting right and
   looping back in from the left; see hero-split.js for the per-card
   base position/size/phase and the drift loop itself. */
.hero-float-field{
  position: absolute;
  inset: 0;
  z-index: 1;
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, black 110px, black calc(100% - 90px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, black 110px, black calc(100% - 90px), transparent 100%);
}
.float-card{
  position: absolute;
  display: block;
  text-decoration: none;
  color: inherit;
  will-change: transform;
}
.float-card-inner{
  display: block;
  animation: floatBob 6s ease-in-out infinite;
}
.float-card img{
  width: 100%;
  height: auto;
  display: block;
  border-radius: 3px;
  transition: transform .5s var(--ease);
}
.float-card:hover img{ transform: scale(1.03); }
.float-card-meta{
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 9px;
  font-size: 11px;
  letter-spacing: .02em;
}
.float-card-meta .name{ color: var(--fg); font-weight: 500; }
.float-card-meta .year{ color: var(--fg-dim); }

@keyframes floatBob{
  0%, 100%{ transform: translateY(0); }
  50%{ transform: translateY(-12px); }
}

@media (max-width: 860px){
  .hero-split-left{ width: min(58vw, 340px); }
}
@media (max-width: 640px){
  .hero-float-field{ display: none; }
}

.hero-3d-overlay{
  position: relative;
  z-index: 2;
  margin-top: auto;
  margin-bottom: 28px;
  text-align: center;
  pointer-events: none;
}
.hero-3d-overlay .hero-name{
  font-size: 13px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--fg-dim);
}
.hero-3d-overlay .hero-tag{
  max-width: 420px;
  margin: 10px auto 0;
  font-size: 14px;
  color: var(--fg-dim);
  line-height: 1.55;
}
.hero-title{
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(48px, 11vw, 150px);
  line-height: .92;
  letter-spacing: -.01em;
  text-transform: uppercase;
}
.hero-title .line{ display:block; overflow:hidden; }
.hero-title .word{
  display:inline-block;
  transform: translateY(110%);
  animation: riseUp 1s var(--ease) forwards;
}
.hero-title .line:nth-child(1) .word{ animation-delay: .15s; }
.hero-title .line:nth-child(2) .word{ animation-delay: .3s; }
.hero-title .line:nth-child(3) .word{ animation-delay: .45s; }

@keyframes riseUp{
  to{ transform: translateY(0); }
}

.hero-inner--mark{
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.hero-mark-wrap{
  position: relative;
  width: min(480px, 60vw);
  margin: 0 auto;
}
.hero-mark{
  display: block;
  width: 100%;
  height: auto;
  opacity: 0;
}
.hero-mark--pink{
  position: absolute;
  top: 0; left: 0;
  pointer-events: none;
  -webkit-mask-image: radial-gradient(circle 50px at var(--mx, -9999px) var(--my, -9999px), black 100%, transparent 100%);
  mask-image: radial-gradient(circle 50px at var(--mx, -9999px) var(--my, -9999px), black 100%, transparent 100%);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  transition: mask-image .15s ease, -webkit-mask-image .15s ease;
}
/* tag mode: the whole mark goes pink, no mask */
body.tag-mode .hero-mark--pink{
  -webkit-mask-image: none;
  mask-image: none;
}
.hero{ cursor: pointer; }
.hero-name{
  margin-top: 22px;
  font-size: 13px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--fg-dim);
  opacity: 0;
}

.hero-tag{
  max-width: 520px;
  margin-top: 14px;
  font-size: clamp(14px,1.4vw,17px);
  color: var(--fg-dim);
  line-height: 1.55;
  text-align: center;
  opacity: 0;
}

.scroll-cue{
  display: flex;
  align-items: center;
  gap: 12px;
  width: fit-content;
  margin: 0 auto;
  opacity: 0;
}
.scroll-cue span{
  font-size: 11px; letter-spacing: .18em; color: var(--fg-dim);
}
.scroll-line{
  width: 1px; height: 46px; background: var(--line);
  position: relative; overflow: hidden;
}
.scroll-line i{
  position:absolute; top:-100%; left:0; width:100%; height:100%;
  background: var(--pink);
  animation: scrollLine 1.8s ease-in-out infinite;
}
@keyframes scrollLine{
  0%{ top:-100%; }
  50%{ top:0%; }
  100%{ top:100%; }
}

/* ---------- reveal on scroll ---------- */
.reveal-up{
  opacity:0;
  transform: translateY(40px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.reveal-up.in-view{ opacity:1; transform: translateY(0); }

.reveal-fade{
  opacity:0;
  transition: opacity 1.2s var(--ease);
  transition-delay: .6s;
}
.reveal-fade.in-view{ opacity:1; }

/* ---------- section shared ---------- */
section{ padding: 140px clamp(20px,4vw,56px); position: relative; }
.section-head{
  display:flex; align-items:flex-end; justify-content:space-between;
  border-bottom: 1px solid var(--line);
  padding-bottom: 24px;
  margin-bottom: 60px;
}
.section-head h2{
  font-family: var(--display);
  font-weight: 600;
  text-transform: uppercase;
  font-size: clamp(28px,4vw,54px);
  line-height: 1.05;
}
.section-index{
  font-size: 13px; color: var(--fg-dim); letter-spacing: .1em;
}

/* ---------- work: cinematic project blocks ---------- */
.work{ padding: 0; }

.work-project{
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
  padding: 120px clamp(20px,4vw,56px) 70px;
  border-bottom: 1px solid var(--line);
  background-size: cover;
  background-position: center;
  overflow: hidden;
}

.work-top{
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  letter-spacing: .16em;
  color: var(--fg-dim);
  text-transform: uppercase;
  margin-bottom: 48px;
}

.work-frame{
  position: relative;
  display: block;
  width: min(920px, 92%);
  aspect-ratio: 16/9;
  margin: 0 auto;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--white) 22%, transparent);
  transition: transform .6s var(--ease);
}
.work-frame:hover{ transform: scale(1.012); }
.work-frame img{
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .8s var(--ease);
}
.work-frame:hover img{ transform: scale(1.06); }

/* GSAP controls these — hidden by default so there's no flash before JS runs */
.work-top, .work-frame, .work-marquee-link, .work-meta{ opacity: 0; }

.corner{ position: absolute; width: 20px; height: 20px; z-index: 2; }
.corner.tl{ top: -1px; left: -1px; border-top: 2px solid var(--fg); border-left: 2px solid var(--fg); }
.corner.tr{ top: -1px; right: -1px; border-top: 2px solid var(--fg); border-right: 2px solid var(--fg); }
.corner.bl{ bottom: -1px; left: -1px; border-bottom: 2px solid var(--fg); border-left: 2px solid var(--fg); }
.corner.br{ bottom: -1px; right: -1px; border-bottom: 2px solid var(--fg); border-right: 2px solid var(--fg); }

.work-marquee-link{
  display: block;
  overflow: hidden;
  margin-top: 40px;
}
.work-marquee-track{
  display: flex;
  align-items: center;
  gap: 30px;
  width: max-content;
  animation: workMarquee 20s linear infinite;
}
.work-marquee-link:hover .work-marquee-track{ animation-play-state: paused; }
.work-marquee-track span{
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(38px,8.5vw,110px);
  line-height: 1;
  text-transform: uppercase;
  color: var(--fg-dim);
  transition: color .4s ease;
}
.work-marquee-track .plus{ font-size: .4em; color: var(--fg-dim); }
.work-marquee-link:hover .work-marquee-track span:not(.plus){ color: var(--fg); }

@keyframes workMarquee{
  from{ transform: translateX(0); }
  to{ transform: translateX(-50%); }
}

.work-meta{
  display: flex;
  justify-content: space-between;
  margin-top: 34px;
  font-size: 12px;
  letter-spacing: .1em;
  color: var(--fg-dim);
  text-transform: uppercase;
}

@media (max-width: 640px){
  .work-marquee-track span{ font-size: clamp(30px,12vw,60px); }
  .work-meta span:nth-child(2){ display:none; }
}

/* ---------- floating CTA dock ---------- */
.floating-cta{
  position: fixed;
  bottom: 28px; left: 28px;
  z-index: 70;
}
.floating-cta-pill{
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: transparent;
  border: 1.5px solid var(--fg-dim);
  color: var(--fg-dim);
  padding: 13px 22px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  transition: transform .35s var(--ease), background .35s var(--ease), border-color .35s var(--ease), color .35s var(--ease);
}
.floating-cta-pill:hover{
  transform: translateY(-3px);
  background: var(--pink);
  border-color: var(--pink);
  color: var(--fg);
}
.floating-cta-pill .dot{
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--fg-dim);
  display: inline-block;
  transition: background .35s var(--ease);
}
.floating-cta-pill:hover .dot{ background: var(--fg); }
@media (max-width: 640px){ .floating-cta{ display:none; } }

/* ---------- about ---------- */
.about-grid{
  display:grid;
  grid-template-columns: 1.4fr .8fr .8fr;
  gap: 60px;
}
.about-bio{
  font-size: clamp(20px,2.4vw,32px);
  line-height: 1.4;
  font-weight: 400;
}
.about-col h3{
  font-size: 12px;
  letter-spacing: .14em;
  color: var(--fg-dim);
  margin-bottom: 18px;
  text-transform: uppercase;
}
.plain-list li{
  font-size: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
}
.plain-list li:last-child{ border-bottom: 1px solid var(--line); }

@media (max-width: 900px){
  .about-grid{ grid-template-columns: 1fr; }
}

/* ---------- about.html: flat two-column layout ---------- */
.about-page{
  padding: 160px clamp(20px,4vw,56px) 0;
}
.about-row{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px,5vw,80px);
}
.about-row-top{ align-items: start; padding-bottom: 90px; }

.about-visual-inline{
  position: relative;
  width: 100%;
  max-width: 620px;
  aspect-ratio: 3 / 4;
  margin: 0 auto;
  top: -100px;
}

.about-title{
  font-family: var(--display);
  font-weight: 900;
  font-size: clamp(48px,7vw,96px);
  line-height: 0.95;
  letter-spacing: -0.01em;
  margin-bottom: 20px;
}
.about-copy{
  font-size: clamp(15px,1.3vw,17px);
  line-height: 1.6;
  font-weight: 300;
}
.about-lists{
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  margin-top: 48px;
}

/* full-bleed band for the contact section — overrides the shared
   color variables locally so every element inside (links, the CTA,
   labels) flips to dark automatically without per-element overrides.
   The accent is a bright colour, so dark text reads far better on it
   than white would. */
.about-contact-band{
  --fg: var(--black);
  --fg-dim: color-mix(in srgb, var(--black) 72%, transparent);
  --line: color-mix(in srgb, var(--black) 35%, transparent);
  background: var(--pink);
  color: var(--fg); /* elements below that only *inherit* color (rather than
    referencing var(--fg) themselves) need this — redefining the custom
    property alone doesn't retroactively change an already-inherited value */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: 70px;
  padding: 56px clamp(20px,4vw,56px) 64px;
}
.about-row-bottom{ align-items: end; }
.about-footer-meta{
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 48px;
}
.about-signature{
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(28px,4vw,44px);
}
.about-cta-col{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}
.about-cta-label{
  font-size: 13px;
  color: var(--fg-dim);
}

@media (max-width: 900px){
  .about-row{ grid-template-columns: 1fr; }
  .about-row-bottom{ align-items: start; }
  /* the -100px lift is tuned for the desktop 2-column layout, where the
     visual sits in its own column next to the copy — once everything
     stacks into a single column it just risks tucking the canvas up
     under the fixed header, so drop it back to a normal top edge */
  .about-visual-inline{ max-width: 100%; margin: 0 auto 40px; top: 0; }
}

/* marquee */
.marquee{
  margin-top: 100px;
  overflow: hidden;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 22px 0;
}
.marquee-track{
  display:flex; gap: 60px; width: max-content;
  animation: marquee 22s linear infinite;
}
.marquee-track span{
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(20px,3vw,36px);
  color: var(--fg-dim);
  text-transform: uppercase;
  white-space: nowrap;
}
@keyframes marquee{
  from{ transform: translateX(0); }
  to{ transform: translateX(-50%); }
}

/* ---------- contact ---------- */
.contact-grid{
  display:grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 60px;
  align-items: start;
}
.contact-cta{
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(40px,7vw,96px);
  text-transform: uppercase;
  display:inline-flex; align-items:center; gap: 20px;
  line-height: 1;
}
.contact-cta-arrow{
  font-size: .5em;
  transition: transform .4s var(--ease);
}
.contact-cta:hover .contact-cta-arrow{ transform: translate(6px,-6px); }

.contact-form{ display:flex; flex-direction:column; gap: 18px; }
.form-row input, .form-row textarea{
  width: 100%;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  padding: 12px 0;
  font-size: 15px;
  outline: none;
  transition: border-color .3s ease;
  resize: none;
}
.form-row input::placeholder, .form-row textarea::placeholder{ color: var(--fg-dim); }
.form-row input:focus, .form-row textarea:focus{ border-color: var(--fg); }
.contact-form button{
  align-self: flex-start;
  margin-top: 8px;
  background: var(--fg);
  color: var(--bg);
  border: none;
  padding: 14px 28px;
  font-size: 13px;
  letter-spacing: .08em;
  cursor: pointer;
  transition: opacity .3s ease;
}
.contact-form button:hover{ opacity: .8; }

@media (max-width: 800px){
  .contact-grid{ grid-template-columns: 1fr; }
}

.contact-footer{
  margin-top: 100px;
  display:flex; align-items:center; justify-content:space-between;
  border-top: 1px solid var(--line);
  padding-top: 24px;
  flex-wrap: wrap;
  gap: 16px;
}
.socials{ display:flex; gap: 24px; }
.socials a{ font-size: 13px; letter-spacing:.06em; }
.socials a:hover{ color: var(--fg-dim); }
.location{ font-size: 13px; color: var(--fg-dim); }

/* ---------- footer ---------- */
.site-footer{
  display:flex; align-items:center; justify-content:space-between;
  padding: 28px clamp(20px,4vw,56px) 40px;
  font-size: 12px;
  color: var(--fg-dim);
}
.site-footer a:hover{ color: var(--fg); }
