/* ============================================================
   CARD FRAME STYLES — 10 distinct treatments
   Shared layout + per-style chrome via .style-{key} classes
   ============================================================ */

/* ---------- Base layout (shared across all styles) ---------- */

.card {
  position: relative;
  box-sizing: border-box;
  color: var(--card-fg, #111);
  background: var(--card-bg, #fff);
  border-radius: var(--card-radius, 0);
  font-family: var(--card-font, "Inter", system-ui, sans-serif);
  isolation: isolate;
  user-select: none;
  --border-w: 14px;
  --border-color: #111;
  --socket-bg: var(--card-bg);
  --socket-mark: #111;
  --socket-size: 26px;
  /* Body-text sizing (plan/card-face-refinements §2): the runtime fitter sizes
     the body between floor and max to fill its box — short bodies GROW toward
     --card-body-max, long bodies SHRINK toward --card-body-floor (never below,
     for legibility). --card-body-size is the no-JS static fallback. */
  --card-body-size: 14px;
  --card-body-floor: 10px;
  --card-body-max: 22px;
}

.frame-chrome {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.frame-border {
  position: absolute;
  inset: 0;
  border: var(--border-w) solid var(--border-color);
  border-radius: inherit;
  box-sizing: border-box;
  z-index: 3;
  pointer-events: none;
}

.card-inner {
  position: absolute;
  inset: var(--border-w);
  display: flex;
  flex-direction: column;
  z-index: 1;
  border-radius: calc(var(--card-radius, 0px) - var(--border-w));
  overflow: hidden;
}

.card-art-wrap {
  position: relative;
  flex: 0 0 38%;
  overflow: hidden;
  background: var(--art-bg, #eee);
}

/* Play-mode stamps (AUTO / FREE / FORCED) — small tilted rubber-stamps in the
   bottom-right of the art window, clipped to the picture frame by the wrap's
   overflow:hidden. Each a slightly different colour + tilt so they read apart. */
.play-badges {
  position: absolute;
  bottom: 5px;
  right: 5px;
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-end;
  gap: 3px;
  z-index: 4;
  pointer-events: none;
}
.play-badge {
  font-family: var(--mono, "Courier New", monospace);
  font-weight: 800;
  font-size: 7.5px;
  line-height: 1;
  letter-spacing: 1.3px;
  text-transform: uppercase;
  padding: 1.5px 4px;
  color: #ccc;
  border: 1.4px solid currentColor;
  border-radius: 2px;
  background: rgba(8, 6, 10, 0.42);
  box-shadow: inset 0 0 0 0.5px currentColor; /* double-edge → stamp feel */
  opacity: 0.9;
}
.pb-auto  { color: #e6bd55; transform: rotate(-9deg); }  /* amber/gold */
.pb-free  { color: #69cc8e; transform: rotate(-6deg); }  /* green */
.pb-force { color: #e3664e; transform: rotate(-11deg); } /* red */

.art-placeholder {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Card illustration (card def `art`): fills the art window, replacing the
   placeholder. Added in proto 2026-06-14; mirror into assets/card-assets/ on
   the vendored-CSS reconciliation pass. */
.card-art-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Mirror the illustration horizontally (card `artFlipX`). For a DIRECTIONAL mirror
   pair — Shove Right / Shove Left — where one piece of art serves both and
   re-hosting a flipped copy would mean a new remote asset plus a deploy to carry
   it. The printed direction glyph derives from pushDirection and already points the
   right way on its own, so this is only about the illustration. */
.card-art-img.flip-x { transform: scaleX(-1); }

.art-stripes {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.85;
}

.art-label {
  position: relative;
  font-family: "JetBrains Mono", "Space Mono", monospace;
  font-size: 8px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  background: rgba(0, 0, 0, 0.6);
  color: #fff;
  padding: 3px 6px;
  border-radius: 2px;
}

.gesture-glyph {
  position: absolute;
  top: 6px;
  left: 6px;
  width: 22px;
  height: 22px;
  color: var(--gesture-color, var(--border-color));
  background: var(--gesture-bg, rgba(255,255,255,0.85));
  border: 1.5px solid var(--gesture-stroke, var(--border-color));
  padding: 2px;
  z-index: 2;
  box-sizing: border-box;
  border-radius: var(--gesture-radius, 0);
}

.card-text {
  flex: 1 1 auto;
  padding: 9px 11px 7px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-height: 0;
  background: var(--text-bg, transparent);
}

.type-line {
  display: flex;
  align-items: baseline;
  gap: 5px;
  font-family: var(--type-font, var(--card-font));
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--rule-color, currentColor);
  padding-bottom: 4px;
  color: var(--type-color, var(--card-fg));
}

.type-icon {
  font-size: 12px;
  line-height: 1;
}

/* The body BOX (fixed by the flex layout); the fit element inside it is sized by
   card-face.ts fitCardText to fill the box. Short bodies are centred so the
   leftover space reads as intentional rather than stranded at the top. */
.card-body {
  font-family: var(--body-font, var(--card-font));
  color: var(--body-color, var(--card-fg));
  flex: 1 1 auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* An over-budget body (still clips at the floor) top-aligns instead, so the text
   reads from its start rather than losing the opening to symmetric clipping. */
.card-body.body-over-budget { justify-content: flex-start; }
.card-body-fit {
  font-size: var(--card-body-size, 14px); /* JS fits between floor and max */
  line-height: 1.35;
}

.card-name-banner {
  flex: 0 0 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--banner-bg, #111);
  color: var(--banner-fg, #fff);
  font-family: var(--name-font, var(--card-font));
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 18px;
  position: relative;
  text-align: center;
}

.card-name {
  position: relative;
  z-index: 1;
}

/* ---------- Frame wrap (holds chrome + border together for socket masking) ---------- */
.frame-wrap {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
}

/* On L2 cards, mask 8 circular holes out of the entire frame stack so the
   border physically breaks at each keypad position — the sockets become
   genuine notches carved into the frame, not stickers placed on top. */
.layer-L2 .frame-wrap {
  --socket-cut-r: 12.5px;
  --socket-cut-blend: 13.5px;
  -webkit-mask-image:
    radial-gradient(circle 14px at 0 0,       transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 50% 0,     transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 100% 0,    transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 0 50%,     transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 100% 50%,  transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 0 100%,    transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 50% 100%,  transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 100% 100%, transparent var(--socket-cut-r), #000 var(--socket-cut-blend));
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(circle 14px at 0 0,       transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 50% 0,     transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 100% 0,    transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 0 50%,     transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 100% 50%,  transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 0 100%,    transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 50% 100%,  transparent var(--socket-cut-r), #000 var(--socket-cut-blend)),
    radial-gradient(circle 14px at 100% 100%, transparent var(--socket-cut-r), #000 var(--socket-cut-blend));
  mask-composite: intersect;
}

/* ---------- Sockets (shared) ---------- */
.socket-ring { position: absolute; inset: 0; z-index: 4; pointer-events: none; }

.socket {
  position: absolute;
  width: 25px;
  height: 25px;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* The well sits in the masked-out hole and supplies depth:
   inset shadow at top reads as a recess; subtle floor highlight at bottom.
   No outer border — the frame already curves around it via the mask. */
.socket-well {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--well-bg, rgba(0, 0, 0, 0.12));
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow:
    inset 0 2.5px 3px rgba(0, 0, 0, 0.55),
    inset 0 -1px 1px rgba(255, 255, 255, 0.18),
    var(--socket-shadow, none);
}

/* Dark-themed styles invert the depth lighting */
.style-cyber .socket-well,
.style-deco .socket-well,
.style-stained .socket-well,
.style-holo .socket-well,
.style-illuminated .socket-well {
  --well-bg: rgba(0, 0, 0, 0.55);
  box-shadow:
    inset 0 2.5px 4px rgba(0, 0, 0, 0.85),
    inset 0 -1px 1px rgba(255, 255, 255, 0.08),
    var(--socket-shadow, none);
}

.socket-circle {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--socket-mark);
  box-shadow: var(--mark-glow, none);
  position: relative;
  z-index: 1;
}

.socket-triangle {
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 11px solid var(--socket-mark);
  filter: var(--mark-filter, none);
  position: relative;
  z-index: 1;
}

/* Empty socket — keep faint dot so 8-grid pattern is legible */
.socket:not(:has(.socket-circle, .socket-triangle)) .socket-well::after {
  content: "";
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--border-color);
  opacity: 0.5;
}

/* ============================================================
   01 · FLAT — modern sport / vibrant flat
   ============================================================ */

.style-flat {
  --card-font: "Inter", system-ui, sans-serif;
  --card-bg: #f8f5ec;
  --card-fg: #14171e;
  --border-w: 16px;
  --border-color: #14171e;
  --card-radius: 14px;
  --art-bg: #ffd13a;
  --art-stripe-a: #ffd13a;
  --art-stripe-b: #ffba07;
  --rule-color: #14171e;
  --gesture-bg: #fff;
  --gesture-stroke: #14171e;
  --gesture-radius: 4px;
}
.style-flat.pol-enemy   { --border-color: #ee2746; --socket-mark: #ee2746; }
.style-flat.pol-friendly { --border-color: #1e54f5; --socket-mark: #1e54f5; }
.style-flat.pol-neutral  { --border-color: #14171e; --socket-mark: #14171e; }

.style-flat .frame-chrome::before {
  content: "";
  position: absolute;
  inset: 6px;
  border: 2px solid var(--border-color);
  border-radius: 10px;
  opacity: 0.18;
}
.style-flat .card-name-banner {
  background: var(--border-color);
  color: #fff8e6;
  font-family: "Inter", sans-serif;
  font-weight: 900;
  font-size: 20px;
  letter-spacing: 0.12em;
}
.style-flat .card-name-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  border-top: 3px solid #fff8e6;
  opacity: 0.4;
}

/* ============================================================
   02 · CYBER — cyberpunk neon
   ============================================================ */

.style-cyber {
  --card-font: "Space Grotesk", "Inter", sans-serif;
  --type-font: "Major Mono Display", "Space Mono", monospace;
  --name-font: "Major Mono Display", "Space Mono", monospace;
  --body-font: "Space Mono", monospace;
  --card-bg: #08091a;
  --card-fg: #d4faff;
  --border-w: 12px;
  --border-color: #0d1330;
  --card-radius: 4px;
  --art-bg: #050617;
  --art-stripe-a: #0a0e25;
  --art-stripe-b: #161c44;
  --rule-color: #2effe7;
  --type-color: #2effe7;
  --body-color: #a4c7d8;
  --gesture-bg: #0d1330;
  --gesture-stroke: #2effe7;
  --gesture-color: #2effe7;
  --socket-shadow: 0 0 6px var(--socket-mark);
  --mark-glow: 0 0 8px var(--socket-mark), 0 0 14px var(--socket-mark);
  --mark-filter: drop-shadow(0 0 4px var(--socket-mark));
}
.style-cyber.pol-enemy    { --socket-mark: #ff2bd6; }
.style-cyber.pol-friendly { --socket-mark: #2effe7; }
.style-cyber.pol-neutral  { --socket-mark: #ffd83d; }

.style-cyber .frame-chrome {
  background:
    linear-gradient(180deg, transparent 0%, rgba(46,255,231,0.04) 50%, transparent 100%);
}
.style-cyber .frame-chrome::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    0deg,
    transparent 0px,
    transparent 2px,
    rgba(46,255,231,0.06) 2px,
    rgba(46,255,231,0.06) 3px
  );
  pointer-events: none;
}
.style-cyber .frame-border {
  border-color: var(--border-color);
  box-shadow:
    inset 0 0 0 2px var(--socket-mark, #2effe7),
    0 0 12px rgba(46,255,231,0.3);
}
.style-cyber .card-art-wrap {
  border-bottom: 1px solid #2effe744;
}
.style-cyber .card-name-banner {
  background: linear-gradient(180deg, #0d1330 0%, #050617 100%);
  color: var(--socket-mark);
  text-shadow: 0 0 6px var(--socket-mark), 0 0 14px var(--socket-mark);
  font-size: 18px;
  letter-spacing: 0.22em;
  border-top: 1px solid var(--socket-mark);
}

/* ============================================================
   03 · RISO — risograph print
   ============================================================ */

.style-riso {
  --card-font: "Work Sans", "Inter", sans-serif;
  --name-font: "Bungee", "Work Sans", sans-serif;
  --card-bg: #f5ecd6;
  --card-fg: #16221d;
  --border-w: 14px;
  --border-color: #e64b3e;
  --card-radius: 3px;
  --art-bg: #f5ecd6;
  --art-stripe-a: #e64b3e;
  --art-stripe-b: #f5ecd6;
  --rule-color: #16221d;
  --gesture-bg: #f5ecd6;
  --gesture-stroke: #16221d;
}
.style-riso.pol-enemy    { --socket-mark: #e64b3e; --border-color: #e64b3e; }
.style-riso.pol-friendly { --socket-mark: #1a5fb4; --border-color: #1a5fb4; }
.style-riso.pol-neutral  { --socket-mark: #16221d; --border-color: #16221d; }

.style-riso .frame-chrome::before {
  /* Halftone dots scattered as paper grain */
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 1px 1px, rgba(22,34,29,0.18) 1px, transparent 1.5px);
  background-size: 5px 5px;
  mix-blend-mode: multiply;
}
.style-riso .frame-chrome::after {
  /* Offset duotone misregistration on border */
  content: "";
  position: absolute;
  inset: 2px;
  border: var(--border-w) solid var(--border-color);
  border-radius: inherit;
  opacity: 0.5;
  mix-blend-mode: multiply;
  filter: hue-rotate(180deg) saturate(0.9);
}
.style-riso .art-placeholder {
  position: relative;
}
.style-riso .art-placeholder::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 2px 2px, var(--border-color) 1.2px, transparent 1.6px);
  background-size: 7px 7px;
  opacity: 0.5;
  mix-blend-mode: multiply;
}
.style-riso .card-name-banner {
  background: var(--border-color);
  color: #f5ecd6;
  font-size: 22px;
  letter-spacing: 0.04em;
  font-weight: 400;
  position: relative;
}
.style-riso .card-name-banner::after {
  /* Misregistration shadow */
  content: attr(data-name);
}
.style-riso .card-name {
  position: relative;
  text-shadow: 2px 1px 0 #1a5fb4cc;
}

/* ============================================================
   04 · DECO — art deco
   ============================================================ */

.style-deco {
  --card-font: "Cinzel", "Cormorant Garamond", serif;
  --body-font: "Cormorant Garamond", serif;
  --name-font: "Cinzel", serif;
  --type-font: "Cinzel", serif;
  --card-bg: #0e1418;
  --card-fg: #e8d49a;
  --border-w: 18px;
  --border-color: #0e1418;
  --card-radius: 2px;
  --art-bg: #15212a;
  --art-stripe-a: #15212a;
  --art-stripe-b: #1a2e3a;
  --rule-color: #d4a93b;
  --type-color: #d4a93b;
  --body-color: #e8d49a;
  --gesture-bg: #0e1418;
  --gesture-stroke: #d4a93b;
  --gesture-color: #d4a93b;
}
.style-deco.pol-enemy    { --socket-mark: #d4a93b; --type-color: #e85d5d; }
.style-deco.pol-friendly { --socket-mark: #d4a93b; --type-color: #4ec6c0; }
.style-deco.pol-neutral  { --socket-mark: #d4a93b; }

.style-deco .frame-chrome {
  background:
    linear-gradient(135deg, #1a2530 0%, #0e1418 50%, #1a2530 100%);
}
.style-deco .frame-border {
  border-color: #d4a93b;
  border-width: 3px;
  box-shadow:
    inset 0 0 0 12px #0e1418,
    inset 0 0 0 14px #d4a93b,
    inset 0 0 0 18px #0e1418;
}
.style-deco .frame-chrome::before {
  /* chevron motif in corners */
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(45deg, #d4a93b 0%, #d4a93b 8px, transparent 8px) top left / 40px 40px no-repeat,
    linear-gradient(-45deg, #d4a93b 0%, #d4a93b 8px, transparent 8px) top right / 40px 40px no-repeat,
    linear-gradient(135deg, #d4a93b 0%, #d4a93b 8px, transparent 8px) bottom left / 40px 40px no-repeat,
    linear-gradient(-135deg, #d4a93b 0%, #d4a93b 8px, transparent 8px) bottom right / 40px 40px no-repeat;
  opacity: 0.35;
}
.style-deco .card-name-banner {
  background: #d4a93b;
  color: #0e1418;
  font-size: 19px;
  letter-spacing: 0.28em;
  font-weight: 700;
  border-top: 2px solid #0e1418;
}

/* ============================================================
   05 · BRUTALIST
   ============================================================ */

.style-brutalist {
  --card-font: "IBM Plex Mono", "Space Mono", monospace;
  --card-bg: #e8e3d8;
  --card-fg: #0a0a0a;
  --border-w: 22px;
  --border-color: #0a0a0a;
  --card-radius: 0;
  --art-bg: #d2cdc0;
  --art-stripe-a: #d2cdc0;
  --art-stripe-b: #b8b3a5;
  --rule-color: #0a0a0a;
  --gesture-bg: #ffffff;
  --gesture-stroke: #0a0a0a;
}
.style-brutalist.pol-enemy    { --socket-mark: #d92020; }
.style-brutalist.pol-friendly { --socket-mark: #1a5fb4; }
.style-brutalist.pol-neutral  { --socket-mark: #0a0a0a; }

.style-brutalist .frame-chrome::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 4px;
  width: calc(100% - 4px);
  height: calc(100% - 4px);
  background: #0a0a0a;
  z-index: -1;
}
.style-brutalist .frame-border {
  border-width: 8px;
}
.style-brutalist .card-inner {
  inset: 8px;
  border: 14px solid var(--card-bg);
  box-sizing: border-box;
}
.style-brutalist .card-art-wrap {
  outline: 1px dashed #0a0a0a;
  outline-offset: -2px;
}
.style-brutalist .type-line {
  font-family: "IBM Plex Mono", monospace;
  letter-spacing: 0;
  text-transform: uppercase;
}
.style-brutalist .card-name-banner {
  background: #0a0a0a;
  color: #e8e3d8;
  font-family: "IBM Plex Mono", monospace;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.16em;
}
.style-brutalist .card-name-banner::before {
  content: "//";
  position: absolute;
  left: 10px;
  color: var(--socket-mark);
}
.style-brutalist .card-name-banner::after {
  content: "//";
  position: absolute;
  right: 10px;
  color: var(--socket-mark);
}

/* ============================================================
   06 · STAINED GLASS
   ============================================================ */

.style-stained {
  --card-font: "Cormorant Garamond", "Playfair Display", serif;
  --body-font: "Cormorant Garamond", serif;
  --name-font: "Cinzel", serif;
  --type-font: "Cinzel", serif;
  --card-bg: #1a1228;
  --card-fg: #f0e3b8;
  --border-w: 18px;
  --border-color: #0a0610;
  --card-radius: 4px;
  --art-bg: #2d1a4a;
  --art-stripe-a: #5a2e6e;
  --art-stripe-b: #2d1a4a;
  --rule-color: #d4a93b;
  --type-color: #f5d77b;
  --gesture-bg: #0a0610;
  --gesture-stroke: #d4a93b;
  --gesture-color: #d4a93b;
}
.style-stained.pol-enemy    { --socket-mark: #e63a4e; --art-bg: #5e1525; --art-stripe-a: #b32340; --art-stripe-b: #5e1525; }
.style-stained.pol-friendly { --socket-mark: #4ea8e6; --art-bg: #122f5e; --art-stripe-a: #2a5cb3; --art-stripe-b: #122f5e; }
.style-stained.pol-neutral  { --socket-mark: #d4a93b; }

.style-stained .frame-chrome {
  background:
    radial-gradient(ellipse at top, #4a2e6e 0%, #1a1228 70%);
}
.style-stained .frame-chrome::before {
  /* lead lines crosshatch */
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(45deg, transparent 48%, rgba(0,0,0,0.4) 49%, rgba(0,0,0,0.4) 51%, transparent 52%) 0 0 / 24px 24px,
    linear-gradient(-45deg, transparent 48%, rgba(0,0,0,0.4) 49%, rgba(0,0,0,0.4) 51%, transparent 52%) 0 0 / 24px 24px;
  opacity: 0.5;
}
.style-stained .frame-border {
  border-color: #0a0610;
  box-shadow:
    inset 0 0 0 2px #d4a93b,
    inset 0 0 12px rgba(0,0,0,0.6);
}
.style-stained .card-name-banner {
  background: linear-gradient(180deg, #0a0610 0%, #1a1228 100%);
  color: #f5d77b;
  font-size: 18px;
  letter-spacing: 0.18em;
  border-top: 2px solid #d4a93b;
  text-shadow: 0 0 8px rgba(245,215,123,0.6);
}

/* ============================================================
   07 · POP ART
   ============================================================ */

.style-popart {
  --card-font: "Inter", sans-serif;
  --name-font: "Bowlby One", "Bungee", sans-serif;
  --type-font: "Bowlby One", "Inter", sans-serif;
  --card-bg: #fff7d1;
  --card-fg: #0a0a0a;
  --border-w: 18px;
  --border-color: #0a0a0a;
  --card-radius: 0;
  --art-bg: #ff3aa3;
  --art-stripe-a: #ff3aa3;
  --art-stripe-b: #ffd700;
  --rule-color: #0a0a0a;
  --gesture-bg: #ffd700;
  --gesture-stroke: #0a0a0a;
}
.style-popart.pol-enemy    { --socket-mark: #e10025; }
.style-popart.pol-friendly { --socket-mark: #1a5fff; }
.style-popart.pol-neutral  { --socket-mark: #0a0a0a; }

.style-popart .frame-chrome {
  background:
    radial-gradient(circle, transparent 1.5px, rgba(0,0,0,0.12) 1.5px) 0 0 / 6px 6px;
}
.style-popart .frame-border {
  border-width: 6px;
  box-shadow:
    inset 0 0 0 6px var(--socket-mark),
    inset 0 0 0 12px #0a0a0a;
}
.style-popart .card-art-wrap {
  background:
    radial-gradient(circle at center, #ffd700 0%, #ffd700 30%, #ff3aa3 30%, #ff3aa3 35%, #ffd700 35%, #ffd700 45%, #ff3aa3 45%);
  position: relative;
}
.style-popart .card-art-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle, #0a0a0a 1px, transparent 1.4px) 0 0 / 4px 4px;
  opacity: 0.35;
}
.style-popart .art-stripes { display: none; }
.style-popart .card-name-banner {
  background: var(--socket-mark);
  color: #fff7d1;
  font-size: 19px;
  letter-spacing: 0.02em;
  border-top: 4px solid #0a0a0a;
  -webkit-text-stroke: 1.2px #0a0a0a;
}

/* ============================================================
   08 · CURRENCY — engraved banknote
   ============================================================ */

.style-currency {
  --card-font: "Playfair Display", "Cormorant Garamond", serif;
  --body-font: "Cormorant Garamond", serif;
  --name-font: "Cinzel", serif;
  --type-font: "Cinzel", serif;
  --card-bg: #f0e2c6;
  --card-fg: #1f1a14;
  --border-w: 14px;
  --border-color: #4a2c1a;
  --card-radius: 2px;
  --art-bg: #e6d4ad;
  --art-stripe-a: #e6d4ad;
  --art-stripe-b: #d4bc8a;
  --rule-color: #4a2c1a;
  --type-color: #4a2c1a;
  --gesture-bg: #f0e2c6;
  --gesture-stroke: #4a2c1a;
}
.style-currency.pol-enemy    { --socket-mark: #8b1c1c; --border-color: #6b1c1c; }
.style-currency.pol-friendly { --socket-mark: #1c3d6b; --border-color: #1c3d6b; }
.style-currency.pol-neutral  { --socket-mark: #4a2c1a; }

.style-currency .frame-chrome {
  background:
    /* Guilloché-like fine pattern */
    repeating-radial-gradient(circle at 30% 40%, transparent 0, rgba(74,44,26,0.08) 1px, transparent 2px, transparent 8px),
    repeating-radial-gradient(circle at 70% 60%, transparent 0, rgba(74,44,26,0.08) 1px, transparent 2px, transparent 10px),
    repeating-linear-gradient(45deg, rgba(74,44,26,0.05) 0, rgba(74,44,26,0.05) 1px, transparent 1px, transparent 4px);
}
.style-currency .frame-border {
  border-width: 2px;
  box-shadow:
    inset 0 0 0 4px var(--card-bg),
    inset 0 0 0 6px var(--border-color),
    inset 0 0 0 8px var(--card-bg),
    inset 0 0 0 9px var(--border-color);
}
.style-currency .card-art-wrap {
  border: 1px solid var(--border-color);
  margin: 4px 4px 0;
  position: relative;
}
.style-currency .card-art-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(45deg, rgba(74,44,26,0.18) 0 1px, transparent 1px 3px);
}
.style-currency .card-name-banner {
  background: transparent;
  color: var(--border-color);
  font-size: 19px;
  letter-spacing: 0.14em;
  border-top: 1px solid var(--border-color);
  border-bottom: 3px double var(--border-color);
  margin: 2px 4px;
}

/* ------------------------------------------------------------
   Card Face Model v3 — icon-algebra corner (card-icon system,
   2026-06-20). ONE generic glyph treatment across L1/L2/L3
   (light fill + dark contour + glow), a split trigger pill, three
   distinct magnitude marks (pips / lifetime number / delay clock),
   and circle-less scope cameos with an intent glow. Shared across
   the hotseat hand, card-preview, and card-author (all load this
   file). Confirmed against card-icon-pill-mockup.html.
   See wiki/visual-design-cards.md § Card Face Model v2.
   ------------------------------------------------------------ */

/* Generic layer-agnostic glyph: the icons load as <img> of currentColor svgs
   (→ black); brightness(0) invert(1) lifts them to a light parchment fill, the
   warm tint matches the note ink, the dark drop-shadows give the contour that
   reads on light stock, and the glow carries it on dark stock — ONE treatment on
   all three layers (retires the per-layer recolor + the white-on-L3 split). */
.style-currency .fx-glyph {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter:
    brightness(0) invert(1) sepia(0.35) saturate(0.6) brightness(1.04)
    drop-shadow(0 0 1.1px #15110b) drop-shadow(0 0 1.1px #15110b)
    drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 7px rgba(0, 0, 0, 0.4));
}

/* Effect corner — just the effect glyph (pill or bare icon), top-RIGHT. The
   magnitude counters live in the top-left bar now (2026-06-21). */
.style-currency .fx-corner {
  position: absolute;
  top: 8px;
  right: 10px;
  z-index: 3;
}
/* Magnitude counter bar — a left-aligned row across the top-LEFT (where the
   scope cameo / seal used to sit), so counters no longer jam behind the effect
   glyph. One treatment on all three layers. */
.style-currency .mag-bar {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 3;
  display: flex;
  flex-direction: row;
  gap: 4px;
  align-items: center;
}

/* Bare icon — default application / direct cast (no capsule, never a circle).
   Sits above the magnitude badges; heavier glow. */
.style-currency .fx-main.bare {
  position: relative;
  z-index: 2;
  display: inline-flex;
  width: 34px;
  height: 34px;
}
.style-currency .fx-main.bare .fx-glyph,
.style-currency .fx-main.bare .icon-stack,
.style-currency .fx-main.bare .icon-multi,
.style-currency .fx-main.bare .icon-spawn { width: 34px; height: 34px; }
.style-currency .fx-main.bare .fx-glyph {
  filter:
    brightness(0) invert(1) sepia(0.35) saturate(0.6) brightness(1.04)
    drop-shadow(0 0 1.2px #15110b) drop-shadow(0 0 1.2px #15110b)
    drop-shadow(0 0 10px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 4px rgba(0, 0, 0, 0.55));
}

/* Trigger pill — ONLY for an explicitly-triggered effect (round 2). A split
   capsule: gold header carrying the trigger's specific glyph (dark ink on gold) +
   a dark body carrying the payload. Sits above the magnitude badges. */
.style-currency .trigger-pill {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: stretch;
  border: 1.6px solid #20190f;
  border-radius: 999px;
  overflow: hidden;
}
.style-currency .trigger-pill .pill-header {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--pill-hdr, #d8b15a);
  border-right: 1.5px solid #20190f;
  padding: 0 7px;
}
.style-currency .pill-header .hdr-glyph {
  display: block;
  width: 15px;
  height: 15px;
  object-fit: contain;
  /* header glyph sits on bright gold → plain dark ink, no glow */
  filter: brightness(0) saturate(100%) opacity(0.85);
}
.style-currency .trigger-pill .pill-body {
  display: flex;
  align-items: center;
  padding: 4px 10px;
  background: var(--pill-body, rgba(20, 15, 8, 0.85));
}
.style-currency .pill-body .fx-glyph,
.style-currency .pill-body .icon-stack,
.style-currency .pill-body .icon-multi,
.style-currency .pill-body .icon-spawn { width: 24px; height: 24px; }

/* Magnitude badges — compact dark chips in the top-left .mag-bar row. charges =
   a bare count (square); lifetime = clock + count; dwell = hourglass + count (its
   own mark). carry = nothing. */
.style-currency .mag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  min-width: 17px;
  height: 17px;
  padding: 0 5px 0 3px;
  background: rgba(20, 15, 8, 0.92);
  border: 1.4px solid #20190f;
  border-radius: 5px;
  color: #f4ecd8;
  font: 700 10.5px ui-sans-serif, system-ui, sans-serif;
}
/* A bare count is basically square (no icon to flank); the icon badges get the
   small right padding so the number doesn't kiss the border. */
.style-currency .mag.mag-count { padding: 0; }
.style-currency .mag .mag-ico { display: block; width: 11px; height: 11px; color: #f4ecd8; }
.style-currency .mag .mag-ico svg { display: block; width: 100%; height: 100%; }

/* Scope cameo RETIRED 2026-06-21 (angel/devil/tile allegiance glyph dropped — it
   wasn't pulling its weight; polarity already reads off the border + socket marks).
   The L2 top-left slot now carries a decorative seal (see § L2 · Bully below). */

/* Icon-composition stack (icon algebra) — the renderer for a multi-layer `icon`
   expression (`poisoned+slash`), and the shape the auto-derived immunity
   composite now emits too, so authored and derived compositions look identical.
   Registered onto the generic light treatment (card-icon system §5) so it reads
   plate-less on any stock: the BASE carries the generic light fill, dimmed so
   the overlay wins the foreground; a DRAWN OPERATOR (.gs-op, e.g. the immunity
   slash) is light ink rimmed by a dark halo that knocks it off the base without
   a competing ring; a GLYPH OVERLAY (.gs-over) gets the same idea via a heavier
   dark drop-shadow rim, since an <img> can't carry two inks.
   (v1 tuning from icon-composition-tuner.html, lifted to light.) */
.style-currency .icon-stack {
  position: relative;
  display: block;
}
.style-currency .icon-stack .gs-base {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0.8;
  filter:
    brightness(0) invert(1) sepia(0.35) saturate(0.6) brightness(1.04)
    drop-shadow(0 0 1.1px #15110b) drop-shadow(0 0 1.1px #15110b)
    drop-shadow(0 0 6px rgba(0, 0, 0, 0.4));
}
.style-currency .icon-stack .gs-op,
.style-currency .icon-stack .gs-over {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.style-currency .icon-stack .gs-op .halo {
  fill: none;
  stroke: #15110b;
  stroke-width: 4.4;
  stroke-linecap: round;
}
.style-currency .icon-stack .gs-op .ink {
  fill: none;
  stroke: #f4ecd8;
  stroke-width: 1.8;
  stroke-linecap: round;
}
/* A glyph overlay sits at ~72% so the base stays readable underneath it, and
   carries a fat dark rim in place of the drawn operator's halo path. */
.style-currency .icon-stack .gs-over {
  object-fit: contain;
  transform: scale(0.72);
  filter:
    brightness(0) invert(1) sepia(0.35) saturate(0.6) brightness(1.04)
    drop-shadow(0 0 1.6px #15110b) drop-shadow(0 0 1.6px #15110b)
    drop-shadow(0 0 1.6px #15110b) drop-shadow(0 0 5px rgba(0, 0, 0, 0.55));
}

/* Multi-direction displace composite (icon algebra) — one mark carrying EVERY
   direction a card displaces in, for a card whose several displace effects the
   single-glyph corner could only voice one of. Drawn inline (not an <img>) since
   the arm set is derived per card, so it takes the light fill directly rather
   than through the brightness/invert recolor the file glyphs need. */
.style-currency .icon-multi {
  position: relative;
  display: block;
}
.style-currency .icon-multi .multi-arrow {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #f4ecd8;
  filter:
    drop-shadow(0 0 1.1px #15110b) drop-shadow(0 0 1.1px #15110b)
    drop-shadow(0 1px 1.5px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 7px rgba(0, 0, 0, 0.4));
}

/* Spawn composite (icon algebra): the event sparkle ring (light-fill glyph, same
   treatment as fx-glyph) with the spawned piece's Unicode char centered in its
   empty middle. Light cream ink + dark halo glow mirrors the glyph look so the
   text noun reads as part of the same idiom. */
.style-currency .icon-spawn {
  position: relative;
  display: block;
}
.style-currency .icon-spawn .spawn-ring {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter:
    brightness(0) invert(1) sepia(0.35) saturate(0.6) brightness(1.04)
    drop-shadow(0 0 1.1px #15110b) drop-shadow(0 0 1.1px #15110b)
    drop-shadow(0 0 6px rgba(0, 0, 0, 0.4));
}
.style-currency .icon-spawn .spawn-piece {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  line-height: 1;
  color: #f4ecd8;
  text-shadow:
    0 0 1.1px #15110b, 0 0 1.1px #15110b,
    0 1px 1.5px rgba(0, 0, 0, 0.55), 0 0 5px rgba(0, 0, 0, 0.4);
}
.style-currency .fx-main.bare .icon-spawn .spawn-piece { font-size: 20px; }

/* ============================================================
   09 · HOLO — holographic foil sports card
   ============================================================ */

.style-holo {
  --card-font: "Oxanium", "Space Grotesk", sans-serif;
  --name-font: "Oxanium", sans-serif;
  --type-font: "Oxanium", sans-serif;
  --card-bg: #f4f4f8;
  --card-fg: #0f1019;
  --border-w: 16px;
  --border-color: #0f1019;
  --card-radius: 18px;
  --art-bg: #0f1019;
  --art-stripe-a: #1a1b2e;
  --art-stripe-b: #0f1019;
  --rule-color: #0f1019;
  --gesture-bg: #f4f4f8;
  --gesture-stroke: #0f1019;
  --gesture-radius: 50%;
}
.style-holo.pol-enemy    { --socket-mark: #ff2563; }
.style-holo.pol-friendly { --socket-mark: #00b9ff; }
.style-holo.pol-neutral  { --socket-mark: #0f1019; }

.style-holo .frame-chrome {
  background:
    conic-gradient(
      from 0deg at 50% 50%,
      #ff2563 0deg,
      #ffd700 60deg,
      #00ff9c 120deg,
      #00b9ff 180deg,
      #c64bff 240deg,
      #ff2563 300deg,
      #ff2563 360deg
    );
  filter: saturate(1.1) brightness(1.05);
}
.style-holo .frame-chrome::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(135deg, rgba(255,255,255,0.4) 0%, transparent 30%, transparent 70%, rgba(255,255,255,0.3) 100%);
}
.style-holo .frame-border {
  border-width: 4px;
  box-shadow:
    inset 0 0 0 10px #f4f4f8,
    inset 0 0 0 12px #0f1019;
}
.style-holo .card-inner {
  inset: 14px;
  border-radius: 6px;
  background: var(--card-bg);
  box-shadow: 0 0 0 2px #d8d8e0 inset;
}
.style-holo .card-art-wrap {
  background:
    linear-gradient(135deg, #0f1019 0%, #2a1b3f 50%, #0f1019 100%);
  position: relative;
}
.style-holo .card-art-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(115deg, transparent 30%, rgba(255,255,255,0.18) 50%, transparent 70%);
}
.style-holo .card-name-banner {
  background: linear-gradient(180deg, #0f1019 0%, #1a1b2e 100%);
  color: #fff;
  font-family: "Oxanium", sans-serif;
  font-weight: 800;
  font-size: 18px;
  letter-spacing: 0.05em;
  border-top: 2px solid var(--socket-mark);
}

/* ============================================================
   10 · ILLUMINATED — maximalist manuscript
   ============================================================ */

.style-illuminated {
  --card-font: "Cormorant Garamond", serif;
  --body-font: "Cormorant Garamond", serif;
  --name-font: "UnifrakturMaguntia", "Cinzel", serif;
  --type-font: "Cinzel", serif;
  --card-bg: #f3e8c8;
  --card-fg: #2a1308;
  --border-w: 20px;
  --border-color: #6b1d1d;
  --card-radius: 6px;
  --art-bg: #d9c189;
  --art-stripe-a: #b58840;
  --art-stripe-b: #d9c189;
  --rule-color: #6b1d1d;
  --type-color: #6b1d1d;
  --gesture-bg: #f3e8c8;
  --gesture-stroke: #6b1d1d;
  --gesture-color: #6b1d1d;
}
.style-illuminated.pol-enemy    { --socket-mark: #6b1d1d; --border-color: #6b1d1d; }
.style-illuminated.pol-friendly { --socket-mark: #1d3a6b; --border-color: #1d3a6b; }
.style-illuminated.pol-neutral  { --socket-mark: #6b1d1d; }

.style-illuminated .frame-chrome {
  background:
    /* Marbled / floral pattern, abstract */
    radial-gradient(ellipse at 20% 20%, rgba(255,215,0,0.4) 0%, transparent 22%),
    radial-gradient(ellipse at 80% 30%, rgba(255,215,0,0.4) 0%, transparent 22%),
    radial-gradient(ellipse at 30% 80%, rgba(255,215,0,0.4) 0%, transparent 22%),
    radial-gradient(ellipse at 75% 75%, rgba(255,215,0,0.4) 0%, transparent 22%),
    radial-gradient(circle at center, #8c3838 0%, #6b1d1d 100%);
}
.style-illuminated .frame-chrome::before {
  /* curl/scroll motifs at corners */
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 12px 12px, #d4a93b 6px, transparent 7px),
    radial-gradient(circle at calc(100% - 12px) 12px, #d4a93b 6px, transparent 7px),
    radial-gradient(circle at 12px calc(100% - 12px), #d4a93b 6px, transparent 7px),
    radial-gradient(circle at calc(100% - 12px) calc(100% - 12px), #d4a93b 6px, transparent 7px);
}
.style-illuminated .frame-border {
  border-width: 2px;
  box-shadow:
    inset 0 0 0 16px transparent,
    inset 0 0 0 18px #d4a93b,
    inset 0 0 0 20px var(--border-color);
}
.style-illuminated .card-inner {
  background: var(--card-bg);
  border: 1px solid #d4a93b;
}
.style-illuminated .card-art-wrap {
  border-bottom: 1px solid #d4a93b;
}
.style-illuminated .card-name-banner {
  background: var(--card-bg);
  color: var(--border-color);
  font-family: "UnifrakturMaguntia", "Cinzel", serif;
  font-size: 26px;
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: none;
  border-top: 2px solid #d4a93b;
  text-shadow: 1px 1px 0 rgba(212,169,59,0.5);
}
