/* ============================================================
   RadioGrub — cards.css
   Station imagery (art.js) and the shared station card + grid
   (cards.js). Clean grids, generous spacing, strong type, RadioGrub
   colours. Joe's mockup governs the final look; this is the system
   it will skin.
   ============================================================ */

/* ---------- artwork ---------- */
.rgArt{
  position:relative; display:block; width:100%; aspect-ratio:1 / 1;
  overflow:hidden; border-radius:12px; background:var(--surface2);
}
.rgArt--circle{ border-radius:50%; }
.rgArt img{ position:absolute; inset:0; width:100%; height:100%; display:block; object-fit:cover; }
/* logos: the whole image, on white, with room to breathe inside a circle */
/* ---- A LOGO NEEDS A PLATE, AND THE PLATE IS NOW DARK ----
   This was white, because a logo can be any colour and white is the safe plate
   for one. On a black site a white square behind every logo reads as a hole
   punched in the page, and Red Cup's mark — red and white on transparency —
   sits far better on the near-black. So the plate follows the site.
   The trade is real and worth knowing: a station whose logo is solid dark with
   no light in it would disappear here. `artworkFit: 'contain'` is per-station,
   so that one gets a white plate of its own the day it turns up — and the
   initials tile already covers a station with no artwork at all. */
.rgArt--contain{ background:var(--surface2); box-shadow:inset 0 0 0 1px var(--line2); }
/* opt-out for a dark logo: set artworkPlate:'light' on the station */
.rgArt--contain.rgArt--plateLight{ background:#f4f4f6; }
.rgArt--contain img{ object-fit:contain; padding:6%; }
.rgArt--circle.rgArt--contain img{ padding:14%; }
/* no artwork: initials on a brand colour */
.rgArt--tile{ background:var(--tile, var(--accent)); color:var(--ink, #fff); display:flex; align-items:center; justify-content:center; }
.rgInitials{ font-weight:950; letter-spacing:-.02em; font-size:clamp(16px, 26cqw, 52px); line-height:1; opacity:.96; }
.rgArt--tile{ container-type:inline-size; }

/* ---------- the grid ---------- */
.rgGrid{
  display:grid; gap:28px 22px;
  grid-template-columns:repeat(auto-fill, minmax(172px, 1fr));
}
.rgGrid--circles{ grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); }

/* ---------- the card ---------- */
.rgCard{ position:relative; min-width:0; border-radius:16px; padding:10px 10px 12px; margin:-10px; transition:background .15s ease; }
.rgCard:hover{ background:var(--surface2); }
.rgCardArt{ position:relative; }
.rgCardArt > a{ display:block; text-decoration:none; }
/* the frame holds the (clipped) art plus what sits on it — never clips */
.rgCardFrame{ position:relative; }
/* art is often inside a link; never inherit link colour or underline */
a .rgArt, .rgArt{ text-decoration:none; }
.rgArt--tile{ color:var(--ink, #fff) !important; }
.rgCard--circle .rgCardFrame{ margin:0 6%; }
.rgCard--circle{ text-align:center; }

.rgBadge{
  position:absolute; top:8px; left:8px; z-index:2;
  font-size:11px; font-weight:950; letter-spacing:.02em;
  padding:4px 9px; border-radius:999px;
  /* ONE readable plate for every state. It sits on top of station artwork,
     which can be anything from a white logo plate to a black photo, so the
     badge brings its own dark ground rather than borrowing the page's.
     (It used to be a near-white plate with --text, which went white-on-white
     once --text became white: every "On air" badge was invisible.) */
  background:rgba(10,10,12,.82); color:#fff;
  border:1px solid rgba(255,255,255,.16);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  box-shadow:0 2px 10px rgba(0,0,0,.45);
}
.rgBadge--live{ background:var(--accent); color:#fff; border-color:rgba(255,255,255,.22); }
.rgBadge--live::before{ content:""; display:inline-block; width:6px; height:6px; margin-right:6px; vertical-align:1px; border-radius:50%; background:currentColor; animation:blink 1.4s infinite; }
.rgBadge--off{ background:rgba(26,26,32,.9); color:rgba(255,255,255,.78); }
.rgBadge--demo{ background:rgba(0,0,0,.92); color:#fff; letter-spacing:.1em; font-size:10px; }
/* On a circle the badge straddles the bottom edge, centred — on the frame, so
   the crop can't cut it. */
.rgCard--circle .rgBadge{ left:50%; top:auto; bottom:0; transform:translate(-50%, 50%); white-space:nowrap; max-width:calc(100% + 12px); overflow:hidden; text-overflow:ellipsis; }

.rgPlay{
  position:absolute; right:8px; bottom:8px; z-index:2;
  width:46px; height:46px; border-radius:50%; border:none; cursor:pointer;
  background:var(--accent); color:#fff; display:flex; align-items:center; justify-content:center;
  box-shadow:0 8px 18px rgba(226,27,35,.35);
  opacity:0; transform:translateY(6px); transition:opacity .15s ease, transform .15s ease, background .15s;
}
.rgPlay svg{ width:20px; height:20px; margin-left:2px; }
.rgPlay:hover{ background:var(--accent2); }
.rgCard:hover .rgPlay, .rgPlay:focus-visible{ opacity:1; transform:none; }
@media (hover:none){ .rgPlay{ opacity:1; transform:none; } }
/* On a circle the play button is centred ON the rim, low on the right — 30°
   below horizontal: 50% ± 50%·cos/sin(30°) = 93.3% / 75%. Lower than that and,
   on a phone-sized circle, it meets the badge's corner. */
.rgCard--circle .rgPlay{ --play:46px; right:auto; bottom:auto;
  left:calc(93.3% - var(--play) / 2); top:calc(75% - var(--play) / 2); width:var(--play); height:var(--play);
  box-shadow:0 0 0 3px var(--bg, #0b0b0e), 0 8px 18px rgba(226,27,35,.35); }
.rgCard--circle:hover .rgPlay{ box-shadow:0 0 0 3px var(--surface2), 0 8px 18px rgba(226,27,35,.35); }   /* the ring matches the card behind it */

.rgCardBody{ display:flex; align-items:flex-start; gap:6px; margin-top:12px; }
.rgCard--circle .rgCardBody{ justify-content:center; margin-top:22px; }
.rgCardTitle{ margin:0; font-size:15px; font-weight:950; letter-spacing:-.2px; line-height:1.25; min-width:0; flex:1;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rgCard--circle .rgCardTitle{ flex:0 1 auto; }
.rgCardTitle a{ color:inherit; text-decoration:none; }
.rgCardTitle a::after{ content:""; position:absolute; inset:0; z-index:1; }   /* whole card is the link */
.rgCardMeta{ margin:3px 0 0; color:var(--muted); font-weight:700; font-size:13px; line-height:1.35;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rgCardSub{ margin:3px 0 0; color:var(--muted2); font-weight:750; font-size:12.5px; min-height:1em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.rgCardSub:empty{ display:none; }
.rgFav{
  position:relative; z-index:2; border:none; background:none; cursor:pointer; padding:0 2px;
  font-size:17px; line-height:1.1; color:var(--muted2);
}
.rgFav:hover, .rgFav.on{ color:var(--accentText); }

.rgEmpty{ color:var(--muted); font-weight:700; margin:0; padding:22px 20px; border:1px dashed var(--line); border-radius:16px; background:var(--surface); }

/* ---------- section rhythm shared by the grid pages ---------- */
.rgSection{ margin-top:56px; }
.rgSectionHead{ display:flex; align-items:flex-end; justify-content:space-between; gap:16px; flex-wrap:wrap; margin-bottom:22px; }
.rgSectionHead h2{ margin:0; font-size:clamp(22px, 2.4vw, 28px); font-weight:980; letter-spacing:-.6px; line-height:1.1; }
.rgSectionHead p{ margin:6px 0 0; color:var(--muted); font-weight:650; font-size:14.5px; line-height:1.5; max-width:70ch; }
.rgSectionHead .rgMore{ font-weight:900; font-size:14px; color:var(--text); text-decoration:none; white-space:nowrap; }
.rgSectionHead .rgMore:hover{ color:var(--accentText); }

@media (max-width:560px){
  .rgGrid{ grid-template-columns:repeat(2, minmax(0, 1fr)); gap:22px 16px; }
  .rgGrid--circles{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
  .rgPlay{ width:40px; height:40px; }
  .rgCard--circle .rgPlay{ --play:40px; }
}

/* `blink` and `wv` were referenced by the live dots and the station page's
   wave bars but never defined anywhere, so neither ever animated. */
@keyframes blink{ 0%,100%{ opacity:1 } 50%{ opacity:.35 } }
@keyframes wv{ 0%,100%{ height:6px } 50%{ height:20px } }
@media (prefers-reduced-motion: reduce){ .rgBadge--live::before{ animation:none; } }

/* ============================================================
   THE BROWSE ROW
   A real scroller with snap, so touch, trackpad and keyboard all work
   with no script at all; carousel.js only adds the arrows. Grids stay
   grids — a row is for skimming, a grid is for comparing.
   ============================================================ */
.rgRow{ position:relative; margin:0 -4px; }
.rgRowTrack{
  display:grid; grid-auto-flow:column;
  grid-auto-columns: clamp(148px, 17vw, 196px);
  gap:18px;
  overflow-x:auto; overscroll-behavior-x:contain;
  scroll-snap-type:x mandatory;
  padding:4px 4px 10px;
  scrollbar-width:none;                      /* the arrows and the fades are the affordance */
}
.rgRowTrack::-webkit-scrollbar{ display:none; }
.rgRowTrack > *{ scroll-snap-align:start; }

/* the fades say "there is more", and stop saying it at the ends */
.rgRow::before, .rgRow::after{
  content:""; position:absolute; top:0; bottom:10px; width:56px; z-index:2;
  pointer-events:none; opacity:0; transition:opacity var(--t2) var(--ease);
}
.rgRow::before{ left:0;  background:linear-gradient(to right, var(--bg), transparent); }
.rgRow::after{  right:0; background:linear-gradient(to left,  var(--bg), transparent); }
.rgRow[data-carousel-at="middle"]::before,
.rgRow[data-carousel-at="end"]::before{ opacity:1; }
.rgRow[data-carousel-at="middle"]::after,
.rgRow[data-carousel-at="start"]::after{ opacity:1; }

.rgRowArrow{
  position:absolute; top:calc(50% - 30px); z-index:3;
  width:40px; height:40px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--surface3); color:var(--text);
  border:1px solid var(--line3); cursor:pointer;
  box-shadow:var(--shadow2);
  opacity:0; transform:scale(.9);
  transition:opacity var(--t2) var(--ease), transform var(--t2) var(--easeOut),
             background var(--t1) var(--ease), border-color var(--t1) var(--ease);
}
.rgRowArrow svg{ width:19px; height:19px; }
.rgRowArrow--prev{ left:-6px; }
.rgRowArrow--next{ right:-6px; }
.rgRowArrow:hover{ background:var(--accent); border-color:var(--accentText); }
.rgRowArrow:disabled{ opacity:0 !important; pointer-events:none; }
/* they arrive on hover, and stay for a keyboard */
.rgRow:hover .rgRowArrow, .rgRow:focus-within .rgRowArrow{ opacity:1; transform:none; }
.rgRowArrow:focus-visible{ opacity:1; transform:none; outline:2px solid var(--accentHot); outline-offset:2px; }
/* nothing to scroll: no arrows, no fades, no clutter */
.rgRow[data-carousel-room="no"] .rgRowArrow{ display:none; }

/* a touch screen has no hover, and does not need arrows — it has a thumb */
@media (hover:none){
  .rgRowArrow{ display:none; }
  .rgRowTrack{ scroll-snap-type:x proximity; }
}

/* ============================================================
   THE DETAIL PASS
   A card on a black page needs more than a border to feel raised, and
   more than a colour change to feel pressable. Three things do it, and
   all three are restrained: a lift, a light edge, and the art gaining
   a little contrast under the cursor. Nothing scales more than 2%,
   nothing bounces, and every one of them is off for reduced motion
   because the duration tokens collapse to zero.
   ============================================================ */
.rgCard{ transition: transform var(--t2) var(--easeOut); }
.rgCardArt{
  position:relative; overflow:hidden; border-radius:var(--r16);
  background:var(--surface);
  box-shadow: 0 1px 0 rgba(255,255,255,.05), 0 10px 26px rgba(0,0,0,.45);
  transition: box-shadow var(--t2) var(--ease), transform var(--t2) var(--easeOut);
}
.rgCard--circle .rgCardArt{ border-radius:50%; }
.rgCardFrame{ transition: transform var(--t2) var(--easeOut); }
.rgCard:hover .rgCardFrame{ transform: translateY(-3px); }   /* art, badge and play lift together */
.rgCard:hover .rgCardFrame .rgCardArt{ transform:none; }
.rgCard:hover .rgCardArt{
  transform: translateY(-3px);
  box-shadow: 0 1px 0 rgba(255,255,255,.12), 0 20px 44px rgba(0,0,0,.62), 0 0 0 1px var(--accentLine);
}
.rgCard:hover .rgArt img{ filter: contrast(1.04) saturate(1.06); }
.rgArt img{ transition: filter var(--t2) var(--ease), transform var(--t3) var(--easeOut); }
.rgCard:hover .rgArt--cover img{ transform: scale(1.03); }

/* the play button arrives rather than being permanently in the way */
.rgPlay{
  opacity:0; transform: translateY(6px) scale(.94);
  transition: opacity var(--t2) var(--ease), transform var(--t2) var(--easeOut), background var(--t1) var(--ease);
}
.rgCard:hover .rgPlay, .rgCard:focus-within .rgPlay{ opacity:1; transform:none; }
.rgPlay:hover{ background: var(--accent); }
@media (hover:none){ .rgPlay{ opacity:1; transform:none; } }

/* titles: heavier and tighter, which is what reads as confident at a glance */
.rgCardTitle{ font-weight:900; letter-spacing:-.018em; }
.rgCardTitle a{ color:var(--text); text-decoration:none; }
.rgCardTitle a:hover{ color:var(--accentText); }
.rgCardMeta{ color:var(--muted2); font-weight:650; letter-spacing:.005em; }

/* a keyboard must see everything a mouse sees */
.rgCard a:focus-visible, .rgPlay:focus-visible, .rgFav:focus-visible{
  outline:2px solid var(--accentHot); outline-offset:3px; border-radius:8px;
}

/* the live dot is the one amber thing on the site, and it should pulse
   slowly enough to read as "on air" rather than as an alarm */
.rgBadge--live{ box-shadow:0 6px 18px rgba(226,27,35,.4); }
