/* ============================================================
   Card templates — geometry derived from reference renders:
   banner 960×430, landscape 960×558, square 960×960
   ============================================================ */

@font-face {
  font-family: 'Arimo';
  font-display: swap;
  font-style: normal;
  font-weight: 400;
  src: url('../assets/fonts/arimo-latin-400-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Arimo';
  font-display: swap;
  font-style: italic;
  font-weight: 400;
  src: url('../assets/fonts/arimo-latin-400-italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Arimo';
  font-display: swap;
  font-style: normal;
  font-weight: 700;
  src: url('../assets/fonts/arimo-latin-700-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Arimo';
  font-display: swap;
  font-style: italic;
  font-weight: 700;
  src: url('../assets/fonts/arimo-latin-700-italic.woff2') format('woff2');
}

.card {
  --accent: #F3C910;
  --ribbon-yellow: #F4C90B;
  --ribbon-green: #467031;
  --card-bg: #1f1f1f;
  --ink: #F2F2F2;
  --ink-strong: #F5F5F5;
  --divider: #FAFAFA;
  --pill-bg: rgba(255, 255, 255, 0.24);
  --pill-ink: #fff;
  --ribbon-ink: #1E1902;
  --ribbon-ink2: #fff;
  --icon-fill: #fff;
  --icon-knockout: #303436;
  position: relative;
  width: 960px;
  background-color: var(--card-bg);
  font-family: 'Arimo', Arial, 'Helvetica Neue', sans-serif;
  color: #fff;
  overflow: hidden;
  flex: none;
  -webkit-font-smoothing: antialiased;
}
.card * { margin: 0; padding: 0; box-sizing: border-box; }

.card.banner    { height: 430px; }
.card.landscape { height: 558px; }
.card.square    { height: 960px; }

/* --- photo texture backgrounds --- */
.card {
  background-color: var(--card-bg);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
/* Texture-image layer as a REAL element (was a ::before). html-to-image can't render a
   pseudo-element's background image in its sandboxed SVG export — it came out blank on the
   downloaded PNG — but a real element's background IS inlined and captured. */
.card .tex-img {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.card .texture {
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(ellipse 120% 90% at 50% 42%,
      rgba(255, 255, 255, 0.045) 0%,
      rgba(255, 255, 255, 0.0) 45%,
      rgba(0, 0, 0, 0.14) 78%,
      rgba(0, 0, 0, 0.30) 100%);
}

/* --- free-tier watermark (UX flush bottom-right, fixed 500×356) --- */
.card {
  --watermark-w: 500px;
  --watermark-h: 356px;
  --watermark-opacity: 0.032;
  --watermark-filter: none;
  /* Soft guard: discourage drag/select “Save image as” on the live preview. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
}
.card img,
.card .watermark,
.card .site-mark {
  -webkit-user-drag: none;
  user-select: none;
  /* Clicks go to the stage (pan), not the bitmap — also blocks image drag-save. */
  pointer-events: none;
}
.card .watermark {
  position: absolute;
  inset: 0;
  z-index: 9;
  pointer-events: none;
  overflow: hidden;
}
.card .watermark img {
  position: absolute;
  right: 0;
  bottom: 0;
  width: var(--watermark-w);
  height: var(--watermark-h);
  min-width: var(--watermark-w);
  max-width: var(--watermark-w);
  min-height: var(--watermark-h);
  max-height: var(--watermark-h);
  flex: none;
  object-fit: fill;
  display: block;
  opacity: var(--watermark-opacity);
  filter: var(--watermark-filter);
}

/* --- vertical site mark (bottom-left) --- */
.card .site-mark {
  position: absolute;
  left: 0;
  bottom: 0;
  z-index: 5;
  writing-mode: vertical-rl;
  font-size: 16px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.5);
  pointer-events: none;
  user-select: none;
}

/* --- cover photo band (landscape / square) --- */
.card .cover {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  overflow: hidden;
  z-index: 1;
}
.card.landscape .cover { height: 198px; }
.card.square    .cover { height: 307px; }

/* body lip — stacks above the cover image; shadow falls onto the photo */
.card.landscape .body-surface,
.card.square .body-surface {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  pointer-events: none;
  background: transparent;
  box-shadow: 0 -6px 16px rgba(0, 0, 0, 0.45);
}
.card.landscape .body-surface { top: 198px; }
.card.square    .body-surface { top: 307px; }
.card .cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transform: scale(1);
  transform-origin: 50% 50%;
  display: block;
}

/* Isometric cover: the uploaded screenshot is projected at a true
   isometric angle — edges at ±30°, parallel projection, vertical
   squash — via the classic iso matrix (X→(.866,-.5), Y→(.866,.5)).
   The element is oversized so the projected parallelogram covers the
   whole band (bounds derived via the inverse matrix). */
.card .cover.iso {
  background: #17191B;
}
.card .cover.iso img {
  display: block;
  position: absolute;
  left: 7.5%;
  top: -150%;
  width: 85%;
  height: 400%;
  object-fit: cover;
  object-position: var(--cover-pos-x, 50%) var(--cover-pos-y, 30%);
  transform: matrix(0.866, -0.5, 0.866, 0.5, 0, 0) scale(var(--cover-zoom, 1));
  transform-origin: center center;
}
.card.square .cover.iso img {
  left: 4%;
  top: -94%;
  width: 92%;
  height: 288%;
}
/* --- framed profile photo (banner / landscape) --- */
.card .photo-frame {
  position: absolute;
  left: 48px;
  width: 280px;
  height: 280px;
  border: 7px solid #fff;
  border-radius: 20px;
  overflow: hidden;
  background: #222;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
  z-index: 2;
}
.card.landscape .photo-frame {
  z-index: 3;
}
.card.banner    .photo-frame { top: 75px; }
.card.landscape .photo-frame { top: 238px; }
.card .photo-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transform: scale(1);
  transform-origin: 50% 50%;
  display: block;
  border-radius: 13px;
}

/* --- circular avatar (square) --- */
.card .avatar-ring {
  position: absolute;
  left: 340px;
  top: 164px;
  width: 280px;
  height: 280px;
  border: 4px solid #fff;
  border-radius: 50%;
  overflow: hidden;
  background: #222;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.38);
  z-index: 3;
}
.card .avatar-ring img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  transform: scale(1);
  transform-origin: 50% 50%;
  display: block;
  border-radius: 50%;
}

/* --- left-aligned content column (banner / landscape) --- */
.card .content {
  position: absolute;
  left: 356px;
  width: 555px;
  z-index: 1;
}
.card.banner    .content { top: 65px; }
.card.landscape .content { top: 228px; }

.card .name {
  font-size: 63px;
  font-weight: 700;
  line-height: 1;
  color: var(--accent);
  letter-spacing: -0.049em;
}
.card .headline {
  margin-top: 8px;
  font-size: 30px;
  font-weight: 400;
  line-height: 35px;
  color: var(--ink);
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* Roles mode only: last phrase stays together when wrapping. */
.card .headline .headline-tail {
  white-space: nowrap;
}
.card .divider {
  border: none;
  height: 2px;
  background: var(--divider);
  margin-top: 22px;
}
.card .links {
  margin-top: 33px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.card .link-row {
  display: flex;
  align-items: center;
  gap: 18px;
  min-height: 32px;
  margin-left: 4px;
}
.card .link-row .icon {
  width: 32px;
  height: 32px;
  flex: none;
  display: block;
}
.card .link-row .icon svg { width: 100%; height: 100%; display: block; }
.card .link-row .url {
  font-size: 30.5px;
  color: var(--ink-strong);
  line-height: 1.1;
  word-break: break-all;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1.5px;
}

/* --- centered content (square / Preferences) ---
   Flex column: identity (name+headline) → links → badges.
   Links use equal margin auto so gap above/below matches
   between the name block and the preference pills. */
.card .content-c {
  position: absolute;
  left: 40px;
  right: 40px;
  top: 467px;
  bottom: 51px;
  z-index: 1;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.card.square .identity-c {
  flex: 0 0 auto;
}
.card.square .name { font-size: 63px; line-height: 1; }
.card.square .headline {
  margin: 4px auto 0;
  max-width: 620px;
  font-size: 28px;
  line-height: 33px;
  color: var(--ink);
}
.card .links-c {
  flex: 0 0 auto;
  margin-top: auto;
  margin-bottom: auto;
  display: flex;
  flex-direction: column;
  gap: 26px;
}
.card .links-c .url {
  font-size: 30.5px;
  color: var(--ink-strong);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1.5px;
  line-height: 1;
}

/* --- badge pills (square) --- */
.card .badges {
  position: static;
  flex: 0 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 36px;
  row-gap: 23px;
  /* Keep the badge grid's original bounds (left 44px, right 28px) while
     content-c stays symmetric at 40/40 so centered text is truly centered. */
  margin-left: 4px;
  margin-right: -12px;
}
.card .badge {
  height: 49px;
  border-radius: 24.5px;
  background: var(--pill-bg);
  display: inline-flex;
  align-items: center;
  gap: 13px;
  padding: 0 26px 0 27px;
  justify-self: end;
  white-space: nowrap;
}
.card .badge:nth-child(even) { justify-self: start; }
.card .badge .icon { width: 27px; height: 27px; flex: none; }
.card .badge .icon svg { width: 100%; height: 100%; display: block; }
.card .badge .txt { font-size: 23.5px; color: var(--pill-ink); line-height: 1; }
.card .badge .txt b { font-weight: 700; }

/* --- FEATURED / #opentowork corner ribbon --- */
.card .ribbon {
  position: absolute;
  top: 0;
  left: 0;
  width: 250px;
  height: 250px;
  overflow: hidden;
  z-index: 6;
  pointer-events: none;
}
.card .ribbon .rotor {
  position: absolute;
  left: -69px;
  top: 144px;
  width: 320px;
  transform: rotate(-40deg);
  transform-origin: 0 0;
  filter: drop-shadow(0 5px 8px rgba(0, 0, 0, 0.35));
}
/* per-band centring: each band's visible chord has its own midpoint
   (the outer band exits the card sooner), so FEATURED shifts left and
   the status band shifts right along the run */
.card.iso-cover .ribbon .band-featured { padding-right: 22px; }
.card.iso-cover .ribbon .band-otw { padding-left: 22px; }

/* isometric cover on → ribbon runs parallel to the iso edges (-30deg);
   rotor anchor recomputed for the shallower angle so the bands keep the
   same perpendicular distance from the corner */
.card.iso-cover .ribbon {
  width: 350px;
  height: 350px;
}
.card.iso-cover .ribbon .rotor {
  /* -30deg chord is longer: 460px rotor spans from beyond the left edge
     to the top-edge exit (inner band edge leaves at x≈291); anchor puts
     the text centre on the visible band's midpoint (≈106, 61) */
  left: -113px;
  top: 142px;
  width: 460px;
  transform: rotate(-30deg);
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.35));
}
.card.iso-cover .ribbon .band-otw {
  box-shadow: 0 7px 14px rgba(0, 0, 0, 0.5);
}

.card .ribbon .band {
  text-align: center;
  overflow: hidden;
}
.card .ribbon .band-featured {
  height: 39.5px;
  background: #F4C90B;
  color: #1E1902;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.3px;
  line-height: 40px;
}
.card .ribbon .band-otw {
  height: 39.5px;
  background: #467031;
  color: #fff;
  font-size: 24px;
  font-weight: 400;
  letter-spacing: 0.2px;
  line-height: 39px;
}
.card .ribbon .band-otw.ribbon-urgent {
  background: #D91E2A;
}

/* FEATURED is UX Jobs' endorsement, so it never appears in the editor preview or on any card
   a person downloads (screenshotting the preview would leak it otherwise). Hidden with
   visibility (not display) so the status band keeps its exact, already-centered two-band
   position instead of collapsing up and drifting off its diagonal chord. Only the paid capture
   we render for posting adds .capture-featured to reveal the banner. */
.card .ribbon .band-featured { visibility: hidden; }
.card.capture-featured .ribbon .band-featured { visibility: visible; }
/* Admin unlock (?admin=TOKEN in app.js): reveal FEATURED in the preview + free export. */
body.admin-featured .card .ribbon .band-featured { visibility: visible; }

/* ============ THEMES ============ */
.card.theme-dark-cement {
  background-image: url('../assets/ui/texture-dark-cement.webp');
}

.card.theme-blue-sky {
  --card-bg: #3d6a9e;
  background-image: url('../assets/ui/texture-blue-sky.webp');
}
.card.theme-blue-sky .texture {
  background-image:
    radial-gradient(ellipse 120% 90% at 50% 42%,
      rgba(255, 255, 255, 0.08) 0%,
      rgba(255, 255, 255, 0.0) 40%,
      rgba(10, 30, 60, 0.22) 72%,
      rgba(10, 30, 60, 0.42) 100%);
}

.card.theme-red-sky {
  --card-bg: #5a2828;
  background-color: var(--card-bg);
  background-image: none;
}
.card.theme-red-sky .tex-img {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: url('../assets/ui/texture-blue-sky.webp') center / cover no-repeat;
  filter: hue-rotate(148deg) saturate(1.08) brightness(0.86);
  pointer-events: none;
}
.card.theme-red-sky .texture {
  z-index: 1;
  background-image:
    radial-gradient(ellipse 120% 90% at 50% 42%,
      rgba(255, 180, 160, 0.08) 0%,
      rgba(255, 255, 255, 0.0) 40%,
      rgba(45, 10, 10, 0.26) 72%,
      rgba(28, 6, 6, 0.46) 100%);
}

.card.theme-night-grid {
  --card-bg: #181818;
  --grid-line: rgba(255, 255, 255, 0.09);
  --grid-size: 40px;
  background-color: var(--card-bg);
  background-image: linear-gradient(165deg, #1f1f1f 0%, #141414 55%, #181818 100%);
}
.card.theme-night-grid .texture {
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px),
    radial-gradient(ellipse 120% 90% at 50% 42%,
      rgba(255, 255, 255, 0.025) 0%,
      transparent 45%,
      rgba(0, 0, 0, 0.16) 78%,
      rgba(0, 0, 0, 0.3) 100%);
  background-size: var(--grid-size) var(--grid-size), var(--grid-size) var(--grid-size), auto;
  background-position: 0 0, 0 0, center;
}

/* Nebula family — archived from theme picker (may restore later).
   Re-add keys to THEMES in app.js; texture: assets/ui/texture-nebula.jpg */
.card.theme-nebula,
.card.theme-cyan-nebula,
.card.theme-magenta-nebula,
.card.theme-yellow-nebula {
  --card-bg: #0a1210;
  --nebula-hue: 0deg;
  --nebula-glow: 80, 160, 130;
  background-color: var(--card-bg);
  background-image: none;
}
.card.theme-nebula .tex-img,
.card.theme-cyan-nebula .tex-img,
.card.theme-magenta-nebula .tex-img,
.card.theme-yellow-nebula .tex-img {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: url('../assets/ui/texture-nebula.jpg') center / cover no-repeat;
  filter: hue-rotate(var(--nebula-hue)) saturate(1.05) brightness(1);
  pointer-events: none;
}
.card.theme-nebula .texture,
.card.theme-cyan-nebula .texture,
.card.theme-magenta-nebula .texture,
.card.theme-yellow-nebula .texture {
  z-index: 1;
  background-image:
    radial-gradient(ellipse 110% 85% at 50% 55%,
      rgba(var(--nebula-glow), 0.08) 0%,
      rgba(255, 255, 255, 0.0) 38%,
      rgba(0, 0, 0, 0.18) 72%,
      rgba(0, 0, 0, 0.42) 100%);
}

.card.theme-cyan-nebula {
  --nebula-hue: 18deg;
  --nebula-glow: 60, 170, 165;
}
.card.theme-magenta-nebula {
  --nebula-hue: 145deg;
  --nebula-glow: 170, 80, 150;
}
.card.theme-yellow-nebula {
  --nebula-hue: -98deg;
  --nebula-glow: 170, 155, 70;
}

.card.theme-obsidian {
  --watermark-opacity: 0.042;
  --card-bg: #050505;
  background-image: url('../assets/ui/texture-obsidian.jpg');
  background-position: center left;
}
.card.theme-obsidian .texture {
  background-image:
    radial-gradient(ellipse 120% 90% at 35% 50%,
      rgba(255, 255, 255, 0.04) 0%,
      rgba(255, 255, 255, 0.0) 40%,
      rgba(0, 0, 0, 0.2) 75%,
      rgba(0, 0, 0, 0.45) 100%);
}

/* Flow family — one wave texture, hue-shifted per CMYK channel.
   teal-flow is archived from the picker (base hue); CSS kept for restore. */
.card.theme-teal-flow,
.card.theme-cyan-flow,
.card.theme-magenta-flow,
.card.theme-green-flow {
  --watermark-opacity: 0.042;
  --card-bg: #051010;
  --flow-hue: 0deg;
  --flow-glow: 0, 180, 160;
  background-color: var(--card-bg);
  background-image: none;
}
.card.theme-teal-flow .tex-img,
.card.theme-cyan-flow .tex-img,
.card.theme-magenta-flow .tex-img,
.card.theme-green-flow .tex-img {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: url('../assets/ui/texture-teal-flow.jpg') center / cover no-repeat;
  filter: hue-rotate(var(--flow-hue)) saturate(1.05) brightness(1);
  pointer-events: none;
}
.card.theme-teal-flow .texture,
.card.theme-cyan-flow .texture,
.card.theme-magenta-flow .texture,
.card.theme-green-flow .texture {
  z-index: 1;
  background-image:
    radial-gradient(ellipse 110% 85% at 50% 55%,
      rgba(var(--flow-glow), 0.07) 0%,
      rgba(255, 255, 255, 0.0) 38%,
      rgba(0, 0, 0, 0.18) 72%,
      rgba(0, 0, 0, 0.42) 100%);
}

.card.theme-cyan-flow {
  --flow-hue: 18deg;
  --flow-glow: 0, 185, 175;
}
.card.theme-cyan-flow .ribbon .band-otw {
  background: #0E4F71;
  color: #fff;
}
.card.theme-magenta-flow {
  --flow-hue: 145deg;
  --flow-glow: 180, 70, 155;
}
.card.theme-magenta-flow .ribbon .band-otw {
  background: #5F223D;
  color: #fff;
}
.card.theme-green-flow {
  --flow-hue: -98deg;
  --flow-glow: 90, 160, 50;
}
.card.theme-green-flow .ribbon .band-otw {
  background: #3A5D07;
  color: #fff;
}

/* Pulse family — one light-trail texture, hue-shifted per CMYK channel.
   yellow-pulse is archived from the picker; CSS kept for restore. */
.card.theme-red-pulse,
.card.theme-cyan-pulse,
.card.theme-magenta-pulse,
.card.theme-yellow-pulse {
  --watermark-opacity: 0.042;
  --card-bg: #050505;
  --pulse-hue: 0deg;
  --pulse-glow: 220, 40, 40;
  --pulse-ribbon: #CE0405;
  background-color: var(--card-bg);
  background-image: none;
}
.card.theme-red-pulse .tex-img,
.card.theme-cyan-pulse .tex-img,
.card.theme-magenta-pulse .tex-img,
.card.theme-yellow-pulse .tex-img {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background: url('../assets/ui/texture-red-pulse.jpg') center bottom / cover no-repeat;
  filter: hue-rotate(var(--pulse-hue)) saturate(1.08) brightness(1.02);
  pointer-events: none;
}
.card.theme-red-pulse .texture,
.card.theme-cyan-pulse .texture,
.card.theme-magenta-pulse .texture,
.card.theme-yellow-pulse .texture {
  z-index: 1;
  background-image:
    radial-gradient(ellipse 120% 70% at 50% 85%,
      rgba(var(--pulse-glow), 0.1) 0%,
      rgba(255, 255, 255, 0.0) 35%,
      rgba(0, 0, 0, 0.22) 70%,
      rgba(0, 0, 0, 0.48) 100%);
}
.card.theme-red-pulse .ribbon .band-otw,
.card.theme-cyan-pulse .ribbon .band-otw,
.card.theme-magenta-pulse .ribbon .band-otw,
.card.theme-yellow-pulse .ribbon .band-otw {
  background: var(--pulse-ribbon);
  color: #fff;
}

.card.theme-cyan-pulse {
  --pulse-hue: 178deg;
  --pulse-glow: 40, 200, 210;
  --pulse-ribbon: #0F6F67;
}
.card.theme-magenta-pulse {
  --pulse-hue: 300deg;
  --pulse-glow: 210, 40, 200;
  --pulse-ribbon: #C804C8;
}
.card.theme-yellow-pulse {
  --pulse-hue: 52deg;
  --pulse-glow: 220, 200, 40;
  --pulse-ribbon: #79350F;
}

/* ============================================================
   OPS THEMES — palettes ported from the UX Jobs Chrome extension
   panel themes (chrome-extension/sidepanel.css). Fully procedural:
   no texture assets, so these add zero weight to the repo.
   Colours are literal rgba (not color-mix) so getComputedStyle
   resolves them cleanly through the html-to-image export path.
   ============================================================ */
.card.theme-amber-crt,
.card.theme-ice-holo,
.card.theme-tactical {
  --watermark-opacity: 0.042;
  --pill-bg: rgba(255, 255, 255, 0.10);
  --pill-ink: var(--ink);
  --divider: var(--ops-line);
  background-color: var(--card-bg);
  /* Grid backdrop tinted with the theme's own ink, as the extension does.
     30px on a ~400px panel → 60px on the 960px card keeps the same density. */
  background-image:
    linear-gradient(to right,  var(--ops-grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--ops-grid) 1px, transparent 1px);
  background-size: 60px 60px;
}
.card.theme-amber-crt .texture,
.card.theme-ice-holo .texture,
.card.theme-tactical .texture {
  background-image:
    radial-gradient(ellipse 115% 88% at 50% 45%,
      rgba(255, 255, 255, 0.05) 0%,
      rgba(255, 255, 255, 0.0) 42%,
      rgba(0, 0, 0, 0.22) 74%,
      rgba(0, 0, 0, 0.48) 100%);
}
/* Phosphor glow on the name — the extension uses 5px on a small title;
   scaled up here for the 63px card name. */
.card.theme-amber-crt .name,
.card.theme-ice-holo .name,
.card.theme-tactical .name {
  text-shadow: 0 0 18px var(--ops-glow);
}

.card.theme-amber-crt {
  --card-bg: #0A0806;
  --ink: #FFB638;
  --ink-strong: #FFC966;
  --icon-knockout: #20180D;
  --ops-grid: rgba(255, 182, 56, 0.07);
  --ops-line: rgba(255, 182, 56, 0.55);
  --ops-glow: rgba(255, 176, 0, 0.55);
}
/* Scanlines — amber is the CRT tube theme. z-index 8 sits above the ribbon (6)
   but below the watermark (9). Softer and wider than the extension's 3px,
   which reads as noise once a 960px card is downscaled in a feed. */
.card.theme-amber-crt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 8;
  pointer-events: none;
  background: repeating-linear-gradient(180deg,
    transparent 0, transparent 3px, rgba(0, 0, 0, 0.10) 4px);
}
.card.theme-amber-crt .ribbon .band-otw {
  background: #4D3A15;
  color: #FFD79A;
}

.card.theme-ice-holo {
  --card-bg: #01060E;
  --ink: #5FD8FF;
  --ink-strong: #9FE9FF;
  --icon-knockout: #0F2333;
  --ops-grid: rgba(95, 216, 255, 0.07);
  --ops-line: rgba(95, 216, 255, 0.55);
  --ops-glow: rgba(95, 216, 255, 0.55);
}
.card.theme-ice-holo .ribbon .band-otw {
  background: #123F57;
  color: #CBEFFF;
}

.card.theme-tactical {
  --card-bg: #080607;
  --ink: #E6D2D4;
  --ink-strong: #F3E6E7;
  --icon-knockout: #1F0F11;
  --ops-grid: rgba(226, 59, 59, 0.08);
  --ops-line: rgba(230, 210, 212, 0.45);
  --ops-glow: rgba(226, 59, 59, 0.60);
}
.card.theme-tactical .ribbon .band-otw {
  background: #3A1A1C;
  color: #F2D8D9;
}


/* Stronger logo watermark on Sky & Pulse themes only — the faint default washes out on those
   busier/lighter grounds, so bump opacity to keep the anti-crop mark visible there. */
.card.theme-red-pulse,
.card.theme-cyan-pulse,
.card.theme-magenta-pulse,
.card.theme-yellow-pulse {
  --watermark-opacity: 0.06;
}
/* Sky grounds are lighter, so the same opacity reads heavier — nudge it just below Pulse. */
.card.theme-blue-sky,
.card.theme-red-sky {
  --watermark-opacity: 0.05;
}
