/* ============================================================================
   PLAYER CARD MODAL
   ============================================================================
   Design handoff: mockups/player-card-modal/design_handoff_player_card_modal/
   README.md + design/player-cards/screen.html. Replaces PlayerProfileModal
   (js/components/PlayerProfileModal.js — left in place, unreferenced).

   All measurements are pixel-for-pixel from the reference (README §1.4:
   "Where this document gives a pixel value, it was measured — honor it").
   Card paper surfaces bind to --color-action-bg (the `-bg` token) per §3.3 —
   NEVER a hardcoded cream — so the card stock themes with the app. The
   .pcm-face wood-grain gradient stops and the computed near-black ink value
   (see js/utils/nflTeamColors.js's inkOn()) are card-local per §7 (they
   imitate printed card stock, not app UI, and were never meant to theme) —
   intentionally NOT tokenized; see the codenote at .pcm-face below.

   Namespaced `.pcm-*` — the app already owns a generic `.card` family in
   base.css (`.card`, `.card-player`, `.card-scoreboard`, ...); this avoids
   any collision.
   ============================================================================ */

.pcm-scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim-black-modal);
  z-index: var(--z-modal-backdrop);
  animation: pcmFadeIn var(--animation-fade);
}

.pcm-sheet {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  pointer-events: none;
}

.pcm-sheet__inner {
  pointer-events: auto;
  position: relative;
  /* Default drawer bg (README §3.2): --color-action-darkest. No
     --drawer-bg/--drawer-edge tokens exist in this app's token set (that's
     a mockup-only theming knob for the design's Tweaks panel) — using the
     concrete default value directly. */
  background: var(--color-action-darkest);
  border-top: 4px solid var(--color-action-primary);
  border-radius: 12px 12px 0 0;
  /* Home-bar/notch clearance on iOS (auth-sheet.css:44 precedent) — env()
     falls back to 0 when unsupported, so the outer max() keeps the 16px
     design minimum either way. */
  padding: 10px 14px max(var(--space-base), env(safe-area-inset-bottom, var(--space-base)));
  max-height: 96vh;
  overflow-y: auto;
  animation: pcmSlideUp 0.28s ease-out;
}

@keyframes pcmFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes pcmSlideUp {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

.pcm-grab {
  width: 44px;
  height: 4px;
  border-radius: 99px;
  background: var(--scrim-white-medium);
  margin: 0 auto 10px;
}

/* Close button: visible circle is 32x32 (design spec) but the real hit
   target is 44x44 (CLAUDE.md touch-target minimum) — the button itself is
   the full 44x44 box, transparent, with the visual circle centered inside
   via a nested span so pixel fidelity and touch-target compliance both hold. */
.pcm-close {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 2;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  border: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.pcm-close__circle {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 2px solid var(--scrim-white-medium);
  background: rgba(0, 0, 0, 0.35);
  color: var(--color-white);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ---- the card ---- */

.pcm-cardwrap {
  margin: 0 auto;
  width: 340px;
  max-width: 100%;
}

/* Flip = two-phase scaleX squash, not a 3D rotation (commissioner ruling
   after three timing passes on the rotateY version: iOS Safari promotes the
   faces' overlay children to compositing layers that ignore inherited
   backface-visibility, so SOME part of the wrong face always leaked at SOME
   point in the rotation). The squash has no backfaces at all: the outgoing
   face scales X→0 (first 0.275s), then the incoming face scales 0→1 (second
   0.275s) — same 0.55s total as the old rotation, and it reads as the same
   card turning edge-on. The state rules live on the faces below; the card
   itself no longer transforms. */
.pcm-card {
  position: relative;
  width: 340px;
  max-width: 100%;
  height: 476px;
  cursor: pointer;
}

.pcm-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  border-radius: 6px;
  overflow: hidden;
  padding: 11px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  /* Card-local wood-grain stops (§7 — imitates printed card stock, kept
     local by design, never themed). */
  background:
    repeating-linear-gradient(87deg, rgba(0, 0, 0, 0.07) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(93deg, rgba(255, 255, 255, 0.06) 0 2px, transparent 2px 9px),
    repeating-linear-gradient(90deg, rgba(0, 0, 0, 0.05) 0 3px, transparent 3px 14px),
    linear-gradient(168deg, #c08a52 0%, #a06d38 40%, #7d4f26 100%);
}

.pcm-face::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 6px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35), inset 0 0 0 2px rgba(255, 255, 255, 0.12);
  pointer-events: none;
}

/* Belt-and-suspenders alongside the JS-set `inert` attribute (PlayerCardModal.js):
   the squashed-away face is visibility:hidden at rest, but block pointer
   events explicitly too so no tap lands mid-transition. Same in BOTH motion
   modes — the reduced-motion block below sets its own equivalent per state. */
.pcm-card:not(.pcm-card--flipped) .pcm-face--back {
  pointer-events: none;
}

.pcm-card--flipped .pcm-face--front {
  pointer-events: none;
}

/* Two-phase squash state rules. Each state declares the transition that
   governs ENTERING it: squashing runs immediately with ease-in (accelerating
   toward edge-on, like the far side of a rotation), expanding waits out the
   other face's 0.275s squash then ease-outs open. `visibility` rides the same
   transitions — hidden lands exactly when a squash completes, and an
   incoming face un-hides exactly when its expansion begins, so at every
   moment exactly one face is visible and mid-squash the card reads as
   turning edge-on rather than vanishing. */
.pcm-face--front {
  transform: scaleX(1);
  visibility: visible;
  transition: transform 0.275s ease-out 0.275s, visibility 0s 0.275s;
}

.pcm-card--flipped .pcm-face--front {
  transform: scaleX(0);
  visibility: hidden;
  transition: transform 0.275s ease-in, visibility 0s 0.275s;
}

.pcm-face--back {
  transform: scaleX(0);
  visibility: hidden;
  transition: transform 0.275s ease-in, visibility 0s 0.275s;
}

.pcm-card--flipped .pcm-face--back {
  transform: scaleX(1);
  /* Must re-declare: the bare .pcm-face--back hidden state above still
     matches while flipped and would otherwise keep winning for visibility. */
  visibility: visible;
  transition: transform 0.275s ease-out 0.275s, visibility 0s 0.275s;
}

/* ---- front ---- */

.pcm-frame {
  position: relative;
  height: 100%;
  background: var(--color-action-bg);
  border: 2px solid rgba(0, 0, 0, 0.4);
  border-radius: 2px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.pcm-photo {
  position: relative;
  flex: 1 1 auto;
  background: var(--color-action-bg);
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.pcm-photo::before {
  content: "";
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.035) 0 2px, transparent 2px 6px);
}

.pcm-headshot {
  position: relative;
  z-index: 2;
  width: 112%;
  max-width: none;
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.4));
  /* translateZ(0) forces its OWN compositing layer explicitly, so the
     backface-visibility set right below actually applies to that layer —
     mobile WebKit child-layer promotion, see the .pcm-face codenote above. */
  transform: translateY(4px) translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.pcm-headshot--hidden {
  display: none;
}

.pcm-corner {
  position: absolute;
  top: 0;
  right: 0;
  width: 100px;
  height: 100px;
  overflow: hidden;
  z-index: 2;
  /* Mobile WebKit child-layer promotion — see the .pcm-face codenote above. */
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.pcm-corner__flag {
  position: absolute;
  top: 19px;
  right: -30px;
  width: 132px;
  /* translateZ(0) forces its own compositing layer explicitly, so the
     backface-visibility below actually applies — mobile WebKit child-layer
     promotion, see the .pcm-face codenote above. */
  transform: rotate(45deg) translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  text-align: center;
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 1.5px;
  padding: 3px 0;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
  border-top: 1px solid rgba(255, 255, 255, 0.35);
  border-bottom: 1px solid rgba(0, 0, 0, 0.25);
  /* Team secondary fill + computed ink (§3.3/§5.1) — bound via
     --pcm-team-secondary/--pcm-ink on .pcm-card (PlayerCardModal.js ALWAYS
     sets both, from nflTeamColors.js's getTeamColors()/inkOn() — including
     its own safe FALLBACK_COLORS for a missing team). Deliberately no CSS
     fallback value here: inkOn() computes the WCAG-safe ink per fill; a
     static fallback (e.g. white) would reintroduce the white-on-orange
     2.76:1 failure for whichever fill it paired with. */
  background: var(--pcm-team-secondary);
  color: var(--pcm-ink);
}

.pcm-teamtab {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  width: 46px;
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.45));
  /* Mobile WebKit child-layer promotion — see the .pcm-face codenote above. */
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.pcm-teamtab img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.pcm-teamtab img.pcm-img--hidden,
.pcm-corner__flag img.pcm-img--hidden {
  display: none;
}

/* Action band — separated from the photo by the same 2px keyline used
   elsewhere on the frame (an earlier team-colored rule was rejected, §3.3B). */
.pcm-pillbar {
  flex: 0 0 auto;
  background: var(--color-action-bg);
  border-top: 2px solid rgba(0, 0, 0, 0.4);
  padding: 9px 9px var(--space-sm);
}

.pcm-pill {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  font-family: var(--font-display);
  font-size: 17px;
  letter-spacing: 3px;
  padding: 9px 0 var(--space-sm);
  border: 2px solid rgba(0, 0, 0, 0.42);
  border-radius: 3px;
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.28);
  cursor: pointer;
  transition: var(--transition-fast);
}

.pcm-pill:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: 0 0 0 rgba(0, 0, 0, 0.28);
}

.pcm-pill:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* --pcm-pill-ink is resolved at runtime (PlayerCardModal.js, resolveAAInk())
   against the pill's ACTUAL computed background — a fixed cream fails as low
   as 2.10:1 in the Chiefs/Cardinals gold-ramp themes where these "-dark"
   token fills are themselves light/mid-tone. Cream fallback covers the
   single frame before the post-mount effect runs. */
.pcm-pill--drop { background: var(--color-danger-dark); color: var(--pcm-pill-ink, var(--color-highlight-cream)); }
.pcm-pill--claim { background: var(--color-accent-aqua-dark); color: var(--pcm-pill-ink, var(--color-highlight-cream)); }
.pcm-pill--trade { background: var(--color-action-dark); color: var(--pcm-pill-ink, var(--color-highlight-cream)); }

/* Locked-player inline reason (rosterLocks) under a disabled DROP pill —
   same "locked — game in progress"/"…completed" string TeamDetail shows. */
.pcm-lock-reason {
  margin-top: var(--space-snug);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  text-align: center;
  color: var(--color-danger-dark);
}

.pcm-plate {
  flex: 0 0 auto;
  position: relative;
  background: var(--color-action-bg);
  border-top: 2px solid rgba(0, 0, 0, 0.16);
  padding: 9px 10px 10px;
}

.pcm-plate__name {
  font-family: var(--font-display);
  font-size: 36px;
  line-height: 0.92;
  letter-spacing: 1px;
  color: var(--color-structure-deepest);
  padding-right: 74px;
  margin: 0;
}

.pcm-trio {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-snug);
  margin-top: var(--space-sm);
  padding-right: 74px;
}

.pcm-trio div {
  border-top: 2px solid rgba(0, 0, 0, 0.22);
  padding-top: var(--space-xs);
}

.pcm-trio b {
  display: block;
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 800;
  color: var(--color-structure-deepest);
  line-height: 1;
}

.pcm-trio i {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 7.5px;
  font-weight: 800;
  letter-spacing: 1px;
  /* Structure-ramp ink, not --color-action-dark (design review: measured as
     low as 2.10:1 in the Chiefs/Cardinals/Niners gold-ramp themes, where
     action-dark is a mid-tone gold near-identical in luminance to the
     --color-action-bg paper it sits on). --color-structure-deep clears
     >=4.5:1 against --color-action-bg in all 8 themes (pinned test:
     nflTeamColors.test.js). */
  color: var(--color-structure-deep);
}

.pcm-seal {
  position: absolute;
  right: 10px;
  bottom: 12px;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  background: var(--color-action-bg);
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.28), inset 0 0 0 2px rgba(0, 0, 0, 0.12);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1;
  border-width: 3px;
  border-style: solid;
  /* Team secondary ring (§3.3) — see .pcm-corner__flag's codenote. */
  border-color: var(--pcm-team-secondary);
}

.pcm-seal b {
  font-family: var(--font-display);
  font-size: 32px;
  letter-spacing: 0.5px;
  /* Structure-ramp ink — see .pcm-trio i's codenote. */
  color: var(--color-structure-deep);
}

.pcm-seal em {
  font-style: normal;
  font-family: var(--font-mono);
  font-size: 7.5px;
  font-weight: 800;
  letter-spacing: 1.8px;
  color: var(--color-structure-deep);
  margin-top: 2px;
}

/* ---- front: drop-confirm overlay ----
   No action buttons live below the card (§3.2). The two-step cap/years
   preview replaces the front face's normal content IN PLACE — same 340x476
   footprint, wood frame still visible — rather than stacking extra buttons
   beneath the card. See PlayerCardModal.js's confirmingDrop branch. */
.pcm-confirm {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px var(--space-md);
  overflow-y: auto;
}

.pcm-confirm__title {
  font-family: var(--font-display);
  font-size: 20px;
  letter-spacing: 1.5px;
  color: var(--color-structure-deepest);
  text-align: center;
  margin: var(--space-xs) 0 0;
}

.pcm-confirm__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-sm);
  padding: var(--space-sm) 10px;
  background: var(--color-danger-bg);
  border-radius: var(--border-radius-sm);
  font-family: var(--font-mono);
}

.pcm-confirm__label {
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--color-structure-deep);
  margin-bottom: var(--space-xs);
}

.pcm-confirm__value {
  font-size: 13px;
  color: var(--color-structure-deepest);
}

.pcm-confirm__before {
  text-decoration: line-through;
  color: var(--color-danger-dark);
  margin-right: var(--space-xs);
}

.pcm-confirm__error {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--color-danger-dark);
}

.pcm-confirm__actions {
  margin-top: auto;
  display: flex;
  gap: var(--space-sm);
}

.pcm-confirm__btn {
  flex: 1;
  min-height: 44px;
  font-family: var(--font-display);
  font-size: 15px;
  letter-spacing: 2px;
  border-radius: 3px;
  border: 2px solid rgba(0, 0, 0, 0.42);
  cursor: pointer;
  transition: var(--transition-fast);
}

.pcm-confirm__btn--confirm {
  background: var(--color-danger-dark);
  color: var(--color-highlight-cream);
}

.pcm-confirm__btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.pcm-confirm__btn--cancel {
  background: transparent;
  color: var(--color-structure-deepest);
}

/* ---- back ---- */

.pcm-bframe {
  height: 100%;
  /* One step warmer/darker than the front per §3.4 — layered translucent
     wash over the same -bg token surface rather than a second hardcoded hex. */
  background:
    linear-gradient(0deg, rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.05)),
    var(--color-action-bg);
  border: 2px solid rgba(0, 0, 0, 0.4);
  border-radius: 2px;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  overflow: hidden;
}

.pcm-bhead {
  display: flex;
  justify-content: space-between;
  align-items: center;
  /* Team secondary color (§3.4) — bound via --pcm-team-secondary on .pcm-card,
     token fallback (never a raw hex) for a player whose NFL team is unknown. */
  border-bottom: 3px solid var(--pcm-team-secondary);
  padding-bottom: 5px;
}

.pcm-bhead b {
  font-family: var(--font-display);
  font-size: 23px;
  letter-spacing: 1.5px;
  color: var(--color-structure-deepest);
}

.pcm-bhead span {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 800;
  /* Structure-ramp ink — see .pcm-trio i's codenote. */
  color: var(--color-structure-deep);
  letter-spacing: 1px;
}

.pcm-btitle {
  font-family: var(--font-display);
  font-size: 13px;
  letter-spacing: 2px;
  /* Structure-ramp ink — see .pcm-trio i's codenote. */
  color: var(--color-structure-deep);
  margin: 0;
}

.pcm-contract {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
}

/* Row labels are <th scope="row"> (a11y: pairs each value cell with its
   label for screen readers) — reset the browser's default bold-center th
   styling to match the plain <td> value cells' look. */
.pcm-contract td,
.pcm-contract th {
  font-size: 11px;
  font-weight: 700;
  color: var(--color-structure-deepest);
  padding: 3px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  text-align: left;
}

.pcm-contract th {
  font-weight: 800;
}

.pcm-contract td:last-child {
  text-align: right;
}

.pcm-statshead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
}

.pcm-segs {
  display: flex;
  border: 2px solid rgba(0, 0, 0, 0.35);
  border-radius: 2px;
  overflow: hidden;
  position: relative;
}

/* Each visible seg pill is small (design spec: padding 3px 9px, 11px font) —
   the invisible ::before expands the real tap target to >=44px without
   inflating the compact stats-header row the design locks in. */
.pcm-seg {
  position: relative;
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 1.4px;
  padding: 3px 9px;
  border: 0;
  background: transparent;
  color: var(--color-structure-deep);
  cursor: pointer;
  transition: var(--transition-fast);
}

/* Asymmetric inset toward the shared divider (4px, vs 16px on the outer
   edges) so the two segments' expanded 44px tap zones don't overlap and
   fight over which one a near-divider tap resolves to. */
.pcm-seg::before {
  content: "";
  position: absolute;
  inset: -16px;
}

.pcm-seg:first-child::before {
  inset: -16px -4px -16px -16px;
}

.pcm-seg:last-child::before {
  inset: -16px -16px -16px -4px;
}

/* .pcm-statshead can hold two .pcm-segs groups side by side (STATS|PROJECTIONS
   next to SEASON|CAREER, when in STATS mode). Trim the two facing outer edges
   from -16px to -4px so their expanded tap corridors can't bridge a compressed
   row gap on narrow phones and steal a tap meant for the neighboring group. */
.pcm-statshead > .pcm-segs:first-child:not(:last-child) > .pcm-seg:last-child::before {
  inset: -16px -4px -16px -4px;
}

.pcm-statshead > .pcm-segs:last-child:not(:first-child) > .pcm-seg:first-child::before {
  inset: -16px -4px -16px -4px;
}

.pcm-seg + .pcm-seg {
  border-left: 2px solid rgba(0, 0, 0, 0.35);
}

.pcm-seg.is-on {
  /* Team secondary fill + computed ink (§4.4) — see .pcm-corner__flag's codenote. */
  background: var(--pcm-team-secondary);
  color: var(--pcm-ink);
}

.pcm-sbwrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
}

.pcm-statsbox {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.pcm-statsbox::-webkit-scrollbar {
  width: 0;
  height: 0;
  display: none;
}

.pcm-sbar {
  position: absolute;
  background: rgba(0, 0, 0, 0.32);
  border-radius: 99px;
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
  z-index: 4;
  /* Vestigial from the rotateY-flip era (mobile-WebKit child-layer
     promotion guard); harmless no-op under the 2D squash. Kept, like the
     other backface guards in this file, pending a cleanup pass if the
     squash mechanism sticks. */
  transform: translateZ(0);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.pcm-sbwrap.is-scrolling .pcm-sbar {
  opacity: 1;
}

.pcm-sbar--v { right: 0; width: 4px; }
.pcm-sbar--h { bottom: 0; height: 4px; }

table.pcm-stats {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--font-mono);
  min-width: max-content;
}

table.pcm-stats th {
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.6px;
  color: var(--color-structure-deep);
  text-align: right;
  padding: 3px;
  padding-right: 9px;
  border-bottom: 2px solid rgba(0, 0, 0, 0.3);
  white-space: nowrap;
  position: sticky;
  top: 0;
  background: var(--color-action-bg);
  z-index: 2;
  /* Sticky + z-index promotes these to their own compositing layers on
     mobile WebKit, which don't inherit the back face's backface-visibility
     — declare it directly (no translateZ: transforms on table cells shift
     sticky rendering; sticky promotion already gives them a layer). */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

table.pcm-stats td {
  font-size: 11px;
  font-weight: 700;
  color: var(--color-structure-deepest);
  text-align: right;
  padding: 3px;
  padding-right: 9px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  white-space: nowrap;
}

table.pcm-stats th:first-child,
table.pcm-stats td:first-child {
  text-align: left;
  font-weight: 800;
  position: sticky;
  left: 0;
  background: var(--color-action-bg);
  box-shadow: 1px 0 0 rgba(0, 0, 0, 0.18);
  z-index: 1;
  padding-right: 10px;
  /* Same promoted-layer guard as the sticky column headers above. */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

table.pcm-stats thead th:first-child {
  z-index: 3;
}

table.pcm-stats th:last-child,
table.pcm-stats td:last-child {
  padding-right: 2px;
}

/* FPTS column emphasis — 3rd column on the SEASON table, LAST column on
   CAREER (§6.3/§6.4). PROJECTIONS shares the SEASON table's exact column
   layout (WK/OPP/FPTS/...), so the same 3rd-column rule applies. */
table.pcm-stats--season tbody td:nth-child(3),
table.pcm-stats--season thead th:nth-child(3),
table.pcm-stats--projections tbody td:nth-child(3),
table.pcm-stats--projections thead th:nth-child(3) {
  font-weight: 800;
  /* Structure-ramp ink — see .pcm-trio i's codenote. */
  color: var(--color-structure-deep);
}

table.pcm-stats--career tbody td:last-child,
table.pcm-stats--career thead th:last-child {
  font-weight: 800;
  /* Structure-ramp ink — see .pcm-trio i's codenote. */
  color: var(--color-structure-deep);
}

/* Current-season highlight. The career table sorts current-season-first
   (commissioner override, 2026-08-21), so this row now sits directly under
   the sticky header — the heavy divider moved from its top edge (mockup's
   bottom-row placement) to its bottom edge to separate it from the history
   below without doubling the header's own border. */
table.pcm-stats tr.pcm-tot td {
  border-bottom: 2px solid rgba(0, 0, 0, 0.3);
  background: rgba(240, 124, 15, 0.14);
}

.pcm-bfoot {
  margin-top: auto;
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 800;
  letter-spacing: 1px;
  /* Structure-ramp ink — see .pcm-trio i's codenote. */
  color: var(--color-structure-deep);
  border-top: 2px solid rgba(0, 0, 0, 0.25);
  padding-top: 5px;
}

.pcm-fliphint {
  text-align: center;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 1.5px;
  color: var(--color-structure-light);
  margin: 10px 0 var(--space-md);
}

.pcm-loading,
.pcm-empty {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  color: var(--color-structure-deep);
  text-align: center;
  padding: 10px;
}

/* ---- reduced motion: cross-fade + subtle horizontal scale substitute
   for the Y-axis flip (§4.3), same 0.55s-in-spirit duration ---- */
@media (prefers-reduced-motion: reduce) {
  /* Replace the sequential squash with a simultaneous cross-fade + a 4%
     scale nudge. The base state rules declare per-state transitions at up
     to (0,2,0), so every state selector is re-declared here at its full
     form — later in source, each wins its tie and unifies onto one 0.35s
     cadence. A state's transition governs ENTERING it, so only the two
     HIDDEN states carry the delayed `visibility` entry (fade fully, THEN
     hide — an instant hide would hard-cut the cross-fade); the visible
     states omit visibility from their transition, so an incoming face
     un-hides at 0s and is present for its whole fade-in. */
  .pcm-face--front,
  .pcm-card--flipped .pcm-face--back {
    opacity: 1;
    transform: scaleX(1);
    visibility: visible;
    transition: opacity 0.35s ease, transform 0.35s ease;
  }

  .pcm-face--back,
  .pcm-card--flipped .pcm-face--front {
    opacity: 0;
    transform: scaleX(0.96);
    pointer-events: none;
    visibility: hidden;
    transition: opacity 0.35s ease, transform 0.35s ease, visibility 0s 0.35s;
  }

  .pcm-card--flipped .pcm-face--back {
    pointer-events: auto;
  }
}
