/* BuildWorth — a neutral, self-sufficient skin.
   A theme that ships a `skill_buildworth` template will override all of it;
   these rules only guarantee the tool is usable in any theme. */
.bw { max-width: 68rem; margin-inline: auto; }
.bw * { box-sizing: border-box; }
.bw-brand { font-size: .72rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; opacity: .7; margin: 0 0 .6rem; }
.bw-hero__title { font-size: clamp(1.7rem, 1.2rem + 2.2vw, 2.8rem); line-height: 1.12; margin: 0 0 .7rem; }
.bw-hero__text { font-size: 1.05rem; line-height: 1.7; opacity: .85; margin: 0 0 1.6rem; max-width: 44rem; }
.bw-h2 { font-size: 1.2rem; margin: 2rem 0 .8rem; }
.bw-fine { font-size: .84rem; opacity: .7; line-height: 1.6; margin: .4rem 0; }
.bw-alert { margin: 0 0 1rem; }
.bw-textlink { text-decoration: underline; text-underline-offset: 4px; }
.bw-list { margin: .6rem 0 1rem 1.1rem; }
.bw-list li { margin-block: .3rem; }
.bw--prose p { line-height: 1.75; max-width: 46rem; }

.bw-form { display: flex; gap: .7rem; align-items: flex-end; flex-wrap: wrap; padding: 1.1rem; }
.bw-field { flex: 1 1 22rem; min-width: 0; }
.bw-field__label { display: block; font-size: .8rem; font-weight: 600; margin-bottom: .35rem; }
.bw-input, .bw-refine__form input, .bw-refine__form select,
.bw-quote__form input, .bw-quote__form textarea {
    width: 100%; padding: .7rem .9rem; font: inherit;
    border: 1px solid currentColor; border-radius: 10px; background: transparent; color: inherit;
}
.bw-submit { white-space: nowrap; }
/* a web address reads left to right in every language, even on a right-to-left page */
[dir='rtl'] .bw-input { direction: ltr; text-align: right; }
.bw-quota { font-weight: 600; margin: 1rem 0 .2rem; }

.bw-recent__list { list-style: none; padding: 0; display: grid; gap: .6rem; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); }
.bw-recent__item a { display: flex; flex-direction: column; gap: .2rem; padding: .8rem 1rem; }

.bw-how__list { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); padding-left: 1.1rem; }
.bw-how__list b { display: block; margin-bottom: .2rem; }
.bw-how__list span { opacity: .8; font-size: .92rem; }

.bw-report__meta { display: flex; flex-wrap: wrap; gap: .5rem; font-size: .85rem; opacity: .75; }
.bw-url { word-break: break-all; }

.bw-running { padding: 1.2rem; }
.bw-running__label { font-weight: 600; margin: 0 0 .7rem; }
.bw-running__bar { display: block; height: 6px; border-radius: 999px; background: rgba(127,127,127,.25); overflow: hidden; }
.bw-running__bar i { display: block; height: 100%; width: 35%; border-radius: 999px; background: currentColor; animation: bwSlide 1.5s ease-in-out infinite; }
@keyframes bwSlide { 0% { margin-left: -35%; } 100% { margin-left: 100%; } }

.bw-summary { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); margin-block: 1.4rem; }
.bw-stat { padding: 1.1rem 1.2rem; }
.bw-stat__label { font-size: .74rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; opacity: .7; margin: 0 0 .5rem; }
.bw-stat__value { font-size: 1.8rem; font-weight: 800; margin: 0 0 .3rem; }
.bw-stat__value small { font-size: .9rem; opacity: .6; }
.bw-stat__value--muted { font-size: 1.05rem; font-weight: 600; opacity: .75; }

.bw-table { width: 100%; border-collapse: collapse; }
.bw-table th, .bw-table td { text-align: start; padding: .55rem .6rem; border-bottom: 1px solid rgba(127,127,127,.25); }

.bw-fix__list { list-style: none; padding: 0; display: grid; gap: .8rem; }
.bw-fix__item { padding: 1rem 1.1rem; }
.bw-fix__sev { font-size: .7rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; opacity: .75; margin: 0 0 .3rem; }
.bw-fix__title { font-size: 1.02rem; margin: 0 0 .4rem; }
.bw-fix__action { font-weight: 600; margin-top: .5rem; }

.bw-refine, .bw-quote { padding: 1.2rem; margin-block: 1.4rem; }
.bw-refine__form, .bw-quote__form { display: grid; gap: .8rem; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); align-items: end; }
.bw-quote__form { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }

.bw-foot { display: flex; gap: .6rem; flex-wrap: wrap; margin-block: 2rem 0; }

.bw-cta { display: block; padding: 1.4rem 1.5rem; border-radius: 16px; border: 1px solid currentColor; }
.bw-cta__label { display: block; font-size: .72rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; opacity: .7; }
.bw-cta__title { display: block; font-size: 1.3rem; font-weight: 800; margin-block: .4rem .3rem; }
.bw-cta__text { display: block; opacity: .8; }
.bw-cta__go { display: inline-block; margin-top: .8rem; font-weight: 700; }

@media (max-width: 640px) {
    .bw-form { flex-direction: column; align-items: stretch; }
    /* In a column the 22rem basis above becomes a HEIGHT, which left a
       350px gap between the field and the button on phones. */
    .bw-field { flex: 0 0 auto; }
    .bw-submit { width: 100%; }
}

/* ── the gate ───────────────────────────────────────────────────────────
   Name and e-mail before the assessment starts. With scripts on it is a
   dialog over a blurred page; with scripts off (no [data-bw-js] on the
   form) the same markup simply renders as two more fields in the form. */
.bw-gate { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; padding: 1rem; }
.bw-gate[hidden] { display: none; }
.bw-gate__backdrop { position: absolute; inset: 0; background: rgba(9, 11, 28, .58); backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px); }
.bw-gate__card {
    position: relative; width: min(100%, 27rem); display: grid; gap: .85rem;
    padding: 1.7rem 1.6rem 1.5rem; border-radius: 22px;
    background: Canvas; color: CanvasText;
    box-shadow: 0 32px 80px rgba(0, 0, 0, .38), 0 0 0 1px rgba(127, 127, 127, .18);
}
.bw-gate__title { font-size: 1.45rem; line-height: 1.2; margin: 0; }
.bw-gate__text { margin: 0 0 .3rem; line-height: 1.6; opacity: .8; }
.bw-gate__field { flex: 1 1 100%; }
.bw-gate__actions { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1rem; margin-top: .4rem; }
.bw-gate__confirm { flex: 1 1 12rem; }
.bw-gate__cancel { background: none; border: 0; padding: .5rem .2rem; font: inherit; color: inherit; opacity: .7; cursor: pointer; text-decoration: underline; text-underline-offset: 4px; }
.bw-gate__cancel:hover, .bw-gate__cancel:focus-visible { opacity: 1; }
html.bw-gate-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
    .bw-gate__backdrop { animation: bwGateFade .25s ease-out both; }
    .bw-gate__card { animation: bwGateRise .32s cubic-bezier(.2, .8, .3, 1) both; }
}
@keyframes bwGateFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes bwGateRise { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
/* lifted to <body>, the dialog is outside .bw: give it the box model back */
.bw-gate[data-bw-js], .bw-gate[data-bw-js] * { box-sizing: border-box; }
/* scripts off: the gate is part of the form, not a dialog */
.bw-form:not([data-bw-js]) .bw-gate { position: static; display: grid; padding: 0; flex: 1 1 100%; }
.bw-form:not([data-bw-js]) .bw-gate__backdrop { display: none; }
.bw-form:not([data-bw-js]) .bw-gate__card { width: 100%; box-shadow: none; padding: 0; border-radius: 0; background: transparent; color: inherit; animation: none; }
.bw-form:not([data-bw-js]) .bw-gate__cancel { display: none; }

/* a visitor we already know: who the report is for, and a way to change it */
.bw-known { margin: .8rem 0 0; font-size: .92rem; opacity: .85; }
.bw-known__change { background: none; border: 0; padding: 0; margin-inline-start: .35rem; font: inherit; color: inherit; cursor: pointer; text-decoration: underline; text-underline-offset: 4px; }
.bw-known__change[hidden] { display: none; }

/* ── the cost figure is GREEN ───────────────────────────────────────────
   It is the good news the report exists to deliver, and the amber "value"
   tone read as a warning. data-band="ok" lets a theme paint it with its
   own green; this rule makes sure of it when the theme paints by tone. */
.bw-summary .bw-stat[data-tone='value'] { --tone-value: var(--tone-ok, #22c55e); --t: var(--tone-ok, #22c55e); }
.bw-summary .bw-stat[data-tone='value'] .bw-stat__value { color: var(--tone-ok, #22c55e); }

/* A neutral two-column body for themes that do not style .bw-layout
   themselves. Stacks below 1080px, which is also the no-CSS behaviour. */
.bw-layout { display: grid; gap: 1.4rem; }
@media (min-width: 1080px) {
  .bw-layout { grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); align-items: start; column-gap: 2rem; }
}

/* Sentence-case labels at a readable size, and controls that stop growing.
   Small-caps labels under 12px are the two things that made this form hard
   to read; an input that spans a 32-inch monitor is the third. */
.bw-field__label { font-size: .9rem; font-weight: 600; text-transform: none; letter-spacing: normal; }
.bw-intro { display: grid; gap: 1.6rem; }
@media (min-width: 1080px) { .bw-intro { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); align-items: start; column-gap: 2rem; } }
.bw-field--wide { grid-column: 1 / -1; }

/* ═══════════════════════════════════════════════════════════════════════
   How it works — the scene
   The design's own artwork, pixel for pixel (scene.webp is lossless), with
   the motion drawn over it in one SVG whose viewBox IS the artwork's pixel
   grid. Every moving layer is transparent at rest, so a still frame is the
   picture itself. The artwork is lifted off its own ground (scene.webp is
   RGBA), so on a dark page the page's background IS its ground; on its own
   the scene is a rounded panel in that ground's colour, which gives the
   original picture back exactly.
   ═══════════════════════════════════════════════════════════════════════ */
.bw-sr {
  position: absolute !important;
  inline-size: 1px; block-size: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.bw-how--scene { container-type: inline-size; }
.bw-scene {
  position: relative; isolation: isolate;
  aspect-ratio: 770 / 862;
  border-radius: 18px; overflow: hidden; overflow: clip;
  /* the artwork's ground is transparent; on its own the scene stands on that ground, which
     gives his picture back */
  background: url("scene-ground.webp") 0 0 / 100% 100% no-repeat, rgb(18 16 45);
}
.bw-scene__base { display: block; inline-size: 100%; block-size: 100%; max-inline-size: none; }
.bw-scene__fx { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; overflow: hidden; pointer-events: none; }
/* The picture carries the three steps itself. While it is wide enough to
   read them, the list says them only to screen readers; on a narrow column
   the picture stops above its steps and the list shows. */
@container (min-width: 520px) {
  .bw-how--scene .bw-steps {
    position: absolute !important; inline-size: 1px; block-size: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
  }
}
/* Not in English: the steps drawn inside the picture are English, so the
   picture stops above them — at every width — and the translated list shows
   under it. The bw-how--own-steps class is set by the view from the locale. */
.bw-how--own-steps .bw-scene { aspect-ratio: 770 / 712; margin-block-end: 1.1rem; clip-path: inset(-20% -20% 0 -20%); }
.bw-how--own-steps .bw-scene__base {
  object-fit: cover; object-position: top;
  -webkit-mask-image: linear-gradient(#000 90%, transparent); mask-image: linear-gradient(#000 90%, transparent);
}
.bw-how--own-steps .bw-scene__fx { -webkit-mask-image: linear-gradient(#000 90%, transparent); mask-image: linear-gradient(#000 90%, transparent); }
.bw-how--own-steps .bw-scene [data-fx-steps] { visibility: hidden; }
@container (min-width: 520px) {
  .bw-how--own-steps .bw-steps {
    position: static !important; inline-size: auto; block-size: auto;
    margin: 0; padding: 0; overflow: visible;
    clip: auto; clip-path: none; white-space: normal;
  }
}
@container (max-width: 519.98px) {
  .bw-scene { aspect-ratio: 770 / 712; margin-block-end: 1.1rem; clip-path: inset(-20% -20% 0 -20%); }
  .bw-scene__base {
    object-fit: cover; object-position: top;
    -webkit-mask-image: linear-gradient(#000 90%, transparent); mask-image: linear-gradient(#000 90%, transparent);
  }
  /* hidden, not removed: removing would restart the rings off the shared clock */
  .bw-scene [data-fx-steps] { visibility: hidden; }
  .bw-scene__fx { -webkit-mask-image: linear-gradient(#000 90%, transparent); mask-image: linear-gradient(#000 90%, transparent); }
}

/* ── the three steps under the picture ── */
.bw-steps {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 10.5rem));
  justify-content: center;
  column-gap: clamp(1.4rem, 3.4vw, 2.8rem);
}
.bw-steps__item { --t: currentColor; position: relative; display: flex; flex-direction: column; align-items: flex-start; }
.bw-steps__item[data-tone='data']  { --t: var(--tone-data, #22d3ee); }
.bw-steps__item[data-tone='value'] { --t: var(--tone-value, #f5b942); }
.bw-steps__item[data-tone='live']  { --t: var(--tone-live, #fb7185); }
.bw-steps__icon {
  display: grid; place-items: center;
  inline-size: 3.5rem; block-size: 3.5rem;
  border-radius: 50%;
  border: 1.5px solid rgba(200, 190, 255, .28);
  margin-block-end: .95rem;
}
.bw-steps__icon svg { inline-size: 1.5rem; block-size: 1.5rem; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.bw-steps__num   { font-size: .78rem; font-weight: 800; letter-spacing: .08em; color: var(--t); margin-block-end: .3rem; }
/* Two balanced lines per step, as the design sets them: a one-line title
   beside two-line ones reads as a misaligned row. */
.bw-steps__title { max-inline-size: 8.2em; font-size: 1.02rem; font-weight: 700; line-height: 1.32; text-wrap: balance; }
/* the arrow between two steps, centred on the circles */
.bw-steps__item:not(:last-child)::after {
  content: '';
  position: absolute;
  inset-block-start: calc(1.75rem - .35rem);
  inset-inline-start: calc(3.5rem + (100% - 3.5rem) / 2 + .2rem);
  inline-size: 1.25rem; block-size: .7rem;
  background: currentColor; opacity: .35;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 12' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 6h17M13 1l5 5-5 5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 12' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 6h17M13 1l5 5-5 5'/%3E%3C/svg%3E") center / contain no-repeat;
}
[dir='rtl'] .bw-steps__item:not(:last-child)::after { transform: scaleX(-1); }
/* Still, as the design draws them: nothing in this column moves. */
@media (max-width: 560px) {
  .bw-steps { column-gap: 1rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .bw-steps__icon { inline-size: 3rem; block-size: 3rem; }
  .bw-steps__title { font-size: .92rem; }
  .bw-steps__item:not(:last-child)::after { display: none; }
}
.bw-fine--link { margin-block-start: .9rem; }

/* ── the scene's motion ─────────────────────────────────────────────────
   One 9-second clock drives everything. Every layer is transparent at rest
   (the 0% and 100% of each keyframe, and nothing starts before .5s), so the
   first frame, every loop's end, and the whole scene under reduced motion is
   the picture itself.
   The story: the A tile lights, the beam rises and the window is scanned
   (step 01); light runs out of the tile along the six cables and each card
   answers as it arrives; the bar blooms and the floor plate is traced (step
   02); the bar drains into its cap and fills back to where the picture has it
   (step 03). The light layer is screened onto the picture and its copies are
   the picture's own highlights (scene-hot.webp), so light only lands on what
   is already lit. The cover layer holds the two patches that stand in for the
   bar and the dots while they move. */
.bw-scene__fx--light { mix-blend-mode: screen; }
.bw-scene .fx { opacity: 0; }
.bw-scene .fx-run, .bw-scene .fx-plate path { fill: none; stroke-linecap: butt; stroke-dashoffset: -100; }
.bw-scene .fx-run--head { stroke-linecap: round; }
.bw-scene .fx-draw { stroke-dasharray: 100; stroke-dashoffset: 100; }
.bw-scene .fx-spark, .bw-scene .fx-mote { transform-box: fill-box; transform-origin: center; }
@media (prefers-reduced-motion: no-preference) {
  .bw-scene { --bw-loop: 9s; }
  .bw-scene .fx { animation: var(--bw-loop) linear infinite both; animation-delay: calc(var(--i, 0) * .12s + var(--d, 0s)); }
  .bw-scene .fx-tile        { animation-name: bwFxTile; }
  .bw-scene .fx-beam        { animation-name: bwFxBeam; }
  .bw-scene .fx-mote        { animation-name: bwFxMote; animation-timing-function: cubic-bezier(.3, 0, .6, 1); }
  .bw-scene .fx-scan        { animation-name: bwFxScanOn; }
  .bw-scene .fx-scan__band  { animation: bwFxScan var(--bw-loop) linear infinite both; }
  .bw-scene .fx-pulse       { animation-name: bwFxPulseOn; }
  .bw-scene .fx-run         { animation: bwFxRun var(--bw-loop) cubic-bezier(.4, 0, .8, .8) infinite both; animation-delay: calc(var(--i, 0) * .12s); }
  .bw-scene .fx-card        { animation-name: bwFxCard; }
  .bw-scene .fx-step--1     { animation-name: bwFxStep1; }
  .bw-scene .fx-step--2     { animation-name: bwFxStep2; }
  .bw-scene .fx-step--3     { animation-name: bwFxStep3; }
  .bw-scene .fx-step--1 .fx-draw { animation: bwFxDraw1 var(--bw-loop) linear infinite both; }
  .bw-scene .fx-step--2 .fx-draw { animation: bwFxDraw2 var(--bw-loop) linear infinite both; }
  .bw-scene .fx-step--3 .fx-draw { animation: bwFxDraw3 var(--bw-loop) linear infinite both; }
  .bw-scene .fx-barflash    { animation-name: bwFxBarFlash; }
  .bw-scene .fx-plate       { animation-name: bwFxPlateOn; }
  .bw-scene .fx-plate path  { animation: bwFxPlate var(--bw-loop) cubic-bezier(.4, 0, .6, 1) infinite both; }
  .bw-scene .fx-spark       { animation-name: bwFxSpark; animation-timing-function: ease-in-out; }
  .bw-scene .fx-track       { animation-name: bwFxTrack; }
  .bw-scene .fx-fill        { animation-name: bwFxFill; }
  .bw-scene .fx-fill__reveal { animation: bwFxReveal var(--bw-loop) linear infinite both; }
  .bw-scene .fx-dotcover    { animation-name: bwFxDotCover; }
  .bw-scene .fx-dot--1      { animation-name: bwFxDot1; }
  .bw-scene .fx-dot--2      { animation-name: bwFxDot2; }
}
/* 1s = 11.11% of the clock */
@keyframes bwFxTile     { 0%, 5.5% { opacity: 0; } 8.5% { opacity: .8; } 16%, 100% { opacity: 0; } }
@keyframes bwFxBeam     { 0%, 6% { opacity: 0; } 11% { opacity: .7; } 23%, 100% { opacity: 0; } }
@keyframes bwFxMote     { 0% { opacity: 0; transform: translateY(0); } 3% { opacity: .9; } 20%, 100% { opacity: 0; transform: translateY(calc(var(--rise) * -1px)); } }
@keyframes bwFxScanOn   { 0%, 11% { opacity: 0; } 12.5%, 28% { opacity: 1; } 29.5%, 100% { opacity: 0; } }
/* the pulse leaves the tile at 27% and reaches its card's border near 34.4%;
   the card lights with it, 60ms behind the head */
@keyframes bwFxPulseOn  { 0%, 27.5% { opacity: 0; } 28.5%, 35.8% { opacity: 1; } 36.8%, 100% { opacity: 0; } }
@keyframes bwFxRun      { 0%, 27% { stroke-dashoffset: -100; } 36.5%, 100% { stroke-dashoffset: 40; } }
@keyframes bwFxCard     { 0%, 33.4% { opacity: 0; animation-timing-function: cubic-bezier(.2, .7, .3, 1); } 35.2% { opacity: .85; animation-timing-function: cubic-bezier(.4, 0, .6, 1); } 46%, 100% { opacity: 0; } }
@keyframes bwFxStep1    { 0%, 6% { opacity: 0; } 7%, 33% { opacity: 1; } 37%, 100% { opacity: 0; } }
@keyframes bwFxStep2    { 0%, 36% { opacity: 0; } 37%, 63% { opacity: 1; } 67%, 100% { opacity: 0; } }
@keyframes bwFxStep3    { 0%, 66% { opacity: 0; } 67%, 91% { opacity: 1; } 95%, 100% { opacity: 0; } }
@keyframes bwFxDraw1    { 0%, 6% { stroke-dashoffset: 100; animation-timing-function: cubic-bezier(.4, 0, .2, 1); } 11%, 100% { stroke-dashoffset: 0; } }
@keyframes bwFxDraw2    { 0%, 36% { stroke-dashoffset: 100; animation-timing-function: cubic-bezier(.4, 0, .2, 1); } 41%, 100% { stroke-dashoffset: 0; } }
@keyframes bwFxDraw3    { 0%, 66% { stroke-dashoffset: 100; animation-timing-function: cubic-bezier(.4, 0, .2, 1); } 71%, 100% { stroke-dashoffset: 0; } }
@keyframes bwFxBarFlash { 0%, 57.5% { opacity: 0; } 60.5% { opacity: .9; } 67%, 100% { opacity: 0; } }
@keyframes bwFxPlateOn  { 0%, 59% { opacity: 0; } 60%, 71% { opacity: .9; } 72.5%, 100% { opacity: 0; } }
@keyframes bwFxPlate    { 0%, 59% { stroke-dashoffset: -100; } 72.5%, 100% { stroke-dashoffset: 26; } }
@keyframes bwFxSpark    { 0% { opacity: 0; transform: scale(.4); } 4% { opacity: 1; transform: scale(1.15); } 10%, 100% { opacity: 0; transform: scale(.4); } }
/* the bar: the copy of its fill (the picture's own pixels) comes on invisibly
   at 65.5%, the empty track fades in beneath it, the fill drains into its left
   cap (68.5-72.8%), refills with its own round cap (73.2-95.4%), and the patch
   fades out before the copy leaves — so the picture comes back without a seam */
@keyframes bwFxTrack    { 0%, 65.5% { opacity: 0; } 68.5%, 95.4% { opacity: 1; } 97.5%, 100% { opacity: 0; } }
@keyframes bwFxFill     { 0%, 65.4% { opacity: 0; } 65.5%, 97.4% { opacity: 1; } 97.5%, 100% { opacity: 0; } }
@keyframes bwFxReveal   { 0%, 68.5% { transform: translate(0, 0); animation-timing-function: cubic-bezier(.55, 0, .9, .5); }
                          72.8%, 73.2% { transform: translate(calc(var(--dx) * -1px), calc(var(--dy) * -1px)); animation-timing-function: cubic-bezier(.35, 0, .25, 1); }
                          95.4%, 100% { transform: translate(0, 0); } }
/* the dots type twice: 31-44.4% and 73.3-89% (the third returns with the face) */
@keyframes bwFxDotCover { 0%, 31% { opacity: 0; } 31.1%, 44.3% { opacity: 1; } 44.4%, 73.2% { opacity: 0; } 73.3%, 88.9% { opacity: 1; } 89%, 100% { opacity: 0; } }
@keyframes bwFxDot1     { 0%, 35.4% { opacity: 0; } 35.5%, 44.3% { opacity: 1; } 44.4%, 79.9% { opacity: 0; } 80%, 88.9% { opacity: 1; } 89%, 100% { opacity: 0; } }
@keyframes bwFxDot2     { 0%, 39.9% { opacity: 0; } 40%, 44.3% { opacity: 1; } 44.4%, 84.3% { opacity: 0; } 84.4%, 88.9% { opacity: 1; } 89%, 100% { opacity: 0; } }
/* the scan's keyframes follow the window's own perspective; generated by tools/cinemagraph.py */
/* scene:keyframes:start */
@keyframes bwFxScan { 0%, 11% { transform: translate(998.4px, 184.9px) skewY(-13.946deg) scale(308.2, 72); } 12.85% { transform: translate(998.4px, 188.1px) skewY(-13.827deg) scale(308.2, 72); } 14.70% { transform: translate(998.4px, 206.8px) skewY(-13.143deg) scale(308.2, 72); } 16.55% { transform: translate(998.4px, 246.5px) skewY(-11.673deg) scale(308.2, 72); } 18.40% { transform: translate(998.4px, 304.8px) skewY(-9.487deg) scale(308.2, 72); } 20.25% { transform: translate(998.4px, 373.8px) skewY(-6.865deg) scale(308.2, 72); } 22.10% { transform: translate(998.4px, 442.8px) skewY(-4.215deg) scale(308.2, 72); } 23.95% { transform: translate(998.4px, 501.1px) skewY(-1.959deg) scale(308.2, 72); } 25.80% { transform: translate(998.4px, 540.9px) skewY(-0.418deg) scale(308.2, 72); } 27.65% { transform: translate(998.4px, 559.5px) skewY(0.305deg) scale(308.2, 72); } 29.5%, 100% { transform: translate(998.4px, 562.8px) skewY(0.431deg) scale(308.2, 72); } }
/* scene:keyframes:end */

/* Arabic joins its letters: no tracking or capitals on the small labels. */
[dir='rtl'] .bw-brand, [dir='rtl'] .bw-stat__label, [dir='rtl'] .bw-fix__sev,
[dir='rtl'] .bw-cta__label, [dir='rtl'] .bw-steps__num { letter-spacing: 0; text-transform: none; }
