/* ============================================================
   lbasile.com — "Atelier noir"
   Warm noir, bone ink, vermillion accent, editorial serif.
   ============================================================ */

:root {
  --bg: #0b0a09;
  --bg-soft: #141210;
  --ink: #ece7df;
  --muted: #8a857c;
  --accent: #ff4d00;
  --line: rgba(236, 231, 223, 0.14);

  --font-display: "Zodiak", Georgia, serif;
  --font-body: "Satoshi", "Helvetica Neue", sans-serif;
  --font-mono: "IBM Plex Mono", monospace;

  --pad: clamp(1.25rem, 4vw, 4rem);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
}

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

html {
  scroll-behavior: smooth;
}

html.lenis,
html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 400;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

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

a {
  color: inherit;
  text-decoration: none;
}

em {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
}

.accent {
  color: var(--accent);
  font-style: normal;
}

.mono {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- Grain ---------- */
.grain {
  position: fixed;
  inset: -50%;
  width: 200%;
  height: 200%;
  pointer-events: none;
  z-index: 9000;
  opacity: 0.55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.06'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain-shift 0.9s steps(4) infinite;
}

@keyframes grain-shift {
  0% { transform: translate(0, 0); }
  25% { transform: translate(-2%, 1.5%); }
  50% { transform: translate(1.5%, -2%); }
  75% { transform: translate(-1%, -1%); }
  100% { transform: translate(2%, 2%); }
}

/* ---------- Preloader ---------- */
.preloader {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--bg);
  display: flex;
  align-items: flex-end;
  /* Ultimate fail-safe: even with JavaScript fully disabled (so neither
     main.js nor the inline fallback can run), never trap the visitor on the
     loader. On the happy path main.js removes the node well before 6s, so this
     never fires. */
  animation: preloader-failsafe 0.5s ease 6s forwards;
}

@keyframes preloader-failsafe {
  to {
    opacity: 0;
    visibility: hidden;
  }
}

.preloader__inner {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  padding: var(--pad);
}

.preloader__name {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.4rem, 3vw, 2.2rem);
}

.preloader__counter {
  font-family: var(--font-mono);
  font-size: clamp(3rem, 10vw, 7rem);
  line-height: 0.9;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* ---------- Cursor ---------- */
.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9500;
  pointer-events: none;
  mix-blend-mode: difference;
  opacity: 0;
  transition: opacity 0.3s;
}

.cursor.is-active {
  opacity: 1;
}

.cursor__dot {
  position: absolute;
  top: -6px;
  left: -6px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ink);
  transition: transform 0.35s var(--ease-out);
}

.cursor.is-hover .cursor__dot {
  transform: scale(3.2);
}

.cursor.is-view .cursor__dot {
  transform: scale(6.5);
}

.cursor__label {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(-50%, -50%);
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bg);
  opacity: 0;
}

.cursor.is-view .cursor__label {
  opacity: 1;
}

@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}

/* ---------- Header ---------- */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 8000;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem var(--pad);
  mix-blend-mode: difference;
}

.header__logo {
  display: flex;
  align-items: center;
}

.header__logo-img {
  display: block;
  height: 0.95rem;
  width: auto;
}

.header__nav {
  display: flex;
  gap: 2rem;
}

.header__nav a {
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  position: relative;
}

.header__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease-out);
}

.header__nav a:hover::after {
  transform: scaleX(1);
  transform-origin: left;
}

.header__meta {
  display: flex;
  gap: 1.25rem;
}

@media (max-width: 760px) {
  .header__nav { display: none; }
  .header__meta span:first-child { display: none; }
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: calc(var(--pad) + 3.5rem) var(--pad) var(--pad);
  overflow: clip;
}

.hero__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
}

.hero__top,
.hero__title,
.hero__bottom {
  position: relative;
  z-index: 1;
}

.hero__top {
  display: flex;
  justify-content: space-between;
}

.hero__title {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(3.4rem, 12.5vw, 11.5rem);
  line-height: 0.94;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  margin: auto 0;
}

.hero__title em {
  font-weight: 400;
  text-transform: none;
  letter-spacing: -0.02em;
  color: var(--accent);
  padding-right: 0.06em;
}

.hero__line {
  display: block;
  overflow: hidden;
}

.hero__line--indent {
  padding-left: clamp(2rem, 14vw, 14rem);
}

.hero__word {
  display: inline-block;
  will-change: transform;
}

.hero__bottom {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 2rem;
}

.hero__bio {
  max-width: 34ch;
  font-size: clamp(0.95rem, 1.4vw, 1.15rem);
  color: var(--muted);
}

.hero__bio strong {
  color: var(--ink);
  font-weight: 500;
}

.hero__scroll {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
}

.hero__scroll-line {
  width: 1px;
  height: 3.2rem;
  background: var(--muted);
  transform-origin: top;
  animation: scroll-pulse 1.8s var(--ease-out) infinite;
}

@keyframes scroll-pulse {
  0% { transform: scaleY(0); transform-origin: top; }
  45% { transform: scaleY(1); transform-origin: top; }
  55% { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}

/* ---------- Marquee ---------- */
.marquee {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 1.1rem 0;
  overflow: clip;
  white-space: nowrap;
}

.marquee__track {
  display: inline-flex;
  will-change: transform;
}

.marquee__item {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.6rem, 3.4vw, 2.8rem);
  padding-right: 0.5em;
}

.marquee__item i {
  font-style: normal;
  font-size: 0.6em;
  vertical-align: middle;
  padding: 0 0.4em;
}

/* ---------- Sections ---------- */
section {
  padding: clamp(5rem, 12vh, 9rem) var(--pad);
}

.section-head {
  display: flex;
  align-items: baseline;
  gap: 1.5rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1rem;
  margin-bottom: clamp(2.5rem, 6vw, 5rem);
}

.section-head__index {
  color: var(--accent);
}

.section-head__hint {
  margin-left: auto;
}

/* ---------- About ---------- */
.about__text {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 4.4vw, 3.6rem);
  line-height: 1.25;
  max-width: 22em;
  font-weight: 400;
}

.about__text em {
  color: var(--accent);
}

.about__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  margin-top: clamp(3rem, 7vw, 6rem);
}

.stat {
  background: var(--bg);
  padding: clamp(1.25rem, 3vw, 2.5rem);
}

.stat__num,
.stat__plus {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 6vw, 5rem);
  line-height: 1;
}

.stat__label {
  display: block;
  margin-top: 0.8rem;
}

@media (max-width: 640px) {
  .about__stats { grid-template-columns: 1fr; }
  .stat {
    display: flex;
    align-items: baseline;
    gap: 1rem;
  }
  .stat__label { margin-top: 0; margin-left: auto; }
}

/* ---------- Work (horizontal scroll) ---------- */
.work {
  padding-bottom: 0;
}

.work__pin {
  position: relative;
  overflow: clip;
}

/* Sideways-scroll hint, pinned bottom-right while the track is scrolling.
   Mirrors the hero scroll cue so visitors know to keep scrolling down. */
.work__hint {
  position: absolute;
  bottom: clamp(1.5rem, 4vh, 3rem);
  right: clamp(1.5rem, 4vw, 3rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  color: var(--muted);
  pointer-events: none;
  z-index: 5;
}

.work__hint-line {
  width: 1px;
  height: 3.2rem;
  background: var(--muted);
  transform-origin: top;
  animation: scroll-pulse 1.8s var(--ease-out) infinite;
}

/* Mobile stacks the cards vertically — no sideways scroll, no hint needed. */
@media (max-width: 1023px) {
  .work__hint { display: none; }
}

.work__track {
  display: flex;
  gap: clamp(1.5rem, 3vw, 3rem);
  padding-bottom: clamp(5rem, 12vh, 9rem);
  width: max-content;
}

.project {
  width: clamp(300px, 38vw, 560px);
  flex-shrink: 0;
}

.project__visual {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: clip;
  border: 1px solid var(--line);
}

.project__art {
  position: absolute;
  inset: -15%;
  transition: transform 0.8s var(--ease-out), filter 0.8s var(--ease-out);
  filter: saturate(0.85);
}

.project:hover .project__art {
  transform: scale(1.07) rotate(1.5deg);
  filter: saturate(1.15);
}

.project__visual--aura .project__art {
  background:
    radial-gradient(120% 90% at 20% 15%, #ff4d00 0%, transparent 55%),
    radial-gradient(100% 110% at 85% 80%, #2b1c4d 0%, transparent 60%),
    conic-gradient(from 220deg at 60% 40%, #0b0a09, #4d1d00, #0b0a09);
}

.project__visual--terra .project__art {
  background:
    radial-gradient(90% 120% at 80% 10%, #d8cfc0 0%, transparent 45%),
    radial-gradient(140% 90% at 15% 85%, #3e5c4b 0%, transparent 60%),
    linear-gradient(160deg, #141210, #25201a 60%, #0b0a09);
}

.project__visual--pulse .project__art {
  background:
    repeating-linear-gradient(90deg, transparent 0 38px, rgba(255, 77, 0, 0.35) 38px 39px),
    radial-gradient(100% 100% at 50% 100%, #1d3a4d 0%, transparent 70%),
    linear-gradient(0deg, #0b0a09, #16222b);
}

.project__visual--noir .project__art {
  background:
    radial-gradient(70% 100% at 50% 0%, #43352a 0%, transparent 60%),
    conic-gradient(from 40deg at 30% 70%, #0b0a09, #2e2117, #0b0a09 70%),
    linear-gradient(200deg, #1a1410, #0b0a09);
}

.project__num {
  position: absolute;
  top: 1rem;
  right: 1.1rem;
  color: var(--ink);
  opacity: 0.7;
}

.project__info {
  padding-top: 1.1rem;
  display: grid;
  gap: 0.15rem;
}

.project__title {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.6vw, 2.2rem);
  font-weight: 400;
}

.project__desc {
  color: var(--muted);
  font-size: 0.95rem;
}

.project__tags {
  margin-top: 0.5rem;
}

/* mobile: vertical stack */
@media (max-width: 1023px) {
  .work__track {
    flex-direction: column;
    width: 100%;
  }
  .project { width: 100%; }
}

/* ---------- Expertise ---------- */
.expertise__list {
  list-style: none;
}

.expertise__row {
  display: grid;
  grid-template-columns: 4rem 1fr;
  grid-template-areas: "num name" "num detail";
  align-items: baseline;
  padding: clamp(1.5rem, 3.5vw, 2.6rem) 0;
  border-bottom: 1px solid var(--line);
  transition: padding-left 0.5s var(--ease-out);
  cursor: default;
}

.expertise__row:hover {
  padding-left: clamp(0.5rem, 2vw, 2rem);
}

.expertise__num {
  grid-area: num;
  color: var(--accent);
}

.expertise__name {
  grid-area: name;
  font-size: clamp(1.8rem, 5vw, 4rem);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 1.05;
  transition: color 0.4s var(--ease-out);
}

.expertise__name em {
  font-weight: 400;
  text-transform: none;
}

.expertise__row:hover .expertise__name {
  color: var(--accent);
}

.expertise__detail {
  grid-area: detail;
  color: var(--muted);
  max-width: 46ch;
  margin-top: 0.4rem;
}

/* ---------- Contact ---------- */
.contact {
  min-height: 88svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: 1.5rem;
}

.contact__cta {
  font-weight: 700;
  font-size: clamp(3rem, 13vw, 12rem);
  line-height: 0.95;
  text-transform: uppercase;
  letter-spacing: -0.03em;
}

.contact__cta-line {
  display: block;
  overflow: hidden;
  /* Étend la zone de clip vers le bas pour ne pas couper les jambages (« g »)
     tout en gardant l'espacement inchangé via la marge négative. */
  padding-bottom: 0.15em;
  margin-bottom: -0.15em;
}

.contact__cta-line > span {
  display: inline-block;
}

.contact__cta-line--accent em {
  font-weight: 400;
  text-transform: none;
}

.contact__arrow {
  display: inline-block;
  font-style: normal;
  color: var(--accent);
  padding-left: 0.15em;
  transition: transform 0.5s var(--ease-out);
}

.contact__cta:hover .contact__arrow {
  transform: translateX(0.2em) rotate(-45deg);
}

.contact__email {
  font-size: 0.9rem;
  border: 1px solid var(--line);
  border-radius: 99px;
  padding: 0.8rem 1.6rem;
  transition: background 0.4s var(--ease-out), color 0.4s var(--ease-out), border-color 0.4s var(--ease-out);
}

.contact__email:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}

/* ---------- Footer ---------- */
.footer {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.5rem;
  padding: 1.5rem var(--pad);
  border-top: 1px solid var(--line);
}

.footer__brand {
  display: flex;
  align-items: center;
  justify-self: start;
}

.footer__copy {
  justify-self: end;
  text-align: right;
}

.footer__brand-img {
  display: block;
  height: 0.95rem;
  width: auto;
}

.footer__links {
  display: flex;
  gap: 1.5rem;
  justify-self: center;
}

.footer__links a {
  transition: color 0.3s;
}

.footer__links a:hover {
  color: var(--accent);
}

@media (max-width: 640px) {
  .footer {
    grid-template-columns: 1fr;
    justify-items: start;
  }
  .footer__brand,
  .footer__links,
  .footer__copy {
    justify-self: start;
    text-align: left;
  }
}

/* ---------- Reveal helpers (JS sets final state) ---------- */
/* Keep each measured word atomic so splitLines() groups lines from accurate
   offsetTop values — prevents hyphenated words (e.g. "six-month") from
   breaking internally and corrupting the line split. */
.split-lines .w {
  white-space: nowrap;
}

.split-lines .line {
  display: block;
  overflow: hidden;
}

.split-lines .line > span {
  display: block;
  will-change: transform;
}

/* ---------- Reduced motion ----------
   Driven by html.rm (set synchronously in <head> from the OS setting and the
   saved toggle preference) rather than the media query directly, so the opt-in
   toggle can override it and CSS stays in sync with main.js. */
html.rm .grain,
html.rm .hero__scroll-line {
  animation: none;
}
html.rm {
  scroll-behavior: auto;
}

/* Work: the horizontal scroll-jacking is JS-driven and disabled here, so
   unclip the pin and let the projects wrap — otherwise cards 3 & 4 sit
   off-screen in an unscrollable row and become unreachable. */
html.rm .work__pin {
  overflow: visible;
}
html.rm .work__track {
  flex-wrap: wrap;
  width: 100%;
}
html.rm .work__hint {
  display: none;
}

/* ---------- Motion toggle ---------- */
.motion-toggle {
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  transition: color 0.3s;
}

.motion-toggle:hover {
  color: var(--accent);
}

.motion-toggle__state {
  color: var(--ink);
}

.motion-toggle:hover .motion-toggle__state {
  color: inherit;
}

/* Gentle opacity-only reveals used by the reduced-motion path. The .rm-reveal
   class is added by JS, so content is never hidden if the script fails to run.
   Cross-fades carry no spatial motion, so they stay within the spirit of
   prefers-reduced-motion while keeping the page feeling alive. */
.rm-reveal {
  opacity: 0;
  transition: opacity 0.7s var(--ease-out);
}
.rm-reveal.is-in {
  opacity: 1;
}
