/* ============================================================================
   RÉSONE — l'art de faire résonner

   Layout follows koralie.com: no hero, no section bands, no empty space. The
   work is the page. A tiny header, a dense justified mosaic, one compact info
   strip, a one-line footer.

   Typeface is Tenor Sans, which ships a single weight (400). Hierarchy is
   therefore carried by SIZE, TRACKING, CASE and COLOUR — never by font-weight.
   Do not add a second family or reach for bold; there isn't one.

   Every hex is a measured pixel value from Canva design DAHWDWi4hD0.
   Do not use a literal hex below this block.
   ========================================================================= */

:root {
  /* — foundation ————————————————————————————————————————— */
  --paper:      #F6F6F5;
  --bone:       #EAE9E5;
  --bone-deep:  #E2E0DC;
  --sand:       #D3C6B8;
  --ash:        #AB9F98;

  /* — ink: warm oxblood, never black —————————————————————— */
  --ink:        #391316;
  --ink-wine:   #4C2A2C;
  --ink-cocoa:  #59473A;
  --ink-soft:   #78615A;
  --ink-mute:   #88726D;

  /* — accent: quoted from the artwork ————————————————————— */
  --terracotta: #B2917A;
  --clay:       #D2B9A5;
  --saffron:    #E8CE8A;
  --gold:       #B99E6C;
  --indigo:     #232C45;
  --ember:      #552D1A;
  --noir:       #150E0B;

  --font: "Tenor Sans", "Optima", "Avenir Next", system-ui, sans-serif;

  /* mosaic rhythm — tight, like koralie */
  --gap:  10px;
  --edge: clamp(12px, 2.4vw, 34px);

  --ease: cubic-bezier(.22,.61,.36,1);
  --fast: 240ms;
  --mid:  520ms;
  --slow: 900ms;
}

/* ============================================================================
   reset
   ========================================================================= */

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

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

body {
  background: var(--bone);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg { 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: 2px solid var(--ink-wine); outline-offset: 3px; }
::selection { background: var(--saffron); color: var(--ink); }

.skip {
  position: absolute; left: 50%; top: 0; translate: -50% -140%; z-index: 200;
  padding: .7rem 1.4rem; background: var(--ink); color: var(--paper);
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  transition: translate var(--fast) var(--ease);
}
.skip:focus-visible { translate: -50% 0; }

/* ============================================================================
   header — koralie proportions: wordmark left, micro-nav right, one subtitle
   ========================================================================= */

.head {
  padding: clamp(18px, 3vw, 30px) var(--edge) clamp(14px, 2.2vw, 22px);
  background: var(--bone);
}

.head__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

/* The wordmark's spacing is NOT uniform tracking. The deck sets the literal
   string `Ré s o  n   e`, so the gaps widen toward the end. These margins were
   measured off the 1920px cover render (ink edge to ink edge, converted to em
   via the R's 33px cap height at 0.70em) and verified back to within 0.004em:

       R→É 0.127   É→S 0.403   S→O 0.424   O→N 0.806   N→E 1.230  (em)

   Each value below is that target minus Tenor Sans's own natural side bearing,
   so do not "simplify" this to one letter-spacing — it would flatten the mark. */
.head__mark {
  font-size: clamp(15px, 1.5vw, 19px);
  font-weight: 400;          /* h1 — Tenor Sans has one weight; don't let UA bold it */
  letter-spacing: 0;
  line-height: 1;
  white-space: nowrap;
}
.head__mark i { font-style: normal; }
.head__mark i:nth-child(1) { margin-right: -0.018em; }   /* R → É */
.head__mark i:nth-child(2) { margin-right:  0.338em; }   /* É → S */
.head__mark i:nth-child(3) { margin-right:  0.309em; }   /* S → O */
.head__mark i:nth-child(4) { margin-right:  0.636em; }   /* O → N */
.head__mark i:nth-child(5) { margin-right:  0.990em; }   /* N → E */

.nav {
  display: flex;
  align-items: center;
  gap: clamp(.9rem, 2vw, 2rem);
  font-size: 10.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.nav a { transition: color var(--fast) var(--ease); }
.nav a:hover, .nav a:focus-visible { color: var(--ink); }
.nav__ig svg { width: 15px; height: 15px; }

/* current page — a hairline under it, not a weight change (there isn't one) */
.nav a.is-here {
  color: var(--ink);
  border-bottom: 1px solid var(--terracotta);
  padding-bottom: 3px;
}

.head__sub {
  margin-top: clamp(10px, 1.4vw, 16px);
  font-size: 10.5px;
  letter-spacing: .26em;
  color: var(--ink-mute);
}

/* Five tracked-out links don't fit beside the wordmark on a phone. Stack the
   header and let the nav wrap — cheaper and calmer than a burger for this. */
@media (max-width: 640px) {
  .head__top { flex-direction: column; align-items: flex-start; gap: 14px; }
  .nav { flex-wrap: wrap; gap: .2rem 1.15rem; letter-spacing: .16em; }
  .head__sub { letter-spacing: .18em; }
}

/* Touch targets. 10px type gives an 18px-tall link, which is far under the 44px
   a finger needs, so pad the box out without moving the text. Keyed on
   `hover: none` rather than width because a tablet needs this at 768px too. */
@media (hover: none) {
  .nav a,
  .head__mark a,
  .foot__line a,
  .card__row a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* the icon link has no text to give it width, so state it */
  .nav__ig { justify-content: center; min-width: 44px; }
  .nav__ig svg { width: 19px; height: 19px; }
  .news__row button,
  .news input { min-height: 44px; }
  /* the contact card's rows get taller; keep the groups legible */
  .card__row { gap: 0; }
}

/* ============================================================================
   the mosaic

   Each tile's flex-grow is its aspect ratio and its flex-basis is 0, so widths
   within a row divide in proportion to aspect. With aspect-ratio set to the
   same number, every tile in a row resolves to an identical height and the row
   fills the width exactly. That is the whole justified-gallery trick.
   ========================================================================= */

.works { padding: 0 var(--edge) 0; }

.row {
  display: flex;
  gap: var(--gap);
  margin-bottom: var(--gap);
}

.w {
  position: relative;
  flex: var(--ar) 1 0;
  /* flex items default to min-width:auto, which pins them to the image's
     intrinsic width and bursts the row. This is the whole ballgame. */
  min-width: 0;
  aspect-ratio: var(--ar);
  padding: 0;
  overflow: hidden;
  background: var(--bone-deep);
}

.w img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(.95);
  transition: scale var(--slow) var(--ease), filter var(--slow) var(--ease);
}

.w__cap {
  position: absolute;
  inset: auto 0 0 0;
  display: grid;
  gap: 2px;
  padding: 2.6rem .9rem .8rem;
  text-align: left;
  color: var(--paper);
  background: linear-gradient(transparent, rgb(21 14 11 / .78));
  opacity: 0;
  translate: 0 .5rem;
  transition: opacity var(--mid) var(--ease), translate var(--mid) var(--ease);
}
.w__cap b { font-weight: 400; font-size: 13px; letter-spacing: .04em; }
.w__cap i {
  font-style: normal;
  font-size: 9.5px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--clay);
}

.w:hover img, .w:focus-visible img { scale: 1.04; filter: saturate(1); }
.w:hover .w__cap, .w:focus-visible .w__cap { opacity: 1; translate: 0 0; }

/* touch has no hover — never hide the titles there */
@media (hover: none) { .w__cap { opacity: 1; translate: 0 0; } }

/* contact card — sits in a mosaic row beside a photo, so it behaves like a tile */
.card {
  flex: 1.15 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1.5rem;
  padding: clamp(1.4rem, 3vw, 2.6rem);
  background: var(--bone-deep);
}
.card__row { display: grid; gap: 2px; }
.card__row b {
  font-weight: 400;
  margin-bottom: .3rem;
  font-size: 10px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.card__row a, .card__row span { font-size: 14px; color: var(--ink-soft); }
.card__row a { transition: color var(--fast) var(--ease); }
.card__row a:hover, .card__row a:focus-visible { color: var(--ink); }

@media (max-width: 880px) { .card { flex-basis: 100%; min-width: 100%; } }

/* Narrow screens: a five-across justified row becomes unreadable, so let rows
   wrap and give each tile a sane minimum. Aspect ratios still hold. */
@media (max-width: 880px) {
  .row { flex-wrap: wrap; }
  .w { flex: var(--ar) 1 calc(50% - var(--gap)); min-width: calc(50% - var(--gap)); }
}
@media (max-width: 520px) {
  .w { flex-basis: 100%; min-width: 100%; }
}

/* ============================================================================
   footer — the only non-image content on the page.
   koralie's pattern: one dark centred band, newsletter, hairline, small lines.
   ========================================================================= */

.foot {
  display: grid;
  justify-items: center;
  gap: 1rem;
  padding: clamp(3rem, 7vw, 5.5rem) var(--edge) clamp(2.2rem, 4vw, 3.2rem);
  background: var(--ink);
  color: var(--bone);
  text-align: center;
}

.news { width: min(100%, 460px); }
.news label {
  display: block;
  margin-bottom: 1rem;
  font-size: 10.5px;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--clay);
}
.news__row {
  display: flex;
  align-items: center;
  gap: .6rem;
  border-bottom: 1px solid color-mix(in srgb, var(--clay) 55%, transparent);
}
.news input {
  flex: 1; min-width: 0; padding: .55rem 0;
  font: inherit; font-size: 13px; color: var(--bone);
  background: none; border: 0; text-align: left;
}
.news input::placeholder { color: color-mix(in srgb, var(--clay) 70%, transparent); }
/* the brightening rule is reinforcement, not the focus indicator — the global
   :focus-visible outline stays put */
.news__row:focus-within { border-bottom-color: var(--clay); }
.news input:user-invalid { color: var(--terracotta); }
.news__row button {
  flex: none; padding: .55rem 0 .55rem .4rem;
  font-size: 10px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--clay); transition: color var(--fast) var(--ease);
}
.news__row button:hover, .news__row button:focus-visible { color: var(--bone); }
.news__msg { min-height: 1.1rem; margin-top: .6rem; font-size: 11px; color: var(--clay); }
.news__msg[data-state="error"] { color: var(--terracotta); }

.foot__rule {
  width: min(100%, 860px);
  height: 1px;
  margin: clamp(1.4rem, 3vw, 2.4rem) 0 .4rem;
  background: color-mix(in srgb, var(--clay) 28%, transparent);
}

.foot__glyph { color: var(--terracotta); }
.foot__glyph svg { width: 52px; }

.foot__line { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.6rem; }
.foot__line a {
  font-size: 12px;
  letter-spacing: .06em;
  color: var(--clay);
  transition: color var(--fast) var(--ease);
}
.foot__line a:hover, .foot__line a:focus-visible { color: var(--bone); }

.foot__fine {
  font-size: 9.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--clay) 62%, transparent);
}

/* ============================================================================
   lightbox
   ========================================================================= */

.lb {
  width: min(94vw, 1180px);
  max-width: none;
  max-height: 92svh;
  /* the `* { margin: 0 }` reset kills the auto margins a modal dialog centres
     itself with — put them back */
  margin: auto;
  padding: 0;
  border: 0;
  background: var(--noir);
  color: var(--paper);
  overflow: visible;
}
.lb::backdrop { background: rgb(21 14 11 / .92); }
@supports (backdrop-filter: blur(1px)) { .lb::backdrop { backdrop-filter: blur(6px); } }

.lb__fig { margin: 0; }
.lb__img { width: 100%; max-height: 78svh; object-fit: contain; background: var(--noir); }

.lb__cap { display: grid; gap: 3px; padding: .9rem 1.2rem 1.1rem; text-align: left; }
.lb__title { font-size: 15px; letter-spacing: .04em; }
.lb__detail { font-size: 10px; letter-spacing: .14em; text-transform: uppercase; color: var(--clay); }

.lb__x, .lb__nav {
  position: absolute; z-index: 2; display: grid; place-items: center;
  width: 2.8rem; height: 2.8rem; line-height: 1;
  color: var(--paper); background: rgb(21 14 11 / .55); border-radius: 50%;
  transition: background var(--fast) var(--ease);
}
.lb__x:hover, .lb__nav:hover,
.lb__x:focus-visible, .lb__nav:focus-visible { background: var(--ink-cocoa); }
.lb__x { top: -1.1rem; right: -1.1rem; font-size: 1.4rem; }
.lb__nav { top: 50%; translate: 0 -50%; font-size: 1.8rem; padding-bottom: .2rem; }
.lb__nav--prev { left: -1.1rem; }
.lb__nav--next { right: -1.1rem; }

@media (max-width: 720px) {
  .lb__x { top: .5rem; right: .5rem; }
  .lb__nav--prev { left: .5rem; }
  .lb__nav--next { right: .5rem; }
}

/* entry/exit — degrades to an instant open where unsupported */
.lb, .lb::backdrop {
  opacity: 0;
  transition: opacity var(--fast) var(--ease), display var(--fast) allow-discrete;
}
.lb[open], .lb[open]::backdrop { opacity: 1; }
@starting-style { .lb[open], .lb[open]::backdrop { opacity: 0; } }

/* ============================================================================
   reveal — only armed once JS proves it can disarm it
   ========================================================================= */

.js .reveal {
  opacity: 0;
  translate: 0 14px;
  transition: opacity var(--mid) var(--ease), translate var(--mid) var(--ease);
  transition-delay: var(--d, 0ms);
}
.js .reveal.is-in { opacity: 1; translate: 0 0; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 1ms !important; animation-iteration-count: 1 !important;
    transition-duration: 1ms !important; scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; translate: none; }
  .w:hover img, .w:focus-visible img { scale: 1; }
}
