/* ---------- BENTO GALLERY ----------
   rig: bento-gallery (creative/rigs/bento-gallery/EXTRACTION.md)

   The rig is banked as a CONCEPT, not a file: the 21st.dev source is paywalled,
   so the mechanism is rebuilt rather than copied. Its three FIXED properties are
   honoured here:
     1. an interlocking mixed-size grid with no empty cells,
     2. a caption anchored bottom-left that strengthens on hover,
     3. click a tile to expand it into a focused view.

   Its DIALS, and the setting taken for this site:
     span pattern      deliberate, hand-placed below. Never randomised, the
                       varied rhythm is the whole look.
     drag vs scroll    scroll. The rig offers both; a brochure page read on a
                       phone is the wrong place for a horizontal drag track.
     expand style      morph, not a hard modal swap. The tile's own rectangle
                       grows into the focused rectangle.
     scrim             gradient from the foot, plus a flat rest veil that lifts
                       off the tile under the pointer.

   Plain CSS grid and vanilla JS. No framer-motion, no framework runtime: this
   ships as static files onto shared hosting. Tokens are the site's own. */

/* The row this replaced carried margin-top:clamp(1.8rem,4vw,3rem) off the
   section head. Keeping that measurement rather than inventing a new one, so
   the rhythm under the head is the same as it is on Home. */
.bento-wrap{margin-top:clamp(1.8rem,4vw,3rem)}
.bento-rubric{
  display:flex;align-items:center;gap:1rem;
  color:var(--dim-2);margin:0 0 1.35rem;
}
.bento-rubric .rule{flex:1}

/* ---------- the grid ----------
   Six columns, eleven rows, sixty-six cells, every one of them filled. The
   map below is the layout: row-start / column-start / row-end / column-end.

     rows 1-2   camera rig (tall)      island shoot (wide)
     rows 3-4   camera rig             dusk drone     jeep crew
     rows 4-6   jungle gear (tall)     mountain dusk (wide)
     rows 7-8   beach follow (wide)                   motion control (tall)
     rows 9-11  magenta dolly (tall)   red monitor (tall)   sand break

   The two wide tiles at rows 5-6 and 7-8 sit on opposite sides of the grid so
   they interlock rather than stack into stripes. */
.bento{
  --g:14px;
  --r:clamp(104px,13.2vw,192px);
  display:grid;
  grid-template-columns:repeat(6,minmax(0,1fr));
  grid-auto-rows:var(--r);
  gap:var(--g);
  margin:0;
}

.bt--rig    {grid-area: 1 / 1 /  4 / 3}
.bt--island {grid-area: 1 / 3 /  3 / 7}
.bt--drone  {grid-area: 3 / 3 /  5 / 5}
.bt--jeep   {grid-area: 3 / 5 /  5 / 7}
.bt--jungle {grid-area: 4 / 1 /  7 / 3}
.bt--mount  {grid-area: 5 / 3 /  7 / 7}
.bt--studio  {grid-area: 7 / 1 /  9 / 5}
.bt--motion {grid-area: 7 / 5 / 10 / 7}
.bt--dolly  {grid-area: 9 / 1 / 12 / 3}
.bt--red    {grid-area: 9 / 3 / 12 / 5}
.bt--sand   {grid-area:10 / 5 / 12 / 7}

/* ---------- the tile ---------- */
.bt{
  position:relative;overflow:hidden;
  min-width:0;min-height:0;
  border:0;padding:0;margin:0;border-radius:14px;
  background:#0b0b0c;color:inherit;font:inherit;text-align:left;
  -webkit-appearance:none;appearance:none;cursor:pointer;
}
.bt img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;
  transition:transform .8s cubic-bezier(.16,.84,.3,1);
}
.bt:hover img,.bt:focus-visible img{transform:scale(1.045)}

/* rest veil: unfocused tiles sit back, the one under the pointer brightens */
.bt::before{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:#000;opacity:.26;transition:opacity .5s ease;
}
.bt:hover::before,.bt:focus-visible::before{opacity:0}

/* gradient scrim under the caption, always on, stronger on hover */
.bt::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:62%;z-index:1;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.34) 46%,rgba(0,0,0,.86) 100%);
  opacity:.9;transition:opacity .5s ease;
}
.bt:hover::after,.bt:focus-visible::after{opacity:1}

/* the affordance: a hairline accent frame draws in, echoing the hero's
   viewfinder corners rather than bolting a new icon onto the page */
.bt-fr{
  position:absolute;inset:10px;z-index:2;pointer-events:none;border-radius:7px;
  border:1px solid var(--mag);
  opacity:0;transform:scale(1.015);
  transition:opacity .4s ease,transform .55s cubic-bezier(.16,.84,.3,1);
}
.bt:hover .bt-fr,.bt:focus-visible .bt-fr{opacity:.9;transform:none}

.bt-cap{
  position:absolute;left:0;right:0;bottom:0;z-index:3;
  padding:clamp(.8rem,1.5vw,1.15rem) clamp(.85rem,1.6vw,1.25rem);
  pointer-events:none;
  font-family:var(--mono);font-size:.6rem;line-height:1.55;
  letter-spacing:.12em;text-transform:uppercase;
  color:rgba(255,255,255,.86);
  text-wrap:pretty;
  transform:translateY(5px);
  transition:color .45s ease,transform .5s cubic-bezier(.16,.84,.3,1);
}
.bt:hover .bt-cap,.bt:focus-visible .bt-cap{color:#fff;transform:none}

.bt:focus-visible{outline:2px solid var(--mag);outline-offset:3px}

/* stagger the reveal left to right across each band. site.js observes every
   .rev on the page, so each tile lights as it enters on its own. */
.bt.rev{transition-delay:0s}
.bt--island.rev,.bt--mount.rev,.bt--red.rev{transition-delay:.07s}
.bt--jeep.rev,.bt--motion.rev{transition-delay:.13s}
.bt--sand.rev{transition-delay:.19s}

.vh{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ---------- narrow screens ----------
   Six columns is too fine below roughly a tablet, so the map switches to two
   columns with the tiles sized by aspect instead of by row unit. Still hand
   placed, still no empty cells. */
@media (max-width:820px){
  .bento{
    --g:10px;
    grid-template-columns:repeat(2,minmax(0,1fr));
    grid-auto-rows:auto;
  }
  .bt--island{grid-area:1 / 1 / 2 / 3;aspect-ratio:16/9}
  .bt--rig   {grid-area:2 / 1 / 3 / 2;aspect-ratio:3/4}
  .bt--jungle{grid-area:2 / 2 / 3 / 3;aspect-ratio:3/4}
  .bt--drone {grid-area:3 / 1 / 4 / 2;aspect-ratio:1/1}
  .bt--jeep  {grid-area:3 / 2 / 4 / 3;aspect-ratio:1/1}
  .bt--studio {grid-area:4 / 1 / 5 / 3;aspect-ratio:16/9}
  .bt--motion{grid-area:5 / 1 / 6 / 2;aspect-ratio:3/4}
  .bt--red   {grid-area:5 / 2 / 6 / 3;aspect-ratio:3/4}
  .bt--mount {grid-area:6 / 1 / 7 / 3;aspect-ratio:16/9}
  .bt--dolly {grid-area:7 / 1 / 8 / 2;aspect-ratio:1/1}
  .bt--sand  {grid-area:7 / 2 / 8 / 3;aspect-ratio:1/1}

  .bt{border-radius:10px}
  .bt-fr{inset:7px;border-radius:5px}
  .bt-cap{font-size:.55rem;letter-spacing:.1em;transform:none}
}

/* ---------- the focused view ----------
   The rig calls for a shared-layout morph rather than a hard modal swap. With
   no framer-motion, the tile's own rectangle is measured on click and the
   focused frame is planted there, then transitioned to the centred rectangle.
   The image is object-fit:cover throughout, and the target rectangle carries
   the image's own aspect, so cover and contain agree at rest and nothing is
   distorted on the way. */
.bl{position:fixed;inset:0;z-index:130;display:none}
.bl.open{display:block}

.bl-scrim{
  position:absolute;inset:0;background:rgba(4,4,5,.95);
  opacity:0;transition:opacity .38s ease;cursor:zoom-out;
}
.bl.show .bl-scrim{opacity:1}

.bl-frame{
  position:fixed;z-index:2;overflow:hidden;border-radius:10px;background:#0b0b0c;
  box-shadow:0 30px 90px rgba(0,0,0,.55);
  transition:
    left   .52s cubic-bezier(.2,.86,.24,1),
    top    .52s cubic-bezier(.2,.86,.24,1),
    width  .52s cubic-bezier(.2,.86,.24,1),
    height .52s cubic-bezier(.2,.86,.24,1),
    opacity .3s ease,
    transform .4s cubic-bezier(.16,.84,.3,1);
}
.bl-frame img{width:100%;height:100%;object-fit:cover;display:block;transition:opacity .16s ease}
.bl-frame.gone{opacity:0;transform:scale(.96)}

.bl-cap{
  position:absolute;left:0;right:0;bottom:0;z-index:3;margin:0;
  display:flex;align-items:baseline;justify-content:space-between;
  gap:1.2rem;flex-wrap:wrap;
  padding:1rem clamp(1.1rem,4vw,2.8rem) clamp(1.1rem,3vh,1.9rem);
  font-family:var(--mono);font-size:.66rem;line-height:1.5;
  letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.86);
  opacity:0;transform:translateY(9px);
  transition:opacity .4s ease .1s,transform .4s ease .1s;
}
.bl.show .bl-cap{opacity:1;transform:none}
.bl-cap .n{
  background:var(--accent);-webkit-background-clip:text;background-clip:text;
  color:transparent;white-space:nowrap;
}

.bl-btn{
  position:absolute;z-index:4;
  border-radius:50%;border:1px solid rgba(255,255,255,.28);
  background:rgba(0,0,0,.5);color:#fff;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  opacity:0;transition:opacity .35s ease .08s,background .3s ease,border-color .3s ease;
}
.bl.show .bl-btn{opacity:1}
.bl-btn:hover{background:var(--mag);border-color:var(--mag)}
.bl-btn:focus-visible{outline:2px solid var(--mag);outline-offset:3px}
.bl-nav{top:50%;margin-top:-26px;width:52px;height:52px;font-size:1.1rem}
.bl-prev{left:max(1rem,3vw)}
.bl-next{right:max(1rem,3vw)}
.bl-x{top:max(1rem,3vh);right:max(1rem,3vw);width:44px;height:44px;font-size:1rem}

@media (max-width:640px){
  .bl-nav{width:42px;height:42px;margin-top:-21px}
  .bl-cap{font-size:.58rem;letter-spacing:.12em}
}

@media (prefers-reduced-motion:reduce){
  .bt img,.bt::before,.bt::after,.bt-fr,.bt-cap,
  .bl-scrim,.bl-frame,.bl-frame img,.bl-cap,.bl-btn{transition:none !important}
}
