:root {
    /* Só claro. A página é uma vitrine de gravações de tela em fundo branco:
       um tema escuro deixaria os vídeos como janelas acesas num quarto
       apagado. `color-scheme` avisa o navegador, para que barra de rolagem e
       controles não venham escuros por conta própria. */
    color-scheme: light;

    --bg-primary: #F4F4F2;
    --bg-secondary: #ffffff;
    --text-primary: #212529;
    --text-secondary: #545454;
    --text-muted: #717171;
    --accent-color: #1FB846;

    /* A coluna inteira é uma lista só — nome, assunto, vídeo —, então os três
       degraus precisam ser uma escala e não três decisões separadas.
       Razão de 1,25 a partir de 16: 16 → 20 → 32 (pulando um degrau no topo,
       porque o nome do manual não é um cabeçalho a mais da lista).
       As alturas de linha são múltiplos de 4 — 24, 24, 40 —, então um título
       que envolve em duas linhas cai no mesmo compasso dos itens abaixo dele
       em vez de empurrar tudo meio passo. Elas encurtam conforme o tamanho
       cresce: 1,5 no corpo, 1,2 na seção, 1,25 no nome, que é o que impede o
       texto grande de parecer esparramado e o pequeno de parecer apertado. */
    --type-title: 32px;
    --type-section: 20px;
    --type-body: 16px;
    --type-caption: 12px;

    --lh-title: 40px;
    --lh-section: 24px;
    --lh-body: 24px;

    --manual-gutter: 24px;

    /* Estreita o bastante para a lista ser uma coluna de leitura e não um
       parágrafo: os títulos mais longos cabem em uma linha, e os que não cabem
       envolvem em duas sem sobrar rio de espaço à direita dos curtos. */
    --col-index: 320px;

    /* O recuo do palco, e é daqui que ele sai — o shadow root da página só o
       aplica. Mais folgado em cima e embaixo: o vídeo é vertical, então é dali
       que ele cresce até encostar, e é dali que o respiro tem que vir. */
    --stage-inset-x: 16px;
    --stage-inset-y: 44px;

    /* A proporção em que o manual é filmado. É o ponto de partida da moldura —
       que se corrige sozinha quando o pôster diz a proporção real — e é o que
       permite saber a largura do palco antes de haver vídeo nenhum. */
    --video-ar: 0.5625;

    /* Índice e player são um bloco só, centralizado. A largura não é um número
       escolhido: é a coluna do índice mais exatamente o que a moldura ocupa na
       altura desta janela. Qualquer folga além disso viraria vão entre a lista
       e o vídeo, que é o que o bloco existe para não ter.

       `svh` e não `dvh`: agora quem rola é a página, e no iOS isso colapsa a
       barra do Safari. Com `dvh` o palco grudado mudaria de altura no meio da
       rolagem e o vídeo cresceria enquanto se lê a lista. `svh` é a medida com
       a barra aberta — a menor das duas —, então ele fica parado. */
    --stage-width: calc(
        (100svh - 2 * var(--stage-inset-y)) * var(--video-ar) + 2 * var(--stage-inset-x)
    );

    /* `ui-rounded` é a família genérica que a Apple mapeia para SF Pro
       Rounded; hoje só o Safari a implementa, então no Chrome do Mac a
       cascata cai para `system-ui` e se resolve como SF Pro — que já alterna
       sozinha entre Text e Display conforme o tamanho. No Windows `system-ui`
       é Segoe UI; no Android, Roboto. Nada é baixado. */
    --manual-font: ui-rounded, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

/* A página é a lista: quem rola é o documento, e não uma caixa dentro dele.
   Isso devolve tudo que o scroll nativo tem e uma caixa não tem — inércia,
   toque na barra de status para voltar ao topo, a barra do Safari saindo do
   caminho. A única caixa de rolagem que sobra é o deck do player, porque é ela
   que faz a paginação com snap. */
body {
    margin: 0;
    background: var(--bg-primary);
    color: var(--text-primary);
    font-family: var(--manual-font);
    font-size: var(--type-body);
    -webkit-font-smoothing: antialiased;
}

/* Com o player cobrindo a tela, o fundo não pode rolar atrás dele. */
body.player-open { overflow: hidden; }

/* Duas faixas: o título e o índice empilhados à esquerda, o palco à direita
   atravessando as duas. A grade tem a altura da lista, não a da janela — é o
   que faz o scroll da página ser o scroll da lista. */
.page {
    min-height: 100svh;
    width: min(100%, calc(var(--col-index) + var(--stage-width)));
    margin-inline: auto;
    display: grid;
    grid-template-columns: var(--col-index) var(--stage-width);
    grid-template-rows: auto 1fr;
    grid-template-areas:
        "hero  stage"
        "index stage";
}

/* Cabeçalho — só o nome. O verde fica para os vídeos, que já são coloridos;
   o título em tinta normal deixa a cor significar conteúdo, não decoração. */
.hero {
    grid-area: hero;
    display: flex;
    align-items: baseline;
    gap: 8px 24px;
    /* 40 embaixo, contra os 32 que separam duas seções: o nome do manual tem
       que ficar um degrau acima do primeiro assunto, não ao lado dele. */
    padding: 40px 20px;
    padding-top: max(40px, env(safe-area-inset-top));
    padding-left: max(20px, env(safe-area-inset-left));
}

/* 700 e não 800: o nome já é o maior corpo da coluna, e o peso extra brigava
   com os títulos de seção em vez de encabeçá-los. */
.hero h1 {
    margin: 0;
    font: 700 var(--type-title)/var(--lh-title) var(--manual-font);
    /* A web não aplica o optical sizing que o app nativo aplica: em tamanho
       grande e peso alto as letras precisam ser puxadas para dentro, senão o
       título parece esparramado. */
    letter-spacing: -0.02em;
    color: var(--text-primary);
}

/* Sem nada de botão: o nome continua sendo o nome. O que ele ganha é foco de
   teclado e a tecla Enter, que um título com um listener não teria. */
.hero h1 button {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    letter-spacing: inherit;
    color: inherit;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
}

.hero h1 button:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 4px;
}

.hero-links[hidden] { display: none; }

.hero-links {
    display: flex;
    gap: 18px;
    margin-left: auto;
    font-size: var(--type-body);
}

.hero-links a {
    color: var(--text-muted);
    text-decoration: none;
}

.hero-links a:hover { color: var(--accent-color); }

/* O respiro do fim é da coluna da lista, e não da grade: um padding no
   container encurta a área do palco por dentro, e o sticky perde exatamente
   esse tanto de curso — no fim da rolagem o player subia 40px. */
booklet-toc {
    grid-area: index;
    padding-bottom: max(40px, env(safe-area-inset-bottom));
}

/* Grudado, não fixo: dentro da própria célula da grade, o player fica parado
   enquanto a lista corre por baixo dele. `align-self: start` é o que dá a ele
   espaço para grudar — esticado até o fim da área, não sobraria caminho e o
   sticky não teria o que fazer. */
booklet-reel {
    grid-area: stage;
    position: sticky;
    top: 0;
    align-self: start;
    height: 100svh;
    min-width: 0;
}

booklet-reel[hidden] { display: none; }

/* O ponto de quebra mora aqui e só aqui. A moldura do vídeo está noutro shadow
   root e não pode consultá-lo, então a resposta desce por herança: ao lado da
   lista há um controle de play no canto e nenhum botão de fechar; por cima
   dela, o contrário, porque lá a moldura inteira é o botão. */
booklet-reel {
    --close-display: none;
    --transport-display: grid;
    --big-play-display: none;
}


/* A moldura vazia do esqueleto precisa cair onde a de verdade cai: mesmo
   palco, mesma proporção, mesma sombra. Ela ocupa a célula do player e sai
   quando o catálogo chega. */
#skeleton {
    grid-area: stage;
    position: sticky;
    top: 0;
    align-self: start;
    height: 100svh;
    display: grid;
    place-items: center;
    /* O mesmo recuo do palco de verdade, senão a moldura vazia sai do lugar
       exato em que a cheia vai entrar e a troca vira um salto. */
    padding: var(--stage-inset-y) var(--stage-inset-x);
    pointer-events: none;
}

#skeleton[hidden] { display: none; }

#skeleton i {
    display: block;
    height: 100%;
    aspect-ratio: 9 / 16;
    background: #fff;
    box-shadow:
        0 1px 2px rgba(28, 28, 30, 0.05),
        0 6px 12px rgba(28, 28, 30, 0.06),
        0 12px 24px rgba(28, 28, 30, 0.07);
}

/* A coluna do índice encolhe antes de o palco ficar estreito demais: o vídeo é
   vertical, e tirar largura dele tira altura junto. */
@media (max-width: 1020px) {
    :root { --col-index: 280px; }
}

/* No telefone não cabem os dois lado a lado, então a página é a lista inteira e
   o player sai de dentro dela por um toque, cobrindo a tela. É a mesma coisa
   que o desktop mostra sempre — só que aqui ela tem que ser pedida. */
@media (max-width: 900px) {
    :root {
        --type-title: 28px;
        --lh-title: 36px;
        --stage-inset-y: 16px;
    }

    .page {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: auto auto;
        grid-template-areas:
            "hero"
            "index";
    }

    /* Fora da grade: cobre a janela, não a célula. E aqui fechar existe.
       A altura é dita, não deduzida de `inset`: o alinhamento que a regra de
       cima usa para o sticky continua valendo para um filho posicionado da
       grade, e com ele a caixa não se estica — ficava com zero de altura, o
       que some com o player e ainda faz o observer achar que todas as páginas
       estão à vista ao mesmo tempo.
       `dvh` e não `svh`: aqui é uma folha sobre a página travada, então a barra
       do Safari não colapsa no meio e a medida maior é a certa. */
    booklet-reel {
        position: fixed;
        inset: 0;
        z-index: 120;
        height: 100dvh;
        /* Escurecer, não tapar: a lista continua atrás, então abrir um vídeo é
           entrar num assunto sem sair do manual. É também o que diz que isto
           tem um fora — e o fora, num lightbox, fecha. */
        background: rgba(0, 0, 0, 0.55);
        --close-display: grid;
        --transport-display: none;
        --big-play-display: grid;
    }

    /* A moldura vazia só faz sentido onde há palco à vista; aqui o que carrega
       primeiro é a lista, e ela é o próprio esqueleto. */
    #skeleton { display: none; }
}

/* Falhar é um aviso no canto, não uma tela. O manual é cortesia: quem veio ver
   outra coisa não deveria receber uma página de erro no lugar da página. */
#warning {
    position: fixed;
    top: 16px;
    right: 16px;
    z-index: 200;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: calc(100vw - 32px);
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(235, 235, 233, 0.94);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow:
        0 2px 4px rgba(28, 28, 30, 0.06),
        0 10px 30px rgba(28, 28, 30, 0.12);
    color: var(--text-primary);
    font-size: 14px;
}

#warning[hidden] { display: none; }

#warning button {
    flex: 0 0 auto;
    padding: 6px 12px;
    border: 0;
    border-radius: 999px;
    background: var(--accent-color);
    color: #fff;
    font: 600 13px/1 inherit;
    cursor: pointer;
}
