@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&family=EB+Garamond:ital,wght@0,400;0,600;1,400&family=Inter:wght@400;500;600;700&display=swap');

:root{
  --bg:#202222;
  --mid:#2D2D2D;
  --cream:#FEE47D;
  --yellow:#D7E646;
  --white:#FFFFFF;
  --muted:#8d8d8d;
  --vhs-hover:#E4EAA0;
  --year-label:#313333;
  --black:#000000;
  --ink:#111111;
  --btn-hover:#eeeeee;
  --btn-off-text:#a8a8a8;  /* disabled filter button text */
  --border:#555555;
  --placeholder:#777777;
}

*{box-sizing:border-box;}

/* Responsive visibility utilities — !important + confined to their own
   media query so they always win over a component's own display:grid/flex
   without fighting it on specificity or source order. */
/* Mobile-only markup is hidden on wide screens only; a narrow landscape
   screen shows it too (desktop arrangement, mobile component sizes — see
   the landscape block at the end of this file). */
@media (min-width:1001px){
  .mobile-only{display:none !important;}
}
img, video{
  -webkit-user-drag:none;
  user-drag:none;
  -webkit-touch-callout:none;
  user-select:none;
  -webkit-user-select:none;
  -webkit-tap-highlight-color:transparent;
}
html,body{margin:0;padding:0;background:var(--bg);color:var(--white);
  font-family:'Inter',system-ui,sans-serif; height:100%; overflow:hidden; touch-action:none;
  /* This is an app-like canvas, not a text document — selection has no
     real use here, and the pointerdown handler in script.js that stops
     the ring from native-drag-ghosting also (as a side effect) stops a
     click from clearing an existing selection the normal way. Rather than
     special-case Ctrl+A, there's simply nothing left to select: it can't
     get stuck highlighted if it was never selectable to begin with. The
     search input is a real form control, so this doesn't affect typing or
     selecting text inside it. */
  user-select:none; -webkit-user-select:none;
}
button{font-family:inherit;}

/* ---------- background layer (behind everything, tied to selection) ---------- */
.bg-layer{
  position:fixed; inset:0;
  z-index:0;
  overflow:hidden;
  background:var(--bg);
}
.bg-layer img, .bg-layer video{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  opacity:0;
  filter:brightness(.55) saturate(.75);
  transition:opacity .8s ease;
}
.bg-layer img.visible, .bg-layer video.visible{opacity:.65;}
.bg-layer::after{
  content:'';
  position:absolute; inset:0;
  background:
    linear-gradient(90deg, var(--mid) 0%, rgba(45,45,45,0) 100%),
    radial-gradient(circle at 28% 55%, rgba(21,21,21,.025), rgba(21,21,21,.75) 75%);
}

/* ---------- layout shell ---------- */
.app{
  display:flex;
  /* width:100%, not 100vw: on notched iPhones in landscape, 100vw is wider
     than the area Safari actually lays the page out in (it counts the
     safe-area insets), so everything sized from it — this container, the
     absolutely-positioned controls pinned to its right edge, the detail
     panel — ended up pushed past the right edge of the screen. A percentage
     follows the real available width. */
  width:100%; height:100vh;
  position:relative;
  z-index:1;
}

.ring-panel{
  position:relative;
  flex:1 1 44%;
  min-width:300px;
  height:100vh;
  overflow:visible;
}

.ring-viewport{
  position:absolute; inset:0;
  overflow:visible;
  z-index:1;
  cursor:grab;
  user-select:none; -webkit-user-select:none;
  -webkit-user-drag:none; user-drag:none;
}
.ring-viewport:active{cursor:grabbing;}
.ring-viewport:focus-visible{outline:none;}

.ring-stage{
  position:absolute; left:0; top:0; width:0; height:0;
  user-select:none; -webkit-user-select:none;
  -webkit-user-drag:none; user-drag:none;
}
.ring-empty-msg{
  position:absolute;
  top:50%; left:50%;
  transform:translate(-50%,-50%);
  font-family:'Archivo Black',sans-serif;
  font-size:16px;
  letter-spacing:.03em;
  color:var(--muted);
  text-align:center;
  opacity:0;
  pointer-events:none;
  transition:opacity .2s ease;
}
.ring-empty-msg.visible{opacity:1;}

.vhs{
  position:absolute;
  left:0; top:0;
  user-select:none; -webkit-user-select:none;
  -webkit-user-drag:none; user-drag:none;
  background:transparent;
  /* No border / rounded clip: the VHS images may carry their own
     transparency, and a 1px outline or a 3px clip would show up around or
     cut into the artwork. The image defines the tape's shape. */
  transition:background .18s ease;
  will-change:transform;
  /* No cursor of its own — it inherits `grab`/`grabbing` from
     .ring-viewport below. The whole ring area (tapes included) is
     draggable the same way, so the cursor should read the same way
     everywhere on it; giving tapes their own `pointer` cursor was what
     made the clipped-off corner pixels (ring-viewport showing through)
     look like a glitch instead of just more of the same grab cursor. */
  pointer-events:auto;
}
.vhs:active{cursor:grabbing;}
.vhs.is-selected{
  background:transparent;
}
.vhs:focus-visible{outline:2px solid var(--white); outline-offset:2px;}

/* Hover indicator: an equilateral triangle sitting just to the left of the
   tape (the ring's-center side). This is a true SIBLING element, not a
   pseudo-element on .vhs — .vhs has a clip-path so its own hit area follows
   its rounded corners exactly, and a pseudo-element would be a descendant
   of that clipped box, getting clipped away right along with it. Kept
   perfectly in sync with its tape by script.js mirroring the tape's own
   width/height/transform onto this element every frame, and revealed only
   while that specific tape is hovered via the adjacent-sibling selector
   below (it immediately follows its .vhs in the DOM). Because the tape's
   whole box is rotated by its angleDeg — the same angle used to place it on
   the ring — "local left" on this un-rotated indicator always ends up
   pointing toward the ring's center, whatever the tape's position is. */
.vhs-indicator{
  position:absolute;
  left:0; top:0;
  pointer-events:none;
  will-change:transform;
}
.vhs-indicator::before{
  content:'';
  position:absolute;
  left:-24px;
  top:50%;
  transform:translateY(-50%);
  width:0;
  height:0;
  border-style:solid;
  border-width:8px 0 8px 14px;
  border-color:transparent transparent transparent var(--yellow);
  opacity:0;
  transition:opacity .18s ease;
}
/* Only on devices with a real hover pointer. On touch screens :hover sticks
   to the last tapped element, which left the triangle lit forever. Touch
   gets a press-only (:active) flash instead. */
@media (hover:hover) and (pointer:fine){
  .vhs:hover + .vhs-indicator::before{opacity:1;}
}
@media (hover:none), (pointer:coarse){
  .vhs:active + .vhs-indicator::before{opacity:1;}
}

.year-label{
  position:absolute;
  left:0; top:0;
  font-family:'Archivo Black',sans-serif;
  font-size:30px;
  color:var(--year-label);
  letter-spacing:.03em;
  white-space:nowrap;
  pointer-events:none;
  user-select:none; -webkit-user-select:none;
  transform-origin:center;
  will-change:transform;
}
/* Compact (phone) layouts use tapes 25px thick vs 53px on desktop (~0.47x),
   so the year labels shrink by the same ratio: 30px -> 14px. */
@media (max-width:1000px){
  .year-label{font-size:14px;}
}

/* ---------- controls (always top-left, above the ring) ---------- */
.controls{
  position:absolute; top:18px; right:18px;
  z-index:5;
  display:flex; flex-direction:column;
  gap:2px;
  width:460px;
}
.filter-toggle{
  border:1px solid var(--black);
  background:var(--white); color:var(--ink);
  font-weight:700; font-size:13px;
  padding:8px 0;
  cursor:pointer;
  letter-spacing:.01em;
  text-align:center;
  transition:background .15s ease, color .15s ease;
}
.filter-toggle.active{background:var(--yellow); color:var(--ink);}
.filter-body{display:flex; flex-direction:column; gap:2px;}
.btn-row{
  display:grid;
  grid-template-columns:repeat(3, 1fr);
  gap:2px;
}
.btn-row.type-row{
  grid-template-columns:repeat(5, 1fr);
}
.btn-row.mobile-top-row{grid-template-columns:1fr 1fr;}
.btn-row.mobile-role-row{grid-template-columns:repeat(2, 1fr);}
.btn-row.mobile-type-row{grid-template-columns:repeat(3, 1fr);}
.filter-btn{
  width:100%;
  border:1px solid var(--black);
  /* disabled look: dark (--mid) with dim text, so on/off is obvious at a glance */
  background:var(--mid); color:var(--btn-off-text);
  font-weight:700; font-size:13px;
  padding:8px 0;
  cursor:pointer;
  letter-spacing:.01em;
  text-align:center;
  transition:background .15s ease, color .15s ease;
}
.btn-row.type-row .filter-btn{font-size:11.5px; padding:8px 2px;}
.filter-btn.active{background:var(--yellow); color:var(--ink);}
/* second row (type buttons): cream instead of yellow when enabled, both the
   desktop row and the mobile .mobile-type-row */
.btn-row.type-row .filter-btn.active,
.btn-row.mobile-type-row .filter-btn.active{background:var(--cream); color:var(--ink);}
/* About: white when open (dark like the other buttons when closed) */
.filter-btn[data-static="about"].active{background:var(--white); color:var(--ink);}


.search-wrap{margin-top:2px;}
.search-input{
  width:100%;
  background:rgba(0,0,0,.35);
  border:1px solid var(--border);
  color:var(--white);
  font-size:12px;
  padding:7px 10px;
  outline:none;
}
.search-input::placeholder{color:var(--placeholder);}
.search-input:focus{border-color:var(--yellow);}

/* ---------- detail panel ---------- */
.detail-panel{
  position:relative;
  z-index:2;
  flex:1 1 56%;
  min-width:644px;
  height:100vh;
  overflow-y:auto;
  overflow-x:hidden;
  padding:0 48px;
  display:flex;
  gap:48px;
  align-items:center;
  justify-content:center;
}
.detail-panel.is-empty .poster-wrap,
.detail-panel.is-empty .info{
  display:none;
}
.poster-wrap{
  /* Was a rigid 300px. Now it can shrink (3x as eagerly as .info, so the
     poster gives way first) down to 150px when the detail panel is pinned
     at its min-width on a narrow window — otherwise .info got squeezed to
     its 200px minimum and its text wrapped. */
  flex:0 3 300px;
  width:300px;
  min-width:150px;
  display:flex;
  flex-direction:column;
  align-items:center;
}
.poster{
  width:100%; /* follows .poster-wrap (300px at most) */
  min-height:200px;
  border-radius:2px;
  position:relative;
  overflow:hidden;
  background:var(--black);
  box-shadow:0 12px 28px rgba(0,0,0,.45);
  cursor:pointer;
  user-select:none; -webkit-user-select:none;
  -webkit-tap-highlight-color:transparent;
  transition:opacity .25s ease;
}
.poster.has-image{
  min-height:0;
  /* Alpha PNGs: no black plate or rectangular shadow behind the image; the
     shadow follows the image's own alpha via drop-shadow on the <img>. */
  background:transparent;
  box-shadow:none;
  overflow:visible; /* don't clip the drop-shadow */
}
.poster.has-image .poster-img{filter:drop-shadow(0 12px 28px rgba(0,0,0,.45));}
.poster-img{
  display:block;
  width:100%;
  height:auto;
  opacity:0;
  user-select:none; -webkit-user-select:none;
  transition:opacity .25s ease;
}
.poster-img.visible{opacity:1;}
.poster-count{
  margin-top:10px;
  font-size:10px; letter-spacing:.08em;
  color:var(--muted);
  pointer-events:none;
}
.info{
  flex:1 1 400px; max-width:600px; min-width:200px; transition:opacity .2s ease;
  /* The rest of the page has selection turned off (see html,body above) —
     but this panel is the one place with real text worth copying (title,
     role/credit, tags, links), so it opts back in here. */
  user-select:text; -webkit-user-select:text;
}
/* {br} soft line break in a title (see renderTitle in script.js): ignored on
   desktop, a real line break on small screens. */
.br-soft{display:none;}
@media (max-width:1000px){
  .br-soft{display:inline;}
}
.info h1{
  font-family:'Archivo Black',sans-serif;
  font-size:clamp(19px,2vw,28px);
  margin:0 0 6px;
  line-height:1.1;
}
.info .episode-line{
  font-family:'Archivo Black',sans-serif;
  font-size:15px;
  letter-spacing:.04em;
  color:var(--yellow);
  margin-bottom:6px;
}
.info .episode-line:empty{display:none;}
.info .meta-line{
  color:var(--muted);
  font-size:14px;
  letter-spacing:.02em;
  margin-bottom:28px;
}
.field{
  display:flex; gap:18px;
  padding:12px 0;
  border-bottom:1px solid var(--mid);
  font-size:14px;
}
.field .k{
  flex:0 0 84px;
  color:var(--muted);
  font-size:11px;
  letter-spacing:.08em;
  text-transform:uppercase;
  padding-top:2px;
}
.field .v{font-weight:600;}
.info h1 em, .field .v em{font-style:italic;}
.tags{margin-top:18px; display:flex; flex-wrap:wrap; gap:6px;}
.tag-chip{
  font-size:11px; color:var(--muted);
  border:1px solid var(--mid);
  padding:3px 8px;
  border-radius:2px;
}
.links{display:flex; flex-wrap:wrap; gap:12px 22px; margin-top:26px;}
.links a{
  color:var(--white); text-decoration:none;
  font-weight:700; font-size:14px;
  border-bottom:2px solid var(--cream);
  padding-bottom:2px;
  white-space:nowrap;
}
.links a:hover{color:var(--cream);}

.hint{
  position:absolute; bottom:14px; left:18px; z-index:5;
  font-size:11px; color:var(--muted); letter-spacing:.02em;
  line-height:1.6;
}


.site-footer{
  position:fixed;
  left:50%; bottom:14px;
  transform:translateX(-50%);
  z-index:10;
  font-size:clamp(7.5px, 2.6vw, 11px);
  color:var(--muted);
  letter-spacing:.02em;
  text-align:center;
  max-width:96vw;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
  pointer-events:none;
}

.site-brand{
  position:fixed;
  left:50%; bottom:15px;
  transform:translateX(-50%);
  z-index:10;
  display:flex; align-items:center; gap:5px;
}
.brand-logo-wrap{
  position:relative;
  width:75px; height:75px;   /* source: 400x400 square */
}
.brand-logo{
  position:absolute; inset:0;
  width:75px; height:75px;
  object-fit:contain;
  cursor:pointer;
  /* no transition: the still and the video swap instantly, no fade */
}
.brand-logo-video{
  position:absolute; inset:0;
  opacity:0;
  pointer-events:none; /* the img on top handles hover detection */
  /* The video and the still use the same 75x75 box (object-fit:contain), so
     if the video's artwork looks smaller it's because the rendered frames
     have more empty margin around the logo than the still does. This scales
     the video up around its center to compensate. 1 = no change; tune it
     until the video's logo matches the still. */
  transform:scale(var(--logo-video-scale, 1.15));
  transform-origin:center;
}
.brand-logo-video.visible{opacity:1;}
/* While the hover video plays, hide the still image underneath it. */
.brand-logo-wrap.is-playing .brand-logo:not(.brand-logo-video){opacity:0;}
/* Stacked-alpha mode: the <video> only decodes; the <canvas> next to it is what's shown. */
.brand-logo-video[data-stacked-alpha]{opacity:0 !important;}
.brand-title{
  height:150px; width:auto;   /* source: 1920x817 — height-constrained, width follows */
  object-fit:contain;
}

/* ---------- responsive: stack on narrow PORTRAIT screens ---------- */
@media (max-width:1000px) and (orientation:portrait){
  /* No page scrollbar on mobile at all — html,body's base rule (top of
     file) is already overflow:hidden/height:100%, so this just stops
     reintroducing a scrollable page the way the old overflow-y:auto /
     height:auto override here used to. The layout below is sized to
     always fit within one fixed 100dvh screen instead (controls' natural
     height + two flex-grow panes splitting the remainder); .info keeps
     its own internal overflow-y:auto as the one deliberate scroll region
     for any single work's content that's genuinely too long. */
  .app{
    flex-direction:column; width:100%;
    height:100vh; height:100dvh;
    overflow:hidden;
  }
  .ring-panel{
    /* flex-grow, not a fixed/calc height — a fixed height (plus this
       panel's own margin-bottom and the stack above it) was what let the
       whole column's required height exceed the real screen on shorter
       phones, pushing the ring down past the visible area entirely (the
       old overflow-y:auto on html,body hid that by making the page
       scroll instead of clipping — removing that above means this has to
       actually fit now). Weighted higher than .detail-panel below since
       the ring is the primary control and needs the most room. */
    flex:2.2 1 auto; width:100%; min-width:0;
    min-height:120px;
    /* Keeps the ring clear of the fixed site-brand/footer overlaid on
       top of it — reduced from the old 56px now that this is flex-sized
       rather than competing with a fixed calc() for the same vh budget. */
    margin-bottom:34px;
  }
  .hint{display:none;}
  .detail-panel{
    flex:1 1 auto; width:100%; min-width:0;
    min-height:110px;
    overflow:hidden;
    padding:6px 10px;
    flex-direction:row;
    align-items:center;
    justify-content:center;
    gap:10px;
  }
  .poster-wrap{
    flex:0 0 auto; width:auto; max-width:120px;
    /* The poster is letterboxed (object-fit:contain) inside a box up to 120px
       wide, so there's invisible space left of it and between it and the
       info. Pulling the box left trades that for margin on the info's right
       edge: poster shifts ~5px left, info right edge gains ~5px. */
    margin-left:-10px;
    height:100%;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
  }
  .poster-count{display:none;} /* dropped on mobile — one more thing that varied per work for no real benefit here */
  .poster{
    /* Fixed aspect box instead of sizing to each image's own natural
       dimensions — a landscape VHS-spine thumbnail and a tall portrait
       poster used to produce very different heights here, which was the
       single biggest source of the row's height changing per work. */
    width:auto; height:100%; max-width:120px;
    min-height:0;
    background:transparent; /* was var(--black) — showed as a solid black
      letterboxing band above/below any poster image whose aspect ratio
      doesn't exactly match this fixed box; object-fit:contain just leaves
      that space empty against the page background instead. */
    box-shadow:none;
  }
  .poster.has-image .poster-img{filter:none;}
  .poster-img{
    width:100%; height:100%;
    object-fit:contain;
  }
  .info{
    flex:1 1 140px; max-width:210px; min-width:0;
    height:100%;
    overflow-y:auto;
    /* The global html,body touch-action:none (see top of file — it's what
       stops the ring-drag gesture from also panning/zooming the page)
       applies to any touch starting inside .info too unless overridden
       here: without this, CREDIT/STUDIO/links content past the fold was
       there but truly unreachable — no amount of overflow-y:auto scrolls
       if the touch gesture that would do it is blocked first. pan-y
       allows vertical scrolling specifically, nothing else. */
    touch-action:pan-y;
    -webkit-overflow-scrolling:touch;
    /* Vertically centers .info-inner (see below) the same "safe" way as
       the poster, but via the OLDER margin:auto flex trick instead of
       `justify-content:safe center` — that newer `safe` keyword isn't
       universally supported, and its fallback (plain `center`) is what
       clipped the title's first line last time: plain center clips
       equally from both ends on overflow, cutting whatever's at the top.
       margin:auto on a flex child has centered-when-it-fits/starts-at-
       the-top-when-it-doesn't behavior in every flexbox implementation,
       no keyword support needed. */
    display:flex;
    flex-direction:column;
  }
  .info-inner{
    width:100%;
    margin:auto 0;
  }
  .info h1{font-size:13px;
    /* Reserve room for a 2-line title at this font-size/line-height so
       switching between a 1-line and 2-line title doesn't change
       .info's own height — see the .detail-panel note below for why
       that height needs to stay put. */
    min-height:2.2em;
    display:flex; align-items:flex-end;
  }
  .info .episode-line{font-size:10px;}
  .info .meta-line{font-size:10px; margin-bottom:10px;}
  .field{
    padding:5px 0; font-size:10px;
    /* Base .field has gap:18px and .k locked to a flex-basis of 84px —
       both sized for the roomy desktop info column. In the ~150px-wide
       mobile one, that alone ate most of the row, squeezing the value
       into a sliver and forcing it to wrap more than it needed to. */
    gap:4px;
  }
  .field .k{font-size:9px; flex:0 0 40px;}
  .field .v{font-size:10px; letter-spacing:-.015em;}
  .tags{display:none;} /* tags hidden on mobile */
  .tag-chip{font-size:9px; padding:2px 6px;}
  .links{gap:6px 12px; margin-top:12px;}
  .links a{font-size:10px; border-bottom-width:1px; padding-bottom:1px;}
  .desktop-only{display:none !important;}

  .filter-toggle{font-size:11px; padding:6px 0;}
  .filter-btn{font-size:11px; padding:6px 0;}
  .btn-row.mobile-type-row .filter-btn{font-size:9px; padding:6px 1px;}

  .site-brand{gap:5px; bottom:10px;}
  .brand-logo-wrap{width:46px; height:46px;}
  .brand-logo{width:46px; height:46px;}
  .brand-title{height:60px;}
  .site-footer{font-size:clamp(5px, 1.6vw, 7px); bottom:6px;}

  /* Prevents the iOS long-press text-selection magnifier/loupe (which reads
     like a zoom gesture) from popping up over the info panel on mobile —
     desktop keeps selection (see .info above), this only turns it back off
     below the 1000px breakpoint. */
  .info{user-select:none; -webkit-user-select:none;}

  /* Match the search box's type size/height to the filter buttons next to
     it — it was noticeably taller and larger-type than its neighbors.
     (The viewport meta's maximum-scale=1/user-scalable=no plus the JS-level
     gesture blocking above are already doing the real zoom-prevention work,
     so this doesn't need to stay pinned at 16px+ the way a plain iOS fix
     normally would.) */
  .search-input{font-size:11px; padding:6px 10px;}

  /* ---- controls: in-flow full-width top bar on mobile (was an
     absolutely-positioned small box pinned to the top-right on desktop) —
     the Filters toggle + About button and the search box now sit
     side-by-side in one row spanning the screen width. The actual
     category/type checkboxes (.filter-body) drop out of this flow
     entirely (position:absolute) so opening/closing them never pushes
     the search box or shifts anything below. */
  .controls{
    position:relative;
    top:auto; right:auto;
    width:100%;
    display:flex;
    flex-direction:row;
    align-items:flex-start;
    flex-wrap:nowrap;
    gap:6px;
    padding:10px 10px 0;
  }
  .btn-row.mobile-top-row{
    flex:0 0 auto;
    width:auto;
    display:flex;
    gap:4px;
  }
  .btn-row.mobile-top-row .filter-toggle,
  .btn-row.mobile-top-row .filter-btn{
    width:auto;
    padding:6px 10px;
    white-space:nowrap;
  }
  .search-wrap{
    flex:1 1 auto;
    min-width:0;
    margin-top:0;
  }
  .filter-body{
    position:absolute;
    left:10px; right:10px; top:100%;
    background:var(--bg);
    z-index:6;
    /* border/padding/margin-top used to jump straight from the .open
       values to 0 the instant the class was removed, while max-height
       kept animating for another .25s — border gone, content pressed
       flat against the edges, box already shifted up, but still visibly
       shrinking: that mismatch between "snapped instantly" and "still
       animating" is the warped look on close. Giving them a real value
       at rest (a transparent 1px border, not none, so its WIDTH never
       changes — only border-color animates) and transitioning all of
       them together with max-height keeps the whole close in sync. */
    border:1px solid transparent;
    padding:0 8px;
    margin-top:0;
    max-height:0;
    overflow:hidden;
    transition:max-height .25s ease, padding .25s ease, margin-top .25s ease, border-color .25s ease;
  }
  .filter-body.open{
    max-height:70vh;
    padding:6px 8px;
    margin-top:6px;
    border-color:var(--border);
  }

  .vhs-indicator::before{
    left:-16px;
    border-width:5px 0 5px 9px;
  }

  /* Poster/info move to the TOP of the stack, ring to the BOTTOM — the
     ring's hub is now off-canvas below the screen (see CFG.mobileSelectedDeg
     in script.js) instead of off-canvas to the left, so the arc rises from
     the bottom edge right where a thumb naturally sits, and the detail
     panel reads first. Swapping `order` keeps index.html's markup order
     (ring, then detail-panel) intact — only the visual order changes. */
  .ring-panel{order:2;}
  .detail-panel{order:1;}
}

/* ---------- about overlay ---------- */
.about-overlay{
  position:fixed; inset:0;
  /* No explicit height here (no 100vh/100dvh) — `inset:0` alone on a
     `position:fixed` element already means top:0/right:0/bottom:0/left:0,
     so the browser computes the height live as "whatever reaches the
     real current bottom edge", continuously, every time the toolbar
     shows/hides. The explicit 100vh (and even 100dvh in some iOS
     versions/webviews) that used to be here instead pinned the box to a
     STATIC number computed once, which could come up short of the real
     visual viewport by however tall the toolbar was — showing as plain
     gray (no pattern, no icons) in exactly the bottom strip where the
     site-brand/footer sit, since that's the area past the short edge.
     inset:0 by itself has no such static snapshot to go stale. */
  z-index:4;
  /* Pattern lives directly on this element's own background now, not on a
     separate `::before` pseudo-element sized with `position:absolute;
     inset:0`. That extra layer was one more thing that could desync from
     this box's real height during the clip-path reveal/iOS toolbar
     resize — the content below the intro text (the footer icon row) was
     reportedly there and clickable but rendering as plain gray, i.e. the
     pattern layer wasn't painting over that area even though this
     element's own box did extend there. A background painted on the
     element itself always covers exactly that element's own border box,
     with nothing else to get out of sync. */
  background:var(--bg) url("assets/brand/queso-net_pattern.png") center / 880px auto repeat;
  display:flex; align-items:center; justify-content:center;
  /* Was overflow:hidden — if the intro text + footer icons together were
     ever taller than the screen, that didn't just hide the overflow, it
     made the footer icons unreachable to look at (while apparently still
     hit-testable) at the same time the old pseudo-element's background
     cut out below the fold. Scrolling means there's always a real way to
     reach anything that doesn't fit on one screen. */
  overflow-y:auto;
  overflow-x:hidden;
  clip-path:circle(0px at center);
  transition:clip-path .9s cubic-bezier(.65,0,.35,1);
  pointer-events:none;
}
.about-overlay.active{
  clip-path:circle(150% at center);
  pointer-events:auto;
}

.about-intro{
  position:relative;
  max-width:900px;
  padding:48px 32px;
  margin:auto; /* with the overlay's own align-items:center, this is what
                  keeps content centered when it fits AND lets it scroll
                  from the top when it doesn't — a flex item with auto
                  margins collapses them to 0 under overflow instead of
                  clipping its start off-screen. */
  text-align:center;
}
.about-intro p{
  font-family:'EB Garamond', Georgia, serif;
  font-size:20px;
  line-height:1.75;
  color:var(--white);
  margin:0;
}
.about-intro-link{
  color:var(--yellow);
  text-decoration:none;
  border-bottom:1px solid transparent;
}
.about-intro-link:hover{border-bottom-color:var(--yellow);}
.about-intro-footnote p{
  font-family:'EB Garamond', Georgia, serif;
  font-style:italic;
  color:var(--yellow);
  font-size:17px;
  margin:26px 0 0;
}
.about-footer-icons{
  margin-top:38px;
  display:flex; justify-content:center; gap:28px;
}
.footer-icon{color:var(--white); font-size:26px; transition:color .15s ease;}
.footer-icon:hover{color:var(--yellow);}

@media (max-width:1000px){
  .about-intro p{font-size:15px;}
  .about-intro-footnote p{font-size:14px;}
  .about-overlay{background-size:560px auto;}
  /* Phones: icons keep the smaller size/spacing (desktop is 26px / 28px). */
  .about-footer-icons{gap:20px;}
  .footer-icon{font-size:18px;}
}

/* Landscape but still smallish (a phone on its side, iPad mini/Air-class
   widths just under 1000px): same desktop design and arrangement, only
   with the desktop layout's fixed pixel minimums relaxed so it doesn't
   spill off the right edge — ring-panel(300)+detail-panel(644) alone is
   944px — and the poster/brand scaled so they fit a short screen. */
@media (max-width:1000px) and (orientation:landscape){
  /* Desktop ARRANGEMENT (ring left, poster/info right, controls
     top-right) at the MOBILE component sizes — everything below mirrors
     the sizes in the portrait block above. */
  .ring-panel{min-width:0;}
  /* Extra right padding nudges the (centered) poster+info block left by
     half of it (~20px). Raise the 52px to move it further left. */
  /* The ring side has a lot of empty room next to the poster, so let the
     detail panel reach 60px further left into it (and give the info column
     the extra width). pointer-events pass through the panel itself so the
     overlapped strip still drags the ring; only poster/info catch input. */
  .detail-panel{min-width:0; margin-left:-60px; padding:0 52px 0 12px; gap:12px; pointer-events:none;}
  .detail-panel .poster-wrap, .detail-panel .info{pointer-events:auto;}
  .poster-wrap{flex:0 0 120px; width:120px;}
  .poster-count{display:none;} /* same as portrait mobile */
  .poster{width:120px;}
  .info{
    flex:1 1 140px; max-width:300px; min-width:0;
    touch-action:pan-y; /* global touch-action:none would block scrolling a long info panel */
    user-select:none; -webkit-user-select:none;
  }
  .info h1{font-size:13px;}
  .info .episode-line{font-size:10px;}
  .info .meta-line{font-size:10px; margin-bottom:10px;}
  .field{padding:5px 0; font-size:10px; gap:4px;}
  .field .k{font-size:9px; flex:0 0 40px;}
  .field .v{font-size:10px; letter-spacing:-.015em;}
  .tags{display:none;} /* tags hidden on mobile */
  .tag-chip{font-size:9px; padding:2px 6px;}
  .links{gap:6px 12px; margin-top:12px;}
  .links a{font-size:10px; border-bottom-width:1px; padding-bottom:1px;}

  /* Collapsed controls (mobile markup) instead of the full desktop rows,
     kept top-right where the desktop controls sit. */
  .desktop-only{display:none !important;}
  .controls{
    top:10px; right:10px;
    width:320px; max-width:50%;
    flex-direction:row; align-items:flex-start; flex-wrap:nowrap; gap:6px;
  }
  .btn-row.mobile-top-row{flex:0 0 auto; width:auto; display:flex; gap:4px;}
  .btn-row.mobile-top-row .filter-toggle,
  .btn-row.mobile-top-row .filter-btn{width:auto; padding:6px 10px; white-space:nowrap;}
  .filter-toggle{font-size:11px;}
  .filter-btn{font-size:11px; padding:6px 0;}
  .btn-row.mobile-type-row .filter-btn{font-size:9px; padding:6px 1px;}
  .search-wrap{flex:1 1 auto; min-width:0; margin-top:0;}
  .search-input{font-size:11px; padding:6px 10px;}
  .filter-body{
    position:absolute; left:0; right:0; top:100%;
    background:var(--bg); z-index:6;
    border:1px solid transparent; padding:0 8px; margin-top:0;
    max-height:0; overflow:hidden;
    transition:max-height .25s ease, padding .25s ease, margin-top .25s ease, border-color .25s ease;
  }
  .filter-body.open{max-height:70vh; padding:6px 8px; margin-top:6px; border-color:var(--border);}

  .vhs-indicator::before{left:-16px; border-width:5px 0 5px 9px;}

  /* Brand logo + title move to the top, immediately LEFT of the controls,
     and are scaled to exactly the controls' row height (--ctl-h) so they
     line up with the filter buttons/search box. The controls are pinned
     top-right at width 320px (max 50% of the screen), so the brand's right
     edge sits that far in, plus a small gap. */
  /* --brand-h: title height (logo follows at 46:60). Larger than the
     controls' own height now, so the brand is vertically centered on the
     controls row (see .site-brand top below) instead of top-aligned. */
  :root{--ctl-h:28px; --brand-h:40px;}
  .btn-row.mobile-top-row .filter-toggle,
  .btn-row.mobile-top-row .filter-btn,
  .search-input{
    height:var(--ctl-h);
    padding-top:0; padding-bottom:0;
    line-height:1;
  }
  .site-brand{
    top:calc(10px + (var(--ctl-h) - var(--brand-h)) / 2); bottom:auto;
    left:auto; transform:none;
    right:calc(10px + min(320px, 50%) + 8px);
    gap:4px;
  }
  /* Title is the taller of the two, so IT matches the controls' height, and
     the logo keeps the portrait-mobile logo:title ratio (46:60) relative to
     it, instead of both being forced to the same height. */
  .brand-title{height:var(--brand-h);}
  .brand-logo-wrap, .brand-logo{
    width:calc(var(--brand-h) * 46 / 60);
    height:calc(var(--brand-h) * 46 / 60);
  }
  .site-footer{font-size:clamp(5px, 1.6vw, 7px); bottom:6px;}
  .hint{display:none;}
}

/* ---------- phones: label column sizes to the longest key ----------
   Keys like AFFILIATE / ORGANIZER / CONCEPT are longer than the fixed 40px
   label column and ran into their values. On phones the rows now share one
   grid: the label column is as wide as the longest key in that panel (never
   narrower than 40px), so values stay aligned and short-key works (ROLE,
   CREDIT, STUDIO) look exactly as before. */
@media (max-width:1000px){
  .field .k{letter-spacing:.05em;}
}
@supports (grid-template-columns: subgrid){
  @media (max-width:1000px){
    .fields{display:grid; grid-template-columns:minmax(40px,max-content) minmax(0,1fr); column-gap:6px;}
    .fields .field{display:grid; grid-template-columns:subgrid; grid-column:1 / -1; column-gap:6px;}
    .fields .field .k{flex:none; width:auto;}
  }
}
@supports not (grid-template-columns: subgrid){
  @media (max-width:1000px){
    .field .k{flex:0 0 58px;}
  }
}
