/* ==========================================================================
   Tenure page (six-years-at-kaluza) — the depth treatment + timeline spine.
   Page-scoped: only six-years-at-kaluza.php and scratch-spine.php link this.
   Everything else on the page is existing kit (case-study.css, typography.css).

   The page is a dive. Each .tn-seg paints one stretch of a single vertical ramp,
   and every segment starts on the stop the previous one ended on, so the water
   reads as one continuous gradient keyed to document position. Pinning stops to
   section boundaries (rather than % of page height) is what guarantees the text
   flip passes AA at every viewport width.
   ========================================================================== */

:root{
  /* The ramp. One line per stop, tune freely. */
  --tn-1:#F3B29E;   /* sunset sky (was #F4A97F) */
  --tn-2:#E58B70;   /* horizon glow */
  --tn-3:#9FD2CF;   /* the waterline, pale aqua */
  --tn-4:#6FB5C4;   /* shallows */
  --tn-5:#3E7393;   /* mid water. Brief proposed #4A86A6 (white 4.00:1, fails AA). #3E7393 is 5.15:1, 4.65:1 under the noise at its brightest */
  --tn-6:#3A5E8C;   /* deeper blue */
  --tn-7:#34406B;   /* indigo */
  --tn-8:#330047;   /* site purple, the exact value .footer and .contact-back use (css/body.css) */

  /* Still water: stretches between indigo and the floor */
  --tn-7a:#342D60;  /* 7 → 8, 30% */
  --tn-7b:#331A55;  /* 7 → 8, 60% */

  /* How tight the waterline blend is (stop 2 → 3) */
  --tn-waterline:180px;
  /* Waterline inset from the bottom of the surface section. Keep in step with
     WATERLINE_INSET in js/tenure.js */
  --tn-line-inset:90px;

  /* Text either side of the one flip */
  --tn-ink-dark:var(--cs-ink);
  --tn-ink-light:#ffffff;
  --tn-ink-light-2:rgba(255,255,255,0.72);   /* cite colour, as .contact-back .cs-quote cite */

  /* Fine noise laid over the water to dither any banding in the long blends */
  --tn-noise:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.05 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
}

/* ---------- Segments ---------- */
.tn-seg{position:relative;overflow:hidden;overflow:clip;}
.tn-seg > *:not(.tn-decor){position:relative;z-index:1;}
.tn-decor{position:absolute;inset:0;z-index:0;pointer-events:none;}

/* Each segment: sRGB first, oklab where supported (cleaner mid-blends, less mud at the waterline) */
.tn-seg--surface{
  /* the waterline sits --tn-line-inset above this section's bottom, at 60% of the screen on
     load; taller content just pushes it down */
  box-sizing:border-box;
  min-height:calc(60vh + var(--tn-line-inset));
  min-height:calc(60svh + var(--tn-line-inset));
  padding-bottom:calc(var(--tn-line-inset) + 32px);   /* min clearance between the stats and the waterline */
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-1) 0,var(--tn-2) calc(100% - var(--tn-waterline)),var(--tn-3) 100%);
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-1) 0,var(--tn-2) calc(100% - var(--tn-waterline)),var(--tn-3) 100%);
}
.tn-seg--shallows{
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-3),var(--tn-4));
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-3),var(--tn-4));
}
/* Text-free stretch: the water crosses the dead zone where neither dark nor light text passes */
.tn-seg--cross{
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-4),var(--tn-5));
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-4),var(--tn-5));
}
.tn-seg--practice{
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-5),var(--tn-6));
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-5),var(--tn-6));
}
.tn-seg--descent{
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-6),var(--tn-7));
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-6),var(--tn-7));
}
.tn-seg--built{
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-7),var(--tn-7a));
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-7),var(--tn-7a));
}
.tn-seg--still{
  background-image:var(--tn-noise),linear-gradient(to bottom,var(--tn-7a),var(--tn-7b));
  background-image:var(--tn-noise),linear-gradient(in oklab to bottom,var(--tn-7a),var(--tn-7b));
}
.tn-seg--floor{
  background-image:linear-gradient(to bottom,var(--tn-7b) 0,var(--tn-8) 240px,var(--tn-8) 100%);
  background-image:linear-gradient(in oklab to bottom,var(--tn-7b) 0,var(--tn-8) 240px,var(--tn-8) 100%);
  background-color:var(--tn-8);
}
/* Fallback colour under each gradient, in case gradients fail */
.tn-seg--surface{background-color:var(--tn-1);}
.tn-seg--shallows{background-color:var(--tn-3);}
.tn-seg--cross{background-color:var(--tn-4);}
.tn-seg--practice{background-color:var(--tn-5);}
.tn-seg--descent{background-color:var(--tn-6);}
.tn-seg--built{background-color:var(--tn-7);}
.tn-seg--still{background-color:var(--tn-7a);}

/* Stats sit in the sky, tucked up under the hero */
.tn-seg--surface .hero-img .text-container{padding-bottom:0;}
.tn-stats-band{padding-top:40px;padding-bottom:0;}
/* Phones: 2x2, so the hero and stats fit above the waterline. Figures step down to the
   heading-3 size (typography.css) and may wrap at half width. */
@media(max-width:600px){
  .tn-stats-band .cs-stats{grid-template-columns:1fr 1fr;gap:24px 16px;}
  .tn-stats-band .cs-stat .n{font-size:1.375em;white-space:normal;}
}

/* Text-free stretch where the water darkens through the band no text colour passes in */
.tn-seg--cross{min-height:250px;}

/* The smooth ramp (js/tenure.js). The per-segment gradients above are the no-JS
   fallback: straight blends, so the slope jumps at every boundary and reads as steps.
   With JS, one page-height gradient is built with stops eased through every section
   boundary, and each segment shows its own slice of it. */
.tn-ramped .tn-seg,
.tn-ramped .tn-seg--floor{
  background-image:var(--tn-ramp);   /* no noise layer here: the sampled ramp doesn't band, and the noise's slight lift showed as a line wherever it stopped */
  background-size:100% var(--tn-ramp-h);
  background-position:0 var(--tn-off,0px);
  background-repeat:no-repeat;
}

/* ---------- The one text flip ---------- */
.tn-dark .cs-stat .l,
.tn-dark .cs-byline,
.tn-dark .cs-readtime,
.tn-dark .cs-byline-sep{color:var(--tn-ink-dark);}
.tn-dark .cs-readtime .cs-clock circle,
.tn-dark .cs-readtime .cs-clock path{stroke:var(--tn-ink-dark);}
.tn-dark .cs-arrow path{stroke:var(--tn-ink-dark);}   /* bronze is 1.95:1 on the waterline */

.tn-light,
.tn-light h2,.tn-light .heading-3,
.tn-light p,.tn-light li,.tn-light b{color:var(--tn-ink-light);}
.tn-light .cs-quote cite{color:var(--tn-ink-light-2);}

/* Links: the homepage's zig-zag underline (.ink, css/home.css), redrawn in white for
   the deep water. Hover goes to the soft bronze, as bronze itself fails on the blue. */
.tn-light .ink{
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='6' viewBox='0 0 12 6'%3E%3Cpath d='M0 5 L3 1 L6 5 L9 1 L12 5' fill='none' stroke='%23ffffff' stroke-width='1'/%3E%3C/svg%3E");
}
.tn-light .ink:hover,
.tn-light .ink:focus-visible{
  color:var(--cs-accent-soft);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='6' viewBox='0 0 12 6'%3E%3Cpath d='M0 5 L3 1 L6 5 L9 1 L12 5' fill='none' stroke='%23f6e7d6' stroke-width='1'/%3E%3C/svg%3E");
}

/* Inline bold, as .cs-related b */
.tn-page b{font-family:'HKGrotesk-bold','Helvetica','Arial',sans-serif;font-weight:normal;}

.tn-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}

/* ==========================================================================
   The timeline spine (doubles as the depth gauge)
   A solid line that grows with scroll (js/tenure.js sets --grow) over a faint
   track, solid dots, and a ring that ripples out from each dot as the line
   reaches it. Without JS the line is fully drawn; without this CSS it is a
   plain ordered list of paragraphs.
   ========================================================================== */
.tn-spine{list-style:none;margin:28px 0 0;padding:0;max-width:66ch;position:relative;--grow:1;--rail-end:0px;}
.tn-spine:before,
.tn-spine:after{
  content:"";position:absolute;left:5px;top:7px;bottom:var(--rail-end);width:1.5px;
  background:currentColor;transform-origin:top;pointer-events:none;
}
.tn-spine:before{opacity:0.22;}                       /* the track */
.tn-spine:after{transform:scaleY(var(--grow));}       /* the line */

.tn-beat{position:relative;padding:0 0 32px 36px;}
.tn-beat:last-child{padding-bottom:0;}
.tn-beat p{margin:0;}
.tn-beat p + p{margin-top:1em;}

/* node label: the bold date range */
.tn-when{display:block;font-size:0.875em;line-height:1.25;margin-bottom:6px;letter-spacing:0.01em;}

/* dots, all solid, centred on the line (x 6px, y 7px). Role changes are larger. */
.tn-beat:before{
  content:"";position:absolute;left:1px;top:2px;width:10px;height:10px;border-radius:50%;
  background:currentColor;z-index:1;
  transition:transform 0.5s cubic-bezier(.3,1.6,.5,1),opacity 0.4s ease;
}
.tn-beat--role:before{left:-1px;top:0;width:14px;height:14px;}
.tn-motion .tn-beat:not(.is-reached):before{transform:scale(0.55);opacity:0.45;}

/* The ripple: when the line arrives, a ring spreads out from the dot, then pulls back
   into a small bubble that wobbles up the line towards the surface. One element the
   whole way, so the ring visibly becomes the bubble. Sized with width/height rather
   than scale so the rim stays a hairline. Role changes: a bigger, doubled ring and a
   slightly bigger bubble that rises further. Stays on the rail (x 0-12px), clear of text. */
.tn-beat:after{
  content:"";position:absolute;left:6px;top:7px;width:10px;height:10px;border-radius:50%;
  border:1px solid currentColor;opacity:0;pointer-events:none;box-sizing:border-box;
  transform:translate(-50%,-50%);
}
/* Three tracks on the one element, same length:
   - rise:  a single gentle ease-in the whole way, so it never stalls between steps
   - shape: ring spreads (0-20%), then slowly gathers into a bubble (20-72%), fades
   - sway:  a small side to side wobble
   transform holds the centring + sway; the rise uses the separate translate property. */
.tn-beat.is-reached:after{
  animation:
    tn-rb-shape 5.4s linear 1 both,
    tn-rb-rise  5.4s cubic-bezier(.3,.18,.7,.55) 1 both,
    tn-rb-sway  5.4s ease-in-out 1 both;
}
.tn-beat--role.is-reached:after{
  animation:
    tn-rb-shape-lg 6s linear 1 both,
    tn-rb-rise-lg  6s cubic-bezier(.3,.18,.7,.55) 1 both,
    tn-rb-sway     6s ease-in-out 1 both;
}
@keyframes tn-rb-rise   {from{translate:0 0;}to{translate:0 -220px;}}
@keyframes tn-rb-rise-lg{from{translate:0 0;}to{translate:0 -270px;}}
@keyframes tn-rb-sway{
  0%  {transform:translate(-50%,-50%);}
  40% {transform:translate(calc(-50% + 3px),-50%);}
  72% {transform:translate(calc(-50% - 3px),-50%);}
  100%{transform:translate(calc(-50% + 2px),-50%);}
}
@keyframes tn-rb-shape{
  0%  {width:10px;height:10px;opacity:0.75;
       box-shadow:0 0 0 0 rgba(255,255,255,0),inset 0 0 0 0 rgba(255,255,255,0);animation-timing-function:cubic-bezier(.2,.6,.3,1);}
  20% {width:26px;height:26px;opacity:0.32;
       box-shadow:0 0 0 0 rgba(255,255,255,0),inset 0 0 0 0 rgba(255,255,255,0);animation-timing-function:ease-in-out;}
  72% {width:11px;height:11px;opacity:0.9;
       box-shadow:0 0 0 0 rgba(255,255,255,0),inset 2px 2px 3px -1px rgba(255,255,255,0.75);}
  87% {opacity:0.7;}
  100%{width:9px;height:9px;opacity:0;
       box-shadow:0 0 0 0 rgba(255,255,255,0),inset 2px 2px 3px -1px rgba(255,255,255,0.75);}
}
@keyframes tn-rb-shape-lg{
  0%  {width:14px;height:14px;opacity:0.85;
       box-shadow:0 0 0 0 rgba(255,255,255,0.16),inset 0 0 0 0 rgba(255,255,255,0);animation-timing-function:cubic-bezier(.2,.6,.3,1);}
  20% {width:34px;height:34px;opacity:0.36;
       box-shadow:0 0 0 5px rgba(255,255,255,0.16),inset 0 0 0 0 rgba(255,255,255,0);animation-timing-function:ease-in-out;}
  72% {width:14px;height:14px;opacity:0.95;
       box-shadow:0 0 0 0 rgba(255,255,255,0),inset 2px 2px 4px -1px rgba(255,255,255,0.8);}
  87% {opacity:0.75;}
  100%{width:12px;height:12px;opacity:0;
       box-shadow:0 0 0 0 rgba(255,255,255,0),inset 2px 2px 4px -1px rgba(255,255,255,0.8);}
}

/* Variant B: role changes tagged in the margin at the node (scratch page only) */
.tn-tag{display:none;}
.tn-spine--b .tn-tag{
  display:block;font-family:'HKGrotesk-bold','Helvetica','Arial',sans-serif;
  font-size:0.875em;line-height:1.25;color:var(--cs-accent-soft);margin-bottom:4px;
}
@media(min-width:992px){
  .tn-spine--b .tn-tag{position:absolute;right:calc(100% + 18px);top:0;white-space:nowrap;margin:0;}
}

/* Variant C: no rail, role changes set in the accent inline (scratch page only).
   Bronze #d37731 is 2.04:1 on this water, so this uses the palette's soft bronze (5.48:1+). */
.tn-spine--c .tn-beat{padding-left:0;}
.tn-spine--c:before,.tn-spine--c:after,.tn-spine--c .tn-beat:before,.tn-spine--c .tn-beat:after{display:none;}
.tn-spine--c .tn-role{color:var(--cs-accent-soft);font-family:'HKGrotesk-bold','Helvetica','Arial',sans-serif;}

/* ==========================================================================
   Environment: light rays, bubbles, creatures. All decorative, aria-hidden.
   ========================================================================== */
.tn-rays{
  /* sunlight raking down through the sky: full at the top, gone by the waterline */
  position:absolute;left:-10%;right:-10%;top:0;bottom:var(--tn-line-inset);
  background:repeating-linear-gradient(104deg,
    rgba(255,255,255,0) 0,
    rgba(255,255,255,0.15) 96px,
    rgba(255,255,255,0) 150px,
    rgba(255,255,255,0) 210px,
    rgba(255,255,255,0.09) 236px,
    rgba(255,255,255,0) 262px,
    rgba(255,255,255,0) 340px);
  -webkit-mask-image:linear-gradient(to bottom,#000 0,rgba(0,0,0,0.5) 45%,transparent 100%);
          mask-image:linear-gradient(to bottom,#000 0,rgba(0,0,0,0.5) 45%,transparent 100%);
  animation:tn-shimmer 11s ease-in-out infinite alternate;
}
@keyframes tn-shimmer{from{opacity:0.55;}to{opacity:1;}}

.tn-bub{
  position:absolute;left:var(--x);top:var(--y);width:var(--s);height:var(--s);
  border-radius:50%;border:1px solid rgba(255,255,255,0.6);
  background:radial-gradient(circle at 32% 30%,rgba(255,255,255,0.55),rgba(255,255,255,0) 60%);
  opacity:0;will-change:transform,opacity;
  animation:tn-rise var(--d) linear var(--delay) infinite;
}
@keyframes tn-rise{
  0%  {transform:translate3d(0,0,0);opacity:0;}
  12% {opacity:0.85;}
  85% {opacity:0.6;}
  100%{transform:translate3d(var(--wob),calc(var(--rise) * -1),0);opacity:0;}
}
/* pause anything that's well offscreen (JS marks segments near the viewport) */
.tn-js .tn-seg:not(.is-near) .tn-bub,
.tn-js .tn-seg:not(.is-near) .tn-rays,
.tn-js .tn-seg:not(.is-near) .tn-creature{animation-play-state:paused;}

/* Creatures live in the empty left column under the section heading, so they can
   never cross a text column. Below 992px the columns stack and they're hidden. */
.tn-creature{display:none;}
@media(min-width:992px){
  .tn-creature{display:block;margin-top:var(--depth,120px);will-change:transform;}
}
.tn-creature svg{display:block;width:100%;height:auto;}
.tn-fish{width:220px;animation:tn-drift-x 19s ease-in-out infinite alternate;}
.tn-fish path{fill:var(--tn-6);opacity:0.42;}
.tn-jelly{width:96px;margin-left:40px;animation:tn-drift-y 15s ease-in-out infinite alternate;}
.tn-jelly .bell{fill:rgba(255,255,255,0.16);}
.tn-jelly .tent{fill:none;stroke:rgba(255,255,255,0.16);stroke-width:2;stroke-linecap:round;}
.tn-ray{width:200px;animation:tn-drift-x 34s ease-in-out infinite alternate;}
.tn-ray path{fill:rgba(255,255,255,0.06);}
@keyframes tn-drift-x{from{transform:translate3d(-14px,0,0);}to{transform:translate3d(14px,-6px,0);}}
@keyframes tn-drift-y{from{transform:translate3d(0,-10px,0);}to{transform:translate3d(6px,10px,0);}}

/* ---------- Rise: underwater text drifts up and fades in as it scrolls in. Nothing
   above the waterline moves. js/tenure.js adds .tn-floaty (only with motion allowed +
   IntersectionObserver), marks elements .tn-float and sets .is-in once each enters. ---------- */
.tn-floaty .tn-float{opacity:0;transform:translate3d(0,28px,0);}
.tn-floaty .tn-float.is-in{animation:tn-rise-in 1.2s cubic-bezier(.22,.61,.36,1) var(--fd,0s) both;}
.tn-floaty .tn-float.is-rising{will-change:transform,opacity;}
@keyframes tn-rise-in{
  from{opacity:0;transform:translate3d(0,28px,0);}
  to  {opacity:1;transform:none;}
}

/* ---------- Reduced motion: the gradient stays, everything else holds still ---------- */
@media (prefers-reduced-motion: reduce){
  .tn-bub{display:none;}
  .tn-rays,.tn-creature{animation:none;}
  .tn-beat:after{animation:none !important;}
  .tn-float{animation:none !important;opacity:1 !important;transform:none !important;}
  .tn-float:before,.tn-float:after{display:none !important;}
}

/* ==========================================================================
   Scratch page only (scratch-spine.php)
   ========================================================================== */
.tn-scratch-label{font-family:'HKGrotesk-bold','Helvetica','Arial',sans-serif;font-size:0.875em;line-height:1.25;color:var(--cs-accent-soft);margin:0 0 8px;}
.tn-ramp{display:grid;grid-template-columns:1fr 1fr;gap:24px;max-width:760px;}
.tn-ramp-stops{display:flex;flex-direction:column;}
.tn-swatch{min-height:150px;padding:14px 16px;font-size:0.875em;line-height:1.35;display:flex;flex-direction:column;justify-content:flex-end;}
.tn-swatch b{font-size:1.125em;}
.tn-swatch code{font-family:var(--cs-mono);font-size:0.875em;}
.tn-ramp-strip{
  background-image:linear-gradient(to bottom,var(--tn-1) 0%,var(--tn-2) 9%,var(--tn-3) 12.5%,var(--tn-4) 25%,var(--tn-5) 37.5%,var(--tn-6) 50%,var(--tn-7) 62.5%,var(--tn-7a) 75%,var(--tn-7b) 87.5%,var(--tn-8) 100%);
  background-image:linear-gradient(in oklab to bottom,var(--tn-1) 0%,var(--tn-2) 9%,var(--tn-3) 12.5%,var(--tn-4) 25%,var(--tn-5) 37.5%,var(--tn-6) 50%,var(--tn-7) 62.5%,var(--tn-7a) 75%,var(--tn-7b) 87.5%,var(--tn-8) 100%);
}
@media(max-width:600px){.tn-ramp{grid-template-columns:1fr;}.tn-ramp-strip{min-height:400px;}}

/* ==========================================================================
   The dive (js/tenure-water.js). A fixed WebGL canvas behind the top three
   segments. html.tn-gl is only set once it has drawn a frame; until then (or
   without WebGL / with reduced motion) the CSS gradients above are the page.
   ========================================================================== */
.tn-gl-canvas{position:fixed;left:0;top:0;width:100%;height:100%;z-index:-1;pointer-events:none;display:block;visibility:hidden;}
.tn-gl .tn-gl-canvas{visibility:visible;}
.tn-gl .tn-seg--surface,
.tn-gl .tn-seg--shallows,
.tn-gl .tn-seg--cross{background:transparent;}
