/* =========================================================
   Cinema Skin FX — title card (front page)

   Ivory ground, a blurred palm shadow raking in from the top
   left, satin folds along the bottom, and the monogram drawing
   itself in above a stacked wordmark.

   The whole entrance is CSS on a delay chain: it plays with
   JavaScript disabled and stops dead under reduced motion.
   Pointer parallax and the cursor glow reuse the shared
   [data-parallax] / [data-spotlight] handlers in main.js.

   Self-contained — remove this file and the <section> and the
   page simply starts at the hero.
   ========================================================= */

.titlecard{
  --tc-ease:cubic-bezier(.16,.84,.44,1);
  --tc-ivory-1:#FBF8F1;
  --tc-ivory-2:#F4EEE1;
  --tc-ivory-3:#EBE2CF;
  --tc-word:#9A7820;   /* 3.4:1 on ivory — large display type only */
  --tc-tag:#7A5E1A;    /* 5.2:1 — safe for the small letterspaced line */
  --tc-header:var(--hdr-h);   /* shared with the header in styles.css */

  position:relative;
  min-height:calc(100vh + var(--tc-header));
  min-height:calc(100svh + var(--tc-header));
  display:grid;
  place-items:start center;
  overflow:hidden;
  isolation:isolate;

  /* The sticky header is a sibling in normal flow, so it would sit on a band
     above the card. Pull the card up under it and pad the content back down. */
  margin-top:calc(-1 * var(--tc-header));

  background:
    radial-gradient(90% 70% at 62% 34%, #FFFEFB 0%, rgba(255,254,251,0) 64%),
    linear-gradient(158deg, var(--tc-ivory-1) 0%, var(--tc-ivory-2) 52%, var(--tc-ivory-3) 100%);
}

/* ---------- Background ---------- */
/* ⚠️ NO BOX ANYWHERE BUT THE PHONE. The phone block turns this into the
   photograph's band and clips it, so the picture can travel inside it; here
   it generates no box at all, which means it cannot become the containing
   block for the absolutely-positioned .tc-photo and the desktop framing is
   byte for byte what it was. */
.tc-frame{display:contents;}
.tc-bg{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden;}

/* Layer order inside the card, back to front:
   video → veil → wash → palm shadow → silk → content */
/* The film. A 16:9 source in a landscape frame, so unlike the portrait still
   it is genuinely full-bleed. transform-origin/scale are left alone — the
   clip already carries its own push-in. */
.tc-film{
  display:none;   /* main.js turns it on; see is-film-on */
  position:absolute;left:0;top:50%;z-index:0;
  translate:0 -50%;

  /* Full width, natural height — NOT object-fit:cover. The callouts are baked
     into this clip near its left and right edges, and cropping the sides to
     fill a 3:2 frame shoves them hard against the viewport edge. Letting the
     ivory ground carry a band above and below keeps the composition the clip
     was built with, and reads as a letterbox, which suits the name. */
  width:100%;height:auto;
  opacity:0;

  /* ⚠️ NOTHING may be added here that has to run per frame — no filter, no
     mask, no clip-path, no blend mode. This element carried
     `filter:saturate(1.05) contrast(1.04)` and a mask-image feathering its two
     horizontal seams, and between them every single frame had to be uploaded
     as a texture, put through a full-frame filter pass and then a full-frame
     mask pass at 1920x1080, 24 times a second, before it could be composited.
     Decode was never the problem — the 1080 VP9 benchmarks at 16x realtime on
     one thread — but that compositing bill is paid on the visitor's GPU, so
     the worse their machine the worse it stuttered.

     The grade now lives in the pixels (baked at encode time with
     `eq=contrast=1.04:saturation=1.05`, which is exactly what the CSS
     shorthand computes), and the feather is .tc-fade, a static gradient
     sitting above the video. Both are free at playback. */
}
.titlecard.is-film-on .tc-film{
  display:block;
  animation:tcFade 1.6s var(--tc-ease) forwards;
}
/* ⚠️ The film does not move, and must not be given a scale or a drift again.
   A slow push was tried twice and rejected twice: the clip was stabilised at
   source precisely so the frame would sit still, and any scale on .tc-film
   has to be mirrored exactly on .tc-hot or every hover target slides off its
   baked box. The picture moves because it is a film. Nothing else moves it. */
/* The feather that used to be a mask on the video. Geometry copies .tc-film
   exactly, so the 9%/91% stops land on the same two seams they always did; it
   sits above the film (same z-index, later in the DOM) and below .tc-veil, so
   the veil still tints it the way it tinted the ground showing through before.

   The colours are the ground measured behind those seams, not guesses:
   #FBF8F1 at the top edge, #F0E9DB at the bottom. The transparent stops repeat
   the same RGB so the ramp does not fade through grey. Re-measure if the card
   background changes. */
.tc-fade{
  display:none;
  position:absolute;left:0;top:50%;z-index:0;
  translate:0 -50%;
  width:100%;
  aspect-ratio:16 / 9;   /* must match .tc-film */
  pointer-events:none;
  background:linear-gradient(180deg,
    #FBF8F1               0%,
    rgba(251,248,241,0)   9%,
    rgba(240,233,219,0)  91%,
    #F0E9DB             100%);
}
.titlecard.is-film-on .tc-fade{display:block;}

.titlecard.is-film-on .tc-photo{display:none;}

/* The still fallback. Unused while .has-film is on, kept because it is the
   one-line way back: drop `has-film` and swap the <video> for the <img>. */
.tc-photo{
  position:absolute;
  top:var(--tc-photo-y,2.5%);left:50%;z-index:0;
  translate:-50% 0;

  /* Sized off the HEIGHT, not stretched edge to edge. The source is a 4:5
     portrait; covering a landscape frame with it would scale the subject to
     roughly 1.5x the size the reference shows. At 120% of the fold her eye
     line lands at 42% down the viewport and her face holds the right scale,
     with the ivory ground carrying the rest of the frame. Framing knobs:
     --tc-photo-h zooms, --tc-photo-y drops her down the frame, --tc-photo-x
     slides her sideways. At the values below her eye line sits 42% down the
     viewport, which is where the reference frame puts it. */
  height:var(--tc-photo-h,112%);
  width:auto;max-width:none;
  margin-left:var(--tc-photo-x,0px);

  /* Feather all three exposed seams so the photo dissolves into the ground
     instead of ending on a hard edge. Two gradients intersected: the sides,
     and the top edge where it is held off the fold. */
  -webkit-mask-image:
    linear-gradient(90deg,transparent 0,#000 13%,#000 87%,transparent 100%),
    linear-gradient(180deg,transparent 0,#000 7%);
  mask-image:
    linear-gradient(90deg,transparent 0,#000 13%,#000 87%,transparent 100%),
    linear-gradient(180deg,transparent 0,#000 7%);
  -webkit-mask-composite:source-in;
  mask-composite:intersect;

  /* The shot is already warm, so this only lifts it — no added sepia. */
  filter:saturate(.94) brightness(1.04) contrast(.97);
  opacity:0;
  animation:tcFade 2.4s var(--tc-ease) .15s forwards;
}
/* Where the lockup sits, as a share of the card. The film-state scrim reads
   these so it follows the lockup when the wide layout moves it off centre. */
.titlecard{ --lock-x:50%; --lock-y:21%; }

.tc-veil{
  position:absolute;inset:0;z-index:1;
  background:
    radial-gradient(56% 26% at 50% 6%,
      rgba(252,249,243,.94) 0%,
      rgba(251,248,241,.72) 46%,
      rgba(249,244,233,.28) 78%,
      rgba(246,240,227,0) 100%),
    linear-gradient(180deg,
      rgba(251,247,238,.34) 0%,
      rgba(248,242,231,.14) 38%,
      rgba(246,239,226,.20) 66%,
      rgba(238,229,211,.52) 100%);
}
.tc-wash{z-index:2;}
.tc-frond{z-index:3;}
.tc-silk{z-index:4;}


/* A slow warm wash so the ground never reads flat */
.tc-wash{
  position:absolute;inset:-10%;
  background:
    radial-gradient(38% 46% at 24% 22%, rgba(226,211,181,.42) 0%, rgba(226,211,181,0) 70%),
    radial-gradient(44% 38% at 82% 68%, rgba(255,253,247,.85) 0%, rgba(255,253,247,0) 72%);
  opacity:0;
  animation:tcWashIn 2.4s var(--tc-ease) .05s forwards;
}
@keyframes tcWashIn{ to{opacity:var(--wash-o,1);} 
}
@keyframes tcFade{ to{opacity:1;} }

/* A slow push-in for the upright card, where the film cannot run.
   ⚠️ It names the SCALE property and nothing else on purpose: .tc-photo already carries
     translate:-50% 0, and translate / rotate / scale are separate properties
     that compose, so this cannot quietly cancel the centring the way a
     transform shorthand would. */
@keyframes tcBreathe{ to{ scale:1.045; } }
/* The phone band's camera move: a push-in with a slow settle down and to the
   right, which is what the desktop film does and the phone cannot have.
   Compositor-only properties, on a layer that is already promoted.

   ⚠️ THE DRIFT GOES DOWN ON PURPOSE, AND THE SCALE STOPS AT 8.5%. This
   element IS the band — there is no frame around it — so scaling it grows its
   box past the band at BOTH ends, and its top edge is the hard one: it opens
   at 13.5% of the card with the tagline's ink ending 31px above it. About an
   origin of 41.5%, a 10% push with an upward drift put the picture's top edge
   23px into that cream, leaving 8px under the tagline. 8.5% with the drift
   reversed costs 11.6px of it instead and keeps 19. Measured at the extreme,
   not reasoned about. */
@keyframes tcPhoneFilm{ to{ scale:1.20; translate:-2.6% -2%; } }
/* The same move for a short phone, where the band is 348px instead of 426
   and opens only 20px under the tagline instead of 31. At the full 8.5% the
   picture crept 9.5px into that and left 10.5px of cream; this leaves 14.8.
   A little more of the travel is spent going down rather than growing. */
@keyframes tcPhoneFilmShort{ to{ scale:1.17; translate:-2.2% -1.7%; } }

/* the phone front screen's entrance, sheen and glint */
@keyframes tcRise{ from{opacity:0;translate:0 14px;} to{opacity:1;translate:0 0;} }
@keyframes tcSheen{ 0%{translate:-120% 0;} 14%{translate:120% 0;} 100%{translate:120% 0;} }
@keyframes tcGlint{ 0%{translate:-70% 0;opacity:0;} 12%{opacity:1;} 34%{translate:70% 0;opacity:0;} 100%{translate:70% 0;opacity:0;} }

/* ---------- Palm shadow ---------- */
.tc-frond{
  position:absolute;
  color:#9C8B6E;
  fill:currentColor;
  pointer-events:none;
}
.tc-frond-a{
  top:-16%;left:-13%;
  width:min(62vw,760px);
  opacity:0;
  filter:blur(7px);
  scale:.94;
  animation:tcFrondA 3.4s var(--tc-ease) .25s forwards;
}
.tc-frond-b{
  top:-24%;left:4%;
  width:min(44vw,540px);
  opacity:0;
  filter:blur(13px);
  scale:.96;
  animation:tcFrondB 3.4s var(--tc-ease) .5s forwards;
}
@keyframes tcFrondA{
  from{opacity:0;scale:.94;}
  to  {opacity:var(--frond-a,.12);scale:1;}
}
@keyframes tcFrondB{
  from{opacity:0;scale:.96;}
  to  {opacity:var(--frond-b,.07);scale:1;}
}

/* ---------- Silk ---------- */
.tc-silk{
  position:absolute;left:-4%;right:-4%;bottom:-2%;
  width:108%;
  /* ⚠️ WITHOUT THIS THE SILK STOPS 16px SHORT OF THE RIGHT EDGE. This is an
     <svg>, and styles.css carries `img,svg{max-width:100%}`, which clamps the
     108% back to 100%. left is still honoured, so the whole overhang lands on
     the LEFT and the right edge falls short — measured at 393: left -15.72,
     width 393 instead of 424.4, right edge 377.3. The bare wash in that strip
     read as a pale band down the card and was reported as exactly that.
     max-width:none rather than width:auto: the clamp applies to the used width
     however it is arrived at, so stretching with left/right hits it too, and a
     replaced element may take its intrinsic size instead of stretching.
     Overhanging is safe — .titlecard is overflow:hidden, as this file says
     further down: "no child can bleed out". */
  max-width:none;
  height:min(44%,360px);
  opacity:0;
  animation:tcSilk 2.2s var(--tc-ease) .55s forwards;
}
.tc-w{transform-box:view-box;transform-origin:50% 100%;}
/* The folds are drawn, not animated. They undulated on four offset loops back
   when this sat on an empty ivory ground and had to earn its texture; over a
   photograph that is just the bottom of the frame refusing to hold still. */
.tc-w1{filter:blur(2.5px);opacity:.85;}
.tc-w2{filter:blur(1.4px);opacity:.92;}
.tc-w3{filter:blur(.6px);}
@keyframes tcSilk{ to{opacity:var(--silk-o,.58);} }
/* Satin highlight riding the crests */
.tc-sheen{
  fill:none;
  stroke:rgba(255,255,255,.92);
  stroke-width:3;
  filter:blur(3px);
  opacity:0;
  animation:tcSheen 2.6s var(--tc-ease) 1.1s forwards;
}
.tc-sheen-2{stroke-width:2;animation-delay:1.35s;}
@keyframes tcSheen{ to{opacity:.75;} }

/* ---------- Content ---------- */
.tc-content{
  position:relative;z-index:2;
  display:flex;flex-direction:column;align-items:center;
  padding:clamp(20px,3.2vh,40px) var(--gutter) 0;
  text-align:center;
  pointer-events:none;   /* the burger and shop pill sit on the same band */
}

/* Monogram */
.tc-mark{
  width:clamp(44px,4.4vw,62px);
  height:auto;
  margin-bottom:clamp(6px,1vh,12px);
  overflow:visible;
  filter:
    drop-shadow(0 0 22px rgba(255,252,244,.95))
    drop-shadow(0 0 46px rgba(255,252,244,.6))
    drop-shadow(0 5px 16px rgba(154,120,32,.3));
}
.tc-spin{
  transform-box:view-box;
  transform-origin:100px 100px;
  animation:
    tcSpin 2.4s var(--tc-ease) forwards,
    tcMarkGlint 6s var(--tc-ease) 3.4s infinite;
}
/* Explicit identity values rather than `none` so the filter list interpolates. */
@keyframes tcMarkGlint{
  0%, 10%, 34%, 100%{filter:drop-shadow(0 0 0 rgba(255,244,205,0)) brightness(1);}
  20%               {filter:drop-shadow(0 0 11px rgba(255,244,205,.95)) brightness(1.16);}
}
@keyframes tcSpin{
  from{transform:rotate(-46deg);}
  to  {transform:rotate(0deg);}
}
.tc-arc{
  fill:none;
  stroke:url(#gGold);
  stroke-linecap:butt;
  stroke-dasharray:0 100;
  opacity:0;

  /* The rotate here composes with each arc's own transform="rotate(a 100 100)"
     attribute. Both turn about the same centre, so they simply add. */
  transform-box:view-box;
  transform-origin:100px 100px;
  rotate:var(--base,0deg);

  animation:
    tcArc 1.7s var(--tc-ease) forwards,
    tcSwirl 7.5s linear infinite;
  animation-delay:
    calc(.2s + var(--a,0) * .17s),
    calc(4.6s + var(--a,0) * .09s);
}

/* Each arc opens toward a full ring, turns a whole number of times so it lands
   back in register, swings a few degrees past, settles, then holds. The timing
   function is set per segment rather than on the animation, so the wind-up,
   the travel and the settle each get their own curve instead of all three
   easing identically. */
@keyframes tcSwirl{
  0%, 10%{
    rotate:var(--base);
    stroke-dasharray:var(--dash);
    animation-timing-function:cubic-bezier(.6,0,.75,.25);     /* wind up */
  }
  42%{
    rotate:calc(var(--base) + var(--turn) * .40);
    stroke-dasharray:var(--open);
    animation-timing-function:cubic-bezier(.25,.6,.35,1);     /* travel */
  }
  62%{
    rotate:calc(var(--base) + var(--turn) + var(--over));
    stroke-dasharray:var(--dash);
    animation-timing-function:cubic-bezier(.3,.9,.4,1);       /* settle back */
  }
  76%, 100%{
    rotate:calc(var(--base) + var(--turn));
    stroke-dasharray:var(--dash);
  }
}
@keyframes tcArc{
  0%  {opacity:0;stroke-dasharray:0 100;}
  28% {opacity:1;}
  100%{opacity:1;stroke-dasharray:var(--dash);}
}

/* Wordmark — stacked, each line wiping open in turn.
   A clip-path wipe (not per-letter opacity) is what keeps the gold gradient:
   background-clip:text paints the background once on the parent, so animating
   opacity on child spans would break the clip. */
.tc-word{
  /* The keyline, on the parent so it composites behind the clipped gold.
     .is-film-on strengthens it — over a photograph it has more to fight. */
  filter:
    drop-shadow(0 0 1.2px rgba(46,33,6,.55))
    drop-shadow(0 1px 3px rgba(46,33,6,.34));

  display:flex;flex-direction:column;align-items:center;
  gap:clamp(2px,.5vh,6px);
  margin-bottom:clamp(7px,1vh,11px);
  font-family:var(--f-display);
  font-weight:400;
  line-height:1.02;
  text-transform:uppercase;
  color:var(--tc-word);
}
.tc-line{
  display:block;

  /* Two clipped layers: a highlight band that travels, over the gold ramp.
     background-clip:text clips every layer, so the sweep only ever shows
     inside the letterforms. The ramp lives in a variable because the film
     state swaps it for a darker one — see the contrast note below. */
  --gold:linear-gradient(101deg,
    #9A7820 0%, #C4A047 18%, #EFDDA3 40%, #C39C3B 58%, #A17F24 78%, #8E6F1D 100%);
  --shine:linear-gradient(102deg,
    rgba(255,255,255,0)   43%,
    rgba(255,255,255,.74) 48.5%,
    rgba(255,250,231,.60) 51%,
    rgba(255,255,255,0)   57%);

  /* A standing highlight across the top of every letter — the emboss you get
     on struck foil. It is a background layer rather than a shadow for the
     reason spelled out below; being clipped to the text, it can only ever
     brighten the letterform, never spill around it. */
  --bevel:linear-gradient(180deg,
    rgba(255,251,232,.40) 0%,
    rgba(255,251,232,0)   26%);

  background-image:var(--shine), var(--bevel), var(--gold);
  background-size:200% 100%, 100% 100%, 230% 100%;
  background-position:-70% 0, 0 0, var(--foil-a,82%) 0;
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  clip-path:inset(0 102% 0 -2%);
  /* No text-shadow here, on either path — see the warning by the film-state
     keyline below. The cream halo that used to sit here was washing the gold
     it was meant to lift. Both paths show a photograph now, so both get the
     dark keyline instead; it lives on .tc-word, the parent, as a filter. */
}
.tc-line-1{
  font-size:clamp(25px,3.4vw,46px);
  letter-spacing:.07em;
  animation:tcWipe 1.35s var(--tc-ease) 1s forwards,
             tcShine 5s cubic-bezier(.36,0,.2,1) 5s infinite;
}
.tc-line-2{
  font-size:clamp(18px,2.4vw,33px);
  letter-spacing:.16em;
  text-indent:.16em;
  animation:tcWipe 1.35s var(--tc-ease) 1.32s forwards,
             tcShine 5s cubic-bezier(.36,0,.2,1) 5.7s infinite;
}
@keyframes tcWipe{
  from{clip-path:inset(0 102% 0 -2%);}
  to  {clip-path:inset(0 -2% 0 -2%);}
}
/* Three layers now, so three positions. Only the first moves. */
@keyframes tcShine{
  0%,   7%{background-position:-70% 0, 0 0, var(--foil-a,82%) 0;}
  30%, 100%{background-position:200% 0, 0 0, var(--foil-a,82%) 0;}
}
/* ⚠️ THE LOCKUP DOES ANSWER THE POINTER NOW, AND THIS NOTE USED TO SAY THE
   OPPOSITE. It read: "No :hover on the lockup. It is a wordmark, not a
   control — nothing here is clickable, so nothing here should answer the
   pointer." That was a defensible rule about affordance and it was overruled
   on request — "make everything here interactive ... once i hover my mouse to
   them". The states are at the foot of this file, under the banner
   THE FRONT SCREEN ANSWERS THE POINTER — gated on (hover:hover), so a phone
   never resolves one. Nothing here became clickable; it only became
   responsive. */

/* Hairline, drawn outward from the centre */
.tc-rule{
  display:block;
  width:min(132px,26vw);height:1px;
  margin-bottom:clamp(6px,.9vh,9px);
  background:linear-gradient(90deg,rgba(154,120,32,0),rgba(154,120,32,.75),rgba(154,120,32,0));
  box-shadow:0 0 12px rgba(255,252,244,.9);
  scale:0 1;
  animation:tcRule 1.3s var(--tc-ease) 1.95s forwards;
}
@keyframes tcRule{ to{scale:1 1;} }

/* Tagline — letter-spacing settles inward as it fades up */
.tc-tag{
  font-family:var(--f-body);
  font-size:clamp(7.5px,.78vw,10px);
  font-weight:500;
  text-transform:uppercase;
  color:var(--tc-tag);
  letter-spacing:.6em;
  text-indent:.6em;
  text-shadow:0 1px 10px rgba(255,252,244,.95), 0 0 26px rgba(255,252,244,.7);
  opacity:0;
  animation:tcTag 1.6s var(--tc-ease) 2.15s forwards;
}
@keyframes tcTag{
  from{opacity:0;letter-spacing:.6em;translate:0 8px;}
  to  {opacity:1;letter-spacing:.3em;translate:0 0;}
}
/* The same settle, landing on the phone's tracking instead of the desktop's.
   See the note in the max-width:700px block. */
@keyframes tcTagSm{
  from{opacity:0;letter-spacing:.44em;translate:0 8px;}
  to  {opacity:1;letter-spacing:.22em;translate:0 0;}
}

/* ---------- Scroll cue ---------- */
.tc-cue{
  position:absolute;left:50%;bottom:clamp(16px,3.6vh,30px);z-index:2;
  translate:-50% 0;
  display:flex;flex-direction:column;align-items:center;gap:9px;
  color:var(--tc-tag);
  opacity:0;
  animation:tcCue 1.2s var(--tc-ease) 3s forwards;
  transition:color .3s var(--tc-ease);
}
.tc-cue:hover{color:#5F4912;}
@keyframes tcCue{ to{opacity:1;} }
.tc-cue-text{font-size:8.5px;letter-spacing:.28em;text-transform:uppercase;font-weight:600;}
.tc-cue-spark{
  width:9px;height:9px;
  background:currentColor;
  clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%);
  opacity:.85;
  animation:tcTwinkle 3.6s var(--tc-ease) infinite;
}
.tc-cue-line{
  width:1px;height:42px;
  background:linear-gradient(180deg,rgba(154,120,34,0),rgba(154,120,34,.5));
  position:relative;overflow:hidden;
}
.tc-cue-line::after{
  content:"";position:absolute;left:0;top:0;width:1px;height:14px;
  background:#9A7820;
  animation:tcCueRun 2.4s var(--tc-ease) infinite;
  will-change:transform;
}
/* ⚠️ transform, NOT top. This runs forever, on the one screen that also has
   the hero film on it, and animating 'top' puts a layout pass in every single
   frame. The film was dropping ~33% of its frames; this was part of why.
   translateY is identical on screen and costs the compositor alone. */
@keyframes tcCueRun{
  0%  {transform:translateY(-14px);opacity:0;}
  35% {opacity:1;}
  100%{transform:translateY(42px);opacity:0;}
}


/* =========================================================
   Clarity while the film is up

   The veil, wash, silk and palm shadow exist to stop an empty ivory ground
   reading flat. Over a photograph they are just haze — which is what made
   the front page look soft. Each one drops back here, and the veil pool
   moves from the top centre to the left, where the lockup now sits, so her
   face is left alone.
   ========================================================= */
.titlecard.is-film-on{
  --wash-o:.30;
  --silk-o:.30;
  --frond-a:.05;
  --frond-b:.03;
}
/* Over the film the lockup needs separation, and there are only two levers:
   the gold or the ground. Taking the gold down is what turned the wordmark
   olive — at that point it is not the brand's gold any more, which is the
   whole reason it came back. So the ground moves instead.

   Which direction depends on the gold. A DARK scrim behind pale gold was
   measured and it is the wrong way round on this film: the frame is a bright
   wall, the gold sat lighter than the scrim, and the two converged at 1.3:1.
   Lifting the ground under DEEP gold is the way that works here — the wall is
   already bright, so the pool only has to finish what it started. The pool
   follows the lockup through --lock-x / --lock-y. */
.titlecard.is-film-on .tc-veil{
  background:
    radial-gradient(34% 30% at var(--lock-x) var(--lock-y),
      rgba(255,253,246,.93) 0%,
      rgba(254,251,242,.71) 44%,
      rgba(252,247,235,.24) 74%,
      rgba(250,245,232,0)  100%),
    linear-gradient(180deg,
      rgba(251,247,238,.12) 0%,
      rgba(248,242,231,0)   38%,
      rgba(238,229,211,.20) 100%);
}

/* ⚠️ THE LOCKUP'S COLOUR IS THE BRAND'S, NOT A CONTRAST DIAL.

   The film state used to solve legibility by taking the gold down — a ramp of
   #5A4308 → #A6853A → #503B06, plus brightness(.76) on the monogram. It
   measured fine and it was wrong: at that point the wordmark is olive, and a
   wordmark in the wrong colour is a wordmark that is wrong. It came back to
   the brand golds and must stay there.

   Both other levers were measured on the real film frame, sampling the
   composited pixels through a glyph mask (thin serif strokes and a keyline
   make percentile sampling useless here):

     darkened gold, no pool         CINEMA 2.95:1   monogram 1.99:1
     brand gold + DARK scrim        CINEMA 1.30:1   ← the trap
     brand gold + lifted pool       CINEMA 3.29:1   monogram 2.59:1

   The dark scrim looks like the obvious move and is backwards on this film:
   the frame is a bright wall, so bright gold ends up LIGHTER than its own
   scrim and the two converge. The wall is already bright — lift it the rest
   of the way instead and let deep gold sit on it. That is what the pool above
   does, and why the ramp below is weighted to the deep half of the brand
   golds rather than the pale half.

   Re-measure if the film is ever recut. A darker frame flips which lever
   works, and the numbers above are for this one. */
.titlecard.is-film-on{
  /* The same slice of the ramp as the ivory state. It used to shift darker
     here; the pool does that job now. */
  --foil-a:82%;
}
/* The film ramp is the brand's own golds — `--gold-accent` through
   `--gold-ink` — weighted to the deep half, because on a bright ground the
   pale half of a metallic ramp does not read as a highlight, it reads as a
   hole. The highlight comes back as the sweep instead, which is how metal
   actually catches light. */
.titlecard.is-film-on .tc-line{
  --gold:linear-gradient(101deg,
    #6A4F13 0%, #90701D 16%, #C29F4B 38%, #A18029 56%, #83661D 76%, #6B5112 100%);

  /* Tight and warm rather than near-white: a wide white core on gold this
     deep bleaches the letterform instead of lighting it. */
  --shine:linear-gradient(102deg,
    rgba(255,255,255,0)   42%,
    rgba(255,240,199,.5)  47%,
    rgba(255,248,226,.82) 50%,
    rgba(255,241,205,.46) 53.5%,
    rgba(255,255,255,0)   58%);
  --bevel:linear-gradient(180deg,
    rgba(255,247,216,.52) 0%,
    rgba(255,247,216,0)   30%);
}
.titlecard.is-film-on .tc-tag{color:#5E4712;}

/* The cream halo was there to lift the type off an ivory ground, where it is
   invisible. Over a photograph it paints a pale plate behind each word and
   eats the contrast it was supposed to protect — CINEMA was disappearing into
   it. Swap it for a soft dark lift, which does the same job in the other
   direction and reads as depth rather than fog. */
/* ⚠️ .tc-line CANNOT USE text-shadow. Its fill is transparent — the gold is a
   background clipped to the glyph — and paint order is background, then text
   shadows, then text. With nothing opaque in the text layer to cover them, the
   shadows paint straight OVER the gold instead of behind it. A tight keyline
   tried here turned CINEMA into flat olive-grey and dropped it from 3.24:1 to
   2.20:1: the fix made it worse, and looked like a gradient bug.

   The keyline goes on the PARENT as a filter instead. drop-shadow works off the
   subtree's alpha silhouette — which for background-clip:text is exactly the
   gold glyph — and composites behind it, where a shadow belongs. It lives on
   .tc-word rather than .tc-line because .tc-line is clipped by the tcWipe
   clip-path, which would cut the shadow off 2% out from the text.

   Anything opaque — .tc-tag, and the SVG monogram — is free to use the normal
   text-shadow / drop-shadow route. This warning is only about the two lines. */
.titlecard.is-film-on .tc-word{
  filter:
    drop-shadow(0 0 1.1px rgba(46,33,6,.5))
    drop-shadow(0 1px 3px rgba(46,33,6,.34))
    drop-shadow(0 5px 20px rgba(46,33,6,.22));
}
.titlecard.is-film-on .tc-tag{
  text-shadow:
    0 0 1.5px  rgba(46,33,6,.7),
    0 1px 3px  rgba(46,33,6,.45);
}
/* The monogram keeps its own gold — #gGold, shared with the product symbols
   elsewhere on the page. It used to be run through brightness(.76), which is
   the same mistake as the ramp: it separated by making the mark not-gold. The
   scrim behind it does that job now; all this adds is the keyline. */
/* The monogram keeps its own gold — #gGold, shared with the product symbols
   elsewhere on the page. It used to be run through brightness(.76), which is
   the same mistake as the ramp: it separated by making the mark not-gold. The
   scrim behind it does that job now; all this adds is the keyline. */
.titlecard.is-film-on .tc-mark{
  filter:
    saturate(1.16) brightness(.8)
    drop-shadow(0 0 1.4px rgba(46,33,6,.85))
    drop-shadow(0 1px 3px rgba(46,33,6,.5))
    drop-shadow(0 3px 14px rgba(46,33,6,.3));
}
.titlecard.is-film-on .tc-rule{
  box-shadow:0 1px 2px rgba(46,33,6,.45);
  background:linear-gradient(90deg,
    rgba(198,164,85,0), rgba(214,182,106,.95), rgba(198,164,85,0));
}

/* =========================================================
   Wide screens: the lockup moves off the subject

   With the film up, the left of the frame is plain backdrop, so the lockup
   sits there rather than on top of her. Gated on the same 7/5 aspect as the
   film — below it the subject fills the frame and the lockup goes back to
   the top, where there is still room for it.
   ========================================================= */
@media (min-aspect-ratio:7/5){
  .titlecard{ --lock-x:17%; --lock-y:28%; }
  .tc-content{
    position:absolute;
    left:17%;top:27svh;
    translate:-50% -50%;
    padding:0;
    width:max-content;max-width:38vw;
  }
  .tc-mark{width:clamp(60px,5.1vw,94px);margin-bottom:clamp(12px,1.6vh,21px);}
  .tc-line-1{font-size:clamp(34px,3.8vw,67px);}
  .tc-line-2{font-size:clamp(24px,2.68vw,47px);}
  .tc-rule{width:min(194px,13.8vw);margin-bottom:clamp(10px,1.4vh,15px);}
  .tc-tag{font-size:clamp(9.5px,.86vw,13.5px);}
}

/* Dust reads as nothing against a photograph at the weight it needs on an
   empty ivory ground. box-shadow rather than a filter — a filter on the
   container would composite all sixteen every frame. */
.titlecard.is-film-on .tc-motes i{
  scale:1.45;
  box-shadow:0 0 7px rgba(255,247,222,.6);
}

/* =========================================================
   Hover targets over the film

   The film has the callouts baked into it, so there is nothing to hover.
   These are invisible hit areas pinned over each baked box, and everything
   they draw is ADDITIVE — the baked box stays the box and never doubles.

   Hovering one runs three things, staggered:
     .tc-hot-ring   a frame opens outward from exactly the baked box's edge
     .tc-hot-comet  a light runs around that frame, continuously
     .tc-hot-fact   a card unfolds under the baked label with the fact

   ⚠️ Nothing here may touch the PICTURE. A lens that brightened the skin
   inside the frame and a veil that settled the rest of the shot back were
   both built and both cut: hovering must not restate the photograph, only
   draw over it. No backdrop-filter, no blur, no tint, on any of these.

   The layer copies .tc-film geometry exactly (full width, 16/9, centred),
   and each spot spans the whole layer, so --l/--t/--w/--h, --fl/--ft and
   --cx/--cy are all plain percentages of the frame and stay aligned at any
   viewport. Measured off assets/video/hero-poster.jpg at 1920x1080 —
   re-measure them if the clip is replaced.
   ========================================================= */
.tc-hot{
  display:none;
  position:absolute;left:0;top:50%;z-index:1;
  translate:0 -50%;
  width:100%;
  aspect-ratio:16 / 9;   /* must match .tc-film */
  pointer-events:none;
}
.titlecard.is-film-on .tc-hot{display:block;}

/* Full-frame, so its children can be placed anywhere in the frame. It takes
   no pointer events itself — only .tc-hot-box does — but :hover still
   propagates up from the box, which is what drives everything else here. */
.tc-hot-spot{position:absolute;inset:0;pointer-events:none;}

.tc-hot-box{
  position:absolute;
  left:var(--l);top:var(--t);
  width:var(--w);height:var(--h);
  pointer-events:auto;
  cursor:crosshair;   /* something is here, but it is not a link */
}

/* --- the frame that opens outward -------------------------------------
   It rests exactly on the baked box's edge and expands past it, so the baked
   box reads as the thing being opened rather than as a second, smaller box.
   ease-out-expo: nearly all the travel happens up front, then it glides. */
.tc-hot-ring{
  position:absolute;inset:0;
  border-radius:8%;
  /* .55, not near-white: the comet below has to read as a light RUNNING the
     outline, and against a fully lit outline it is invisible. */
  box-shadow:inset 0 0 0 1.5px rgba(255,252,243,.55);
  filter:drop-shadow(0 0 6px rgba(255,246,220,.85))
         drop-shadow(0 0 17px rgba(255,238,196,.45));
  opacity:0;
  scale:1;
  transition:opacity .3s var(--tc-ease),
             scale .62s cubic-bezier(.16,1,.3,1);
  pointer-events:none;
}
.tc-hot-box:hover .tc-hot-ring{opacity:1;scale:1.24;}

/* The light that runs the outline.

   A conic gradient cannot be spun by rotating its own element — the element
   is a rounded rectangle, so rotating it turns the shape, not just the
   light. Instead an oversized SQUARE child carries the gradient and rotates,
   and this element masks everything but a 1.6px band around its edge. 160%
   so the square's corners still cover the box at 45 degrees. The two mask
   layers minus each other (content-box minus border-box) are what cut the
   band; -webkit-mask-composite:xor is the same thing for Safari.

   The filter lives on .tc-hot-ring, the parent: filter is applied before
   mask within an element, so a drop-shadow here would glow the whole square
   and then be masked away. On the parent it glows the finished band. */
.tc-hot-comet{
  position:absolute;inset:0;
  border-radius:inherit;
  padding:1.7px;
  overflow:hidden;
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite:exclude;
  pointer-events:none;
}
.tc-hot-comet::before{
  content:"";
  position:absolute;left:-30%;top:-30%;width:160%;height:160%;
  background:conic-gradient(from 0turn at 50% 50%,
    rgba(255,247,220,0)    0turn .42turn,
    rgba(255,250,232,.34)  .70turn,
    rgba(255,253,243,.86)  .88turn,
    #ffffff                .955turn,
    rgba(255,250,232,.48)  .985turn,
    rgba(255,247,220,0)    1turn);
  animation:tcHotComet 2.4s linear infinite;
  animation-play-state:paused;   /* parked until hovered */
}
.tc-hot-box:hover .tc-hot-comet::before{animation-play-state:running;}
@keyframes tcHotComet{ to{rotate:1turn;} }

/* --- the fact card ----------------------------------------------------
   Pinned under the baked label and inset by its own padding, so the card's
   TEXT lines up with the baked label's left edge rather than the card's box
   does. It unfolds from that top-left corner, a beat after the frame opens.

   It carries a plate because it has to: the four fact areas run from mean
   luminance 202 (blown-out backdrop) to 59 (her hair), and no single ink
   colour clears 4.5:1 across that range. The plate flattens the range, and
   #4E3B10 then holds about 8:1 on every one of them. */
/* ⚠️ 16% IS A DESKTOP NUMBER. It is 224px in a 1400px frame and 63px on a
   phone — narrow enough to set one word per line, which is exactly what a
   device photograph of this card showed. The layer is display:none unless the
   film is playing and the film only runs on wide screens, so this should be
   unreachable on a phone; it is capped in the narrow block below anyway,
   because "should be unreachable" is not a width. */
.tc-hot-fact{
  position:absolute;
  left:var(--fl);top:var(--ft);
  width:var(--fw,16%);
  display:block;
  padding:clamp(9px,.72vw,14px) clamp(10px,.86vw,17px);
  border-radius:clamp(6px,.5vw,10px);
  /* Opaque enough to need no backdrop-filter. It carried a blur so a lighter
     plate could still hold contrast over her hair; the blur read as the shot
     going soft behind the card, so the plate does the whole job instead. */
  background:rgba(255,251,243,.96);
  box-shadow:0 6px 26px rgba(40,30,12,.15),
             inset 0 0 0 1px rgba(154,120,34,.18);
  text-align:left;
  opacity:0;
  scale:.9;
  translate:0 6px;
  transform-origin:0 0;
  transition:opacity .34s var(--tc-ease),
             scale .5s cubic-bezier(.16,1,.3,1),
             translate .5s cubic-bezier(.16,1,.3,1);
  pointer-events:none;
}
.tc-hot-spot:hover .tc-hot-fact{
  opacity:1;scale:1;translate:0 0;
  transition-delay:.11s;   /* the frame opens first, then this unfolds */
}
.tc-hot-fact b{
  display:block;
  margin-bottom:.42em;
  color:#7A5E1A;   /* 4.6:1 on the plate */
  font-family:var(--f-body);
  font-size:clamp(7px,.58vw,11px);
  font-weight:600;
  letter-spacing:.22em;
  text-transform:uppercase;
}
.tc-hot-fact span{
  display:block;
  color:#4E3B10;   /* 8:1 on the plate */
  font-family:var(--f-body);
  font-size:clamp(10px,.88vw,17.5px);
  font-weight:400;
  line-height:1.5;
  letter-spacing:.005em;
}

/* =========================================================
   Callouts vs. the film

   The clip was generated from a screenshot of this page, so it already
   has the four callouts painted into it. Drawing ours on top would double
   them, and they cannot be aligned because the clip pushes in.

   Cropping does not save us. Narrowing the frame takes the baked LABELS
   off screen but leaves the baked BOXES in the middle of it, blown up — so
   a phone would show our labelled callouts next to four orphan squares.
   There is no viewport where both sets can coexist.

   So it is one or the other, and main.js picks: the film on frames wider
   than 7/5, the still everywhere else and under reduced motion. `is-film-on`
   is only set once the clip is actually going in, so a failed load or a
   phone still gets the still with our live, interactive callouts.

   opacity — not display:none — so the label text stays in the accessibility
   tree and in the markup for search engines even while the film is up.
   ========================================================= */
.titlecard.is-film-on .tc-notes{opacity:0;pointer-events:none;}

/* ⚠️ ...and the notes themselves, or the film's callouts cannot be reached.

   pointer-events:none on the LAYER above does not survive .tc-note setting
   pointer-events:auto back on the marks inside it. So with the film up, four
   invisible marks sat directly over the four .tc-hot-box hit areas and ate
   every pointer aimed at them — .tc-hot and .tc-notes are both z-index 1 and
   .tc-notes comes later in the markup, so it wins the hit test.

   Measured at 1440x900 with a real pointer: elementFromPoint over the first
   hot box returned span.tc-box inside div.tc-note, :hover never reached the
   box, and the fact card stayed at opacity 0. The hover facts on the film
   have never opened. Same block on a phone in landscape, where the film is
   what is playing and a tap is what is aimed at it. */
.titlecard.is-film-on .tc-note{pointer-events:none;}

/* Pause control. WCAG 2.2.2 — the loop never stops on its own. */
.tc-vidbtn{
  display:none;   /* .is-film-on turns it on */
  position:absolute;right:var(--gutter);bottom:clamp(16px,3.6vh,30px);z-index:3;
  align-items:center;gap:7px;
  padding:8px 14px 8px 11px;
  border-radius:999px;
  border:1px solid rgba(154,120,32,.58);
  background:rgba(255,253,248,.93);
  box-shadow:0 3px 16px rgba(24,20,12,.20);
  color:var(--tc-tag);
  font-family:var(--f-body);
  font-size:9.5px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;
  cursor:pointer;
  opacity:0;
  animation:tcCue 1.2s var(--tc-ease) 3.2s forwards;
  transition:background-color .3s var(--tc-ease),border-color .3s var(--tc-ease),color .3s var(--tc-ease);
}
.titlecard.is-film-on .tc-vidbtn{display:inline-flex;}
.tc-vidbtn[hidden]{display:none !important;}

/* ---- THE PILL IS OFF THE FRONT PAGE ----
   Asked for directly: "remove this". It is removed from SIGHT and not from
   the page, because of the line at the top of this block — WCAG 2.2.2, and
   the film is <video muted loop> that auto-starts and never stops on its own.
   On a wide screen with no reduced-motion preference this button is the only
   thing that can stop it, so it stays reachable by keyboard and by a screen
   reader while being invisible to everyone else.

   ⚠️ Collapsed rather than display:none, because display:none takes it out of
     the focus order too and there would be nothing left to reach.

   ⚠️ If it should go completely, delete the <button class="tc-vidbtn"> in
     index.html and this block with it — but then nothing on the page can stop
     the loop, and that is a deliberate accessibility trade, not a tidy-up. */
.titlecard.is-film-on .tc-vidbtn:not(:focus-visible){
  width:1px;height:1px;
  padding:0;border:0;
  overflow:hidden;
  clip-path:inset(50%);
  white-space:nowrap;
  background:transparent;
  box-shadow:none;
  opacity:0;
  animation:none;
}
/* ⚠️ animation AND opacity, explicitly. The base rule fades this pill in with
   animation:tcCue 1.2s var(--tc-ease) 3.2s forwards from opacity:0 — the
   rule above cancels that animation, so on focus it would otherwise restart
   and the button would stay invisible for another 3.2 seconds. Everything
   else comes back by itself once the rule above stops matching. */
.titlecard.is-film-on .tc-vidbtn:focus-visible{
  opacity:1;
  animation:none;
}
.tc-vidbtn:hover{background:rgba(255,253,248,.95);border-color:rgba(154,120,32,.8);color:#5F4912;}
.tc-ico{width:11px;height:11px;fill:currentColor;flex:none;}
.tc-ico-play{display:none;}
.tc-vidbtn[aria-pressed="true"] .tc-ico-pause{display:none;}
.tc-vidbtn[aria-pressed="true"] .tc-ico-play{display:block;}

/* The hint. A hover-only interaction is invisible until you happen to cross
   it, so the card says so once and then stops. Both states are animations:
   the fade-in fills forwards, and a plain opacity rule would lose to that
   fill, so the exit has to be an animation too. */
.tc-hint{
  display:none;
  position:absolute;z-index:3;
  right:var(--gutter);
  top:calc(var(--tc-header) + clamp(16px,3.4svh,38px));
  align-items:center;gap:7px;
  margin:0;
  padding:7px 13px 7px 10px;
  border-radius:999px;
  border:1px solid rgba(154,120,32,.42);
  background:rgba(255,253,248,.93);
  color:var(--tc-tag);
  font-family:var(--f-body);
  font-size:9.5px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;
  opacity:0;
  animation:tcCue 1.2s var(--tc-ease) 4.6s forwards;
  pointer-events:none;
}
.titlecard.is-film-on .tc-hint{display:inline-flex;}
.titlecard.is-explored .tc-hint{animation:tcHintOut .55s var(--tc-ease) forwards;}
@keyframes tcHintOut{
  from{opacity:1;translate:0 0;}
  to  {opacity:0;translate:0 -7px;}
}
.tc-hint svg{
  width:12px;height:12px;flex:none;
  fill:none;stroke:currentColor;stroke-width:1.7;
  stroke-linecap:round;
}

/* =========================================================
   Ambient motion

   Two loops that keep running once the entrance has settled: dust
   drifting up through the light, and an analysis sweep that crosses
   the frame every 9s. Each callout pings as the sweep reaches it —
   the per-note `--t` in the markup is simply when that happens.
   ========================================================= */
.tc-motes{
  position:absolute;inset:0;z-index:5;
  pointer-events:none;overflow:hidden;
}
.tc-motes i{
  position:absolute;
  left:var(--mx);top:var(--my);
  width:var(--ms);height:var(--ms);
  border-radius:50%;
  background:radial-gradient(circle,
    rgba(255,253,246,.98) 0%,
    rgba(255,247,225,.62) 42%,
    rgba(255,244,214,0)   72%);
  opacity:0;
  animation:tcMote var(--md) linear var(--mdel) infinite;
}
@keyframes tcMote{
  0%  {opacity:0;          translate:0 0;}
  14% {opacity:var(--mo);}
  72% {opacity:var(--mo);}
  100%{opacity:0;          translate:var(--mdx) calc(-1 * var(--mup));}
}

/* The sweep: a soft glow trailing a bright leading edge. It crosses in the
   first 35% of the cycle and rests for the remainder. Linear timing, because
   the callout ping delays are computed against a constant speed. */
/* =========================================================
   Skin-analysis callouts

   Each note is a box pinned at --x/--y with a lead line and a
   label running left or right. Everything animates from the box
   outward: box scales in, lead grows to --len, label fades at the
   far end. Hovering one lifts it and dims the rest.
   ========================================================= */
.tc-notes{
  position:absolute;inset:0;z-index:1;
  pointer-events:none;
  --note-ink:#6E5730;   /* 5.4:1 on the ivory ground */
}

/* ⚠️ HIDDEN BY DEFAULT, EVERYWHERE, AND THIS RULE IS LOAD-BEARING.
   main.js builds a .tc-fact plate for every callout unconditionally, but until
   now every style it had — including display:none — lived inside
   @media (hover:none) and (pointer:coarse). On a phone-sized viewport with a
   FINE pointer that block does not match, so the plate was an unstyled inline
   span inside this 38-80px square and a whole sentence poured out of it one
   word per line, straight down the front page.

   Measured at 393x852: with touch emulation the plates are 0x0 display:none;
   with a fine pointer they are 95x178 and 66x231, display:inline. Two of
   four, because notes 2 and 3 are display:none under 620px — which is exactly
   the two columns the device photograph showed.

   ⚠️ A phone-sized VIEWPORT and a COARSE POINTER are different questions.
     Anything that must not appear on a narrow screen has to be turned off by
     something that is true on every narrow screen; a pointer query is not. */
.tc-fact{display:none;}

/* ⚠️ THE PHONE FRONT SCREEN IS OFF BY DEFAULT, and this rule is the gate.
   Everything it names is markup that only the supplied phone comp asks for;
   above 720px the card is exactly what it was. Same lesson as .tc-fact
   directly above — the switch that hides something has to live where it is
   always true, not inside the query that happens to describe the case you
   were looking at. */
.tc-head,.tc-promise,.tc-acts,.tc-links,.tc-cards,.tc-foot{display:none;}


.tc-note{
  --s:clamp(38px,5vw,80px);
  --k0:0px;        /* lead exit point, from the box centre */
  --kx:.01px;      /* elbow run  — .01 not 0 so atan2() stays defined */
  --ky:0px;        /* elbow drop */
  --dy:calc(var(--k0) + var(--ky));
  --lgap:clamp(12px,1.1vw,18px);

  position:absolute;
  left:var(--x);top:var(--y);
  width:var(--s);
  aspect-ratio:1;
  translate:-50% -50%;
  pointer-events:auto;
  transition:opacity .45s var(--tc-ease);
}
/* Dim the others so the hovered one reads as selected */
.tc-notes:hover .tc-note{opacity:.42;}
.tc-notes .tc-note:hover,
.tc-notes .tc-note:focus-within{opacity:1;}

/* --- the box --- */
.tc-box{
  position:absolute;inset:0;
  border:1px solid rgba(255,255,255,.85);
  box-shadow:0 0 0 1px rgba(154,120,34,.10), 0 2px 18px rgba(24,20,12,.10);
  opacity:0;
  scale:.72;
  animation:tcBoxIn .9s var(--tc-ease) forwards;
  animation-delay:calc(2.5s + var(--d) * .22s);
  transition:scale .5s var(--tc-ease), border-color .4s var(--tc-ease), box-shadow .5s var(--tc-ease);
}
@keyframes tcBoxIn{ to{opacity:1;scale:1;} }
/* the soft light that blooms under the box on hover */
.tc-box::after{
  content:"";
  position:absolute;inset:-70%;
  border-radius:50%;
  background:radial-gradient(circle, rgba(255,252,244,.72) 0%, rgba(255,252,244,0) 68%);
  opacity:0;
  transition:opacity .5s var(--tc-ease);
  pointer-events:none;
}
.tc-note:hover .tc-box{
  scale:1.14;
  border-color:#fff;
  box-shadow:0 0 0 1px rgba(255,255,255,.5), 0 6px 30px rgba(24,20,12,.18);
}
.tc-note:hover .tc-box::after{opacity:1;}

/* the ring that fires as the sweep crosses this box */
.tc-box::before{
  content:"";
  position:absolute;inset:-1px;
  border:1px solid rgba(255,255,255,.92);
  opacity:0;
  pointer-events:none;
  animation:tcPing 9s var(--tc-ease) infinite;
  animation-delay:calc(5.2s + var(--t,1.2s));
}
@keyframes tcPing{
  0%  {opacity:0; scale:1;}
  3%  {opacity:.9;scale:1;}
  18% {opacity:0; scale:1.6;}
  100%{opacity:0; scale:1.6;}
}

/* --- sparkles inside the box --- */
.tc-spark,.tc-dot{
  position:absolute;
  background:#fff;
  filter:drop-shadow(0 0 4px rgba(255,255,255,.9));
}
.tc-spark{
  width:9px;height:9px;
  left:22%;top:26%;
  clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%);
  animation:tcTwinkle 3.2s var(--tc-ease) infinite;
  animation-delay:calc(var(--d) * .4s);
}
.tc-dot{
  width:3px;height:3px;border-radius:50%;
  right:26%;bottom:28%;
  opacity:.9;
}
@keyframes tcTwinkle{
  0%,100%{opacity:.55;scale:.86;}
  50%    {opacity:1;scale:1.12;}
}
.tc-note:hover .tc-spark{animation-duration:1.5s;}

/* --- lead line --- */
.tc-lead{
  position:absolute;top:50%;
  width:0;height:1px;
  background:linear-gradient(90deg, rgba(255,255,255,.9), rgba(255,255,255,.55));
  animation:tcLead .95s var(--tc-ease) forwards;
  animation-delay:calc(2.75s + var(--d) * .22s);
  transition:background .4s var(--tc-ease);
}
@keyframes tcLead{ to{width:var(--len);} }
.is-right .tc-lead{left:calc(100% + var(--kx));transform:translateY(var(--dy));}
.is-left  .tc-lead{right:calc(100% + var(--kx));transform:translateY(var(--dy));
  background:linear-gradient(270deg, rgba(255,255,255,.9), rgba(255,255,255,.55));}
/* the node where the lead meets the label */
.tc-lead::after{
  content:"";
  position:absolute;top:50%;
  width:4px;height:4px;border-radius:50%;
  background:#fff;
  translate:0 -50%;
  box-shadow:0 0 6px rgba(255,255,255,.9);
  opacity:.75;
  transition:opacity .4s var(--tc-ease), scale .4s var(--tc-ease);
}
.is-right .tc-lead::after{left:-2px;}
.is-left  .tc-lead::after{right:-2px;}
.tc-note:hover .tc-lead::after{opacity:1;scale:1.5;}

/* the elbow, for notes that leave the box at a corner */
.tc-lead::before{
  content:"";
  position:absolute;top:0;
  width:hypot(var(--kx),var(--ky));height:1px;
  background:rgba(255,255,255,.82);
  opacity:0;
  animation:tcFade .5s var(--tc-ease) forwards;
  animation-delay:calc(2.7s + var(--d) * .22s);
}
.is-right .tc-lead::before{right:100%;transform-origin:100% 50%;rotate:atan2(var(--ky),var(--kx));}
.is-left  .tc-lead::before{left:100%; transform-origin:0 50%;  rotate:calc(-1 * atan2(var(--ky),var(--kx)));}

/* --- label --- */
.tc-label{
  position:absolute;top:50%;
  display:flex;flex-direction:column;gap:3px;
  width:max-content;max-width:38vw;
  color:var(--note-ink);
  opacity:0;
  animation:tcFade .8s var(--tc-ease) forwards;
  animation-delay:calc(3.3s + var(--d) * .22s);
  transition:translate .5s var(--tc-ease), color .4s var(--tc-ease);
}
.is-right .tc-label{
  left:calc(100% + var(--kx) + var(--len) + var(--lgap));
  transform:translateY(calc(var(--dy) - .62em));
  text-align:left;
}
.is-left .tc-label{
  right:calc(100% + var(--kx) + var(--len) + var(--lgap));
  transform:translateY(calc(var(--dy) - .62em));
  text-align:right;
  align-items:flex-end;
}
.tc-label b{
  font-family:var(--f-body);
  font-size:clamp(9.5px,.95vw,12.5px);
  font-weight:600;
  letter-spacing:.19em;
  text-transform:uppercase;
  text-shadow:0 0 3px rgba(255,252,244,.9), 0 1px 8px rgba(255,252,244,.95), 0 0 20px rgba(255,252,244,.8);
}
.tc-label span{
  font-family:var(--f-body);
  font-size:clamp(9px,.9vw,12px);
  font-weight:300;
  letter-spacing:.02em;
  color:#75623C;   /* 4.7:1 */
  text-shadow:0 0 3px rgba(255,252,244,.9), 0 1px 8px rgba(255,252,244,.95), 0 0 18px rgba(255,252,244,.75);
}
.tc-note:hover .tc-label{color:#2F2415;}
.is-right:hover .tc-label{translate:6px 0;}
.is-left:hover  .tc-label{translate:-6px 0;}

/* Small screens: two notes only, pulled toward the edges */
@media (max-width:860px){
  .tc-label{max-width:32vw;}
  .tc-label b{letter-spacing:.14em;}
}
@media (max-width:620px){
  .tc-note:nth-child(2),
  .tc-note:nth-child(3){display:none;}
  .tc-label{max-width:34vw;}

  /* ⚠️ !important because --x and --y are INLINE on each .tc-note in the
     markup, one set of coordinates shared by every screen. They were surveyed
     against the desktop frame, where the lockup ends around 27% of the card;
     the phone lockup now ends at 36%, so Brightens at --y:32.5% was landing
     ON it — the box cut through SKINFX and the lead line ran straight over
     "PREMIUM CINEMATIC SKINCARE", with "dull skin" and "SKINCARE" printing on
     top of each other.

     Measured at 393x659: lockup 82..238, scroll cue 549..635. That leaves
     250..540 as the only band on this screen where a callout can sit without
     hitting one of them, and these two --y values put both boxes inside it —
     47% = 310 on her cheekbone, 72% = 475 on the shoulder of her shirt.

     --x comes in from 52.8% because the label hangs off the right of the box:
     at the old x it ended 29.8px from the frame edge, which is inside the
     20px gutter but not by enough to survive a longer word. A shorter lead
     buys the rest. */
  .tc-note{--len:34px !important;}
  .tc-note:nth-child(1){--x:46.5% !important;--y:47% !important;}
  .tc-note:nth-child(4){--x:56% !important;--y:72% !important;}
}

/* =========================================================
   Header — cover mode while the title card is on screen.
   `is-cover` is set from main.js. The capsule itself lives in
   styles.css with the rest of the header states; this is only
   what goes inside it over the artwork.
   ========================================================= */

/* The card carries the wordmark at full size directly below, so the bar
   shows the monogram alone — the ring reads as the brand without printing
   "CINEMA SKINFX" twice, sixty pixels apart. */
.site-header.is-cover .logo-type{
  opacity:0;
  transform:translateX(-6px);
  pointer-events:none;
  transition:opacity .45s var(--tc-ease), transform .45s var(--tc-ease);
}
.site-header.is-cover .logo-mark{transform:scale(1.06);}
.logo-mark{transition:transform .45s var(--tc-ease);}
.logo-type{transition:opacity .45s var(--tc-ease), transform .45s var(--tc-ease);}

/* Burger ink has to hold on bright artwork */
.site-header.is-cover .nav-toggle span{background:#7A5E1A;}

/* ---------- Responsive ---------- */
@media (max-width:860px){
  .tc-frond-a{width:min(96vw,620px);top:-10%;left:-24%;}
  .tc-frond-b{width:min(70vw,420px);top:-18%;left:-6%;}
  .tc-silk{height:min(38%,280px);}
}
@media (max-width:720px){
  /* ⚠️ One screen has to mean one screen. The base rule is

       min-height:calc(100svh + var(--tc-header));
       margin-top :calc(-1 * var(--tc-header));

     and those two net out ONLY if the header is out of flow. It is
     position:sticky — in flow — so it still occupies its own band, the card
     starts at y=1 instead of y=-74, and the "+ header" is added on top rather
     than absorbed. Measured: 733px of card in a 659px viewport at 393x659,
     and 74px over at 393x852 and at 360x640 too.

     74px is a rounding error on a desktop and the whole problem on a phone.
     It is exactly the scroll cue, which measured 51px BELOW the fold — so the
     one element whose entire job is to say "there is more below" was the one
     element a phone never got to see.

     Pull by the header's full border box (--hdr-h plus its 1px bottom rule)
     so the card starts at y=0, then ask for one small viewport. svh, not dvh:
     dvh re-lays-out the card every time Safari's toolbar slides, and svh errs
     toward slightly short, which is the harmless direction. */
  .titlecard{
    margin-top:calc(-1 * (var(--tc-header) + 1px));

    /* ⚠️ EVERY VALUE IN THIS CHAIN IS THE SCREEN OR TALLER. THAT IS THE RULE,
       and breaking it is what kept this card short on two different phones
       through three attempted fixes.

       The chain used to read vh, then svh, then dvh, then lvh. A fallback
       chain is not a preference list — the last value the browser UNDERSTANDS
       is the one it uses, and any reader whose browser stopped short of the
       last line landed on svh: the SMALL viewport, the one measured with the
       toolbar showing. At the top of a page the toolbar is showing, so the
       screen is the LARGE viewport, and a card cut to the small one ends
       exactly one toolbar above the bottom of the screen. What fills that
       strip is .trust — its three gold badges, reported twice, from an
       iPhone and from an Android, both about one header high.

       svh is now gone from this chain entirely. It was never the right unit
       for a BOX that has to cover the screen; it is the right unit for COPY
       that has to stay clear of the toolbar, which is where it still lives
       (.tc-content, below).

       ⚠️ 100vh IS A REAL FALLBACK HERE, NOT A TOKEN ONE. Mobile browsers
         have always resolved vh against the chrome-hidden viewport — the
         behaviour everybody once complained about — which is precisely what
         lvh names today. A browser too old for lvh therefore gets the same
         height by its own old rule, and the chain is correct at both ends. */
    min-height:100vh;
    /* ⚠️ dvh ON TOP OF svh, AND THE NOTE ABOVE ARGUED AGAINST IT. That note
       chose svh because "dvh re-lays-out the card every time Safari's toolbar
       slides, and svh errs toward slightly short, which is the harmless
       direction". Slightly short turned out not to be harmless: 100svh is
       FROZEN at the toolbar-shown height, so the moment Safari's toolbar
       slides away the visible viewport grows to lvh and the card no longer
       reaches the bottom of the screen. Reproduced by pinning the card to 760
       in an 844 viewport — the 84px that opens up is the top of .trust, so the
       artwork ends in a hard horizontal cut with a flat cream band under it.
       That is what was reported.

       ⚠️ THERE IS NO WAY TO PAINT THAT BAND FROM THE CARD. The card's box
       ends at svh; whatever follows in flow owns everything below it, and
       .titlecard is overflow:hidden so no child can bleed out. Filling the
       screen means the card has to BE that tall.

       dvh does both things the note wanted and the report needs: toolbar
       shown, dvh == svh, so the card is never taller than the screen; toolbar
       hidden, dvh == lvh, so it still reaches the bottom. Measured flush at
       844, 852, 760, 659, 640 and 932, starting at y=0 in every one.

       ⚠️ THE SCROLL CUE THE NOTE WAS PROTECTING NO LONGER EXISTS HERE.
       .tc-cue is display:none !important in this very block — it was taken off
       the phone later, with the callouts. A check that it "stays above the
       fold" passes on a phone no matter what the height rule says, because it
       has no box. What is actually held above the fold now is the closing
       line, and that is what was measured: it ends 15-22px up. The cost is
       a reflow while the toolbar slides, which is the trade every full-height
       hero makes, and it is the cheaper of the two. Kept BELOW svh so a
       browser without dvh still gets the old behaviour.

       ⚠️ AND dvh WAS STILL NOT ENOUGH FOR THE BOX. Reported off a real
       iPhone with a photograph: the card stops short and the trust band's
       icons sit under it, on screen, before anything has been scrolled — the
       exact failure this note describes, one unit further along.

       dvh is the viewport THAT IS VISIBLE RIGHT NOW, so a card cut to it is
       only ever correct for the instant it was measured. iOS moves that
       number by design: the toolbar is collapsed on some loads and expands
       on the first touch, and it slides during the very scroll that brings
       the fold into view. Every one of those moments is a card shorter than
       the screen, and the gap fills with whatever comes next in flow,
       because .titlecard is overflow:hidden and nothing of its own can reach
       down there.

       lvh is the viewport with the browser's chrome HIDDEN — the largest the
       visible area can ever become. Cut to that, the card covers the screen
       in all three states, and the only thing ever hidden is more of the
       card's own ground. Short shows another section; tall shows more card,
       and only one of those is a defect.

       ⚠️ THE COPY DOES NOT FOLLOW IT UP THERE. .tc-content stays on dvh so
         the closing line goes on sitting on the floor of what is VISIBLE
         rather than on the floor of the box — see the note on it below,
         which used to say the two must be the same number and now says why
         they must not be.

       ⚠️ 100vh IS THE FALLBACK AND IT IS THE RIGHT ONE. Mobile Safari has
         always resolved vh against the chrome-hidden viewport, which is what
         lvh names — so a browser too old for lvh lands on the same height by
         its own rule. */
    min-height:100lvh;

    /* ⚠️ AND A MEASURED HEIGHT ON TOP OF THE UNIT, because on two real
       phones the unit came back SHORTER THAN THE SCREEN IT WAS PAINTING ON.
       Reported four times from an iPhone and an Android: the card ends about
       a toolbar above the bottom and .trust's badges sit in the strip. Every
       unit in the chain above is defined as the screen or taller, so one of
       them is not telling the truth on those devices, and no fifth unit is
       going to settle it from here.

       --screen-h is set from JavaScript: the tallest viewport this tab has
       actually reported, watched across the toolbar sliding and cleared on
       rotation (see screenHeight() in main.js). max() takes whichever is
       bigger, so the card is the screen or taller whatever the unit claims,
       and a browser without max() or without JS keeps the line above.

       ⚠️ THE 0px FALLBACK IS LOAD-BEARING. Before the script runs the var
         is unset, and max(100lvh, 0px) is just the lvh line again — never a
         collapsed card. */
    min-height:max(100lvh, var(--screen-h, 0px));
  }

  /* The card slides under the header; the content has to come back out from
     under it. It never did — the old padding-top was 66px against a 75px
     header, so the monogram sat 8px BEHIND the glass. */
  /* ⚠️ NO LONGER CLEARS THE HEADER, BECAUSE THE HEADER NO LONGER HAS A PLATE.
     The old value pushed the monogram below the bar so it would not sit
     behind glass; over the cover the bar is now just a burger and a bag with
     no background, and the comp puts the mark BETWEEN them. */
  /* ⚠️ THIS IS THE AIR ABOVE THE MONOGRAM, and at 6px the mark began 9px
     from the top of the screen while the tagline ended 6.7px from the
     photograph — a 75px lockup in a 91px band, touching at both ends. The
     group is trimmed below; this is the top half of giving it room. */
  .tc-content{padding-top:clamp(14px,2.1svh,20px);}

  /* ⚠️ THIS IS HALF OF THE CENTRING AND .tc-foot IS THE OTHER HALF.
     "i gitna ang logo": the lockup used to sit in a header band at the top
     of the card with the picture under it. There is no band now — the film
     is the whole card — so the lockup and the copy are one block on it, and
     this auto margin is what lifts that block off the top. With the second
     auto margin on the closing line the free space splits evenly, so the
     group centres and the closing line is still on the floor. */
  .tc-mark{margin-top:auto;}

  /* A 4:5 source in a tall narrow frame is cropped hard whatever we do, so
     take the minimum zoom that still covers the fold — plus the 6% drop that
     buys the enlarged lockup its clearance above her eye line. Height goes up
     by the same 6% so the bottom edge still reaches. */
  /* ============================================================
     THE SUPPLIED PHONE COMP.

     Measured against the screen inside the handset photograph, with the
     status bar taken off, so the page area is 1521px tall and every figure
     below is a share of THAT:

       header row     0.8% - 4.3%    burger left, lockup centred, bag right
       CINEMA SKINFX  5.2% - 6.8%    one line
       tagline        7.8% - 8.3%
       photograph     9.5% - 49.5%
       headline      50.3% - 56.6%
       sub           56.7% - 59.1%
       Shop Now      61.1% - 66.3%   x 21.6%-78.4%, so 56.8vw
       Learn More    68.7% - 69.7%
       cards         75.2% - 84.7%   centres 17.5% / 50% / 82.5%
       pips          86.7% - 87.6%
       closing line  94.6% - 95.9%
     ============================================================ */

  /* The photograph is a BAND here, not the whole card: it ends around half
     way and the copy is read on cream below it. The mask already feathers
     its lower edge, so this only has to stop it short. */
  /* ⚠️ A COVER BAND, NOT A HEIGHT-SIZED PORTRAIT. The base rule sizes this
     off its height with width:auto because it is a 4:5 source in a landscape
     frame; asked for 40% of the height that way it is 273px wide in a 393px
     screen. The comp runs it edge to edge, so here it covers instead — and
     the object-position keeps her eye line in the band rather than her chin. */
  /* the lockup rides in the header band now, so the light follows it up */
  /* the lockup runs 2.1% to 10.2% of the card now, so the pool centres on
     where it actually is rather than where it used to be */
  .titlecard{
    /* ⚠️ THE POOL FOLLOWS THE LOCKUP AND THE LOCKUP HAS MOVED TO THE MIDDLE.
       6% was the header band this card used to keep the name in. Measured
       after centring: the monogram opens at about 27% of the card and the
       tagline closes at about 38%, so the light is aimed at the middle of
       that. Leaving it at 6% lights the empty top of the film and leaves the
       name in whatever the footage happens to be doing. */
    --lock-y:32%;

  }

  /* ⚠️ THE BAND IS THE FRAME NOW, NOT THE PHOTOGRAPH. The picture used to be
     its own band, which is why its camera move had to stay tiny: scaling the
     element grew its box past the band at both ends, up into the cream the
     lockup sits in and down over the headline, and every extra per cent came
     out of that gap. Measured, it bought 1.21px a second — a move nobody can
     see. The frame's edges do not move, so the picture inside can travel as
     far as it likes. */
  /* ⚠️ THE FILM IS THE WHOLE CARD NOW. Asked for directly: the logo in the
     middle, the video behind it, and the video whole.
     This is the third shape this band has had and each one was asked for.
     It ran wall to wall in the top half with the copy on cream below it;
     then it became a framed card in the same place; now there is no band at
     all — the film fills the card and every line on the screen is read ON
     it. So the scrim below stops being a tint and starts being the thing
     that makes the page legible. See .tc-veil.
     Everything the framed version added is gone rather than overridden:
     the radius, the keyline pseudo-element, the shadow, the aspect box and
     the centring offset. A rule that is not there cannot win an argument. */
  .tc-frame{
    display:block;
    position:absolute;
    inset:0;
    translate:none;
    width:auto;height:auto;
    z-index:0;
    overflow:hidden;
    pointer-events:none;
    border-radius:0;
    box-shadow:none;
    /* the mask stays off: there is no seam to feather, the card IS the film */
    -webkit-mask-image:none;
            mask-image:none;
  }
  .tc-photo{
    /* ⚠️ OVERSIZED ON PURPOSE. 8% of overlap on every side is the room the pan
       travels into; at inset:0 the element exactly fills the frame and any
       translate at all would drag an empty edge into view. */
    position:absolute;
    top:-8%;left:-8%;
    width:116%;height:116%;
    translate:none;
    max-width:none;margin-left:0;
    object-fit:cover;
    /* 38%, not 22%: at 22% a 0.80 portrait in a 0.46 card kept the top of
       her head and cut her at the collarbone. This is her face on the upper
       third with the silk below it. */
    object-position:50% 38%;
    /* the frame carries it now, and two masks would darken the seam twice */
    -webkit-mask-image:none;
            mask-image:none;
  }

  /* the card is one screen, and the copy hangs off the bottom of it */
  .tc-content{
    /* ⚠️ .titlecard lays this out as a FLEX ITEM, so without a width it
       shrink-wraps to its widest child — it measured 491px when the card row
       was oversized and 299px once that was fixed, and the whole screen slid
       off centre both times. It is the card, so it is the card width. */
    width:100%;
    min-height:100svh;
    /* ⚠️ IT TRACKS THE SCREEN, AND THE CARD NO LONGER DOES. This block is
       what the closing line hangs off the bottom of, via the auto margins
       described below, so its height has to be the height of what the reader
       can actually SEE: dvh, the visible viewport, in whatever state the
       toolbar happens to be.

       This note used to read "two heights that must be the same number,
       written as the same number", and the card was dvh alongside it. The
       card is 100lvh now — it was measured stopping short of a real iPhone
       screen with the next section showing in the gap, and the reasoning is
       written out in full up there. The two numbers are deliberately
       different from here on:

         the BOX is lvh   so the ground always covers the screen
         the COPY is dvh  so the closing line always sits on the visible floor

       With the toolbar hidden they are the same number again and nothing
       moves. With it shown, the card runs a toolbar's worth further down
       behind it — ground only, nothing to read — and the copy stops at the
       glass. Left at svh this would stop short in the other direction the
       moment the toolbar slid away.

       ⚠️ AND svh STAYS IN *THIS* CHAIN, on purpose. Here the short
         direction is the safe one: copy that stops above the toolbar is
         readable, copy that runs under it is not. The card's chain wants the
         opposite and no longer contains it. */
    min-height:100dvh;
    /* ⚠️ STILL flex-start, AND THE CENTRING IS DONE WITH AUTO MARGINS.
       justify-content:center was tried and it changed nothing, because
       .tc-foot carries margin-top:auto and an auto margin takes all the free
       space before the container's alignment is consulted. The pair of auto
       margins — here on .tc-mark, and the logged one on .tc-foot — split
       that space in two instead: the lockup and the copy sit as one block in
       the middle of the film, and the closing line stays on the floor. */
    justify-content:flex-start;
    padding-bottom:clamp(10px,2.4svh,22px);
  }

  /* ---- the lockup, in the header band ---- */
  /* ⚠️ ONE LINE. .tc-word is a flex column everywhere else; a row here turns
     "Cinema / SkinFX" into "CINEMA SKINFX" with no markup change. */
  .tc-word{flex-direction:row;gap:.30em;align-items:baseline;margin-bottom:2px;}
  /* ⚠️ THE COMP HAS NO HAIRLINE HERE. Its header band runs straight from
     CINEMA SKINFX to the tagline; this rule plus its margins is most of the
     ~20px the lockup was sitting low by. */
  .tc-rule{display:none;}
  /* ⚠️ THE LEADING, NOT THE TYPE. This box measured 18.1px tall for 11px
     of type, so about 7px of it is leading under a run of caps with no
     descenders to leave room for. Those 7px cost nothing that can be read.
     The size is left alone on purpose: the Phone legibility block at the
     foot of this file audited the card at 390x844, found this line on a
     7.5px floor and pinned it to 11px, and that decision stands. It also
     beats the font-size on this very line, which is why this rule can only
     usefully set leading. */
  .tc-tag{font-size:clamp(8px,2.5vw,10.5px);letter-spacing:.22em;line-height:1.1;}

  /* ⚠️ EVERYTHING IN THIS BLOCK IS UNREACHABLE ON A PHONE NOW, ON PURPOSE.
     main.js no longer puts is-film-on on a portrait phone, so the photograph
     shows instead — "remove the boxes sa face", and the squares cannot come
     out of the footage because they REPLACE her skin rather than tint it.
     The rules are kept, not deleted: restoring the film is one term in one
     expression in main.js, and then this block is what styles it. */
  /* ---- the film, in the same band as the still ---- */
  /* ⚠️ IT CAN COME HERE NOW, because the frame clips it and because the cut it
     is given has had the baked labels and connector lines taken out. It fills
     the frame and covers; nothing per-frame is added to it — no filter, no
     mask, no clip-path — which is the rule this file has carried since the
     film was first measured and which the README has the decode figures for.
     ⚠️ THAT RULE IS ALSO WHY THE FILM IS NOT BRIGHTENED HERE. "Make the video
     light" is a filter's job and a filter on this element costs a full-frame
     pass on the visitor's GPU twenty-four times a second. The light is laid
     ON TOP instead, by .tc-veil, which is a static layer that never animates
     and is composited once. */
  .tc-film{
    position:absolute;
    top:0;left:0;
    width:100%;height:100%;
    translate:none;
    object-fit:cover;
    /* ⚠️ THE CUT IS A PORTRAIT AND THE CROP IS GONE. The square-ish 600x650
       cut in a 393x852 card showed HALF the frame — cover matched the height
       and threw away 300 of 600 columns. There is no arrangement of a 0.92
       source in a 0.46 box that avoids that, so the source was rebuilt:
       380x824 from the master at x=1053 y=128, which is 0.4612 against this
       screen's 0.4613. See the README for the delogo rectangles that made
       that column usable at all.

       ⚠️ SHE IS CENTRED NOW, AND THE FOUR SQUARES ARE BACK. THAT IS THE
       DECISION, NOT A REGRESSION. The squares are welded to her face across
       master x 736-1080, so a window that centres her face has to contain
       them; delogo over an eyebrow and a nostril tears them, tested on all
       four by an earlier pass. Three cuts avoided that by staying to the
       RIGHT of her face (600x650, then 498x1080, then 380x824) and every one
       of them had her cut by the LEFT edge — measured, nine framings, the
       darkness centroid stuck at 39-42% against 50% for centred, moving a
       point or two whatever the crop. The request was raised as costly twice,
       with the numbers, and reaffirmed: "IGITNA MO NGA KAHIT ANONG PANG
       KALABASAN NYAN". So: 498x1080 at x=611, because her face centre is
       master x=860 and 611 + 249 = 860.
       ⚠️ DO NOT slide this window back to the right to "clean it up". That is
       what the three previous cuts were, and it is what was rejected.
       ⚠️ Centring pulled in the two LEFT connector lines as well, which would
       have read as two white rules across the hero. They ARE removed — 3px of
       ink each (y 496-498 x 483-738, y 696-698 x 573-961), measured off the
       pixels, cleared by 3px a side. Checked at 2x on the finished file:
       gone, with no streak. Only the squares remain.
       40%, not 50%: an older 360x640 phone is 0.5625 and cover has to take
       about 18% off the height there. Biasing up keeps her ear and the
       earring — the frame's one sharp detail, at 28% down — inside the
       window, and spends the loss on silk at the bottom instead. */
    object-position:50% 40%;
  }
  /* ⚠️ THE STILL STAYS UNDERNEATH, AND THIS IS NOT BELT AND BRACES. The base
     rule hides .tc-photo whenever is-film-on, which is right on a desktop
     where the film is the whole background. Here the film is one band, and the
     first version of this ALSO held the film at opacity 0 until is-film-live —
     a class that comes off on pause. Tap the pause control, or scroll the card
     out of view so the observer pauses it, or stall mid-loop, and the band had
     neither film nor still in it. It had cream.
     Found by a measurement that reported the band at mean 245 of 255 — paper,
     not a photograph — because the probe paused the film to hold a frame and
     switched off the thing it was measuring. The absurd number is what made it
     obvious; a plausible one would not have.
     The film is opaque and fills the frame, so nothing changes while it plays.
     The instant it is not painting there is a finished photograph behind it. */
  .titlecard.is-film-on .tc-photo{display:block;}
  /* but it must not keep pushing in where nobody can see it */
  .titlecard.is-film-on .tc-photo{animation:tcFade 2.4s var(--tc-ease) .15s forwards;}
  /* the frame's own mask feathers the band; .tc-fade is the 16/9 letterbox
     seam treatment for the wide layout and has no meaning here */
  .titlecard.is-film-on .tc-fade{display:none;}

  /* ⚠️ THE SCRIPT LINE IS GONE, ASKED FOR DIRECTLY. "Skin / that tells /
     your story" in Parisienne hung off the photograph's lower left. It had
     already been rescued once — clearing the veil left it at 1.92:1 through
     its own glyphs against her hair, and a deeper ink plus a four-layer halo
     brought it back rather than putting the wash over the whole band again.
     The standard it was held to was "it still has to read", and the person
     looking at it says it does not: "hindi naman sya kita".

     It was aria-hidden and duplicated no fact — the four facts are .sr-only
     text inside .tc-cards and are untouched — so the element, its rules and
     its entry in three grouped selectors all came out together rather than
     being switched off and left behind. */

  /* ---- the headline, under the photograph ---- */
  /* margin-top:auto is what drops this whole group to the bottom of the
     column, so the photograph keeps the top half to itself */
  .tc-head{
    display:block;
    /* ⚠️ NOT margin-top:auto. That is "whatever is left in the column", so it
       moved every time anything else in the column did — taking the pips out
       pushed this group 60px further down. The photograph band closes at 50%
       of the card and the lockup above ends around 11%, so this is the gap
       between them, stated. */
    /* ⚠️ PLUS THE 14px THE LOCKUP GAVE UP. This is a flex column, so
       shortening the lockup above lifted the headline, the sub, both
       buttons, the cards and the closing line by the same 13.9px — none of
       which were asked to move. fitcheck passed it anyway: the headline
       drifted from 11px above the comp to 25px above it, inside the wider
       tolerance that rows compared box-to-ink are given. That tolerance is
       for the difference between a line box and an ink band, not for a
       drift, so the stated gap grows by what the band above it lost. */
    /* ⚠️ ONE TERM AGAIN. The +14px existed to give back what trimming the
       lockup had taken off the top of this column; the lockup has grown
       past that now, so the compensation is folded back into the figure
       rather than left as a correction to a correction.
       The photograph closes at 63.5% of the card, so this is the gap from
       the tagline to twelve pixels past that edge, stated. */
    /* ⚠️ A GAP, NOT AN OFFSET. This was 54.7svh, and every one of the
       figures that justified it — 50% for the band, 4.7 for the air above
       and below it — described a picture that this line had to step over.
       The film is behind the whole column now, so what is left is the space
       between the lockup and the headline and nothing else. */
    margin-top:clamp(22px,4.6svh,44px);
    font-family:var(--f-display);
    font-weight:400;
    /* two lines inside 429-482, so about 28px */
    font-size:clamp(22px,7vw,32px);
    line-height:1.12;
    letter-spacing:.004em;
    color:#4A3B22;
  }
  .tc-promise{
    display:block;
    /* the comp sets this straight under the headline — 482 to 483 */
    margin-top:2px;
    font-family:var(--f-body);
    font-size:clamp(10.5px,3.1vw,13px);
    font-weight:400;
    letter-spacing:.20em;
    text-transform:uppercase;
    /* NOTE: THE GLYPH-MASK READING IS A FLOOR, NOT THE CONTRAST.
       It reported 2.82:1 for this line and I darkened the fill on the
       strength of it — then computed the declared colour and found the comp
       tone below was already 5.56:1 on this ground, comfortably over the 4.5
       it owes. The method averages every covered pixel, and small
       letterspaced caps are mostly ANTIALIASED EDGE, so the mean ink comes
       back far lighter than the fill. It is the right instrument for the
       wordmark, whose gold is a gradient with no single declared colour; it
       is the wrong one for flat type. Reverted.

       ⚠️ AND THEN THE GROUND CHANGED UNDER IT. "already 5.56:1 on this
       ground" was the whole of that reasoning, and this line is not on that
       ground any more — it is on the film. Measured by the same declared-
       colour method the note above argues for: 3.68:1, against the 4.5 a
       13px line owes. #6B5F52 needs a ground of .71 to pass and the painted
       ground here is .62; closing that with cream takes about .83 of it,
       which is a wash with no film left in it.
       So the ink moves and the method does not: same instrument, same 4.5,
       one step darker. 4.73:1. */
    color:#5C5142;
  }

  /* ---- the two actions ---- */
  /* ⚠️ SIDE BY SIDE AND EQUAL, which is the format of the supplied reference
     and the opposite of what was here. Stacked, the pair took 87px of a
     screen that has just had its card row removed; as one row they take 46,
     and the two read as a choice rather than as a main action with a
     footnote under it. */
  .tc-acts{
    display:flex;flex-direction:row;align-items:stretch;justify-content:center;
    gap:2.8vw;
    width:100%;
    padding-inline:3.5vw;
    margin-top:clamp(12px,2.4svh,22px);
    pointer-events:auto;
  }
  /* ⚠️ THE SECONDARY IS SMALLER THAN THE PRIMARY, and they were identical.
     Measured off the comp's own pills — the gold fill for one, the outline's
     top and bottom edges for the other:
        Shop Now    56.9vw x 43px, text about 15px
        Learn More  42.2vw x 34px, text about 13px
     Building both at 56.8vw and 44px is most of why the pair read heavy. */
  .tc-shop,.tc-more{
    position:relative;
    display:flex;align-items:center;justify-content:center;gap:.5em;
    border-radius:999px;
    font-family:var(--f-body);
    text-decoration:none;
  }
  /* ⚠️ EQUAL, AND BOTH OVER THE TOUCH FLOOR. The note above describes the
     comp's pair, which were 56.9vw x 43 and 42.2vw x 34 — a shape the
     reference replaces. Equal halves of the row, 46px tall, so the 44px
     guideline is met by the box itself and the transparent pseudo-element
     that used to grow the smaller target is no longer needed. */
  .tc-shop,.tc-more{
    flex:1 1 0;min-width:0;
    min-height:46px;
    font-size:clamp(12.5px,3.5vw,15px);
    text-align:center;
    line-height:1.15;
  }
  /* the pseudo-element that used to grow the smaller pill's target is gone
     with the smaller pill: both are 46px now, over the 44px guideline */
  /* the comp's primary: a gold bar, 56.8vw wide and 80/1883 of the screen tall */
  .tc-shop{
    font-weight:600;
    color:#2A2113;
    background:linear-gradient(103deg,#C9A54B 0%,#E5CE8C 38%,#C29A38 72%,#A8822A 100%);
    box-shadow:0 10px 26px rgba(154,120,32,.32), inset 0 1px 0 rgba(255,250,232,.55);
  }
  .tc-more{
    font-weight:500;
    color:#5E4E30;
    background:rgba(255,252,246,.5);
    box-shadow:inset 0 0 0 1.4px rgba(176,143,58,.55);
  }
  /* the arrow went with "Shop Now"; the reference's pills carry no glyph */
  /* ⚠️ ON A PHONE THE PRESS IS THE WHOLE AFFORDANCE. There is no hover to
     fall back on, so the only moment a control can say "yes, that was me"
     is while the thumb is down — and 2.2% of scale on a gold pill is not
     much of a yes. The fill deepens and the lift drops as well, which is
     what a physical button does.
     ⚠️ AND THE PLATFORM FLASH HAS TO GO WITH IT. iOS paints its own grey
     rectangle over any tapped link — a grey square across a round gold
     button — and that is the wrong answer once there is a real one. */
  .tc-shop,.tc-more,.tc-links a{
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
  }
  .tc-shop,.tc-more{
    transition:scale .18s var(--tc-ease),
               box-shadow .18s var(--tc-ease),
               background-color .18s var(--tc-ease);
  }
  .tc-shop:active{
    scale:.968;
    background:linear-gradient(103deg,#B18F36 0%,#C9AC64 38%,#A57F20 72%,#8B6916 100%);
    box-shadow:0 3px 9px rgba(154,120,32,.26), inset 0 1px 0 rgba(255,250,232,.32);
  }
  .tc-more:active{
    scale:.968;
    background:rgba(249,242,229,.96);
    box-shadow:inset 0 0 0 1.7px rgba(142,113,38,.85);
    color:#4C3E24;
  }

  /* ---- the round links under them ---- */
  /* ⚠️ SOLID CIRCLES WITH THE GLYPH KNOCKED OUT, which is both the format of
     the reference and what BRAND.md requires: "gold on black clears contrast
     easily; gold on white does not — never set small gold type on white". A
     20px icon is small type, so the gold is the ground here, not the ink. */
  .tc-links{
    display:flex;justify-content:center;align-items:center;
    gap:clamp(11px,3.4vw,17px);
    width:100%;
    margin:clamp(11px,2.1svh,19px) 0 0;
    padding:0;
    list-style:none;
    pointer-events:auto;
  }
  .tc-links li{display:flex;}
  .tc-links a{
    display:flex;align-items:center;justify-content:center;
    width:clamp(44px,11.2vw,48px);aspect-ratio:1;
    border-radius:50%;
    color:#FDF8EC;
    background:linear-gradient(152deg,#C6A044 0%,#AC8630 58%,#8E6D1E 100%);
    box-shadow:
      inset 0 1px 0 rgba(255,250,232,.45),
      0 6px 15px rgba(120,94,40,.22);
    transition:scale .18s var(--tc-ease),
               box-shadow .18s var(--tc-ease),
               background-color .18s var(--tc-ease);
  }
  .tc-links a:active{
    scale:.9;
    background:linear-gradient(152deg,#AC8630 0%,#8E6D1E 58%,#77590F 100%);
    box-shadow:inset 0 1px 0 rgba(255,250,232,.28), 0 2px 6px rgba(120,94,40,.26);
  }
  .tc-links svg{
    width:45%;height:auto;
    fill:none;stroke:currentColor;stroke-width:1.7;
    stroke-linecap:round;stroke-linejoin:round;
  }

  /* ---- the three cards ---- */
  /* ⚠️ SIZED SO THREE FIT AND A FOURTH DOES NOT. The comp's card centres sit
     at 17.5%, 50% and 82.5% of the screen, which is a 28.4% card on a 4%
     gutter. The fourth is off the right-hand edge, which is what the pips are
     for — and what makes the row obviously draggable. */
  .tc-cards{
    display:grid;
    grid-auto-flow:column;
    /* ⚠️ vw, NOT %. A percentage column in a grid whose own width is being
       decided by its contents is circular, so the percentage silently stops
       being one and every column falls back to its content width — the row
       measured 451px in a 393px screen and took .tc-content out to 491 with
       it. The comp's card is 29.5% of the SCREEN, so vw is what it meant. */
    /* ⚠️ THREE THAT FIT, NOT A SCROLLER. 100vw less two 3.5vw gutters leaves
       93vw; two 3.6vw gaps off that leaves 85.8vw, so each card is 28.6vw —
       the comp's 29.5 to within a pixel, with nothing left to swipe to. */
    grid-template-columns:repeat(3,1fr);
    grid-auto-flow:row;
    gap:3.6vw;
    min-width:0;
    width:100vw;
    margin-inline:calc(50% - 50vw);
    /* measured: the row sat 20px high against the comp at 2.6svh */
    margin-top:clamp(20px,4.2svh,38px);
    padding-inline:3.5vw;
    pointer-events:auto;
  }
  .tc-card{
    display:flex;flex-direction:column;align-items:center;justify-content:center;
    gap:2px;
    /* the comp's card is 218x185 of a 740px screen — wider than it is tall */
    aspect-ratio:1 / 0.85;
    padding:clamp(8px,2vw,14px) 4px;
    border-radius:clamp(14px,4vw,20px);
    /* the comp's frosted glass: a pale fill, a light rim, and a lifted edge */
    background:linear-gradient(160deg, rgba(255,253,249,.80) 0%, rgba(250,243,231,.62) 100%);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,.9),
      inset 0 0 0 1px rgba(176,143,58,.16),
      0 8px 20px rgba(120,94,40,.13);
  }
  /* ⚠️ SPOKEN, NOT DELETED. The fourth callout has nowhere else to live on a
     phone — .tc-notes is display:none here — so it is taken out of sight the
     way .sr-only does it, and stays in the accessibility tree. */
  /* ⚠️ THE WHOLE ROW IS SPOKEN NOW, NOT JUST THE FOURTH. Asked to take the
     cards off the front screen — but on a phone .tc-notes is display:none,
     so this row IS the four facts and deleting it would take all four out
     of the document. The fourth card was already being clipped this exact
     way; the rule simply moves up to the list. Nothing is painted, every
     fact is still read aloud. */
  .tc-cards,
  .tc-card.is-spoken{
    position:absolute;width:1px;height:1px;padding:0;margin:-1px;
    overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
  }
  /* nothing inside a 1px clip should still be animating every frame */
  .tc-cards .tc-card::after{animation:none;content:none;}
  .tc-card-ico{display:block;margin-bottom:clamp(2px,.8svh,7px);}
  .tc-card-ico svg{
    width:clamp(20px,6.2vw,27px);height:auto;
    fill:none;stroke:#B08F3A;stroke-width:1.5;
    stroke-linecap:round;stroke-linejoin:round;
  }
  .tc-card b{
    font-family:var(--f-display);
    font-weight:400;
    font-size:clamp(13px,4vw,17px);
    color:#2E2617;
    letter-spacing:.004em;
  }
  .tc-card span{
    font-family:var(--f-body);
    font-size:clamp(9.5px,2.9vw,12px);
    color:#6B5F52;
  }



  /* ---- the closing line ---- */
  /* =========== the part that is not in the comp ===========
     Everything below moves opacity or a transform only, stops dead under
     prefers-reduced-motion, and is paused by .is-idle whenever main.js
     cannot see the card. */

  /* the screen arrives in order rather than all at once */
  /* .tc-cards is off this list: it is clipped to a pixel now, and an
     element nobody can see does not need to arrive. */
  .tc-head,.tc-promise,.tc-acts,.tc-links,.tc-foot{
    opacity:0;
    animation:tcRise .78s var(--tc-ease) forwards;
  }
  .tc-head   {animation-delay:1.20s;}
  .tc-promise{animation-delay:1.34s;}
  .tc-acts   {animation-delay:1.48s;}
  .tc-links  {animation-delay:1.62s;}
  .tc-cards  {animation-delay:1.62s;}
  .tc-foot   {animation-delay:1.92s;}

  /* ⚠️ ONE STREAK, THEN ELEVEN SECONDS OF NOTHING. A button that glitters
     continuously stops reading as gold and starts reading as an advert. The
     streak is a pseudo-element so the bar's own gradient is never repainted. */
  .tc-shop{position:relative;overflow:hidden;isolation:isolate;}
  .tc-shop::after{
    content:"";
    position:absolute;inset:0;
    z-index:-1;
    background:linear-gradient(104deg,
      rgba(255,255,255,0) 38%,
      rgba(255,252,240,.62) 48%,
      rgba(255,255,255,0) 58%);
    translate:-120% 0;
    animation:tcSheen 11s var(--tc-ease) 2.4s infinite;
  }

  /* ⚠️ THE SECONDARY PILL ASKS TO BE PRESSED NOW, asked for: something
     "gumagalaw or hook so that mag press sila ng inquire button". Two rings
     open out of its edge and fade, then it rests for six seconds — the same
     bargain the gold bar’s streak strikes one rule above this: a control
     that moves without stopping stops reading as an invitation and starts
     reading as an advert.
     ⚠️ NO GLYPH WAS ADDED TO DO THIS. "the reference’s pills carry no
       glyph" is a logged decision fifty lines up and an arrow would have
       been the easy way to break it.
     ⚠️ IT RUNS OFF THE SAME CYCLE BUT NOT THE SAME BEAT: 9s against the
       streak’s 11s, and 3.6s in rather than 2.4s, so the two pills are never
       both moving. On the rare frames they nearly coincide the row still
       reads as one thing happening, not two competing.
     The ring is drawn ON TOP: this pill’s ground is half-transparent, so a
     ring behind it would show through the fill as a smudge rather than sit
     on its edge. It cannot take a press — pointer-events:none — and the
     reduced-motion block at the foot of styles.css stops it outright. */
  .tc-more::after{
    content:"";
    position:absolute;inset:0;
    border-radius:999px;
    pointer-events:none;
    box-shadow:0 0 0 1.4px rgba(176,143,58,.55);
    opacity:0;
    animation:tcAsk 9s var(--tc-ease) 3.6s infinite;
  }
  @keyframes tcAsk{
    0%  {scale:1;    opacity:0;}
    3%  {scale:1;    opacity:.9;}
    17% {scale:1.14; opacity:0;}
    20% {scale:1;    opacity:0;}
    23% {scale:1;    opacity:.62;}
    37% {scale:1.14; opacity:0;}
    100%{scale:1;    opacity:0;}
  }

  /* the specular catch the comp draws on the card edges, travelling */
  .tc-card{position:relative;overflow:hidden;isolation:isolate;}
  .tc-card::after{
    content:"";
    position:absolute;inset:-40% -60%;
    z-index:-1;
    background:radial-gradient(38% 44% at 50% 50%,
      rgba(255,253,244,.92) 0%, rgba(255,251,236,.34) 42%, rgba(255,250,235,0) 100%);
    translate:-70% 0;
    animation:tcGlint 9s var(--tc-ease) infinite;
  }
  .tc-card:nth-child(2)::after{animation-delay:1.6s;}
  .tc-card:nth-child(3)::after{animation-delay:3.2s;}
  .tc-card:nth-child(4)::after{animation-delay:4.8s;}

  /* a card answers a finger */
  .tc-card{transition:scale .22s var(--tc-ease), box-shadow .22s var(--tc-ease);}
  .tc-card:active{scale:.972;}

  .tc-foot{
    display:block;
    /* ⚠️ margin-top:auto, AND IT IS A LOGGED DECISION — "the one element
       that really does belong at the bottom whatever the phone's height
       turns out to be". Taking it off is what made justify-content:center
       work, and that was the wrong way round: an auto margin eats ALL the
       free space in a flex column before justify-content is ever consulted,
       so the rule to change was never this one. See .tc-mark, which now
       carries the matching auto margin, so the free space splits in two and
       the group centres with this line still on the floor. */
    margin-top:auto;
    padding-top:clamp(10px,2.2svh,20px);
    font-family:var(--f-body);
    font-size:clamp(9px,2.7vw,11.5px);
    font-weight:500;
    letter-spacing:.28em;
    text-transform:uppercase;
    /* ⚠️ #8A7A63 CANNOT PASS AND NEVER COULD. Solve 4.5:1 for the ground it
       would need and the answer is 1.09 on a scale that stops at 1.0 — so
       this line was under even on cream, at 3.75:1 for 10.6px of type, long
       before the film went behind it. The film only made it visible: 1.85:1.
       It is the same warm bronze the tagline takes on a phone, two steps
       lighter, so the closing line still reads quieter than the name above
       it. Measured after: see the README. */
    color:#5A4B33;
  }

  /* ---- what the comp does NOT have ---- */
  /* the callouts are off her face here; the same four facts are the cards */
  .tc-notes,.tc-hot,.tc-hint,.tc-cue{display:none !important;}

  /* ---- the header bar the comp draws ---- */
  /* ⚠️ IT IS SHOWN OVER THE COVER NOW. The rule below used to hide it
     outright on a phone; the comp puts the burger and the bag in that band,
     so it stays — stripped to those two, with no plate of its own, because
     .tc-content already supplies the lockup between them. */
  .site-header.is-cover{opacity:1;translate:0 0;pointer-events:auto;background:none;box-shadow:none;}
  /* ⚠️ THE PLATE IS ON .header-inner, NOT ON .site-header. Switching the
     header's own background off left the capsule painting over the monogram,
     because the capsule is .header-inner::before — a backdrop-filter, a
     background and seven box-shadows. content:none takes it off the page
     instead of trying to neutralise each of those. */
  .site-header.is-cover::before,
  .site-header.is-cover::after,
  .site-header.is-cover .header-inner::before,
  .site-header.is-cover .header-inner::after{content:none;}
  /* ⚠️ visibility, NOT JUST opacity. Tab stop 2 of 14 on this screen was the
     header logo at y=19, reading "inema SkinFX" — invisible to eyes and to a
     pointer, and still in the focus order, so a keyboard visitor tabs to
     something that is not there and the ring is painted around nothing.
     opacity and pointer-events do not remove an element from the tab order.
     visibility does, and it comes straight back when is-cover comes off. */
  .site-header.is-cover .logo,
  .site-header.is-cover .scroll-progress{opacity:0;pointer-events:none;visibility:hidden;}
  .site-header.is-cover .header-inner{justify-content:space-between;}
  .site-header.is-cover .nav-toggle{order:-1;}

  /* ⚠️ AND THE RDR LOCKUP LEAVES THE LAYOUT HERE, NOT JUST THE PICTURE.
     It is visibility:hidden over the card, which hides it and KEEPS ITS BOX
     " and the rule above is what makes that box a problem: with the burger
     pulled to order:-1 and no header action beside it, space-between parks
     the lockup hard against the right edge. The lockup is absolute and
     nowrap and 170px wide against a 102px stack, by design, so it overhangs
     " and at 393 it measured left 271, RIGHT 441. Fifty pixels past the
     screen.

     That is 48px of horizontal scroll on the whole document, from an
     element nobody can see. On a phone it reads as the page sliding under
     the thumb while scrolling, which is what was reported. Measured by
     bisection: hiding this one element took scrollWidth from 441 back to
     393.

     display:none rather than a width or a clip, because there is nothing to
     preserve: the lockup is invisible in cover mode anyway. It comes back
     with the docked bar, which is the only place it is ever seen, and the
     cross-fade on wider screens is untouched.

     ⚠️ DO NOT 'RESTORE' THIS TO visibility FOR THE FADE. The fade it would
       buy is a fade of something that is not on screen; the cost is a page
       that scrolls sideways on every phone. */
  .site-header.is-cover .logo-rdr{display:none;}
  .site-header.is-cover .header-actions{order:9;}
  /* ⚠️ NO ACTION IN THIS BAND AT ALL. The comp puts a shopping bag here; there
     is no shop on this page for it to open, and the front screen's own Shop
     Now already goes to cinemaskinfx.com. The burger stays, the lockup sits
     between, and the right side is empty on purpose. */
  .site-header.is-cover .header-actions{display:none;}

  /* ⚠️ THE STILL GETS THE CAMERA MOVE, BECAUSE THE FILM CANNOT RUN HERE.
     Measured: the film plays on a phone held sideways (playhead 6.19 -> 8.70
     over 2.5s at 852x393) and is display:none upright.

     ⚠️ AND THE REASON IS IN THE CLIP'S PIXELS, NOT IN A RULE. hero-720.mp4 is
       1280x720 with the four callouts PAINTED INTO IT — "BRIGHTENS dull skin"
       at x 918-997, "HYDRATES deeply" at 240-307, "REDUCES blemishes" at
       920-981, "SMOOTHS texture" at 300-368 — each with a connector line
       running from the label to a highlight box on her face.

       A 393x426 band cover-crops that to the middle 52%, x 308 to 972. That
       cuts the label TEXT and leaves all four CONNECTOR LINES running off the
       left and right edges to nothing. Three windows were rendered and looked
       at; every one has them, because the lines cross her face — there is no
       crop that keeps her and loses them. The other two clips in the project
       root are the same shot with the same graphics baked in.

       assets/img/hero.jpg is the same model in the same room with nothing
       painted on her, so the band gets what the film gives — the push-in the
       film's own note says it "carries" — on the frame that has no UI on it.

     ⚠️ THE TWO LAYERS NO LONGER SHARE ONE MAP, AND THAT IS SAFE HERE. The
       note that used to sit in this place explained that .tc-photo and
       .tc-notes must run the SAME keyframes about the same point of the card,
       or the callout boxes slide off the features they label — .tc-notes at
       inset:0 has the card's centre, while .tc-photo is 106% tall from 6% down
       so that same point is 41.5% down its box, which is why the origins
       differ. All of that still holds wherever both are drawn. It does not
       apply in this block: .tc-notes is display:none !important here, in both
       orientations, so there is nothing for the photograph to slide out from
       under. The origin stays at 41.5% because it is still the right point to
       push in about. */
  .tc-photo{
    /* ⚠️ PROMOTED ON PURPOSE. This element carries a mask-image AND a filter,
       and titlecard.css already warns that per-frame work on a masked layer is
       paid full-frame on the visitor GPU. will-change lets the compositor
       scale one cached texture instead of re-rasterising the mask every
       frame; measured below. */
    /* both properties the move touches, so the compositor keeps one texture */
    will-change:scale, translate;
    /* the element is the picture now, not the band, so it pushes in about
       its own middle rather than about a point computed for the old box */
    transform-origin:50% 50%;
    /* ⚠️ linear, NOT --tc-ease. That variable is cubic-bezier(.16,.84,.44,1),
     a strong ease-OUT: it spends the first two seconds doing most of the
     travel and then crawls. Measured with it, the band changed 10.3% of its
     pixels over two seconds and read as a photograph. A camera move wants a
     constant rate, which is what linear is; the direction change at each end
     of the alternate is a fifth of a per cent per second and nobody sees it.
⚠️ 14s ALTERNATE, NOT A LOOP THAT SNAPS BACK. tcBreathe was 4.5% over
       30s — 0.15% a second, which reads as a photograph, not as a camera.
       This is 10% over 24s with a drift, 0.4% a second, and it reverses
       rather than cutting, so there is never a jump back to the start. */
    animation:tcFade 2.4s var(--tc-ease) .15s forwards,
              tcPhoneFilm 14s linear 1.4s infinite alternate;
  }
  .tc-notes{
    will-change:scale;
    transform-origin:50% 50%;
    animation:tcBreathe 30s var(--tc-ease) 1.4s infinite alternate;
  }

  /* ⚠️ THE LIGHT HAS TO BE WHERE THE NAME IS.
     Measured through the glyphs: CINEMA 1.56:1, SKINFX 1.26:1, the monogram
     1.71:1 — against 2.49 / 2.45 / 2.83 for the same gold on the desktop. The
     ink is identical in both. The ground is not: a pale rgb(244,237,224) wash
     on the desktop, rgb(174,155,139) of her hair here.

     The base .tc-veil aims its pool at 50% 6% and is 26% tall, so it has
     faded out by about 19% of the card — and on a phone the lockup runs 10%
     to 29%. SKINFX and the tagline are below the light that exists for them.

     --lock-x / --lock-y are already on .titlecard, already set per
     breakpoint, and the film's own scrim already follows them; only this
     base veil was carrying hardcoded coordinates. Pointing it at the
     variables fixes portrait AND the landscape case, where the block moves
     to 26% and a fixed 50% would light the wrong half of the screen. */
  /* ⚠️ AND IT KEEPS THIS VEIL WITH THE FILM ON, WHICH NEEDS THE SECOND
     SELECTOR TO SAY SO. `.titlecard.is-film-on .tc-veil` further up replaces
     the veil wholesale and outranks a bare `.tc-veil` three selectors to one,
     so switching the film on for a phone silently swapped in a wash that was
     cut for a full-bleed 16:9 desktop frame. Measured over this band: that one
     costs 3.58 of spread, this one 0.89 — four times as much, out of a picture
     this file spent a whole change recovering. Same rule, same specificity,
     later in the file, so it wins on order rather than on weight. */
  /* ⚠️ THIS IS NOT A TINT ANY MORE, IT IS THE LEGIBILITY. Asked for in as
     many words — "add something para maging light yung video and makita ang
     logo and business name". Every line on this screen is now read on
     moving footage, so the cream that used to sit in the lower half as
     BACKGROUND has to be supplied here as a wash.
     Direction: LIFT, never darken. The note on the film-state veil further
     up this file measured a dark scrim behind pale gold and found it the
     wrong way round on this footage — the frame is a bright wall, the gold
     sat lighter than the scrim and the two converged at 1.3:1. The wall is
     already bright, so the wash only has to finish what it started.
     The pool follows --lock-x / --lock-y, which is why the lockup moving to
     the middle of the card moves --lock-y with it. */
  .tc-veil,
  .titlecard.is-film-on .tc-veil{
    background:
      /* ⚠️ SHORT AND HIGH NOW. At 34% tall from 21% down it reached to 55%
         of the card and laid a near-opaque wash over the whole photograph.
         The lockup is in the header band here — 1.4% to 8.3% — so the light
         belongs there and nowhere else. */
      /* ⚠️ THE POOL CAME DOWN BECAUSE THE SHEET WENT UP. At .90 with a sheet
         of .36 under it the lockup's ground measured 88.9 and the promise
         two lines below it measured 56.2 — a bright disc with the rest of
         the copy falling off the edge of it. The sheet now carries the card
         and this only finishes the gold, which is the one ink here that
         cannot be darkened: the ramp is the brand's and another session
         logged that deliberately. */
      radial-gradient(98% 19% at var(--lock-x) var(--lock-y),
        rgba(253,250,245,.75) 0%,
        rgba(252,249,242,.57) 48%,
        rgba(250,246,236,.27) 78%,
        rgba(247,241,229,0) 100%),
      /* ⚠️ CLEARED ACROSS THE BAND. This ran .34 / .14 / .20 / .52 down the
         whole card, which is a pale sheet laid over the photograph — measured
         at 68% of all the clarity there was to recover. The photograph lives
         between 11% and 49.5%, so the wash is taken to .02 through there and
         kept at both ends: the top is the lockup's ground, the bottom is the
         cream the headline and the sub are read on. */
      /* ⚠️ THESE STOPS ARE PERCENTAGES OF THE CARD, NOT OF THE PICTURE, so
         they do not follow it on their own. The clear window was cut for a
         band running 11% to 49.5%, moved once for 13.5% to 63.5%, and the
         framed picture closes at about 58.5% — so the .17 -> .52 ramp came
         up by five points with it. Leaving them put drops that ramp back
         across the picture's lower third, which is the exact wash that
         measured 68% of all the clarity there was to recover.
         The foot moves by about two points across phone sizes now that the
         band is sized off the width; these are cut for the middle of that. */
      /* ⚠️ AND THE CLEAR WINDOW IS GONE. These stops used to open a hole at
         .02 through the middle of the card because the PICTURE was there and
         a wash over it was measured at 68% of all the clarity there was to
         recover. The picture is the whole card now and the copy is on it, so
         a hole in the middle is a hole where the headline is. It runs as one
         even wash instead, heaviest at the two ends where the type is
         densest. */
      /* ⚠️ AND THE SHEET IS THE HALF OF IT THAT CAN GO TOO FAR. At .74 /
         .58 / .54 / .60 / .78 every line on the card read comfortably and
         the film had gone: a pale cream screen with a suggestion of hair in
         it. The point of putting the film behind the copy is that it is
         still a film. These are the lowest values that hold the type —
         see the measured table in the README — and they are deliberately
         heavier at the two ends, where the lockup and the closing line are,
         than through the middle, where the copy sits on the darkest part of
         the frame anyway. */
      /* ⚠️ THESE ARE THE FIGURES THE MEASUREMENTS ASKED FOR, not a look.
         Ground luminance under each line, wash before -> after:
           lockup   88.9   promise 56.2   closing 41.7
         .36 through the middle put the promise at 3.62:1 against the 4.5 a
         13px line owes and the closing line at 1.85:1. Solving each for the
         ground that gets it to 4.5 gives .64-.65 of cream through the whole
         type block, which is what these stops are.
         ⚠️ The two ENDS are deliberately left open. The film is the point of
         this layout; a sheet that is even from edge to edge is the version
         that was tried first and it erased the picture. The top 12% and the
         bottom 10% are where the film is still film. */
      linear-gradient(180deg,
        /* the top 12% and the 55-85% band are the film. Everything else is
           carrying a line of type — see the table at the head of this rule */
        rgba(252,249,242,.34) 0%,
        rgba(252,249,242,.38) 12%,
        rgba(251,247,238,.60) 26%,
        rgba(250,246,236,.66) 42%,
        /* ⚠️ THE TAPER STARTS AT 54, NOT AT 42. Started earlier, the
           interpolated value at 47.5% — where the promise sits — drops from
           .66 to about .62 and takes that line back under 4.5:1. The stop
           that matters is not the one nearest the type, it is the pair the
           type is interpolated between. */
        rgba(250,246,236,.66) 54%,
        rgba(250,245,234,.50) 68%,
        rgba(249,244,232,.46) 84%,
        /* the closing line is pinned to the floor, so the floor cannot be
           the clearest part of the card: at .34 it measured 4.46:1 against
           4.5 even with the darker ink */
        rgba(248,242,230,.48) 92%,
        rgba(246,239,225,.46) 100%);
  }

  /* The labels land on the subject here rather than beside her, so the ink
     goes back to the darker bronze to hold contrast over hair and skin. */
  .tc-notes{--note-ink:#4A3B26;}
  .tc-label span{color:#5E4E38;font-weight:500;}

  /* The tagline sits on the same hair and skin as those labels and was left
     on the desktop bronze. Measured through a glyph mask at 393x659: ink
     L.127 against a ground of L.302, which is 2.0:1 for an 11px line — the
     note ink above scores 3.6:1 on the same pixels. Same ink, same reason.

     Not touching the gold of the wordmark: that ramp is the brand's, it was
     settled deliberately, and it is carried by its own keyline rather than by
     its fill. Measured for the record, not to be changed — CINEMA 1.01:1 and
     SKINFX 1.41:1 on fill alone. */
  .tc-tag{--tc-tag:#4A3B26;}

  /* ⚠️ The lockup used to bottom out on every phone made. Both lines are
     clamped against vw — clamp(25px,3.4vw,46px) and clamp(18px,2.4vw,33px) —
     and 3.4vw only reaches the 25px floor at a 735px viewport, so a 393px
     screen and a 320px screen got byte-identical type. The result measured
     100.6 x 47.1: a brand name 26% of the screen wide, under a TAGLINE that
     ran 267px, or 68%. The subtitle outweighed the title by 2.7 times.

     min(vw, svh) rather than vw alone, the same as #why: a phone held on its
     side is 660px wide and 360 tall, and a name sized off width alone would
     not fit the height it has left. */
  .tc-mark{
    /* the comp's mark is 70px of a 740px screen — 37px at 393, not 46-68 */
    /* ⚠️ AND NOW UNDER THE COMP, ASKED FOR. At 37.3px this was the largest
       single thing in the band — 41% of its height, more than the name and
       the tagline together. It is a monogram sitting directly above the
       word it stands for, so it is the one element here that can give up
       height without giving up meaning: 27.9px at 393, and still wider
       than the cap height of the name under it.
       Nearly all of the 14px this change needed comes from here, so that
       the name can keep the size it was just matched to a reference at. */
    /* ⚠️ AND BACK UP AGAIN, BECAUSE THE BAND GREW. 27.9px was the size that
       fitted a 91px band; the band is 115px now and asked to be roomier
       "for logo and name", and a mark left at the smaller size would read
       as lost in it rather than as given room. 31.8px at 393 — still under
       the 37.3px it started at. */
    width:clamp(27px,8.1vw,34px);
    /* the comp runs the mark straight into the name, 44 to 44 */
    margin-bottom:2px;
    /* ⚠️ THE BASE FILTER IS A WHITE HALO, and it was right when this sat on
       her hair. The veil above now lays a pale wash under the whole lockup,
       and a white glow on a near-white ground is invisible work. A dark
       keyline is what defines a small gold mark against pale. */
    filter:
      drop-shadow(0 0 .9px rgba(46,33,6,.72))
      drop-shadow(0 1px 3px rgba(46,33,6,.32))
      drop-shadow(0 5px 16px rgba(154,120,32,.22));
  }

  /* ⚠️ SMALL TYPE IS MOSTLY EDGE. CINEMA is 37.7px here against 46px on a
     desktop, so proportionally far more of each glyph is antialiased — and an
     edge pixel is a blend of ink and ground, which now lightens it because
     the ground is pale. Measured through the glyphs: the same gold reads
     rgb(189,169,121) here and rgb(168,148,100) on a desktop.
     The stylesheet already says this wordmark is carried by its keyline
     rather than by its fill. This is that, turned up for the size — and it
     leaves the brand's gold ramp exactly where another session settled it. */
  .tc-word{
    filter:
      drop-shadow(0 0 .9px rgba(46,33,6,.9))
      drop-shadow(0 0 2.4px rgba(46,33,6,.44))
      drop-shadow(0 1px 3px rgba(46,33,6,.34));
  }
  /* ⚠️ THE TWO LINES MATCH HERE, because they are one line here. Stacked,
     "Cinema" leads and "SkinFX" is the smaller second line; set side by side
     as the comp has them, that difference reads as a mistake. */
  .tc-line-1,
  .tc-line-2{font-size:clamp(16px,5.2vw,22px);letter-spacing:.055em;text-indent:0;}

  /* ⚠️ A DEEPER GOLD, AND ONLY ON A PHONE.
     Measured against the supplied reference, both read the same way —
     glyph cores against the paper:

         reference   3.46:1   ink rgb(152,126,74)   sat 0.51
         shipped     2.75:1   ink rgb(164,144,93)   sat 0.43

     Three things were washing it out, all of them inside the letterforms:
     the ramp's pale stop (#EFDDA3 at 40%), the bevel laying
     rgba(255,251,232,.40) across the top quarter of every letter, and the
     shine sweeping a white streak through. At 46px those read as struck
     foil; at 20px they are most of the letter.

     So on a phone the name is one ramp with no pale stop and nothing over
     it. The desktop keeps the brand's foil exactly as it was settled. */
  .tc-line-1,
  .tc-line-2{
    --gold:linear-gradient(101deg,
      #7E6228 0%, #9B7B35 24%, #BE9F5C 50%, #9B7B35 76%, #795E23 100%);
    background-image:var(--gold);
    background-size:100% 100%;
    background-position:0 0;
  }
  /* the keyline does more work now that the fill is not carrying a highlight */
  .tc-word{
    filter:
      drop-shadow(0 0 .8px rgba(46,33,6,.55))
      drop-shadow(0 1px 2.5px rgba(46,33,6,.30));
  }
  .tc-rule{width:min(150px,38vw);}

  /* No bar over the front page. is-cover is on the header for as long as the
     title card is the thing you are looking at (main.js: y < card height -
     140), so this hides it exactly there and hands it back the moment you
     scroll into the page. Nothing moves when it goes: the header is
     position:sticky, its flow band is the top 75px of the document, and the
     card is already pulled up over that band — so this changes what is
     painted, not what is laid out.

     Not display:none. The bar has to be able to slide back in and a display
     swap has nothing to animate; opacity and translate do, and they leave the
     flow alone so the card cannot jump as the class flips. */
  /* ⚠️ THE RULE THAT USED TO BE HERE HID THE BAR OUTRIGHT
     (opacity:0; translate:0 -100%). The comp puts the burger and the bag in
     that band, so it is gone rather than overridden — it sat LATER in this
     same block than its replacement and quietly won. */
}

/* ---------- A short phone ----------
   Measured at 360x740 once the round links went in: the closing line landed
   5px under them, where the same gap at 393x852 is 92px.

   ⚠️ EVERYTHING BELOW THE PICTURE IS FIXED PX NOW — 46px pills, 44px circles,
   and type already floored for legibility — so a screen 112px shorter has
   nowhere to absorb it. The photograph is the only element here measured as a
   share of the card rather than in pixels, so it is the one that gives the
   room back. Nothing raised for a thumb or for reading is touched.

   The headline's offset has to come down by the same amount, because it is
   stated as the gap from the tagline to just past the picture's lower edge —
   move one without the other and the copy lands on the photograph. */
@media (max-width:720px) and (max-height:800px){
  /* The 47% band that used to be shortened here no longer exists: the film
     is the card. What is left in this block is the gentler camera move. */
  /* and a gentler camera move, for the same reason the picture is shorter */
  .tc-photo{
    animation:tcFade 2.4s var(--tc-ease) .15s forwards,
              tcPhoneFilmShort 14s linear 1.4s infinite alternate;
  }
  /* ⚠️ THE 51svh THAT WAS HERE IS GONE WITH THE BAND. It was the short
     screen's version of stepping over the picture — "the picture closes at
     447.7 and the headline opened at 441.7" — and there is no picture in
     the column to step over any more. The clamp() on .tc-head shortens
     itself on a short screen, which is the whole reason it is a clamp. */
}

/* A phone held sideways is still a phone — under 720px wide, and over the
   7/5 aspect ratio that hands .tc-content to the wide layout further up this
   file. That layout takes the block OUT OF FLOW (position:absolute, left:17%,
   translate:-50% -50%, padding:0) and my portrait padding-top lands on the
   same element from a LATER rule, so it won.

   Measured at 659x393 before this block existed: 81px of padding grew a
   centred box upward until its top sat at -8, and the tagline ran from -10 to
   234 — off the left edge of the screen. There is nothing to pad away from
   here: the block is positioned, not flowed, so the header is not above it.

   left:17% is also too far in for a 659px frame. The tagline is 244px wide
   and centred on that anchor, so it needs 122px of room on each side plus the
   20px gutter — 142px, or 21.5%. 26% clears it at every width this block can
   see. --lock-x moves with it because the film scrim reads that variable to
   follow the lockup; leaving one behind would part the light from the type. */
@media (max-width:720px) and (min-aspect-ratio:7/5){
  .titlecard{--lock-x:26%;}

  /* ⚠️ SIDEWAYS GETS THE SAME FULL-BLEED FILM, which is what it wants and
     what the desktop has always done — .tc-content is out of flow at
     left:26% here, so the film is the ground behind it either way. The
     override that used to sit here put back a 47% band, and there is no
     band left to put back. Sideways still takes the WIDE cut, because
     chooseCut reads the portrait media query and not this one. */

  /* top:27svh is 106px on a 393px-tall frame, and the block is 148px tall
     centred on it — so it opened at y=32 with a 75px header over the top of
     it, and the monogram was cut in half by the glass. 42svh puts the centre
     at 165 and the top at 91, clear of the header, with the block ending at
     239 and the scroll cue not starting until 290.

     ⚠️ THE BLOCK IS NOT 148px TALL ANY MORE — it is about 332, because the
     lockup and the copy are one group on the film now instead of a lockup
     with a picture between it and the rest. 42svh centres that on 165, which
     opens it at −1: the wordmark under the burger and off the top of the
     screen. 50svh centres it on the screen's own middle, which is where a
     block this tall has to sit.

     ⚠️ AND min-height:0, BECAUSE THE AUTO MARGINS DO NOT BELONG HERE. The
     pair on .tc-mark and .tc-foot centre the group against a full portrait
     screen; this block is out of flow and centred by translate, so a
     min-height of 100svh only feeds those margins free space to push the
     group apart with. Zero it and the column shrink-wraps, which is what
     translate:-50% expects to be centring.
     Before this rule the tagline measured at y −65 and the closing line at
     417 on a 393-tall screen — both off it, at opposite ends, and that was
     true of the band and the framed card too. */
  .tc-content{padding-top:0;left:26%;top:50svh;min-height:0;}
}

/* ---------- Touch ----------
   ⚠️ Every callout on this card opens on :hover, and this device has none —
   the emulated handset reports (hover:none) and (pointer:coarse). Hiding the
   prompt was the first answer and it was the wrong one: the marks are still
   DRAWN as things that do something, so they have to do it. main.js puts
   .is-open on a tap, and every rule below is the pointer version of itself
   fired by a class instead.

   Two layers carry callouts and only one is ever up at a time: .tc-hot over
   the film, .tc-notes over the still (see the is-film-on rules above). Both
   are wired, because a phone gets the still upright and the film on its side.

   ⚠️ Ask about the POINTER, not the width. The first version of this hid the
   hover prompt on a width rule; turn the same phone on its side and it is
   659px wide, the rule stops matching, and the page goes back to inviting a
   gesture the hardware cannot make. Measured: it reappeared at 659x393, on
   top of the "dull skin" label. */
@media (max-width:720px){
  /* ⚠️ A PLATE THAT IS 63px WIDE SETS ONE WORD PER LINE. Same shape as the
     .tc-fact plate the touch layout uses a few rules down — sized to its
     content, capped against the viewport, rather than to a share of a frame
     that is only wide on a desktop. */
  .tc-hot-fact{width:max-content;max-width:min(74vw,260px);}
}

@media (hover:none) and (pointer:coarse){

  /* A 38px mark is not a target. This is the thing being offered to a finger,
     so it gets the 44 every touch guideline asks for. */
  /* !important because --s is INLINE on every .tc-note in the markup, the
     same reason --len needs it in the 620px block. Without it this rule loses
     to the attribute and the mark stays 38px — measured, and it did. */
  .tc-note{--s:clamp(46px,12vw,64px) !important;cursor:pointer;}
  /* ⚠️ var(--tc-tag), NOT THE SAME HEX TYPED AGAIN. #7A5E1A is declared
     twelve lines into this file as --tc-tag, with the contrast note that
     justifies it, and .tc-note is inside .titlecard so the variable is in
     scope. The other three focus rings on this page all name a token; this was
     the only one that did not, which is how a colour drifts out of step with
     the note that vouches for it. Identical pixels, one source. */
  .tc-note:focus-visible{outline:2px solid var(--tc-tag);outline-offset:6px;border-radius:4px;}

  .tc-notes.has-open .tc-note{opacity:.42;}
  .tc-notes .tc-note.is-open{opacity:1;z-index:4;}

  /* The fact plate hangs off the MARK, not off the label. The label is
     already pushed to one side by a lead line — at --x:56% its right edge is
     315px into a 393px screen, and a 240px sentence hung off that would end
     at 555. Centred under the mark it spans 100..340 at 393 and 61..297 at
     320, inside the gutter at every width this block can see. */
  .tc-note .tc-fact{
    display:none;
    position:absolute;
    left:50%;top:calc(100% + 10px);
    translate:-50% 0;
    width:max-content;max-width:min(74vw,260px);
    padding:9px 12px;
    border-radius:9px;
    background:rgba(255,251,243,.96);
    box-shadow:0 6px 26px rgba(40,30,12,.15),
               inset 0 0 0 1px rgba(154,120,34,.18);
    color:#4E3B10;   /* 8:1 on the plate */
    font-family:var(--f-body);
    font-size:11.5px;font-weight:400;line-height:1.45;letter-spacing:.005em;
    text-align:left;
    text-shadow:none;
    pointer-events:none;
  }
  .tc-note.is-open .tc-fact{display:block;animation:tcFade .34s var(--tc-ease) forwards;}
  /* the lower mark sits at 72% of the card, so its plate opens upward or it
     would land on the scroll cue at 549 */
  .tc-note:nth-child(4) .tc-fact{top:auto;bottom:calc(100% + 10px);}

  /* The film's boxes are percentages of the CLIP, so their size is the
     clip's decision, not ours — measured 34x36 at 659x393, which is a fine
     target for a mouse and a mean one for a thumb. The drawn frame must not
     move (it has to stay registered to the box painted into the footage), so
     the TARGET grows and the picture does not: a transparent pseudo-element
     8px outside it on every side, which takes the touch on its behalf.
     34x36 becomes 50x52. */
  .tc-hot-box::before{content:"";position:absolute;inset:-8px;}

  /* the film layer, same states */
  .tc-hot-spot.is-open .tc-hot-fact{opacity:1;scale:1;translate:0 0;transition-delay:.11s;}
  .tc-hot-box.is-open .tc-hot-ring{opacity:1;scale:1.24;}
  .tc-hot-box.is-open .tc-hot-comet::before{animation-play-state:running;}

  /* Nobody taps a mark they were not told about. The prompt runs on the still
     as well as the film now — main.js swaps its word to "Tap" — and it still
     retires for good the first time anything is opened.

     ⚠️ Its top offset is measured from the header, and on a phone there is no
     longer a header over this card. At the old offset the pill started at
     x=200 against a monogram centred on 172..220, so it landed on the mark.
     The bar's vacated band is exactly where it belongs. */
  .tc-hint{display:inline-flex;top:clamp(14px,3svh,26px);}
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion:reduce){
  .tc-wash,.tc-frond-a,.tc-frond-b,.tc-silk,.tc-w1,.tc-w2,.tc-w3,.tc-w4,
  .tc-sheen,.tc-sheen-2,.tc-spin,.tc-arc,.tc-line,.tc-rule,.tc-tag,.tc-cue,
  .tc-cue-line::after{
    animation:none !important;
  }
  .tc-wash,.tc-tag,.tc-cue,.tc-photo{opacity:1;}
  .tc-silk{opacity:.58;}
  /* the push-in is motion by definition, and .tc-notes only ever carries it */
  /* ⚠️ IT DRIFTS NOW AS WELL AS SCALING, AND THE FIX FOR THAT IS TO DO
     NOTHING. The first attempt added `translate:none !important` here on the
     reasoning that the reset should state the resting value rather than rely
     on it — which is exactly backwards, because THERE IS NO ONE RESTING
     VALUE. The base rule centres the photograph with `left:50%;
     translate:-50% 0`; only the phone block, where it is full-bleed, sets
     `translate:none`. One !important covering both breakpoints would have
     shoved the desktop still half its own width to the right for every
     visitor who asks for reduced motion.
     `animation:none` already hands the element back to the cascade, which
     holds the right value for whichever breakpoint is live. */
  .tc-photo,
  .tc-notes{animation:none !important;scale:1 !important;}
  /* ⚠️ opacity:1 IS LOAD-BEARING HERE. The entrance starts these at opacity:0
     and animates them up; kill the animation without restoring the resting
     state and the whole front screen is simply invisible. */
  .tc-head,.tc-promise,.tc-acts,.tc-cards,.tc-foot{
    animation:none !important;opacity:1 !important;translate:0 0;
  }
  .tc-shop::after,
  .tc-card::after{animation:none !important;opacity:0;}
  .tc-cards{scroll-behavior:auto;}
  .tc-frond-a{opacity:.12;scale:1;}
  .tc-frond-b{opacity:.07;scale:1;}
  .tc-sheen{opacity:.75;}
  .tc-arc{stroke-dasharray:var(--dash);opacity:1;}
  .tc-line{clip-path:none;}
  .tc-box,.tc-lead,.tc-label,.tc-spark,.tc-cue-spark{animation:none !important;}
  .tc-lead::before{animation:none !important;opacity:1;}
  .tc-motes{display:none;}
  .tc-arc,.tc-spin,.tc-line{animation:none !important;}
  .tc-arc{stroke-dasharray:var(--dash);opacity:1;rotate:var(--base);}
  .tc-hot-comet::before{animation:none !important;}
  .tc-hot-ring,.tc-hot-fact{transition:none !important;}
  .tc-hint{animation:none !important;display:none !important;}
  /* Reduced motion falls back to the still, so the film must not paint. */
  .tc-film{display:none !important;}
  .tc-box::before{animation:none !important;opacity:0;}
  .tc-box{opacity:1;scale:1;}
  .tc-lead{width:var(--len);}
  .tc-label{opacity:1;}
  .tc-rule{scale:1 1;}
  .tc-tag{letter-spacing:.3em;}
}

@media print{
  .titlecard{min-height:0;padding:40px 0;margin-top:0;}
  .tc-bg,.tc-cue{display:none;}
}

/* ---------- Phone legibility ----------
   Audited at 390x844. Three runs of type on this card were under the floor:
   the tagline at 7.5px, the scroll cue at 8.5px and the hotspot labels at
   9 to 9.5px. All three are clamp()ed against vw, so a phone lands on the
   bottom stop and the bottom stop was too low.

   ⚠️ The tracking has to come down as the size goes up. "PREMIUM CINEMATIC
   SKINCARE" is 26 characters; at 11px with the desktop's .6em of tracking it
   would run about 354px, which does not fit a 390px screen once the card's
   own padding is taken off. At .22em it runs about 245px. */
@media (max-width:700px){
  /* ⚠️ letter-spacing:.22em here is NOT what the finished line ends up at.
     tcTag is an animation-fill-mode:forwards animation whose to-frame sets
     letter-spacing:.3em, and a filled animation beats a plain declaration —
     so the settled tagline measured 266.8px wide, not the ~245px this rule
     was written for. Same trap that made the contrast mask read the wrong
     glyph positions earlier: the animation, not the rule, has the last word.
     Hand the phone its own keyframe so the two agree. */
  .tc-tag{font-size:11px;letter-spacing:.22em;animation-name:tcTagSm;}
  .tc-cue-text{font-size:10.5px;letter-spacing:.2em;}
  /* only two of the four notes survive below 620px, so there is room to give
     the two that remain a wider box to grow into */
  .tc-label{max-width:40vw;}
  .tc-label b{font-size:11.5px;}
  .tc-label span{font-size:11px;}
}


/* ===========================================================
   THE FRONT SCREEN ANSWERS THE POINTER
   "make everything here interactive aggalaw sila once i hover
   my mouse to them". Every element on the desktop card now has
   a state, and the three callouts already had theirs.

   ⚠️ THE HARD PART IS WHICH PROPERTY IS STILL FREE. Everything
     on this card lands on an entrance animation with forwards,
     and a filled animation beats an ordinary declaration however
     specific it is — so a hover written on a property the
     entrance already owns does nothing, silently. Read off the
     keyframes:

       .tc-mark      no animation of its own  -> scale, filter
       .tc-line-1/2  tcWipe clip-path, tcShine background-position
                                              -> translate
       .tc-rule      tcRule scale             -> transform, opacity
       .tc-tag       tcTag opacity/letter-spacing/translate
                                              -> scale, color
       .tc-cue       tcCue opacity            -> translate
       .tc-hint      tcCue opacity            -> translate, border

     That is why the tagline SCALES rather than shifts and the
     hairline changes WIDTH rather than scale: in both cases the
     obvious property was already taken.

   ⚠️ GATED ON (hover:hover) AND (pointer:fine). A phone resolves
     :hover on tap and holds it until you tap elsewhere, so an
     ungated hover state is a thing that sticks on a phone.
   =========================================================== */
@media (hover:hover) and (pointer:fine){

  /* ⚠️ WITHOUT THIS NOTHING BELOW CAN EVER FIRE. .tc-content is
     pointer-events:none — "the burger and shop pill sit on the same band" —
     and .tc-hint sets its own, so every element here was unreachable and every
     state was correct CSS that no pointer could touch. Measured: the topmost
     element at the centre of each of them was .titlecard, not the element.

     ⚠️ THE CONTAINER KEEPS ITS none. Only the pieces get a pointer back, so
     the empty air around the lockup stays transparent and the header controls
     under it are still reachable. min-width:721px because below that the phone
     layout puts the lockup INTO the header band, on top of the burger. */
  @media (min-width:721px){
    .tc-mark,.tc-word,.tc-tag,.tc-hint{ pointer-events:auto; }
  }

  /* --- the monogram: it leans in and the halo swells --- */
  .tc-mark{
    transition:scale .5s var(--tc-ease), filter .5s var(--tc-ease);
    cursor:default;
  }
  .tc-mark:hover{
    scale:1.07;
    filter:
      drop-shadow(0 0 26px rgba(255,252,244,1))
      drop-shadow(0 0 56px rgba(255,246,214,.78))
      drop-shadow(0 6px 18px rgba(154,120,32,.42));
  }

  /* --- the wordmark: the two lines part, and the hairline
         under them opens with the pair --- */
  .tc-line-1,.tc-line-2{ transition:translate .45s var(--tc-ease); }
  .tc-word:hover .tc-line-1{ translate:0 -3px; }
  .tc-word:hover .tc-line-2{ translate:0 3px; }

  /* ⚠️ transform, NOT width, AND NOT scale.
     - width ran BACKWARDS: a fixed min(186px,32vw) is narrower than the 194px
       this line rests at on a desktop, so hovering closed it. Measured
       194 -> 186. The resting width is 132, 150 or 194 depending on the
       breakpoint, so no single fixed value can be "wider" at all of them.
     - scale is owned by tcRule, which animates the scale PROPERTY to 1 1 with
       forwards and would beat any declaration here.
     - transform is a separate property, composes with scale, is set by nothing
       else on this element, is proportional at every breakpoint, and costs no
       layout. */
  .tc-rule{ transition:transform .5s var(--tc-ease), opacity .5s var(--tc-ease); }
  /* no .tc-rule:hover — the hairline is 1px tall and a one-pixel target is not
     a target. It opens from its siblings instead. */
  .tc-word:hover ~ .tc-rule,
  .tc-mark:hover ~ .tc-rule{ transform:scaleX(1.22); opacity:1; }

  /* --- the tagline: scale, because tcTag owns translate and
         letter-spacing all the way to its resting values --- */
  .tc-tag{
    transition:scale .45s var(--tc-ease), color .45s var(--tc-ease);
    transform-origin:50% 50%;
  }
  .tc-tag:hover{ scale:1.05; color:#5F4912; }

  /* --- the skin-facts hint: it lifts and the ring warms --- */
  .tc-hint{
    transition:translate .4s var(--tc-ease),
               border-color .4s var(--tc-ease),
               background-color .4s var(--tc-ease);
  }
  .tc-hint:hover{
    translate:0 -2px;
    border-color:rgba(154,120,32,.85);
    background-color:rgba(255,255,252,.99);
  }

  /* --- the scroll cue: it nods toward the scroll it is asking
         for, and its own two loops quicken --- */
  .tc-cue{ transition:color .3s var(--tc-ease), translate .4s var(--tc-ease); }
  .tc-cue:hover{ translate:-50% 4px; }
  .tc-cue:hover .tc-cue-spark{ animation-duration:1.2s; }
  .tc-cue:hover .tc-cue-line::after{ animation-duration:1.1s; }

  /* --- the callout labels already move; this only deepens the
         ink so the pair reads as one response --- */
  .tc-note:hover .tc-label{ color:#241B0E; }
}

/* ⚠️ AND NONE OF IT UNDER REDUCED MOTION. The colour stays, because a colour
   change is not motion and it is what tells a pointer user the thing is
   responsive at all; the travel and the scale go. */
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:reduce){
  .tc-mark:hover{ scale:1; }
  .tc-word:hover .tc-line-1,
  .tc-word:hover .tc-line-2{ translate:0 0; }
  .tc-word:hover ~ .tc-rule,
  .tc-mark:hover ~ .tc-rule{ transform:none; }
  .tc-tag:hover{ scale:1; }
  .tc-hint:hover{ translate:0 0; }
  .tc-cue:hover{ translate:-50% 0; }
  .tc-cue:hover .tc-cue-spark,
  .tc-cue:hover .tc-cue-line::after{ animation-duration:inherit; }
}
