/*
 * instagram.css — the home page's Instagram band as a carousel (2.1.0).
 *
 * The band is Smash Balloon's free feed: square photographs laid out in a grid, inside our wash
 * (`motion.css`). This file turns that grid into a **wheel** — the focused slide centred, one post
 * each side at 72% scale and 45% opacity, an arrow each side stepping one post at a time — and
 * `public/js/instagram.js` does the only part CSS cannot: each slide's distance from the centre, as
 * an integer in `--dwd-offset`.
 *
 * Every rule is scoped to the state that script puts on the plugin's own container,
 * `#sb_instagram #sbi_images.dwd-carousel`. So with JavaScript off, or a script that never runs, the
 * plugin's 4-up grid is exactly what renders: the markup is the plugin's either way and there is no
 * half-carousel state to fall into. See `docs/adr/0012-instagram-band-carousel-of-the-plugins-grid.md`
 * and `CONTEXT.md` §7.
 *
 * ⚠ The plugin's own front-end script keeps running, and two of its behaviours reach in here:
 *
 *   • `setImageHeight()` stamps an inline `height` on every `.sbi_photo` — `#sbi_images` width ÷
 *     `data-cols`, re-stamped on resize — and inline styles lose to nothing else. It takes the one
 *     `!important` in this file. The *value* matters more than the override: the plugin's
 *     `img { height: inherit }` is what makes a slide square and `object-fit: cover` crop the
 *     photograph instead of hanging it from the top of its frame, and `auto` would hand a 4:5 photo a
 *     taller box than the slide it sits in.
 *   • `#sb_instagram #sbi_images .sbi_item { transition: all … }` animates any property we touch, so
 *     the transition this file wants is declared rather than assumed.
 *
 * Everything else wins on specificity, and the plugin's stylesheet loads before this one anyway. Its
 * inline `padding-bottom: 10px` on `#sb_instagram` is left alone deliberately: overriding it would
 * cost a second `!important` for nothing.
 *
 * ⚠ The scope carries **two ids** on purpose. `sbi-styles.min.css` writes its item rules as
 * `#sb_instagram #sbi_images .sbi_item` — two ids and a class — so a scope of
 * `#sbi_images.dwd-carousel .sbi_item` (one id, two classes) loses to it whatever the load order, and
 * the plugin's `width: 100%` and `transition: all …` come through: the slides then measure the whole
 * track and every step animates as `all`. Matching its two ids beats it on class count.
 */

/* 1. The frame — a wrapper the script creates around the track, so the arrows can be placed against
   the slides rather than against the feed, which also holds the profile header above them. It is also
   the clip: a slide more than one step out is invisible and must not widen the page. Its vertical
   padding is the 12px the plugin's own grid carried (`#sbi_images { padding: 12px 0 }`), so the band's
   rhythm above and below the photographs is unchanged. */
.dwd-carousel-frame {
  position: relative;
  overflow: hidden;
  padding-block: var(--wp--preset--spacing--12);
}

/* 2. The track — `#sbi_images`, carrying the state class. Every size the wheel has is one of these
   custom properties, which is why the 782px breakpoint is a couple of numbers rather than a second
   code path, and why resizing the window needs no JavaScript at all. */
#sb_instagram #sbi_images.dwd-carousel {
  --dwd-carousel-slide: min(38vw, 420px);   /* the focused slide, and the band's own height */
  --dwd-carousel-side: 0.72;                /* the neighbours, as a fraction of it */
  --dwd-carousel-side-opacity: 0.45;
  --dwd-carousel-duration: 480ms;           /* ours, not the plugin's `--sb-duration-*` tokens */
  /* Centre to centre: half the focused slide plus half a neighbour, so the three slots meet without
     overlapping and without a gap. Derived, so changing `--dwd-carousel-side` cannot drift from it. */
  --dwd-carousel-advance: calc(var(--dwd-carousel-slide) * (1 + var(--dwd-carousel-side)) / 2);

  display: block;                           /* the plugin sets grid; the slides are out of flow */
  position: relative;
  height: var(--dwd-carousel-slide);
  padding: 0;
}

/* 3. The slides. `left: 50%` and the -50% in the transform put every slide's centre on the track's
   centre, and `--dwd-offset` moves it an exact number of steps from there. The plugin's `.sbi_item`
   rule sets `width: 100%`; ours is narrower and more specific. */
#sb_instagram #sbi_images.dwd-carousel .sbi_item {
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--dwd-carousel-slide);
  transform: translateX(calc(-50% + var(--dwd-offset, 0) * var(--dwd-carousel-advance)))
    scale(var(--dwd-scale, 1));
  transition: transform var(--dwd-carousel-duration) ease,
    opacity var(--dwd-carousel-duration) ease;
}

/* The plugin fades the feed in by removing `sbi_transition` from each item about 500ms after it is
   built. While that class is on, its own `opacity: 0` has to keep winning, or the band appears
   before the photographs do; once it is gone, the wheel's own opacity takes over. */
#sb_instagram #sbi_images.dwd-carousel .sbi_item:not(.sbi_transition) {
  opacity: var(--dwd-opacity, 0);
}

#sb_instagram #sbi_images.dwd-carousel .sbi_item.dwd-slot-centre {
  --dwd-scale: 1;
  --dwd-opacity: 1;
}

#sb_instagram #sbi_images.dwd-carousel .sbi_item.dwd-slot-side {
  --dwd-scale: var(--dwd-carousel-side);
  --dwd-opacity: var(--dwd-carousel-side-opacity);
}

#sb_instagram #sbi_images.dwd-carousel .sbi_item.dwd-slot-out {
  --dwd-scale: var(--dwd-carousel-side);
  --dwd-opacity: 0;
}

/* The one `!important` — see the header. Without it the link box is the grid's 1/4 width tall and the
   bottom of a slide is dead to the pointer. */
#sb_instagram #sbi_images.dwd-carousel .sbi_photo {
  height: var(--dwd-carousel-slide) !important;
}

/* A neighbour is a way into the wheel, not a link: its photograph must not be clicked, tabbed to, or
   keep the plugin's hover fade. The slide itself takes the click that focuses it (`instagram.js`),
   which is why this is `pointer-events` on the link rather than `inert` on the item — `inert` would
   swallow that click as well. */
#sb_instagram #sbi_images.dwd-carousel .sbi_item:not(.dwd-slot-centre) .sbi_photo {
  pointer-events: none;
}

#sb_instagram #sbi_images.dwd-carousel .sbi_item.dwd-slot-side {
  cursor: pointer;
}

/* Whatever is more than one step out is drawn off the end of the track and clipped by the frame; it
   must not answer a click either, or a click near the edge would pull the wheel to a post nobody
   can see. */
#sb_instagram #sbi_images.dwd-carousel .sbi_item.dwd-slot-out {
  pointer-events: none;
}

/* An item with no slot at all is not a slide: the feed's **Load More** button appends posts to this
   track, and the wheel is built once, so those arrive without an offset. They are already invisible
   (they inherit no `--dwd-opacity`), and this keeps them from lying on top of the centred slide and
   eating its clicks — which is otherwise exactly what an invisible slide at offset 0 does. It is not
   a substitute for turning Load More off in the feed builder (`CONTEXT.md` §7): a control whose effect
   nobody can see is still a control nobody should be offered. */
#sb_instagram #sbi_images.dwd-carousel .sbi_item:not(.dwd-slot-centre):not(.dwd-slot-side):not(.dwd-slot-out) {
  pointer-events: none;
}

/* 4. The arrows. `secondary` at rest, `primary` on hover and focus, on a near-white disc so they read
   over a photograph as well as over the wash. At 1600px they sit in the 158px of gutter either side
   of the three slots; at narrower desktops the gutter runs out and they overlap the faded neighbour,
   which is what the disc is for. */
.dwd-carousel-frame .dwd-carousel-arrow {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--wp--preset--color--secondary-200);
  border-radius: 50%;
  background-color: color-mix(in srgb, var(--wp--preset--color--base) 92%, transparent);
  color: var(--wp--preset--color--secondary);
  transform: translateY(-50%);
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  transition: color 200ms ease, border-color 200ms ease;
}

.dwd-carousel-frame .dwd-carousel-arrow:hover,
.dwd-carousel-frame .dwd-carousel-arrow:focus-visible {
  color: var(--wp--preset--color--primary);
  border-color: currentColor;
}

/* The ring is drawn inside the button: the frame clips at its own edge, and the arrows sit on it. */
.dwd-carousel-frame .dwd-carousel-arrow:focus-visible {
  outline: 2px solid var(--wp--preset--color--primary);
  outline-offset: -3px;
}

.dwd-carousel-frame .dwd-carousel-arrow--prev {
  left: 0;
}

.dwd-carousel-frame .dwd-carousel-arrow--next {
  right: 0;
}

.dwd-carousel-frame .dwd-carousel-arrow svg {
  display: block;
  width: 1.25rem;
  height: 1.25rem;
}

/* The wheel's position, for a screen reader: each step rewrites it. Visually hidden, but not
   `display: none` — a live region has to stay in the accessibility tree to be announced. */
.dwd-carousel-frame .dwd-carousel-status {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* 5. The first paint. The script writes all eight offsets before the wheel is ever seen, and the wheel
   must not animate that. */
#sb_instagram #sbi_images.dwd-carousel.dwd-carousel-still .sbi_item {
  transition: none;
}

/* 6. One slide on a phone, with a peek of the next. Only the slide's size changes: the advance is
   derived from it, so the neighbours keep their 72% and stay one step away. The 320px cap is reached
   below 421px viewport width, which keeps the step across the 782px boundary small (320px here,
   297px there) even though the composition changes at it. */
@media (max-width: 782px) {
  #sb_instagram #sbi_images.dwd-carousel {
    --dwd-carousel-slide: min(76vw, 320px);
  }

  /* A finger swipes — see `instagram.js` — so the arrows would be a control for nobody. */
  .dwd-carousel-frame .dwd-carousel-arrow {
    display: none;
  }
}

/* 7. `prefers-reduced-motion`: the step still happens, instantly. The opacity still fades, because the
   focus moving is the point of the band and it is not a movement across the screen. */
@media (prefers-reduced-motion: reduce) {
  #sb_instagram #sbi_images.dwd-carousel .sbi_item {
    transition: opacity var(--dwd-carousel-duration) ease;
  }
}

/* 8. The feed's own button row — Load More and Follow on Instagram — moves to the **top right of the
   band**, on the line the profile header occupies, where a follow link is a call to action rather
   than a footer. `:has()` is the state test: the frame only exists once the wheel has been built, so
   with JavaScript off the buttons stay exactly where the plugin puts them.

   `#sbi_load` is plugin markup — `clear: both; float: left; text-align: center; width: 100%` — and it
   is the *last* child of `#sb_instagram`, after the track, which is why this is a position rather than
   a reordering: nothing in the DOM moves, and the plugin's own footer attributes keep applying. */
#sb_instagram:has(> .dwd-carousel-frame) {
  position: relative;
}

#sb_instagram:has(> .dwd-carousel-frame) #sbi_load {
  position: absolute;
  /* Flush with the header's own content box, which sits inside its 12px of padding. */
  top: var(--wp--preset--spacing--12);
  /* A little inside the column's right edge, not on it: hard against the edge the button reads as
     pinned to the page rather than sitting in the band's header row. `spacing|16` is the knob. */
  right: var(--wp--preset--spacing--16);
  z-index: 2;
  width: auto;
  float: none;
  text-align: right;
}

/* The buttons are taken out of the flow, so the header's text would happily run underneath them. It
   is given their width back as padding, which is invisible while the biography is short and is the
   difference between a two-line biography and an unreadable one when it is not. 18rem is the two
   buttons and their gap, measured at 1600px (Load More is off on this site, which makes it generous —
   the Follow button alone is about 14rem). */
#sb_instagram:has(> .dwd-carousel-frame) .sb_instagram_header {
  padding-right: 18rem;
}

/* ⚠ A phone has no 18rem to spare, so below the carousel's own breakpoint both halves of the rule are
   undone: the buttons go back to the centred row below the wheel where the plugin put them, and the
   header keeps its full width. */
@media (max-width: 782px) {
  #sb_instagram:has(> .dwd-carousel-frame) #sbi_load {
    position: static;
    width: 100%;
    float: left;
    text-align: center;
  }

  #sb_instagram:has(> .dwd-carousel-frame) .sb_instagram_header {
    padding-right: 0;
  }
}
