/* skyhigh-art.css — the art layer. GENERATED by tools/art_engine.py; edit the engine, not this file.
   Written against site.css's own tokens so the palette can never drift from the site's.
   Budget (water-motion, measured 2026-08-25): transform and opacity only. No filter, no backdrop-filter,
   no fixed-attachment backgrounds. Motion stops off-screen and when the tab is hidden. */

.sha-layer{position:absolute;inset:0;pointer-events:none;overflow:hidden;z-index:0}
.sha-layer canvas{display:block;width:100%;height:100%}
/* Every section that hosts art becomes the positioning context, and its own content stays above the art. */
[data-section]{position:relative}
[data-section] > *:not(.sha-layer):not(.sha-scatter){position:relative;z-index:1}

/* ---------- the record ---------- */
.sha-vinyl{
  --sha-spin:14s;
  position:relative;display:block;aspect-ratio:1;width:100%;
  border-radius:50%;
  /* The turntable read: a disc tilted away from the viewer, not a flat circle pasted on the page. */
  transform:perspective(1200px) rotateX(var(--sha-tilt,0deg));
  transform-style:preserve-3d;
}
.sha-vinyl__spin{
  position:absolute;inset:0;border-radius:50%;
  animation:sha-rotate var(--sha-spin) linear infinite;
  animation-play-state:paused;
  will-change:transform;
}
.sha-vinyl[data-playing="1"] .sha-vinyl__spin{animation-play-state:running}
/* The album art sits UNDER the label ring, so one Blender render serves all twelve releases. */
.sha-vinyl__art{
  position:absolute;left:50%;top:50%;width:33%;height:33%;
  transform:translate(-50%,-50%);border-radius:50%;object-fit:cover;
  box-shadow:0 0 0 1px rgba(0,0,0,.55);
}
.sha-vinyl__disc,.sha-vinyl__label{position:absolute;inset:0;width:100%;height:100%;border-radius:50%}
/* The grooves are drawn here, not baked into the render.
   Two rounds of Blender tuning could not make a procedural bump read as concentric grooves at web scale: at a
   fine scale they alias into radial streaks, and coarse enough to survive the downscale they stop looking like
   a record. The honest split is to let Cycles do what it is actually better at — a black dielectric body with a
   true radial sheen — and draw the rings deterministically, where the spacing is exact, costs no bytes, and
   scales with the element instead of with the render. This layer sits INSIDE the spinning wrapper, so the
   grooves turn with the record while the sheen above it does not. */
.sha-vinyl__grooves{
  position:absolute;inset:0;border-radius:50%;
  /* A 1px light ring every 4px does not read as grooves — at any real element size the rings fall below a
     pixel and average into a flat grey haze over the black body, which is exactly how the first pass turned a
     correctly-exposed black disc silver on screen. Grooves are dark VALLEYS with a thin catch of light on the
     land between them, so the dark line carries the pattern and the light line is barely there. */
  background:repeating-radial-gradient(circle at 50% 50%,
    rgba(0,0,0,.55) 0 1.5px,
    rgba(248,248,246,.028) 1.5px 2.5px,
    rgba(0,0,0,0) 2.5px 6px);
  -webkit-mask-image:radial-gradient(circle at 50% 50%, transparent 0 16.5%, #000 17% 99%, transparent 100%);
  mask-image:radial-gradient(circle at 50% 50%, transparent 0 16.5%, #000 17% 99%, transparent 100%);
}
.sha-vinyl__label{width:34%;height:34%;left:33%;top:33%;inset:auto;opacity:.92}
/* The highlight does NOT rotate. Real vinyl keeps its sheen where the light is while the record turns under it;
   a highlight baked into the spinning disc is the single thing that makes a CSS record look fake. */
.sha-vinyl__sheen{
  position:absolute;inset:0;border-radius:50%;pointer-events:none;
  /* Screen-blending a bright sheen over a black disc lifts the whole face. Keep the highlight narrow and let
     the record stay black: the sheen should be a glint you notice, not a wash you see through. */
  background:
    radial-gradient(80% 55% at 28% 20%, rgba(248,248,246,.085), rgba(248,248,246,0) 40%),
    radial-gradient(70% 45% at 74% 82%, rgba(226,167,44,.07), rgba(226,167,44,0) 46%);
}
.sha-vinyl__hole{
  position:absolute;left:50%;top:50%;width:3.2%;height:3.2%;transform:translate(-50%,-50%);
  border-radius:50%;background:var(--void,#000);
}
@keyframes sha-rotate{from{transform:rotate(0)}to{transform:rotate(360deg)}}

/* A record that slides out of its sleeve on hover — the crate-digging gesture. */
.sha-sleeve{position:relative;display:block;isolation:isolate}
.sha-sleeve .sha-vinyl{
  position:absolute;top:0;left:0;width:100%;
  transform:translateX(0) perspective(1200px) rotateX(var(--sha-tilt,0deg));
  transition:transform .62s var(--ease-arrive,cubic-bezier(.22,.61,.36,1));
  z-index:-1;
}
.sha-sleeve:hover .sha-vinyl,.sha-sleeve:focus-within .sha-vinyl{transform:translateX(34%) perspective(1200px) rotateX(var(--sha-tilt,0deg))}

/* ---------- scattered archive ---------- */
/* Photographs placed in the page's gutters at different depths. They are NEVER placed over text: the engine
   only ever writes them into the left and right margins, and below 900px they are removed entirely rather than
   allowed to collide with a single-column layout. */
.sha-scatter{position:absolute;inset:0;pointer-events:none;z-index:0}
/* PLATES, not confetti. This is an artist's showcase: the photographs ARE the work, so they are printed at
   plate scale, at full opacity, and ALIGNED — no random tilt, no half-transparent wash. The earlier treatment
   painted 640-3024px archive scans into 121-196px boxes at 0.34-0.51 opacity, which is a contact sheet, not an
   exhibition. Plates are allowed to bleed off the viewport edge (a deliberate editorial move) so the printed
   size can exceed the margin without ever crossing into the text column. */
.sha-scatter figure{
  position:absolute;margin:0;width:var(--w,clamp(360px,42vw,760px));
  /* The bleed is a TRANSFORM, not a left/right offset. A percentage in `left` resolves against the
     CONTAINING BLOCK, so a 46% bleed on a 432px plate inside a 1440px section computed to -662px and pushed
     every photograph completely off screen — the page looked deliberately empty rather than broken. A
     percentage in `translate` resolves against the ELEMENT's own size, which is what a bleed actually means. */
  transform:translate3d(var(--sha-x,0),var(--sha-y,0px),0);
  will-change:transform;
}
.sha-scatter img{
  display:block;width:100%;height:auto;
  box-shadow:0 30px 80px rgba(0,0,0,.72),0 0 0 1px var(--seam-strong,rgba(248,248,246,.32));
  opacity:var(--o,1);
}
/* One gold hairline along the bleed edge, so a plate reads as deliberately cropped rather than broken. */
.sha-scatter figure[data-bleed="right"] img{border-right:2px solid var(--canvas-gold,#e2a72c)}
.sha-scatter figure[data-bleed="left"] img{border-left:2px solid var(--canvas-gold,#e2a72c)}
.sha-scatter figcaption{
  display:block;margin-top:10px;font:400 12px/1.3 var(--mono,ui-monospace,monospace);
  letter-spacing:.16em;text-transform:uppercase;color:var(--canvas-gold,#e2a72c);opacity:.9;
}
@media (max-width:900px){.sha-scatter{display:none}}

/* ---------- musical notes ---------- */
.sha-notes{position:absolute;inset:0;z-index:0;pointer-events:none}

/* ---------- the story timeline, as BANDS ---------- */
/* Owner 2026-09-10 on the live /story/: "this is incredibly boring!" It was an <ol> of ten table rows carrying
   1967 Kingston, the Burning Spear crew, Bob Marley passing in 1981, Tenor Saw, Julian and Damian — the most
   dramatic material on the site, set at 13px grey. The list stays an <ol> and each moment keeps its data-era,
   so the era filter above it keeps working; only the presentation changes. */
ol.timeline{list-style:none;margin:0;padding:0}
/* SPECIFICITY, not order: site.css already styles `.timeline li` with a 7rem first column, and a bare
   `.tl-band` (one class) loses to it however late this file loads — which crushed every moment's text into a
   112px ribbon one word wide while the picture took the rest. `ol.timeline li.tl-band` outranks it. */
ol.timeline li.tl-band{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;
  gap:clamp(24px,4vw,72px);padding:clamp(44px,6vw,110px) 0;
  border-top:1px solid var(--seam,rgba(248,248,246,.13));border-bottom:0;
}
ol.timeline li.tl-band[data-side="right"] .tl-say{grid-column:2}
ol.timeline li.tl-band[data-side="right"] .tl-plate{grid-column:1;grid-row:1}
.tl-say{min-width:0}
/* The year IS the drama. */
.tl-band .year{
  display:block;
  font:900 clamp(52px,9vw,168px)/.82 var(--display,"Big Shoulders Display",Impact,sans-serif);
  letter-spacing:-.03em;color:var(--salt,#f8f8f6);text-transform:uppercase;margin:0 0 clamp(14px,1.6vw,24px);
}
.tl-band p{font:300 clamp(18px,1.8vw,29px)/1.42 var(--body,"DM Sans",sans-serif);max-width:30ch;color:var(--salt,#f8f8f6)}
.tl-band .src{display:inline-block;margin-top:18px;font:400 11px/1 var(--mono,ui-monospace,monospace);letter-spacing:.16em;text-transform:uppercase;color:var(--ash,#8c8c89)}
.tl-band .src a{color:inherit;text-decoration:none;border-bottom:1px solid var(--seam-strong,rgba(248,248,246,.32));padding-bottom:3px}
.tl-band .src a:hover{color:var(--canvas-gold,#e2a72c)}
/* The picture runs to the edge of the screen. On the live page the biggest image was 196px on a 1440 viewport. */
.tl-plate{margin:0}
.tl-plate img{display:block;width:100%;height:clamp(300px,40vw,600px);object-fit:cover;box-shadow:0 40px 90px rgba(0,0,0,.7)}
.tl-band[data-era="1960s"] .tl-plate img{border-inline-start:3px solid var(--canvas-green,#1c5b3a)}
.tl-band[data-era="1970s"] .tl-plate img{border-inline-start:3px solid var(--canvas-gold,#e2a72c)}
.tl-band[data-era="1980s"] .tl-plate img{border-inline-start:3px solid var(--canvas-red,#a12f28)}
.tl-band[data-era="2000s"] .tl-plate img{border-inline-start:3px solid var(--canvas-gold,#e2a72c)}
@media (max-width:900px){
  ol.timeline li.tl-band{grid-template-columns:1fr;gap:20px}
  ol.timeline li.tl-band[data-side="right"] .tl-say,ol.timeline li.tl-band[data-side="right"] .tl-plate{grid-column:1}
  ol.timeline li.tl-band[data-side="right"] .tl-plate{grid-row:auto}
  .tl-plate img{height:clamp(220px,56vw,400px)}
}

/* ---------- groove divider ---------- */
/* Concentric run-out grooves as a section seam. Pure SVG, no image request. */
.sha-groove{display:block;width:100%;height:64px;overflow:hidden;opacity:.5}
.sha-groove svg{display:block;width:100%;height:100%}
.sha-groove .g{fill:none;stroke:rgba(28,91,58,.42);stroke-width:.5}

/* ---------- the tricolor, at rest ---------- */
/* Measured 2026-09-10: gold was 80-100% of the accent on every page and red was 0% on five of eight. Hover
   states carry red now, but a hover is invisible until someone touches it, so the flag also has to be present
   when the page is just sitting there. Every section opens on a red/gold/green rule — 2px, no layout cost, and
   it reads as the flag rather than as decoration because the proportions are the flag's. */
[data-section]{position:relative}
[data-section]::before{
  content:"";position:absolute;top:0;left:0;right:0;height:2px;pointer-events:none;
  background:linear-gradient(90deg,
    var(--canvas-red,#a12f28) 0 33.33%,
    var(--canvas-gold,#e2a72c) 33.33% 66.66%,
    var(--canvas-green,#1c5b3a) 66.66% 100%);
  opacity:.55;
}
/* The HERO gets no rule of its own. The masthead now closes on the same tricolor and a hero sits flush
   beneath it (measured gap: 0px), so both together painted one thick doubled band instead of a hairline.
   Whoever is directly under the header owns that edge, and that is the header. */
[data-section$=".hero"]::before{display:none}

/* Action = red, matching site.css's recoloured hover states, so a link and a button answer the same way. */
.sha-scatter figcaption{color:var(--canvas-gold,#e2a72c)}
.tl-band .src a:hover{color:var(--red-ink,#d64b40);border-bottom-color:var(--canvas-red,#a12f28)}
/* A moment told by SkyHigh himself is provenance, and provenance is roots. A sourced moment keeps the neutral
   label so the two kinds of evidence stay visibly different. */
.tl-band .src:not(:has(a)){color:var(--green-ink,#2f8f5b)}

/* ---------- equaliser rule ---------- */
.sha-eq{display:flex;align-items:flex-end;gap:3px;height:18px}
.sha-eq i{display:block;width:3px;background:var(--canvas-gold,#e2a72c);transform-origin:bottom;animation:sha-bar 1.1s ease-in-out infinite;animation-play-state:paused}
/* A five-bar meter in one colour is a loading spinner; in the flag's colours it is the music. */
.sha-eq i:nth-child(1),.sha-eq i:nth-child(2){background:var(--canvas-green,#1c5b3a)}
.sha-eq i:nth-child(4),.sha-eq i:nth-child(5){background:var(--canvas-red,#a12f28)}
.sha-eq[data-playing="1"] i{animation-play-state:running}
.sha-eq i:nth-child(2){animation-delay:-.22s}.sha-eq i:nth-child(3){animation-delay:-.45s}
.sha-eq i:nth-child(4){animation-delay:-.67s}.sha-eq i:nth-child(5){animation-delay:-.9s}
@keyframes sha-bar{0%,100%{height:22%}50%{height:100%}}

/* ---------- reduced motion: remove MOTION, never CONTENT ---------- */
@media (prefers-reduced-motion:reduce){
  .sha-vinyl__spin,.sha-eq i{animation:none!important}
  .sha-sleeve .sha-vinyl{transition:none}
  .sha-scatter figure{transform:none}   /* plates are aligned; there is no tilt to preserve */
  .sha-notes{display:none}          /* the note field is motion by definition; there is no still version of it */
}
