/* ShrikeGames: one stylesheet for the whole site.
 *
 * Monochrome drawn from the logo, with a single red accent. Thumbnails supply
 * every other colour on the page; the accent is reserved for links, focus and
 * the current page. Every ratio below was measured, not judged:
 *
 *   light  accent #c0261f on #f7f7f8 = 5.54:1   (AA body text)
 *   dark   accent #f2635a on #0e0f11 = 6.13:1   (AA body text)
 *   muted  #5b5f66 on paper = 5.99:1   /  #a4a9b2 on dark = 8.12:1
 *
 * No state is signalled by colour alone: the current nav item also carries an
 * underline, and every interactive element keeps a visible focus ring.
 */

/* ---------------------------------------------------------------- tokens */

:root {
  color-scheme: light;

  --paper: #f7f7f8;
  --card: #ffffff;
  --ink: #101114;
  --muted: #5b5f66;
  --hairline: #e3e3e6;
  --rule: #c9cbd0;
  --accent: #c0261f;
  --accent-ink: #ffffff;      /* text on an accent fill */
  --shadow: 0 1px 2px rgba(16, 17, 20, 0.06), 0 8px 24px rgba(16, 17, 20, 0.06);

  --sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
          "Hiragino Kaku Gothic ProN", "Yu Gothic", "Noto Sans JP", Meiryo, sans-serif;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;

  --gutter: clamp(1rem, 4vw, 2.5rem);
  --measure: 62ch;
  --radius: 4px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper: #0e0f11;
    --card: #17181b;
    --ink: #f2f3f5;
    --muted: #a4a9b2;
    --hairline: #26282c;
    --rule: #3a3d43;
    --accent: #f2635a;
    --accent-ink: #140605;
    --shadow: none;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: #0e0f11;
  --card: #17181b;
  --ink: #f2f3f5;
  --muted: #a4a9b2;
  --hairline: #26282c;
  --rule: #3a3d43;
  --accent: #f2635a;
  --accent-ink: #140605;
  --shadow: none;
}

/* ------------------------------------------------------------------ base */

*, *::before, *::after { box-sizing: border-box; }

/* [hidden] comes from the UA stylesheet as display:none, so any author rule
   setting display on the same element silently wins and the element stays on
   screen. Everything filtered here (.card, .songrow, .streamrow) sets display,
   so this has to outrank them. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

a { color: var(--accent); text-underline-offset: 0.18em; }
a:hover { text-decoration-thickness: 2px; }

/* One ring, everywhere, always visible. */
:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Japanese sets tighter than Latin and counts characters, not words. */
:root[lang="ja"] body { line-height: 1.85; }
:root[lang="ja"] .prose { max-width: 44em; }
:root[lang="ja"] .eyebrow,
:root[lang="ja"] .btn,
:root[lang="ja"] .nav a { letter-spacing: 0.02em; text-transform: none; }

/* --------------------------------------------------------------- headings */

h1, h2, h3 {
  margin: 0;
  line-height: 1.1;
  letter-spacing: -0.025em;
  font-weight: 800;
  text-wrap: balance;
}
:root[lang="ja"] h1,
:root[lang="ja"] h2,
:root[lang="ja"] h3 { letter-spacing: -0.005em; line-height: 1.3; }

h1 { font-size: clamp(2.25rem, 1.4rem + 4.2vw, 4.5rem); }
h2 { font-size: clamp(1.5rem, 1.2rem + 1.5vw, 2.25rem); }
h3 { font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.01em; }

.eyebrow {
  margin: 0 0 0.75rem;
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
}

.prose { max-width: var(--measure); color: var(--muted); }
.prose strong { color: var(--ink); font-weight: 650; }

/* ------------------------------------------------------------ a11y chrome */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--paper);
  font-weight: 600;
}
.skip:focus { left: 0; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------------------------------------------------------------- layout */

.wrap {
  width: min(1200px, 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(2.5rem, 6vw, 4.5rem); }
.section + .section { border-top: 1px solid var(--hairline); }

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  margin-bottom: clamp(1.25rem, 3vw, 2rem);
}

/* ---------------------------------------------------------------- header */

.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--hairline);
}
@supports not (backdrop-filter: blur(2px)) { .masthead { background: var(--paper); } }

.masthead-inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 60px;
  padding-block: 0.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: 1.0625rem;
  white-space: nowrap;
}
.brand img { width: 32px; height: 32px; border-radius: 50%; }

.nav {
  display: flex;
  gap: 0.25rem;
  margin-left: auto;
  align-items: center;
}
.nav a {
  display: inline-flex;
  white-space: nowrap;
  align-items: center;
  min-height: 44px;
  padding-inline: 0.75rem;
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9375rem;
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--accent); }
/* Current page: accent AND an underline: never colour alone. */
.nav a[aria-current="page"] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* --------------------------------------------------------- language switch */

/* The theme and language switches travel as one block, so exactly one element
   after the brand ever claims the header's free space. When they were separate
   siblings both took `margin-left: auto` and the space split between them,
   stranding the nav mid-header; wrapping them makes that unrepresentable. On a
   narrow screen the pair wraps as a unit rather than taking a row each. */
.switches { display: none; }
.js .switches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-left: auto;
}
.js .nav + .switches { margin-left: 0; }   /* the nav is already doing the pushing */

.langswitch {
  display: inline-flex;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
}
.langswitch button {
  appearance: none;
  white-space: nowrap;
  min-height: 36px;
  padding-inline: 0.7rem;
  border: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  cursor: pointer;
}
.langswitch button + button { border-left: 1px solid var(--rule); }
.langswitch button[aria-pressed="true"] { background: var(--ink); color: var(--paper); }
.langswitch button:hover:not([aria-pressed="true"]) { color: var(--ink); }

/* The theme control is the same component as the language switch, so the two read
   as one set. Its buttons carry an icon and a word; the icon is decorative. */
.themeswitch button { display: inline-flex; align-items: center; gap: 0.3rem; }
.themeswitch-icon { font-size: 0.9375rem; line-height: 1; }

/* Hover has to be visible on the unpressed half too, or the control looks inert
   until it is clicked. */
.langswitch button:hover:not([aria-pressed="true"]) { background: var(--hairline); }

/* ------------------------------------------------------------------- hero */

.hero { padding-block: clamp(2.5rem, 8vw, 6rem); }
.hero-grid {
  display: grid;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  grid-template-columns: 1fr;
}
.hero-mark { width: clamp(96px, 18vw, 168px); height: auto; }

/* The daily upload cadence is the channel's strongest claim, so it leads the
   hero rather than hiding in the paragraph. */
.kicker {
  display: inline-block;
  margin: 0 0 0.9rem;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
:root[lang="ja"] .kicker { letter-spacing: 0.08em; text-transform: none; }
.hero p { margin: 1.25rem 0 0; font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem); }

.actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 48px;
  padding-inline: 1.25rem;
  border-radius: var(--radius);
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--paper);
  font-weight: 650;
  font-size: 0.9375rem;
  text-decoration: none;
  cursor: pointer;
}
.btn:hover { background: transparent; color: var(--ink); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--rule); }
.btn--ghost:hover { border-color: var(--ink); background: transparent; }

/* ------------------------------------------------------------------ cards */

.grid {
  display: grid;
  gap: clamp(1rem, 2.5vw, 1.75rem);
  grid-template-columns: 1fr;
}

.card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  overflow: hidden;
}
.card:hover { border-color: var(--rule); }
.card:focus-within { outline: 3px solid var(--accent); outline-offset: 3px; }

/* aspect-ratio reserves the space, so nothing jumps as thumbnails arrive. */
.card-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--hairline);
  overflow: hidden;
}
/* Absolute, not height:100%: a percentage height against an aspect-ratio box
   does not resolve everywhere, and the fallback leaves YouTube's 4:3 hqdefault
   letterboxed inside the card instead of filling it. */
.card-thumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-duration {
  position: absolute;
  right: 0.5rem;
  bottom: 0.5rem;
  padding: 0.1rem 0.4rem;
  border-radius: 3px;
  background: rgba(8, 9, 11, 0.82);
  color: #fff;
  font-family: var(--mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

.card-body { padding: 0.875rem 1rem 1.125rem; display: flex; flex-direction: column; gap: 0.4rem; }

.card-title { margin: 0; font-size: 1rem; font-weight: 650; line-height: 1.35; letter-spacing: -0.01em; }
.card-title a { color: var(--ink); text-decoration: none; }
.card-title a:hover { color: var(--accent); text-decoration: underline; }
/* The whole card is clickable, but the link text stays the accessible name. */
.card-title a::after { content: ""; position: absolute; inset: 0; }
.card { position: relative; }

.card-meta {
  margin: 0;
  color: var(--muted);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}
.card-meta span + span::before { content: " · "; }

.tags { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.15rem; }
.tag {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  padding: 0.15rem 0.45rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--muted);
}

/* ----------------------------------------------------------------- search */

.toolbar { display: none; }
.js .toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 1.5rem;
}
.field {
  flex: 1 1 16rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 48px;
  padding-inline: 0.875rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
}
.field:focus-within { outline: 3px solid var(--accent); outline-offset: 2px; }
.field input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  padding-block: 0.5rem;
}
.field input:focus { outline: none; }

.sortbar { display: inline-flex; gap: 0.25rem; }
.sortbar button {
  appearance: none;
  min-height: 44px;
  padding-inline: 0.9rem;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  cursor: pointer;
}
.sortbar button[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.status { color: var(--muted); font-size: 0.875rem; margin: 0 0 1rem; }
.empty { padding: 3rem 1rem; text-align: center; color: var(--muted); }

/* ------------------------------------------------------------------ facts */

.facts {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  margin-top: 2.5rem;
  grid-template-columns: 1fr;
}
.fact {
  padding-top: 1.25rem;
  border-top: 2px solid var(--ink);
}
.fact h3 { margin-bottom: 0.5rem; }
.fact p { margin: 0 0 0.5rem; color: var(--muted); max-width: 46ch; }
.fact-note { font-size: 0.9375rem; }
:root[lang="ja"] .fact p { max-width: 34em; }

@media (min-width: 700px) { .facts { grid-template-columns: repeat(2, 1fr); } }

/* ------------------------------------------------------------------ clips */

.field--select { flex: 0 1 12rem; padding-inline: 0; }
.sortfield { flex: 0 1 14rem; }
:root[lang="ja"] .sortfield { flex-basis: 16rem; }
.field--select select {
  width: 100%;
  min-height: 46px;
  padding-inline: 0.875rem;
  border: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}
.field--select select:focus { outline: none; }

.clips {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
  /* Each card keeps its own height. Without this, playing one clip stretches
     its neighbour to match and the neighbour's contents spread out to fill
     the gap. */
  align-items: start;
}
.clip {
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 0.875rem 1rem;
  display: grid;
  gap: 0.5rem;
  align-content: start;   /* pack to the top rather than distributing */
}
.clip-name { margin: 0; font-weight: 650; word-break: break-word; }
.clip-meta { margin: 0; color: var(--muted); font-size: 0.8125rem; font-variant-numeric: tabular-nums; }
.clip-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.clip-actions .btn { min-height: 44px; font-size: 0.875rem; }
.clip-video { width: 100%; aspect-ratio: 16 / 9; max-height: 60vh; background: #000;
               border-radius: var(--radius); display: block; }

/* Stands in for a thumbnail: same shape as the video that replaces it, so the
   card does not jump when it loads. */
.clip-stage {
  appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  padding: 0;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background:
    repeating-linear-gradient(45deg, transparent 0 10px,
      color-mix(in srgb, var(--ink) 4%, transparent) 10px 20px),
    var(--paper);
  color: var(--ink);
  cursor: pointer;
}
.clip-stage { position: relative; overflow: hidden; }
.clip-stage:hover { border-color: var(--accent); color: var(--accent); }

/* The lazily loaded first frame, sitting behind the play glyph. */
.clip-preview {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
}
/* The glyph must stay readable over an unknown frame, so it carries its own
   disc rather than trusting the video to be dark. */
.clip-glyph {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  background: rgba(8, 9, 11, 0.62);
  color: #fff;
  font-size: 1.4rem;
  line-height: 1;
  padding-left: 0.15em;
}
.clip-stage.has-preview { background: #000; border-color: var(--rule); }
.clip-stage:hover .clip-glyph { background: var(--accent); color: var(--accent-ink); }
.clip-stage.is-loading .clip-glyph { opacity: 0.4; }
.clip-stage.is-error { border-color: var(--rule); }
.clip-note { font-family: var(--mono); font-size: 0.8125rem; margin-left: 0.5rem; }

@media (min-width: 900px) { .clips { grid-template-columns: repeat(2, 1fr); } }

/* -------------------------------------------------------------- setlists */

.songlist, .streamlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }

.songrow, .streamrow {
  border-top: 1px solid var(--hairline);
  padding-top: 0.875rem;
  display: grid;
  gap: 0.5rem;
}
.songrow-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }
.songrow-title { font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.01em; margin: 0; }
.songrow-artist { margin: 0; color: var(--muted); font-size: 0.9375rem; }
.songrow-views {
  margin: 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}
.songrow-count {
  margin: 0 0 0 auto;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}

/* Each take is a link straight to its second in the video. */
.takes { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.375rem; }
.takes a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 32px;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--ink);
  text-decoration: none;
  font-size: 0.8125rem;
}
.takes a:hover { border-color: var(--accent); color: var(--accent); }
.take-date, .take-stamp {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.takes a:hover .take-stamp, .takes a:hover .take-date { color: inherit; }

.takes--wide { flex-direction: column; align-items: stretch; gap: 0.25rem; }
.takes--wide a { border-radius: var(--radius); justify-content: flex-start; }
.takes--wide .take-song { font-weight: 600; }
.takes--wide .take-artist { color: var(--muted); margin-left: auto; text-align: right; }

.error { padding-block: clamp(3rem, 10vw, 7rem); }
.error .eyebrow { font-size: 0.8125rem; letter-spacing: 0.2em; }
.error h1 { margin-bottom: 1rem; }
.error-latest { margin-top: 3rem; padding-top: 1.75rem; border-top: 1px solid var(--hairline); }
.error-latest .takes { flex-direction: column; align-items: stretch; gap: 0.25rem; }
.error-latest .takes a { border-radius: var(--radius); }

/* ----------------------------------------------------------------- footer */

.foot {
  border-top: 1px solid var(--hairline);
  padding-block: 2.5rem 3.5rem;
  color: var(--muted);
  font-size: 0.875rem;
}
.foot-links { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin-bottom: 1.25rem; }
.foot-links a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;          /* WCAG 2.5.8 target size; these are standalone links,
                                not links inside a sentence, so the exception does
                                not apply to them. */
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
}
.foot-links a:hover { color: var(--accent); text-decoration: underline; }

/* -------------------------------------------------------------- responsive */

@media (min-width: 600px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 960px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .grid--wide { grid-template-columns: repeat(4, 1fr); }
  .hero-grid { grid-template-columns: auto 1fr; }
}

/* The nav needs its own row long before phone widths: at 200% zoom a desktop
   window behaves like a ~640px viewport, and the brand and nav collide there. */
/* The nav drops to its own row while there is still room for the brand and both
   switches beside each other. At 760px it left the switches ~220px to fit 304px
   of controls, so they wrapped into two rows and the header grew a step taller on
   exactly the widths a tablet uses. 940px is measured, not guessed: it is
   the narrowest width at which brand, nav and both switches share a line. */
@media (max-width: 940px) {
  .masthead-inner { flex-wrap: wrap; row-gap: 0.25rem; }
  .nav {
    order: 3;
    width: 100%;
    margin-left: 0;
    overflow-x: auto;
    scrollbar-width: none;
    border-top: 1px solid var(--hairline);
  }
  .nav::-webkit-scrollbar { display: none; }
  .nav a { padding-inline: 0.6rem; font-size: 0.875rem; }
  .brand span { font-size: 1rem; }
}

@media (max-width: 480px) {
  /* Below this the switches no longer fit beside the wordmark, so they take a row
     of their own rather than competing for the remainder of the brand's line. That
     also makes the alignment identical on every page: sharing the row left them
     pushed right on a page with no nav and pulled left on a page with one, and
     the leftover width was tight enough that a few pixels of Japanese text tipped
     them onto two rows. */
  .js .switches {
    flex: 1 1 100%;          /* a flex item takes its line from flex-basis, not width */
    margin-left: 0;
    gap: 0.25rem;
  }
  /* At 320px the row is 273px wide and the two groups came to 273.7px, so they
     wrapped on a rounding error. The padding below leaves about 10px of slack,
     which is what keeps a slightly wider rendering of the Japanese labels on one
     line. Targets stay well over the 24px minimum: these buttons are 36px tall. */
  .langswitch button { padding-inline: 0.4rem; }
  .themeswitch button { gap: 0.15rem; }
  .themeswitch-icon { font-size: 0.875rem; }
}

@media print {
  .masthead, .switches, .toolbar, .skip { display: none; }
  body { background: #fff; color: #000; }
}
