/* vah.link house style — themes: gallery (1a), editorial (1b), studio (1c) */
* { box-sizing: border-box; }

/* Spider-trap decoy anchor (page.html.j2): off-screen, not display:none, so
   dumb crawlers that skip CSS still parse the href and follow it into the maze
   (the href is a rotating, organic-looking path — no fixed /trap any more). */
.vh-trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
body {
  margin: 0; min-height: 100vh; display: flex; justify-content: center;
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  background: var(--page-bg); color: var(--fg);
}
.card {
  width: 100%; max-width: 440px; padding: 34px 30px 28px;
  display: flex; flex-direction: column; align-items: center;
}
/* landing / 404 use the card as a centered marketing panel (no inline
   styles — the CSP has no style-src 'unsafe-inline') */
.center-page { justify-content: center; min-height: 80vh; }
.links-narrow { max-width: 300px; }

/* ---- value-var defaults (gallery/light/outline/airy/simple) ----
   These are exactly the vars the per-page /<slug>/style.css :root block
   emits (link_site/style.py::compute_css_vars). That stylesheet is linked
   after this one, so its :root wins per-page. This block only exists so a
   page renders sanely if the per-page stylesheet is ever unavailable.
   Secondary vars the endpoint does NOT emit (--muted, --faint, --rule,
   --accent-soft, --avatar-hair, --placeholder-fg, --mark) keep their
   theme-scoped defaults below, same as before. */
:root {
  --page-bg: #f4f1ea; --fg: #1a1a1a; --hair: #ddd5c6; --accent: #c4622d;
  --stripe-a: #e7e0d4; --stripe-b: #efe9de;
  --display-font: 'Spectral', serif; --display-weight: 500;
  --btn-radius: 10px; --avatar-radius: 50%;
  --gap: 10px; --btn-pad: 13px 16px;
  --btn-bg1: #c4622d; --btn-fg1: #fff; --btn-border1: none;
  --btn-bg2: transparent; --btn-fg2: #1a1a1a; --btn-border2: 1px solid #ddd5c6;
  /* Premium (Pro/Founder) styling — "off" defaults; compute_css_vars overrides. */
  --page-image: none; --btn-image: none; --text-fx: none;
}

/* ---- gallery (default, panel 1a): light, centered, outline rows ---- */
body {
  --muted: #8a8375; --faint: #a39a88;
  --rule: #e4ddce; --accent-soft: #faf3ec;
  --avatar-hair: #e2dacb; --placeholder-fg: #b0a794; --mark: #c9c0af;
}
.hero {
  width: 100%; aspect-ratio: 5 / 2; object-fit: cover;
  border-radius: 12px; display: block; margin-bottom: 4px;
}
.avatar {
  width: 108px; height: 108px; margin-top: 8px; border-radius: var(--avatar-radius);
  object-fit: cover; border: 1px solid var(--avatar-ring, var(--avatar-hair));
  box-shadow: var(--avatar-shadow, none);
}
/* Avatar overlaid on the hero (hero_avatar_pos). The wrap is positioned; the
   avatar is absolute + vertically centered, horizontally left/center/right. */
.hero-wrap { position: relative; width: 100%; margin-bottom: 4px; }
.hero-wrap .hero { margin-bottom: 0; }
.avatar-over { position: absolute; top: 50%; transform: translateY(-50%); margin: 0; z-index: 2; }
.hero-wrap.avatar-left  .avatar-over { left: 18px; }
.hero-wrap.avatar-right .avatar-over { right: 18px; }
.hero-wrap.avatar-center .avatar-over { left: 50%; transform: translate(-50%, -50%); }
.avatar-placeholder {
  display: flex; align-items: center; justify-content: center;
  background: repeating-linear-gradient(135deg, var(--stripe-a) 0 9px, var(--stripe-b) 9px 18px);
}
.avatar-placeholder span { font: 400 9px 'Space Mono', monospace; letter-spacing: .1em; color: var(--placeholder-fg); }
.name {
  font-family: var(--name-font, var(--display-font)); font-weight: var(--name-weight, var(--display-weight));
  font-style: var(--name-style, normal); font-size: var(--name-size, 33px);
  line-height: 1.05; margin: 22px 0 0; text-align: center; letter-spacing: -.01em;
}
/* Verified checkmark inline with the artist name (shown when the page has a
   verified property). Sized to the text, tinted with the page accent. */
.name-verified { width: .62em; height: .62em; margin-left: .18em; vertical-align: baseline;
  fill: var(--accent, #c4622d); display: inline-block; }
.handle { font: 400 11px 'Space Mono', monospace; letter-spacing: .03em; color: var(--muted); margin: 9px 0 0; }
.bio { font: 400 15px/1.5 'Spectral', serif; color: #4a463d; text-align: center; margin: 16px 0 0; max-width: 27ch; }
/* Discipline / art-tag chips under the bio, above featured work. */
.art-tags { list-style: none; display: flex; flex-wrap: wrap; justify-content: center;
  gap: 7px; margin: 15px 0 0; padding: 0; max-width: 30ch; }
.art-tag { font: 400 10px 'Space Mono', monospace; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); border: 1px solid var(--rule); border-radius: 999px; padding: 4px 10px; white-space: nowrap; }
.rule { width: 100%; height: 1px; background: var(--rule); margin: 26px 0 22px; }
.kicker { font: 400 10px 'Space Mono', monospace; letter-spacing: .14em; color: var(--faint); }
.featured-work { width: 100%; }
.featured-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 14px; }
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; width: 100%; }
.work img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 4px; display: block; }
.work-link { display: block; cursor: pointer; }
/* Pure-CSS lightbox: hidden until its #lb-<id> is the :target. */
.lightbox {
  display: none; position: fixed; inset: 0; z-index: 100;
  align-items: center; justify-content: center; padding: 24px;
  background: rgba(0,0,0,.86);
}
.lightbox:target { display: flex; }
.lightbox-backdrop { position: absolute; inset: 0; cursor: zoom-out; }
/* Open-tracking beacon: 1px, invisible. Its background-image URL is set per
   work in the generated style.css and only resolves while the lightbox is
   :target, so the request fires on open (never as a page-load preload). */
.lb-beacon { position: absolute; width: 1px; height: 1px; opacity: 0;
  pointer-events: none; background-repeat: no-repeat; background-size: 1px 1px; }
.lightbox-img {
  position: relative; max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 6px; box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
/* 18+ interstitial (NSFW add-on) */
.nsfw-badge {
  align-self: center; font: 700 15px 'Space Mono', monospace; letter-spacing: .12em;
  color: #fff; background: #b3341f; border-radius: 999px; padding: 6px 14px; margin-bottom: 14px;
}
.nsfw-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 20px; width: 100%; }
.nsfw-continue {
  display: block; text-align: center; text-decoration: none; padding: var(--btn-pad);
  border-radius: var(--btn-radius); background: var(--accent); color: #fff; font-weight: 600;
}
.nsfw-cancel { display: block; text-align: center; text-decoration: none; color: var(--fg); opacity: .7; font-size: 14px; }
/* Verified-accounts registry badges */
.verified-accounts { width: 100%; margin-top: 26px; }
.verified-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.verified-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 11px 14px; border: 1px solid var(--hair); border-radius: var(--btn-radius);
  background: var(--btn-bg2); font-size: 13px;
}
.verified-check { color: var(--accent); font-weight: 700; }
.verified-platform { text-transform: capitalize; font-weight: 600; }
.verified-id { color: var(--muted); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
.verified-id[href] { text-decoration: underline; }
.verified-date { margin-left: auto; font-size: 11px; color: var(--faint); white-space: nowrap; }
/* "Products I use" affiliate section */
.products { width: 100%; margin-top: 26px; }
.product-list { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.product-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 11px 14px; border: 1px solid var(--hair); border-radius: var(--btn-radius);
  text-decoration: none; color: var(--fg); background: var(--btn-bg2);
}
.product-label { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.product-arrow { opacity: .5; margin-left: 10px; }
.product-disclosure { font-size: 11px; opacity: .6; margin-top: 10px; text-align: center; }
/* Per-link share/report menu (native <details>, no JS) */
.link-row-wrap { display: flex; align-items: stretch; gap: 6px; }
.link-row-wrap .link-row { flex: 1; }
.link-menu { position: relative; }
.link-menu > summary {
  /* NB: do NOT set display:flex/grid/block-with-flex here — WebKit/Safari
     stops toggling <details> when the summary's display is changed, so the
     menu opens but won't close. Keep default display; center the glyph with
     text-align + line-height instead. */
  list-style: none; cursor: pointer; text-align: center;
  width: 40px; height: 100%; min-height: 42px; line-height: 42px;
  border: 1px solid var(--hair); border-radius: var(--btn-radius);
  color: var(--fg); user-select: none; font-size: 18px; box-sizing: border-box;
}
.link-menu > summary::-webkit-details-marker { display: none; }
.link-menu > summary::marker { content: ''; }
.link-menu-pop {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; min-width: 170px;
  background: var(--page-bg); border: 1px solid var(--hair); border-radius: 10px;
  box-shadow: 0 12px 34px rgba(0,0,0,.28); padding: 6px; display: flex; flex-direction: column;
}
.link-menu-pop a { padding: 9px 11px; text-decoration: none; color: var(--fg); font-size: 13px; border-radius: 6px; }
.link-menu-pop a:hover { background: var(--stripe-a); }
/* Footer: view-on-mobile QR + legal links */
.qr-toggle { text-align: center; }
.qr-toggle > summary { cursor: pointer; font-size: 12px; color: var(--fg); opacity: .7; list-style: none; }
.qr-toggle > summary::-webkit-details-marker { display: none; }
.qr-img { width: 150px; height: 150px; margin: 10px auto 0; display: block; background: #fff; padding: 8px; border-radius: 8px; box-sizing: border-box; }
.foot-links { display: flex; gap: 12px; }
.foot-link { font-size: 11px; color: var(--fg); opacity: .6; text-decoration: none; }
.foot-link:hover { opacity: 1; }
/* Legal pages (/tos, /privacy) */
.legal { max-width: 640px; align-items: stretch; text-align: left; }
.legal .name { text-align: left; }
.legal-body { font-size: 14px; line-height: 1.6; }
.legal-body h2 { font-family: var(--display-font); font-size: 16px; margin: 22px 0 6px; }
.legal-note { opacity: .5; font-style: italic; margin-top: 22px; }
.links { width: 100%; display: flex; flex-direction: column; gap: var(--gap); margin-top: 26px; }
.link-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--btn-pad); border: var(--btn-border2); border-radius: var(--btn-radius);
  text-decoration: none; font: 500 14px 'Hanken Grotesk', sans-serif;
  background: var(--btn-bg2); color: var(--btn-fg2);
}
.link-tag { font: 400 9px 'Space Mono', monospace; color: var(--faint); letter-spacing: .08em; }
/* Inline verified check on a link whose URL is a verified property (replaces the
   old standalone verified-accounts list). */
.link-verified { width: .85em; height: .85em; margin-left: .3em; vertical-align: -.13em;
  fill: var(--accent, #c4622d); display: inline-block; }
.link-row.featured .link-verified { fill: var(--btn-fg1); }
.link-row.featured { border: var(--btn-border1); background: var(--btn-bg1); color: var(--btn-fg1); }
.link-row.featured .link-tag { color: var(--btn-fg1); }
/* Date-gated link in its preview window: visible but not yet clickable. */
.link-row.inactive { opacity: .5; pointer-events: none; cursor: default; }
.link-row.inactive .link-tag { color: var(--faint); letter-spacing: .1em; }
.foot { margin-top: 30px; display: flex; flex-direction: column; align-items: center; gap: 5px; }
.invited-by { font: 400 9.5px 'Space Mono', monospace; letter-spacing: .06em; color: var(--faint); }
.vah-mark { font: 400 9px 'Space Mono', monospace; letter-spacing: .1em; color: var(--mark); }

/* Public reverse-lookup page (/verify) */
.lookup { justify-content: flex-start; min-height: 80vh; }
.lookup-form { display: flex; gap: 8px; width: 100%; margin-top: 22px; }
.lookup-input {
  flex: 1; padding: var(--btn-pad); border-radius: var(--btn-radius);
  border: 1px solid var(--hair); font: 400 14px 'Hanken Grotesk', sans-serif;
  background: var(--btn-bg2); color: var(--fg);
}
.lookup-btn {
  padding: var(--btn-pad); border-radius: var(--btn-radius); border: var(--btn-border1);
  background: var(--btn-bg1); color: var(--btn-fg1); font: 600 14px 'Hanken Grotesk', sans-serif;
  cursor: pointer;
}
.lookup-result {
  width: 100%; margin-top: 22px; padding: 14px 16px; border-radius: var(--btn-radius);
  border: 1px solid var(--hair); font-size: 14px; line-height: 1.5;
}
.lookup-result.verified { border-color: var(--accent); background: var(--accent-soft); }
.lookup-result.verified .verified-check { color: var(--accent); font-weight: 700; margin-right: 4px; }
.lookup-result .verified-date { margin-top: 6px; font-size: 12px; color: var(--faint); }

/* ---- editorial (panel 1b): dark, left-aligned, solid rows ---- */
body[data-theme="editorial"] {
  --muted: #8a8171; --faint: #6b6456;
  --rule: #2a2721;
  --avatar-hair: #33302a; --placeholder-fg: #6b6456;
}
body[data-theme="editorial"] .card { align-items: flex-start; padding-bottom: 30px; }
body[data-theme="editorial"] .avatar { width: 96px; height: 96px; }
body[data-theme="editorial"] .name { font-size: 42px; line-height: .98; text-align: left; letter-spacing: -.02em; }
body[data-theme="editorial"] .handle { margin-top: 11px; }
body[data-theme="editorial"] .bio { font: 300 16px/1.5 'Spectral', serif; text-align: left; color: #c8c2b4; max-width: 30ch; }
body[data-theme="editorial"] .rule { margin: 28px 0 20px; }
body[data-theme="editorial"] .work-grid { grid-template-columns: repeat(2, 1fr); }
body[data-theme="editorial"] .work img { aspect-ratio: 4/3; }
body[data-theme="editorial"] .foot { align-items: flex-start; }
body[data-theme="editorial"] .vah-mark { color: #48443b; }

/* ---- studio (panel 1c): expressive, pills, offset avatar plate ---- */
body[data-theme="studio"] {
  --muted: #8a8474; --faint: #9a9583;
  --rule: transparent;
  --avatar-hair: #dcd5c5; --placeholder-fg: #a9a08d;
  background:
    radial-gradient(120% 90% at 80% 0%, #f6efe4 0, transparent 60%),
    radial-gradient(100% 80% at 0% 100%, #e7efdf 0, transparent 55%),
    var(--page-bg);
  position: relative;
}
body[data-theme="studio"]::before {
  content: ''; position: fixed; inset: 0; pointer-events: none;
  background-image: repeating-linear-gradient(0deg, rgba(122,140,90,.05) 0 1px, transparent 1px 4px);
}
body[data-theme="studio"] .avatar { width: 118px; height: 118px; }
body[data-theme="studio"] .name { font-size: 44px; line-height: .94; margin-top: 26px; letter-spacing: -.02em; }
body[data-theme="studio"] .handle { margin-top: 12px; }
body[data-theme="studio"] .bio { font-style: italic; color: #4c473c; margin-top: 14px; max-width: 26ch; }
body[data-theme="studio"] .link-row { justify-content: center; font-weight: 600; }
body[data-theme="studio"] .link-row .link-tag { display: none; }
body[data-theme="studio"] .foot { margin-top: 28px; }
body[data-theme="studio"] .vah-mark { color: #b9bda6; }

/* ---- Premium (Pro/Founder) styling — vars default to "off" in :root ---- */
/* Full-bleed page background image, layered over the theme --page-bg color.
   Appended last so its background-image longhand wins over the base body
   `background:` shorthand. */
body {
  background-image: var(--page-image);
  background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* Graphic button background over the computed --btn-bg (all rows incl. featured). */
.links .link-row {
  background-image: var(--btn-image);
  background-size: cover; background-position: center;
}
/* Text drop-shadow / outline in a chosen color — readability over image backgrounds. */
.name, .bio { text-shadow: var(--text-fx); }

/* Embedded players (Spotify / YouTube / SoundCloud / Apple Music / Bandcamp).
   The iframe is emitted by us with a src validated against the embed allowlist;
   the page CSP frame-src pins the same hosts. Video keeps a 16:9 box, audio
   players use their natural fixed height. */
.link-embed { margin: 10px 0; }
.link-embed iframe { width: 100%; border: 0; border-radius: 12px; display: block; }
.link-embed.is-audio iframe { height: 352px; }
.link-embed.is-video iframe { aspect-ratio: 16 / 9; height: auto; }
/* ── Custom (WYSIWYG) profile layout ─────────────────────────────────────────
   A CSS grid whose columns/gap and per-block positions are set in the per-page
   stylesheet (style.py) — never inline (the page CSP forbids inline styles).
   Blocks inherit the profile theme via the same --accent/--fg/--rule vars. */
.cust-grid { display: grid; margin: 22px 0 6px; align-items: start; }
.cust-block { min-width: 0; overflow-wrap: anywhere; }
.cust-h { font-family: var(--display-font); font-weight: var(--display-weight);
  color: var(--fg); margin: 0; line-height: 1.15; }
h1.cust-h { font-size: 30px; } h2.cust-h { font-size: 23px; } h3.cust-h { font-size: 18px; }
.cust-text { color: var(--fg); font-size: 15px; line-height: 1.6; }
.cust-text p { margin: 0 0 .7em; } .cust-text p:last-child { margin-bottom: 0; }
.cust-text a { color: var(--accent); text-decoration: underline; }
.cust-text ul, .cust-text ol { margin: 0 0 .7em; padding-left: 1.3em; }
.cust-text blockquote { margin: 0 0 .7em; padding-left: .9em;
  border-left: 3px solid var(--rule); color: var(--muted); }
.align-left { text-align: left; } .align-center { text-align: center; } .align-right { text-align: right; }
.cust-img { display: block; max-width: 100%; height: auto; border-radius: var(--btn-radius, 10px); }
.cust-imglink { display: block; }
.cust-btn { display: block; text-align: center; text-decoration: none;
  background: var(--btn-bg1, var(--accent)); background-image: var(--btn-image);
  background-size: cover; background-position: center;
  color: var(--btn-fg, #fff); font-weight: 600; font-size: 15px;
  padding: var(--btn-pad, 13px 16px); border-radius: var(--btn-radius, 10px); }
.cust-btn-dead { opacity: .5; }
.cust-social { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.cust-social-item { text-decoration: none; display: inline-flex; color: var(--accent); }
.cust-social-svg { width: 24px; height: 24px; display: block; fill: currentColor; }
.cust-spacer { width: 100%; }
.cust-divider { border: 0; border-top: 1px solid var(--rule); margin: 0; width: 100%; }
/* Mobile: collapse the 2-D grid to a single column in (row, col) order so a
   desktop-designed layout still reads top-to-bottom on a phone. */
@media (max-width: 640px) {
  .cust-grid { grid-template-columns: 1fr !important; }
  /* grid-row:auto is load-bearing: blocks are emitted in (row, col) order, so
     dropping the explicit row lets them auto-flow one-per-row in reading order.
     Without it, two blocks that shared a row (side-by-side, or an accidental
     same-cell drop) keep that row and OVERLAP once forced into one column. */
  .cust-block { grid-column: 1 / -1 !important; grid-row: auto !important; }
}
/* Featured-work widget: a tile grid of the artist's works (tier-capped). Empty
   slots render as dashed placeholders so the widget keeps its full footprint. */
.cust-works { display: grid; gap: 8px; width: 100%; }
.cust-works.cols-2 { grid-template-columns: repeat(2, 1fr); }
.cust-works.cols-3 { grid-template-columns: repeat(3, 1fr); }
.cust-works.cols-4 { grid-template-columns: repeat(4, 1fr); }
.cust-work { display: block; }
.cust-work img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 4px; display: block; }
.cust-work-ph { aspect-ratio: 1; border-radius: 4px; border: 1px dashed var(--rule, #ddd);
  background: repeating-linear-gradient(135deg, transparent 0 8px, rgba(128,128,128,.06) 8px 16px); }
/* Managed widgets — the artist's live links / products / avatar / hero, so a
   custom layout can reproduce the whole stock page. Reuse the button + product
   looks; avatar/hero mirror the stock shapes. */
.cust-links { display: flex; flex-direction: column; gap: 9px; width: 100%; }
.cust-verified { width: .8em; height: .8em; margin-left: .3em; vertical-align: -.08em; fill: currentColor; }
.cust-soon { font: 400 9px 'Space Mono', monospace; letter-spacing: .1em; margin-left: .5em; opacity: .8; }
.cust-products { display: flex; flex-direction: column; gap: 7px; width: 100%; }
.cust-product { display: flex; align-items: center; justify-content: space-between;
  text-decoration: none; color: var(--fg); border: 1px solid var(--rule); border-radius: var(--btn-radius, 10px);
  padding: 10px 14px; font-size: 14px; }
.cust-product-arrow { opacity: .5; }
.cust-product-disc { font-size: 11px; color: var(--muted); margin: 4px 0 0; }
.cust-avatar { width: 108px; height: 108px; object-fit: cover; display: block; margin: 0 auto;
  border: 1px solid var(--avatar-ring, var(--hair)); box-shadow: var(--avatar-shadow, none); }
.cust-avatar.shape-round { border-radius: 50%; }
.cust-avatar.shape-square { border-radius: var(--avatar-radius, 8px); }
.cust-avatar-ph { background: repeating-linear-gradient(135deg, var(--stripe-a) 0 9px, var(--stripe-b) 9px 18px); }
.cust-hero { width: 100%; aspect-ratio: 16/7; object-fit: cover; border-radius: var(--btn-radius, 10px); display: block; }
.cust-hero-ph { aspect-ratio: 16/7; border-radius: var(--btn-radius, 10px);
  background: repeating-linear-gradient(135deg, var(--stripe-a) 0 12px, var(--stripe-b) 12px 24px); }
/* Embed / player widget — an inline media player (Spotify/YouTube/Apple Music).
   Provider-specific sizing: YouTube is 16:9, the audio widgets are fixed-height. */
.cust-embed { width: 100%; }
.cust-embed iframe { width: 100%; border: 0; display: block; border-radius: var(--btn-radius, 10px); }
.cust-embed.provider-youtube { aspect-ratio: 16 / 9; }
.cust-embed.provider-youtube iframe { height: 100%; }
.cust-embed.provider-spotify iframe { height: 152px; }
.cust-embed.provider-apple_music iframe { height: 175px; }
/* Managed links widget rows: a button with the title centered and the link's
   tag (or SOON) as a small pill on the right, matching the stock link look. */
.cust-link-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.cust-link-label { flex: 1; min-width: 0; text-align: center; }
.cust-link-tag { flex-shrink: 0; font: 400 9px 'Space Mono', monospace; letter-spacing: .1em;
  text-transform: uppercase; opacity: .85; padding: 2px 8px; border: 1px solid currentColor;
  border-radius: 999px; }
/* Hero widget avatar overlay (mirrors the stock hero_avatar_pos): the avatar is
   vertically centered on the hero, positioned left / center / right. */
.cust-hero-wrap { position: relative; width: 100%; }
.cust-hero-wrap .cust-hero { margin: 0; }
.cust-hero-avatar { position: absolute; top: 50%; transform: translateY(-50%);
  width: 92px; height: 92px; object-fit: cover; border-radius: 50%; z-index: 2;
  border: 2px solid var(--page-bg); box-shadow: var(--avatar-shadow, 0 2px 10px rgba(0,0,0,.25)); }
.cust-hero-wrap.avatar-left  .cust-hero-avatar { left: 18px; }
.cust-hero-wrap.avatar-right .cust-hero-avatar { right: 18px; }
.cust-hero-wrap.avatar-center .cust-hero-avatar { left: 50%; transform: translate(-50%, -50%); }
/* Live-streaming badge — shown on a link whose channel is on air right now
   (status is cached server-side; see services/live_status). Pure CSS, no JS. */
.link-live, .cust-live {
  display: inline-flex; align-items: center; gap: 5px; flex-shrink: 0;
  font: 700 9px 'Space Mono', monospace; letter-spacing: .12em;
  color: #fff; background: #e23b2e; border-radius: 999px; padding: 2px 8px;
}
.live-dot { width: 6px; height: 6px; border-radius: 50%; background: #fff;
  animation: vah-live-pulse 1.6s ease-in-out infinite; }
@keyframes vah-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
/* Social icon for a channel that's live: a small dot on the corner. */
.cust-social-item.is-live { position: relative; }
.cust-social-item.is-live .live-dot { position: absolute; top: -1px; right: -1px;
  width: 8px; height: 8px; background: #e23b2e; border: 1px solid var(--page-bg); }
/* Reduced motion: keep the badge, drop the pulse. */
@media (prefers-reduced-motion: reduce) { .live-dot { animation: none; } }
