/* Dolvero v2 component layer - THE single definition of every shared component.
   Load AFTER v2-bg.css and BEFORE any page's inline <style>.

   Why this exists: ten pages were built separately and each redefined .card,
   .panel, .btn, .stat, .chip, .empty and h1 privately, with different padding,
   radius and colour. ~2,700 lines of inline CSS across the app and no two pages
   agreeing. A page must not redefine anything in here - if a component needs a
   variant, add a modifier class HERE so every page gets it.

   Every value is a token from v2-bg.css so both themes are automatic. */

:root{
  --ui-r-sm:8px; --ui-r:12px; --ui-r-lg:16px;
  --ui-pad:18px; --ui-pad-lg:22px;
  --ui-gap:14px;
  --ui-t:160ms cubic-bezier(.32,.72,0,1);
}

/* ---------- page scaffolding ---------- */
.v2wrap{max-width:1320px;margin:0 auto;padding:26px 20px 72px}
.v2wrap--narrow{max-width:860px}

.v2head{margin:6px 0 22px}
.v2head h1{font-size:clamp(24px,3.2vw,32px);font-weight:800;letter-spacing:-.03em;
  line-height:1.1;margin:0 0 6px}
.v2head p{font-size:14.5px;color:var(--muted);margin:0;line-height:1.6}

.v2head--center{max-width:660px;margin-left:auto;margin-right:auto;text-align:center}

.v2sec{margin:30px 0 12px;font-size:11px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:var(--faint)}
/* .v2sec carries its own vertical margin, which fights a flex row that wants to
   put a muted note beside the title. This is that row: the label loses the
   margin to the row, and the note sits on the same line and wraps below it on a
   narrow screen. */
.v2sechead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:30px 0 14px}
.v2sechead .v2sec{margin:0}
.v2sechead__note{font-size:12.5px;color:var(--muted)}

/* ---------- surfaces ---------- */
.ui-card{border-radius:var(--ui-r);padding:var(--ui-pad);
  background:var(--bg-glass);border:1px solid var(--bg-glass-line)}
.ui-panel{border-radius:var(--ui-r-lg);
  background:var(--bg-panel);border:1px solid var(--bg-glass-line);overflow:hidden}
/* a compact list row - .ui-card's 18px is far too much for a six-row stack */
.ui-card--sm{padding:11px 12px}
/* A header carries a title, often a standfirst and sometimes a badge or two, so
   it has to be allowed to wrap. */
.ui-panel__h{display:flex;align-items:center;gap:10px;padding:15px var(--ui-pad);
  border-bottom:1px solid var(--bg-glass-line);font-size:14px;font-weight:700;
  flex-wrap:wrap}
/* A panel title is frequently a real heading element. The page reset only zeroes
   margin and padding, so without this the UA renders an h2 at 1.5em and panel
   titles disagree from page to page. */
.ui-panel__h h1,.ui-panel__h h2,.ui-panel__h h3,.ui-panel__h h4{
  font-size:inherit;font-weight:inherit;line-height:inherit;letter-spacing:inherit}
/* the standfirst beside the title: it has to say it is neither 14px nor 700 */
.ui-panel__h__sub{font-size:12px;font-weight:400;letter-spacing:0;color:var(--muted)}
.ui-panel__b{padding:var(--ui-pad)}
.ui-panel__b--flush{padding:0}
/* a hero body - what the big panels used before they were migrated */
.ui-panel__b--lg{padding:var(--ui-pad-lg)}

@supports ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  .ui-card{-webkit-backdrop-filter:blur(14px) saturate(1.35);backdrop-filter:blur(14px) saturate(1.35)}
  .ui-panel{-webkit-backdrop-filter:blur(18px) saturate(1.3);backdrop-filter:blur(18px) saturate(1.3)}
}
@media (prefers-reduced-transparency: reduce){
  .ui-card,.ui-panel{background:var(--solid-fallback);
    -webkit-backdrop-filter:none;backdrop-filter:none}
}

/* ---------- the same surfaces without the blur ----------
   backdrop-filter is a compositing pass per element and prod is one shared
   vCPU, on a page people leave open all day. A directory paints up to 24 cards,
   points 12, and one analytics tab five panels: that is 24 blur passes to say
   what a border already says. Same radius, same padding, same border, same
   tinted ground - only the blur is dropped.

   Two things keep this honest. It sits AFTER the @supports block, so it wins on
   source order rather than by force, and it never restates `background`, so the
   reduced-transparency fallback above still owns the solid ground. */
.ui-card--plain{-webkit-backdrop-filter:none;backdrop-filter:none}
.ui-panel--flat{-webkit-backdrop-filter:none;backdrop-filter:none}

/* ---------- stat tiles ---------- */
.ui-stats{display:grid;gap:var(--ui-gap);
  grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}
.ui-stat{border-radius:var(--ui-r);padding:16px 18px;
  background:var(--bg-glass);border:1px solid var(--bg-glass-line)}
.ui-stat__l{font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;
  color:var(--faint);margin-bottom:7px}
.ui-stat__v{font-size:23px;font-weight:800;letter-spacing:-.025em;line-height:1.1}
.ui-stat__s{font-size:12.5px;color:var(--muted);margin-top:5px;line-height:1.5}
/* Inside a panel the tile is a card in a card. This keeps the type scale and
   the grid and drops the box. */
.ui-stat--bare{padding:0;background:none;border-color:transparent}
/* a per-row figure rather than a headline one */
.ui-stat__v--sm{font-size:14px;font-weight:600;letter-spacing:-.01em;line-height:1.35}

/* ---------- buttons: one scale, three intents ---------- */
.ui-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;
  height:40px;padding:0 18px;border-radius:var(--ui-r-sm);border:1px solid transparent;
  cursor:pointer;font-family:inherit;font-size:14px;font-weight:600;letter-spacing:-.005em;
  transition:background var(--ui-t),border-color var(--ui-t),box-shadow var(--ui-t),transform 120ms ease;
  text-decoration:none}
.ui-btn:active{transform:translateY(1px)}
.ui-btn:focus-visible{outline:2px solid var(--soft);outline-offset:2px}
.ui-btn[disabled],.ui-btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed;transform:none}
.ui-btn--primary{color:#fff;background:linear-gradient(135deg,var(--accent),var(--accent2));
  box-shadow:0 10px 26px -14px rgba(37,84,212,.9)}
.ui-btn--quiet{color:var(--text);background:var(--bg-glass);border-color:var(--bg-glass-line)}
.ui-btn--quiet:hover{border-color:var(--line2)}
/* --sell-text, not --sell: the raw token is 3.76:1 on white and fails AA in
   the light scheme. --sell-text exists in v2-bg.css for exactly this. */
.ui-btn--danger{color:var(--sell-text);background:transparent;border-color:rgba(239,68,68,.38)}
.ui-btn--sm{height:32px;padding:0 12px;font-size:12.5px}
/* An <a> cannot take `disabled`, so a pager arrow with nowhere to go says so
   with aria - and then has to stop being clickable, not merely look inert. */
a.ui-btn[aria-disabled="true"]{pointer-events:none}
/* the positive counterpart of --primary: a payout, a claim, an approval */
.ui-btn--ok{color:#fff;background:linear-gradient(135deg,var(--buy),#059669);
  box-shadow:0 10px 26px -14px rgba(16,185,129,.9)}
/* The momentary result of pressing it - a copy that worked, or did not. Both
   name the -text colour: raw --buy and --sell fail contrast on the light
   theme, and this is being read as words. */
.ui-btn.is-ok{color:var(--buy-text);background:rgba(16,185,129,.14);
  border-color:rgba(16,185,129,.45);box-shadow:none}
.ui-btn.is-bad{color:var(--sell-text);background:rgba(239,68,68,.12);
  border-color:rgba(239,68,68,.45);box-shadow:none}

/* ---------- chips ---------- */
.ui-chip{display:inline-flex;align-items:center;gap:5px;
  padding:3px 9px;border-radius:999px;font-size:11px;font-weight:700;
  letter-spacing:.04em;border:1px solid var(--bg-glass-line);color:var(--muted);
  background:var(--bg-glass)}
.ui-chip--ok{color:var(--buy-text);background:rgba(16,185,129,.13);border-color:rgba(16,185,129,.3)}
.ui-chip--bad{color:var(--sell-text);background:rgba(239,68,68,.13);border-color:rgba(239,68,68,.32)}
.ui-chip--warn{color:var(--warn);background:rgba(245,158,11,.13);border-color:rgba(245,158,11,.32)}
.ui-chip--info{color:var(--soft);background:rgba(79,125,240,.13);border-color:rgba(79,125,240,.3)}

/* ---------- tables ---------- */
.ui-tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.ui-table{width:100%;border-collapse:collapse;font-size:13px}
.ui-table th{position:sticky;top:0;z-index:1;text-align:left;white-space:nowrap;
  padding:10px 14px;font-size:10.5px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;color:var(--faint);
  background:var(--solid-fallback);border-bottom:1px solid var(--bg-glass-line)}
.ui-table td{padding:11px 14px;white-space:nowrap;
  border-bottom:1px solid rgba(147,184,255,.06)}
.ui-table tbody tr:hover td{background:rgba(255,255,255,.03)}
:root[data-theme="light"] .ui-table tbody tr:hover td{background:rgba(20,45,110,.04)}
.ui-table .num{text-align:right;font-variant-numeric:tabular-nums}
/* Ten columns do not fit a phone. The table keeps a floor and scrolls sideways
   inside .ui-tablewrap rather than crushing every column. */
.ui-table--wide{min-width:1000px}

/* ---------- empty and error states ---------- */
.ui-empty{padding:38px 22px;text-align:center;color:var(--faint);font-size:13.5px;
  line-height:1.65;border:1px dashed var(--bg-glass-line);border-radius:var(--ui-r)}
.ui-empty strong{display:block;color:var(--muted);font-size:14.5px;margin-bottom:6px}
/* The page column is 1320px and a centred line that long cannot be read, so the
   copy caps its own measure. A trailing action needs air above it. */
.ui-empty p{max-width:52ch;margin:0 auto}
.ui-empty .ui-btn{margin-top:14px}
/* An error says the same shape of thing as an empty state - a title, then a
   line explaining it - so it takes the same treatment and the same centring. */
.ui-error{padding:16px 18px;border-radius:var(--ui-r);font-size:13.5px;text-align:center;
  color:var(--sell-text);background:rgba(239,68,68,.09);border:1px solid rgba(239,68,68,.3)}
.ui-error strong,.ui-error h2,.ui-error h3{display:block;font-size:14.5px;
  font-weight:700;margin-bottom:6px}
.ui-error p{max-width:52ch;margin:0 auto}

/* ---------- meters ---------- */
/* display is load-bearing: this is a <span> at 6 of its call sites, and one of
   them sits in a bare <td> (analytics symbol P&L). An inline span ignores
   height, so the bar silently did not render there at all. */
.ui-meter{display:block;height:5px;border-radius:4px;overflow:hidden;background:rgba(147,184,255,.14)}
/* width:0 is load-bearing. Every call site sets an inline width; one that
   forgets used to paint FULL, and on this product a meter reads as drawdown
   used or progress to target. Full-by-default is a lie in the dangerous
   direction, so the floor is empty and the inline width is the only thing that
   fills it. */
.ui-meter i{display:block;width:0;height:100%;border-radius:4px;
  background:linear-gradient(90deg,var(--accent),var(--soft))}
.ui-meter--ok i{background:linear-gradient(90deg,var(--buy),#34d399)}
.ui-meter--warn i{background:linear-gradient(90deg,var(--warn),#fbbf24)}
.ui-meter--bad i{background:linear-gradient(90deg,var(--sell),#f87171)}

/* ---------- segmented control (one size, matching the challenges picker) ---------- */
.ui-seg{display:inline-flex;padding:3px;gap:3px;border-radius:10px;
  background:var(--bg-glass);border:1px solid var(--bg-glass-line)}
.ui-seg button,.ui-seg a{padding:8px 15px;border:none;border-radius:var(--ui-r-sm);
  background:none;cursor:pointer;font-family:inherit;font-size:13px;font-weight:600;
  color:var(--muted);text-decoration:none;transition:background var(--ui-t),color var(--ui-t)}
.ui-seg button:hover:not(:disabled):not(.is-on),
.ui-seg a:hover:not(.is-on){color:var(--text);background:rgba(255,255,255,.05)}
.ui-seg .is-on{background:#fff;color:#0b1120}
:root[data-theme="light"] .ui-seg .is-on{background:var(--accent);color:#fff}
.ui-seg button:disabled{opacity:.4;cursor:not-allowed}
/* The pages that had a focus ring lost it to the migration and fell back to the
   UA default. One of these controls is the checkout picker, so it gets the same
   ring as every other focusable thing in this layer. */
.ui-seg button:focus-visible,.ui-seg a:focus-visible{outline:2px solid var(--soft);
  outline-offset:2px}
/* One line is the default on purpose. Six view tabs, or one chip per account
   status, do not fit a phone - those opt in rather than scrolling sideways. */
.ui-seg--wrap{flex-wrap:wrap}

/* ---------- form controls ----------
   There was no form layer at all, which is why settings, the directory toolbar
   and the referral link field each kept their own. One control height (40px,
   the same as .ui-btn) so a select and a button line up in one toolbar row. */
.ui-field{display:flex;flex-direction:column;gap:7px;min-width:0}
.ui-field__l{font-size:11px;font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--faint)}
.ui-input,.ui-select{width:100%;min-width:0;height:40px;padding:0 12px;
  border-radius:var(--ui-r-sm);border:1px solid var(--bg-glass-line);
  background:var(--bg-glass);color:var(--text);font-family:inherit;font-size:13.5px;
  transition:border-color var(--ui-t),box-shadow var(--ui-t)}
.ui-input::placeholder{color:var(--faint)}
.ui-input:hover,.ui-select:hover{border-color:var(--line2)}
.ui-input:focus,.ui-select:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px rgba(79,125,240,.2)}
.ui-input[readonly]{color:var(--muted)}
.ui-select{cursor:pointer}
/* the dropdown list is painted by the OS and inherits nothing from the page */
.ui-select option{background:var(--solid-fallback);color:var(--text)}
/* one bordered box holding an icon and a bare input - the referral link field.
   The ring goes on the box, because the input inside it has no border of its
   own to light up. */
.ui-inwrap{display:flex;align-items:center;gap:9px;height:40px;padding:0 13px;
  border-radius:var(--ui-r-sm);border:1px solid var(--bg-glass-line);
  background:var(--bg-glass);
  transition:border-color var(--ui-t),box-shadow var(--ui-t)}
.ui-inwrap:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px rgba(79,125,240,.2)}
.ui-inwrap svg{flex:none;color:var(--faint)}
.ui-inwrap input{flex:1;min-width:0;height:100%;border:none;background:none;
  color:var(--text);font-family:inherit;font-size:13.5px;outline:none}

/* ---------- pagination ----------
   Not .ui-seg: that styles only button and a children, and a pager needs a
   <span> for the page you are already on and for an arrow with nowhere to go. */
.ui-pager{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:7px;margin-top:26px}
.ui-pager a,.ui-pager span{min-width:36px;height:36px;padding:0 11px;
  display:inline-flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:600;border-radius:var(--ui-r-sm);
  border:1px solid var(--bg-glass-line);color:var(--muted);background:var(--bg-glass)}
.ui-pager a{text-decoration:none;
  transition:color var(--ui-t),border-color var(--ui-t),background var(--ui-t)}
.ui-pager a:hover{color:var(--text);border-color:var(--line2)}
.ui-pager a:focus-visible{outline:2px solid var(--soft);outline-offset:2px}
/* same inversion as .ui-seg .is-on, for the same reason */
.ui-pager .is-on{color:#0b1120;background:#fff;border-color:#fff}
:root[data-theme="light"] .ui-pager .is-on{color:#fff;background:var(--accent);
  border-color:var(--accent)}
.ui-pager .is-off{opacity:.34}
/* Scoped, not bare: `.ui-pager span` above carries an element in its selector
   and would otherwise outweigh a single class and keep the box on. */
.ui-pager .ui-pager__meta{border-color:transparent;background:none;
  color:var(--faint);font-weight:500}

/* ---------- avatar / monogram ----------
   One box, sized by --ui-av so the initials scale with it instead of every page
   picking its own pair. The ink is named rather than inherited: the accent goes
   dark blue in the light scheme and a near-black --text on it is unreadable. */
.ui-av{display:flex;align-items:center;justify-content:center;flex:none;
  width:var(--ui-av,36px);height:var(--ui-av,36px);border-radius:50%;overflow:hidden;
  font-size:calc(var(--ui-av,36px) * .34);font-weight:800;letter-spacing:.02em;
  line-height:1;color:#fff;
  background:linear-gradient(135deg,var(--accent),var(--accent2))}
.ui-av img{width:100%;height:100%;object-fit:cover;display:block}
.ui-av--sm{--ui-av:26px}
.ui-av--lg{--ui-av:44px}
.ui-av--xl{--ui-av:76px}
/* a pseudonymous entrant has no initials to show, so the box says so */
.ui-av--anon{color:var(--soft);background:var(--bg-glass);
  border:1px dashed var(--bg-glass-line)}

/* ---------- utilities ---------- */
/* P&L tone, defined once. --buy-text and --sell-text exist because raw --buy
   and --sell fail AA on white; in the dark scheme they are the same colour. */
.up,.ui-up{color:var(--buy-text)}
.down,.ui-down{color:var(--sell-text)}
.flat,.ui-flat{color:var(--muted)}
.ui-row{display:flex;align-items:center;gap:10px}
.ui-spread{display:flex;align-items:center;justify-content:space-between;gap:12px}
.ui-muted{color:var(--muted)}
.ui-faint{color:var(--faint)}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ---------- loading skeletons ----------
   Edge had no shared loading state at all: zero uses of `skeleton`, zero
   `is-loading`, one spinner and one shimmer, with seventeen files improvising
   their own. What they improvised was almost always the bare word "Loading"
   dropped into an .empty box. That tells a customer nothing about what is
   arriving, and it makes the layout jump when the real content lands, because
   one line of text was holding the space that a six-row table is about to want.

   A skeleton fixes both: it says "this is a table, it is coming" and it
   reserves the space so nothing moves.

   Markup contract:
     - the HOST carries aria-busy="true" while it waits, and drops it when the
       content lands.
     - the skeleton subtree carries aria-hidden="true". A screen reader
       announcing eight empty boxes is worse than silence; pair it with one .sr
       line naming what is loading.
     - a skeleton is for a REGION of content. A single action in flight, like
       the order button, gets .ui-spin instead.

   The sweep is a gradient on a pseudo-element moved with transform. Not an
   animated background-position, and above all not an animated background-image:
   that property is DISCRETE, so no engine interpolates it, and an element
   mid-swap has no background at all. transform is also the only one of the
   three the compositor runs without repainting the row every frame, which
   matters when a phone is showing thirty of these at once. */
.ui-sk{position:relative;overflow:hidden;display:block;
  height:12px;border-radius:6px;background:var(--w2)}
/* The highlight is --w3 laid over a --w2 ground, so the sweep is brighter than
   the base in BOTH themes without this file naming a colour of its own. Every
   value here is a token, exactly as the header promises. */
.ui-sk::after{content:'';position:absolute;inset:0;
  background:linear-gradient(90deg,transparent 0%,var(--w3) 50%,transparent 100%);
  transform:translateX(-100%);animation:uiSkSweep 1.4s ease-in-out infinite}
@keyframes uiSkSweep{to{transform:translateX(100%)}}

/* Shapes. Heights match the real components so the swap is invisible:
   --fig is .ui-stat__v at 23px, --sub is .ui-stat__s at 12.5px, --label is the
   11px uppercase .ui-stat__l. */
.ui-sk--fig{height:23px;border-radius:7px}
.ui-sk--title{height:17px;border-radius:6px}
.ui-sk--label{height:9px;border-radius:5px;width:42%}
.ui-sk--sub{height:11px;border-radius:5px;width:64%}
.ui-sk--pill{height:24px;border-radius:999px;width:78px}
.ui-sk--circle{border-radius:50%;height:var(--ui-av,34px);width:var(--ui-av,34px);flex:none}
.ui-sk--w25{width:25%}.ui-sk--w40{width:40%}.ui-sk--w55{width:55%}
.ui-sk--w70{width:70%}.ui-sk--w85{width:85%}.ui-sk--full{width:100%}

/* A figure tile, reserving exactly what .ui-stat occupies. Same radius, same
   padding, same surface, so four of these become four stats without a reflow. */
.ui-sk-stat{border-radius:var(--ui-r);padding:16px 18px;
  background:var(--bg-glass);border:1px solid var(--bg-glass-line);
  display:flex;flex-direction:column;gap:10px}
/* .ui-stats is the grid these sit in, so a skeleton set drops straight into it */
.ui-sk-stat .ui-sk--fig{width:72%}

/* Rows in a table or a list. The 11px/14px padding and the hairline are lifted
   from .ui-table td so the placeholder rows and the real rows share a rhythm. */
.ui-sk-row{display:flex;align-items:center;gap:14px;padding:11px 14px;
  border-bottom:1px solid var(--line)}
.ui-sk-row:last-child{border-bottom:none}
/* flex:1 would set flex-basis:0 and equalise every fluid cell, which silently
   makes the width modifiers no-ops inside a row: a --w40 and a --w25 came out
   the same size. `1 1 auto` lets the declared width act as the basis, so the
   cells keep their relative proportions and still share the leftover space. */
.ui-sk-row .ui-sk{flex:1 1 auto;min-width:0}
/* Fixed-size cells inside a row. These MUST be scoped to .ui-sk-row: the row
   gives every bar flex:1 at specificity 0-2-0, and flex:1 means flex-basis:0,
   which overrides a plain width. An unscoped .ui-sk--pill at 0-1-0 therefore
   lost its 78px and stretched to fill the row. Matching the row's specificity
   and coming later is what makes these hold their size. */
.ui-sk-row .ui-sk--num{flex:none;width:74px}
.ui-sk-row .ui-sk--pill{flex:none;width:78px}
.ui-sk-row .ui-sk--circle{flex:none;width:var(--ui-av,34px)}
/* Every row sweeping in lockstep reads as one flat object. A small stagger
   reads as a list of separate things, which is what it is. */
.ui-sk-row:nth-child(2) .ui-sk::after{animation-delay:.07s}
.ui-sk-row:nth-child(3) .ui-sk::after{animation-delay:.14s}
.ui-sk-row:nth-child(4) .ui-sk::after{animation-delay:.21s}
.ui-sk-row:nth-child(5) .ui-sk::after{animation-delay:.28s}
.ui-sk-row:nth-child(6) .ui-sk::after{animation-delay:.35s}
.ui-sk-row:nth-child(7) .ui-sk::after{animation-delay:.42s}
.ui-sk-row:nth-child(8) .ui-sk::after{animation-delay:.49s}

/* A paragraph. The closing line is short, which is the thing that makes a stack
   of bars read as text rather than as a chart. */
.ui-sk-lines{display:flex;flex-direction:column;gap:9px}
.ui-sk-lines .ui-sk:last-child{width:58%}

/* One action, one spinner: a single request in flight inside a button. Never
   for a region of content, which gets a skeleton. index.php had the only copy
   of this in the app, declared privately; this is that, shared. */
.ui-spin{display:inline-block;width:15px;height:15px;flex:none;
  border:2px solid var(--w3);border-top-color:var(--text);border-radius:50%;
  animation:uiSpin .62s linear infinite}
@keyframes uiSpin{to{transform:rotate(1turn)}}

/* Content replacing a skeleton should arrive, not blink into place. */
.ui-in{animation:uiIn .32s cubic-bezier(.32,.72,0,1) both}
@keyframes uiIn{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}

/* Asked for no motion, gets no motion. The states still change - they just
   arrive rather than ease in. */
@media (prefers-reduced-motion: reduce){
  .ui-input,.ui-select,.ui-inwrap,.ui-pager a{transition:none}
  /* The skeleton keeps its shape and loses its sweep. The shape is the part
     that does the work; the sweep was only ever saying "still going". */
  .ui-sk::after{animation:none;opacity:0}
  .ui-in{animation:none}
  /* A spinner that does not turn is not a spinner, and it is the only signal a
     busy button has. It slows down rather than stopping. */
  .ui-spin{animation-duration:1.5s}
}
