/* ============================================================
   Dalmend scan landing — Nexus V22 / Kavalsia Inc. / Siavash Sadighi
   style.css
   ============================================================ */

:root{
  --ink:        #0a0a0a;
  --ink-panel:  #0c0b09;
  --gold:       #c2a679;
  --gold-soft:  #dfc496;
  --gold-deep:  #b89c6f;
  --cream:      #f4f1ea;
  --cream-soft: #cfc7b8;

  --f-display: "Cormorant Garamond", Georgia, serif;
  --f-body:    "Inter", system-ui, -apple-system, sans-serif;
  --f-mono:    ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --maxw: 1280px;
  --pad: clamp(1.25rem, 5vw, 4rem);
  --ease: cubic-bezier(.22,.61,.36,1);

  --deck-size: clamp(1.05rem, 2.4vw, 1.4rem);
  --top-band: 120px;
}

@media (max-width: 560px){
  :root{ --deck-size: 1rem; }
}

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

html{
  -webkit-text-size-adjust: 100%;
  background: var(--ink);
}

@media (prefers-reduced-motion: no-preference){
  html{ scroll-behavior: smooth; }
}

body{
  background: var(--ink);
  color: var(--cream);
  font-family: var(--f-body);
  font-weight: 300;
  line-height: 1.7;
  letter-spacing: .01em;
  /* clip, not hidden: hidden on one axis forces the other axis to
     auto per the CSS overflow spec, which makes html/body an
     implicit scroll container and breaks position:sticky (computed
     against the nearest scroll container) for every .section-inner
     on the page. clip has no such pairing rule. */
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img{ display: block; max-width: 100%; }
a{ color: inherit; text-decoration: none; }

/* keep the gold focus ring, never delete it */
:focus-visible{
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

/* selection */
::selection{
  background: var(--gold);
  color: var(--ink);
}

/* scrollbar (webkit) */
::-webkit-scrollbar{ width: 10px; }
::-webkit-scrollbar-track{ background: var(--ink); }
::-webkit-scrollbar-thumb{
  background: var(--gold-deep);
  border-radius: 6px;
  border: 2px solid var(--ink);
}
html{ scrollbar-color: var(--gold-deep) var(--ink); scrollbar-width: thin; }

/* ---------- canvas ---------- */
#scene{
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
  display: block;
  background: var(--ink);
}

.grain{
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  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");
}

/* ---------- brand mark ---------- */
/* the top var(--top-band) is reserved for the wordmark alone;
   no caption may enter it at any scroll position (see .section-inner
   sticky offset + .top-guard-hide below) */
.brand-mark{
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  display: flex;
  justify-content: center;
  padding: clamp(1.1rem, 3vw, 1.6rem) var(--pad);
  pointer-events: none;
  /* the wordmark is persistent chrome over a scene whose brightness at
     the very top of frame varies by section (measured: 2.28:1 against
     the burn section, s7, where the top of frame reads brighter than
     elsewhere) -- not a plate behind a text block (the "bare ink, no
     plates" rule is about the section captions), but a graduated scrim
     under a fixed nav bar, the same job the vignette already does for
     the text column. Invisible over the near-black ground everywhere
     else; only does real work over a bright frame. */
  background: linear-gradient(to bottom, rgba(0,0,0,.72) 0%, rgba(0,0,0,.72) 65%, transparent 100%);
}
/* Dalmend-alignment restyle, type item 1: the wordmark is small
   persistent chrome (like a nav item), not a display line or a
   product name, so it takes the site's signature small-type
   treatment -- Inter, uppercase, wide tracking -- instead of the
   display face. */
.brand-mark a{
  pointer-events: auto;
  font-family: var(--f-body);
  font-weight: 500;
  font-size: .82rem;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--cream-soft);
  opacity: .85;
  transition: opacity .3s var(--ease), color .3s var(--ease);
}
.brand-mark a:hover,
.brand-mark a:focus-visible{
  opacity: 1;
  color: var(--gold);
}

/* ---------- layout ---------- */
main{
  position: relative;
  z-index: 2;
}

.scene-section{
  position: relative;
  min-height: calc(var(--section-vh, 100) * 1vh);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
}

#s10{ padding-bottom: 1rem; }
.site-footer{ margin-top: auto; }

/* text zone: bare ink, no plates. Pinned below the reserved wordmark
   band while its section is active, so a caption can never sit under
   the wordmark; unpins with its own section and is cross-faded out
   by .top-guard-hide (app.js) before it would rise back through the
   band on exit. Left column on desktop (model sits offset right of
   center); on mobile the same column simply reads as type-above,
   model-below since there is no side-by-side room. */
.section-inner{
  position: sticky;
  top: var(--top-band);
  z-index: 2;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding: 0 var(--pad);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: 1.1rem;
}

.section-inner.hero{ gap: 1.5rem; }

/* ---------- type ---------- */
/* Dalmend-alignment restyle, type item 1: display lines get the tight
   pole of the site's tracking contrast (-0.02 to -0.04em) so they read
   as confident editorial display type against the wide-tracked small
   caps everywhere else -- that contrast IS the look. Composition fix
   (item 2, section 9): a display heading with no measure can run the
   full width of the max-width column, which is how the s9 reveal line
   used to reach into the model's screen position on the right; capping
   the measure keeps every display line inside the left text column
   regardless of how long the sentence is, without a plate or box. */
.display{
  font-family: var(--f-display);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--cream);
  max-width: 13em;
}
.display.huge{ font-size: clamp(2.4rem, 8vw, 6rem); }
.display.medium{ font-size: clamp(1.9rem, 5.6vw, 3.6rem); }
/* composition fix (item 2): only one line may hold display scale in
   a given viewport. Used on the close line (s10) so it steps down
   from the reveal line (s9) instead of the two competing for the
   same weight at the section boundary. */
.display.small{ font-size: clamp(1.5rem, 3.2vw, 2.2rem); }

/* product-page name treatment: same size scale as .display.huge
   (the 6rem cap is never exceeded), uppercase and tracked wider so
   the name reads as a mark rather than a sentence */
.name-display{
  text-transform: uppercase;
  letter-spacing: .05em;
  font-weight: 500;
}

.deck{
  font-family: var(--f-body);
  font-weight: 300;
  font-size: var(--deck-size);
  line-height: 1.65;
  max-width: 68ch;
  color: var(--cream);
}
.deck.small{
  font-size: calc(var(--deck-size) * .82);
  color: var(--cream-soft);
  max-width: 58ch;
}
/* scoped exception: the mobile ember-assembly caption on the product
   pages sits over a bright, scattering gold point field for most of
   its section (measured 3.9-4.27:1 against --cream-soft, the WebGL
   vignette's own protection over that particular content is not
   ours to touch). --cream clears >5.8:1 against the same measured
   background. Used only where measured, not a blanket change to
   .deck.small elsewhere. */
.deck.small.on-bright{ color: var(--cream); }
.deck a{
  color: var(--gold);
  text-decoration: underline;
  text-underline-offset: .18em;
  transition: color .3s var(--ease);
}
.deck a:hover,
.deck a:focus-visible{ color: var(--gold-soft); }

.mono{
  font-family: var(--f-mono);
  color: var(--gold);
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
}
.count{
  font-size: clamp(1.6rem, 5vw, 2.6rem);
  display: flex;
  align-items: baseline;
  gap: .5em;
}
.count-label{
  font-family: var(--f-body);
  font-size: .38em;
  color: var(--cream-soft);
  text-transform: uppercase;
  letter-spacing: .22em;
}
.material-tag{
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .25em;
}

em{ font-style: italic; color: var(--gold-soft); }

/* ---------- collection links ---------- */
/* Dalmend-alignment restyle, type item 1: these were small Cormorant
   italic and read as an afterthought. Tracked uppercase Inter, the
   site's own small-type signature, with a real hover/focus state
   (color + an underline that grows in, not just a color swap) and a
   44px tap target on mobile (see the mobile media query below). */
.collection-links{
  display: flex;
  flex-wrap: wrap;
  gap: .7rem 2rem;
  justify-content: flex-start;
  padding-top: .3em;
}
.collection-links a{
  font-family: var(--f-body);
  font-weight: 500;
  font-size: clamp(.82rem, 1.4vw, .95rem);
  text-transform: uppercase;
  letter-spacing: 2.5px;
  color: var(--cream-soft);
  padding: .3em .05em;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: .45em;
  transition: color .3s var(--ease), text-decoration-color .3s var(--ease);
}
.collection-links a:hover,
.collection-links a:focus-visible{
  color: var(--gold);
  text-decoration-color: var(--gold);
}

/* ---------- CTA ---------- */
.cta{
  display: inline-block;
  font-family: var(--f-body);
  font-weight: 500;
  font-size: 1rem;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--gold);
  padding: 1em 2.2em;
  transition: background .3s var(--ease), transform .3s var(--ease);
}
.cta:hover,
.cta:focus-visible{
  background: var(--gold-soft);
}
.cta:active{ transform: translateY(1px); }

/* ---------- footer ---------- */
/* metadata line: same small-type treatment as everything else in
   this tier (Inter, uppercase, tracked), sized down since a whole
   sentence at 2px tracking reads wide -- see type item 1. */
.site-footer{
  position: relative;
  z-index: 2;
  width: 100%;
  text-align: center;
  padding: 3rem var(--pad) 2.5rem;
  font-size: .68rem;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--cream-soft);
  opacity: .7;
}
.site-footer a{
  color: var(--cream-soft);
  text-decoration: underline;
  text-underline-offset: .2em;
  transition: color .3s var(--ease);
}
.site-footer a:hover,
.site-footer a:focus-visible{
  color: var(--gold);
}

/* ---------- hairline gold rule: quiet structure, never a divider box ---------- */
.rule-gold{
  width: 100%;
  max-width: 5.5rem;
  height: 1px;
  border: 0;
  background: linear-gradient(to right, var(--gold-deep), transparent);
  opacity: .4;
}

/* ============================================================
   motion: content visible by default, JS arms entrances
   ============================================================ */
.reveal{
  opacity: 1;
  transform: none;
  filter: none;
}

/* ---------- per-word masked heading reveal ---------- */
/* visible, unsplit text is the fallback: if JS never runs (no-JS) or
   never gets to initWordReveal, this is just a heading with normal
   text and full opacity — nothing here depends on the split existing. */
.reveal-heading{ opacity: 1; }
.word-mask{
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}
.word{ display: inline-block; }

html.js-armed .reveal-heading .word{
  transform: translateY(105%);
  opacity: 0;
  transition: transform .72s var(--ease), opacity .6s var(--ease);
  transition-delay: calc(var(--i, 0) * 40ms);
  will-change: transform, opacity;
}
html.js-armed .reveal-heading.is-in .word{
  transform: translateY(0);
  opacity: 1;
}
@media (prefers-reduced-motion: reduce){
  html.js-armed .reveal-heading .word{
    transform: none !important;
    opacity: 1 !important;
    transition: none !important;
  }
}

html.js-armed .reveal{
  opacity: 0;
  transform: translateY(18px);
  filter: blur(2px);
  transition:
    opacity .9s var(--ease),
    transform .9s var(--ease),
    filter .9s var(--ease);
  will-change: opacity, transform, filter;
}

html.js-armed .reveal.is-in{
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* stagger children within a section slightly */
html.js-armed .section-inner .reveal:nth-child(2){ transition-delay: .08s; }
html.js-armed .section-inner .reveal:nth-child(3){ transition-delay: .16s; }
html.js-armed .section-inner .reveal:nth-child(4){ transition-delay: .24s; }

@media (prefers-reduced-motion: reduce){
  html.js-armed .reveal{
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    transition: none !important;
  }
}

/* top-band exit guard (app.js): fades a caption out before it would
   ever rise back through the reserved wordmark band as its section's
   sticky pin releases. Declared after the reduced-motion block so it
   wins the tie between two !important opacity rules — the guard must
   hold even with motion reduced, since it is a layout rule, not an
   animation. */
.top-guard-hide{
  opacity: 0 !important;
  pointer-events: none !important;
}

/* ---------- mobile ---------- */
@media (max-width: 560px){
  .section-inner{ gap: .85rem; }
  .cta{
    display: block;
    width: 100%;
    text-align: center;
    min-height: 44px;
    line-height: 1.2;
    padding: 1em 1.2em;
  }
  .collection-links{
    flex-direction: column;
    gap: .7rem;
    align-items: flex-start;
  }
  .collection-links a{
    min-height: 44px;
    display: flex;
    align-items: center;
  }
  .brand-mark a{ min-height: 44px; display: flex; align-items: center; }
}

/* no horizontal scroll anywhere. clip, not hidden — see the note on
   body's overflow-x above; the html rule needs the same fix, since
   pairing it with a visible overflow-y here would trip the same
   spec rule and re-break every .section-inner's sticky pin. */
html{ overflow-x: clip; }
html, body{ max-width: 100%; }
