/* HOWL
   Rhythmic cutlist. Sixteen short cuts, nothing pinned, nothing held in the act
   stack. The one thing that holds is the table band, which is fixed chrome and
   outlives the cut it starts in.

   Colour architecture: the saturation lives in the GROUND and the accent is a
   light. Every ground is opaque and every change lands on a hard edge, because
   a cut is not an interpolation. Two accent stops, one amber hue, keyed to the
   ground family, because a page that hard-cuts between light and dark grounds
   cannot clear 4.5:1 on both with one stop. */

:root {
  /* dark family is the page at rest */
  --sc-canvas:      #B0210A;
  --sc-surface:     #41202B;
  --sc-ink:         #FFF3E4;
  --sc-ink-soft:    #F6C9A4;
  --sc-accent:      #FFDE3D;
  --sc-accent-ink:  #2A0F1E;

  --sc-font-display: "Big Shoulders Display", "Archivo Black", system-ui, sans-serif;
  --sc-font-text:    "Space Grotesk", system-ui, -apple-system, sans-serif;
  --sc-font-mono:    "Space Grotesk", system-ui, sans-serif;

  --sc-shadow-color: 10 70% 6%;
  --sc-r-sm: 2px; --sc-r-md: 4px; --sc-r-lg: 6px; --sc-r-pill: 999px;

  /* the grounds */
  --g-ember:    #B0210A;
  --g-ember-hot:#C6250A;
  --g-charred:  #41202B;
  --g-orange:   #E1560F;
  --g-amber:    #E9971A;
  --g-yellow:   #F2E409;
  --g-violet:   #2A1A55;

  /* the band */
  --bar-h: 3.25rem;
  --peek: 8.5svh;
  --k: 0;      /* convergence, 0 wide to 1 closed */
  --open: 0;   /* the peak unfurl, 0 parked to 1 full viewport */
}

/* Ground families. Restating `color` alongside the token is not optional: a
   colour already resolved on <body> is inherited as a computed value, so a
   subtree that only redefines --sc-ink renders in the body's ink. */
.g-ember     { --sc-canvas: var(--g-ember); }
.g-ember-hot { --sc-canvas: var(--g-ember-hot); }
.g-charred   { --sc-canvas: var(--g-charred); }
.g-violet    { --sc-canvas: var(--g-violet); }
.g-ember, .g-ember-hot, .g-charred, .g-violet {
  --sc-ink: #FFF3E4; --sc-ink-soft: #F6C9A4; --sc-accent: #FFDE3D; --sc-accent-ink: #2A0F1E;
  color: var(--sc-ink);
}
.g-orange { --sc-canvas: var(--g-orange); }
.g-amber  { --sc-canvas: var(--g-amber); }
.g-yellow { --sc-canvas: var(--g-yellow); }
.g-orange, .g-amber, .g-yellow {
  /* Secondary ink is tinted from the ink hue rather than lightened toward the
     ground. On chilli orange a genuinely soft value measures 3.1:1, which is
     fine for a large heading and fails body text: the ferment captions and the
     bottle lines are both body. Every value soft enough to read as secondary
     lands under the floor here, so on these three grounds the secondary role is
     carried by size, weight and letter spacing and the value stays at the ink.
     The dark grounds keep a real second value. */
  --sc-ink: #2A0F1E; --sc-ink-soft: #2A0F1E; --sc-accent: #2E0E00; --sc-accent-ink: #F2E409;
  color: var(--sc-ink);
}

html, body { background: var(--g-ember); }
body { font-weight: 400; }
.sc-display { font-weight: 800; letter-spacing: -0.01em; text-transform: uppercase; }
.sc-label { font-weight: 700; }

/* Condensed display carries a lot of words per line, so the ramp runs hotter
   than the floor's and the biggest step is reserved for two moments. */
.howl-xxl { font-size: clamp(3.4rem, 13.5vw, 12rem); line-height: 0.86; }
.howl-xl  { font-size: clamp(2.6rem, 8.5vw, 7.5rem);  line-height: 0.9; }

/* ------------------------------------------------------------------ bar --
   The grammar asks for loud chrome, not a minimal one. Full width, high
   contrast, the action at the same weight as the wordmark. */
.bar {
  position: fixed; inset: 0 0 auto 0; z-index: 70;
  height: var(--bar-h);
  display: flex; align-items: center; gap: var(--sc-4);
  padding-inline: clamp(0.75rem, 3vw, 2rem);
  background: #2A0F1E;
  color: #FFF3E4;
  border-bottom: 2px solid var(--g-yellow);
}
.bar__mark {
  font-family: var(--sc-font-display); font-weight: 800; text-transform: uppercase;
  font-size: clamp(1.4rem, 3vw, 2rem); line-height: 1; letter-spacing: 0.02em;
  color: var(--g-yellow); text-decoration: none;
}
.bar__cat {
  margin: 0; font-size: var(--sc-t-xs); letter-spacing: 0.14em; text-transform: uppercase;
  color: #F6C9A4;
}
.bar__cta {
  margin-left: auto;
  font-family: var(--sc-font-display); font-weight: 800; text-transform: uppercase;
  font-size: clamp(1.05rem, 2.2vw, 1.5rem); line-height: 1; letter-spacing: 0.02em;
  color: #2A0F1E; background: var(--g-yellow);
  padding: 0.55rem 0.9rem; border-radius: var(--sc-r-sm); text-decoration: none;
  white-space: nowrap;
  transition: background var(--sc-d-fast) var(--sc-ease-out), color var(--sc-d-fast) var(--sc-ease-out);
}
.bar__cta:hover { background: #FFF3E4; }
.bar__cta:active { transform: translateY(1px); }
@media (max-width: 640px) { .bar__cat { display: none; } }

/* ----------------------------------------------------------------- cuts -- */
.cut {
  position: relative;
  min-height: calc(var(--h, 1) * 100svh);
  background: var(--sc-canvas);
  display: flex; flex-direction: column; justify-content: center;
  padding-top: calc(var(--bar-h) + var(--sc-5));
  padding-bottom: calc(var(--peek) + var(--sc-5));
}
.cut__in { width: 100%; max-width: var(--sc-maxw); margin-inline: auto; padding-inline: var(--sc-gutter); }
.cut__in--wide { max-width: 92rem; }
.kicker {
  margin: 0 0 var(--sc-4); font-size: var(--sc-t-sm); font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--sc-accent);
}

/* A media cut is edge to edge. Text never is. */
.cut--media { padding: 0; }
.frame { position: relative; flex: 1 1 auto; min-height: inherit; overflow: clip; }
.frame__fill, .frame__poster, .frame__clip {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.frame__clip { opacity: 0; transition: opacity 320ms var(--sc-ease-out); }
.frame.is-playing .frame__clip { opacity: 1; }
.frame.is-playing .frame__poster { opacity: 0; }
.frame__poster { transition: opacity 320ms var(--sc-ease-out); }
.frame .sc-copy { bottom: calc(var(--peek) + var(--sc-5)); }
.frame .sc-scrim { z-index: 1; }
/* The floor's band is dense across the bottom 22% of the frame. HOWL's copy
   sits from roughly 18% to 40% of the frame height, above the table band, so
   the density has to reach further up or the line is graded against raw plate.
   Measured, not tuned by eye: the harness reports the worst frame under each
   line and these stops are what cleared it. */
.frame .sc-scrim--band {
  background: linear-gradient(to top,
    color-mix(in oklab, var(--scrim-mix, var(--sc-canvas)) 98%, transparent) 0%,
    color-mix(in oklab, var(--scrim-mix, var(--sc-canvas)) 96%, transparent) 36%,
    color-mix(in oklab, var(--scrim-mix, var(--sc-canvas)) 58%, transparent) 52%,
    transparent 68%);
}
/* A light ground mixes its scrim out of its own canvas, which lays a slab of
   amber across the bottom half of the frame. That is invisible against a colour
   field and it throws away half of a photograph. Two full bleed cuts sit on
   light grounds, so their copy goes light and their scrim goes dark: the ground
   still owns the section, and the photograph keeps its contrast. */
.cut--darkcopy {
  --sc-ink: #FFF3E4; --sc-ink-soft: #F6C9A4;
  --sc-accent: #FFDE3D; --sc-accent-ink: #2A0F1E;
  --scrim-mix: #2A0F0A;
  color: var(--sc-ink);
}

/* three vessels, one row, hard cut, no card */
.trio { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sc-4); margin-top: var(--sc-5); }
.trio figure { margin: 0; }
.trio img { width: 100%; height: clamp(9rem, 31svh, 19rem); object-fit: cover; border-radius: var(--sc-r-sm); }
.trio figcaption {
  margin-top: var(--sc-2); font-size: var(--sc-t-xs); font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--sc-ink-soft);
}

/* the printed batch seal */
.seal {
  display: inline-block; padding: var(--sc-4) var(--sc-5);
  border: 3px solid var(--sc-accent); border-radius: var(--sc-r-sm);
  rotate: -2.4deg; background: transparent;
}
.seal__top, .seal__foot {
  margin: 0; font-size: var(--sc-t-xs); font-weight: 700;
  letter-spacing: 0.28em; text-transform: uppercase; color: var(--sc-accent);
}
.seal__mid {
  margin: var(--sc-4) 0; font-family: var(--sc-font-display); font-weight: 800;
  text-transform: uppercase; line-height: 0.94; letter-spacing: -0.01em;
  font-size: clamp(2rem, 6vw, 4.5rem); color: var(--sc-ink);
}

/* the lateral strip. Not a pan act: a flow cut whose rail is driven from the
   act's own --sc-p, so nothing pins and nothing is held. */
.strip { position: relative; width: 100%; overflow: clip; }
.strip__rail {
  display: flex; gap: var(--sc-5); align-items: flex-end;
  padding-inline: var(--sc-gutter);
  translate: calc(var(--travel, 0px) * -1 * var(--sc-p, 0)) 0;
  will-change: translate;
}
.strip__lead { flex: 0 0 auto; align-self: center; max-width: 22rem; }
.bottle { flex: 0 0 auto; width: clamp(13rem, 24vw, 20rem); margin: 0; }
.bottle img { width: 100%; height: clamp(8rem, 24svh, 16rem); object-fit: cover; border-radius: var(--sc-r-sm); }
.bottle h3 {
  margin: var(--sc-3) 0 var(--sc-1); font-family: var(--sc-font-display);
  font-weight: 800; text-transform: uppercase; font-size: var(--sc-t-xl); line-height: 1;
}
.bottle p { margin: 0; font-size: var(--sc-t-sm); color: var(--sc-ink-soft); max-width: 22ch; }

/* faces, cut fast */
.faces { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sc-3); margin-top: var(--sc-5); }
/* A figure carries a user-agent margin of 1em 40px. Without this reset every
   face sits 80px narrower than its own grid cell, which is invisible on desktop
   and turns the row into three slivers on a phone. */
.faces figure { margin: 0; }
.faces img { width: 100%; height: clamp(9rem, 30svh, 18rem); object-fit: cover; border-radius: var(--sc-r-sm); }

/* the close */
/* The close keeps the band's clearance like every other cut. Without it the
   closing line and the footer sit under the table strip at the bottom of the
   final screen, which the contrast pass catches as light type over the bright
   objects. */
.cut--close { padding-bottom: calc(var(--peek) + var(--sc-5)); }
.close { position: relative; flex: 1 1 auto; display: flex; flex-direction: column;
          justify-content: flex-end; overflow: clip; }
.close__set {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0.38;
}
/* Density under the closing line, as a sibling of the copy rather than a
   pseudo-element on it. A scrim written as a child is hidden along with the
   text when the pass photographs the frame underneath, so it is never
   measured and tuning it moves no number at all. */
.close__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top,
    color-mix(in oklab, var(--sc-canvas) 96%, transparent) 0%,
    color-mix(in oklab, var(--sc-canvas) 94%, transparent) 46%,
    color-mix(in oklab, var(--sc-canvas) 52%, transparent) 66%,
    transparent 82%);
}
.close__in { position: relative; z-index: 2; width: 100%; max-width: var(--sc-maxw);
             margin-inline: auto; padding-inline: var(--sc-gutter); }
.close__in p { margin: var(--sc-4) 0 var(--sc-5); color: var(--sc-ink); max-width: 40ch; }
.cta {
  display: inline-block; font-family: var(--sc-font-display); font-weight: 800;
  text-transform: uppercase; font-size: clamp(1.3rem, 3vw, 2.1rem); line-height: 1;
  padding: 0.7rem 1.3rem; border-radius: var(--sc-r-sm);
  background: var(--sc-accent); color: var(--sc-accent-ink); text-decoration: none;
  transition: background var(--sc-d-fast) var(--sc-ease-out);
}
.cta:hover { background: #FFF3E4; }
.cta:active { transform: translateY(1px); }
.foot {
  position: relative; z-index: 2; width: 100%; max-width: var(--sc-maxw);
  margin: var(--sc-7) auto 0; padding-inline: var(--sc-gutter);
  font-size: var(--sc-t-xs); color: var(--sc-ink);
  display: flex; gap: var(--sc-5); flex-wrap: wrap;
}
.foot p { margin: 0; }

/* ================================================================ THE BAND ==
   The signature move. A top-down slice of the table, fixed at the bottom edge
   for the whole page. Every cut the visitor passes pulls the objects one
   measured step toward the centre. At the peak the whole panel rises to fill
   the viewport and the convergence completes on one bowl.

   Parked position is a translate, never a height, so the unfurl is one
   transform and nothing reflows. */
.table {
  position: fixed; inset: 0; z-index: 58;
  pointer-events: none;
  translate: 0 calc((100svh - var(--peek)) * (1 - var(--open)));
  transition: translate 720ms var(--sc-ease-drawer);
  will-change: translate;
}
.table__surface {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% 100%, #8E1A06 0%, #6B1305 55%, #4A0E04 100%);
  border-top: 2px solid var(--g-yellow);
}
.table__peak { position: absolute; inset: 0; opacity: var(--open); }
.table__plate, .table__clip {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.table__clip { opacity: 0; transition: opacity 320ms var(--sc-ease-out); }
.table.is-playing .table__clip { opacity: 1; }
/* Density where the peak headline sits, which is the upper band, and a
   vignette that leaves the closing bowl at the centre of the frame alone. */
.table__veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(to bottom,
      rgba(44, 8, 2, 0.94) 0%,
      rgba(44, 8, 2, 0.90) 34%,
      rgba(44, 8, 2, 0.44) 50%,
      rgba(44, 8, 2, 0) 64%),
    radial-gradient(120% 88% at 50% 62%,
      rgba(44, 8, 2, 0) 42%, rgba(44, 8, 2, 0.52) 100%);
  opacity: var(--open);
}
/* Anchored to the band's TOP, not its bottom. The band is a full-height panel
   parked below the fold, so the strip the visitor sees at rest is its first
   --peek pixels; a row anchored to the bottom sits eight hundred pixels off
   screen and the objects only ever appear at the peak. */
.table__row {
  position: absolute; left: 0; right: 0; top: calc(var(--peek) * 0.5);
  height: 0;
  translate: 0 calc(var(--open) * 46svh);
  opacity: var(--obfade, 1);
  transition: translate 720ms var(--sc-ease-drawer), opacity 240ms linear;
}
.table.is-peak .table__row { transition: translate 720ms var(--sc-ease-drawer); }
.ob {
  position: absolute; left: 50%; top: 50%;
  display: block;
  background: #E8C9A0;
  border-radius: var(--sc-r-pill);
  /* The convergence stops short of a point. Nine objects driven all the way to
     one coordinate stack into a single silhouette, and the closing table reads
     as one dot. They keep 12% of their spread and gain a vertical offset, so
     the peak lands as a crowd around one bowl. */
  translate: calc(var(--b) * (1 - var(--k) * 0.88) * 88vw - 50%)
             calc(var(--v, 0) * var(--k) * 15svh - 50%);
  scale: calc(1 + var(--k) * 1.15);
  box-shadow: var(--sc-e2);
  transition: translate 520ms var(--sc-ease-out), scale 520ms var(--sc-ease-out);
  will-change: translate;
}
/* Through the peak the convergence is scroll driven, so it tracks the hand
   directly. Everywhere else the objects step between cuts and want the ease. */
.table.is-peak .ob { transition: none; }
.ob--bowl   { width: 4.6svh; height: 4.6svh; background: #F6E3C6; }
.ob--plate  { width: 5.4svh; height: 5.4svh; background: #D9B48C; }
.ob--glass  { width: 2.4svh; height: 2.4svh; background: #FFDE3D; }
.ob--bottle { width: 1.9svh; height: 5.6svh; border-radius: 0.6svh; background: #7A1206; border: 2px solid #FFDE3D; }
.ob--stick  { width: 0.5svh; height: 6svh; border-radius: 0.25svh; background: #C89A6A; rotate: 14deg; }
.ob--hand   { width: 7svh; height: 2.2svh; border-radius: 1.1svh; background: #B4794A; }

/* the peak copy. Fixed above the band, so it rises with nothing and reads at
   the centre of the unfurled table. */
.peak {
  position: fixed; inset: 0; z-index: 59;
  display: grid; place-items: start center;
  pointer-events: none;
  padding: clamp(5rem, 15svh, 11rem) var(--sc-gutter) 0;
  text-align: center;
}
.peak h2 { max-width: 22ch; }
.peak { opacity: var(--open); transition: opacity 520ms var(--sc-ease-out); }

/* --------------------------------------------------------------- states -- */
[data-sc-in].sc-in, [data-sc-stagger] > .sc-in { opacity: 1; }

/* ------------------------------------------------------- reduced motion --
   The cuts become a fast read. Every section stays legible, every colour cut
   survives because the colour carries the story, and the convergence lands in
   its final composed state instead of travelling. */
@media (prefers-reduced-motion: reduce) {
  .table, .table__row, .ob { transition: none; }
  .strip__rail { translate: none; }
  .strip { overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; }
  .strip__rail > * { scroll-snap-align: center; }
  .frame__clip, .table__clip { display: none; }
}

/* --------------------------------------------------------------- mobile -- */
@media (max-width: 860px) {
  :root { --peek: 10svh; --bar-h: 3rem; }
  .howl-xxl { font-size: clamp(2.6rem, 13vw, 4.4rem); }
  .howl-xl  { font-size: clamp(2.1rem, 10vw, 3.4rem); }
  .trio { grid-template-columns: 1fr 1fr; }
  .trio figure:last-child { display: none; }
  .faces { grid-template-columns: 1fr 1fr; }
  .faces figure:last-child { display: none; }
    /* A narrow screen makes the peak cluster vertical, which reads as a totem
     rather than a table. Keep more of the horizontal spread and less of the
     vertical one here. */
  .ob { translate: calc(var(--b) * (1 - var(--k) * 0.78) * 82vw - 50%)
                   calc(var(--v, 0) * var(--k) * 7svh - 50%); }
  /* The objects are sized in viewport heights, which is right on a landscape
     screen and wrong on a tall narrow one: at 390 by 844 the same pills cover a
     third of the width and swamp the peak bowl. Scale the whole set down here
     and let the peak grow less. */
  .ob { scale: calc((1 + var(--k) * 0.9) * 0.6); }

  /* Touch targets. The close action and the bar action both measured under
     44px, and the footer link had none at all. */
  .cta { padding: 0.95rem 1.35rem; }
  .bar__cta { padding: 0.85rem 1rem; }
  .foot a { display: inline-flex; align-items: center; min-height: 44px; }
  .bar__mark { display: inline-flex; align-items: center; min-height: 44px; }
  .foot { flex-direction: column; gap: var(--sc-2); }
}
