/* ==========================================================================
   Hay Ink homepage, design system
   Plain CSS. No frameworks. Only external dependency is Google Fonts.
   Order: tokens, reset, primitives, motion, then sections 1..8, then media.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* dark ground */
  --ink:        #0f0f0f;
  --void:       #080808;
  --panel:      #1c1c1c;
  --panel-2:    #121212;

  /* light ground */
  --cream:      #F6F4F0;
  --cream-deep: #EDE9E0;
  --graphite:   #1a1a1a;

  /* accents */
  --teal:       #00aea8;
  --teal-deep:  #007a76;
  --magenta:    #db2777;
  --cta:        #FFD60A;
  --violet:     #a855f7;
  --yellow:     #facc15;

  /* type on dark */
  --on-dark:      #F6F4F0;
  --on-dark-soft: rgba(246, 244, 240, .58);
  --on-dark-mute: rgba(246, 244, 240, .34);
  --hair-dark:    rgba(246, 244, 240, .12);

  /* type on cream */
  --on-cream:      #1a1a1a;
  --on-cream-soft: rgba(26, 26, 26, .58);
  --on-cream-mute: rgba(26, 26, 26, .38);
  --hair-cream:    rgba(26, 26, 26, .12);

  /* type */
  --font-display: 'Lexend Mega', 'Arial Black', system-ui, sans-serif;
  --font-body:    'Space Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* the house easing */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* rhythm */
  --wrap:    1320px;
  --gutter:  clamp(20px, 5vw, 72px);
  --sec-y:   clamp(72px, 10vw, 148px);

  /* display scale: sized so the longest hero line clears the gutters */
  --h1: clamp(30px, 5.8vw, 76px);
  --h2: clamp(27px, 3.5vw, 48px);
  --h3: clamp(18px, 1.5vw, 22px);
}

/* --------------------------------------------------------------------------
   2. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  font-family: var(--font-body);
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--ink);
  color: var(--on-dark);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.7;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, textarea { font: inherit; color: inherit; }
ul, ol { list-style: none; }

:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 3px;
}

.ico {
  width: 1em; height: 1em;
  stroke: currentColor; stroke-width: 1.8; fill: none;
  stroke-linecap: round; stroke-linejoin: round;
}

/* --------------------------------------------------------------------------
   3. PRIMITIVES
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Eyebrow pattern: text-xs uppercase tracking [0.3em] */
.eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3em;
  text-transform: uppercase;
  line-height: 1.4;
  margin-bottom: 22px;
}
.eyebrow-teal    { color: var(--teal); }
/* Eyebrow sits on cream at 11px, so it needs a darkened shade of the
   accent to clear the 4.5:1 floor. The buttons keep the full yellow
   (#FFD60A), which is a brand colour, not a text colour. */
.eyebrow-cta     { color: #7a6000; }
.eyebrow-magenta { color: #f472b6; }
.eyebrow-violet  { color: #7e22ce; }

.sec-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--h2);
  line-height: 1.08;
  letter-spacing: -.02em;
  color: var(--on-cream);
  max-width: 15ch;
}
.sec-title-light { color: var(--on-dark); }

.sec-lead {
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.75;
  color: var(--on-cream-soft);
  max-width: 46ch;
}
.sec-lead-light { color: var(--on-dark-soft); }

/* Section head: asymmetric, never a centered stack */
.sec-head {
  display: grid;
  grid-template-columns: 7fr 5fr;
  gap: clamp(24px, 4vw, 64px);
  align-items: end;
  margin-bottom: clamp(40px, 5vw, 72px);
}

.section-cream { background: var(--cream); color: var(--on-cream); }

/* Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 17px 34px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .01em;
  line-height: 1;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .28s var(--ease), color .28s var(--ease),
              border-color .28s var(--ease), transform .35s var(--ease);
  will-change: transform;
}
.btn-sm { padding: 12px 22px; font-size: 13px; }
.btn-block { width: 100%; }

/* OWNER DECISION 2026-08-21 (do not revert): Hagop rejected teal/green buttons
   ("the green is weird, find something else"). Primary CTAs are YELLOW. */
.btn-primary { background: var(--cta); color: #17130f; }
.btn-primary:hover { background: #E6C009; }

.btn-ghost {
  color: var(--on-dark);
  border-color: rgba(246, 244, 240, .26);
  background: transparent;
}
.btn-ghost:hover { border-color: var(--on-dark); background: rgba(246, 244, 240, .06); }

.btn-dark { background: var(--graphite); color: var(--cream); }
.btn-dark:hover { background: var(--cta); color: #17130f; }

/* Logo chip: the Hay Ink mark is black strokes on transparent, so on dark
   grounds it needs a cream plate to survive. No white variant exists. */
.brand-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--cream);
  padding: 10px 13px;
  border-radius: 3px;
  transition: transform .4s var(--ease);
}
.brand-chip img { height: 34px; width: auto; }
.brand:hover .brand-chip { transform: translateY(-2px); }

/* --------------------------------------------------------------------------
   4. MOTION
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay: var(--d, 0s);
}
.reveal.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   5. NAV
   -------------------------------------------------------------------------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 90;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background .4s var(--ease), border-color .4s var(--ease);
}
.nav.is-stuck {
  background: #0d0d0d;
  border-bottom-color: var(--hair-dark);
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  height: 78px;
}
.nav-links { display: flex; gap: 30px; margin-left: auto; }
.nav-links a {
  font-size: 13px;
  font-weight: 500;
  color: var(--on-dark-soft);
  transition: color .25s var(--ease);
}
.nav-links a:hover { color: var(--on-dark); }

/* Menu button: only exists below 1080px, where the link row becomes a panel. */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 40px;
  height: 40px;
  padding: 0 7px;
  background: transparent;
  border: 0;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  height: 1px;
  background: var(--on-dark);
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}
.nav.is-open .nav-toggle span:first-child { transform: translateY(3.5px) rotate(45deg); }
.nav.is-open .nav-toggle span:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

/* --------------------------------------------------------------------------
   6. SECTION 1, HERO
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  background: var(--ink);
  overflow: hidden;
  padding: 130px 0 120px;
}
.hero-bg { position: absolute; inset: 0; }
.hero-bg img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 62%;
  transform: scale(1.02);
  will-change: transform;
}
/* slow zoom, class added by main.js and skipped under reduced motion */
.hero-bg.is-zooming img { animation: heroZoom 34s var(--ease) infinite alternate; }
@keyframes heroZoom {
  from { transform: scale(1.02); }
  to   { transform: scale(1.14); }
}

.hero-scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(100deg, rgba(8,8,8,.94) 0%, rgba(8,8,8,.82) 34%, rgba(8,8,8,.34) 62%, rgba(8,8,8,.5) 100%),
    linear-gradient(180deg, rgba(8,8,8,.78) 0%, rgba(8,8,8,0) 36%, rgba(8,8,8,.5) 100%);
}

.hero-inner { position: relative; z-index: 2; }

.hero-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--h1);
  line-height: 1.02;
  letter-spacing: -.035em;
  color: var(--on-dark);
  margin-bottom: 30px;
}
.hero-line-1 { display: block; }

/* Kinetic line. Words are stacked and swapped by main.js. */
.hero-rot {
  display: block;
  position: relative;
  min-height: 1.06em;
  color: var(--teal);
  white-space: nowrap;
}
.hero-rot-item {
  position: absolute;
  inset: 0 auto auto 0;
  opacity: 0;
  transform: translateY(.32em);
  transition: opacity .55s var(--ease), transform .65s var(--ease);
  will-change: transform, opacity;
}
.hero-rot-item.is-active { opacity: 1; transform: none; }
.hero-rot-item.is-out { opacity: 0; transform: translateY(-.32em); }

.hero-sub {
  font-size: clamp(16px, 1.35vw, 19px);
  line-height: 1.72;
  color: var(--on-dark-soft);
  max-width: 52ch;
  margin-bottom: 42px;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 16px; }

.hero-cue {
  position: absolute;
  left: var(--gutter);
  bottom: 34px;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
  transition: color .3s var(--ease);
}
.hero-cue:hover { color: var(--on-dark); }
.hero-cue-line {
  display: block;
  width: 34px; height: 1px;
  background: currentColor;
  transform-origin: left;
  animation: cueSlide 2.6s var(--ease) infinite;
}
@keyframes cueSlide {
  0%, 100% { transform: scaleX(.4); opacity: .5; }
  50%      { transform: scaleX(1);  opacity: 1; }
}

/* --------------------------------------------------------------------------
   7. SECTION 2, TRUST STRIP
   -------------------------------------------------------------------------- */
.trust {
  background: var(--void);
  padding: clamp(48px, 6vw, 76px) 0 clamp(36px, 4vw, 52px);
  border-bottom: 1px solid var(--hair-dark);
}
.trust-stats {
  display: flex;
  flex-wrap: wrap;
  /* space-between so the three numbers compose across the full band instead of
     clustering in the left half on a wide screen */
  justify-content: space-between;
  gap: clamp(36px, 7vw, 100px);
  padding-bottom: clamp(40px, 5vw, 64px);
}
.trust-stat { display: flex; flex-direction: column; gap: 8px; }
.trust-n {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 3.6vw, 50px);
  line-height: 1;
  letter-spacing: -.04em;
  color: var(--on-dark);
}
.trust-l {
  font-size: 13px;
  letter-spacing: .04em;
  color: var(--on-dark-mute);
}

/* Client logo marquee ---------------------------------------------------- */
.marquee { border-top: 1px solid var(--hair-dark); padding-top: clamp(28px, 3vw, 40px); }
.marquee-label {
  padding-inline: var(--gutter);
  max-width: var(--wrap);
  margin: 0 auto 26px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.marquee-viewport {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 58px, #000 calc(100% - 58px), transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 58px, #000 calc(100% - 58px), transparent 100%);
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee var(--marquee-duration, 34s) linear infinite;
}
.marquee:hover .marquee-track { animation-play-state: paused; }
@keyframes marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
.marquee-group { display: flex; align-items: center; gap: clamp(28px, 4vw, 56px); padding-right: clamp(28px, 4vw, 56px); }

/* Client marks arrive on white or light grounds and none has a mono version,
   so each sits on a cream plate, desaturated at rest and full colour on hover. */
.logo-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: clamp(126px, 12vw, 156px);
  height: clamp(96px, 9vw, 118px);
  padding: 16px 22px;
  background: var(--cream);
  border-radius: 3px;
  transition: transform .4s var(--ease);
}
.logo-chip img {
  max-height: 100%;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  filter: grayscale(1) contrast(.92);
  opacity: .66;
  transition: filter .4s var(--ease), opacity .4s var(--ease);
}
.logo-chip:hover { transform: translateY(-3px); }
.logo-chip:hover img { filter: none; opacity: 1; }
/* Floor Vision artwork is pure white: needs a dark chip, and hover must not gray it out */
.logo-chip--dark { background: #1c1c1c; }
.logo-chip--dark img { filter: none; opacity: .8; }
.logo-chip--dark:hover img { opacity: 1; }
/* Pizzanini ship no transparent version: the file is white artwork baked onto a
   solid red tile. Matching the chip to that red is the only way it does not read
   as a hard rectangle sitting inside the cream plate. */
.logo-chip--tile {
  background: #e2032e;
  padding: 14px 18px;
  /* the whole chip desaturates, not just the artwork, so it follows the same
     grey at rest and colour on hover rule as the transparent marks */
  filter: grayscale(1) contrast(.92);
  opacity: .78;
  transition: transform .4s var(--ease), filter .4s var(--ease), opacity .4s var(--ease);
}
.logo-chip--tile:hover { filter: none; opacity: 1; }
.logo-chip--tile img { filter: none; opacity: 1; }

/* --------------------------------------------------------------------------
   8. SECTION 3, FPV PROCESS WORLD
   The engine builds and themes its own DOM inside #world. Everything here is
   either a theme variable it reads, or styling for the static copy fallback
   it hides on mount.
   -------------------------------------------------------------------------- */
.process-world { background: var(--ink); }

#world {
  --sw-bg: #0f0f0f;
  --sw-ink: #F6F4F0;
  --sw-ink-soft: rgba(246, 244, 240, .58);
  --sw-accent: #00aea8;
  --sw-font-display: 'Lexend Mega', 'Arial Black', sans-serif;
  --sw-font-body: 'Space Grotesk', system-ui, sans-serif;
}

.process-static { padding: var(--sec-y) 0; }
/* Set by the inline script in <head> whenever the scroll flight is going to
   mount. It keeps the fallback out of the very first layout, so its five lazy
   stills are never queued. See the comment on that script. */
.fpv .process-static { display: none; }
.process-static-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--h2);
  line-height: 1.08;
  letter-spacing: -.02em;
  color: var(--on-dark);
  max-width: 16ch;
  margin-bottom: clamp(40px, 5vw, 72px);
}
.process-list { display: flex; flex-direction: column; gap: clamp(28px, 4vw, 56px); }
.process-item {
  display: grid;
  grid-template-columns: 7fr 5fr;
  gap: clamp(20px, 3vw, 48px);
  align-items: center;
}
.process-item:nth-child(even) { grid-template-columns: 5fr 7fr; }
.process-item:nth-child(even) .process-figure { order: 2; }
.process-figure {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--panel-2);
}
.process-figure img { width: 100%; height: 100%; object-fit: cover; }
.process-copy h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--h3);
  letter-spacing: -.01em;
  color: var(--on-dark);
  margin-bottom: 10px;
}
.process-num { color: var(--teal); margin-right: 10px; }
.process-copy p { color: var(--on-dark-soft); max-width: 42ch; }

/* The flight ------------------------------------------------------------
   Everything below only applies once js/main.js has mounted the engine, which
   it does not do under prefers-reduced-motion. The engine's own CSS lives in
   a cascade layer, so these plain rules win over it whatever the specificity.

   The section is taller than the flight: the lead in above #world means the
   fixed layers always fade up against flat ink instead of cutting in over the
   trust strip. .is-live is toggled by main.js while the section owns the
   screen. */
/* Two numbers, both about the seams around the flight.

   padding-top is the lead in. The gate flips the moment the section top crosses
   the viewport top, so this is how much scroll happens before scene 1 is fully
   lit. One crossfade's worth (the engine's crossfade is 0.2vh) is enough: any
   more and the hero's "Watch the Process" lands the visitor on flat black.

   margin-bottom cancels the engine's own trailing viewport (it makes the track
   1vh taller than the flight "so the last flight completes"). The flight ends
   exactly when the gate hides the fixed layers, so that spare viewport was a
   screenful of nothing between the last scene and the cream section. Pulling the
   next section up by the same amount puts it right where the flight ends. */
.process-world.is-flight { padding-top: 6vh; margin-bottom: -100vh; }

#world .sw-sky,                 /* the section's own background does this job */
#world .sw-topbar {             /* no brand, nav, or cta configured: it is empty */
  display: none;
}

/* Asymmetric on purpose: fading up over .34s reads as a dissolve, but on a fast
   scroll back up the same .34s leaves the flight copy ghosting over the trust
   strip. Out is quick, in stays slow. */
#world .sw-stage,
#world .sw-copylayer,
#world .sw-route,
#world .sw-hint,
#world .sw-scrollbar {
  opacity: 0;
  visibility: hidden;
  transition: opacity .12s var(--ease), visibility 0s linear .12s;
}
/* #world in the selector on purpose: the hidden state above is carried by an
   id, so the live state has to be at least as specific. */
.process-world.is-live #world .sw-stage,
.process-world.is-live #world .sw-copylayer,
.process-world.is-live #world .sw-route,
.process-world.is-live #world .sw-hint,
.process-world.is-live #world .sw-scrollbar {
  opacity: 1;
  visibility: visible;
  transition: opacity .34s var(--ease), visibility 0s;
}

/* Flight progress, along the bottom edge. The engine puts it at the top,
   where our own nav bar would cover it. */
#world .sw-scrollbar {
  top: auto;
  bottom: 0;
  height: 2px;
  background: rgba(246, 244, 240, .1);
}

/* Legibility scrim. The engine hangs one off the copy layer, which would then
   need its own gate: carrying it on each scene instead means it fades in and
   out with the artwork it is darkening. Same angle as the hero scrim. */
#world .sw-copylayer::before { display: none; }
#world .sw-scene::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(8,8,8,.93) 0%, rgba(8,8,8,.78) 32%, rgba(8,8,8,.3) 60%, rgba(8,8,8,.06) 100%),
    linear-gradient(180deg, rgba(8,8,8,.5) 0%, rgba(8,8,8,0) 30%, rgba(8,8,8,.34) 100%);
}

/* Scene copy, aligned to the page's own wrap so it lines up with every other
   section instead of the engine's default gutter. */
#world .sw-copy {
  left: max(var(--gutter), calc((100% - var(--wrap)) / 2 + var(--gutter)));
  width: min(46vw, 500px);
}
#world .sw-copy__num {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .22em;
  color: var(--on-dark-mute);
}
#world .sw-copy__eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .3em;
  margin-top: 18px;
}
#world .sw-copy__title {
  font-family: var(--font-display);
  font-size: clamp(26px, 3vw, 42px);
  line-height: 1.06;
  letter-spacing: -.03em;
  margin-top: 12px;
  text-shadow: 0 2px 34px rgba(8, 8, 8, .75);
}
#world .sw-copy__body {
  margin-top: 18px;
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.7;
  /* a step brighter than --on-dark-soft: this copy sits on photography, not
     on a flat panel */
  color: rgba(246, 244, 240, .76);
  max-width: 34ch;
  text-shadow: 0 1px 20px rgba(8, 8, 8, .8);
}

/* The engine's pills would be white on cream. Match the page buttons. */
#world .sw-copy__cta { margin-top: 30px; }
#world .sw-btn {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  padding: 17px 34px;
  border-radius: 0;
  transition: background .28s var(--ease), color .28s var(--ease), border-color .28s var(--ease);
}
/* OWNER DECISION 2026-08-21: yellow CTAs, never teal/green (see .btn-primary) */
#world .sw-btn--primary { background: var(--cta); color: #17130f; }
#world .sw-btn--primary:hover { background: #E6C009; transform: none; }

#world .sw-route__label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--on-dark);
  background: rgba(10, 10, 10, .86);
  border-color: var(--hair-dark);
  backdrop-filter: none;
}
#world .sw-hint {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .3em;
  color: var(--on-dark-mute);
}

@media (max-width: 860px) {
  .process-world.is-flight { padding-top: 5vh; }
  /* The engine's scroll hint sits at the bottom edge, where the scene copy also
     lives on a phone. One or the other, and the copy wins. */
  #world .sw-hint { display: none; }
  /* Copy sits over the bottom of the frame on phones (the engine handles the
     placement), so the scrim has to run bottom up rather than left to right. */
  #world .sw-scene::after {
    background: linear-gradient(0deg, rgba(8,8,8,.95) 4%, rgba(8,8,8,.74) 38%, rgba(8,8,8,.16) 70%, rgba(8,8,8,.4) 100%);
  }
  #world .sw-copy { left: var(--gutter); right: var(--gutter); width: auto; }
}

/* --------------------------------------------------------------------------
   9. SECTION 4, WHAT WE MAKE
   -------------------------------------------------------------------------- */
.make { padding: var(--sec-y) 0; }

.make-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(14px, 1.6vw, 22px);
}
.tile-5 { grid-column: span 5; }
.tile-7 { grid-column: span 7; }

.tile {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid rgba(26, 26, 26, .07);
  overflow: hidden;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease), border-color .5s var(--ease);
}
.tile:hover {
  transform: translateY(-5px);
  box-shadow: 0 26px 60px rgba(26, 26, 26, .11);
  border-color: rgba(26, 26, 26, .14);
}

/* Each render carries its own slightly different studio background (and some
   have a vignette), so contain would show a seam against any flat plate.
   Cover it is, with the two tile widths given aspect ratios that land on the
   same media height. That keeps the grid rows level AND keeps the crop small
   enough that no collar or hem is cut off. */
.tile-media {
  position: relative;
  display: block;
  flex: 0 0 auto;
  overflow: hidden;
  background: var(--cream-deep);
}
.tile-5 .tile-media { aspect-ratio: .90; }   /* narrow tile, crops sideways */
.tile-7 .tile-media { aspect-ratio: 1.275; } /* wide tile, crops top and bottom */

.tile-media img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transition: opacity .5s var(--ease), transform .8s var(--ease);
}
.tile-back { opacity: 0; }
.tile:hover .tile-front { opacity: 0; }
.tile:hover .tile-back  { opacity: 1; }
.tile:hover .tile-media img { transform: scale(1.03); }

.tile-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: clamp(22px, 2.2vw, 32px);
  flex: 1 1 auto;
}
.tile-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--h3);
  letter-spacing: -.02em;
  color: var(--on-cream);
  line-height: 1.2;
}
.tile-desc { font-size: 14.5px; line-height: 1.65; color: var(--on-cream-soft); flex: 1; }
.tile-cta {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 8px;
  margin-top: auto;
  padding-top: 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--teal-deep);
}
.tile-cta .ico { font-size: 15px; transition: transform .4s var(--ease); }
.tile:hover .tile-cta .ico { transform: translateX(5px); }

/* The one dark note in the cream band. Real line art from the artist line runs
   across the whole panel as a texture, so the tile has something in it where
   the paired tiles have a photograph. */
.tile-more {
  position: relative;
  background: var(--graphite);
  border-color: var(--graphite);
}
.tile-more::after {
  content: '';
  position: absolute;
  inset: 0;
  background: right bottom / cover no-repeat;
  filter: grayscale(1) brightness(1.9) contrast(1.05);
  mix-blend-mode: screen;
  opacity: .12;
  /* Strongest bottom right, gone by the top left, so the name and the standfirst
     always sit on flat ink. */
  -webkit-mask-image: radial-gradient(135% 115% at 100% 100%, #000 18%, transparent 88%);
          mask-image: radial-gradient(135% 115% at 100% 100%, #000 18%, transparent 88%);
  pointer-events: none;
}
/* The texture is 55KB of pure decoration a screen and a half below the fold, and
   a CSS background on a laid out element is fetched at first paint whether or not
   anyone can see it. Hanging the URL off .is-in defers it to the same scroll that
   reveals the tile. Two paths opt out of that by design: under reduced motion,
   and with no IntersectionObserver, js/main.js flags every .reveal in at once, so
   those visitors still pay for the texture up front. The file is flattened onto
   black at export (no alpha channel, about half the bytes of the cut out
   original, invisible at 12%), which is what the screen blend above puts back. */
.tile-more.is-in::after {
  background-image: url('../assets/photos/chechu-art-texture.webp');
}
/* This tile carries no media, so the grid row stretches it to the height of the
   photographed tile beside it, roughly 450px taller than its copy. The list is
   the element that absorbs that: a stacked hairline list stretches and spaces its
   own rows out, where the old pill row could only sit there at one fixed height.
   Centring the whole body instead (an earlier attempt) just split the empty black
   into two bands. One column needs no override: nothing forces the tile taller
   than its copy there, so the list simply collapses to its natural height. */
.tile-more .tile-body { flex: 1 1 auto; position: relative; z-index: 1; }
.tile-more .tile-name { color: var(--cream); }
.tile-more .tile-desc { color: rgba(246, 244, 240, .55); flex: 0 0 auto; max-width: 46ch; }
.tile-cta-light { color: var(--teal); }

.more-list {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  margin: 14px 0 0;
  border-top: 1px solid rgba(246, 244, 240, .14);
}
/* Equal shares of whatever height is going, rather than natural height plus one
   gap: five even rows read as a spec table, five tight rows with 90px of air
   between them read as a bug. */
.more-list li {
  display: flex;
  flex: 1 1 0;
  align-items: center;
  min-height: 46px;
  padding: 10px 0;
  font-size: 14px;
  letter-spacing: .01em;
  color: rgba(246, 244, 240, .82);
  border-bottom: 1px solid rgba(246, 244, 240, .14);
}
/* The dot is the only ornament: a bullet glyph would inherit the list marker
   styling reset elsewhere in the sheet. */
.more-list li::before {
  content: '';
  flex: 0 0 auto;
  width: 5px;
  height: 5px;
  margin-right: 14px;
  border-radius: 50%;
  background: var(--teal);
}

/* --------------------------------------------------------------------------
   10. SECTION 5, REAL WORK
   -------------------------------------------------------------------------- */
.real { background: var(--panel-2); padding: var(--sec-y) 0; }

/* Three photographs, one per column, sized so the stack finishes within about
   40px of level. The middle column drops to break the top line: ragged reads as
   editorial, a row of three matched rectangles reads as a stock grid. */
.gallery {
  display: grid;
  grid-template-columns: 1fr .85fr 1.1fr;
  gap: clamp(16px, 1.8vw, 26px);
  align-items: start;
}
.gcol { display: flex; flex-direction: column; gap: clamp(16px, 1.8vw, 26px); }
.gcol-b { padding-top: clamp(0px, 5vw, 70px); }

.shot { position: relative; }
.shot img {
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  background: var(--panel);
  transition: transform .9s var(--ease), filter .9s var(--ease);
}
.gcol-a .shot img { aspect-ratio: 3 / 4; }
.gcol-b .shot img { aspect-ratio: 2 / 3; }
/* squarer and cropped higher: the third frame is the same tee as the first, so
   it earns its place as a closer look at the print, not a second copy */
.gcol-c .shot img { aspect-ratio: 1; object-position: 50% 34%; }
.shot:hover img { transform: scale(1.02); }

.shot figcaption {
  margin-top: 12px;
  font-size: 12.5px;
  line-height: 1.6;
  letter-spacing: .01em;
  /* these captions carry the artist-line credit, so they have to be readable at
     rest, not only on hover */
  color: var(--on-dark-soft);
  transition: color .4s var(--ease);
}
.shot:hover figcaption { color: var(--on-dark); }

/* --------------------------------------------------------------------------
   11. SECTION 6, HOW IT WORKS
   -------------------------------------------------------------------------- */
.how { padding: var(--sec-y) 0; }
.how-grid {
  display: grid;
  grid-template-columns: 4.5fr 7.5fr;
  gap: clamp(36px, 6vw, 96px);
  align-items: start;
}
.how-intro .sec-title { margin-bottom: 22px; }
.how-note {
  font-size: 15.5px;
  line-height: 1.75;
  color: var(--on-cream-soft);
  max-width: 40ch;
  margin-bottom: 32px;
}

.how-steps { border-top: 1px solid var(--hair-cream); }
.how-step {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(20px, 3vw, 46px);
  align-items: start;
  padding: clamp(28px, 3.2vw, 44px) 0;
  border-bottom: 1px solid var(--hair-cream);
}
/* staircase, so the band is not three identical rows */
.how-step:nth-child(2) { padding-left: clamp(0px, 4vw, 56px); }
.how-step:nth-child(3) { padding-left: clamp(0px, 8vw, 112px); }

.how-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(30px, 3.4vw, 48px);
  line-height: .95;
  letter-spacing: -.05em;
  color: var(--teal-deep);
  opacity: .44;
}
.how-text h3 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--h3);
  letter-spacing: -.02em;
  color: var(--on-cream);
  margin-bottom: 10px;
}
.how-text p { font-size: 15px; line-height: 1.72; color: var(--on-cream-soft); max-width: 52ch; }

/* --------------------------------------------------------------------------
   12. SECTION 7, QUOTE
   -------------------------------------------------------------------------- */
.quote { background: var(--ink); padding: var(--sec-y) 0; }
.quote-grid {
  display: grid;
  grid-template-columns: 5.5fr 6.5fr;
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}
/* The intro column is narrow and Lexend Mega is wide, so this headline gets
   its own step down the scale to avoid a four line stack with an orphan. */
.quote-intro .sec-title {
  font-size: clamp(24px, 2.9vw, 40px);
  max-width: 18ch;
  margin-bottom: 24px;
}
.quote-note {
  font-size: 15.5px;
  line-height: 1.75;
  color: var(--on-dark-soft);
  max-width: 44ch;
  margin-bottom: 30px;
}

/* The Telegram button is the one primary action in the section, so it sits in
   the intro column: on one column that column comes first, which puts it above
   the email form rather than after it. */
.quote-primary { margin-bottom: 34px; }
.quote-primary-note {
  margin-top: 14px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--on-dark-mute);
}

.contact-list { border-top: 1px solid var(--hair-dark); }
.contact-list li {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: 16px;
  align-items: baseline;
  padding: 14px 0;
  border-bottom: 1px solid var(--hair-dark);
  font-size: 14.5px;
}
.contact-k {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.contact-list a { color: var(--on-dark); transition: color .25s var(--ease); }
.contact-list a:hover { color: var(--teal); }

/* Form ------------------------------------------------------------------- */
.quote-form {
  background: var(--panel-2);
  border: 1px solid var(--hair-dark);
  padding: clamp(26px, 3vw, 44px);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
/* Names the form as the second of the two channels, so the panel does not read
   as a competing primary next to the Telegram button. */
.quote-form-label {
  font-size: 13px;
  line-height: 1.6;
  color: var(--on-dark-mute);
  padding-bottom: 16px;
  margin-bottom: -4px;
  border-bottom: 1px solid var(--hair-dark);
}
.field { display: flex; flex-direction: column; gap: 8px; }
.field label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--on-dark-mute);
}
.field input,
.field textarea {
  background: transparent;
  border: 1px solid rgba(246, 244, 240, .16);
  padding: 14px 16px;
  /* 16px exactly: anything smaller makes iOS Safari zoom the viewport on focus */
  font-size: 16px;
  font-weight: 300;
  color: var(--on-dark);
  transition: border-color .3s var(--ease), background .3s var(--ease);
  resize: vertical;
}
.field input::placeholder,
.field textarea::placeholder { color: rgba(246, 244, 240, .26); }
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--teal);
  background: rgba(246, 244, 240, .03);
}
/* The rule above drops the shared outline, which is right for a click but wrong
   for a keyboard: a border colour shift is not a focus indicator on its own, and
   it disappears entirely under forced-colors. Keyboard focus keeps the ring. */
.field input:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}
.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] { border-color: var(--magenta); }

.quote-form .btn { margin-top: 6px; }
.form-help { font-size: 13px; line-height: 1.65; color: var(--on-dark-mute); }
.form-help a { color: var(--on-dark-soft); border-bottom: 1px solid rgba(246, 244, 240, .3); }
/* The number has spaces in it, so it breaks mid-digits at the end of the line. */
.form-help a[href^="tel:"] { white-space: nowrap; }
.form-help a:hover { color: var(--teal); border-color: var(--teal); }
.form-status {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--teal);
  border-left: 1px solid var(--teal);
  padding-left: 14px;
}
.form-status[data-tone="error"] { color: #f9a8d4; border-color: var(--magenta); }

/* --------------------------------------------------------------------------
   13. SECTION 8, FOOTER
   -------------------------------------------------------------------------- */
.footer { background: var(--void); padding: clamp(56px, 6vw, 84px) 0 30px; }
.footer-inner {
  display: grid;
  grid-template-columns: 2.4fr 1fr 1.1fr 1fr;
  gap: clamp(28px, 4vw, 64px);
  padding-bottom: clamp(36px, 4vw, 56px);
  border-bottom: 1px solid var(--hair-dark);
}
.footer-brand p {
  margin-top: 20px;
  font-size: 14px;
  line-height: 1.75;
  color: var(--on-dark-mute);
  max-width: 32ch;
}
.footer-col h3 {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--on-dark-soft);
  margin-bottom: 18px;
}
.footer-col a, .footer-col span {
  display: block;
  font-size: 14px;
  color: var(--on-dark-mute);
  margin-bottom: 11px;
  transition: color .25s var(--ease);
}
.footer-col a:hover { color: var(--on-dark); }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  padding-top: 26px;
  font-size: 12.5px;
  color: rgba(246, 244, 240, .26);
}

/* --------------------------------------------------------------------------
   14. RESPONSIVE
   -------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  /* The section anchors stay reachable on tablet and phone: the row turns into
     a panel under the bar, opened by .nav-toggle. */
  .nav-toggle { display: flex; }
  .nav.is-open { background: #0d0d0d; }
  .nav-links {
    position: fixed;
    inset: 78px 0 auto 0;
    flex-direction: column;
    gap: 0;
    margin-left: 0;
    padding: 6px var(--gutter) 22px;
    background: #0d0d0d;
    border-bottom: 1px solid var(--hair-dark);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition: opacity .3s var(--ease), transform .3s var(--ease), visibility 0s linear .3s;
  }
  .nav.is-open .nav-links {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: opacity .3s var(--ease), transform .3s var(--ease), visibility 0s;
  }
  .nav-links a {
    padding: 15px 0;
    font-size: 15px;
    border-bottom: 1px solid var(--hair-dark);
  }
  .nav-links a:last-child { border-bottom: 0; }

  .sec-head { grid-template-columns: 1fr; align-items: start; }
  .how-grid { grid-template-columns: 1fr; }
  .quote-grid { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .make-grid { grid-template-columns: repeat(6, 1fr); }
  .tile-5, .tile-7 { grid-column: span 6; }
  .tile-5 .tile-media,
  .tile-7 .tile-media { aspect-ratio: 1; }   /* one column: square, no crop at all */

  .gallery { grid-template-columns: 1fr 1fr; }
  .gcol-b { padding-top: 0; }
  /* the third shot runs the full width under the pair, cropped to a band */
  .gcol-c { grid-column: span 2; }
  .gcol-c .shot img { aspect-ratio: 5 / 4; object-position: 50% 40%; }

  .process-item,
  .process-item:nth-child(even) { grid-template-columns: 1fr; }
  .process-item:nth-child(even) .process-figure { order: 0; }
}

@media (max-width: 759px) {
  /* Hero: let the rotating line wrap so long words never overflow the gutter.
     Armenian will need this headroom too. */
  :root { --h1: clamp(26px, 7.6vw, 46px); }
  /* 2 lines is the no-JS floor. main.js measures the real tallest phrase and
     overrides this, so there is never a dead gap under a one line phrase. */
  .hero-rot { white-space: normal; min-height: 2.16em; }
  .hero { min-height: auto; padding: 128px 0 100px; }
  .hero-actions .btn { flex: 1 1 auto; }
  /* the sideways scrim reads as near black on a narrow screen, so go vertical */
  .hero-scrim {
    background: linear-gradient(180deg, rgba(8,8,8,.92) 0%, rgba(8,8,8,.6) 44%, rgba(8,8,8,.88) 100%);
  }

  /* the stats wrap here, and space-between would strand a hole in the last row */
  .trust-stats { gap: 28px 40px; justify-content: flex-start; }
  .how-step:nth-child(2),
  .how-step:nth-child(3) { padding-left: 0; }
  .contact-list li { grid-template-columns: 92px 1fr; }
}

@media (max-width: 560px) {
  /* logo + quote button + menu button have to share 375px */
  .nav-inner { gap: 10px; }
  .btn-sm { padding: 11px 15px; font-size: 12px; }

  .gallery { grid-template-columns: 1fr; }
  .gcol-c { grid-column: auto; }
  .gcol-c .shot img { aspect-ratio: 4 / 5; object-position: 50% 42%; }
  .footer-inner { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   15. REDUCED MOTION
   Every moving part above has a static fallback here.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }

  .reveal { opacity: 1; transform: none; }
  .hero-bg.is-zooming img { animation: none; transform: scale(1.02); }
  .marquee-track { animation: none; transform: none; }
  .marquee-viewport { overflow-x: auto; }
  .hero-cue-line { animation: none; transform: none; }
  .hero-rot-item { transition: none; }
}
