@font-face{font-family:'Lexend';src:url('assets/fonts/Lexend-Regular.woff2') format('woff2');font-weight:400;font-style:normal;font-display:swap;}
@font-face{font-family:'Lexend';src:url('assets/fonts/Lexend-Medium.woff2') format('woff2');font-weight:500;font-style:normal;font-display:swap;}
@font-face{font-family:'Lexend';src:url('assets/fonts/Lexend-SemiBold.woff2') format('woff2');font-weight:600;font-style:normal;font-display:swap;}
@font-face{font-family:'Lexend';src:url('assets/fonts/Lexend-Bold.woff2') format('woff2');font-weight:700;font-style:normal;font-display:swap;}
:root{
    --bg:#f6f1e7; --panel:#fbf8f2; --panel2:#eee6d6; --border:rgba(43,38,32,.07);
    --text:#2b2621; --muted:#83766a; --accent:#8a3324; --accent2:#33564a;
    --danger:#a8342a; --ok:#33564a; --warn:#b9832e; --on-accent:#fbf8f2;
    --grid-line:#e2d7c3; --header-h:64px; --action-bar-h:55px; --main-vpad:40px;
    --res-fechada-fg:#a8342a; --res-fechada-bg:rgba(168,52,42,.12);
    --res-aberta-fg:#33564a; --res-aberta-bg:rgba(51,86,74,.12);
    --res-sem-fg:#5c7a52; --res-sem-bg:rgba(92,122,82,.12);
    --conflict-bg:rgba(168,52,42,.08); --turma-active-bg:rgba(138,51,36,.09);
    --preview-ok-bg:rgba(29,122,74,.72); --preview-conflict-bg:rgba(214,40,30,.75);
    --mini-preview-ok-bg:rgba(41,109,181,.75);
    --preview-ring:rgba(43,38,32,.55); --other-campus:#a8342a; --room-other:#8a3324;
    --danger-hover-bg:rgba(168,52,42,.1); --hover-bg:#e4d9c2; --accent-hover:#6f2a1e;
    --mini-last:#2f6fb0; --info-strong:#2b2621; --ead-text:#000000;
    --font-display:'Lexend',-apple-system,Helvetica,Arial,sans-serif; --font-body:'Lexend',-apple-system,Helvetica,Arial,sans-serif;
    --stripe: rgba(43,38,32,.04);
  }
  html[data-theme="dark"]{
    --bg:#0e0e10; --panel:#18181b; --panel2:#26262c; --border:rgba(238,230,214,.07);
    --text:#e8e8ea; --muted:#b5b5ba; --accent:#c9603f; --accent2:#5c9384;
    --danger:#dd7362; --ok:#5c9384; --warn:#d9a54f; --on-accent:#0e0e10;
    --grid-line:#2e2e34;
    --res-fechada-fg:#e58b7e; --res-fechada-bg:rgba(221,115,98,.16);
    --res-aberta-fg:#8fc2b2; --res-aberta-bg:rgba(92,147,132,.16);
    --res-sem-fg:#9fb98f; --res-sem-bg:rgba(159,185,143,.14);
    --conflict-bg:rgba(221,115,98,.12); --turma-active-bg:rgba(111,168,220,.16);
    --preview-ok-bg:rgba(46,181,128,.65); --preview-conflict-bg:rgba(255,79,63,.68);
    --mini-preview-ok-bg:rgba(111,168,220,.68);
    --preview-ring:rgba(0,0,0,.65); --other-campus:#e58b7e; --room-other:#e58b7e;
    --danger-hover-bg:rgba(221,115,98,.14); --hover-bg:#2e2e34; --accent-hover:#a84f33;
    --mini-last:#6fa8dc; --info-strong:#b5b5ba; --ead-text:#ffffff;
    --stripe: rgba(238,230,214,.03);
  }
  *{box-sizing:border-box;}
  /* overflow-x:hidden (sozinho) faz o navegador computar overflow-y como
     "auto" por baixo dos panos em vários motores — isso é regra do próprio
     CSS quando só um dos dois eixos é definido — e isso quebra
     position:sticky dos descendentes, especialmente em Safari/iOS (é por
     isso que a barra de ações + mini-tabela não estavam "descendo juntas"
     de forma confiável no celular). overflow-x:clip evita esse efeito
     colateral mantendo o mesmo objetivo (sem scroll horizontal). */
  html,body{overflow-x:clip;overflow-y:visible;max-width:100%;}
  body{margin:0;font-family:var(--font-body);
    background:var(--bg);color:var(--text);min-height:100vh;transition:background .15s,color .15s;}
  header{padding:14px 26px 6px;display:flex;align-items:center;
    justify-content:space-between;flex-wrap:wrap;gap:10px;background:var(--bg);
    min-height:var(--header-h);}
  .header-title-row{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0;width:100%;}
  header h1{font-family:var(--font-display);font-size:22px;margin:0;font-weight:600;letter-spacing:-.2px;white-space:nowrap;}
  header h1 span{color:var(--accent);font-style:italic;}
  header h1 #brandUtfpr{color:var(--text);font-style:normal;font-weight:600;font-size:.42em;letter-spacing:.02em;vertical-align:middle;}
  .header-extras{display:flex;align-items:center;gap:8px;flex-shrink:0;}

  /* ============== BARRA DE AÇÕES FIXA ==============
     Diferente do header (título, tema, github), que rola normalmente com
     a página, esta barra com desfazer/refazer/copiar/colar/limpar fica
     grudada no topo da tela o tempo todo via position:sticky. */
  .action-bar{position:sticky;top:0;z-index:100;background:var(--bg);
    padding:10px 26px;display:flex;align-items:center;gap:10px;
    border-bottom:1px solid var(--border);}

  /* ============== MINI-PRÉVIA DA GRADE (só no celular) ==============
     Um resuminho puramente visual — sem texto — espelhando a grade real
     (uma célula por aula x dia): verde onde há aula, vermelho só em
     conflito. Preenche o canto vazio do topo quando a barra de
     ferramentas quebra para a linha de baixo. */
  /* Ancorada à barra de ações (sticky): como um elemento sticky também
     funciona como bloco de referência para descendentes com position
     absolute, a mini-grade acompanha a barra perfeitamente ao rolar,
     sem precisar de cálculo via JS nem ficar "pulando" de posição. */
  .mini-grid{display:none;position:absolute;top:100%;right:10px;}
  .day-med,.day-abbr{display:none;}
  .toolbar{display:flex;gap:6px;flex-wrap:wrap;align-items:center;}
  button{cursor:pointer;border:none;background:var(--panel2);color:var(--text);
    padding:9px 14px;border-radius:4px;font-size:12.5px;font-weight:600;font-family:var(--font-body);
    transition:.15s;display:flex;align-items:center;gap:6px;}
  .btn-label-short{display:none;}
  button:hover{background:var(--hover-bg);}
  button.primary{background:var(--accent);color:var(--on-accent);}
  button.primary:hover{background:var(--accent-hover);}
  button:disabled{opacity:.4;cursor:not-allowed;}
  button:disabled:hover{background:var(--panel2);}
  button.danger{background:transparent;color:var(--danger);}
  button.danger:hover{background:var(--danger-hover-bg);}
  button:disabled{opacity:.4;cursor:not-allowed;}
  main{display:grid;grid-template-columns:320px 1fr;gap:20px;padding:20px 26px;max-width:1650px;margin:0 auto;}
  /* Sem isso, um item de grid encolhe apenas até o tamanho do seu conteúdo
     (min-width:auto por padrão) — como a tabela da grade tem min-width
     próprio, a coluna do grid (e a página inteira) era empurrada para
     além da viewport no celular, mesmo com overflow-x:hidden no body. */
  main > *{min-width:0;}
  @media(max-width:980px),(orientation:portrait){main{grid-template-columns:1fr;}}
  .panel{background:var(--panel);border-radius:5px;padding:16px;}
  .search{width:100%;padding:10px 22px 10px 24px;border-radius:0;border:none;border-bottom:1px solid var(--border);background:transparent;
    color:var(--text);font-size:14px;font-family:var(--font-body);}
  .search::placeholder{color:var(--muted);}
  .search:focus{outline:none;border-bottom-color:var(--accent);}
  .course-select-wrap{display:flex;align-items:center;gap:8px;margin-bottom:14px;}
  .course-select-wrap label{font-size:12.5px;color:var(--muted);font-weight:500;flex-shrink:0;}
  .course-select-wrap select{flex:1;min-width:0;padding:8px 26px 8px 10px;border-radius:4px;
    border:1px solid var(--border);background:var(--panel2);color:var(--text);
    font-family:var(--font-body);font-size:13.5px;cursor:pointer;
    appearance:none;-webkit-appearance:none;-moz-appearance:none;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2383766a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat:no-repeat;background-position:right 8px center;background-size:13px;}
  html[data-theme="dark"] .course-select-wrap select{
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b5b5ba' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");}
  .course-select-wrap select:focus{outline:2px solid var(--accent);outline-offset:-1px;}
  .course-select-wrap select:disabled{opacity:.6;cursor:wait;}
  .search-wrap{position:relative;margin-bottom:14px;}
  .search-icon{position:absolute;left:2px;top:50%;transform:translateY(-50%);
    color:var(--muted);pointer-events:none;}
  .search-clear{position:absolute;right:0;top:50%;transform:translateY(-50%);background:transparent;
    color:var(--muted);padding:4px;width:20px;height:20px;border-radius:50%;justify-content:center;}
  .search-clear:hover{background:var(--hover-bg);color:var(--text);}
  /* Regra base: só entra em vigor de fato em telas ≤980px, onde o painel
     empilha acima da grade (ver linha 93) e a página rola normalmente —
     acima de 981px essa altura é substituída pelo layout flex mais preciso
     lá embaixo ("PAINEL ESQUERDO ACOMPANHA A ALTURA DA TELA"), que calcula
     o espaço restante de verdade em vez de usar um valor fixo "chutado".
     O min() aqui evita que a lista cresça sem limite em celulares com tela
     muito alta. */
  .subject-list{max-height:min(calc(100vh - 260px), 760px);overflow-y:auto;padding-right:4px;}
  /* Em tablets (layout já em coluna única, mas tela ainda alta o
     suficiente para a lista ficar exageradamente longa) a lista de
     disciplinas fica 1/3 menor que o padrão acima — só nessa faixa;
     no celular (≤700px) ela continua com a altura padrão. */
  @media(min-width:701px) and (max-width:980px){
    .subject-list{max-height:calc((100vh - 260px) * 0.6667);}
  }
  /* O aviso de conflito aparece depois da grade grande (não antes) em
     qualquer largura — PC, tablet retrato, tablet paisagem — assim a
     pessoa já vê a tabela antes do aviso. Só no celular (≤700px, regra
     lá embaixo) ele continua aparecendo em cima, como era antes. */
  .content-col{display:flex;flex-direction:column;}
  .stats-row{order:1;}
  .grid-wrap{order:2;}
  .conflict-banner{order:3;}
  .legend{order:4;}
  .footer-note{order:5;}
  .subject-list::-webkit-scrollbar{width:6px;}
  .subject-list::-webkit-scrollbar-thumb{background:var(--grid-line);border-radius:4px;}
  .subject{border-radius:5px;margin-bottom:6px;background:var(--panel2);overflow:hidden;}
  .subject-head{padding:11px 12px;display:flex;justify-content:space-between;align-items:center;cursor:pointer;gap:8px;}
  .subject-head.hover-linked{background:var(--hover-bg);}
  @media(hover:hover) and (pointer:fine){
    .subject-head:hover{background:var(--hover-bg);}
  }
  .subject-head-text{min-width:0;flex:1;}
  .subject-title{font-family:var(--font-display);font-size:14.5px;font-weight:600;line-height:1.3;overflow-wrap:break-word;}
  .subject-code{color:var(--info-strong);font-size:11px;font-weight:500;display:flex;flex-wrap:nowrap;align-items:center;gap:6px;height:15px;}
  .subject-code-text{line-height:1;flex-shrink:0;}
  /* Selo da turma: um quadrado minimalista de bordas arredondadas
     desenhado em SVG (só contorno, sem preenchimento) em volta do
     número — mesmo tom neutro do resto da linha (código/reserva). */
  .turma-chip{position:relative;display:inline-flex;align-items:center;justify-content:center;
    padding:2px 7px;line-height:1;color:var(--info-strong);}
  .turma-chip.chip-empty{opacity:0;pointer-events:none;}
  .turma-chip-bg{position:absolute;inset:0;width:100%;height:100%;color:var(--info-strong);}
  .turma-chip-text{position:relative;z-index:1;font-weight:600;font-size:10.5px;line-height:1;}
  .turma-chip-star{position:relative;z-index:1;font-size:10.5px;line-height:1;margin-left:1px;}
  /* Linha reservada pro nome do professor, sempre em baixo do código da
     matéria (min-height mantém o espaço mesmo quando ainda não há nada
     selecionado, pra lista não "pular" ao selecionar/desmarcar). */
  .subject-prof{color:var(--info-strong);font-size:10.5px;font-weight:500;font-style:italic;height:13px;line-height:13px;margin-top:1px;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  /* No escuro, as cores de disciplinas selecionadas (vindas da paleta, pensada
     para fundo escuro nos blocos da grade) ficam pouco legíveis como texto
     sobre o painel escuro — clareamos e saturamos um pouco só o texto aqui. */
  html[data-theme="dark"] .subject-title-colored{filter:brightness(1.55) saturate(1.15);}
  .chev{color:var(--muted);transition:.15s;flex-shrink:0;display:inline-flex;align-items:center;}
  .subject.open .chev{transform:rotate(90deg);}
  .turma-panel{display:none;padding:0 10px 10px;}
  .subject.open .turma-panel{display:block;}
  .turma-opt{display:flex;align-items:stretch;justify-content:space-between;gap:8px;padding:8px 9px;
    border-radius:4px;margin-top:5px;cursor:pointer;font-size:12px;background:var(--panel);}
  .turma-opt:hover{background:var(--hover-bg);}
  .turma-opt.active{background:var(--turma-active-bg);}
  .turma-opt .t-left{display:flex;flex-direction:column;gap:1px;justify-content:center;flex:1;min-width:0;}
  .turma-opt .t-turma{font-weight:700;}
  .turma-opt .t-prof{color:var(--muted);font-size:10.5px;}
  .turma-opt .t-meta{color:var(--muted);font-size:10px;margin-top:2px;}
  .t-res{font-weight:700;padding:1px 5px;border-radius:3px;background:var(--panel2);}
  .t-res-fechada{color:var(--res-fechada-fg);background:var(--res-fechada-bg);}
  .t-res-aberta{color:var(--res-aberta-fg);background:var(--res-aberta-bg);}
  .t-res-sem-reserva{color:var(--res-sem-fg);background:var(--res-sem-bg);}
  .t-res.res-inline{font-size:9.5px;padding:1px 4px;}
  /* Ao lado do código da matéria, a reserva fica neutra — sem o destaque
     colorido que faz na lista de turmas — pra combinar com o resto do
     texto (código, turma, professor). */
  .subject-code .t-res.res-inline,
  .subject-code .t-res.res-inline.t-res-fechada,
  .subject-code .t-res.res-inline.t-res-aberta,
  .subject-code .t-res.res-inline.t-res-sem-reserva{background:none;color:var(--info-strong);font-weight:500;padding:0;line-height:1;}
  /* Vagas total/calouros, exibido logo ao lado do selo de reserva
     (Aberta/Fechada/Sem reserva), tanto na lista de turmas quanto no
     resumo ao lado do código da matéria. */
  .t-vagas{color:var(--muted);font-weight:500;}
  .turma-opt .t-meta .t-vagas{font-size:10px;}
  .subject-code .t-vagas.vagas-inline{font-size:9.5px;color:var(--info-strong);line-height:1;}
  /* Só no tema claro: professor, vagas e o selo de reserva (Aberta/
     Fechada/Sem reserva) de cada turma na lista ficam num tom só,
     um pouco mais escuro que --muted (#83766a) — mantém a mesma
     "família" de cor do site, só reduz o contraste/protagonismo desse
     texto secundário. O tema escuro continua exatamente como estava. */
  html[data-theme="light"] .turma-opt .t-prof,
  html[data-theme="light"] .turma-opt .t-meta,
  html[data-theme="light"] .t-vagas,
  html[data-theme="light"] .t-res-fechada,
  html[data-theme="light"] .t-res-aberta,
  html[data-theme="light"] .t-res-sem-reserva{color:#6f6255;}
  .turma-opt .t-remove{align-self:stretch;height:auto;color:var(--danger);font-size:13px;background:none;border:none;cursor:pointer;padding:2px 8px;display:flex;align-items:center;justify-content:center;}
  /* Botão de fixar (pin) no modo normal — mesmo estado do modo compacto
     (ver State.pinned em app.js), só muda a aparência/posição pra
     combinar com o layout deste modo. Fica à esquerda do "✕", os dois
     só aparecem na turma ativa. */
  .turma-opt .t-pin-btn{align-self:stretch;height:auto;flex-shrink:0;color:var(--muted);background:none;border:none;
    cursor:pointer;padding:2px 6px;display:flex;align-items:center;justify-content:center;
    transition:color .12s ease,background .12s ease;}
  .turma-opt .t-pin-btn:hover{background:var(--hover-bg);color:var(--text);}
  .turma-opt .t-pin-btn.pinned{color:var(--accent2);}
  .turma-opt .t-pin-btn.pinned svg{fill:currentColor;}
  /* Indicativo (não-clicável) de turma fixada, ao lado do código da
     turma, quando ela NÃO é a ativa — o botão de pin de verdade só
     existe na turma ativa. */
  .t-turma .t-pin-indicator{display:inline-flex;vertical-align:middle;margin-left:5px;color:var(--accent2);opacity:.85;position:relative;top:-1px;}

  /* ============== MODO COMPACTO ==============
     O botão de cada turma vira um controle segmentado de até 3 partes,
     lado a lado:
       1) "i" (informações)  — só entra no DOM na turma ATIVA da
          matéria; nas demais nem aparece, deixando o texto da turma
          (.t-mid) ocupar mais espaço.
       2) turma (.t-mid)     — a maior parte do botão (flex:1 enche o
          espaço que sobra das outras duas, fixas). Mostra só o código
          da turma (ex.: "S21") quando o painel está em 2 colunas
          (turmas>8); com 1 coluna sobra espaço e mostra "Turma S21".
          Clique normal seleciona a turma; se ela JÁ estiver
          selecionada, o hover fica vermelho (ver .active .t-mid:hover)
          e o clique nesse estado REMOVE — substitui o antigo botão
          "✕".
       3) pin                — sempre visível, estreito, sem nenhuma
          animação de aparecer/sumir.
     Ver renderSubjectList() em app.js pra montagem do HTML de cada modo. */
  html[data-compact="true"] .turma-opt{padding:0;gap:0;align-items:stretch;overflow:hidden;}
  html[data-compact="true"] .t-turma{flex:0 0 auto;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  /* Prioridade de curso (t.prio): ao lado do código da turma, tom
     apagado, o mais compacta possível — trunca com "…" se não couber
     (ver showPrio em renderSubjectList(), app.js, pra quando ela
     aparece/some conforme a turma está selecionada ou não). */
  html[data-compact="true"] .t-prio-compact{
    flex:1 1 auto;min-width:0;margin-left:6px;text-align:right;
    font-size:9.5px;color:var(--muted);opacity:.7;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  }
  html[data-compact="true"] .turma-opt.active .t-mid:hover .t-prio-compact{color:inherit;opacity:.8;}
  html[data-compact="true"] .turma-opt.pinned:not(.active) .t-prio-compact{padding-right:16px;}

  html[data-compact="true"] .t-info-btn{
    flex:0 0 22px;align-self:stretch;width:auto;height:auto;border-radius:0;font-size:12px;padding:0;
    background:color-mix(in srgb, var(--panel2) 78%, black 22%);
    transition:background .12s ease,color .12s ease;
  }
  html[data-compact="true"] .t-info-btn:hover{background:var(--hover-bg);}
  html[data-compact="true"] .t-info-btn[aria-expanded="true"]{background:var(--accent2);color:var(--on-accent);}

  html[data-compact="true"] .t-mid{
    flex:1;min-width:0;position:relative;display:flex;align-items:center;padding:7px 9px;cursor:pointer;
    border-left:1px solid var(--border);transition:background .12s ease,color .12s ease;
  }
  html[data-compact="true"] .t-mid:hover{background:var(--hover-bg);}
  /* Indicativo (não-clicável) de que a turma está fixada, mostrado por
     cima do canto direito do botão do meio quando ela NÃO é a turma
     ativa — o botão de pin de verdade (clicável) só existe na turma
     ativa (ver renderSubjectList() em app.js). */
  html[data-compact="true"] .t-pin-indicator{
    position:absolute;top:50%;right:7px;transform:translateY(-50%);
    display:flex;pointer-events:none;color:var(--accent2);opacity:.85;
  }
  html[data-compact="true"] .turma-opt.active .t-mid:hover .t-pin-indicator{color:inherit;}
  /* Turma já selecionada: passar o mouse pela parte do meio vira um
     aviso de remoção (vermelho do tema, funciona no claro e no escuro),
     e o clique nesse estado remove a turma — ver selectOrRemove() em
     app.js. O vermelho se estende aos 3 segmentos do controle (i / meio
     / pin), não só o do meio — por isso o :has() no seletor, escutando
     o hover do meio mas pintando o .turma-opt inteiro. */
  html[data-compact="true"] .turma-opt.active .t-mid:hover{background:var(--danger);color:var(--on-accent);}
  html[data-compact="true"] .turma-opt.active .t-mid:hover .other-campus{color:inherit;}
  html[data-compact="true"] .turma-opt.active:has(.t-mid:hover) .t-info-btn,
  html[data-compact="true"] .turma-opt.active:has(.t-mid:hover) .t-pin-btn{background:var(--danger);color:var(--on-accent);}

  html[data-compact="true"] .t-pin-btn{
    flex:0 0 11px;align-self:stretch;width:auto;height:auto;margin:0;
    border-left:1px solid var(--border);border-radius:0;background:none;color:var(--muted);
    cursor:pointer;display:flex;align-items:center;justify-content:flex-end;
    transition:color .12s ease,background .12s ease;
  }
  html[data-compact="true"] .t-pin-btn svg{width:13px;height:13px;flex-shrink:0;}
  html[data-compact="true"] .t-pin-btn:hover{background:var(--hover-bg);color:var(--text);}
  html[data-compact="true"] .t-pin-btn.pinned{color:var(--accent2);}
  html[data-compact="true"] .t-pin-btn.pinned svg{fill:currentColor;}

  /* Painel de turmas em 2 colunas (só no modo compacto, quando a matéria
     aberta tem muitas turmas — ver renderSubjectList em app.js). Grid em
     vez de column-count: com column-count cada coluna tem sua própria
     altura "balanceada" e os itens não alinham entre si de uma coluna
     pra outra; com grid de 2 colunas + grid-auto-flow:row, cada linha
     tem a MESMA altura nas duas colunas, então elas ficam alinhadas. */
  .subject.open .turma-panel.two-col{display:grid;grid-template-columns:1fr 1fr;gap:4px 8px;}

  /* Modo compacto: em vez de abrir "por baixo" da turma clicada (o que
     bagunçaria o alinhamento das colunas, ver acima), o painel de
     informações da turma ativa sempre aparece uma única vez, no rodapé
     de toda a lista, ocupando as duas colunas e em formato horizontal
     (chips lado a lado) — mais fácil de ler que texto empilhado. O botão
     "i" da turma correspondente continua destacado (aria-expanded) pra
     indicar de qual turma é a informação exibida. */
  html[data-compact="true"] .turma-info{
    display:flex;flex-wrap:wrap;gap:5px 16px;line-height:1.4;margin-top:8px;}
  .turma-panel.two-col .turma-info{grid-column:1 / -1;}
  .t-info-btn{align-self:stretch;flex-shrink:0;width:16px;height:auto;padding:0;border-radius:4px;background:var(--panel2);
    color:var(--accent2);font-family:var(--font-display);font-style:italic;font-weight:700;font-size:12px;
    display:flex;align-items:center;justify-content:center;line-height:1;}
  .t-info-btn:hover{background:var(--hover-bg);}
  .t-info-btn[aria-expanded="true"]{background:var(--accent2);color:var(--on-accent);}
  .other-campus{color:var(--other-campus);font-weight:800;}
  .turma-info{font-size:11px;color:var(--muted);margin-top:6px;line-height:1.6;padding:8px 9px;background:var(--panel);border-radius:4px;}
  .badge{display:inline-block;padding:2px 7px;border-radius:3px;font-size:10px;font-weight:700;margin-left:6px;}
  .badge.selected-badge{background:var(--accent);color:var(--on-accent);}
  .badge.badge-ead{background:none;color:var(--ead-text);padding:0;font-weight:800;vertical-align:middle;}
  .badge.badge-ead.badge-ead-hidden{display:none;}
  html[data-theme="dark"] .badge.selected-badge{background:var(--mini-last);}
  .grid-wrap{overflow-x:auto;border-radius:5px;position:relative;}
  table.grid{border-collapse:separate;border-spacing:0;width:100%;min-width:860px;background:var(--panel);border-radius:5px;}
  
  table.grid thead th{font-family:var(--font-display);background:var(--panel2);padding:9px 3px;font-size:12.5px;color:var(--text);font-weight:600;
    position:sticky;top:0;z-index:20;}
  table.grid thead th:first-child{left:0;z-index:21;}
  
  table.grid td{vertical-align:top;height:36px;padding:0;position:relative;}

  table.grid tbody tr:nth-child(even) td {
    background-color: var(--stripe);
  }

  td.time-col{color:var(--muted);font-size:10.5px;text-align:center;padding:3px 2px;
    white-space:nowrap;font-weight:600;position:sticky;left:0;z-index:10;line-height:1.2;}
  table.grid td.time-col{vertical-align:middle;}
  
  table.grid tbody tr:nth-child(odd) td.time-col { background-color: var(--panel); }
  table.grid tbody tr:nth-child(even) td.time-col { background-color: var(--panel2); }

  .cell-block{position:absolute;inset:2px;border-radius:3px;padding:2px 5px;font-size:10px;line-height:1.2;
    overflow:hidden;display:flex;flex-direction:column;justify-content:center;color:#fbf8f2;font-weight:600;}
  .cell-block .b-name{font-weight:700;font-size:10.5px;}
  .cell-block .b-sub{opacity:.85;font-weight:500;font-size:9px;}
  .cell-block .b-room.other{color:#ffe1d6;font-weight:800;}
  .cell-block.conflict::before{content:"";position:absolute;inset:0;border-radius:3px;pointer-events:none;z-index:0;
    background:repeating-linear-gradient(45deg, #ff1f1f 0 4px, transparent 4px 10px);opacity:.75;}
  .cell-block.conflict .b-name,.cell-block.conflict .b-sub,.cell-block.conflict .b-room{position:relative;z-index:1;}
  .cell-block{cursor:pointer;transition:filter .12s,transform .12s;}
  .cell-block.hover-linked{filter:brightness(1.1);transform:scale(1.02);}
  @media(hover:hover) and (pointer:fine){
    .cell-block:hover{filter:brightness(1.1);transform:scale(1.02);}
  }
  .cell-preview{position:absolute;inset:0px;border-radius:3px;pointer-events:none;z-index:5;
    box-shadow:0 0 0 2.5px var(--preview-ring) inset;}
  .cell-preview.pv-ok{background:var(--preview-ok-bg);}
  .cell-preview.pv-conflict{background:var(--preview-conflict-bg);}
  .empty-state{padding:60px 20px;text-align:center;color:var(--muted);font-size:13px;}
  .stats{display:flex;gap:20px;padding:10px 4px;font-size:12px;color:var(--muted);flex-wrap:wrap;}
  .stats b{color:var(--text);font-family:var(--font-display);font-size:14px;}
  .stat-with-icon{display:inline-flex;align-items:center;gap:5px;}
  /* Linha que contém as estatísticas (esquerda) e os botões de template
     (direita) — fica logo acima da grade grande. No celular (ver media
     query no fim do arquivo) essa linha vira coluna: templates abaixo
     das estatísticas, alinhados à esquerda. */
  .stats-row{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:12px;}
  .stats-row .stats{margin-bottom:0;flex:1;min-width:0;}
  /* Modo horizontal: estatísticas em uma linha só (font-size ajustado via fitStatsLine em app.js). */
  @media(min-width:981px) and (orientation:landscape){
    .stats-row .stats{flex-wrap:nowrap;overflow:hidden;}
    .stats-row .stats>div{white-space:nowrap;flex-shrink:0;}
  }
  .template-bar{display:flex;gap:6px;flex-shrink:0;padding-top:6px;}
  .template-btn{width:34px;height:34px;padding:0;border-radius:4px;
    background:var(--panel2);color:var(--text);border:1px solid var(--border);
    font-family:var(--font-display);font-weight:700;font-size:13.5px;
    display:flex;align-items:center;justify-content:center;}
  .template-btn:hover{background:var(--hover-bg);}
  .template-btn.active{background:var(--accent2);color:var(--on-accent);border-color:var(--accent2);}
  .conflict-banner{background:var(--conflict-bg);color:var(--danger);
    padding:10px 14px;border-radius:3px;margin-bottom:12px;font-size:12.5px;display:none;}
  .conflict-banner.show{display:block;}
  .toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%) translateY(20px);
    background:var(--text);color:var(--bg);padding:10px 18px;border-radius:4px;
    font-size:13px;opacity:0;transition:.25s;pointer-events:none;z-index:200;
    max-width:80vw;}
  .toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
  .legend{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px;}
  .legend-item{display:flex;align-items:center;gap:6px;font-size:10px;color:var(--muted);}
  .legend-dot{width:9px;height:9px;border-radius:2px;flex-shrink:0;}
  .footer-note{font-size:10px;color:var(--muted);text-align:center;padding:8px;}
  .footer-note .dot-red{color:var(--danger);font-weight:800;}
  /* flex-wrap:nowrap de propósito: com o botão de pin (fixadas) somado aos
     três filtros de texto, preferimos que os três encolham horizontalmente
     (flex:1 os deixa dividir igualmente o espaço que sobra) a quebrar linha
     — o botão de pin tem largura fixa (flex:0 0 auto) e não participa
     dessa divisão. */
  .filter-row{display:flex;gap:6px;margin-bottom:12px;flex-wrap:nowrap;}
  .filter-row button{flex:1 1 0;font-size:11px;padding:7px 6px;background:transparent;min-width:0;}
  .filter-row button:hover{background:var(--panel2);}
  .filter-row button.active{background:var(--accent2);color:var(--on-accent);}
  /* Os três botões de texto não dividem o espaço igualmente: "Selecionadas"
     é uma palavra única e comprida (não quebra linha), então recebe mais
     espaço; "Todas" é curto e sobra espaço à toa se ficar igual aos
     outros, então recebe menos. "Com conflito" fica com a proporção
     padrão (1), no meio dos dois. */
  .filter-row #filterAll{flex:0.7 1 0;}
  .filter-row #filterSelected{flex:1.7 1 0;}
  /* Botão de pin (fixadas): mesma altura dos outros três, mas largura fixa
     e ícone centralizado, igual aos .icon-btn da action-bar — não encolhe
     junto com os filtros de texto (flex:0 0 auto). */
  .filter-row .filter-pin-btn{flex:0 0 32px;width:32px;padding:0;justify-content:center;color:var(--accent2);}
  .filter-row .filter-pin-btn svg{flex-shrink:0;}
  .filter-row .filter-pin-btn.active{background:var(--accent2);color:var(--on-accent);}
  .icon-btn{padding:9px;width:34px;height:34px;justify-content:center;}
  .icon-btn svg{flex-shrink:0;}
  .github-link{background:var(--panel2);color:var(--text);border-radius:4px;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;transition:.15s;}
  .github-link:hover{background:var(--hover-bg);}

  /* ============== SLIDER DE TEMA (claro/escuro), com "sistema" oculto ==============
     Não há um terceiro botão visível para "sistema": a preferência de sistema
     continua funcionando em segundo plano (ver app.js) e, quando ativa, este
     controle exibe o sol ou a lua conforme a aparência atual do SO. Um clique
     define uma preferência explícita (claro ou escuro), saindo do modo sistema. */
  .compact-toggle{flex-shrink:0;position:relative;color:var(--text);}
  .compact-toggle:hover{background:var(--hover-bg);}
  .compact-toggle[aria-pressed="false"]{background:var(--accent2);color:var(--on-accent);}
  .compact-toggle .ct-icon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);transition:opacity .15s ease,transform .15s ease;}
  .compact-toggle .ct-icon-expanded{opacity:0;transform:translate(-50%,-50%) scale(.7);}
  .compact-toggle[aria-pressed="true"] .ct-icon-compact{opacity:1;transform:translate(-50%,-50%) scale(1);}
  .compact-toggle[aria-pressed="true"] .ct-icon-expanded{opacity:0;transform:translate(-50%,-50%) scale(.7);}
  .compact-toggle[aria-pressed="false"] .ct-icon-compact{opacity:0;transform:translate(-50%,-50%) scale(.7);}
  .compact-toggle[aria-pressed="false"] .ct-icon-expanded{opacity:1;transform:translate(-50%,-50%) scale(1);}

  /* Lista de turmas selecionadas, formato do Ctrl+C. Conteúdo gerado por
     renderEnrolledDropdown() em app.js a cada abertura. */
  .enrolled-dropdown-wrap{position:relative;flex-shrink:0;}
  .enrolled-toggle{color:var(--text);}
  .enrolled-toggle:hover{background:var(--hover-bg);}
  .enrolled-toggle[aria-expanded="true"]{background:var(--accent2);color:var(--on-accent);}
  .enrolled-dropdown{position:absolute;top:calc(100% + 6px);right:0;min-width:190px;max-width:280px;
    max-height:320px;overflow-y:auto;background:var(--panel);border-radius:8px;
    box-shadow:0 4px 18px rgba(0,0,0,.18),0 0 0 1px var(--border);z-index:150;padding:5px;}
  .enrolled-dropdown[hidden]{display:none;}
  .enrolled-dropdown-empty{padding:10px 9px;font-size:12px;color:var(--muted);text-align:center;}
  .enrolled-dropdown-item{display:flex;align-items:center;justify-content:space-between;gap:6px;width:100%;}
  .enrolled-dropdown-item .edi-code,.enrolled-dropdown-item .edi-turma{
    font-family:inherit;background:transparent;border:none;cursor:pointer;color:var(--text);
    padding:6px 9px;border-radius:5px;font-size:12.5px;transition:.12s;
    font-variant-numeric:tabular-nums;}
  .enrolled-dropdown-item .edi-code{font-weight:600;flex:1 1 auto;text-align:left;}
  .enrolled-dropdown-item .edi-turma{color:var(--muted);flex:0 0 auto;}
  .enrolled-dropdown-item .edi-code:hover,.enrolled-dropdown-item .edi-code:focus-visible,
  .enrolled-dropdown-item .edi-turma:hover,.enrolled-dropdown-item .edi-turma:focus-visible{
    background:var(--hover-bg);outline:none;color:var(--accent2);}

  .theme-toggle{background:transparent;padding:0;width:56px;height:30px;border-radius:999px;flex-shrink:0;}
  .theme-toggle:hover{background:transparent;}
  .tt-track{position:relative;display:block;width:56px;height:30px;border-radius:999px;background:var(--panel2);box-shadow:inset 0 0 0 1px var(--border);}
  .tt-thumb{position:absolute;top:3px;left:3px;width:24px;height:24px;border-radius:50%;background:var(--panel);
    box-shadow:0 0 0 1px var(--border);display:flex;align-items:center;justify-content:center;color:var(--accent);
    transition:transform .2s ease;}
  .tt-thumb svg{width:14px;height:14px;}
  html[data-theme="dark"] .tt-thumb{transform:translateX(26px);}

  /* ============== ACESSIBILIDADE ============== */
  .visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
    clip:rect(0,0,0,0);white-space:nowrap;border:0;}
  table.grid caption{caption-side:top;}
  [role="button"]{outline-offset:2px;}
  /* Em toque (mobile/tablet), .cell-block recebe foco por ter tabindex="0",
     e alguns navegadores desenham o outline padrão do sistema mesmo fora
     de navegação por teclado (não respeitam :focus-visible nesse caso).
     Isso aparecia como um quadrado sobre a turma ao tocar, com ou sem
     conflito. Zeramos o :focus "puro" e mantemos o realce só para
     :focus-visible (teclado). */
  .cell-block{-webkit-tap-highlight-color:transparent;}
  .cell-block:focus{outline:none;}
  .subject-head:focus-visible,
  .turma-opt:focus-visible,
  .cell-block:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
  .theme-switch button:focus-visible,
  button:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}

  /* ============== TABLET/CELULAR: mini-prévia da grade ==============
     Mesmo breakpoint em que .main vira coluna única (linha 92): a partir
     daqui o painel de disciplinas fica empilhado acima da grade grande, e
     é justamente nesse momento — tanto em celular quanto em tablet no
     modo retrato — que a mini-grade flutuante ajuda a não perder a noção
     da grade enquanto se rola a lista de disciplinas. Por isso ela usa o
     mesmo breakpoint do layout, em vez do breakpoint mais estreito (700px)
     usado pelos ajustes exclusivos de celular logo abaixo. */
  @media(max-width:980px),(orientation:portrait){
    /* Mini-grade flutuante: presa logo abaixo da barra de ações fixa,
       ancorada via CSS (position:absolute dentro do .action-bar, que é
       sticky) — acompanha a barra sem "pular" ao rolar e sem depender de
       cálculo via JS. Some tanto quando a tabela grande está visível na
       tela quanto quando a página é rolada até o final (ver app.js), para
       não duplicar informação nem sobrar flutuando sobre o rodapé. */
    .mini-grid{
      display:grid;width:84px;height:126px;gap:1.5px;padding:5px;margin-top:8px;
      border-radius:5px;background:var(--panel2);
      box-shadow:0 4px 14px rgba(0,0,0,.28),0 0 0 1px var(--border);
      z-index:90;opacity:.78;
      pointer-events:none;transition:opacity .25s ease,transform .25s ease;
    }
    .mini-grid.mini-hidden{opacity:0;transform:translateY(-10px) scale(.9);}
    .mini-cell{border-radius:1px;background:var(--stripe);}
    .mini-cell.mini-filled{background:var(--ok);}
    .mini-cell.mini-last{background:var(--mini-last);}
    .mini-cell.mini-conflict{background:var(--danger);}
    .mini-cell.mini-preview-ok{background:var(--mini-preview-ok-bg);}
    .mini-cell.mini-preview-conflict{background:var(--preview-conflict-bg);}

    /* Busca e linha de filtros um pouco mais estreitas: a mini-grade
       flutuante fica presa no canto superior direito da tela (ancorada no
       .action-bar, que é sticky), então tanto o botão de limpar (x) da
       busca quanto o botão "Com conflito" ficavam embaixo dela, impossível
       de clicar. Aplicando a mesma margem nas duas linhas, os três botões
       de filtro (que têm flex:1) dividem igualmente o espaço que sobra e
       nenhum deles invade a área da mini-grade. */
    /* Sede e Curso ficam acima da busca, mas usam a mesma faixa de
       largura reduzida (margin-right:76px) para não passar por baixo
       da mini-grade flutuante, que fica presa no canto superior direito
       da tela (ver .mini-grid). Sem isso, os dois seletores cobriam a
       mini-tabela em vez de pararem antes dela, como a busca já fazia. */
    .course-select-wrap{margin-right:96px;}
    .course-select-wrap label{font-size:11px;}
    .course-select-wrap select{padding:6px 24px 6px 8px;font-size:12px;background-position:right 6px center;background-size:11px;}

    .search-wrap,
    .filter-row{margin-right:96px;}
    .filter-row button{font-size:10.5px;padding:7px 4px;}
    /* O pin fica um pouco mais estreito aqui: é o mesmo margin-right:96px
       acima que já limita até onde a fileira de filtros pode chegar (pra
       não passar por baixo da mini-grade flutuante); o pin, por estar
       dentro de .filter-row, respeita esse mesmo limite — só precisa ceder
       um pouco de largura própria pros três botões de texto caberem. */
    .filter-row .filter-pin-btn{flex-basis:28px;width:28px;}

    /* Grade sem scroll lateral: o min-width:860px da tabela (regra base,
       pensada pra desktop) era maior que a largura disponível em muitos
       tablets, forçando rolar para o lado só para ver sábado. Aqui a
       tabela ocupa 100% da largura do container e os dias da semana
       usam a sigla de uma letra (day-abbr) em vez do nome completo, do
       mesmo jeito que já era feito no celular — assim as 7 colunas cabem
       inteiras na tela. */
    .day-full,.day-med{display:none;}
    .day-abbr{display:inline;}
    .grid-wrap{overflow-x:hidden;}
    table.grid{min-width:0;width:100%;table-layout:fixed;}
    table.grid thead th{padding:6px 2px;font-size:11px;}
    table.grid thead th:first-child{width:40px;}
    td.time-col{font-size:9px;padding:3px 2px;line-height:1.15;word-break:break-word;white-space:normal;}
    .cell-block{padding:2px 3px;}
    .cell-block .b-name{font-size:9px;line-height:1.15;}
    .cell-block .b-sub{font-size:7.5px;}
  }

  /* ============== TABLET NO MODO PAISAGEM (largura > 980px) ==============
     Acima de 980px o .main já volta a ser duas colunas (painel de 320px +
     grade), então a tabela tenta usar seu min-width:860px da regra base
     (pensada pra desktop largo). Em tablets na horizontal (~1024–1200px de
     largura) sobra menos espaço que isso depois do painel + gap + padding,
     e o .grid-wrap (overflow-x:auto) força um scroll lateral só pra ver
     sábado. Aqui, na mesma faixa, aplicamos o mesmo tratamento "sem scroll"
     usado no tablet retrato/celular: sigla de um dia (day-abbr), tabela
     com table-layout:fixed ocupando 100% da coluna, e fontes um pouco
     menores — sem mexer no layout de duas colunas em si. */
  @media(min-width:981px) and (max-width:1240px){
    .day-full,.day-med{display:none;}
    .day-abbr{display:inline;}
    .grid-wrap{overflow-x:hidden;}
    table.grid{min-width:0;width:100%;table-layout:fixed;}
    table.grid thead th{padding:6px 2px;font-size:11px;}
    table.grid thead th:first-child{width:40px;}
    td.time-col{font-size:9px;padding:3px 2px;line-height:1.15;word-break:break-word;white-space:normal;}
    .cell-block{padding:2px 3px;}
    .cell-block .b-name{font-size:9px;line-height:1.15;}
    .cell-block .b-sub{font-size:7.5px;}
  }

  /* ============== TELAS GRANDES / 4K ==============
     main tem max-width:1650px (linha 90) pra não esticar demais em
     monitores largos — mas em 4K isso deixa uma margem enorme dos dois
     lados e o conteúdo (com fontes/alturas pensadas pra ~1400-1600px)
     fica visualmente pequeno "flutuando" no meio da tela. Aqui, a partir
     de ~1900px de largura, aumentamos o max-width, a coluna do painel de
     disciplinas e as fontes/alturas da tabela e da lista, escalando tudo
     junto — e mais um degrau a partir de ~2600px pra telas 4K "de
     verdade" (sem escala do sistema operacional).
     Importante: também exigimos altura de sobra (min-height), não só
     largura. Um monitor 1920x1080 tem largura de 4K mas pouca altura útil
     de verdade (depois de barra de abas/favoritos do navegador e barra de
     tarefas, sobra bem menos que 1080px) — se a tabela crescesse aqui do
     mesmo jeito, os horários da noite ficariam abaixo da dobra e forçariam
     rolar a página. Por isso essas regras só entram quando também há
     altura suficiente pra caber tudo sem precisar rolar. */
  @media(min-width:1900px) and (min-height:1000px){
    :root{--header-h:76px; --action-bar-h:74px; --main-vpad:52px;}
    main{max-width:2300px;grid-template-columns:420px 1fr;gap:26px;padding:26px 34px;}
    header{padding:20px 34px 10px;}
    header h1{font-size:30px;}
    .header-extras{gap:12px;}
    .theme-toggle,.tt-track{width:70px;height:38px;}
    .tt-thumb{width:32px;height:32px;top:3px;left:3px;}
    html[data-theme="dark"] .tt-thumb{transform:translateX(32px);}
    .tt-thumb svg{width:18px;height:18px;}
    .icon-btn{width:44px;height:44px;padding:11px;}
    .icon-btn svg{width:20px;height:20px;}
    .action-bar{padding:14px 34px;gap:14px;}
    .toolbar{gap:10px;}
    button{font-size:15px;padding:12px 18px;border-radius:5px;}
    .panel{padding:22px;border-radius:7px;}
    .search{font-size:17px;padding:14px 26px 14px 27px;}
    .search-icon{width:17px;height:17px;left:3px;}
    .filter-row button{font-size:13.5px;padding:10px 12px;}
    .filter-row .filter-pin-btn{flex-basis:40px;width:40px;}
    .filter-row .filter-pin-btn svg{width:16px;height:16px;}
    .subject-title{font-size:19px;}
    .subject-code{font-size:14px;height:19px;}
    .subject-prof{font-size:13px;height:16px;line-height:16px;}
    .turma-opt{font-size:15px;padding:12px 13px;}
    .turma-opt .t-prof{font-size:13px;}
    .turma-opt .t-meta{font-size:12.5px;}
    .stats{font-size:14px;gap:26px;}
    .stats b{font-size:17px;}
    table.grid thead th{font-size:16px;padding:13px 5px;}
    table.grid thead th:first-child{width:84px;}
    table.grid td{height:54px;}
    td.time-col{font-size:14px;padding:5px 3px;}
    .cell-block{padding:6px 9px;}
    .cell-block .b-name{font-size:15px;}
    .cell-block .b-sub{font-size:13px;}
    .legend-item{font-size:13px;}
    .footer-note{font-size:12px;}
  }
  @media(min-width:2600px) and (min-height:1300px){
    :root{--header-h:94px; --action-bar-h:92px; --main-vpad:64px;}
    main{max-width:3000px;grid-template-columns:520px 1fr;gap:32px;padding:32px 44px;}
    header{padding:26px 44px 12px;}
    header h1{font-size:38px;}
    .header-extras{gap:16px;}
    .theme-toggle,.tt-track{width:86px;height:46px;}
    .tt-thumb{width:40px;height:40px;top:3px;left:3px;}
    html[data-theme="dark"] .tt-thumb{transform:translateX(40px);}
    .tt-thumb svg{width:22px;height:22px;}
    .icon-btn{width:54px;height:54px;padding:14px;}
    .icon-btn svg{width:24px;height:24px;}
    .action-bar{padding:18px 44px;gap:18px;}
    .toolbar{gap:14px;}
    button{font-size:18px;padding:15px 22px;border-radius:6px;}
    .panel{padding:28px;border-radius:8px;}
    .search{font-size:20px;padding:16px 30px 16px 30px;}
    .search-icon{width:19px;height:19px;left:4px;}
    .filter-row button{font-size:16px;padding:12px 14px;}
    .filter-row .filter-pin-btn{flex-basis:48px;width:48px;}
    .filter-row .filter-pin-btn svg{width:18px;height:18px;}
    .subject-title{font-size:22px;}
    .subject-code{font-size:16px;height:21px;}
    .subject-prof{font-size:15px;height:18px;line-height:18px;}
    .turma-opt{font-size:17px;padding:14px 15px;}
    .turma-opt .t-prof{font-size:15px;}
    .turma-opt .t-meta{font-size:14px;}
    .stats{font-size:16px;gap:32px;}
    .stats b{font-size:20px;}
    table.grid thead th{font-size:19px;padding:16px 6px;}
    table.grid thead th:first-child{width:100px;}
    table.grid td{height:64px;}
    td.time-col{font-size:16px;padding:6px 4px;}
    .cell-block{padding:7px 10px;}
    .cell-block .b-name{font-size:18px;}
    .cell-block .b-sub{font-size:15px;}
    .legend-item{font-size:15px;}
    .footer-note{font-size:14px;}
  }

  /* ============== PAINEL ESQUERDO ACOMPANHA A ALTURA DA TELA ==============
     Só entra a partir de 981px (mesmo ponto em que main vira duas colunas -
     ver linha 93): abaixo disso o painel empilha acima da grade e a página
     já rola normalmente, então não faz sentido travar a altura aqui.
     Em vez de "adivinhar" um deslocamento fixo (abordagem antiga, que errava
     em telas mais baixas e fazia a lista - e a página inteira - crescer além
     da viewport), o painel vira uma coluna flex com altura exatamente igual
     ao espaço que sobra depois do header e da barra de ações (ambos medidos
     via variável CSS, atualizada nos breakpoints de tela grande/4K acima) e
     do padding vertical do <main>. A lista de disciplinas ocupa (flex:1) o
     que sobrar dentro do painel — não importa quanto os selects, a busca e
     os filtros ocupem, ela sempre absorve exatamente o restante, sem contas
     manuais. O max() garante uma altura mínima utilizável em telas muito
     baixas, mesmo que isso implique rolar a página nesse caso extremo. */
  @media(min-width:981px) and (orientation:landscape){
    .panel{display:flex;flex-direction:column;
      height:max(calc(100vh - var(--header-h) - var(--action-bar-h) - var(--main-vpad) - 6px), 400px);}
    .subject-list{flex:1;min-height:160px;max-height:none;overflow-y:auto;}
  }

  /* ============== TELA COM POUCA ALTURA (notebooks) ==============
     As regras de largura acima já encolhem os dias/colunas quando a
     janela fica estreita. Isso aqui faz o equivalente na vertical:
     em telas de notebook (largas o bastante pra manter o layout de
     duas colunas, mas com pouca altura), a grade inteira — altura das
     linhas, cabeçalho dos dias e os horários da coluna da esquerda —
     encolhe em degraus, pra caber sem precisar rolar a página. Só
     entra a partir de min-width:981px pra não se sobrepor aos ajustes
     de celular/tablet acima, que já cuidam da própria altura deles. */
  /* Faixa extra pensada pro caso mais comum de todos: monitor 1920x1080
     com o navegador maximizado. A largura é grande, mas a altura útil de
     verdade (depois de abas/barra de endereço do navegador + barra de
     tarefas do Windows) costuma sobrar bem menos que 1080px — muitas vezes
     entre 850 e 960px — o suficiente pra sobrar sem essa faixa e empurrar
     os horários da noite pra baixo da dobra, obrigando a rolar a página. */
  @media(max-height:960px) and (min-width:981px){
    table.grid thead th{padding:7px 3px;font-size:12px;}
    td.time-col{font-size:10px;padding:2.5px;}
    table.grid td{height:33px;}
    .cell-block{padding:2px 4px;}
    .cell-block .b-name{font-size:10px;}
    .cell-block .b-sub{font-size:8.5px;}
  }
  @media(max-height:820px) and (min-width:981px){
    table.grid thead th{padding:6px 3px;font-size:11.5px;}
    td.time-col{font-size:9.5px;padding:2px;}
    table.grid td{height:30px;}
    .cell-block{padding:2px 4px;}
    .cell-block .b-name{font-size:9.5px;}
    .cell-block .b-sub{font-size:8px;}
  }
  @media(max-height:680px) and (min-width:981px){
    table.grid thead th{padding:4px 3px;font-size:10.5px;}
    td.time-col{font-size:8.5px;padding:2px 1px;}
    table.grid td{height:25px;}
    .cell-block{padding:1px 3px;}
    .cell-block .b-name{font-size:8.5px;line-height:1.15;}
    .cell-block .b-sub{font-size:7px;}
  }

  /* ============== CELULAR: grade compacta sem scroll lateral ==============
     Colocado no final do arquivo de propósito: várias regras base de
     table.grid/.grid-wrap/.cell-block estão espalhadas pelo CSS com a
     mesma especificidade destas aqui, então, para garantir que estas
     realmente vençam a cascata (não dependendo só do media query), elas
     precisam vir depois no arquivo. */
  @media(max-width:700px){
    main{padding:12px 10px;gap:12px;}
    .header-title-row{width:100%;justify-content:space-between;flex-wrap:nowrap;gap:6px;}
    header h1{white-space:nowrap;font-size:19px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;min-width:0;}
    header h1 #brandUtfpr{font-size:5.9px;}
    .header-extras{gap:5px;flex-shrink:0;}
    .header-extras .icon-btn,.header-extras .compact-toggle,
    .header-extras .github-link{width:32px;height:32px;padding:0;}
    .header-extras .ct-icon{width:15px;height:15px;}
    .header-extras .github-link svg{width:15px;height:15px;}
    .header-extras .theme-toggle,.header-extras .tt-track{width:48px;height:26px;}
    .header-extras .tt-thumb{width:20px;height:20px;top:3px;left:3px;}
    html[data-theme="dark"] .header-extras .tt-thumb{transform:translateX(22px);}
    .header-extras .tt-thumb svg{width:12px;height:12px;}

    /* Exceção do celular: aqui o aviso de conflito volta a aparecer em
       cima da grade (ordem original), diferente do PC/tablet acima, onde
       ele aparece depois da tabela. Ele também precisa ficar entre o
       texto de estatísticas e os botões de template — só que esses dois
       moram dentro de .stats-row (uma única linha flex no PC). Por isso,
       no celular, .stats-row vira "display:contents": ela deixa de gerar
       uma caixa própria e .stats / .template-bar passam a ser filhos
       diretos de .content-col, podendo ser intercalados com o banner via
       "order" abaixo. */
    .stats-row{display:contents;}
    .stats{order:1;margin-bottom:8px;}
    .conflict-banner{order:2;}
    .template-bar{order:3;margin-bottom:10px;}
    .grid-wrap{order:4;}
    .legend{order:5;}
    .footer-note{order:6;}

    /* Ícones/texto usam clamp() para escalar com a largura da tela e
       sempre caber numa linha só, sem scroll lateral. */
    .action-bar{padding:8px 3vw;gap:1.5vw;}
    .action-bar .toolbar{flex-wrap:nowrap;gap:1.5vw;width:100%;justify-content:space-between;
      container-type:inline-size;container-name:toolbar;}
    .action-bar .toolbar button{padding:clamp(6px,2.2vw,11px) clamp(4px,1.6vw,10px);
      font-size:clamp(10px,3.1vw,13px);white-space:nowrap;}
    .action-bar .toolbar .icon-btn{width:clamp(26px,9vw,38px);height:clamp(26px,9vw,38px);
      padding:0;flex-shrink:0;}
    .action-bar .toolbar .icon-btn svg{width:clamp(14px,4.2vw,18px);height:clamp(14px,4.2vw,18px);}
    .action-bar .toolbar .enrolled-dropdown-wrap{flex-shrink:0;}
    .action-bar .toolbar #btnCopy,.action-bar .toolbar #btnPaste{flex:1 1 0;min-width:0;justify-content:center;}
    /* Label curta por padrão; volta para "Copiar/Colar Turmas" quando a
       toolbar tem espaço (@container, não viewport). */
    .action-bar .toolbar .btn-label-full{display:none;}
    .action-bar .toolbar .btn-label-short{display:inline;}
    @container toolbar (min-width:360px){
      .action-bar .toolbar .btn-label-full{display:inline;}
      .action-bar .toolbar .btn-label-short{display:none;}
    }

    /* Nomes dos dias reduzidos a uma única letra (S, T, Q...) e a tabela
       forçada a ocupar exatamente 100% da largura disponível, para caber
       inteira na tela sem precisar de scroll lateral. */
    .day-full,.day-med{display:none;}
    .day-abbr{display:inline;}
    .grid-wrap{overflow-x:hidden;border-radius:5px;}
    table.grid{min-width:0;width:100%;table-layout:fixed;border-radius:5px;}
    table.grid thead th{padding:4px 0;font-size:10px;}
    table.grid thead th:first-child{width:26px;}
    td.time-col{font-size:7px;padding:2px 1px;line-height:1.1;word-break:break-word;white-space:normal;}
    table.grid td{height:26px;}
    .cell-block{padding:1px 2px;inset:1px;border-radius:2px;}
    .cell-block .b-name{font-size:7.5px;line-height:1.1;}
    .cell-block .b-sub{font-size:6px;}
    .cell-block .b-room{display:none;}
    .legend-item{font-size:9px;}
    .stats{gap:10px;font-size:11px;}
    .template-bar{gap:5px;}
    .template-btn{width:26px;height:26px;font-size:11px;border-radius:3px;}
  }
  @media(max-width:420px){
    main{padding:10px 6px;}
    table.grid thead th{padding:3px 0;font-size:9px;}
    table.grid thead th:first-child{width:22px;}
    td.time-col{font-size:6.5px;}
    table.grid td{height:23px;}
    .cell-block .b-name{font-size:7px;}
    .cell-block .b-sub{font-size:5.5px;}
  }
/* Bloco de texto para SEO — conteúdo indexável explicando a ferramenta,
   fora do fluxo interativo do app. Segue a mesma largura/paleta do main. */
.seo-intro{max-width:1650px;margin:8px auto 32px;padding:0 26px;color:var(--text);}
.seo-intro h2{font-size:17px;font-weight:700;margin:24px 0 8px;font-family:var(--font-display);}
.seo-intro h3{font-size:14px;font-weight:600;margin:18px 0 6px;color:var(--text);font-family:var(--font-display);}
.seo-intro p{font-size:13px;line-height:1.6;color:var(--muted);margin:0 0 4px;max-width:820px;}
/* Fileira compacta de atalhos de teclado, em forma de "chips": cada um é
   uma tecla (ou combinação) em estilo de keycap + uma legenda curta ao
   lado. Usa as mesmas variáveis de tema do resto do site (painel/borda/
   texto), então acompanha claro/escuro automaticamente. */
.shortcuts-row{display:flex;flex-wrap:wrap;gap:8px 20px;margin-top:16px;}
.shortcut{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);white-space:nowrap;}
kbd{font-family:var(--font-display);font-size:10.5px;font-weight:600;color:var(--text);
  background:var(--panel2);border:1px solid var(--border);border-radius:4px;
  padding:2px 6px;line-height:1.5;box-shadow:0 1.5px 0 var(--border);}
@media(max-width:700px){
  .seo-intro{padding:0 14px;}
  .seo-intro h2{font-size:15px;}
  .seo-intro h3{font-size:13px;}
  .seo-intro p{font-size:12.5px;}
  .shortcuts-row{gap:7px 14px;margin-top:14px;}
  .shortcut{font-size:11px;}
  kbd{font-size:10px;padding:1.5px 5px;}
}
