/* TING opening sequence — 1:1 vanilla port of the original Next.js hero.
   Sources of truth: components/home/Hero.tsx, hero-timeline.ts, globals.css,
   scenes/SequenceField.tsx, scenes/WeaveField.tsx, brand/*.
   Six acts scrubbed by damped scroll over a 520svh stage; grounds cut at
   0.19 / 0.76 / 0.945. Grounds use the site's carbon black (#0a0a0b) per
   the brand's later direction; every timing and layout number matches the
   reference implementation. */

/* ---------- stage + pane (JS-driven pinning; CSS sticky unreliable here) --- */

.ting-stage {
  height: 640svh; /* +120svh: scroll room for the logo fill sequence */
  position: relative;
  z-index: 1; /* under the fixed header (z 50) */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: 0 !important;
}

.ting-stage__pane {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
  /* With no JS the sequence resolves to its final, readable state. */
  --progress: 1;
}

/* With JS the timeline starts at its beginning (his `scripting: enabled`
   block). The hook's inline write takes over from the first frame. */
@media (scripting: enabled) {
  .ting-stage__pane {
    --progress: 0;
  }
}

.ting-stage__pane.is-pinned { position: fixed; }
.ting-stage__pane.is-past { top: auto; bottom: 0; }

/* ---------- the window system (his globals.css .stage block) -------------- */

.stage {
  --from: 0;
  --span: 0.1;
  --t: clamp(0, calc((var(--progress, 1) - var(--from)) / var(--span)), 1);
}

.stage-in { opacity: var(--t); }
.stage-out { opacity: calc(1 - var(--t)); }

.stage-rise {
  transform: translate3d(0, calc((1 - var(--t)) * var(--rise, 32px)), 0);
}

.stage-travel {
  --travel-x: 0px;
  --travel-y: 0px;
  transform: translate(-50%, -50%)
    translate(calc(var(--t) * var(--travel-x)), calc(var(--t) * var(--travel-y)));
  will-change: transform;
}

.stage-grow {
  --scale-from: 1;
  --scale-to: 1;
  --tile-scale: calc(
    var(--scale-from) + (var(--scale-to) - var(--scale-from)) * var(--t)
  );
  transform: scale(var(--tile-scale));
  will-change: transform;
}

/* ---------- grounds: base light + one layer per cut, fading in and staying */

.ting-ground {
  position: absolute;
  inset: 0;
}

.ting-ground--light { background: #ffffff; }
.ting-ground--dark  { background: #0a0a0b; }

/* ---------- canvases ------------------------------------------------------ */

.ting-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

/* ---------- grain (his .grain dither tile) -------------------------------- */

.ting-grain {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 140px 140px;
}

/* ---------- type voices (his @utility set) -------------------------------- */

.t-label {
  font-family: "Zen Dots", ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
}

.t-annotation {
  font-family: "Zen Dots", "Helvetica Neue", -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Arial, sans-serif;
  font-style: italic;
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  line-height: 1.5;
  white-space: nowrap;
}

.t-serif {
  font-family: "Zen Dots", Didot, "Playfair Display", "Times New Roman", Times, serif;
  font-weight: 400;
  letter-spacing: 0.005em;
}

.t-wordmark {
  font-family: "Zen Dots", "Haettenschweiler", "Arial Narrow", "Helvetica Neue", Impact, sans-serif;
  font-stretch: 75%;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 0.8;
  /* brand casing is "EXting" — no transform, the markup carries the case */
}

/* ---------- container (his Container: max-w 1440, px 6/10) ---------------- */

.t-container {
  margin-inline: auto;
  width: 100%;
  max-width: 1440px;
  padding-inline: 1.5rem;
}

@media (min-width: 768px) {
  .t-container { padding-inline: 2.5rem; }
}

/* ---------- act 1: the specimen tile --------------------------------------
   Outer: leaves 0.20–0.28. Middle: travels 0.07–0.18. Inner: grows 0–0.07.
   Ink = near-black on the bone sheet (his text-bg). */

.t-specimen {
  position: absolute;
  left: 34%;
  top: 51%;
  color: #0a0a0b;
}

.t-tile {
  position: relative;
  width: 34svh;
  height: 34svh;
}

/* Blow-through plate: the box's four corners walk outward — a dark ground
   grows from the tile's bounds to past the viewport while everything inside
   (mark, labels, texture) keeps its size on top of it. */
.t-tile__plate {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: calc(100% + var(--t) * 160vmax);
  height: calc(100% + var(--t) * 160vmax);
  background: #0a0a0b;
}

/* MarkTile: near-black square, twill weave, raking sheen, label cloud, mark */
.t-tile__box {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #0a0a0b;
}

/* Carbon photo ground, framed like the Figma crop (wider than the tile). */
.t-tile__photo {
  position: absolute;
  top: 0;
  left: -16.4%;
  width: 186%;
  height: 124%;
  max-width: none;
  object-fit: cover;
}

/* Outline echo of the mark. At rest (.is-masked) the tile's middle column
   swallows it, per Figma; during the intro draw the line runs unbroken.
   The gap's alpha is a registered property so the cut can dissolve in
   rather than snap (falls back to an instant cut where unsupported). */
@property --echo-gap {
  syntax: "<color>";
  inherits: false;
  initial-value: #fff;
}

.t-tile__echo-wrap {
  position: absolute;
  inset: 0;
  --echo-gap: #fff;
  -webkit-mask-image: linear-gradient(90deg, #fff 0 33.4%, var(--echo-gap) 33.4% 66.6%, #fff 66.6%);
  mask-image: linear-gradient(90deg, #fff 0 33.4%, var(--echo-gap) 33.4% 66.6%, #fff 66.6%);
  transition: --echo-gap 1.4s ease;
}

.t-tile__echo-wrap.is-masked {
  --echo-gap: transparent;
}

.t-tile__echo {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 75%;
  height: auto;
  filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.7));
  transition: filter 1.8s ease;
}

/* Intro: the echo draws itself (stroke-dashoffset via hero.js) under a hot
   halo; the solid mark holds back until the line has closed, then breathes
   in — long fade, faint unfurl from 97%. */
.t-tile.is-intro .t-tile__echo {
  filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.95)) drop-shadow(0 0 18px rgba(255, 255, 255, 0.55));
}

.t-tile.is-intro .t-tile__mark {
  opacity: 0;
  transform: scale(0.97);
}

/* Sits outside the clipped box. At rest the clip hugs the tile edge exactly
   (Figma's deliberate cut-offs); during the blow-through the clip walks
   outward with the plate, releasing the labels from the four edges. */
.t-cloud.t-tile__cloud {
  opacity: 0.85;
  overflow: visible;
  clip-path: inset(calc(var(--t, 0) * -80vmax));
}

.t-tile__cloud span {
  color: #fff;
  text-transform: capitalize;
  text-shadow: 2.5px 0 1.7px rgba(255, 255, 255, 0.5), 0.85px 0 1.7px rgba(255, 255, 255, 0.75);
}

.t-tile__grid {
  color: #9c9c9c;
  opacity: 0.6;
}

/* Staged out during the blow-through — compose with the base 0.6 alpha
   (.t-tile__grid would otherwise out-cascade .stage-out's opacity). */
.t-tile__grid.stage-out {
  opacity: calc(0.6 * (1 - var(--t)));
}

.t-tile__mark {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 68.5%;
  height: auto;
  filter: drop-shadow(0 0 12px rgba(255, 255, 255, 0.3));
  /* Ease-out: the fill is visible the moment it starts, then settles softly. */
  transition: opacity 1.8s cubic-bezier(0.22, 0.61, 0.36, 1), transform 1.8s cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* Layout rules flush to the tile's four edges; hairline at every scale. */
.t-rule-v,
.t-rule-h {
  position: absolute;
  background: currentColor;
  opacity: 0.13;
  pointer-events: none;
}

/* When staged out (pre-zoom), compose the fade with the base 0.13 alpha —
   .t-rule-* would otherwise out-cascade .stage-out's opacity. */
.t-rule-v.stage-out,
.t-rule-h.stage-out {
  opacity: calc(0.13 * (1 - var(--t)));
}

.t-rule-v {
  top: -400vh;
  height: 900vh;
  width: calc(1px / var(--tile-scale, 1));
}

.t-rule-h {
  left: -400vw;
  width: 900vw;
  height: calc(1px / var(--tile-scale, 1));
}

.t-rule-v.at-start { left: 0; }
.t-rule-v.at-end { left: 100%; }
.t-rule-h.at-start { top: 0; }
.t-rule-h.at-end { top: 100%; }

/* Caption hung off the tile's lower right; type size holds while it grows. */
.t-caption {
  position: absolute;
  left: 120%;
  top: 62%;
  /* font-size lives here so the width tracks the quote's own type; 22em
     breaks after "beauty," and "fabric" — three lines. (em, not ch: Zen
     Dots' "0" is ~1.03em, far wider than its average glyph, so ch misleads) */
  font-size: 1.125rem;
  width: 22em;
  transform: scale(calc(1 / var(--tile-scale, 1)));
  transform-origin: left top;
}

.t-caption p {
  margin: 0;
  line-height: 1.45;
}

@media (min-width: 768px) {
  .t-caption { font-size: 1.25rem; }
}

@media (max-width: 47.9375rem) {
  /* phone: the tile takes the centre of the frame (34% leaves a dead right
     third at this width) and the caption drops below it, left-aligned */
  .t-specimen { left: 50%; }

  /* act 1's sideways drift is a desktop gesture — 16vw pushes the tile
     off-centre on a phone, so it holds the middle (!important outguns the
     template's inline --travel-x) */
  .t-specimen .stage-travel { --travel-x: 0px !important; }

  /* the solo mark grows toward the letter formation before dissolving into
     it; the formation is 66vmin ≈ 66vw here, not the desktop 66vh — 2.85×
     would blow past the screen, ~1.45× meets it (and, with the travel gone,
     concentric with it) */
  .t-tile .stage-grow { --scale-to: 1.45 !important; }

  .t-caption {
    left: 0;
    top: 116%;
    /* hangs off the tile's left edge, which sits ~(50vw - 17svh) in, and the
       act-1 travel pushes it another 16vw right — 58vw survives all of it */
    width: min(22em, 58vw);
    font-size: 1rem;
  }
}

/* ---------- acts 2–4 (the dark frames) ------------------------------------ */

.t-acts {
  position: absolute;
  inset: 0;
}

.t-acts__copy {
  position: relative;
  display: flex;
  height: 100%;
  flex-direction: column;
  justify-content: space-between;
  padding-block: 6rem;
}

@media (min-width: 768px) {
  .t-acts__copy { padding-block: 7rem; }
}

.t-acts .t-annotation { color: #f2f0ec; }

.t-acts h1.t-wordmark {
  margin: 0;
  color: #f2f0ec;
  font-size: clamp(6rem, 26vw, 22rem);
}

.t-acts__claim { margin-top: 1.5rem; }

/* Product slot, right of centre, desktop only (his lg:block) */
.t-slot {
  position: absolute;
  right: 6%;
  top: 50%;
  height: 46%;
  width: 22%;
  display: none;
}

@media (min-width: 1024px) {
  .t-slot { display: block; }
}

/* stage-rise composes with the slot's own centering translate */
.t-slot.stage-rise {
  transform: translateY(-50%)
    translate3d(0, calc((1 - var(--t)) * var(--rise, 32px)), 0);
}

.t-slot__ph {
  height: 100%;
  width: 100%;
  background: rgba(82, 82, 90, 0.6);
}

/* Construction act */
.t-construction,
.t-construction__inner {
  position: absolute;
  inset: 0;
}

.t-grid-main {
  position: absolute;
  left: 50%;
  top: 50%;
  height: 42svh;
  width: 42svh;
  transform: translate(-50%, -50%);
  color: rgba(242, 240, 236, 0.25);
}

.t-grid-detail {
  position: absolute;
  left: 34%;
  top: 24%;
  height: 11svh;
  width: 11svh;
  color: rgba(242, 240, 236, 0.2);
}

/* Annotation cloud (fixed table, JS-populated) */
.t-cloud {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.t-cloud span {
  position: absolute;
  color: #f2f0ec;
  opacity: var(--o, 1);
  animation: t-cloud-drift 10s ease-in-out infinite;
}

/* Labels wander + breathe; per-span phase comes from JS (random duration
   + negative delay), so the cloud never moves in lockstep. */
@keyframes t-cloud-drift {
  0%, 100% {
    translate: 0 0;
    opacity: calc(var(--o, 1) * 0.35);
  }
  25% {
    translate: var(--dx, 8px) calc(var(--dy, -6px) * -0.6);
  }
  50% {
    translate: calc(var(--dx, 8px) * -0.7) var(--dy, -6px);
    opacity: var(--o, 1);
  }
  75% {
    translate: calc(var(--dx, 8px) * 0.4) calc(var(--dy, -6px) * 0.8);
  }
}

@media (prefers-reduced-motion: reduce) {
  .t-cloud span {
    animation: none;
  }
}

/* ---------- act 6: at rest, on the grid ------------------------------------ */

.t-rest {
  position: absolute;
  inset: 0;
}

.t-rest__grid {
  position: absolute;
  left: 54%;
  top: 50%;
  height: 26svh;
  width: 26svh;
  transform: translateY(-50%);
  color: rgba(242, 240, 236, 0.3);
}

/* ---------- scroll affordance ---------------------------------------------- */

.t-hint {
  position: absolute;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  color: #0a0a0b;
}

.t-hint .t-label { opacity: 0.5; }

/* ---------- logo fill sequence: interior artwork swaps inside the
   letter-formed outline (transparent PNGs, sized to the canvas formation:
   width 0.66 × short side, mark aspect 263:203, centred) ------------------- */

.t-fills {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: 66vmin;
  aspect-ratio: 263 / 203;
  pointer-events: none;
}

.t-fill {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* on the bone sheet the weave keeps its natural depth; just a touch of
   contrast so the twill reads at distance */
.t-fill--carbon {
  filter: contrast(1.08);
}

/* ---------- construction grid svg ------------------------------------------ */

.t-cgrid {
  position: absolute;
  inset: 0;
  height: 100%;
  width: 100%;
}

/* ---------- header follows the ground tone (fixed bar inverts) -------------
   Ink only — the veil/border belong to .is-scrolled in style.css. */

html[data-tone="light"] .ting-header .wp-block-site-title a,
html[data-tone="light"] .ting-header .wp-block-navigation a,
html[data-tone="light"] .ting-header .wp-block-navigation__responsive-container-open,
html[data-tone="light"] .ting-header .wc-block-mini-cart__button {
  color: #0a0a0b !important;
}

html[data-tone="light"] .ting-header .ting-header__icons a { color: #0a0a0b; }

/* ---------- reduced motion: the composition at rest, not a shorter scrub --- */

.t-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .ting-stage { height: auto; }
  .ting-stage__pane { display: none; }

  .t-still {
    display: flex;
    min-height: 100svh;
    flex-direction: column;
    justify-content: space-between;
    overflow: hidden;
    background: #0a0a0b;
    padding-block: 7rem;
  }

  .t-still .t-annotation { color: #f2f0ec; }

  .t-still h1.t-wordmark {
    margin: 0;
    color: #f2f0ec;
    font-size: clamp(5rem, 20vw, 16rem);
  }

  .t-still__row {
    display: flex;
    flex-direction: column;
    gap: 3rem;
  }

  .t-still__gridbox {
    position: relative;
    height: 30svh;
    width: 30svh;
    flex-shrink: 0;
    color: rgba(242, 240, 236, 0.3);
  }

  .t-still__gridbox .t-still__mark {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 66%;
    height: auto;
  }

  .t-still__quote {
    margin-top: 3.5rem;
    max-width: 22em;
    font-size: 1.125rem;
    line-height: 1.45;
    color: #c9c7c1;
  }
}

@media (prefers-reduced-motion: reduce) and (min-width: 1024px) {
  .t-still__row {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
  }
}
