/* 06-shell.css — タブ型の画面（ヘッダー・タブ・ホーム・このサイトについて）
 *
 * style.css を分けたもの。元は1本の7,600行だった。
 * ⚠️ 読み込む順番を変えないこと。番号の順に重ねることで、
 *    分ける前とまったく同じ見た目になる。あとの番号が勝つ。
 * ⚠️ 新しい指定をここの先頭に足さないこと。
 *    打ち消し合っている指定があるので、置き場所で結果が変わる。
 */

/* ── FAB ──
   バーそのものを原色で塗り、アイコンと文字を読める色にする。
   アイコンを原色の文字色にすると、明るいメンバー色で見えなくなるため。 */
.is-member-page .fab-container {
    background: var(--member-brand, var(--main-accent));
    border-top-color: var(--member-brand, var(--main-accent));
}

.is-member-page .fab-btn,
.is-member-page .fab-btn svg {
    color: var(--member-ink, #111);
    /* 既定の白い下地を消して、バーのメンバー色を活かす */
    background: transparent;
    border-color: transparent;
    box-shadow: none;
}

.is-member-page .fab-btn span {
    color: var(--member-ink, #111);
    opacity: 0.85;
}

/* PCのFABは丸い浮きボタンなので、1つずつ塗る */
@media (min-width: 769px) {
    .is-member-page .fab-container {
        background: transparent;
        border-top-color: transparent;
    }

    .is-member-page .fab-btn {
        background: var(--member-brand, var(--main-accent));
        border-color: var(--member-brand, var(--main-accent));
    }
}

/* ══════════════════════════════════════════
   タブ型の画面（app.html）
   下のタブバーの上にプレイヤーが乗り、その上に本文が入る。
   ══════════════════════════════════════════ */
#app-shell {
    max-width: 980px;
    margin: 0 auto;
    padding: 0 16px;
    /* ⚠️ body が display:flex なので、これが無いと flex アイテムの
       「最小幅は中身の最小幅」という既定が効いて画面幅まで縮まない。
       新着の横スクロールなど中身が広い箇所があるため、はみ出しの原因になる。 */
    width: 100%;
    min-width: 0;
    /* 下のタブバーとプレイヤーに隠れないよう余白をとる */
    /* 下に重なる帯（タブバー＋プレイヤー）のぶんだけ空ける。
   ⚠️ 余分に足さないこと。いちばん下まで送ったときに、その余りがそのまま空白として見える。 */
    padding-bottom: calc(var(--app-tabs-h, 62px) + var(--jb-player-h, 0px));
}

.app-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 14px 0 10px;
}

.app-brand {
    display: flex;
    flex-direction: column;
    gap: 2px;
    text-decoration: none;
    color: var(--text-color);
    min-width: 0;
}

.app-brand-name {
    font-family: 'Montserrat', sans-serif;
    font-weight: 900;
    font-size: 1rem;
    letter-spacing: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-brand-sub {
    font-size: 0.66rem;
    opacity: 0.65;
    letter-spacing: 1px;
}

.app-header .theme-toggle { flex: 0 0 auto; }

.app-view { min-height: 60vh; }
.app-loading { padding: 40px 0; text-align: center; opacity: 0.6; }

.app-intro {
    font-size: 0.84rem;
    line-height: 1.7;
    opacity: 0.85;
    margin-bottom: 24px;
}

.app-footer { margin-top: 24px; }

/* ── 下のタブバー ── */
.app-tabs {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9999;
    display: flex;
    justify-content: center;
    gap: 0;
    padding: 6px 8px;
    padding-bottom: max(6px, env(safe-area-inset-bottom));
    background: var(--bg-color);
    border-top: 1px solid var(--border-color);
}

.app-tab {
    flex: 1 1 0;
    max-width: 140px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 6px 4px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-decoration: none;
    color: var(--text-color);
    opacity: 0.55;
    border-radius: 12px;
}

.app-tab.is-on {
    opacity: 1;
    color: var(--main-accent);
}

.app-tab:hover { opacity: 1; }

/* ── 共通の見出し ── */
.sh-section { margin-bottom: 30px; }

.sh-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 12px;
}

.sh-head h2 {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 1px;
}

.sh-note {
    font-size: 0.76rem;
    opacity: 0.7;
    margin-bottom: 10px;
    line-height: 1.6;
}

.sh-empty {
    padding: 40px 0;
    text-align: center;
    font-size: 0.85rem;
    opacity: 0.6;
}

/* ── 新着（横スクロール） ── */
.sh-rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 152px;
    gap: 12px;
    overflow-x: auto;
    /* 端が切れて見えるほうが「横に続く」と分かる */
    padding-bottom: 6px;
    scroll-snap-type: x proximity;
}

.sh-card {
    scroll-snap-align: start;
    cursor: pointer;
    min-width: 0;
}

.sh-card-thumb {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: 8px;
    background: #000;
    display: block;
}

.sh-card-date { font-size: 0.66rem; opacity: 0.6; margin-top: 6px; }

.sh-card-title {
    font-size: 0.82rem;
    font-weight: 700;
    line-height: 1.35;
    margin-top: 2px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.sh-card-sub {
    font-size: 0.68rem;
    opacity: 0.7;
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ── メンバーカード ── */
.sh-members {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr));
    gap: 10px;
}



/* ── ランダム再生 ── */
.sh-random-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
}

.sh-random-row .jb-select { flex: 0 0 110px; width: 110px; border-radius: 999px; }
.sh-random-row .jb-hero-btn { flex: 1 1 auto; width: auto; }

/* ── 統計のサブタブ ── */
.sh-stats-tabs {
    overflow-x: auto;
    flex-wrap: nowrap;
}

.sh-stats-tabs .jb-tab { flex: 0 0 auto; }

/* タブ型の画面ではプレイヤーをタブバーの上に置く */
#app-shell ~ .jb-player,
body:has(#app-shell) .jb-player {
    bottom: var(--app-tabs-h, 62px);
}

@media (min-width: 769px) {
    .app-brand-name { font-size: 1.15rem; }
    .sh-rail { grid-auto-columns: 190px; }
}

/* ⚠️ hidden 属性は必ず効かせること。
   PC用の .jb-player:not(.is-mini){display:flex} が既定の [hidden]{display:none} に
   勝ってしまい、再生前からプレイヤーが出てしまう。 */
.jb-player[hidden] { display: none !important; }

/* ══════════════════════════════════════════
   タブ型の画面 — 見た目の作り直し
   ──────────────────────────────────────────
   このサイトが元から持っている作り（Montserratの大文字見出し、
   ガラス調のカード、シアンのアクセント、ユニットごとの発光）に寄せる。
   角は丸めすぎず、面で塗らずに「線と光」で見せるのが当サイトの調子。
   ══════════════════════════════════════════ */

/* ── ヘッダー ── */
.app-header {
    position: relative;
    padding: 18px 0 14px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 22px;
}

/* 見出しの下に走る細い光の線 */
.app-header::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: -1px;
    width: 96px;
    height: 1px;
    background: linear-gradient(to right, var(--main-accent), transparent);
}

.app-brand-name {
    font-family: 'Montserrat', sans-serif;
    font-weight: 900;
    font-size: 1.05rem;
    letter-spacing: 2px;
    text-transform: uppercase;
}

.app-brand-sub {
    font-size: 0.62rem;
    letter-spacing: 2px;
    opacity: 0.5;
}

/* ── 見出し（英字＋日本語） ── */
.sh-head {
    display: block;
    margin-bottom: 14px;
    padding-left: 12px;
    border-left: 3px solid var(--main-accent);
}

.sh-head-en {
    margin: 0;
    font-family: 'Montserrat', sans-serif;
    font-size: 1.15rem;
    font-weight: 900;
    letter-spacing: 3px;
    text-transform: uppercase;
    line-height: 1.2;
}

.sh-head-ja {
    margin: 2px 0 0;
    font-size: 0.7rem;
    letter-spacing: 1px;
    opacity: 0.6;
}

.sh-section { margin-bottom: 38px; }

/* ── 新着カード ── */
.sh-rail { gap: 14px; }

.sh-card-thumb-wrap {
    position: relative;
    border-radius: 4px;
    overflow: hidden;
    /* 角を落として面を作る。丸角一辺倒にしないための処理 */
    clip-path: polygon(0 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%);
}

.sh-card-thumb { border-radius: 0; }

/* 乗せたときだけ再生の印を出す */
.sh-card-play {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--bg-color);
    background: rgba(0, 0, 0, 0.35);
    opacity: 0;
    transition: opacity 0.2s ease;
}

.sh-card-play svg {
    padding: 9px;
    background: var(--main-accent);
    border-radius: 50%;
}

.sh-card:hover .sh-card-play { opacity: 1; }

.sh-card-date {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.62rem;
    letter-spacing: 1px;
    color: var(--main-accent);
    opacity: 0.85;
    margin-top: 8px;
}

.sh-card-title { font-size: 0.84rem; }

/* ── ユニットとメンバー ── */
.sh-unit { margin-bottom: 26px; }

/* 既存の .unit-label をそのまま使うが、この画面では少し小さく */
.sh-unit .unit-label {
    font-size: 1.25rem;
    letter-spacing: 5px;
    margin-bottom: 12px;
}

.sh-members {
    display: grid;
    /* ⚠️ auto-fill にしないこと。4人に対して空の列が作られ、右側が空く
       （769〜1023px の幅で起きていた）。auto-fit なら空の列が潰れる。 */
    grid-template-columns: repeat(auto-fit, minmax(min(158px, 100%), 1fr));
    gap: 10px;
}

/* メンバーは「面で塗る」のではなく、左端の色帯と発光で示す。
   参考にした他サイトとの違いが出る部分であり、
   ライトモードでも色が沈まないという実利もある。 */
.sh-member {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 13px 14px 13px 18px;
    font-family: inherit;
    text-align: left;
    color: var(--text-color);
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    overflow: hidden;
    cursor: pointer;
    transition: border-color 0.25s ease, transform 0.25s ease;
}

.sh-member-bar {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 4px;
    background: var(--c, var(--main-accent));
    box-shadow: 0 0 10px var(--c, var(--main-accent));
}

.sh-member:hover {
    border-color: var(--c, var(--main-accent));
    transform: translateY(-2px);
}

.sh-member-name {
    font-size: 0.9rem;
    font-weight: 700;
    letter-spacing: 0.5px;
}

.sh-member-count {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.66rem;
    letter-spacing: 1px;
    opacity: 0.55;
}

/* ── ランダム再生 ── */
.sh-random { padding: 18px; border-radius: 6px; }
.sh-random .sh-note { margin-bottom: 12px; }

/* ── 下のタブバー ── */
.app-tabs {
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border-top: 1px solid var(--border-color);
}

/* 半透明だと下の一覧が透けて読みにくいので、地の色を1枚敷く */
.app-tabs::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--bg-color);
    opacity: 0.82;
    z-index: -1;
}

.app-tab {
    position: relative;
    font-family: 'Montserrat', sans-serif;
    letter-spacing: 1px;
    border-radius: 0;
}

/* 選んでいるタブは上に光の線を出す */
.app-tab.is-on::before {
    content: '';
    position: absolute;
    top: -6px;
    left: 50%;
    transform: translateX(-50%);
    width: 26px;
    height: 2px;
    background: var(--main-accent);
    box-shadow: 0 0 8px var(--main-accent);
}

.app-tab span { font-size: 0.6rem; }

/* ── 統計のサブタブ ── */
.sh-stats-tabs .jb-tab {
    font-family: 'Montserrat', sans-serif;
    letter-spacing: 1px;
}

@media (min-width: 769px) {
    .sh-head-en { font-size: 1.4rem; }
    .app-brand-name { font-size: 1.2rem; }
    .sh-unit .unit-label { font-size: 1.5rem; }
}

/* ── 見出しに送りボタンを並べる ── */
.sh-head.has-nav {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 12px;
}

.sh-head-text { min-width: 0; }

.sh-rail-nav {
    flex: 0 0 auto;
    display: flex;
    gap: 6px;
}

.sh-rail-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    color: var(--text-color);
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 50%;
    cursor: pointer;
    transition: border-color 0.2s ease, color 0.2s ease, opacity 0.2s ease;
}

.sh-rail-btn:hover:not(:disabled) {
    color: var(--main-accent);
    border-color: var(--main-accent);
}

.sh-rail-btn:disabled {
    opacity: 0.25;
    cursor: default;
}

/* ボタンで送るので、スクロールバーは出さない */
.sh-rail {
    scrollbar-width: none;
    -ms-overflow-style: none;
}

.sh-rail::-webkit-scrollbar { display: none; }

/* ── モバイルでサイト名が切れないようにする ── */
.app-header {
    /* 名前が長いので、狭い画面では縦に積む */
    flex-wrap: wrap;
}

.app-brand { flex: 1 1 auto; }

@media (max-width: 420px) {
    .app-brand-name {
        font-size: 0.82rem;
        letter-spacing: 1px;
        /* ⚠️ nowrap のままだと末尾が「…」で落ちる。狭い画面では折り返させる */
        white-space: normal;
        overflow: visible;
        line-height: 1.25;
    }

    .app-brand-sub { font-size: 0.58rem; letter-spacing: 1px; }
    .app-header .theme-toggle { transform: scale(0.88); transform-origin: right center; }
}

/* PCは文字のまま。アイコンは狭い画面でだけ出す */
.app-header .theme-icon { display: none; }

/* ── モバイルのテーマ切替を控えめにする ──
   PCは2つ並べたままでよいが、狭い画面では主張が強すぎるので、
   いまの状態だけを小さく出す。
   ⚠️ 押す相手は要素全体（#theme-toggle-btn）なので、
      表示するラベルを1つに減らしても切り替えは効く。 */
@media (max-width: 768px) {
    .app-header .theme-toggle {
        padding: 0;
        background: transparent;
        border-color: var(--border-color);
        opacity: 0.75;
    }

    .app-header .theme-toggle:hover { opacity: 1; }

    /* 選ばれていないほうは隠す */
    .app-header .theme-toggle .theme-label { display: none; }

    .app-header .theme-toggle .theme-label.active {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 38px;
        height: 32px;
        padding: 0;
        /* アクセント色のベタ塗りをやめ、地の文字色にする */
        color: var(--text-color);
        background: transparent;
        border-radius: 999px;
    }

    /* 狭い画面はアイコンだけにする（月＝ダーク／太陽＝ライト） */
    .app-header .theme-icon { display: block; }
    .app-header .theme-text { display: none; }
}

/* ── ヘッダーの ⓘ ボタン ── */
.app-info-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    margin-left: auto;
    margin-right: 8px;
    color: var(--text-color);
    opacity: 0.6;
    text-decoration: none;
    border: 1px solid var(--border-color);
    border-radius: 50%;
    transition: opacity 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.app-info-btn:hover {
    opacity: 1;
    color: var(--main-accent);
    border-color: var(--main-accent);
}

/* ── フッターの「このサイトについて」 ── */
.app-footer { text-align: center; }

.app-about-link {
    display: inline-block;
    margin-bottom: 8px;
    padding: 6px 16px;
    font-size: 0.76rem;
    color: var(--text-color);
    opacity: 0.75;
    text-decoration: none;
    border: 1px solid var(--border-color);
    border-radius: 999px;
}

.app-about-link:hover {
    opacity: 1;
    color: var(--main-accent);
    border-color: var(--main-accent);
}

/* ── このサイトについて ── */
.sh-about { max-width: 720px; }

.sh-about-block {
    padding: 16px 18px;
    margin-bottom: 14px;
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--main-accent);
    border-radius: 4px;
}

.sh-about-block h3 {
    margin: 0 0 10px;
    font-size: 0.92rem;
    font-weight: 700;
    letter-spacing: 1px;
}

.sh-about-block ul {
    margin: 0;
    padding: 0;
    list-style: none;
}

.sh-about-block li {
    position: relative;
    padding-left: 14px;
    margin-bottom: 8px;
    font-size: 0.8rem;
    line-height: 1.75;
}

.sh-about-block li:last-child { margin-bottom: 0; }

/* 行頭の点。記号を打たずに作るので、折り返しても位置が崩れない */
.sh-about-block li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0.72em;
    width: 5px;
    height: 5px;
    background: var(--main-accent);
    border-radius: 50%;
    opacity: 0.7;
}

.sh-about-block a {
    color: var(--main-accent);
    overflow-wrap: anywhere;
}

/* お問い合わせフォームへの導線。
   ⚠️ 上の .sh-about-block a より強く書くこと。
      でないと文字色がアクセント色になり、同じ色の下地に重なって読めなくなる。 */
.sh-about-block a.sh-about-cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
    padding: 11px 20px;
    font-size: 0.84rem;
    font-weight: 700;
    color: var(--bg-color);
    background: var(--main-accent);
    border-radius: 999px;
    text-decoration: none;
}

.sh-about-block a.sh-about-cta:hover { filter: brightness(1.1); }

/* ── 通知（トースト） ── */
.jb-toast {
    position: fixed;
    left: 50%;
    bottom: calc(var(--app-tabs-h, 62px) + var(--jb-player-h, 0px) + 16px);
    transform: translate(-50%, 12px);
    z-index: 10002;
    max-width: min(88vw, 420px);
    padding: 10px 18px;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--bg-color);
    background: var(--main-accent);
    border-radius: 999px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s ease, transform 0.2s ease;
}

.jb-toast.is-on {
    opacity: 1;
    transform: translate(-50%, 0);
}

/* ── 再生中はヘッダーのサイト名だけ残して覆う ──
   PC・モバイルとも同じ扱いにする。
   ⚠️ ヘッダーの高さは端末や文字の折り返しで変わるので、
      --app-header-h に実測を入れて使う（app-shell.js が配る）。 */
.jb-player:not(.is-mini) {
    top: var(--app-header-h, 64px);
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    overflow: hidden;
}

.jb-player:not(.is-mini) .jb-sheet {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.jb-player:not(.is-mini) .jb-seek,
.jb-player:not(.is-mini) .jb-bar {
    flex: 0 0 auto;
    width: 100%;
}

/* 覆っている間はヘッダーを最前面に残す */


/* ヘッダーだけ残して覆っている間は、後ろの本文を触らせない */
body.jb-covering .app-view,
body.jb-covering .app-footer { visibility: hidden; }

/* ── 楽曲一覧・動画一覧のタブを中央に ── */
.jb-panel > .jb-tabs { justify-content: center; }

/* 「全〇曲」は左に寄せる */
.jb-count { text-align: left; }

/* ── メンバーカード：本体ボタン＋プロフィールへのリンク ── */
.sh-member {
    /* 中にボタンとリンクを縦に並べるので、外側は入れ物に徹する */
    padding: 0;
    align-items: stretch;
}

.sh-member-main {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 13px 14px 8px 18px;
    font-family: inherit;
    text-align: left;
    color: var(--text-color);
    background: transparent;
    border: 0;
    cursor: pointer;
}

/* 公式サイトへの案内。曲の絞り込みと押し間違えないよう、小さく下に置く */
.sh-member-profile {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    align-self: flex-start;
    margin: 0 14px 11px 18px;
    padding: 3px 9px;
    font-family: 'Montserrat', sans-serif;
    font-size: 0.58rem;
    font-weight: 700;
    letter-spacing: 1px;
    color: var(--text-color);
    opacity: 0.6;
    text-decoration: none;
    border: 1px solid var(--border-color);
    border-radius: 999px;
}

.sh-member-profile:hover {
    opacity: 1;
    color: var(--c, var(--main-accent));
    border-color: var(--c, var(--main-accent));
}

/* ── リストタブの小見出し ── */
.sh-sub-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 12px;
    margin-bottom: 12px;
}

.sh-sub-head h3 {
    margin: 0;
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 1px;
}

.sh-sub-head .sh-note { margin: 0; }

/* ── プレイリスト ── */
.sh-pl-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
    gap: 10px;
}

.sh-pl {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px 8px 4px 0;
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--main-accent);
    border-radius: 4px;
}

.sh-pl-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 11px 8px 11px 14px;
    font-family: inherit;
    text-align: left;
    color: var(--text-color);
    background: transparent;
    border: 0;
    cursor: pointer;
}

.sh-pl-name {
    font-size: 0.88rem;
    font-weight: 700;
    overflow-wrap: anywhere;
}

.sh-pl-count {
    font-family: 'Montserrat', sans-serif;
    font-size: 0.64rem;
    letter-spacing: 1px;
    opacity: 0.55;
}

/* ── バックアップの案内 ── */
.sh-backup {
    padding: 14px 16px;
    margin-bottom: 26px;
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--border-color);
    border-radius: 4px;
}

.sh-backup .sh-note { margin-bottom: 10px; }

.sh-backup-btns { display: flex; gap: 8px; }

/* ── コードの受け渡しに使う小さな画面 ── */
.sh-modal {
    position: fixed;
    inset: 0;
    z-index: 10010;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: rgba(0, 0, 0, 0.55);
}

.sh-modal-box {
    width: 100%;
    max-width: 460px;
    padding: 20px;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}

.sh-modal-title {
    margin: 0 0 8px;
    font-family: 'Montserrat', sans-serif;
    font-size: 1rem;
    font-weight: 900;
    letter-spacing: 2px;
}

.sh-modal-note {
    margin: 0 0 12px;
    font-size: 0.76rem;
    line-height: 1.7;
    opacity: 0.75;
}

.sh-modal-text {
    width: 100%;
    height: 130px;
    padding: 10px;
    font-family: monospace;
    font-size: 0.72rem;
    line-height: 1.5;
    color: var(--text-color);
    background: var(--card-bg);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    resize: vertical;
    box-sizing: border-box;
    /* コードは長い1行になるので、折り返して全体を見せる */
    overflow-wrap: anywhere;
}

.sh-modal-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 14px;
}

.sh-modal-btn {
    padding: 9px 18px;
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--text-color);
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    cursor: pointer;
}

.sh-modal-btn.is-primary {
    color: var(--bg-color);
    background: var(--main-accent);
    border-color: var(--main-accent);
}

.sh-modal-btn:hover { filter: brightness(1.08); }

/* ── プレイヤー内のタブも中央に ── */
.jb-sheet-tabs { justify-content: center; }

/* ── 繰り返しが「切」のときを見て分かるようにする ──
   色が薄いだけでは判別しづらいので、アイコンに斜線を重ねる。
   ⚠️ 斜線は2本引くこと。1本だと矢印と重なって、
      どこが斜線なのか分からなくなる（地色で太い線を敷いてから上に重ねる）。 */
#jb-repeat::before,
#jb-repeat::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 22px;
    height: 2px;
    transform: translate(-50%, -50%) rotate(-45deg);
    pointer-events: none;
}

#jb-repeat::before {
    height: 5px;
    background: var(--bg-color);
}

#jb-repeat::after { background: currentColor; }

/* 「入」のときは斜線を消す */
#jb-repeat.is-on::before,
#jb-repeat.is-on::after { display: none; }

/* 「1曲」の印は is-on のときだけ出す（斜線と入れ替わる） */
#jb-repeat[data-mode="one"].is-on::after {
    display: block;
    content: '1';
    left: auto;
    top: auto;
    width: auto;
    height: auto;
    position: static;
    transform: none;
    background: none;
    font-size: 0.55rem;
    font-weight: 700;
    margin-left: 2px;
}

/* ── 最小化したときは1行に畳む ──
   縮めても操作の段が縦に積まれたままだと高さが157pxあり、
   そのぶん本文の下に余白を確保するので画面が間延びする。
   細い進捗線・曲名・操作を横一列に並べて、帯1本にする。 */
.jb-player.is-mini {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
}

/* ⚠️ flex-basis は 0 にすること。
   auto のままだと中身の幅ぶんを主張して1行を占め、操作の段が下へ折り返す。 */
.jb-player.is-mini .jb-mini { flex: 1 1 0; min-width: 0; }

/* 進捗は時間表示を落として細い線だけにし、帯の上端へ置く。
   ⚠️ flex の流れに残さないこと。
      幅100%を指定しても、幅0の要素とは同じ行に収まってしまい
      （合計が親幅を超えないため改行されない）、曲名の欄を潰してしまう。 */
.jb-player.is-mini .jb-seek {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    gap: 0;
    padding: 0;
    max-width: none;
}

.jb-player.is-mini { padding-top: 3px; }

.jb-player.is-mini .jb-seek-time { display: none; }
.jb-player.is-mini .jb-progress { height: 3px; border-radius: 0; }
.jb-player.is-mini .jb-progress-knob { display: none; }

.jb-player.is-mini .jb-bar {
    flex: 0 0 auto;
    display: flex;
    gap: 2px;
    width: auto;
    max-width: none;
    margin: 0;
    padding: 4px 8px 4px 0;
}

/* 畳んだ帯では、送り・再生・閉じるだけ残す */
.jb-player.is-mini #jb-shuffle,
.jb-player.is-mini #jb-prev,
.jb-player.is-mini #jb-repeat,
.jb-player.is-mini .jb-volume { display: none; }

.jb-player.is-mini .jb-icon-btn {
    min-width: 38px;
    min-height: 38px;
    border-color: transparent;
}

.jb-player.is-mini .jb-play {
    min-width: 40px;
    min-height: 40px;
    border-color: var(--main-accent);
}

.jb-player.is-mini .jb-mini-main { padding: 5px 8px; }
.jb-player.is-mini .jb-mini-slot { width: 78px; height: 44px; }
.jb-player.is-mini .jb-sheet { width: 78px; height: 44px; top: 50%; transform: translateY(-50%); }
.jb-player.is-mini .jb-video-wrap { width: 78px; height: 44px; }

/* ── 最上部へ戻る ──
   タブバーとプレイヤーの上に浮かせる。位置は実測値から組み立てるので、
   プレイヤーの開閉で高さが変わっても重ならない。 */
.app-totop {
    position: fixed;
    right: 16px;
    bottom: calc(var(--app-tabs-h, 62px) + var(--jb-player-h, 0px) + 14px);
    z-index: 9998;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    color: var(--text-color);
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 50%;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22);
    cursor: pointer;
    /* ふだんは出さない。押せない状態で残らないよう当たり判定も切る */
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
}

.app-totop.is-on {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.app-totop:hover {
    color: var(--main-accent);
    border-color: var(--main-accent);
}

/* ── 再生画面で覆っている間は後ろを動かさない ── */
html.jb-scroll-lock {
    overflow: hidden;
    /* スマホの慣性スクロールが後ろへ抜けるのを防ぐ */
    overscroll-behavior: none;
    touch-action: none;
}

/* プレイヤーの中は動かせるままにする。
   ⚠️ touch-action を戻しておくこと。html で止めたままだと
      再生リストや楽曲情報を指でスクロールできなくなる。 */
html.jb-scroll-lock .jb-player { touch-action: auto; }

/* 中の一覧を端まで送っても、その先が後ろのページへ繋がらないようにする */
.jb-queue-pane,
.jb-sheet-body,
.jb-info {
    overscroll-behavior: contain;
}

/* ── ヘッダーを画面上部に貼り付ける ──
   ⚠️ 地色は画面の端まで届かせること。
      #app-shell には左右の余白があり、PCでは中央寄せで幅も狭いため、
      ヘッダーだけ内側で切れて左右に別の色の帯が見えてしまう。
      いったん画面幅いっぱいに広げてから、中身を元の位置へ戻す。 */
.app-header {
    position: sticky;
    top: 0;
    z-index: 10001;
    background: var(--bg-color);
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    padding-left: max(16px, calc(50vw - 490px + 16px));
    padding-right: max(16px, calc(50vw - 490px + 16px));
}

/* 覆っている間も同じ扱い（別指定は不要） */
body.jb-covering .app-header { z-index: 10001; }

/* ── 最小化したプレイヤーが下のタブと重ならないようにする ──
   ⚠️ プレイヤーの位置はタブバーの実測高さを基準にすること。 */
.jb-player.is-mini { bottom: var(--app-tabs-h, 62px); }

/* ── メンバーのチップ ──
   ⚠️ 濃い色のメンバーだけ白文字になって浮くのを避ける。
      塗りを薄めて、文字はどのメンバーでも地の色で揃える。 */
.jb-chip.is-on {
    color: var(--text-color);
    background: color-mix(in srgb, var(--chip-color, var(--main-accent)) 26%, var(--bg-color));
    border-color: var(--chip-color, var(--main-accent));
    font-weight: 700;
}

/* color-mix が使えない場合は、これまでどおり塗りつぶす */
@supports not (background: color-mix(in srgb, red, blue)) {
    .jb-chip.is-on {
        color: var(--chip-on, var(--bg-color));
        background: var(--chip-color, var(--main-accent));
    }
}

/* ══════════════════════════════════════════
   モバイルの再生画面
   ──────────────────────────────────────────
   動画を小さくして、下の一覧に高さを回す。
   ⚠️ 高さの配分は flex で行い、max-height の決め打ちに頼らないこと。
      端末ごとに画面の高さが違ううえ、開いているタブによって
      伸ばしたい要素が変わるため。
   ══════════════════════════════════════════ */
@media (max-width: 899px) {
    .jb-player:not(.is-mini) .jb-sheet {
        display: flex;
        flex-direction: column;
        min-height: 0;
    }

    .jb-player:not(.is-mini) .jb-layout {
        display: flex;
        flex-direction: column;
        flex: 1 1 auto;
        min-height: 0;
    }

    /* 動画は小さめに。高さで頭打ちにして 16:9 を保つ */
    .jb-player:not(.is-mini) .jb-video-wrap {
        flex: 0 0 auto;
        width: auto;
        max-width: min(100% - 32px, 46vh);
        max-height: 26vh;
        margin: 4px auto 10px;
    }

    /* 楽曲情報と再生リストは、開いているほうだけを残りいっぱいに広げる。
       ⚠️ 両方に flex-grow を持たせないこと。高さを半分ずつ分け合ってしまう。 */
    .jb-player:not(.is-mini) .jb-sheet-body,
    .jb-player:not(.is-mini) .jb-queue-pane {
        flex: 0 0 auto;
        max-height: none;
        min-height: 0;
    }

    /* 楽曲情報タブのとき */
    .jb-player:not(.is-mini):not(.is-tab-queue) .jb-sheet-body {
        flex: 1 1 auto;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    .jb-player:not(.is-mini):not(.is-tab-queue) .jb-info {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
    }

    /* 再生リストタブのとき */
    .jb-player:not(.is-mini).is-tab-queue .jb-queue-pane {
        flex: 1 1 auto;
        overflow-y: auto;
    }

    /* タブだけの帯になるので、余白を詰める */
    .jb-player:not(.is-mini).is-tab-queue .jb-sheet-body {
        overflow: visible;
        padding-bottom: 0;
    }

    .jb-player:not(.is-mini) .jb-sheet-tabs { margin-bottom: 6px; }

    /* シークと操作は下に固定したまま縮めない */
    .jb-player:not(.is-mini) .jb-seek,
    .jb-player:not(.is-mini) .jb-bar { flex: 0 0 auto; }
}

/* ── モバイルの再生リストは1行を詰めて、より多く見せる ── */
@media (max-width: 899px) {
    .jb-player:not(.is-mini) .jb-q-item { padding: 5px 4px; gap: 7px; }
    .jb-player:not(.is-mini) .jb-q-thumb { width: 48px; height: 27px; }
    .jb-player:not(.is-mini) .jb-q-main { padding: 1px 2px; gap: 0; }
    .jb-player:not(.is-mini) .jb-q-title { font-size: 0.78rem; line-height: 1.3; }
    .jb-player:not(.is-mini) .jb-q-sub { font-size: 0.64rem; line-height: 1.3; }

    /* 歌唱と原曲が長いと何行にも折り返して1件が高くなるので、1行に収める */
    .jb-player:not(.is-mini) .jb-q-sub {
        display: block;
        max-width: 100%;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .jb-player:not(.is-mini) .jb-q-now { font-size: 0.55rem; padding: 0 6px; margin-bottom: 1px; }
    .jb-player:not(.is-mini) .jb-q-btn { min-width: 28px; min-height: 28px; }

    /* 見出しの操作も小さくして、一覧に高さを回す */
    .jb-player:not(.is-mini) .jb-queue-head { padding: 4px 0 6px; }
    .jb-player:not(.is-mini) .jb-queue-btn { padding: 4px 9px; font-size: 0.68rem; }
}

/* ── モバイルは動画と余白をさらに詰めて、一覧に高さを回す ── */
@media (max-width: 899px) {
    .jb-player:not(.is-mini) .jb-video-wrap {
        max-width: min(100% - 32px, 38vh);
        max-height: 21vh;
        margin: 2px auto 6px;
    }

    /* 最小化ボタンだけの行。高さを持たせず、動画の上に重ねる */
    .jb-player:not(.is-mini) .jb-sheet-head {
        position: absolute;
        top: 2px;
        left: 4px;
        z-index: 2;
        padding: 0;
    }

    .jb-player:not(.is-mini) .jb-sheet { position: relative; padding-top: 30px; }

    .jb-player:not(.is-mini) .jb-sheet-tabs { margin-bottom: 2px; }
    .jb-player:not(.is-mini) .jb-tab { padding: 7px 12px; }
}

/* ── メンバーの絞り込みチップを揃えて並べる ──
   名前の長さがまちまちで折り返しがそろわないので、等幅の枠に入れる。
   8名なので4列×2段にきれいに収まる。 */
.jb-chips {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
    gap: 6px;
}

.jb-chip {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px 4px;
    text-align: center;
    /* 枠に収まらない名前は詰めて出す（枠の幅は揃えたままにする） */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (min-width: 560px) {
    .jb-chips { grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); }
}

/* ── ヘッダーのサイト名は押せる範囲を広げる ── */
.app-brand {
    align-self: stretch;
    justify-content: center;
    padding: 4px 0;
}

/* ── 全画面で再生している間は下のタブを隠す ──
   ⚠️ 隠したぶんプレイヤーを下まで伸ばすこと。
      タブの高さぶん浮いたままだと、下に地色の帯が残る。 */
body.jb-covering .app-tabs { display: none; }
/* ⚠️ セレクタを弱めないこと。既定側が body:has(#app-shell) .jb-player で
   ID相当の強さを持つため、クラスだけでは負けて効かない。 */
body.jb-covering #app-shell ~ .jb-player:not(.is-mini),
body.jb-covering:has(#app-shell) .jb-player:not(.is-mini),
body.jb-covering .jb-player:not(.is-mini) { bottom: 0; }

/* ── 重なり順を明確にする ──
   ⚠️ プレイヤーとタブバーの前後関係を決めておくこと。
      スクロール中に描き直されると、指定がないほうが上に来て重なって見える。
      下から順に「タブバー → プレイヤー」。 */
.app-tabs { z-index: 9990; }
.jb-player { z-index: 9995; }

/* 最小化中はタブバーの上に、ぴたりと接して置く */
.jb-player.is-mini {
    bottom: var(--app-tabs-h, 62px);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.16);
}

/* 全画面のときはタブを隠しているので、その下端まで使い切る */
body.jb-covering .jb-player:not(.is-mini) {
    top: var(--app-header-h, 64px);
    bottom: 0;
}

/* 再生リストの「続きを出す」 */
.jb-q-more {
    list-style: none;
    padding: 8px 4px 12px;
    text-align: center;
}

.jb-q-more button {
    background: none;
    border: 1px solid color-mix(in srgb, var(--main-accent) 35%, transparent);
    border-radius: 999px;
    color: var(--main-accent);
    cursor: pointer;
    font-family: inherit;
    font-size: 0.8rem;
    padding: 7px 18px;
}

.jb-q-more button:hover {
    background: color-mix(in srgb, var(--main-accent) 12%, transparent);
}

/* ------------------------------------------------------------------
   質感の調整
   すりガラス＋大きなぼかし影をどのカードにも同じようにかけていたため、
   全体がのっぺりして既製品のような見た目になっていた。
   ぼかしは弱め、境界は細い線で出し、影は落とす向きを揃えて浅くする。
   背景も完全な無彩色をやめ、ダークは青インク寄り、ライトは紙寄りにする。
   ------------------------------------------------------------------ */
:root {
    --bg-color: #0d1014;
    --card-bg: rgba(23, 26, 33, 0.88);
    --border-color: rgba(255, 255, 255, 0.085);
    --glass-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 6px 18px -10px rgba(0, 0, 0, 0.8);
    --glass-blur: blur(6px);
}

[data-theme="light"] {
    --bg-color: #f4f2ee;
    --card-bg: #fffefb;
    --border-color: rgba(26, 28, 35, 0.13);
    --glass-shadow: 0 1px 1px rgba(60, 55, 45, 0.06), 0 6px 16px -12px rgba(60, 55, 45, 0.45);
}

/* 角の丸みを揃える。ばらばらの大きな丸みが既製感の元だった。 */
.cyber-card,
.sh-card,
.sh-about-block,
.jb-panel {
    border-radius: 10px;
}

/* ------------------------------------------------------------------
   一覧・再生リストの行
   歌唱者と原曲は中途半端な位置で折り返さず、1行に収めて末尾を省略する。
   ------------------------------------------------------------------ */
.jb-row-sub,
.jb-row-date,
.jb-q-sub {
    overflow-wrap: normal;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.jb-q-title {
    overflow-wrap: normal;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ------------------------------------------------------------------
   絞り込みを固定する
   曲を探しながらスクロールしている最中に検索欄が消えると探し直しになるため、
   一覧の上に貼り付けたままにする。
   ------------------------------------------------------------------ */
.jb-filters {
    position: sticky;
    top: calc(var(--app-header-h, 0px) - 1px);
    z-index: 5;
    padding: 10px 0 8px;
    background: var(--bg-color);
    border-bottom: 1px solid var(--border-color);
}

/* 数を出す行も一緒に貼り付けて、境目が透けないようにする */
.jb-count {
    position: sticky;
    top: calc(var(--app-header-h, 0px) - 1px);
    z-index: 4;
    background: var(--bg-color);
}

/* ------------------------------------------------------------------
   縮小プレイヤーの曲名を流す
   長い曲名は省略すると何の曲か分からなくなるので、収まらないときだけ流す。
   収まっているものは動かさない（ずっと動いていると読みづらい）。
   ------------------------------------------------------------------ */
.jb-mini-title.is-marquee {
    text-overflow: clip;
}

.jb-mini-title.is-marquee > .jb-marquee-inner {
    display: inline-block;
    padding-right: 2.5em;
    animation: jb-marquee var(--marquee-sec, 10s) linear infinite;
}

@keyframes jb-marquee {
    0%, 12% { transform: translateX(0); }
    88%, 100% { transform: translateX(calc(-1 * var(--marquee-dist, 0px))); }
}

/* 端末で「視差効果を減らす」を選んでいる人には、動きを出さない。
   ⚠️ 0s にはせず 0.01ms にすること。0s だと、終わりを待って進む処理
      （transitionend）が来なくなる環境がある。 */
@media (prefers-reduced-motion: reduce) {
    .jb-mini-title.is-marquee > .jb-marquee-inner { animation: none; }
    .jb-mini-title.is-marquee { text-overflow: ellipsis; }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}
