/*
 * THE EXPAND-IN-PLACE EMBED — the shared frame and mechanic (W128, Ryan
 * 2026-09-04).
 *
 * Served as a static asset and pulled in by `<EmbedExpandStyles>` rather than
 * `import`ed, for the reason given at the top of chrome.css.
 *
 * Class prefix `sf-xp-`.
 *
 * ═══ WHAT THIS IS ═══
 *
 * Ryan, on the Rust Armor pop-up's galvanization film: it must expand the way
 * the CATEGORY PAGE's hero film does — "full pop-up width, overlaying the
 * right-rail pole photo, pushing content down; SAME border, drop shadow,
 * formatting… This needs to be a repeatable pattern."
 *
 * ═══ THE ONE IDEA: TWO BOXES, ONE CUSTOM PROPERTY ═══
 *
 * `--sf-xp-w` is read by BOTH a `::before` spacer and an absolutely-positioned
 * box:
 *
 *   the SPACER is what the surrounding column's flow sees — it is what pushes
 *     the content below the embed down as it grows;
 *   the BOX is what the reader sees — absolute, so it can paint OVER whatever
 *     sits beside it rather than displacing it.
 *
 * Sizing both from one property is what stops the drawn width and the reserved
 * width from ever drifting apart, and gives one place to read the geometry from.
 * It is `category.css`'s own structure, transplanted; see
 * `use-embed-expand.ts`'s header for where the seam between shared and
 * caller-owned is drawn and why the category hero is not converted in this pass.
 *
 * ═══ THE FRAME'S NUMBERS ARE THE CATEGORY HERO'S, AND A TEST SAYS SO ═══
 *
 * `border-radius: var(--radius-media)`, `overflow: hidden`, and
 * `box-shadow: 0 14px 36px rgba(23, 24, 26, 0.22)` are copied from
 * `.sf-cat-hero__film-box`, and the phone step-down to `0 10px 26px` /0.2 is
 * copied from its phone rung. There is NO border on it — Ryan's word "border"
 * describes the drawn edge, and on that surface the edge is the radius and the
 * shadow (the bordered card on the same page is a static annotation, not an
 * expander). `tests/modal-shell.test.ts` reads both sheets and asserts the
 * declarations are equal, so "SAME border, drop shadow, formatting" is held by
 * a gate rather than by this paragraph.
 *
 * ═══ WHAT THE CALLER MUST SET ═══
 *
 *   `--sf-xp-w`         the REST width. Required.
 *   `--sf-xp-w` again,  under its own `[data-big="true"]` rule — the EXPANDED
 *                       width, which is always derived from the caller's own
 *                       layout and can never live here.
 *   `--sf-xp-ratio`     the box's aspect ratio. Defaults to 16/9.
 */

.sf-xp {
  --sf-xp-ratio: 16 / 9;
  position: relative;
}

/*
 * THE FLOW SPACER. It reserves exactly the drawn box's rectangle in the
 * column, which is how the content underneath moves down as the box grows and
 * why the box itself can be taken out of flow at all.
 */
.sf-xp::before {
  aspect-ratio: var(--sf-xp-ratio);
  content: "";
  display: block;
  width: var(--sf-xp-w);
}

.sf-xp__box {
  aspect-ratio: var(--sf-xp-ratio);
  background: linear-gradient(
    160deg,
    var(--brand-color-media-well-a, #23262e),
    var(--brand-color-media-well-b, #0b0c0e)
  );
  border-radius: var(--radius-media);
  box-shadow: 0 14px 36px rgba(23, 24, 26, 0.22);
  left: 0;
  overflow: hidden;
  position: absolute;
  top: 0;
  width: var(--sf-xp-w);
}

@media (prefers-reduced-motion: no-preference) {
  .sf-xp::before,
  .sf-xp__box {
    transition: width 280ms cubic-bezier(0.22, 0.61, 0.36, 1);
  }
}

/*
 * SCROLL ANCHORING OFF while a box is grown. Chrome's anchoring tries to keep
 * whatever it picked as the anchor still, which means it fights a 280ms width
 * animation that changes the height of everything under it — the category
 * hero's own note records the same fix. Descendants AND following siblings,
 * because both move.
 */
.sf-xp[data-big="true"],
.sf-xp[data-big="true"] *,
.sf-xp[data-big="true"] ~ * {
  overflow-anchor: none;
}

/* ------------------------------------------------------- the control ----- */

/*
 * The pill, at the box's bottom-right. `.sf-cat-hero__film-btn`'s own drawing:
 * a white pill on the media well, mono micro caps, 32px tall.
 *
 * BOTTOM-RIGHT IS THE DEFAULT AND STAYS THE DEFAULT — it is the category
 * hero's own corner, and `tests/modal-shell.test.ts` asserts the two sheets
 * agree on it. See `[data-native-chrome]` below for the one caller that has to
 * move, and why moving the DEFAULT would have been the wrong repair.
 */
.sf-xp__controls {
  align-items: center;
  bottom: 12px;
  display: flex;
  gap: 8px;
  position: absolute;
  right: 14px;
  z-index: 4;
}

/*
 * ═══ W160 (Ryan, 2026-09-04): OUT OF THE PLATFORM'S OWN BAND ═══
 *
 * "It's like this video has all of its own controls and you layered expand on
 * top. I don't think the category page is like that." It is not: the category
 * hero's `<video>` carries NO `controls` attribute at all — a silent
 * decorative loop — so its bottom-right corner is empty and the pill lives
 * there. A real `<video controls>` fills that exact corner with fullscreen and
 * overflow buttons.
 *
 * A caller whose media draws its own bottom strip sets `data-native-chrome` and
 * the cluster lifts to the top-right, which no player chrome occupies. It sits
 * there in BOTH states rather than moving when playback starts — a control that
 * relocates mid-interaction is worse than one in an unusual corner.
 *
 * THE DEFAULT DID NOT MOVE, deliberately. Relocating every embed's pill to fix
 * one caller would have broken the parity with the category page that W128's
 * whole extraction rests on, to spare one line of CSS.
 */
.sf-xp[data-native-chrome="true"] .sf-xp__controls {
  bottom: auto;
  top: 12px;
}

/* ------------------------------------------- the content gutter (W163) --- */

/*
 * W163/W164 (Ryan, 2026-09-04) — AND IT REVISES HIS OWN W134/W136.
 *
 * Those asked for the pop-up's films to run literal full width, and walking the
 * result he took it back: the films were the only things in either pop-up
 * touching the panel's edges, so they read as breaking OUT of the document
 * rather than belonging to it. Set `data-gutter` and the embed takes the
 * surface's own inset, which lines its left edge up with the section header's
 * icon — the leftmost thing on the page above it.
 *
 * `--sf-xp-gutter` IS THE SURFACE'S NUMBER, not this sheet's: a caller whose
 * measure is inset by something other than 32 sets it and everything else here
 * follows. The default matches the pop-ups' own `.sf-ra__section` /
 * `.sf-la__howto` padding, which is where the alignment has to land.
 */
.sf-xp[data-gutter="true"] {
  margin-left: var(--sf-xp-gutter, 32px);
  margin-right: var(--sf-xp-gutter, 32px);
}

.sf-xp__btn {
  align-items: center;
  background: var(--brand-color-surface, #ffffff);
  border: 0;
  border-radius: var(--radius-pill);
  box-shadow: 0 2px 10px rgba(11, 12, 14, 0.36);
  color: var(--brand-color-ink, #17181a);
  cursor: pointer;
  display: flex;
  font-family: var(--brand-font-mono, monospace);
  font-size: var(--text-micro);
  gap: 6px;
  height: 32px;
  letter-spacing: 0.12em;
  padding: 0 11px 0 9px;
}

.sf-xp__btn svg {
  height: 14px;
  width: 14px;
}

/*
 * `[data-on]`, NOT `[aria-pressed]` — the category page's ruling of 2026-08-27,
 * inherited whole. The label is an ACTION ("Expand" / "Shrink"), so the visible
 * verb IS the accessible name and "Shrink, pressed" would be a contradiction.
 * The state is drawn twice (the glyph and the fill) and announced never.
 */
.sf-xp__btn[data-on="true"] {
  background: var(--brand-color-ink, #17181a);
  color: var(--brand-color-surface, #ffffff);
}

.sf-xp__btn:focus-visible {
  outline: var(--sf-focus-ring, 2px solid var(--brand-color-accent, #c4530a));
  outline-offset: var(--sf-focus-ring-offset, 2px);
}

/* -------------------------------------------------------------- media ---- */

/*
 * The element the frame wraps. `object-fit: contain` rather than `cover`: a
 * film letterboxes into the frame's ratio instead of being cropped, and the
 * well's gradient is what shows in the bars.
 *
 * ═══ IT CARRIES THE FRAME'S OWN RADIUS (W160) ═══
 *
 * Ryan, on the pop-up's player beside the category embed: "the border radius
 * looks different." `.sf-xp__box` clips with `overflow: hidden` and that is
 * enough for an `<img>` — but a `<video>` is composited on its own layer, and
 * an ancestor's overflow clip does not reliably round a video's corners on
 * every GPU path. The square corners were the video's, painting through a
 * rounded box. Declaring the radius ON the element makes the two agree by
 * construction rather than by trusting the clip.
 *
 * The value is the frame's, not a second number: change `.sf-xp__box` and this
 * follows, and the parity test reads both.
 */
.sf-xp__media {
  border-radius: var(--radius-media);
  display: block;
  height: 100%;
  object-fit: contain;
  width: 100%;
}

/* ------------------------------------------------ the resting cue (W160) -- */

/*
 * THE WHOLE RECTANGLE IS THE PLAY CONTROL, at rest — the category hero's own
 * arrangement (its `.sf-cat-hero__film-tap` covers the same box), for the same
 * reason: a poster with a play mark on it says "a film you can start" without
 * borrowing the platform's furniture, and a reader should not have to find a
 * small target on a still.
 *
 * IT IS UNMOUNTED ON PLAY by `shade-video-player.tsx`, not merely hidden. A
 * transparent full-rectangle button left in the tree over a live seek bar is
 * exactly the collision W160 is about, in the other direction.
 */
.sf-xp__cue {
  align-items: center;
  background: none;
  border: 0;
  cursor: pointer;
  display: flex;
  inset: 0;
  justify-content: center;
  padding: 0;
  position: absolute;
  z-index: 3;
}

/*
 * The 52px white disc, one step up from the modal shell's own 44 because this
 * one sits on a full-width still rather than a 296px thumbnail. Its lift is the
 * pill's, since both float on unpredictable footage.
 */
.sf-xp__cue-mark {
  align-items: center;
  background: var(--brand-color-surface, #ffffff);
  border-radius: var(--radius-pill);
  box-shadow: 0 2px 10px rgba(11, 12, 14, 0.36);
  color: var(--brand-color-ink, #17181a);
  display: flex;
  height: 52px;
  justify-content: center;
  /* OPTICAL CENTRING: a right-pointing triangle's visual centre sits left of
   * its box's, so the disc's contents shift right by a couple of pixels. */
  padding-left: 4px;
  transition: transform 120ms ease-out;
  width: 52px;
}

.sf-xp__cue:hover .sf-xp__cue-mark {
  transform: scale(1.06);
}

@media (prefers-reduced-motion: reduce) {
  .sf-xp__cue-mark {
    transition: none;
  }

  .sf-xp__cue:hover .sf-xp__cue-mark {
    transform: none;
  }
}

.sf-xp__cue:focus-visible {
  outline: var(--sf-focus-ring-on-dark, 2px solid var(--brand-color-accent-on-dark, #ffb27a));
  outline-offset: var(--sf-focus-ring-inset, -2px);
}

/* -------------------------------------------------------------- a phone -- */

@media (max-width: 767.98px) {
  .sf-xp__box {
    box-shadow: 0 10px 26px rgba(23, 24, 26, 0.2);
  }

  /*
   * THE CONTROL GOES AND THE STATE IS DEFUSED, both — the category hero's own
   * phone treatment. At this rung the embed is already the full measure, so
   * "expand" has nothing to expand into; hiding only the button would leave a
   * surface that could still be grown by a stale state.
   */
  .sf-xp__btn--size {
    display: none;
  }

  .sf-xp[data-big="true"] {
    --sf-xp-w: 100%;
  }
}
