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

html {
  height: 100%;
  height: -webkit-fill-available;
}

body {
  min-height: 100%;
  min-height: -webkit-fill-available;
  color: #111;
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-font-smoothing: antialiased;
  background-color: #f5f5f3;
  background-image: url("assets/dots.png");
  background-repeat: repeat;
  background-size: 1400px auto;
  background-position: top left;
}

body.is-booting,
body.contents-open,
html.is-locked body {
  overflow: hidden;
}

/* ---------- Soft password gate ---------- */

.gate {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 10000;
  align-items: center;
  justify-content: center;
  padding: max(1.5rem, env(safe-area-inset-top)) 1.5rem max(1.5rem, env(safe-area-inset-bottom));
  /* Let the body off-white + grid show through */
  background: transparent;
}

html.is-locked .gate {
  display: flex;
}

html.is-locked #site {
  visibility: hidden;
  pointer-events: none;
}

.gate__box {
  width: min(22rem, 88vw);
  padding: 2rem 1.75rem 1.75rem;
  border: 1px solid #111;
  border-radius: 10px;
  background-color: #f5f5f3;
}

.gate__form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  width: 100%;
}

.gate__label {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(0.85rem, 2vw, 0.95rem);
  letter-spacing: 0.16em;
  line-height: 1.2;
  color: rgba(17, 17, 17, 0.5);
  text-align: center;
}

/* Field chrome lives here so the input can stay ≥16px (no iOS focus zoom)
   while the mask dots still read small via scale. */
.gate__field {
  width: 100%;
  height: 2.1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-bottom: 1px solid rgba(17, 17, 17, 0.22);
  transition: border-color 0.25s ease;
  overflow: hidden;
}

.gate__form:focus-within .gate__field {
  border-bottom-color: rgba(17, 17, 17, 0.55);
}

.gate__input {
  width: 200%;
  height: 2.1rem;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 16px; /* iOS won't zoom if ≥16px */
  letter-spacing: 0.45em;
  line-height: 2.1rem;
  color: #111;
  text-align: center;
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0;
  outline: none;
  box-shadow: none;
  caret-color: rgba(17, 17, 17, 0.75);
  -webkit-appearance: none;
  appearance: none;
  -webkit-text-security: disc;
  transform: scale(0.5);
  transform-origin: center center;
}

.gate__error {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  color: rgba(17, 17, 17, 0.5);
  min-height: 1.1em;
  text-align: center;
}

.gate__submit {
  margin-top: 0.35rem;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(0.8rem, 1.8vw, 0.9rem);
  letter-spacing: 0.16em;
  line-height: 1;
  color: #111;
  background: transparent;
  border: 1px solid #111;
  border-radius: 10px;
  padding: 0.72rem 1.9rem;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition:
    background-color 0.2s ease,
    color 0.2s ease;
}

.gate__submit:hover,
.gate__submit:focus-visible {
  background-color: #111;
  color: #f5f5f3;
  outline: none;
}

.gate__submit:active {
  opacity: 0.88;
}

.gate__form.is-wrong .gate__field {
  border-bottom-color: rgba(17, 17, 17, 0.55);
  animation: gate-shake 0.4s ease;
}

@keyframes gate-shake {
  0%,
  100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5px);
  }
  75% {
    transform: translateX(5px);
  }
}

/* ---------- Hero ---------- */

.landing {
  position: relative;
  width: 100%;
  /* Fallbacks first — some mobile browsers still mishandle svh/dvh alone */
  height: 100vh;
  height: 100svh;
  min-height: 100vh;
  min-height: -webkit-fill-available;
  min-height: 100dvh;
  overflow: hidden;
}

.landing__bg {
  position: absolute;
  inset: 0;
  background: url("assets/titlebg.jpg") center center / cover no-repeat;
  z-index: 0;
}

/* Two identical layers. script.js paints the incoming image onto the hidden
   one, raises its z-index so it covers the other, and fades its opacity up.
   Stacking is set explicitly because DOM order alone would always put the same
   element on top, and half the transitions would then happen out of sight.
   Duration is overridden from script.js (FADE_MS) so the two can't drift. */
.landing__bg--fade {
  transition: opacity 0.55s ease;
}

@media (prefers-reduced-motion: reduce) {
  .landing__bg--fade {
    transition: none;
  }
}

.landing__logo-wrap {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 clamp(0.5rem, 1.5vw, 1.25rem);
}

.hero-logo {
  position: relative;
  /* Matches the kindling.svg viewBox. The mark is ~3.55:1, so the second term
     is the height cap: 210vh of width lands the logo at ~59vh tall. */
  width: min(80vw, 210vh);
  max-width: none;
  aspect-ratio: 1330 / 375;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.hero-logo.is-ready {
  opacity: 1;
}

.hero-logo svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

.hero-logo path {
  fill: #f7f3e4;
}

/* The sweep re-runs the filter every frame; hint it only while running. */
.hero-logo.is-inking svg {
  will-change: filter;
}

/* ---------- Slides ---------- */

.slides {
  --slide-width: 72vw;
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 45% tighter than the original clamp(3rem, 8vh, 5.5rem). */
  gap: clamp(1.65rem, 4.4vh, 3.03rem);
  padding:
    clamp(4rem, 10vh, 7rem)
    clamp(1rem, 4vw, 2rem)
    clamp(5rem, 12vh, 8rem);
  background: transparent;
}

.slide {
  width: var(--slide-width);
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.85rem;
  scroll-margin-top: 5.5rem;
  opacity: 0;
  translate: 0 28px;
  transition:
    opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1),
    translate 0.9s cubic-bezier(0.22, 1, 0.36, 1);
}

.slide.is-visible {
  opacity: 1;
  translate: 0 0;
}

.slide__title {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(0.8rem, 1.35vw, 0.95rem);
  letter-spacing: 0.04em;
  line-height: 1.2;
  color: rgba(17, 17, 17, 0.72);
  text-shadow:
    0 0 0.4px rgba(0, 0, 0, 0.28),
    0.35px 0 0 rgba(0, 0, 0, 0.22),
    -0.35px 0 0 rgba(0, 0, 0, 0.22),
    0 0.35px 0 rgba(0, 0, 0, 0.22),
    0 -0.35px 0 rgba(0, 0, 0, 0.22);
}

.slide__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  /* Same 8% shadow on every slide. Positive spread pushes the soft cast
     onto the page so it still reads around near-black artwork. */
  box-shadow: 0 8px 28px 4px rgba(0, 0, 0, 0.08);
}


/* ---------- Overview grid (bird's eye view of the deck) ---------- */

.overview {
  position: relative;
  z-index: 1;
  padding:
    clamp(2rem, 5vh, 3.5rem)
    clamp(1rem, 4vw, 2rem)
    clamp(4rem, 9vh, 6rem);
}

.overview__inner {
  width: var(--overview-width, 72vw);
  margin: 0 auto;
}

.overview__heading {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: clamp(0.8rem, 1.35vw, 0.95rem);
  letter-spacing: 0.04em;
  color: rgba(17, 17, 17, 0.72);
  margin-bottom: 1.1rem;
}

.overview__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: clamp(0.6rem, 1.2vw, 1rem);
}

.overview__item {
  position: relative;
  display: block;
  border-radius: 6px;
  overflow: hidden;
  text-decoration: none;
  background: rgba(17, 17, 17, 0.06);
  box-shadow: 0 4px 14px 2px rgba(0, 0, 0, 0.07);
  transition:
    transform 0.25s cubic-bezier(0.22, 1, 0.36, 1),
    box-shadow 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}

.overview__thumb {
  display: block;
  width: 100%;
  height: auto;
}

.overview__meta {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.15rem;
  padding: 0.5rem 0.55rem;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0) 45%,
    rgba(0, 0, 0, 0.78) 100%
  );
  opacity: 0;
  transition: opacity 0.25s ease;
}

.overview__num,
.overview__label {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  color: #fff;
  line-height: 1.2;
}

.overview__num {
  font-weight: 400;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  opacity: 0.75;
}

.overview__label {
  font-weight: 300;
  font-size: 0.72rem;
  letter-spacing: 0.01em;
}

.overview__item:hover,
.overview__item:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 10px 24px 4px rgba(0, 0, 0, 0.14);
}

.overview__item:hover .overview__meta,
.overview__item:focus-visible .overview__meta {
  opacity: 1;
}

.overview__item:focus-visible {
  outline: 2px solid #111;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .overview__item {
    transition: none;
  }
}

/* ---------- Contents toggle (sticky + / x) — LEFT ---------- */

.contents-toggle {
  position: sticky;
  top: 1.25rem;
  /* Sit in the left gutter beside the slide column — never over the slides,
     and never flush to the viewport edge on wide screens */
  align-self: flex-start;
  margin-top: 0;
  margin-right: 0;
  margin-bottom: -44px;
  margin-left: max(
    1rem,
    calc((100% - var(--slide-width)) / 2 - 44px - 1.1rem)
  );
  z-index: 90;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  background: #000;
  color: #fff;
  cursor: pointer;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  transition:
    transform 0.45s cubic-bezier(0.22, 1, 0.36, 1),
    background-color 0.35s ease,
    box-shadow 0.35s ease;
}

.contents-toggle:hover {
  transform: scale(1.04);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.22);
}

.contents-toggle:active {
  transform: scale(0.96);
}

.contents-toggle__icon {
  position: relative;
  width: 14px;
  height: 14px;
  display: block;
}

.contents-toggle__bar {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 1.5px;
  background: #fff;
  border-radius: 999px;
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.contents-toggle__bar--a {
  transform: translate(-50%, -50%) rotate(0deg);
}

.contents-toggle__bar--b {
  transform: translate(-50%, -50%) rotate(90deg);
}

body.contents-open .contents-toggle__bar--a {
  transform: translate(-50%, -50%) rotate(45deg);
}

body.contents-open .contents-toggle__bar--b {
  transform: translate(-50%, -50%) rotate(-45deg);
}

/* When open, park the toggle over the panel's top-left corner */
body.contents-open .contents-toggle {
  position: fixed;
  top: calc(1.1rem + 12px);
  left: calc(1.1rem + 12px);
  right: auto;
  align-self: auto;
  margin: 0;
  z-index: 95;
}

/* ---------- Contents panel ---------- */

.contents-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(0, 0, 0, 0.18);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.contents-backdrop:not([hidden]) {
  display: block;
}

body.contents-open .contents-backdrop {
  opacity: 1;
  pointer-events: auto;
}

.contents-panel {
  position: fixed;
  top: 1.1rem;
  left: 1.1rem;
  bottom: 1.1rem;
  z-index: 80;
  width: min(320px, calc(100vw - 2.2rem));
  background: #000;
  color: #fff;
  border-radius: 10px;
  overflow: hidden;
  transform: translate3d(-110%, 0, 0);
  opacity: 0;
  pointer-events: none;
  transition:
    transform 0.55s cubic-bezier(0.22, 1, 0.36, 1),
    opacity 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

body.contents-open .contents-panel {
  transform: translate3d(0, 0, 0);
  opacity: 1;
  pointer-events: auto;
}

.contents-panel__inner {
  height: 100%;
  overflow-y: auto;
  padding: 1.35rem 1.25rem 1.5rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.25) transparent;
}

.contents-panel__header {
  margin-bottom: 1.35rem;
  padding-left: 2.6rem;
}

.contents-panel__brand {
  font-family: "Geist Sans", Geist, "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-size: 1.35rem;
  letter-spacing: -0.02em;
  line-height: 1.15;
  color: #fff;
}

.contents-panel__label {
  margin-top: 0.55rem;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.72);
}

.contents-panel__nav {
  display: flex;
  flex-direction: column;
  gap: 0.72rem;
}

.contents-link {
  display: grid;
  grid-template-columns: 1.7rem 1fr;
  gap: 0.65rem;
  align-items: baseline;
  text-decoration: none;
  color: #fff;
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.contents-link:hover {
  opacity: 0.72;
}

.contents-link:active {
  transform: translateX(2px);
}

.contents-link__num {
  font-family: "Geist Sans", Geist, "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 600;
  font-size: 0.82rem;
  letter-spacing: -0.01em;
  color: #fff;
}

.contents-link__label {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 100;
  font-size: 0.82rem;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.92);
}

/* ---------- Footer ---------- */

.site-footer {
  position: relative;
  z-index: 1;
  width: 100%;
  background: #000000;
  overflow: hidden;
  line-height: 0;
}

.site-footer__inner {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: clamp(3rem, 7vw, 6rem) clamp(1rem, 3vw, 3rem) 0;
  margin: 0;
}

.site-footer__logo {
  display: block;
  width: 100%;
  max-width: none;
  height: auto;
  /* kindling.svg carries its own fill="#F7F3E4", so it already reads cream on
     the black ground — no invert, which would turn the cream navy. */
  /* Push the mark past the page edge so .site-footer's overflow: hidden slices
     its lower edge. Percentage margins resolve against width, and this mark is
     ~3.55:1, so -3.5% crops roughly 12% of its height. */
  margin-bottom: -3.5%;
}

@media (max-width: 720px) {
  /* Full height on a phone forces a choice between cropping the 16:9 hero to
     a vertical sliver or letterboxing it. Instead, let the section take the
     photo's own proportions: it fills edge to edge with no crop and no bars. */
  .landing {
    height: auto;
    min-height: 0;
    aspect-ratio: 16 / 9;
  }

  .landing__bg {
    background-position: center center;
  }

  /* The section is now only as tall as the photo, so centre the logo in it. */
  .landing__logo-wrap {
    align-items: center;
    padding: 0 clamp(1rem, 5vw, 1.5rem);
  }

  .hero-logo {
    width: 88vw;
  }

  .slides {
    --slide-width: 88vw;
  }

  .overview__inner {
    --overview-width: 88vw;
  }

  .overview__grid {
    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  }

  .slide {
    width: var(--slide-width);
  }

  .contents-toggle {
    margin-left: max(
      0.65rem,
      calc((100% - var(--slide-width)) / 2 - 44px - 0.65rem)
    );
  }
}
