/* ==========================================================================
   KRESTA TEXTILE — Layout
   --------------------------------------------------------------------------
   The reference's defining structure: every section is its own rounded card
   floating on a sage page ground, with that ground showing through the gaps
   between them. Nothing is edge to edge.

   Spacing rule to avoid specificity collisions: vertical rhythm is owned by
   `.section` ONLY. No element selector sets section padding.
   ========================================================================== */

.page {
  position: relative;
  min-height: 100vh;
  padding: var(--frame);
  /* Leaves room for the fixed bar sitting on top of the hero card. */
  padding-top: 0;
}

/* ---------------------------------------------------------------- header --
   Fixed, but inset by --frame and rounded at the top so at rest it reads as
   the bar across the top of the hero card, exactly as in the reference.

   It stays fixed rather than scrolling away with the card: this page exists
   to collect enquiries, and the basket counter and quote CTA have to remain
   reachable from anywhere in a long scroll.                                */

/* Glass. The bar must be TRANSLUCENT for this to mean anything:
   backdrop-filter blurs what sits behind an element, so over an opaque
   --bar the glass buttons inside would be blurring flat colour and would
   render as nothing. At 0.68 the hero photography refracts through the bar
   and the buttons have something real to sit on.

   Kept dark enough that nav text clears AA over the brightest frame in the
   reveal chain — verified, not assumed. */
.header {
  position: fixed;
  top: var(--frame);
  left: var(--frame);
  right: var(--frame);
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  gap: var(--s-5);
  padding: var(--s-4) clamp(var(--s-5), 3vw, var(--s-8));
  background: rgba(45, 65, 63, 0.68);
  -webkit-backdrop-filter: blur(22px) saturate(1.3);
  backdrop-filter: blur(22px) saturate(1.3);
  border-bottom: 1px solid rgba(244, 251, 250, 0.07);
  /* Square, not rounded: with --frame at 0 the header sits flush against
     the true viewport top-left/top-right. A rounded corner here would
     leave two small triangles of sage body colour showing through the
     arc — exactly the artefact this change exists to remove. */
  border-radius: 0;
  transition: background var(--dur-mid) var(--ease-out);
}

.header.is-stuck {
  background: rgba(45, 65, 63, 0.78);
  box-shadow: 0 10px 30px rgba(12, 24, 22, 0.28);
}

/* No blur support, or the reader has asked for less transparency: fall back
   to the solid bar rather than leaving text on bare photography. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .header,
  .header.is-stuck {
    background: var(--bar);
  }
}

@media (prefers-reduced-transparency: reduce) {
  .header,
  .header.is-stuck {
    background: var(--bar);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

.header__brand {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  width: clamp(96px, 11vw, 140px);
}

.header__brand svg {
  width: 100%;
  height: auto;
  color: var(--text);
}

/* Centred nav, sentence case, light — as in the reference. */
.header__nav {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: clamp(var(--s-4), 2.2vw, var(--s-6));
}

.header__dropdown {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.header__dropdown-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  background: rgba(244, 251, 250, 0.04);
  border: 1px solid transparent;
  color: var(--text-3);
  cursor: pointer;
  font-family: var(--font-ui);
  font-size: var(--t-small);
  font-weight: var(--w-body);
  letter-spacing: 0.01em;
  padding: var(--s-2) var(--s-4);
  border-radius: calc(var(--radius-card) * 0.55);
  transition: color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
}

.header__dropdown-toggle:hover,
.header__dropdown-toggle:focus-visible {
  color: var(--text);
  background: rgba(244, 251, 250, 0.1);
  border-color: rgba(244, 251, 250, 0.18);
}

.header__dropdown-toggle::after {
  content: "▾";
  display: inline-block;
  font-size: 0.7em;
  transform: translateY(-1px);
}

.header__dropdown-menu {
  position: absolute;
  top: calc(100% - 0.2rem);
  left: 50%;
  transform: translateX(-50%);
  min-width: 18rem;
  max-width: 22rem;
  width: min(22rem, calc(100vw - 4rem));
  padding: var(--s-3);
  display: none;
  flex-direction: column;
  align-items: center;
  gap: var(--s-2);
  background: rgba(18, 30, 28, 0.96);
  backdrop-filter: blur(22px) saturate(1.3);
  border: 1px solid rgba(244, 251, 250, 0.08);
  border-radius: calc(var(--radius-card) * 0.85);
  box-shadow: 0 36px 72px rgba(7, 18, 17, 0.24);
  z-index: var(--z-header);
  pointer-events: auto;
}

.header__dropdown.show .header__dropdown-menu,
.header__dropdown:focus-within .header__dropdown-menu,
.header__dropdown:hover .header__dropdown-menu {
  display: flex;
}

.header__dropdown-link,
.header__dropdown-toggle {
  color: var(--text-3);
}

.header__dropdown-link {
  position: relative;
  overflow: hidden;
  display: block;
  width: calc(100% - var(--s-4));
  margin: 0;
  padding: 0.65em 1.1em;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 0.9em;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--text-3);
  text-decoration: none;
  background: linear-gradient(
      170deg,
      rgba(244, 251, 250, 0.075) 0%,
      rgba(244, 251, 250, 0.02) 100%
    ),
    rgba(14, 27, 24, 0.52);
  border: 1px solid rgba(244, 251, 250, 0.12);
  border-radius: 8px;
  box-shadow: inset 0 1px 0 rgba(244, 251, 250, 0.15),
    inset 0 -1px 0 rgba(12, 24, 22, 0.12),
    0 4px 10px rgba(12, 24, 22, 0.18);
  transition: color var(--dur-mid) var(--ease-out),
    background var(--dur-mid) var(--ease-out),
    border-color var(--dur-mid) var(--ease-out),
    box-shadow var(--dur-mid) var(--ease-out),
    border-radius var(--dur-slow) var(--ease-out),
    transform var(--dur-mid) var(--ease-out);
}

.header__dropdown-link::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(
    105deg,
    rgba(244, 251, 250, 0) 30%,
    rgba(244, 251, 250, 0.18) 50%,
    rgba(244, 251, 250, 0) 70%
  );
  transform: translateX(-135%);
  opacity: 0;
  transition: transform 1000ms var(--ease-inout), opacity 180ms linear;
}

.header__dropdown-link:hover,
.header__dropdown-link:focus-visible,
.header__dropdown-toggle:hover,
.header__dropdown-toggle:focus-visible {
  color: var(--text);
}

.header__dropdown-link:hover,
.header__dropdown-link:focus-visible {
  background: linear-gradient(
      170deg,
      rgba(244, 251, 250, 0.145) 0%,
      rgba(244, 251, 250, 0.05) 100%
    ),
    rgba(14, 27, 24, 0.6);
  border-color: rgba(244, 251, 250, 0.24);
  box-shadow: inset 0 1px 0 rgba(244, 251, 250, 0.34),
    inset 0 -1px 0 rgba(12, 24, 22, 0.2),
    0 8px 20px rgba(12, 24, 22, 0.26);
  transform: translateY(-1px);
}

.header__dropdown-link:hover::before,
.header__dropdown-link:focus-visible::before {
  transform: translateX(135%);
  opacity: 1;
}

.header__dropdown-link:hover,
.header__dropdown-link:focus-visible {
  background: rgba(244, 251, 250, 0.04);
}

.header__link {
  position: relative;
  font-family: var(--font-ui);
  font-size: var(--t-small);
  font-weight: var(--w-body);
  letter-spacing: 0.01em;
  color: var(--text-3);
  padding-block: var(--s-2);
  transition: color var(--dur-fast) var(--ease-out);
}

.header__link::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 2px;
  width: 100%;
  height: 1px;
  background: var(--text-2);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-mid) var(--ease-out);
}

.header__link:hover,
.header__link.is-current {
  color: var(--text);
}

.header__link:hover::after,
.header__link.is-current::after {
  transform: scaleX(1);
}

.header__actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex: 0 0 auto;
  margin-left: auto;
}

/* ------------------------------------------------------------- sections --
   Each is a card. Gradient runs light at the top to dark at the bottom,
   matching the reference's soft atmospheric fall-off.                     */

/* Content cards run DEEPER than the hero — as in the reference, where the
   hero is the lightest surface on the page and everything below settles.

   This is also what makes the muted label colours legible: --text-4 clears
   4.5:1 on --card-deep-top but not on the lighter hero tone, so no small
   muted text is ever placed on the hero. */
.section {
  position: relative;
  z-index: var(--z-content);
  margin-bottom: var(--card-gap);
  padding-block: var(--section-y);
  padding-inline: var(--page-pad);
  border-radius: var(--radius-card);
  background: linear-gradient(
    170deg,
    var(--card-deep-top) 0%,
    var(--card-deep-bot) 100%
  );
  overflow: hidden;
}

.section__inner {
  max-width: var(--page-max);
  margin-inline: auto;
}

.section__head {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  margin-bottom: var(--s-8);
  max-width: 46ch;
}

/* The gaps between cards do the dividing now. */
.section__rule {
  display: none;
}

/* ----------------------------------------------------------------- hero -- */

/* --- hero as a scroll track -----------------------------------------
   .hero is an invisible track with no styling of its own. All the card
   treatment lives on .hero__stage, which sticks to the viewport while the
   track scrolls past. --hero-track sets how much scroll the reveal gets.

   The radius and gradient must sit on the STAGE, not the track: on the
   track they would render at the top and bottom of a 190vh block, so the
   rounded bottom corner would never be on screen.                       */

/* --hero-stages must match the number of [data-hero-layer] elements in
   index.html. One viewport to read the resting state, then --hero-step of
   scroll per reveal.

   The step has tightened as the chain has grown — 95svh at two stages,
   72svh at three, now 60svh at four. Left at 95svh, five states would run
   to nearly five screens before the page proper began, which is far too
   long a walk to the enquiry form on a site whose whole job is collecting
   enquiries. At 60svh the whole sequence is ~3.4 screens and each reveal
   still gets most of a viewport to land.

   This is the dial to turn if the hero starts feeling long. */
.hero {
  --hero-stages: 4;
  --hero-step: 60svh;
  --hero-track: calc(100svh + var(--hero-stages) * var(--hero-step));
  position: relative;
  z-index: var(--z-content);
  height: var(--hero-track);
  margin-bottom: var(--card-gap);
}

.hero__stage {
  position: sticky;
  top: var(--frame);
  height: calc(100svh - var(--frame) * 2);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: clamp(6rem, 12vh, 9rem) var(--page-pad) clamp(3rem, 8vh, 6rem);
  border-radius: var(--radius-card);
  background: linear-gradient(168deg, var(--card-top) 0%, var(--card-bot) 100%);
  overflow: hidden;
}

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

/* Title and caption occupy the SAME grid cell so one can cross-fade into
   the other in place. The CTA sits in the row beneath and never moves. */
.hero__inner {
  position: relative;
  z-index: var(--z-content);
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  align-items: center;
  row-gap: clamp(var(--s-7), 6vh, var(--s-9));
}

.hero__title,
.hero__caption {
  grid-column: 1;
  grid-row: 1;
}

.hero__cta {
  grid-column: 1;
  grid-row: 2;
}

.hero__caption {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-4);
  max-width: 26ch;
}

/* Local pool of shade under the caption. The global hero scrim is tuned
   for the cloth; the garment carries a bright shoulder highlight exactly
   where this text lands, which dragged the eyebrow to 4.47:1.

   Fading the whole caption (--hero-in) carries this with it, so the shade
   only exists while there is text to protect. */
.hero__caption::before {
  content: "";
  position: absolute;
  inset: -60% -45%;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(
    ellipse at center,
    rgba(22, 43, 38, 0.66) 0%,
    rgba(22, 43, 38, 0.4) 48%,
    rgba(22, 43, 38, 0) 74%
  );
}

.hero__caption > * {
  position: relative;
  z-index: 1;
}

/* --text-4 is scaled for the deep card gradient. Over a photograph it
   measured 3.15:1 against the garment's shoulder highlight — a real AA
   failure. Photographs are lighter and far more variable than any flat
   surface, so the same rule that keeps muted text off --card-top applies
   with more force here: over imagery, nothing dimmer than --text-2. */
.hero__caption .u-eyebrow {
  color: var(--text-2);
}

.hero__eyebrow {
  margin-bottom: var(--s-6);
}

.hero__title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(var(--s-4), 2.2vh, var(--s-6));
  width: 100%;
}

.hero__lead {
  margin-bottom: var(--s-7);
  max-width: 48ch;
  text-align: center;
}

.hero__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-4);
}

/* Small factual note pinned to the bottom-left of the hero card, with a
   thin left rule — straight from the reference. */
.hero__note {
  position: absolute;
  left: clamp(var(--s-5), 4vw, var(--s-8));
  bottom: clamp(var(--s-5), 5vh, var(--s-8));
  z-index: var(--z-content);
  max-width: 34ch;
  padding-left: var(--s-4);
  border-left: 1px solid var(--hairline-strong);
  text-align: left;
  font-size: var(--t-small);
  line-height: 1.75;
  /* --text-2 rather than --text-3: the hero is the lightest card on the
     page, so body-dim would drop under 4.5:1 near the top of the gradient. */
  color: var(--text-2);
}

/* --- video hero variant -----------------------------------------------
   Used by about.html and range.html: the same sticky scroll-track as the
   homepage hero (.hero / .hero__stage, driven by js/hero-reveal.js), but
   with a looping video as the base layer instead of the cloth photograph,
   and normally just one [data-hero-layer] reveal stage rather than four
   (set per instance via inline style="--hero-stages:1").

   The homepage hero deliberately runs full-bleed UNDER the fixed header —
   that is what makes the header read as "a bar across the top of the
   card". These two video heroes crop a specific product shot rather than
   an abstract cloth texture, so having the header's ~80px sit permanently
   over the top of the frame hid a meaningful part of the video and made a
   short card crop hard on the subject. Both flaws share one fix: start
   the whole track below the header, and keep the sticky stage pinned
   there (not at true viewport top) while it scrolls — the video then
   gets the entire hero card to fill, header included in the reckoning
   rather than stolen from it. */
.hero--video {
  margin-top: var(--header-h);
}

.hero--video .hero__stage {
  top: var(--header-h);
  height: calc(100svh - var(--header-h) - var(--frame) * 2);
}

@media (prefers-reduced-motion: reduce) {
  .hero--video .hero__stage {
    min-height: calc(100svh - var(--header-h));
  }
}

/* ---------------------------------------------------------------- about -- */

.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(var(--s-7), 6vw, var(--s-10));
  align-items: start;
}

.about__story {
  position: relative;
}

/* Photograph sits behind the story text as a quiet textured backdrop, not
   a framed photo — inset:0 on .about__story so it never shifts the text
   layout. z-index:-1 (not 0) so it paints in the stacking step BEFORE
   .about__story's in-flow text children regardless of DOM order. */
.about__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  border-radius: var(--radius-card);
}

.about__bgimg {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.2) contrast(1.05) saturate(1.05);
}

.about__bgimg[hidden] {
  display: none;
}

/* Same gradient family as .card-deep, so the photo reads as the section's
   own dark surface catching a little texture rather than a separate image
   dropped on top of it — text needs to stay comfortably above 4.5:1. */
.about__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgba(22, 43, 38, 0.94) 0%,
    rgba(22, 43, 38, 0.88) 45%,
    rgba(22, 43, 38, 0.72) 100%
  );
}

.about__story p + p {
  margin-top: var(--s-5);
}

.about__side {
  display: flex;
  flex-direction: column;
}

.about__values {
  display: flex;
  flex-direction: column;
  border-top: 1px solid var(--hairline);
}

.about__figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s-5);
  margin-top: var(--s-9);
  padding-top: var(--s-7);
  border-top: 1px solid var(--hairline);
}

/* ------------------------------------------------------------- products -- */

.products {
  position: relative;
}

.products__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--card-gap);
}

.custom {
  margin-top: var(--s-9);
  padding-top: var(--s-7);
  border-top: 1px solid var(--hairline);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: clamp(var(--s-6), 5vw, var(--s-9));
  align-items: start;
}

.custom__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-3) var(--s-6);
}

.custom__item {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  padding-block: var(--s-2);
  color: var(--text-3);
  font-size: var(--t-small);
}

.custom__item::before {
  content: "";
  flex: 0 0 auto;
  width: 14px;
  height: 1px;
  background: var(--text-4);
  transform: translateY(-4px);
}

/* -------------------------------------------------------------- contact -- */

.contact__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  gap: clamp(var(--s-7), 6vw, var(--s-10));
  align-items: start;
}

.contact__detail + .contact__detail {
  margin-top: var(--s-6);
}

.contact__label {
  display: block;
  margin-bottom: var(--s-2);
}

.contact__value {
  color: var(--text-2);
  font-size: var(--t-small);
  line-height: 1.8;
}

.contact__value a:hover {
  color: var(--text);
}

/* --------------------------------------------------------------- footer -- */

.footer {
  position: relative;
  z-index: var(--z-content);
  /* Top stays rounded — it borders a --card-gap sage gap, same as every
     other card, so the curve blends in and is invisible. Bottom is square:
     it touches the true page edge where --frame is 0, and rounding it
     leaked real sage at (0,899) and (1439,899) — confirmed by direct pixel
     sample, same defect the header had at the top. */
  border-radius: var(--radius-card) var(--radius-card) 0 0;
  background: linear-gradient(
    170deg,
    var(--card-deep-top) 0%,
    var(--card-deep-bot) 100%
  );
  padding: var(--s-8) var(--page-pad) var(--s-6);
}

.footer__inner {
  max-width: var(--page-max);
  margin-inline: auto;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-6);
  align-items: flex-start;
  justify-content: space-between;
}

.footer__brand svg {
  width: 140px;
  height: auto;
  color: var(--text-2);
}

.footer__tagline {
  margin-top: var(--s-4);
}

.footer__cols {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-8);
}

.footer__col {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
}

.footer__col a:hover {
  color: var(--text);
}

/* Closing bookend to the hero's opening flourish — the one .reveal-rule
   on the page, drawing in slowly (var(--dur-draw)) while the columns
   above it have already settled. Supplies the top gap+line .footer__base
   used to carry itself via border-top. */
.footer__rule {
  max-width: var(--page-max);
  margin: var(--s-8) auto 0;
  height: 1px;
  background: var(--hairline);
}

.footer__base {
  max-width: var(--page-max);
  margin: var(--s-5) auto 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-6);
  justify-content: space-between;
}

/* --------------------------------------------------------- placeholder --
   Visible marker so invented company data cannot reach production
   unnoticed. Remove once the real values are in.                          */

.is-placeholder {
  border-bottom: 1px dashed rgba(244, 251, 250, 0.4);
}

/* ---------------------------------------------------------- breakpoints -- */

@media (max-width: 1100px) {
  .products__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 960px) {
  /* Centred absolute nav starts colliding with the logo and actions. */
  .header__nav {
    display: none;
  }
}

@media (max-width: 900px) {
  .about__grid,
  .contact__grid,
  .custom {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 700px) {
  .products__grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .hero__note {
    position: static;
    margin-top: var(--s-8);
    max-width: none;
  }
}

@media (max-width: 620px) {
  /* The quote CTA overflowed the bar on small screens. The enquiry button
     stays — it is the one that carries state — and the hero CTA is only a
     scroll away.

     Scoped to .header deliberately: components.css loads after this file,
     so a bare `.header__cta` tie is lost to `.btn { display:inline-flex }`. */
  .header .header__cta {
    display: none;
  }
}

@media (max-width: 560px) {
  .footer__inner {
    flex-direction: column;
  }

  .footer__cols {
    gap: var(--s-6);
  }
}
