/* ============================================================
   bpa-bifrost, Bifrost Studios site layer
   ------------------------------------------------------------
   Loads AFTER site/home.css (the shared site layer) and after
   brands/bifrost/studios.css. Only what the Studios Home draws
   that neither the engine nor the shared layer covers.

   Studios differs from Group in the three documented ways
   (amber accent, pronounced rounding, same Concrette titles) and
   in one thing the three-thing rule does not cover: its hero is
   a full-bleed painting with knockout type, where Group's is the
   arch motif on a plate. That is a page difference, not a brand
   difference, which is why it lives here and not in the brand
   pack.
   ============================================================ */


/* ------------------------------------------------------------
   S3 · THE CONTENT WELL IS FILLED, NOT OUTLINED    RAISE
   ------------------------------------------------------------
   The engine draws an empty .ui-content__media as transparent
   with a 1px rule, on the reasoning that an empty well should
   read as a recess. 40004577:15296 draws it as a solid plate one
   step down from the section, with no rule.

   Small, and it is the difference between "nothing here yet" and
   "an image goes here". Raised rather than promoted, because the
   engine's version is a defensible choice and this may be the
   file being loose.
   ------------------------------------------------------------ */
.ui-section--content .ui-content__media:not(:has(img)) {
  background: var(--ui-ground);
  border: 0;
}


/* ------------------------------------------------------------
   S4 · THE STAGE CARD ILLUSTRATIONS
   ------------------------------------------------------------
   Exported from the file as SVG and served as <img>, so they are
   not 8KB of path data inside a hand-authored page. They carry
   their own fills (the plate and the amber), which are the right
   values for this brand and only this brand: a Forge version of
   this section would need its own export, not a recolour.
   ------------------------------------------------------------ */
.ui-card__glyph--img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}


/* ------------------------------------------------------------
   S5 · A NEWSLETTER IN THE CTA BAND               PROMOTE
   ------------------------------------------------------------
   40004577:15927 uses the CTA band for a newsletter rather than a
   button row. The engine's CTA already knocks out the title, the
   lead, .ui-prose and .ui-copy against the accent plate, but it
   has never had a control in the band, so .ui-signup arrives
   still painting --ui-ink: black hairline and black placeholder
   on amber.

   Three declarations, all of them the same knockout the engine
   already applies to every other role in this section. That is
   why this is a PROMOTE and not a RAISE: the engine's own list at
   6.3.21 is simply missing a row.

   ⚠ Contrast, and it is the live open decision: knockout white on
   #FFB259 measures 1.51 : 1. The design system's own report flags
   this exact pair as the worse of the two brands. Built as drawn.
   ui-mode--inverted on the section fixes it and passes AA.
   ------------------------------------------------------------ */
.ui-section--cta .ui-signup {
  margin-block-start: var(--s-w-s);
  margin-inline: auto;
  max-width: 353px;                       /* 40004577:15932 */
  border-color: color-mix(in srgb, var(--ui-ink-on-accent) 40%, transparent);
}
.ui-section--cta .ui-signup:focus-within { border-color: var(--ui-ink-on-accent); }
.ui-section--cta .ui-signup__input,
.ui-section--cta .ui-signup__submit { color: var(--ui-ink-on-accent); }
.ui-section--cta .ui-signup__input::placeholder {
  color: color-mix(in srgb, var(--ui-ink-on-accent) 60%, transparent);
}

/* The consent line under it. Same knockout, same 60% as the
   engine's own .ui-copy--dim rather than a new token. */
.bf-cta__note {
  margin-block: var(--s-w-s) 0;
  margin-inline: auto;
  max-width: var(--ui-measure);
  color: color-mix(in srgb, var(--ui-ink-on-accent) 60%, transparent);
}
.bf-cta__note .ui-link {
  color: inherit;
  text-decoration: underline;
}


/* ------------------------------------------------------------
   S6 · THE PORTFOLIO INDEX IS FOUR UP, NOT THREE     RAISE
   ------------------------------------------------------------
   The engine sets --span: 4 on every .ui-section__cards child,
   which is three per row of twelve columns, and its own Colorful
   proof page draws exactly that. 40004577:15717 draws twelve
   cards at 260 wide in rows of four: span 3.

   An index of 25 wants four; a set of three strategies wants
   three. So this is a per-USE choice, not a per-brand one, and
   the engine has no modifier for it yet. Written here against the
   section rather than as a bare --span override so it stays
   readable as "this index runs four up".

   Raised, not promoted: the fix belongs in the engine as
   .ui-section__cards--dense (or a --span the markup can set), and
   the shape of that modifier is 6.3's call, not this page's.
   ------------------------------------------------------------ */
@media (min-width: 1120px) {
  #portfolio .ui-section__cards > * { --span: 3; }
}


/* ------------------------------------------------------------
   S7 · THE SIGNUP SUBMIT ON AN ACCENT BAND
   ------------------------------------------------------------
   Part of S5, kept separate because it is a state fix rather than
   a colour one. .ui-signup__submit rests on --ui-plate, which is
   correct on a page ground and reads as a pale blob on the amber
   plate: the frame draws the arrow bare, with the plate arriving
   only on hover. Resting transparent, hover unchanged.
   ------------------------------------------------------------ */
.ui-section--cta .ui-signup__submit { background: transparent; }
.ui-section--cta .ui-signup__submit:hover,
.ui-section--cta .ui-signup__submit[data-state="hover"] {
  background: color-mix(in srgb, var(--ui-ink-on-accent) 20%, transparent);
  color: var(--ui-ink-on-accent);
}


/* ------------------------------------------------------------
   S10 · THE PAGE SWAP                             PROMOTE
   ------------------------------------------------------------
   Two pieces of motion, both deliberately close to invisible.

   The SWAP is opacity only. Animating the grid's height while the
   card count changes between pages makes everything below it jump,
   which is worse than a cut. Out at --dur-fast, in at --dur-base:
   leaving is quicker than arriving, which reads as the new page
   settling rather than the old one being yanked.

   The REVEAL is a 24px rise and a fade, once, never reversed. It
   was 12px until 20 August, when Lasse asked for "a little bit
   more motion when we scroll down, things have to appear in a more
   website kind of way". 24px on bands and parts, 14px on cards
   inside a staggered grid. Still one gesture, still never reversed,
   still nothing that moves while the user scrolls.
   Bands arrive as one object; grid rows stagger by 55ms per card
   with the delay capped, because forty cards each arriving on their
   own turns a portfolio into a slot machine. The hero is excluded:
   fading in the thing the visitor came to see costs and buys
   nothing.

   THE REVEAL RULES MOVED OUT, 20 August, to site/home.css as G9.
   They were here, and Group Home does not load this file, so
   switching the reveal on for that page added the classes and
   painted nothing: measured transition-duration 0s. Exactly the
   same mistake as G7's first version, one file over. Anything the
   script can apply on more than one page belongs in the shared
   layer. What is left below is the portfolio pager's swap, which
   really is one page's.

   Nothing moves on continuous scroll: no parallax, no scaling,
   nothing that keeps moving while the user does.
   ------------------------------------------------------------ */
.ui-section__cards.is-swapping {
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease);
}
.ui-section__cards {
  transition: opacity var(--dur-base) var(--ease);
}

/* Belt and braces for the swap. Reduced motion gets a cut, not a
   faster fade. The reveal's own guard is in site/home.css G9. */
@media (prefers-reduced-motion: reduce) {
  .ui-section__cards,
  .ui-section__cards.is-swapping {
    opacity: 1;
    transition: none;
  }
}


/* ------------------------------------------------------------
   S14 · A ROLE LINE THAT IS NOT WRITTEN YET
   ------------------------------------------------------------
   The founder role line is "role, studio" ("CEO, Breakwater").
   Where neither is supplied the renderer prints the handover
   pack's own "under progress" marker rather than collapsing the
   slot, because eleven names with nothing under them reads as
   eleven broken cards. Dimmed and italic, the same treatment as
   an unwritten portfolio description, so it can never be mistaken
   for a real job title.

   Delete nothing when the titles arrive: the marker disappears on
   its own the moment content/founders.json has a role or a studio.
   ------------------------------------------------------------ */
.ui-person__role--pending {
  font-style: italic;
  opacity: 0.6;
}


/* ------------------------------------------------------------
   S15 · THE RAILS LOSE THEIR SCROLLBARS           PROMOTE
   ------------------------------------------------------------
   Both horizontal rails (the founder row and the gallery) drew a
   native scrollbar across the full width of the band, which on the
   gallery sat directly under the photographs and read as a rule.
   Reported by Lasse, 19 August.

   Hiding a scrollbar is normally a mistake, because it removes the
   only affordance saying "there is more". It is safe HERE and only
   here because both rails now have a working pager above them, and
   dragging, wheeling and keyboard scrolling all still work: this
   hides the indicator, not the mechanism.

   Promote with that condition attached: the engine should hide the
   bar when a rail is paged and keep it when the rail is bare.
   ------------------------------------------------------------ */
.ui-person-row,
.ui-section__rail {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* old Edge */
}
.ui-person-row::-webkit-scrollbar,
.ui-section__rail::-webkit-scrollbar { display: none; }


/* ------------------------------------------------------------
   S16 · THE GALLERY CENTREPIECE
   ------------------------------------------------------------
   The frame draws one enlarged photograph among four reduced ones.
   Lasse, 19 August: accentuate the middle one further, and make the
   arrows and numbers move which photograph is enlarged.

   The engine sizes the active frame at --ui-gallery-w (353px) and
   the rest at eleven fifteenths of it (259px). The bump is a
   multiplier on the engine's own token rather than a new number, so
   it survives the token changing and stays legible as "15% more
   than the system's".

   inline-size transitions, so the swap is the soft change asked for
   rather than a cut. Only one element resizes per interaction, so
   the cost is a single layout, and the height follows from the
   engine's aspect-ratio without a second declaration.
   ------------------------------------------------------------ */
.ui-section--gallery .ui-section__frame {
  transition: inline-size var(--dur-base) var(--ease);
}
.ui-section--gallery .ui-section__frame--active {
  inline-size: calc(var(--ui-gallery-w) * 1.15);
}
@media (prefers-reduced-motion: reduce) {
  .ui-section--gallery .ui-section__frame { transition: none; }
}


/* ------------------------------------------------------------
   S18 · NEITHER RAIL MOVES WHEN YOU USE IT       PROMOTE
   ------------------------------------------------------------
   Two reported jumps, 19 August, both measured before being
   touched, and both the same bug in different clothes: a rail
   whose height is set by its tallest child, where the tallest
   child changes as you interact.

   FOUNDERS. Closed the row is 524px; with the longest bio open it
   is 590px. Pressing a plus moved the section 66px under the
   cursor. The reserve is set by site/index-controls.js, which
   opens each card in turn, takes the tallest, and reserves the
   difference: bios run one to three lines and the wrap point moves
   with the card width, so a hardcoded number would be wrong at two
   of the three widths and wrong again on the next bio. The blank
   sits at the foot of the band rather than inside every card,
   which is why the reserve is on the row and not on .ui-person.

   GALLERY. Worse, and less obvious: at rest the rail is 517px, but
   sampled every 35ms through a pager transition it dips to 449 and
   climbs back. The enlarged frame animates its width, so mid-way
   BOTH frames are middling and neither is 517 tall. A floor fixes
   it, expressed off the engine's own token and the drawn aspect
   ratio so it cannot drift from S16's 1.15 multiplier.

   Promote: any rail that changes a child's size owes its own
   height a floor, and the engine has three of them.
   ------------------------------------------------------------ */
.ui-person-row {
  padding-block-end: var(--bf-person-reserve, 0px);
}

.ui-section--gallery .ui-section__rail {
  /* Set by site/index-controls.js from the active frame's measured
     height, NOT computed here.

     The first version was
       min-block-size: calc(var(--ui-gallery-w) * 1.15 * 450 / 353);
     which worked at 1440 and did nothing at all below 1120, because
     --ui-gallery-w becomes a PERCENTAGE there (100% at 393,
     calc((100% - 20px) / 2) at 834) and a percentage
     min-block-size resolves against the parent's HEIGHT, not its
     width. Measured: still jumping 99px at 834 and 86px at 393.

     Same mistake as the arch hover reading --arch-cx as pixels when
     it was "56%", made again one file over. The rule that was
     already written down after that one: take the measurement off
     the rendered element. */
  min-block-size: var(--bf-gallery-floor, 0px);
}
