@import url("/data/export/tokens.css");

/* ═══════════════════════════════════════════════════════════════════
   THE LIVE LAYER

   Every specimen on this site is built with these rules. None of them
   is a screenshot. The text is real text, select it, copy it, edit it
   in devtools. The shape is the shape SVG this system ships. Hover,
   focus and the pressed state are the real ones, so if they are wrong
   here they are wrong in your app too.

   This file IS the implementation. The code panel on each component
   quotes it rather than describing it.
   ═══════════════════════════════════════════════════════════════════ */

.pcx{
  --pcx-shape:none;
  --pcx-w:auto;
  --pcx-h:auto;
  --pcx-ink:var(--pc-ink,#141414);
  --pcx-pad-x:0px;
  --pcx-pad-y:0px;

  position:relative;
  box-sizing:border-box;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:var(--pcx-w);
  height:var(--pcx-h);
  padding:var(--pcx-pad-y) var(--pcx-pad-x);

  /* the drawn plate, face, hard offset shadow and outline in one file */
  background:var(--pcx-shape) 50% 50% / 100% 100% no-repeat;

  font-family:var(--dsp);
  font-style:italic;
  font-weight:800;
  text-transform:uppercase;
  line-height:1;
  letter-spacing:.01em;
  /* every replica carries a price, a countdown, an odds figure or a balance 
     TYPOGRAPHY.md puts tabular figures on all of them, so it goes on the root
     and every specimen below inherits it */
  font-variant-numeric:tabular-nums;
  color:var(--pcx-ink);
  text-align:center;
  -webkit-user-select:text;
  user-select:text;
}

/* ── G26, white display type carries a black outline ─────────────
   Measured on the source page: of the white TEXT nodes sitting on a LIGHT
   ground, 32 of 32 are stroked, not most, all. On a dark ground it is
   discretionary (46 of 196). So the outline is what makes white type survive
   a ground that is close to it in value, and every specimen whose ink is white
   is a candidate regardless of the plate it happens to be shown on here.

   The ink arrives inline from the catalogue (`--pcx-ink:#ffffff`), and a custom
   property's VALUE cannot be matched by a selector, so this matches the style
   attribute text instead. Only two ink values exist in the catalogue, #000000
   (15) and #ffffff (6), so there is nothing else for this to catch by accident.

   Weight is the measured ramp, not a fixed 1px: ~1px per 30px of type, floored
   at 1px, capped at 2px. `paint-order` keeps it outside the glyph so a 19px
   button label does not thicken into mush. */
.pcx[style*="--pcx-ink:#ffffff" i],
.pcx[style*="--pcx-ink:#fff;" i],
.pcx[style*="--pcx-ink:white" i]{
  -webkit-text-stroke:var(--display-stroke,clamp(1px,.0333em,2px)) var(--pc-ink,#141414);
  paint-order:stroke fill;
}

/* the sub-display text inside a specimen is 0.30em and 0.43em, below the 18px
   floor at every size the library uses, and the artwork does not stroke there
   (2 of 310). Secondary text opts back out. */
.pcx .pcx-eyebrow,
.pcx .pcx-body,
.pcx .pcx-hint{ -webkit-text-stroke:0 }

/* content sits above the plate and never inherits its sizing */
.pcx > .pcx-t,
.pcx > .pcx-stack{ position:relative; z-index:1; max-width:100%; }

.pcx-stack{
  display:flex;
  flex-direction:column;
  gap:var(--pcx-gap,10px);
  align-items:flex-start;
  text-align:left;
  width:100%;
}

.pcx-eyebrow{
  font-family:var(--dsp); font-style:normal; font-weight:600;
  font-size:.30em; letter-spacing:.16em; opacity:.62;
}
.pcx-title{ font-size:1em; }
.pcx-row{ display:flex; gap:8px; flex-wrap:wrap; }

/* ── interaction ─────────────────────────────────────────────────
   The comic press: the face moves toward its own shadow and back.
   No easing curve is invented here, the product's standard band is
   160-240ms (SPEC_MOTION §2), and this sits at the bottom of it. */
/* The press distance is the component's OWN shadow offset, not a fixed 3px.
   LoadMore, the reference, moves 6.13, because that is where its shadow is.
   Hardcoding 3 made anything with a deep shadow read as a half-press: the face
   stops short of its own shadow instead of landing on it. Offsets across the
   library run 3.51 (mobile buttons) to 20.02 (SpinnerSelect). */
.pcx[data-interactive]{
  --press:3px;                    /* override per component from its shadow token */
  cursor:pointer;
  /* was a hand-typed .16s cubic-bezier(.16,1,.3,1); those are now
     --pc-duration-fast and --pc-ease-emphasized, measured x15 in the product */
  transition:transform var(--pc-duration-fast) var(--pc-ease-emphasized);
}
.pcx[data-interactive]:hover { transform:translate(calc(var(--press) * -1), calc(var(--press) * -1)) }
.pcx[data-interactive]:active{ transform:translate(var(--press), var(--press)) }

/* G10, the drawn ring follows the silhouette. A background-image plate
   cannot be stroked along its edge, so this is the DECLARED FALLBACK,
   not the same thing. 3px, because the silhouette ring is unavailable
   and a heavier rectangle reads worse than a lighter one. */
.pcx:focus-visible{
  outline:3px solid var(--pc-color-accent,#FFA800);
  outline-offset:2px;
}
.pcx[data-small]:focus-visible{ outline-width:3px }

/* ── motion ─────────────────────────────────────────────────────
   There is no motion layer here beyond the press above, and that is the point.
   The press is measured: the face travels to its own shadow and back (G15).
   Everything else the analysis proposed, an entrance rise, a steps(1) snap 
   was written, looked at, and deleted, because nothing in the library used it.
   An animation with no caller is decoration, and SPEC_MOTION §8 already ruled
   that out once. Motion enters this file when a component needs it, not before.

   What the product does that we deliberately do NOT adopt: rotation (7 uses,
   3 unrelated idioms, nothing else turns), spring (4 configs against dozens of
   tweens), and entrance animation on mount (the product animates pages and
   state changes, never a button appearing). */

/* ── reduced motion ─────────────────────────────────────────────
   The product respects this in under half its CSS and in 2 of 28 framer
   modules, 7%. On a prediction market that flashes and sweeps on the money
   path, that is the highest-priority finding in the motion analysis. This is a
   standard to raise, not one to inherit: everything that moves here stops. */
@media (prefers-reduced-motion:reduce){
  .pcx[data-interactive]{ transition:none }
  .pcx[data-interactive]:hover, .pcx[data-interactive]:active{ transform:none }
}

/* ── the skeleton rule, one class, every shape ─────────────────── */
.pcx[data-skeleton]{ filter:grayscale(1) brightness(0) invert(1) opacity(.14) }
.pcx[data-skeleton] > *{ visibility:hidden }

/* ── the fitter ──────────────────────────────────────────────────
   Specimens are shown at their drawn size and scaled to fit the card.
   transform: scale keeps the DOM real, the text stays selectable and
   the layout stays inspectable, which a resized raster cannot do. */
.pcx-fit{
  display:flex; align-items:center; justify-content:center;
  width:100%; height:100%; overflow:hidden;
}
.pcx-fit > .pcx-scale{
  transform:scale(var(--fit,1));
  transform-origin:center center;
  flex:0 0 auto;
}
/* sheet variant: width-fit with JS-tightened height, so a scaled-down wide
   specimen does not leave its full unscaled height as a hole in the stage */
.pcx-fit[data-tight]{height:auto;overflow:visible}
.pcx-fit[data-tight] > .pcx-scale{transform-origin:top center}

/* ── the stage in the detail sheet ───────────────────────────────── */
/* The stage holds the specimen. It draws NOTHING of its own, no checkerboard,
   no border, no second frame. A component sitting on decoration is a picture of
   a component; what belongs here is the thing itself.

   The one exception is legibility, not decoration: a handful of components are
   white type with no plate of their own, TableHeader, SummaryBar, DisplayTitle 
   and on the artwork they sit on the black page ground. Those are flagged
   surface:dark in the catalogue and get a flat fill, or they are invisible. */
.pcx-stage{
  position:relative;
  padding:34px;
  background:transparent;
  overflow:auto;
}
.pcx-stage[data-ground="dark"]{ background:#141414 }
.pcx-stage[data-ground="paper"]{ background:transparent }
.pcx-stage[data-ground="orange"]{ background:var(--pc-color-accent,#FFA800) }
.pcx-stage[data-ground="violet"]{ background:var(--pc-color-purple,#9652EF) }

.pcx-live-flag{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--mono); font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:#0AFFE2;
  border:1px solid rgba(10,255,226,.35); border-radius:2px;
  padding:3px 7px;
}
.pcx-live-flag::before{ content:''; width:5px; height:5px; border-radius:50%; background:#0AFFE2 }

.pcx-render-flag{
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--mono); font-size:10px; letter-spacing:.12em;
  text-transform:uppercase; color:var(--pc-color-accent,#FFA800);
  border:1px solid rgba(255,168,0,.35); border-radius:2px;
  padding:3px 7px;
}

/* ── the four authored components, built for real ────────────────── */

.pcx-chiprow{
  display:flex; gap:8px;                    /* the measured gap-2 */
  overflow-x:auto; scrollbar-width:none;
}
.pcx-chiprow::-webkit-scrollbar{ display:none }
.pcx-chiprow > *{ flex:0 0 auto }           /* never wraps to a second row */

.pcx-brandfield{
  display:flex; align-items:center; justify-content:center;
  min-height:72px; padding:24px 9%;         /* 9% = the far side of max-w-82% */
  background:var(--pc-color-accent,#FFA800);
}
.pcx-brandfield img{ max-height:48px; width:auto; max-width:82% }
.pcx-brandfield[data-tone="black"]{ background:var(--pc-ink,#141414) }
.pcx-brandfield[data-tone="violet"]{ background:var(--pc-color-purple,#9652EF) }
/* the mark is drawn orange: 1:1 on orange, 2.29:1 on violet. Both fail. */
.pcx-brandfield[data-tone="orange"] img,
.pcx-brandfield[data-tone="violet"] img{ filter:brightness(0) }

.pcx-stats{
  display:grid; grid-template-columns:repeat(2,1fr); width:100%;
}
@media (min-width:640px){ .pcx-stats{ grid-template-columns:repeat(4,1fr) } }
.pcx-stats > div{ padding:0 26px; border-left:2px solid var(--pc-ink,#141414) }  /* stroke/2, G6 */
.pcx-stats > div:first-child{ padding-left:0; border-left:0 }
.pcx-stats .k{
  font-family:var(--dsp); font-style:normal; font-weight:600;
  font-size:13px; letter-spacing:2.1px; text-transform:uppercase; opacity:.62;
}
.pcx-stats .v{
  font-family:var(--dsp); font-style:italic; font-weight:800;
  font-size:34px; margin-top:6px;
}

/* ═══════════════════════════════════════════════════════════════════
   STATES

   The artwork draws exactly ONE interaction state in the whole file 
   LoadMore's focus ring. Everything below is authored from that one
   precedent plus the comic mechanic the plates already carry, and each
   one says what it MEANS, because a state nobody can name is decoration.

   data-force is for the documentation matrix: it pins a state so it can
   be shown side by side. Never ship data-force in an app, use the real
   pseudo-classes, which are the rules directly above each forced one.
   ═══════════════════════════════════════════════════════════════════ */

/* HOVER, the plate lifts off its own shadow. The shadow is drawn INTO
   the SVG, so the face moves and the gap widens. No colour change:
   the artwork never recolours on hover. */
.pcx[data-force="hover"]{ transform:translate(calc(var(--press,3px) * -1), calc(var(--press,3px) * -1)) }

/* ACTIVE, it lands on its shadow. Same distance, opposite direction,
   so press and release are the same gesture reversed. */
.pcx[data-force="active"]{ transform:translate(var(--press,3px), var(--press,3px)) }

/* FOCUS, G10. The ring is the silhouette stroked; where the shape is a
   background image it cannot be stroked, so this is the declared fallback. */
.pcx[data-force="focus"]{ outline:3px solid var(--pc-color-accent,#FFA800); outline-offset:2px }

/* DISABLED, the control stops being a control. Colour is what carries
   meaning in this system (violet acts, green wins, red loses), so
   removing colour is the honest way to say "this does nothing now".
   The shadow stays: the plate is still a plate, it is just inert. */
.pcx[data-state="disabled"],
.pcx[data-force="disabled"]{
  filter:grayscale(1);
  opacity:.45;
  cursor:not-allowed;
  pointer-events:none;
}

/* LOADING, the skeleton rule. Not a separate drawing: the component's
   own silhouette, flattened. */
.pcx[data-force="loading"]{ filter:grayscale(1) brightness(0) invert(1) opacity(.14) }
.pcx[data-force="loading"] > *{ visibility:hidden }

/* ERROR, a 2px red inner stroke on the face, which is the device G2
   handed the error state when it took the orange ring away from it.
   Paired with AlertStrip [inline] beneath the field; the stroke alone
   is never enough, because colour alone is never enough. */
.pcx[data-state="error"],
.pcx[data-force="error"]{
  box-shadow:inset 0 0 0 2px var(--pc-color-danger,#EA2A46);
}

/* SELECTED, weight, not colour. Badge / Step already establishes this
   as the system's active convention, so selection reuses it rather than
   inventing a second signal. */
.pcx[data-state="selected"],
.pcx[data-force="selected"]{ font-weight:800; text-decoration:underline; text-underline-offset:.18em; text-decoration-thickness:.09em }

/* ── the documentation matrix ─────────────────────────────────── */
.pcx-matrix{
  display:grid; gap:14px;
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  margin:18px 0 6px;
}
.pcx-cell{
  border:1px solid #2a2a2e; border-radius:4px; overflow:hidden;
  background:#0e0e10;
}
.pcx-cell .top{
  display:flex; align-items:center; justify-content:center;
  height:104px; padding:10px; overflow:hidden;
}
.pcx-cell[data-ground="paper"] .top{ background:var(--pc-paper,#EFE9D8) }
/* the caption carries a state label and then a sentence explaining what the
   state means, a sentence is body copy, so it is set in the body face */
.pcx-cell .cap{
  border-top:1px solid #2a2a2e; padding:8px 10px;
  font-family:var(--ui); font-size:10.5px; line-height:1.5; color:#8a8a92;
}
.pcx-cell .cap b{
  display:block; color:#e8e8ec; font-size:11px;
  letter-spacing:.1em; text-transform:uppercase; margin-bottom:3px;
}
.pcx-cell[data-missing] .top{ opacity:.3 }
.pcx-cell[data-missing] .cap b{ color:var(--pc-color-accent,#FFA800) }

/* ── the money-path components ───────────────────────────────────── */

.pcx-field[data-fstate="focus"]  { outline:5px solid var(--pc-color-accent,#FFA800); outline-offset:2px }
.pcx-field[data-fstate="invalid"]{ box-shadow:inset 0 0 0 2px var(--pc-color-danger,#EA2A46) }
.pcx-field[data-fstate="disabled"]{ filter:grayscale(1); opacity:.45; cursor:not-allowed }

/* the message that must ship with any invalid field, a colour is not a message.
   "Not enough balance, you have $18.40." is a sentence addressed to a person,
   so it is body face; mono here made the error read as a stack trace. */
.pcx-hint{
  display:block; font-family:var(--ui); font-size:11.5px; line-height:1.5;
  font-variant-numeric:tabular-nums;
  color:var(--pc-color-danger,#EA2A46); margin-top:-4px;
}

.pcx-code{ display:flex; gap:12px }
.pcx-code .cell{
  display:flex; align-items:center; justify-content:center;
  width:64px; height:78px;
  background:#fff;
  border:2px solid var(--pc-ink,#141414);          /* stroke/2, the step G6 added */
  box-shadow:4px 4px 0 #000;                        /* hard, zero blur, like every plate */
  font-family:var(--dsp); font-style:italic; font-weight:800; font-size:30px;
  font-variant-numeric:tabular-nums;   /* one digit per box, they must not shift */
  color:var(--pc-ink,#141414);
}
/* the ring sits on the NEXT EMPTY cell, a row of identical boxes cannot
   say where you are any other way */
.pcx-code .cell.caret{ border-color:var(--pc-color-accent,#FFA800); border-width:5px }
/* a wrong code is wrong as a whole; reddening one digit would lie about which */
.pcx-code[data-cstate="invalid"] .cell{ border-color:var(--pc-color-danger,#EA2A46) }
.pcx-code[data-cstate="invalid"] .cell.caret{ border-width:2px }

.pcx[data-claim="pending"]{ opacity:.6 }
.pcx[data-claim="claimed"]{ filter:grayscale(1); opacity:.45; pointer-events:none }

.pcx-body{
  font-family:var(--dsp); font-style:italic; font-weight:500;
  font-size:.43em; line-height:1.4; opacity:.8;
}

/* the real share card, taken from the product rather than redrawn */
.pcx-pnl{ display:block; width:770px; height:auto; flex:0 0 auto }

/* ── the specimen is the artwork ──────────────────────────────────
   Shown at its drawn size where it fits, scaled down where it does not.
   Nothing is overlaid on it: the drawing already says what it is. */
.pcx-art{
  display:block;
  width:var(--w); height:auto;
  max-width:100%;
  flex:0 0 auto;
}
.pcx-art[data-interactive]{ cursor:pointer; transition:transform .16s cubic-bezier(.16,1,.3,1) }
.pcx-art[data-interactive]:hover { transform:translate(calc(var(--press,3px) * -1), calc(var(--press,3px) * -1)) }
.pcx-art[data-interactive]:active{ transform:translate(var(--press,3px), var(--press,3px)) }
.pcx-art:focus-visible{ outline:3px solid var(--pc-color-accent,#FFA800); outline-offset:3px }
@media (prefers-reduced-motion:reduce){ .pcx-art[data-interactive]{ transition:none } }
/* a fit floor means content can exceed its box, crop rather than shrink to nothing */
.pcx-fit{ overflow:hidden }
/* a fit floor means content can exceed its box, crop rather than shrink to nothing */
.pcx-fit{ overflow:hidden }
