/* Streambar Streamcam — the decorative border that sits over a camera box.
 *
 * The rules this file keeps, and must keep:
 *   * IT FILLS THE SOURCE. A Streamcam is chrome round a capture and a capture
 *     is whatever size the creator made it, so #root fills the browser source
 *     at ANY aspect and every number below is drawn in `--f-unit`: the shorter
 *     side of the root's own box divided by 484, the shorter side of the design.
 *     860x484 is 1, 1280x720 is 1.487, 1920x1080 is 2.231 — one factor, so the
 *     lines, corners, mark and writing keep their proportions instead of the
 *     frame growing a hairline edge on a big source. The module measures the
 *     ROOT (never the viewport: the panel's preview mounts the same module into
 *     a scaled box) and writes the number here; the `1` below is what a page
 *     draws if a config never arrives.
 *   * THICKNESS IS ONE MULTIPLIER. How heavy the border is drawn is a setting
 *     (`[data-thick]`), and it becomes exactly one number here — `--f-line` —
 *     which EVERY stroke a style draws is its own base times: Pulse's ring,
 *     Pitch's cut, Broadcast's edge and brackets, Blaze's and Floodlight's
 *     line, Blade's two, Chevron's ring. A style added later joins in by
 *     writing its stroke in the same money; nothing else has to know the
 *     setting exists. The furniture that is not the border — the LIVE
 *     pill, the identity plate, Pitch's band — keeps its size, and only MOVES
 *     when a heavier stroke would otherwise reach it (`--f-edge`, below).
 *   * The MIDDLE IS THE CAMERA. This source sits over the camera source in
 *     OBS, so every pixel that is not the border, the LIVE pill or the style's
 *     own lower-third band stays see-through.
 *   * Colours arrive as CSS VARIABLES the module wrote from the overlay's own
 *     theme, never as tenant text in a rule, each with its `-rgb` tint triple.
 *   * MOTION IS `transform`, `opacity` and `filter` in CSS keyframes, nothing
 *     else; `[data-anim]` says which run and the timings live HERE. Nothing is
 *     DRAWN by a keyframe — at `off` every style is still whole.
 *
 * The styles are `[data-style]` on #root — eight of them, three from the first
 * batch (Pulse, Pitch, Broadcast), four from the second (Blaze, Blade,
 * Chevron, Floodlight) and Crest, the one that goes with the Crest BAR — and
 * the LIVE pill, identity block and locked plate are one node in every one of
 * them. Crest is also the only style with a SKIN (`[data-skin]`, the same
 * allowlist the bar's crest wears): its `[data-style="crest"]` block is the
 * GEOMETRY and the `[data-skin="…"]` block after it is the LOOK, and a skin may
 * never move or resize anything. */

:root { color-scheme: normal; }

#root {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  overflow: hidden;
  background: transparent;
  /* The theme, as the module writes it. `--f-a` and `--f-b` are the account's
     TWO BRAND COLOURS — theme.primary and theme.accent, the pair every bar is
     built out of (secondary is the ground behind them, text is the writing).
     The fallbacks are the product defaults, so a frame draws something even
     if a config never arrives. */
  --f-a: #7B2FBE;      --f-a-rgb: 123, 47, 190;
  --f-b: #E5B800;      --f-b-rgb: 229, 184, 0;
  --f-text: #FFFFFF;   --f-text-rgb: 255, 255, 255;
  --f-bg: #1A0A2E;     --f-bg-rgb: 26, 10, 46;
  /* THE UNIT: how big one design pixel is on this source. 1 at 860x484, and the
     module rewrites it whenever the root's box changes. */
  --f-unit: 1;
  /* The two SCALES: `--f-scale` is the Text size (below), `--f-logo` the logo
     dial (theme.logoSize / 100, 0.5–1.2), written by the module. Every type
     size and logo height below is a base number times one of them AND the unit. */
  --f-scale: 1;
  /* THE LINE: how heavy every stroke is drawn, set by `[data-thick]` below.
     2 is Medium, the default and the standing value — about double the line a
     Streamcam drew before the setting existed, which was a hairline over a
     1080p camera. */
  --f-line: 2;
  /* …and WHERE THAT STROKE ENDS, in real px: the inner edge of the deepest
     thing this style draws (Pulse's ring by default — 16 in from the source,
     plus 4 of stroke per step of the line). The LIVE pill and the identity
     plate clear THIS rather than each carrying a thickness sum of their own,
     and each style that is inset differently says so in one line of its own
     section. At `thin` every one of them works out at exactly the number that
     was there before thickness existed, so nothing moves until a heavier line
     would actually reach it. */
  --f-edge: calc((16px + 4px * var(--f-line)) * var(--f-unit));
  font-family: var(--f-font, system-ui, -apple-system, "Segoe UI", sans-serif);
  font-weight: 700;
  font-synthesis: none;
  color: var(--f-text);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.3s ease;
}
/* Hidden is the bar's own rule: the source stays in the scene and stops
   drawing. Never display/geometry — OBS keeps the page warm either way. */
#root[data-hidden="1"] { opacity: 0; }

/* TEXT SIZE. A Streamcam is read off a camera box at arm's length, so how big
   the writing is is a setting, not a nicety. Medium is the default and needs no
   rule; the other two only move the one multiplier. */
#root[data-text="small"] { --f-scale: 0.85; }
#root[data-text="large"] { --f-scale: 1.25; }

/* BORDER THICKNESS. A frame is read over somebody's camera at whatever size
   they made it, so how heavy the border is is a setting too. All four steps are
   written out — Medium is the standing value on #root as well, so the ladder can
   be read in one place rather than inferred from what is missing. Thin is the
   line every Streamcam drew before this existed; the steps above it are ~2x,
   ~3.25x and ~4.5x that, which is a stroke that still reads as a border at 4K
   rather than a slab. */
#root[data-thick="thin"]   { --f-line: 1; }
#root[data-thick="medium"] { --f-line: 2; }
#root[data-thick="thick"]  { --f-line: 3.25; }
#root[data-thick="extra"]  { --f-line: 4.5; }

/* ---- the identity block: logo + handle ---------------------------------
 * ONE node in every style, so `update()` rewrites the handle in place and
 * swaps the logo's src without touching the tree. */
.sc-id {
  position: absolute;
  display: flex;
  align-items: center;
  gap: calc(10px * var(--f-unit));
  /* 70 % of the source: room for 40 characters at Large before the ellipsis. */
  max-width: 70%;
  box-sizing: border-box;
}
.sc-logo { display: block; width: auto; object-fit: contain; }
.sc-logo.is-off { display: none; }
.sc-handle {
  line-height: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#root[data-case="upper"] .sc-handle { text-transform: uppercase; }
/* Nothing to say and no mark to show ⇒ no pill and no tab. Pitch is the
   exception: its band IS the look, so it stays either way. */
#root[data-style="pulse"] .sc-id.is-off,
#root[data-style="broadcast"] .sc-id.is-off,
#root[data-style="blaze"] .sc-id.is-off,
#root[data-style="blade"] .sc-id.is-off,
#root[data-style="chevron"] .sc-id.is-off,
#root[data-style="crest"] .sc-id.is-off,
#root[data-style="floodlight"] .sc-id.is-off { display: none; }

/* ---- the LIVE pill ------------------------------------------------------
 * Top left, inside the frame edge, and shown whenever the creator asked for it
 * — the Text tab's switch IS the switch. The node always exists; `[data-live]`
 * shows it. At Large the pill is ~19 design px of type in ~42 of pill, which
 * still clears the 26/24 it is inset by at the thinnest line; a heavier one
 * only pushes that inset further in. */
.sc-live {
  position: absolute;
  /* Inside the frame edge, and it MOVES only when the frame edge comes out to
     meet it: `--f-edge` is where this style's stroke ends, and the 6 and the 4
     are the gaps the pill always sat at beyond it. At `thin` that is 26 and 24,
     exactly where it was; the max() keeps it there for any style whose stroke
     is shallower than the pill's own inset. */
  left: max(calc(26px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  top: max(calc(24px * var(--f-unit)), calc(var(--f-edge) + 4px * var(--f-unit)));
  display: flex;
  align-items: center;
  gap: calc(8px * var(--f-scale, 1) * var(--f-unit));
  padding: calc(6px * var(--f-scale, 1) * var(--f-unit)) calc(13px * var(--f-scale, 1) * var(--f-unit)) calc(6px * var(--f-scale, 1) * var(--f-unit)) calc(10px * var(--f-scale, 1) * var(--f-unit));
  border-radius: 999px;
  background: rgba(8, 8, 10, 0.72);
  border: calc(1px * var(--f-unit)) solid rgba(255, 60, 60, 0.55);
  box-shadow: 0 calc(4px * var(--f-unit)) calc(14px * var(--f-unit)) rgba(0, 0, 0, 0.35);
  font-size: calc(15px * var(--f-scale, 1) * var(--f-unit));
  letter-spacing: 0.16em;
  line-height: 1;
  color: #FFFFFF;
}
#root:not([data-live="1"]) .sc-live { display: none; }
.sc-dot {
  width: calc(9px * var(--f-scale, 1) * var(--f-unit));
  height: calc(9px * var(--f-scale, 1) * var(--f-unit));
  border-radius: 50%;
  background: #FF3B30;
  box-shadow: 0 0 calc(8px * var(--f-unit)) rgba(255, 59, 48, 0.9);
}
#root[data-anim="calm"] .sc-dot   { animation: sc-blink 2.4s ease-in-out infinite; }
#root[data-anim="lively"] .sc-dot { animation: sc-blink 1.1s ease-in-out infinite; }
@keyframes sc-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* ======================================================================
 * PULSE — a soft glowing gradient border in the two brand colours.
 *
 * The border is the padding-box mask trick: 4px of padding, a mask that keeps
 * the ring and drops the content box, so the middle stays see-through. BOTH
 * mask layers and the composite pair are on the SAME element — a single-layer
 * mask with `xor` composites to nothing in some Chromium builds. Inside it one
 * oversized square carrying the conic gradient spins on `transform`; that
 * gradient is PAINTED, so at `data-anim="off"` the ring is still and whole.
 * ====================================================================== */
#root[data-style="pulse"] .sc-ring {
  position: absolute;
  inset: calc(16px * var(--f-unit));
  border-radius: calc(16px * var(--f-unit));
  /* THE RING'S STROKE. The padding IS the line here (the mask drops the content
     box), so it is the one number the thickness moves — the ring's OUTER edge
     stays at 16, the glow behind it keeps its inset, and a heavier ring grows
     inwards over the camera rather than off the source. */
  padding: calc(4px * var(--f-line) * var(--f-unit));
  overflow: hidden;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  transition: filter 0.25s ease;
}
/* The spinner is a SQUARE of 1240 design px — 2.56 x the source's shorter side,
   which clears the diagonal of any source up to about 2.35:1 either way (16:9,
   16:10, 4:3, 1:1, 9:16 and 21:9 are all inside it), so the gradient covers
   every edge at every angle. A conic gradient's colour depends only on the
   ANGLE from its centre, so making the square bigger than the old 1040 changes
   nothing about what is drawn — only how far out it still reaches. */
#root[data-style="pulse"] .sc-ring::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: calc(1240px * var(--f-unit));
  height: calc(1240px * var(--f-unit));
  margin: calc(-620px * var(--f-unit)) 0 0 calc(-620px * var(--f-unit));
  background: conic-gradient(from 0deg, var(--f-a), var(--f-b) 35%, var(--f-a) 62%, var(--f-b) 85%, var(--f-a) 100%);
  transform: rotate(0deg);
}
#root[data-style="pulse"][data-anim="calm"] .sc-ring::before   { animation: sc-spin 18s linear infinite; }
#root[data-style="pulse"][data-anim="lively"] .sc-ring::before { animation: sc-spin 7s linear infinite; }
@keyframes sc-spin { to { transform: rotate(360deg); } }

/* The glow: one box-shadow on an empty box behind the ring, rasterised once. */
#root[data-style="pulse"] .sc-glow {
  position: absolute;
  inset: calc(16px * var(--f-unit));
  border-radius: calc(16px * var(--f-unit));
  box-shadow: 0 0 calc(24px * var(--f-unit)) calc(2px * var(--f-unit)) rgba(var(--f-a-rgb), 0.42),
    0 0 calc(54px * var(--f-unit)) calc(12px * var(--f-unit)) rgba(var(--f-b-rgb), 0.16),
    inset 0 0 calc(22px * var(--f-unit)) calc(1px * var(--f-unit)) rgba(var(--f-a-rgb), 0.10);
  opacity: 0.92;
  transition: opacity 0.25s ease, filter 0.25s ease;
}
/* THE FLASH. `pulse()` adds this for ~900ms when a config arrives that has
   just gone live: a transition, not a keyframe, so it settles. */
#root.is-flash .sc-glow { opacity: 1; filter: brightness(1.8) saturate(1.15); }
#root.is-flash .sc-ring { filter: brightness(1.45) saturate(1.1); }

#root[data-style="pulse"] .sc-id {
  /* The pill clears the ring the same way the LIVE pill does — 6 beyond where
     the stroke ends, which is 26 at `thin`, exactly where it always sat. */
  left: max(calc(26px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  bottom: max(calc(26px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  padding: calc(8px * var(--f-unit)) calc(16px * var(--f-unit)) calc(8px * var(--f-unit)) calc(12px * var(--f-unit));
  border-radius: 999px;
  background: rgba(var(--f-bg-rgb), 0.74);
  border: calc(1px * var(--f-unit)) solid rgba(var(--f-text-rgb), 0.16);
  box-shadow: 0 calc(6px * var(--f-unit)) calc(18px * var(--f-unit)) rgba(0, 0, 0, 0.35);
}
#root[data-style="pulse"] .sc-logo  { height: calc(26px * var(--f-logo, 1) * var(--f-unit)); max-width: calc(92px * var(--f-logo, 1) * var(--f-unit)); }
#root[data-style="pulse"] .sc-handle { font-size: calc(26px * var(--f-scale, 1) * var(--f-unit)); letter-spacing: 0.03em; }

/* ======================================================================
 * PITCH — the cut-corner frame with a thick brand band along the bottom. The
 * corners are a clip-path on the border layer (top-left and bottom-right, so
 * the band's cut answers the frame's; its two mask layers and composite pair
 * are on that one element too), and a skewed sweep runs across the band.
 * ====================================================================== */
/* Pitch is cut 8 in from the source and its stroke is the 5 of padding below,
   so its stroke ends here — shallower than Pulse's ring, which is why the pill
   above stays where it was on this style until the line is heavy. */
#root[data-style="pitch"] { --f-edge: calc((8px + 5px * var(--f-line)) * var(--f-unit)); }
#root[data-style="pitch"] .sc-cut {
  position: absolute;
  inset: calc(8px * var(--f-unit));
  /* THE CUT LINE. The padding is the stroke (the mask drops the middle), so the
     thickness moves this and nothing else about the shape: the 34 of corner cut
     and the band below are the style's GEOMETRY, not its line. */
  padding: calc(5px * var(--f-line) * var(--f-unit));
  background: linear-gradient(135deg, var(--f-a) 0%, var(--f-b) 55%, var(--f-a) 100%);
  clip-path: polygon(calc(34px * var(--f-unit)) 0, 100% 0, 100% calc(100% - 34px * var(--f-unit)), calc(100% - 34px * var(--f-unit)) 100%, 0 100%, 0 calc(34px * var(--f-unit)));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
}
#root[data-style="pitch"] .sc-id {
  left: calc(8px * var(--f-unit));
  right: calc(8px * var(--f-unit));
  bottom: calc(8px * var(--f-unit));
  /* Fixed: the band is part of the frame's shape, so it does not grow with the
     writing — and it does not grow with the LINE either. A thicker Pitch is a
     thicker cut round a band that is the same band; the day the band follows the
     thickness is the day the style has two sizes instead of one look.
     64 design px holds Large (37.5) and a 120 % logo (52.8). */
  height: calc(64px * var(--f-unit));
  max-width: none;
  gap: calc(16px * var(--f-unit));
  padding: 0 calc(26px * var(--f-unit));
  overflow: hidden;
  background: linear-gradient(90deg, var(--f-a) 0%, var(--f-a) 58%, var(--f-b) 100%);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 26px * var(--f-unit)), calc(100% - 26px * var(--f-unit)) 100%, 0 100%);
}
#root[data-style="pitch"] .sc-logo { height: calc(44px * var(--f-logo, 1) * var(--f-unit)); max-width: calc(132px * var(--f-logo, 1) * var(--f-unit)); }
#root[data-style="pitch"] .sc-handle {
  font-size: calc(30px * var(--f-scale, 1) * var(--f-unit));
  letter-spacing: 0.04em;
  text-transform: uppercase;      /* the look is shouty whatever the theme's case says */
  text-shadow: 0 calc(2px * var(--f-unit)) calc(6px * var(--f-unit)) rgba(0, 0, 0, 0.3);
}
/* The sweep spans the BAND rather than being a 92px box that has to be told how
   far to travel: the travelling element is as wide as what it crosses, the
   highlight is painted into its left end with `background-size`, and the
   keyframe ends at `translateX(100%)` — one band width, whatever that is. So
   the light crosses the whole band at 860 wide and at 1920 wide alike. */
.sc-sweep {
  position: absolute;
  top: -30%;
  left: 0;
  right: 0;
  height: 160%;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.4) 50%, rgba(255, 255, 255, 0) 100%) no-repeat;
  background-size: calc(92px * var(--f-unit)) 100%;
  transform: skewX(-18deg) translateX(calc(-180px * var(--f-unit)));
}
#root[data-style="pitch"][data-anim="calm"] .sc-sweep   { animation: sc-sweep 6s ease-in-out infinite; }
#root[data-style="pitch"][data-anim="lively"] .sc-sweep { animation: sc-sweep 3s ease-in-out infinite; }
/* The travel is over at 55%; the rest of the loop is the gap, which makes it
   read as "every six seconds", not "always sweeping". */
@keyframes sc-sweep {
  0%        { transform: skewX(-18deg) translateX(calc(-180px * var(--f-unit))); }
  55%, 100% { transform: skewX(-18deg) translateX(100%); }
}
/* …and the frame arrives from below once, on load. `both` so it holds where
   it lands; `off` never plays it, and the frame is drawn either way. */
#root[data-style="pitch"]:not([data-anim="off"]) .sc-cut,
#root[data-style="pitch"]:not([data-anim="off"]) .sc-id {
  animation: sc-rise 0.6s cubic-bezier(0.16, 0.84, 0.32, 1) both;
}
@keyframes sc-rise {
  from { transform: translateY(calc(72px * var(--f-unit))); opacity: 0; }
  to   { transform: translateY(0); opacity: 1; }
}

/* ======================================================================
 * BROADCAST — a clean rule with L-shaped corner brackets, a lower-third tab,
 * and a short bright segment travelling the top and bottom lines.
 *
 * THE RULE WENT INVISIBLE IN OBS and nothing was hiding it — no mask, no
 * keyframe, no inset, no overflow. It was 2px of `rgba(var(--f-text-rgb),.6)`:
 * a 60% tint of the TEXT colour, the one colour here that is NOT a brand
 * colour, which washes out of a bright camera and sinks into a dark one. So:
 * the BRAND colour, 3 design px at its thinnest, opaque, over a dark keyline — an OUTER
 * box-shadow, clipped to outside the border box, so it can never fog the
 * see-through middle (`inset` would, and is banned here). NO mask here, so
 * nothing waits on `mask-composite`, and the shimmer rides ON the line instead
 * of drawing it: `data-anim="off"` is a whole frame.
 * ====================================================================== */
/* Broadcast is a rule with BRACKETS SITTING OUTSIDE IT, 4 in from the source,
   and the 3 px of clear air between the two is the whole motif — so the rule
   steps inwards as the stroke grows instead of letting the brackets swallow it:
   4 (the bracket) + 3 x the line (its stroke) + 3 (the gap) = where the rule
   starts. At `thin` that is 10, exactly where it always was. `--f-rule` is the
   one number the rule and the two shims that ride ON it share; `--f-edge` is
   where that rule's own stroke then ends, for the pill and the tab above. */
#root[data-style="broadcast"] {
  --f-rule: calc((7px + 3px * var(--f-line)) * var(--f-unit));
  --f-edge: calc(var(--f-rule) + 3px * var(--f-line) * var(--f-unit));
}
#root[data-style="broadcast"] .sc-edge {
  position: absolute;
  inset: var(--f-rule);
  /* THE RULE. 3 design px is the thinnest it is ever drawn (`thin`) and the
     floor the whole style was rebuilt around — under that it disappears over a
     camera — and every heavier step is that times the line. */
  border: calc(3px * var(--f-line) * var(--f-unit)) solid var(--f-a);
  border-radius: calc(4px * var(--f-unit));
  box-shadow: 0 0 0 calc(1px * var(--f-unit)) rgba(0,0,0,.55), 0 0 calc(6px * var(--f-unit)) rgba(0,0,0,.35);
}
/* The brackets wear the rule's stroke, and their LEGS grow with it but only
   mildly — 4 design px per step, so 30 at `thin` (what they always were) and 44
   at the heaviest. A bracket whose legs stayed at 30 under a 13 px stroke reads
   as a blob rather than as a corner. */
.sc-corner {
  position: absolute;
  width: calc((26px + 4px * var(--f-line)) * var(--f-unit));
  height: calc((26px + 4px * var(--f-line)) * var(--f-unit));
  border: calc(3px * var(--f-line) * var(--f-unit)) solid var(--f-a);
}
/* A bracket is a square with two borders off, so a shadow all round it would
   lay dark lines across the camera; offset to the corner's own two sides it
   lands only on the stroke that is there. */
.sc-corner.is-tl { left: calc(4px * var(--f-unit)); top: calc(4px * var(--f-unit)); border-right: 0; border-bottom: 0; box-shadow: calc(-1px * var(--f-unit)) calc(-1px * var(--f-unit)) 0 rgba(0,0,0,.55); }
.sc-corner.is-tr { right: calc(4px * var(--f-unit)); top: calc(4px * var(--f-unit)); border-left: 0; border-bottom: 0; box-shadow: calc(1px * var(--f-unit)) calc(-1px * var(--f-unit)) 0 rgba(0,0,0,.55); }
.sc-corner.is-bl { left: calc(4px * var(--f-unit)); bottom: calc(4px * var(--f-unit)); border-right: 0; border-top: 0; box-shadow: calc(-1px * var(--f-unit)) calc(1px * var(--f-unit)) 0 rgba(0,0,0,.55); }
.sc-corner.is-br { right: calc(4px * var(--f-unit)); bottom: calc(4px * var(--f-unit)); border-left: 0; border-top: 0; box-shadow: calc(1px * var(--f-unit)) calc(1px * var(--f-unit)) 0 rgba(0,0,0,.55); }
/* The shimmer, the same shape as Pitch's sweep and for the same reason: the
   element spans the LINE it rides, a 150 design px highlight is painted into
   its left end, and the keyframe ends one full width along — so it crosses at
   any source size. The bottom one runs the other way, so the two read as a
   circuit. It is decoration — the line is whole without it. */
.sc-shim {
  position: absolute;
  left: var(--f-rule);
  right: var(--f-rule);
  /* It rides ON the rule, so it is exactly as tall as the rule is. */
  height: calc(3px * var(--f-line) * var(--f-unit));
  background: linear-gradient(90deg, rgba(var(--f-b-rgb), 0) 0%, var(--f-b) 50%, rgba(var(--f-b-rgb), 0) 100%) no-repeat;
  background-size: calc(150px * var(--f-unit)) 100%;
  transform: translateX(calc(-180px * var(--f-unit)));
  opacity: 0.9;
}
.sc-shim.is-top { top: var(--f-rule); }
.sc-shim.is-bot { bottom: var(--f-rule); }
#root[data-style="broadcast"][data-anim="calm"] .sc-shim   { animation: sc-shim 8s linear infinite; }
#root[data-style="broadcast"][data-anim="lively"] .sc-shim { animation: sc-shim 3s linear infinite; }
/* …after the shorthand above, which would otherwise reset the direction. */
#root[data-style="broadcast"] .sc-shim.is-bot { animation-direction: reverse; }
@keyframes sc-shim {
  from { transform: translateX(calc(-180px * var(--f-unit))); }
  to   { transform: translateX(100%); }
}
#root[data-style="broadcast"] .sc-id {
  /* 30 is where the tab has always sat and where it stays: the rule only comes
     out past it at the heaviest step, and then the tab clears it by the same 6
     everything else does. */
  left: max(calc(30px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  bottom: max(calc(30px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  padding: calc(9px * var(--f-unit)) calc(18px * var(--f-unit));
  border-radius: calc(3px * var(--f-unit));
  background: rgba(var(--f-bg-rgb), 0.82);
  border-left: calc(3px * var(--f-unit)) solid var(--f-b);
  box-shadow: 0 calc(6px * var(--f-unit)) calc(16px * var(--f-unit)) rgba(0, 0, 0, 0.32);
}
#root[data-style="broadcast"] .sc-logo  { height: calc(24px * var(--f-logo, 1) * var(--f-unit)); max-width: calc(84px * var(--f-logo, 1) * var(--f-unit)); }
#root[data-style="broadcast"] .sc-handle { font-size: calc(24px * var(--f-scale, 1) * var(--f-unit)); letter-spacing: 0.07em; }

/* ======================================================================
 * BLAZE — fire. Tongues licking up from the bottom edge and along the lower
 * sides, the first brand colour their core and the second their tips, under a
 * fine line that carries the rest of the edge.
 *
 * The fire is PAINTED, in two layers of radial ellipses — one on the element,
 * one on its ::before, their tongues at different places along the edge — so
 * `off` is a fire that is drawn and still. The keyframes only scale the layers
 * up from the bottom at DIFFERENT speeds, which is what reads as a flicker
 * rather than a pulse; `calm` swaps that for one slow breath of the same
 * flames. Every tongue is sized in PER CENT of the band it rises from, so it is
 * the same fire at 480 px and at 4K with no length of its own.
 * ====================================================================== */
#root[data-style="blaze"] { --f-edge: calc((10px + 2px * var(--f-line)) * var(--f-unit)); }
/* The plain line TWO styles wear — Blaze's edge over the fire, Floodlight's
   frame under its lamps — one rule, one stroke, in the same money as the rest. */
.sc-fline {
  position: absolute;
  inset: calc(10px * var(--f-unit));
  border: calc(2px * var(--f-line) * var(--f-unit)) solid var(--f-a);
  border-radius: calc(6px * var(--f-unit));
  box-shadow: 0 0 0 calc(1px * var(--f-unit)) rgba(0, 0, 0, 0.45);
}
/* The bottom 46 %, as far as a tongue ever reaches; the only thing translucent
   over the camera is the heat sitting ON the edge. */
#root[data-style="blaze"] .sc-flame {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: 54%;
  transform-origin: 50% 100%;
  background:
    radial-gradient(ellipse 8% 44% at 11% 100%, rgba(var(--f-b-rgb), 0.9), rgba(var(--f-a-rgb), 0.62) 40%, rgba(var(--f-a-rgb), 0) 70%),
    radial-gradient(ellipse 11% 66% at 28% 100%, rgba(var(--f-b-rgb), 0.82), rgba(var(--f-a-rgb), 0.6) 38%, rgba(var(--f-a-rgb), 0) 68%),
    radial-gradient(ellipse 9% 50% at 47% 100%, rgba(var(--f-b-rgb), 0.86), rgba(var(--f-a-rgb), 0.58) 42%, rgba(var(--f-a-rgb), 0) 70%),
    radial-gradient(ellipse 12% 70% at 67% 100%, rgba(var(--f-b-rgb), 0.8), rgba(var(--f-a-rgb), 0.6) 36%, rgba(var(--f-a-rgb), 0) 66%),
    radial-gradient(ellipse 8% 46% at 87% 100%, rgba(var(--f-b-rgb), 0.88), rgba(var(--f-a-rgb), 0.6) 40%, rgba(var(--f-a-rgb), 0) 70%),
    radial-gradient(ellipse 20% 30% at 0% 76%, rgba(var(--f-b-rgb), 0.55), rgba(var(--f-a-rgb), 0.45) 40%, rgba(var(--f-a-rgb), 0) 72%),
    radial-gradient(ellipse 20% 30% at 100% 76%, rgba(var(--f-b-rgb), 0.55), rgba(var(--f-a-rgb), 0.45) 40%, rgba(var(--f-a-rgb), 0) 72%),
    linear-gradient(to top, rgba(var(--f-a-rgb), 0.34) 0%, rgba(var(--f-a-rgb), 0) 34%);
}
/* The second rank, BETWEEN the first: the two never line up, which is why it
   reads as fire and not as a bar of light. */
#root[data-style="blaze"] .sc-flame::before {
  content: "";
  position: absolute;
  inset: 0;
  transform-origin: 50% 100%;
  opacity: 0.85;
  background:
    radial-gradient(ellipse 7% 56% at 19% 100%, rgba(var(--f-b-rgb), 0.85), rgba(var(--f-a-rgb), 0.5) 40%, rgba(var(--f-a-rgb), 0) 70%),
    radial-gradient(ellipse 9% 40% at 38% 100%, rgba(var(--f-b-rgb), 0.8), rgba(var(--f-a-rgb), 0.5) 42%, rgba(var(--f-a-rgb), 0) 72%),
    radial-gradient(ellipse 10% 62% at 57% 100%, rgba(var(--f-b-rgb), 0.85), rgba(var(--f-a-rgb), 0.5) 38%, rgba(var(--f-a-rgb), 0) 68%),
    radial-gradient(ellipse 8% 46% at 77% 100%, rgba(var(--f-b-rgb), 0.8), rgba(var(--f-a-rgb), 0.5) 42%, rgba(var(--f-a-rgb), 0) 72%),
    radial-gradient(ellipse 7% 38% at 95% 100%, rgba(var(--f-b-rgb), 0.85), rgba(var(--f-a-rgb), 0.5) 40%, rgba(var(--f-a-rgb), 0) 70%);
}
/* CALM is a glow — the same flames, breathing, the two layers out of step.
   LIVELY is the flicker. */
#root[data-style="blaze"][data-anim="calm"] .sc-flame           { animation: sc-ember 6s ease-in-out infinite; }
#root[data-style="blaze"][data-anim="calm"] .sc-flame::before   { animation: sc-ember 8.5s ease-in-out infinite; animation-delay: -3s; }
#root[data-style="blaze"][data-anim="lively"] .sc-flame         { animation: sc-fire 1.5s ease-in-out infinite; }
#root[data-style="blaze"][data-anim="lively"] .sc-flame::before { animation: sc-fire2 1.1s ease-in-out infinite; }
@keyframes sc-ember {
  0%, 100% { transform: scaleY(1); opacity: 0.88; }
  50%      { transform: scaleY(1.06); opacity: 1; }
}
@keyframes sc-fire {
  0%, 100% { transform: scaleY(1) scaleX(1); opacity: 0.92; }
  30%      { transform: scaleY(1.16) scaleX(0.97); opacity: 1; }
  64%      { transform: scaleY(0.9) scaleX(1.03); opacity: 0.82; }
}
@keyframes sc-fire2 {
  0%, 100% { transform: scaleY(0.96) translateX(0); opacity: 0.8; }
  38%      { transform: scaleY(1.22) translateX(1%); opacity: 0.95; }
  71%      { transform: scaleY(0.86) translateX(-1%); opacity: 0.68; }
}

/* ======================================================================
 * BLADE — two sharp diagonal cuts at opposite corners and a DOUBLE line: a
 * heavy outer edge with a fine inner one held off it, both on the padding-box
 * mask Pitch uses and both in `--f-line`, so the pair thickens together and the
 * air between them stays the motif. A light runs each cut — a bar as long as
 * that cut's own hypotenuse, rotated onto it, the highlight travelling inside
 * it under `overflow: hidden`, so at `off` it is parked out of sight and the
 * two lines are the whole style.
 * ====================================================================== */
#root[data-style="blade"] { --f-edge: calc((13px + 5.5px * var(--f-line)) * var(--f-unit)); }
.sc-blade {
  position: absolute;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
}
.sc-blade.is-out {
  inset: calc(8px * var(--f-unit));
  padding: calc(4px * var(--f-line) * var(--f-unit));
  background: linear-gradient(135deg, var(--f-a) 0%, var(--f-b) 52%, var(--f-a) 100%);
  clip-path: polygon(calc(96px * var(--f-unit)) 0, 100% 0, 100% calc(100% - 96px * var(--f-unit)), calc(100% - 96px * var(--f-unit)) 100%, 0 100%, 0 calc(96px * var(--f-unit)));
}
.sc-blade.is-in {
  inset: calc((13px + 4px * var(--f-line)) * var(--f-unit));
  padding: calc(1.5px * var(--f-line) * var(--f-unit));
  background: rgba(var(--f-b-rgb), 0.85);
  clip-path: polygon(calc(80px * var(--f-unit)) 0, 100% 0, 100% calc(100% - 80px * var(--f-unit)), calc(100% - 80px * var(--f-unit)) 100%, 0 100%, 0 calc(80px * var(--f-unit)));
}
/* The cut runs from 8 in to 104 in, so its middle is 56 from BOTH sides and its
   hypotenuse is 96 root 2 — 136 design px, which is the bar. */
.sc-streak {
  position: absolute;
  width: calc(136px * var(--f-unit));
  height: calc(3px * var(--f-line) * var(--f-unit));
  overflow: hidden;
  opacity: 0.9;
}
.sc-streak::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(var(--f-b-rgb), 0) 0%, rgba(255, 255, 255, 0.95) 50%, rgba(var(--f-b-rgb), 0) 100%);
  transform: translateX(-130%);
}
.sc-streak.is-tl { left: calc(56px * var(--f-unit)); top: calc(56px * var(--f-unit)); transform: translate(-50%, -50%) rotate(-45deg); }
.sc-streak.is-br { right: calc(56px * var(--f-unit)); bottom: calc(56px * var(--f-unit)); transform: translate(50%, 50%) rotate(-45deg); }
#root[data-style="blade"][data-anim="calm"] .sc-streak::before   { animation: sc-cutlight 7s ease-in-out infinite; }
#root[data-style="blade"][data-anim="lively"] .sc-streak::before { animation: sc-cutlight 2.6s ease-in-out infinite; }
/* …after the shorthand, so the far cut lights half a cycle behind the near one. */
#root[data-style="blade"] .sc-streak.is-br::before { animation-delay: -1.3s; }
@keyframes sc-cutlight {
  0%        { transform: translateX(-130%); }
  62%, 100% { transform: translateX(230%); }
}

/* ======================================================================
 * CHEVRON — the border is a RING OF CHEVRONS pointing clockwise, alternating
 * the two brand colours, with a light chasing them round.
 *
 * Four nodes, one per edge, and NOT one per segment. Each edge is two
 * background layers, a near half and a far half, tiled in squares of
 * `--f-chev` — half the strip's height, so the tile is square whatever the
 * source is. In a square tile a 45deg hard-stop gradient splits corner to
 * corner and the two halves are mirror images: that is a chevron. Turn both
 * angles a quarter and they point the next way round — right along the top,
 * down the right, left along the bottom, up the left. The tile being a fixed
 * square rather than the edge's own length is what makes the phase the same at
 * 860 wide and at 3840, which `background-position` could never promise. The
 * chase is a TRANSLATING highlight, one per edge, a quarter cycle apart.
 * ====================================================================== */
#root[data-style="chevron"] {
  --f-chev: calc((4px + 2.5px * var(--f-line)) * var(--f-unit));
  --f-edge: calc((14px + 5px * var(--f-line)) * var(--f-unit));
  --f-chase: 9s;
}
#root[data-style="chevron"][data-anim="lively"] { --f-chase: 3.6s; }
.sc-chev { position: absolute; overflow: hidden; }
.sc-chev.is-top, .sc-chev.is-bot    { left: calc(6px * var(--f-unit)); right: calc(6px * var(--f-unit)); height: calc(2 * var(--f-chev)); }
.sc-chev.is-left, .sc-chev.is-right { top: calc(6px * var(--f-unit) + 2 * var(--f-chev)); bottom: calc(6px * var(--f-unit) + 2 * var(--f-chev)); width: calc(2 * var(--f-chev)); }
.sc-chev.is-top   { top: calc(6px * var(--f-unit)); }
.sc-chev.is-bot   { bottom: calc(6px * var(--f-unit)); }
.sc-chev.is-left  { left: calc(6px * var(--f-unit)); }
.sc-chev.is-right { right: calc(6px * var(--f-unit)); }
/* 49.5/50.5 rather than a flat 50: one per cent of the tile is the softest edge
   a gradient can be given with no length of its own, and it is what stops the
   diagonal crawling at 4K. */
.sc-chev.is-top {
  background:
    linear-gradient(45deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) left top / var(--f-chev) 50% repeat-x,
    linear-gradient(135deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) left bottom / var(--f-chev) 50% repeat-x;
}
.sc-chev.is-right {
  background:
    linear-gradient(135deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) right top / 50% var(--f-chev) repeat-y,
    linear-gradient(225deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) left top / 50% var(--f-chev) repeat-y;
}
.sc-chev.is-bot {
  background:
    linear-gradient(225deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) left bottom / var(--f-chev) 50% repeat-x,
    linear-gradient(315deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) left top / var(--f-chev) 50% repeat-x;
}
.sc-chev.is-left {
  background:
    linear-gradient(315deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) left top / 50% var(--f-chev) repeat-y,
    linear-gradient(45deg, var(--f-a) 0 49.5%, var(--f-b) 50.5% 100%) right top / 50% var(--f-chev) repeat-y;
}
/* The chase has the shape Pitch's sweep and Broadcast's shimmer have: the
   element spans the edge it rides, the highlight is painted into one end with
   `background-size`, and the keyframe ends one full edge along. */
.sc-chev::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.72) 50%, rgba(255, 255, 255, 0) 100%) no-repeat;
  background-size: calc(140px * var(--f-unit)) 100%;
  transform: translateX(calc(-160px * var(--f-unit)));
}
.sc-chev.is-left::before, .sc-chev.is-right::before {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.72) 50%, rgba(255, 255, 255, 0) 100%) no-repeat;
  background-size: 100% calc(140px * var(--f-unit));
  transform: translateY(calc(-160px * var(--f-unit)));
}
#root[data-style="chevron"]:not([data-anim="off"]) .sc-chev::before { animation: sc-chevx var(--f-chase) linear infinite; }
/* …then each edge is turned to face the way round: the uprights run on the Y
   keyframe, the bottom and the left run backwards, and the four are a quarter
   of a cycle apart — which is the light going round. */
#root[data-style="chevron"] .sc-chev.is-right::before { animation-name: sc-chevy; animation-delay: calc(var(--f-chase) * -0.75); }
#root[data-style="chevron"] .sc-chev.is-bot::before   { animation-direction: reverse; animation-delay: calc(var(--f-chase) * -0.5); }
#root[data-style="chevron"] .sc-chev.is-left::before  { animation-name: sc-chevy; animation-direction: reverse; animation-delay: calc(var(--f-chase) * -0.25); }
@keyframes sc-chevx {
  from { transform: translateX(calc(-160px * var(--f-unit))); }
  to   { transform: translateX(100%); }
}
@keyframes sc-chevy {
  from { transform: translateY(calc(-160px * var(--f-unit))); }
  to   { transform: translateY(100%); }
}

/* ======================================================================
 * FLOODLIGHT — a thin frame with a lamp in each top corner throwing a soft
 * beam down across the picture, the way a stadium does at night.
 *
 * A beam is ONE node: a box pinned to its corner, the cone cut out with a
 * `clip-path` in PER CENT (so it opens at the same angle whatever the source
 * is) and filled with a gradient all but gone a third of the way down — the
 * face under it is never covered, which is the only reason a beam is allowed
 * over the middle at all. The lamp is a radial stop at the cone's apex, so it
 * costs no node. The flicker is opacity and nothing else, the two lamps out of
 * step, slower at `calm`, absent at `off` — where the beams are still drawn,
 * because they ARE the style.
 * ====================================================================== */
#root[data-style="floodlight"] { --f-edge: calc((10px + 2px * var(--f-line)) * var(--f-unit)); }
.sc-beam {
  position: absolute;
  top: calc(10px * var(--f-unit));
  width: 72%;
  height: 86%;
  opacity: 0.9;
}
.sc-beam.is-l {
  left: calc(10px * var(--f-unit));
  clip-path: polygon(0 0, 9% 0, 96% 100%, 26% 100%);
  background:
    radial-gradient(ellipse 9% 5% at 4% 0%, rgba(var(--f-b-rgb), 0.95), rgba(var(--f-b-rgb), 0) 72%),
    linear-gradient(to bottom, rgba(var(--f-b-rgb), 0.32) 0%, rgba(var(--f-b-rgb), 0.12) 38%, rgba(var(--f-a-rgb), 0.05) 70%, rgba(var(--f-a-rgb), 0) 100%);
}
.sc-beam.is-r {
  right: calc(10px * var(--f-unit));
  clip-path: polygon(91% 0, 100% 0, 74% 100%, 4% 100%);
  background:
    radial-gradient(ellipse 9% 5% at 96% 0%, rgba(var(--f-b-rgb), 0.95), rgba(var(--f-b-rgb), 0) 72%),
    linear-gradient(to bottom, rgba(var(--f-b-rgb), 0.32) 0%, rgba(var(--f-b-rgb), 0.12) 38%, rgba(var(--f-a-rgb), 0.05) 70%, rgba(var(--f-a-rgb), 0) 100%);
}
#root[data-style="floodlight"][data-anim="calm"] .sc-beam   { animation: sc-flood 11s ease-in-out infinite; }
#root[data-style="floodlight"][data-anim="lively"] .sc-beam { animation: sc-flood 4.5s ease-in-out infinite; }
/* …after the shorthand, so the two lamps never flicker together. */
#root[data-style="floodlight"] .sc-beam.is-r { animation-delay: -2.6s; }
@keyframes sc-flood {
  0%, 100% { opacity: 0.88; }
  34%      { opacity: 0.72; }
  53%      { opacity: 1; }
  72%      { opacity: 0.8; }
}

/* ======================================================================
 * CREST — clipped colour wheel; all motion controls live below.
 * Stops sample equal perimeter distances, converted to angles with atan2.
 * The stationary ring owns thickness; moving paint never changes its cut.
 * ====================================================================== */
#root[data-style="crest"] {
  --f-edge: calc((10px + 4px * var(--f-line)) * var(--f-unit));
  --f-crest-stroke: calc(4px * var(--f-line) * var(--f-unit));
  --f-crest-run: 20s;
  --f-crest-comet: 7s;
  --f-crest-enter: 1s;
  --f-crest-light: .6;
  --f-crest-tail: 16deg;
}
/* THE SPEED IS THE FRAME'S OWN ANIMATION SETTING, not a control of its own:
   the desk above is CALM, what a new Streamcam is made on, and these are the
   three numbers the style shipped with. `off` reads neither — it is painted. */
#root[data-style="crest"][data-anim="lively"] {
  --f-crest-run: 12s;
  --f-crest-comet: 4s;
  --f-crest-light: .95;
}
#root[data-style="crest"] .sc-crest {
  position: absolute;
  inset: calc(10px * var(--f-unit));
  padding: calc(4px * var(--f-line) * var(--f-unit));
  overflow: hidden;
  container-type: size;
  /* The INNER edge of the stroke, written ONCE: the hole a skin winds its own
     outline around, chamfered to that skin's `--crest-inner-cut`. */
  --crest-ring:
    var(--crest-inner-cut) var(--f-crest-stroke),
    var(--f-crest-stroke) var(--crest-inner-cut),
    var(--f-crest-stroke) calc(100% - var(--crest-inner-cut)),
    var(--crest-inner-cut) calc(100% - var(--f-crest-stroke)),
    calc(100% - var(--crest-inner-cut)) calc(100% - var(--f-crest-stroke)),
    calc(100% - var(--f-crest-stroke)) calc(100% - var(--crest-inner-cut)),
    calc(100% - var(--f-crest-stroke)) var(--crest-inner-cut),
    calc(100% - var(--crest-inner-cut)) var(--f-crest-stroke),
    var(--crest-inner-cut) var(--f-crest-stroke);
}
#root[data-style="crest"] .sc-crest::before {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: calc(100cqw + 100cqh);
  height: calc(100cqw + 100cqh);
  transform: translate(-50%, -50%) rotate(0turn);
}
#root[data-style="crest"]:not([data-anim="off"]) .sc-crest::before {
  animation: sc-crestDraw var(--f-crest-enter) cubic-bezier(.16,1,.3,1) both,
    sc-crestrun var(--f-crest-run) linear var(--f-crest-enter) infinite;
}
@keyframes sc-crestrun {
  from { transform: translate(-50%, -50%) rotate(0turn); }
  to   { transform: translate(-50%, -50%) rotate(-1turn); }
}
/* The stop angles below are ALSO written by frame.js as plain degrees
   (`--f-crest-aN`, the same maths off this box): OBS's older Chromium cannot
   resolve atan2 here and would paint no ring. The atan2 is the fallback. */
/* Each skin owns the outer cut and the inner cut parallel to it, then hands
   both to the one ring above. Unlike clipping a rectangular mask, this leaves
   a continuous stroke across every chamfer. */
#root[data-style="crest"][data-skin="default"] .sc-crest {
  --crest-cut: calc(18px * var(--f-unit));
  --crest-inner-cut: calc(var(--crest-cut) + .414214 * var(--f-crest-stroke));
  clip-path: polygon(evenodd,
    var(--crest-cut) 0, calc(100% - var(--crest-cut)) 0,
    100% var(--crest-cut), 100% calc(100% - var(--crest-cut)),
    calc(100% - var(--crest-cut)) 100%, var(--crest-cut) 100%,
    0 calc(100% - var(--crest-cut)), 0 var(--crest-cut), var(--crest-cut) 0,
    var(--crest-ring), var(--crest-cut) 0);
}
#root[data-style="crest"][data-skin="skcards"] .sc-crest {
  --crest-cut: calc(28px * var(--f-unit));
  --crest-inner-cut: calc(var(--crest-cut) + .414214 * var(--f-crest-stroke));
  clip-path: polygon(evenodd,
    0 0, 100% 0, 100% 100%, 0 100%, 0 0,
    var(--crest-ring), 0 0);
}
#root[data-style="crest"][data-skin="default"] .sc-crest::before {
  --p1: calc((100cqw + 100cqh) * 0.16666667);
  --a1: var(--f-crest-a1, atan2(min(var(--p1), 50cqw), calc(50cqh - max(0cqw, var(--p1) - 50cqw))));
  --p2: calc((100cqw + 100cqh) * 0.33333333);
  --a2: var(--f-crest-a2, atan2(min(var(--p2), 50cqw), calc(50cqh - max(0cqw, var(--p2) - 50cqw))));
  background: conic-gradient(var(--f-a) 0deg var(--a1),
    var(--f-b) var(--a1) var(--a2),
    var(--f-a) var(--a2) 90deg,
    var(--f-b) 90deg calc(180deg - var(--a2)),
    var(--f-a) calc(180deg - var(--a2)) calc(180deg - var(--a1)),
    var(--f-b) calc(180deg - var(--a1)) 180deg,
    var(--f-a) 180deg calc(360deg - calc(180deg - var(--a1))),
    var(--f-b) calc(360deg - calc(180deg - var(--a1))) calc(360deg - calc(180deg - var(--a2))),
    var(--f-a) calc(360deg - calc(180deg - var(--a2))) 270deg,
    var(--f-b) 270deg calc(360deg - var(--a2)),
    var(--f-a) calc(360deg - var(--a2)) calc(360deg - var(--a1)),
    var(--f-b) calc(360deg - var(--a1)) 360deg);
}
#root[data-style="crest"][data-skin="skcards"] .sc-crest::before {
  --p1: calc((100cqw + 100cqh) * 0.11111111);
  --a1: var(--f-crest-a1, atan2(min(var(--p1), 50cqw), calc(50cqh - max(0cqw, var(--p1) - 50cqw))));
  --p2: calc((100cqw + 100cqh) * 0.22222222);
  --a2: var(--f-crest-a2, atan2(min(var(--p2), 50cqw), calc(50cqh - max(0cqw, var(--p2) - 50cqw))));
  --p3: calc((100cqw + 100cqh) * 0.33333333);
  --a3: var(--f-crest-a3, atan2(min(var(--p3), 50cqw), calc(50cqh - max(0cqw, var(--p3) - 50cqw))));
  --p4: calc((100cqw + 100cqh) * 0.44444444);
  --a4: var(--f-crest-a4, atan2(min(var(--p4), 50cqw), calc(50cqh - max(0cqw, var(--p4) - 50cqw))));
  background: conic-gradient(#701b32 0deg var(--a1),
    #e3b522 var(--a1) var(--a2),
    #8fc4e8 var(--a2) var(--a3),
    #701b32 var(--a3) var(--a4),
    #e3b522 var(--a4) calc(180deg - var(--a4)),
    #8fc4e8 calc(180deg - var(--a4)) calc(180deg - var(--a3)),
    #701b32 calc(180deg - var(--a3)) calc(180deg - var(--a2)),
    #e3b522 calc(180deg - var(--a2)) calc(180deg - var(--a1)),
    #8fc4e8 calc(180deg - var(--a1)) 180deg,
    #701b32 180deg calc(360deg - calc(180deg - var(--a1))),
    #e3b522 calc(360deg - calc(180deg - var(--a1))) calc(360deg - calc(180deg - var(--a2))),
    #8fc4e8 calc(360deg - calc(180deg - var(--a2))) calc(360deg - calc(180deg - var(--a3))),
    #701b32 calc(360deg - calc(180deg - var(--a3))) calc(360deg - calc(180deg - var(--a4))),
    #e3b522 calc(360deg - calc(180deg - var(--a4))) calc(360deg - var(--a4)),
    #8fc4e8 calc(360deg - var(--a4)) calc(360deg - var(--a3)),
    #701b32 calc(360deg - var(--a3)) calc(360deg - var(--a2)),
    #e3b522 calc(360deg - var(--a2)) calc(360deg - var(--a1)),
    #8fc4e8 calc(360deg - var(--a1)) 360deg);
}
/* A narrow white head and fading tail wash the chamfers as they pass. */
#root[data-style="crest"] .sc-crest::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: calc(100cqw + 100cqh); height: calc(100cqw + 100cqh);
  transform: translate(-50%, -50%);
  background: conic-gradient(#fff 0deg, #ffffff66 2deg,
    transparent var(--f-crest-tail), transparent 360deg);
  opacity: var(--f-crest-light);
}
#root[data-style="crest"]:not([data-anim="off"]) .sc-crest::after {
  animation: sc-crestLightIn var(--f-crest-enter) steps(1, end) both,
    sc-crestComet var(--f-crest-comet) linear var(--f-crest-enter) infinite;
}
#root[data-style="crest"][data-anim="off"] .sc-crest::after { display: none; }
@keyframes sc-crestDraw {
  from { transform: translate(-50%, -50%) scaleX(0); opacity: 0; }
  to { transform: translate(-50%, -50%) scaleX(1); opacity: 1; }
}
@keyframes sc-crestLightIn { from { opacity: 0; } to { opacity: var(--f-crest-light); } }
@keyframes sc-crestComet {
  from { transform: translate(-50%, -50%) rotate(0turn); }
  to { transform: translate(-50%, -50%) rotate(-1turn); }
}

/* ---- the four new styles' plate ----------------------------------------
 * The same identity block the others have, in the corner Pulse and Broadcast
 * keep it, clearing its own style's `--f-edge` by the same 6 — only the shape
 * of the plate under it is the style's own. Crest joins them: its plate is the
 * cut corner its border wears, and nothing about it is the skin's. */
#root[data-style="blaze"] .sc-id,
#root[data-style="blade"] .sc-id,
#root[data-style="chevron"] .sc-id,
#root[data-style="crest"] .sc-id,
#root[data-style="floodlight"] .sc-id {
  left: max(calc(28px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  bottom: max(calc(28px * var(--f-unit)), calc(var(--f-edge) + 6px * var(--f-unit)));
  padding: calc(8px * var(--f-unit)) calc(16px * var(--f-unit)) calc(8px * var(--f-unit)) calc(12px * var(--f-unit));
  background: rgba(var(--f-bg-rgb), 0.78);
  box-shadow: 0 calc(6px * var(--f-unit)) calc(18px * var(--f-unit)) rgba(0, 0, 0, 0.35);
}
#root[data-style="blaze"] .sc-id      { border-radius: 999px; border: calc(1px * var(--f-unit)) solid rgba(var(--f-b-rgb), 0.55); }
#root[data-style="blade"] .sc-id      { clip-path: polygon(calc(14px * var(--f-unit)) 0, 100% 0, 100% 100%, 0 100%, 0 calc(14px * var(--f-unit))); border-bottom: calc(2px * var(--f-unit)) solid var(--f-b); }
#root[data-style="chevron"] .sc-id    { clip-path: polygon(0 0, calc(100% - 13px * var(--f-unit)) 0, 100% 50%, calc(100% - 13px * var(--f-unit)) 100%, 0 100%); padding-right: calc(26px * var(--f-unit)); }
#root[data-style="floodlight"] .sc-id { border-radius: calc(3px * var(--f-unit)); border-top: calc(2px * var(--f-unit)) solid var(--f-b); }
/* Crest's plate answers its border: the same corner cut, top-left and
   bottom-right, at the plate's own size. GEOMETRY, not the skin — a skin swaps
   the colours and the cut on the BORDER, and the plate is furniture. */
#root[data-style="crest"] .sc-id      { clip-path: polygon(calc(12px * var(--f-unit)) 0, 100% 0, 100% calc(100% - 12px * var(--f-unit)), calc(100% - 12px * var(--f-unit)) 100%, 0 100%, 0 calc(12px * var(--f-unit))); }
#root[data-style="blaze"] .sc-logo,
#root[data-style="blade"] .sc-logo,
#root[data-style="chevron"] .sc-logo,
#root[data-style="crest"] .sc-logo,
#root[data-style="floodlight"] .sc-logo { height: calc(26px * var(--f-logo, 1) * var(--f-unit)); max-width: calc(92px * var(--f-logo, 1) * var(--f-unit)); }
#root[data-style="blaze"] .sc-handle,
#root[data-style="blade"] .sc-handle,
#root[data-style="chevron"] .sc-handle,
#root[data-style="crest"] .sc-handle,
#root[data-style="floodlight"] .sc-handle { font-size: calc(26px * var(--f-scale, 1) * var(--f-unit)); letter-spacing: 0.04em; }

/* ======================================================================
 * LOCKED — a Starter or Pro account that lapsed to Free. The frame does NOT
 * come off mid-broadcast: a plain rule and our tag, nothing else built, and
 * every setting still on the row — the thickness among them, which is why this
 * plate does NOT read `--f-line`: it is the same plate for everybody, and the
 * weight they chose comes back with the rest of it the day they upgrade.
 * ====================================================================== */
.sc-lock {
  position: absolute;
  inset: calc(10px * var(--f-unit));
  border: calc(2px * var(--f-unit)) solid rgba(255, 255, 255, 0.35);
  border-radius: calc(6px * var(--f-unit));
}
.sc-tag {
  position: absolute;
  right: calc(20px * var(--f-unit));
  bottom: calc(16px * var(--f-unit));
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: calc(12px * var(--f-unit));
  font-weight: 600;
  letter-spacing: 0.1em;
  color: rgba(255, 255, 255, 0.72);
  text-shadow: 0 calc(1px * var(--f-unit)) calc(3px * var(--f-unit)) rgba(0, 0, 0, 0.6);
}

/* ======================================================================
 * REDUCED MOTION — one rule, last, and blunt: a machine that asks for less
 * gets a frame that is FINISHED and still. Every gradient, glow, bracket, rule
 * and band is PAINTED, never an animation's first frame.
 * ====================================================================== */
@media (prefers-reduced-motion: reduce) {
  #root, #root *, #root *::before, #root *::after {
    animation: none !important;
    transition: none !important;
  }
}
