/* ============================================================================
   04 · la cuerda de ejemplos.  Family: clothesline.  The page's ONLY
   horizontal scroller: ten ads hang from one rope inside a scroll-snap row,
   with the copy sheet pinned on the desk above it.

   THE ROPE.  One inline SVG path, not repeated segments between pins, and
   stretched with preserveAspectRatio="none" across the whole track:
     - the mockup shows ONE continuous catenary from end to end (the prints
       hang off it, they do not each pull a local sag), and a single path is
       the only way to keep that curve continuous while the track's width
       changes with the viewport (2825px at 1440, 2364px at 390);
     - the viewBox is 0 0 1200 60 and the svg's CSS height is exactly 60px, so
       the vertical scale is 1:1 and the 5px stroke keeps its real thickness
       however far the path is stretched sideways. Only x is scaled.
   The path is  M0 6 Q600 74 1200 6, i.e. y(f) = 6 + 4*34*f*(1-f) in px:
   the ends sit 6px down and the deepest point of the sag is 34px lower.

   HANGING FROM A CURVE.  A print whose clip straddles a sagging rope has to
   drop by exactly the rope's own drop at its own x. The drop function of a
   quadratic through the midpoint control is 4*S*f*(1-f) with f the item's
   share of the track width, so every hanger carries its own
     --f = 4*f*(1-f)   (a factor of --sag, in the partial, next to --rot)
   and CSS does margin-top: calc(var(--sag) * var(--f)).  Eleven items
   (ten prints + the closing note) at a 252px pitch inside 37.44px of desk
   padding give centres at f = .054 .143 .232 .322 .411 .500 .589 .678 .768
   .857 .946, hence --f = .20 .49 .71 .87 .97 1 .97 .87 .71 .49 .20.
   The same factors hold at 390 (pitch 214 in a 2364px track: f = .047 ... .953,
   so the factors move by at most .02 = 0.8px). One set of numbers, both widths.

   VERTICAL STACK of the row, all measured from the track's top:
     --hang-top   46px   the print's top edge at the ends of the rope
     rope svg     32px   = --hang-top - 14, so its path's end-line (+6) lands
                         8px above the print's top edge at both ends
     clip        -32px   from the print's top: 52px tall, so it covers the
                         rope (at -8) and overlaps the print by 20px
   Because the rope's drop and the hanger's drop are the same function of f,
   those three relationships hold at every one of the eleven items.

   GEOMETRY, measured.  1440 (desk-pad 37.44px): sheet 680x296 at x=37; track
   37.44 + 11*230 + 10*22 + 37.44 = 2825px, of which 1440 is visible, so the
   sixth print is cut by the right edge and the row reads as scrollable.
   Print 230x409, kraft tag 216x130, the closing note 230x119, row 660px tall,
   section 1221px.
   390: sheet 366x246, print 200x356, tag 192x120, track 2364px, row 587px,
   section 969px. The row is the only horizontal scroller on the page.
   ========================================================================= */

.s-04{
  position:relative;
  padding:var(--gap-section) 0;

  --pw:230px;            /* print width; the print material derives its height */
  --gap-hang:28px;       /* air between two prints on the rope */
  --sag:34px;            /* the deepest point of the rope, see the path above */
  --hang-top:46px;       /* room above the print for the clip and the rope */
  --clip-top:-32px;
  --tag-w:184px;         /* the tag is a label: clearly narrower than the print */
  --tag-gap:18px;        /* the visible cord between print and tag */
}

/* ---------- the copy sheet, pinned on the desk above the rope ------------ */
/* 680px is the narrowest sheet that still fits "nos funciona en Meta." on one
   line: 21 characters of Archivo Black are ~11.5em, the .t-h2 clamp tops out
   at 48px, and 680px minus 2*34.6px of sheet padding leaves 611px for 552px
   of type. 50vw keeps the same headroom down to 900px. */
.s-04 .s04-head{
  width:min(680px, 50vw);
  margin:0 0 var(--gap-object) var(--desk-pad);
}
.s-04 .s04-head .pin-a{--px:8%;--py:0%;--pr:-17deg}
.s-04 .s04-head .pin-b{--px:92%;--py:0%;--pr:14deg}
.s-04 .s04-head h2 span{display:block}
.s-04 .s04-sub{
  margin-top:var(--gap-row);
  max-width:56ch;
  color:var(--ink-soft);
}

/* ---------- the scroller ------------------------------------------------- */
/* Full bleed on purpose: the rope has to run off both edges of the desk and
   the last print has to be cut by the right edge. */
.s-04 .s04-row{
  overflow-x:auto;
  overflow-y:hidden;
  overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  scroll-padding-left:var(--desk-pad);
  /* The cut print at the right edge plus the snap are the affordance; a 15px
     grey system bar across the oak is not (the hero's mobile deck hides it
     the same way). Arrow keys still scroll: the row is tabindex=0. */
  scrollbar-width:none;
}
.s-04 .s04-row::-webkit-scrollbar{display:none}

.s-04 .s04-track{
  position:relative;
  width:max-content;
  display:flex;
  align-items:flex-start;
  gap:var(--gap-hang);
  padding:var(--hang-top) var(--desk-pad) 14px;
}

.s-04 .s04-rope{
  position:absolute;
  left:0;
  top:calc(var(--hang-top) - 14px);
  width:100%;
  height:60px;              /* = the viewBox height: vertical scale stays 1:1 */
  z-index:var(--z-felt);
}

/* ---------- one hanger: print, clothespin, kraft tag --------------------- */
.s-04 .hanger{
  position:relative;
  flex:0 0 auto;
  width:var(--pw);
  margin-top:calc(var(--sag) * var(--f, 0));
  scroll-snap-align:start;
  transform-origin:50% 0;   /* it swings around the clip, not its middle */
  transform:rotate(calc(var(--rot, 0deg) + var(--sway, 0) * var(--sway-dir, 1) * 1deg));
}
/* site.js writes --sway (+-1) on the row while it scrolls; alternate items
   lean the other way (behaviour-contract 9). */
.s-04 .hanger[data-sway="-"]{--sway-dir:-1}

.s-04 .clip{
  position:absolute;
  left:50%;
  top:var(--clip-top);
  transform:translateX(-50%) rotate(var(--clip-rot, 0deg));
}

/* seven of the ten ads have no clip, so they promise nothing when you point
   at them (no data-video, no <video>, no .play, not focusable) */
.s-04 .print:not([data-video]){cursor:default}

/* ---------- the kraft tag hanging under each print ----------------------- */
/* A hang tag, not a caption box: the material's own eyelet (.is-punched), a
   twine cord from the print's bottom edge down through that eyelet, 18px of
   desk showing between the two, a counter-tilt against the hanger's own lean,
   and 184px against the print's 230 so it reads as a label. The cord is
   --rope-dark (twine), never --string: the red string is the hero's and s05's.
   The eyelet's own centre is at clamp(7px,.8vw,11px) + 3.5px, inside the 28px
   left padding .is-punched adds, so the cord never crosses the type.
   Kraft ink on every line: --ink-soft is 3.3:1 on kraft, --kraft-ink is 8.6:1. */
.s-04 .hang-tag{
  display:block;
  width:var(--tag-w);
  margin:var(--tag-gap) 0 0 calc((var(--pw) - var(--tag-w)) / 2);
  transform:rotate(var(--tag-rot, 0deg));
}
.s-04 .hang-tag::after{
  content:"";
  position:absolute;
  left:calc(clamp(7px,.8vw,11px) + 3.5px);
  top:calc(-1 * var(--tag-gap));
  width:2px;
  height:calc(var(--tag-gap) + 50%);   /* down to the eyelet at 50% height */
  border-radius:1px;
  background:var(--rope);              /* the twine face, so it reads on oak */
}
.s-04 .ht-fmt{color:var(--kraft-ink)}
/* .t-small for both the title and the description, so the tag adds no seventh
   size to the scale: the hierarchy is weight (900 against 500), not size. The
   caps and the tracking the .kraft-tag inherits are cleared here, and every
   line takes kraft ink. */
.s-04 .ht-title{
  margin:5px 0 0;
  font-weight:900;          /* the title, not the repeated format label, leads */
  line-height:1.3;
  letter-spacing:0;
  text-transform:none;
  color:var(--kraft-ink);
}
.s-04 .ht-desc{
  margin:5px 0 0;
  letter-spacing:0;
  text-transform:none;
  color:var(--kraft-ink);
}
.s-04 .ht-dur{
  margin:8px 0 0;
  color:var(--kraft-ink);
}

/* ---------- the closing note at the right end of the rope ---------------- */
.s-04 .note-tag{
  width:var(--pw);
  text-align:left;
  padding:clamp(10px,1.2vw,16px) clamp(11px,1.2vw,17px);
}

/* ---------- the rope's anchors ------------------------------------------- */
/* The brief ties the rope between two pins at the far edges. They live inside
   the track, so the left one is the first thing at scroll start and the right
   one the last thing at scroll end. --px and --py take lengths as happily as
   percentages, and --hang-top - 8px is exactly where the path's end-line sits. */
.s-04 .rope-pin{--py:calc(var(--hang-top) - 8px)}
.s-04 .rope-pin-a{--px:12px;--pr:-17deg}
.s-04 .rope-pin-b{--px:calc(100% - 12px);--pr:20deg}

/* ---------- entry ------------------------------------------------------- */
/* Both objects use the materials' own 12px settle in reading order (the sheet,
   then the rope with everything on it), so there is no variant to define and
   nothing to override: after the manager's Phase-3 fix the reveal's end state
   already keeps --rot and the hover lift. */

/* ---------- the prop: a spare pair of clothespins on the desk ------------ */
.s-04 .prop-clips{
  right:clamp(16px,3vw,54px);
  top:clamp(40px,7vw,104px);
  --prop-w:clamp(120px,12vw,178px);
  --rot:-9deg;
}

/* ============================================================================
   MOBILE  < 900px.  Same rope, same row (it stays the only horizontal
   scroller on the page), smaller prints, tags still under them. The sheet
   goes full width inside the 12px desk margin and its tilt drops to 0.4deg.
   ========================================================================= */
@media (max-width: 899px){
  .s-04{
    --pw:200px;
    --gap-hang:14px;
    --hang-top:36px;
    --clip-top:-26px;     /* the clip is 18x42 below 900px */
    --tag-w:164px;
    --tag-gap:15px;
  }
  /* the sheet's own tilt is inline and already inside the 1deg phone cap */
  .s-04 .s04-head{
    width:auto;
    margin:0 var(--desk-pad) var(--gap-object);
  }
  .s-04 .s04-head .pin-a{--px:9%}
  .s-04 .s04-head .pin-b{--px:91%}
  .s-04 .s04-sub{max-width:none}
  .s-04 .hang-tag{margin-top:var(--tag-gap)}

  /* The hangers' desktop tilts are inline (up to 1.3deg) and an inline custom
     property cannot be overridden, so the phone reads --rot-m instead: the
     same pattern materials.css uses for a .board-stack column. Alternating
     0.8deg keeps the row inside the 1deg phone cap. */
  .s-04 .hanger{
    transform:rotate(calc(var(--rot-m, 0deg) + var(--sway, 0) * var(--sway-dir, 1) * 1deg));
  }
  .s-04 .hanger:nth-of-type(odd){--rot-m:-.8deg}
  .s-04 .hanger:nth-of-type(even){--rot-m:.8deg}
  .s-04 .hang-tag{transform:rotate(var(--tag-rot-m, 0deg))}
  .s-04 .hanger:nth-of-type(odd) .hang-tag{--tag-rot-m:.7deg}
  .s-04 .hanger:nth-of-type(even) .hang-tag{--tag-rot-m:-.7deg}
}
