Reestruturação visual das logos
This commit is contained in:
parent
131cf6ea85
commit
02b6668cce
55
CLAUDE.md
55
CLAUDE.md
@ -63,15 +63,27 @@ Portal/
|
||||
|
||||
### Logos em `static/img/`
|
||||
|
||||
`static/img/` tem três variantes do logo "D De Paula Contadores" (D em degradê dourado/marrom + texto), todas PNG com fundo transparente:
|
||||
Duas identidades visuais coexistem **de propósito** hoje: o logo cursivo "D De Paula Contadores" (usado só nos documentos/PDFs que a aplicação gera, ver abaixo) e a marca nova "P.I.D." (`.svg`, ver `pid-marca-leiame.md` em `C:\Users\Depaula\Documents\Projetos\LOGOS\pid-marca`), adotada no favicon, no login e na sidebar do Portal. **Essa separação é deliberada, não uma migração incompleta**: um documento gerado pela aplicação (contrato, procuração, recibo do Indicador de Desempenho, PDF da Simulação de Custo de Contratação) é emitido como se o próprio escritório o tivesse gerado — carrega a identidade do escritório perante o cliente, não a identidade do Portal como ferramenta interna. A marca "P.I.D." é só pra UI do Portal em si. Não migrar o logo de um gerador de documento pra "P.I.D." (nem vice-versa numa tela do Portal) sem confirmar de novo com o usuário.
|
||||
|
||||
- `logo.png` — original, texto **preto**. Serve como fonte pra gerar as outras variantes e também é usada diretamente em `index.html` (login) quando `data-theme="light"` — o card do login usa `--bg-surface` (claro nesse tema), e o texto branco de `logo-branco.png` ficava ilegível contra ele.
|
||||
- `logo-branco.png` — usada em `index.html` no login quando `data-theme="dark"` (default) e sempre no `sidebar__brand` dos 5 shells (a sidebar usa fundo frozen sempre escuro, independente do tema — ver "Sidebar" em `layout.css` — então não precisa alternar) — mesmo D colorido de `logo.png`, mas com o texto recolorido pra branco. Gerada programaticamente a partir de `logo.png` (script Python com Pillow: qualquer pixel opaco quase-neutro/escuro — `max(r,g,b) < 70` e `spread(r,g,b) < 12` — virou branco; o D nunca entra nesse filtro porque mesmo na sombra mais escura do degradê ele mantém um matiz quente nitidamente não-neutro). Se o logo oficial mudar, regerar `logo-branco.png` a partir do novo `logo.png` com o mesmo filtro, não editar à mão.
|
||||
- A troca da logo do login por tema é feita em `theme.js` (`pidSyncLoginLogo()`): o `<img id="login-logo">` de `index.html` carrega os dois caminhos resolvidos por `{% static %}` em `data-logo-dark`/`data-logo-light`, e o JS só troca o `src` conforme `data-theme` atual — chamado no load e no evento `pid:theme-changed`.
|
||||
- `logo-mono.png` — versão totalmente monocromática (D **e** texto em branco/cinza claro). Não usada em nenhum template hoje; existe como variante alternativa (útil se algum dia precisar de um logo "chapado" sem o dourado do D).
|
||||
- `favicon.png` — só o D (sem o texto "De Paula Contadores"), quadrado, 192×192, usado como ícone da aba do navegador (`<link rel="icon" type="image/png">` no `<head>` das 7 páginas). Gerado a partir de `logo.png` com o mesmo filtro de `logo-branco.png` (pixel opaco quase-neutro/escuro — `max(r,g,b) < 70` e `spread(r,g,b) < 12` — é texto, não o D), mas em vez de recolorir esses pixels pra branco, eles são apagados (`alpha = 0`); o resultado é recortado pelo bounding box do que sobrou opaco e centralizado num canvas quadrado transparente (o D é mais alto que largo). Se o logo oficial mudar, regerar a partir do novo `logo.png` com o mesmo processo, não editar à mão.
|
||||
**Logo cursivo "D De Paula Contadores"** (D em degradê dourado/marrom + texto, PNG com fundo transparente) — não aparece em nenhum template HTML hoje, só nos PDFs gerados pela aplicação:
|
||||
|
||||
Tamanho: `.sidebar__logo` é `width: 200px; height: auto` (era 56×56 fixo, esmagava o logo — a arte é bem mais larga que alta, ~1.41:1 — e ficava pequena demais); encolhe pra `44px` quando a sidebar colapsa (desktop `.is-collapsed` e o breakpoint mobile), senão o logo vaza da faixa de 76px.
|
||||
- `logo.png` — original, texto **preto**. Serve como fonte pra gerar as outras variantes e é usada diretamente no recibo do Indicador de Desempenho (`indicadores/recibo.py`, `LOGO_PATH`, redimensionada/recomprimida em memória pra impressão — ver "Indicador de Desempenho" abaixo).
|
||||
- `logo-branco.png` — usada no cabeçalho do PDF de Simulação de Custo de Contratação (`custo_contratacao/pdf.py`, banner marrom escuro, ver "Simulação de Custo de Contratação" abaixo) — até uma rodada anterior também era usada no `sidebar__brand` dos 10 shells, migrada pra marca "P.I.D." (ver abaixo; a UI do Portal e os documentos gerados usam fontes de logo independentes agora). Mesmo D colorido de `logo.png`, mas com o texto recolorido pra branco; gerada programaticamente a partir de `logo.png` (script Python com Pillow: qualquer pixel opaco quase-neutro/escuro — `max(r,g,b) < 70` e `spread(r,g,b) < 12` — virou branco; o D nunca entra nesse filtro porque mesmo na sombra mais escura do degradê ele mantém um matiz quente nitidamente não-neutro). Se o logo oficial mudar, regerar `logo-branco.png` a partir do novo `logo.png` com o mesmo filtro, não editar à mão.
|
||||
- `logo-mono.png` — versão totalmente monocromática (D **e** texto em branco/cinza claro). Não usada em nenhum consumidor hoje; existe como variante alternativa (útil se algum dia precisar de um logo "chapado" sem o dourado do D).
|
||||
|
||||
**Marca nova "P.I.D."**:
|
||||
|
||||
- `pid-icone.svg` — ícone quadrado, variante pra **fundo claro** (corpo roxo escuro `#4B2E75`); chegou a ser usada no login quando `data-theme="light"`, mas o usuário pediu pra usar sempre a mesma logo nos dois temas — **não tem mais nenhum consumidor** hoje (mesma situação de `pid-favicon.svg`/`pid-logo-horizontal.svg` abaixo).
|
||||
- `pid-icone-escuro.svg` — ícone quadrado, variante pra **fundo escuro** (corpo roxo mais claro `#7B5BA8`, pra manter contraste); usada (a) no favicon (`<link rel="icon" type="image/svg+xml">` no `<head>` das 11 páginas) e (b) no login, **sempre**, nos dois temas — o card do login já é congelado escuro nos dois temas (ver "Card de login" abaixo), e agora o ícone também, pedido explícito do usuário ("deixe no tema claro a mesma logo usada no tema escuro"; antes alternava com `pid-icone.svg` conforme `data-theme`, mecanismo removido — ver "Ícone do login é clicável" abaixo). O ícone da sidebar (expandida e colapsada, 10 shells) e o do card de login usam o **mesmo desenho/cores** desse arquivo, mas como markup `<svg>` inline copiado direto no HTML, não uma referência a este arquivo — ver "Ícone do login/sidebar são clicáveis" abaixo pro motivo (precisa expor os olhos pro CSS/JS animar o piscar ao clicar).
|
||||
- `pid-logo-horizontal-escuro.svg` — assinatura horizontal (ícone + "P.I.D." + "PORTAL INTERNO DA DE PAULA" em texto, viewBox `300×80`, texto claro `#F2EDE3`/dourado `#C6A24A` — variante pra fundo escuro). Mesmo caso do ícone acima: a sidebar expandida (10 shells) usa o mesmo desenho como `<svg>` inline, não uma referência a este arquivo.
|
||||
- `pid-favicon.svg` (versão simplificada sem o sorriso, pro leiame recomendar pra 16–24px — não usada, o favicon usa `pid-icone-escuro.svg` mesmo), `pid-logo-horizontal.svg` (variante fundo claro da assinatura) e `pid-icone.svg` (acima) não têm nenhum consumidor no Portal hoje.
|
||||
|
||||
**`sidebar__brand` com duas marcas sobrepostas (crossfade), não uma redimensionada** (`layout.css`): a sidebar expandida mostra a assinatura com texto (tem texto, ilegível se só encolhida) e a colapsada mostra só o símbolo — são dois `<svg class="sidebar__logo sidebar__logo--full">`/`<svg class="sidebar__logo sidebar__logo--icon">` **sempre presentes no DOM**, sobrepostos via `position:absolute` dentro de `.sidebar__brand` (`position:relative; height:92px`, alto o bastante pra caber as duas sem depender da altura natural de nenhuma, já que filhos absolutos não contribuem pra altura do pai). `.sidebar__logo--full` é `width:250px; max-width:96%` (quase toda a largura útil da sidebar, `264px` menos o padding horizontal de `.sidebar`) — aumentado em duas rodadas a partir do tamanho inicial (`176px`/`70%` → `220px`/`92%` → `250px`/`96%`) porque o subtítulo "PORTAL INTERNO DA DE PAULA" (fonte pequena dentro do SVG, viewBox `300×80`) ficava ilegível menor; `height:92px` acompanhou cada aumento pra sobrar espaço vertical (proporção do SVG é `300:80`, então a altura renderizada escala junto com a largura). A transição entre elas é `opacity`+`transform:scale()` (`var(--transition-base)`, mesma duração das outras animações do sidebar) — pedido explícito do usuário pra não ser uma troca brusca; `.app-shell.is-collapsed` (toggle desktop) e o breakpoint mobile (`@media (max-width:1024px)`, onde o colapsado é o estado *default* e `.is-expanded-mobile` o inverte, mesmo padrão já usado pelos demais elementos do menu nesse breakpoint) alternam qual das duas fica com `opacity:1`.
|
||||
|
||||
**Ícone do login e da sidebar são clicáveis, com os olhos piscando** (pedido explícito do usuário, em duas rodadas — primeiro a sidebar, depois o ícone do login): tanto `.sidebar__brand` (10 shells) quanto `#login-logo-btn` (`index.html`) tiveram o ícone convertido de `<img src="...svg">` pra `<svg>` **inline**, com markup idêntico ao de `pid-icone-escuro.svg` copiado direto no HTML — um `<img>` não expõe seu conteúdo interno pro CSS/JS da página (é uma imagem opaca), então não dava pra animar só os olhos sem inlinear. Dentro de cada SVG, os dois olhos (círculo creme + glint escuro) ficam num `<g class="pid-icon-eye">` próprio, sem nenhum `transform` no XML (a posição já vem dos `cx`/`cy` dos círculos) — importante porque um `transform` de CSS aplicado num elemento que já tem um `transform` de atributo **substitui** o atributo inteiro (perderia a posição); mantendo os dois olhos "limpos" desse jeito, a única transformação deles é a que a animação de piscar aplica. `.pid-icon-eye`/`.is-blinking`/`@keyframes pidIconBlink` moram em `base.css` (`transform-box:fill-box; transform-origin:center` faz o `scaleY()` girar em torno do próprio olho, não da origem do SVG; `scaleY(1)→0.05→1`, 200ms, os dois olhos piscam juntos) — em `base.css`, não em `layout.css`, porque é carregado por **todas** as páginas, inclusive `index.html` (que não carrega `layout.css`).
|
||||
|
||||
- **Sidebar** (`static/js/sidebar-brand.js`, incluído logo depois de `api.js` nos 10 shells): `.sidebar__brand` deixou de ser `<div>` e virou `<a href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">` — a mudança de tag não afeta o CSS existente (todo seletor é por classe), então o crossfade descrito acima continua igual. O script escuta o clique: ignora cliques modificados (`ctrl`/`cmd`/`shift`/botão do meio — deixa abrir em nova aba normalmente), senão faz `preventDefault()`, adiciona `.is-blinking` em todo `.pid-icon-eye` dentro do link (pega os olhos das duas marcas — a visível e a escondida pelo crossfade, inofensivo já que a escondida tem `opacity:0`) e só navega pra `portal.html` depois de 260ms, tempo suficiente pra piscada terminar de tocar antes da página trocar — mesmo espírito de "deixar a transição ser vista antes de navegar" já usado na animação de intro do login.
|
||||
- **Login** (`static/js/login-logo-blink.js`, novo): `#login-logo-btn` é um `<button type="button">` (não um link — não há pra onde navegar a partir do próprio login), sem `preventDefault`/delay nenhum, só dispara a piscada ao clicar; é puramente decorativo, sem efeito colateral. Também aqui foi a oportunidade de simplificar um mecanismo que existia só por causa do `<img>`: a logo do login **alternava** entre `pid-icone.svg`(claro)/`pid-icone-escuro.svg`(escuro) conforme `data-theme`, via `pidSyncLoginLogo()` em `theme.js` — removida junto com essa mudança, a pedido do usuário ("deixe no tema claro a mesma logo usada no tema escuro"), já que o card do login já era congelado escuro nos dois temas mesmo antes disso (ver "Card de login" abaixo) — a lógica de alternância nunca fazia muito sentido nesse contexto. Agora `#login-logo-btn` sempre usa as cores/desenho de `pid-icone-escuro.svg`, sem nenhuma checagem de tema.
|
||||
|
||||
### Backend serve o frontend (mesma origem)
|
||||
|
||||
@ -612,13 +624,13 @@ Terceiro checkbox de "Tipo de importação" (ao lado de Mensalidade/Coparticipa
|
||||
| Arquivo | Contém |
|
||||
|---|---|
|
||||
| `tokens.css` | Variáveis (`:root`, tema claro em `:root[data-theme="light"]`). |
|
||||
| `base.css` | Reset global, incluindo `[hidden] { display: none !important; }` — necessário porque vários componentes (`.no-access`, `.app-card`, `.notif-badge`) definem seu próprio `display`, o que sem o `!important` sobrescreveria o comportamento nativo de `hidden`. Também os `@keyframes` globais de animação (`pidFadeIn`/`pidFadeSlideUp`/`pidScaleIn`, ver "Animações" abaixo), já que é o único CSS carregado por **todas** as páginas sem exceção (inclusive `index.html`). |
|
||||
| `base.css` | Reset global, incluindo `[hidden] { display: none !important; }` — necessário porque vários componentes (`.no-access`, `.app-card`, `.notif-badge`) definem seu próprio `display`, o que sem o `!important` sobrescreveria o comportamento nativo de `hidden`. Também os `@keyframes` globais de animação (`pidFadeIn`/`pidFadeSlideUp`/`pidScaleIn`, ver "Animações" abaixo) e `.pid-icon-eye`/`pidIconBlink` (piscar de olho do ícone "P.I.D.", reaproveitado pela sidebar e pelo login — ver "Ícone do login e da sidebar são clicáveis" abaixo), já que é o único CSS carregado por **todas** as páginas sem exceção (inclusive `index.html`). |
|
||||
| `layout.css` | Casca do shell: `.app-shell`, `.sidebar*`, `.nav-*`, `.fav-toggle`, `.topbar*`. A sidebar usa tokens **congelados**, independentes de tema (fundo sempre escuro em claro/escuro) — não trocar por variáveis que espelham `:root[data-theme="light"]`. Exceção deliberada: `--sidebar-text-primary`/`--sidebar-text-secondary`/`--sidebar-text-muted` (texto/ícone do menu) *são* sobrescritas em `:root[data-theme="light"]` (`tokens.css`) pra branco puro — pedido explícito do usuário pra melhorar a legibilidade; só o fundo/borda da sidebar continuam frozen. Também `.page-content` (largura do conteúdo de cada página, `max-width:1200px` centralizado por padrão) + o modificador `.page-content--wide` (`max-width:1600px`) — `portal.html` ("Principal") é a única página que usa só `.page-content` puro (grade de favoritos fica mais confortável de leitura mais estreita); as outras 7 páginas (`perfis-acesso.html`, `usuarios.html`, `links-ferramentas.html`, `acessos-gerais.html`, `ramais.html`, `calendario-individual.html`, `importacao-plano-saude.html`) usam `class="page-content page-content--wide"` no `<main>`, decisão explícita do usuário pra aproveitar melhor o espaço entre a sidebar e a borda da tela em telas de tabela/formulário. Uma página nova que seja mais "aplicação" (tabela, formulário, CRUD) do que "dashboard" deve nascer já com `page-content--wide`. |
|
||||
| `components.css` | UI genérica reutilizável: `.btn-solid/.btn-outline/.btn-ghost/.btn-danger-outline`, **`.modal-overlay`/`.modal-card`** (moldura genérica de modal, + o modificador `.modal-card--wide` pra quando precisa de mais espaço horizontal) **e também** `.modal-field`/`.modal-field-row`/`.modal-checkbox`/`.modal-error`/`.modal-actions` (campos internos do modal — moldura e campos vivem juntos aqui, apesar do nome sugerir só a moldura, incluindo `select`/`textarea` dentro de `.modal-field`, com seta customizada via `background-image` porque o nativo do browser destoa do tema escuro), `.app-card*`, `.no-access`, `.checklist-box`/`.checklist-item`/`.checklist-item__info`/`.checklist-item__nome`/`.checklist-item__departamento`/`.checklist-empty`/`.checklist-search`/`.checklist-select-all` (lista com checkbox, segunda linha de detalhe e busca — usada nos checklists de Perfis de Acesso/Departamento em `usuarios.html`) e `.dual-select`/`.dual-select__*` (vinculação em duas tabelas — não vinculados/vinculados, ver seção "Liderança" — usada em `usuarios.html` e no modal "Gerenciar Usuário" de todo shell). |
|
||||
| `perfis-acesso.css` | `.pa-*` (tela de Perfis de Acesso), incluindo as seções (`.ua-section*`) e campos específicos (`.ua-inline-add`/`.ua-departamento-item`/`.ua-active-toggle`/`.ua-liderados-field`) do formulário de edição de `usuarios.html`. |
|
||||
| `calendario.css` | Só `.calendar-*` (grade mensal, células de dia, nav do mês) — os campos do modal de compromisso usam as classes genéricas `.modal-field`/`.modal-checkbox`/`.modal-error`/`.modal-actions` de `components.css`. |
|
||||
| `widgets.css` | `.widgets-*`, `.widget-card*`, `.widget-picker-*` — só usado em `portal.html`; também tem `#portal-title` (fonte "Bree Serif" do título "Portal De Paula" no topbar), que não é widget mas mora aqui por ser o único CSS próprio da página. |
|
||||
| `login.css` | Só usado em `index.html`; `.login-card__title` ("Portal De Paula") usa a mesma fonte "Bree Serif" do `#portal-title` de `portal.html`. |
|
||||
| `widgets.css` | `.widgets-*`, `.widget-card*`, `.widget-picker-*` — só usado em `portal.html`. O topbar da tela inicial não tem mais título/slogan nenhum (`<h1 id="portal-title">` — chegou a existir brevemente com o slogan "Grandes aplicações de todos os tamanhos" em fonte "Pinyon Script"/dourado, removido a pedido do usuário na mesma rodada; ver `login.css` abaixo pra onde o slogan acabou indo) — o `<link>` do Google Fonts em `portal.html` também foi removido junto, já que não sobrou nenhum uso de fonte customizada nessa página. |
|
||||
| `login.css` | Só usado em `index.html`; `.login-card__title` ("Portal Interno da De Paula") usa a fonte "Bree Serif" (importada só nesta página). O slogan da marca ("Grandes aplicações de todos os tamanhos.", `pid-marca-leiame.md` tem esse e um segundo, "Ainda funciona. Agora pensa.", não usado em lugar nenhum) mora aqui, não no topbar de `portal.html` (onde chegou a existir e foi removido, ver `widgets.css` acima) — passou primeiro pelo rodapé do card (abaixo de "Esqueceu sua senha?...") antes de subir pra logo abaixo do título, posição atual (pedido explícito do usuário). `.login-heading` (`display:flex; flex-direction:column; gap:var(--space-1)`) agrupa `.login-card__title` e `.login-slogan`, com um espaçamento bem menor entre os dois (`--space-1`) do que o `gap:var(--space-5)` que `.login-card` usa entre seus próprios filhos diretos — sem esse agrupamento, o slogan ficaria longe demais do título pra parecer uma assinatura. `.login-slogan` usa a fonte script "Pinyon Script" (mesmo `<link>` do Google Fonts de `.login-card__title`, agora com as duas famílias), `font-size:1.2rem` (menor que o `1.3rem` do título do card, pedido explícito do usuário) e cor dourada fixa `#c6a24a` (cor da marca, não um token de tema/`--accent`). O card do login é **congelado escuro nos dois temas** (`--login-card-bg`/`--login-field-bg`/`--login-border`/`--login-text-*`, definidos só em `:root` de `tokens.css`, nunca redefinidos em `:root[data-theme="light"]` — mesmo padrão de `--sidebar-*`, ver comentário ao lado deles em `tokens.css`) — pedido explícito do usuário; só o fundo da própria página ao redor do card (`.login-page`, via `--bg-canvas`/`--overlay-scrim`/`--accent-rgb`) continua acompanhando o tema claro/escuro. A logo, porém, continua alternando por `data-theme` (`pid-icone.svg` no claro/`pid-icone-escuro.svg` no escuro, ver "Marca nova P.I.D." acima) via `pidSyncLoginLogo()`/`data-logo-dark`/`data-logo-light` em `theme.js` — pedido explícito do usuário, mesmo o card ficando sempre com o mesmo fundo escuro por baixo dela. |
|
||||
| `links-ferramentas.css` | `.lf-*` — só usado em `links-ferramentas.html`. |
|
||||
| `acessos-gerais.css` | `.ag-*` — só usado em `acessos-gerais.html`. |
|
||||
| `ramais.css` | `.ram-*` — só usado em `ramais.html`; a tabela em si reaproveita `.pa-table*`/`.pa-row-actions` de `perfis-acesso.css` (mesmo padrão que `usuarios.html` já usa sem CSS próprio). |
|
||||
@ -634,3 +646,26 @@ Ao adicionar uma tela nova que precise de modal, reuse `.modal-overlay`/`.modal-
|
||||
Três `@keyframes` genéricos em `base.css` (`pidFadeIn`, `pidFadeSlideUp`, `pidScaleIn`) — reutilizados via `animation` (não `transition`) em elementos que entram/saem do layout via `hidden`/`display:none` (modal, dropdown, `.page-content` a cada navegação, `.login-card`), porque só `animation` reinicia sozinho quando um elemento passa de `display:none` para visível; `transition` não anima essa troca (não há frame intermediário). Duração sempre curta (120–200ms) — pedido explícito do usuário: "fluidas, porém rápidas, otimizando o tempo". Botões (`.btn-solid`/`.btn-outline`/`.btn-ghost`/`.btn-danger-outline`/`.icon-btn`) ganharam `transform: scale()` no `:active` como feedback de clique.
|
||||
|
||||
**Nenhuma dessas animações respeita `prefers-reduced-motion`** — decisão deliberada do usuário ("as animações devem ignorar a preferência de não mostrar animações ou de acessibilidade do computador do usuário"), não um descuido. Não adicionar um bloco `@media (prefers-reduced-motion: reduce)` desativando isso sem confirmar de novo com o usuário, já que contraria um pedido explícito.
|
||||
|
||||
### Animação de intro do login
|
||||
|
||||
Ao apertar "Entrar" com sucesso, `index.html` toca uma animação de marca em tela cheia (~6,2s: 500ms de fade + ~5,7s de animação) antes de navegar pra `portal.html` — pedido explícito do usuário, inspirado num arquivo `pid-intro-escuro.html` que ele forneceu (mesma pasta de origem dos SVGs da marca "P.I.D.", `C:\Users\Depaula\Documents\Projetos\LOGOS\pid-marca`).
|
||||
|
||||
**Origem do arquivo — por que não foi só copiado**: `pid-intro-escuro.html` não é HTML/CSS simples, é um bundle auto-contido de um editor de "Design Canvas" (Anthropic) — um `<script type="__bundler/manifest">` com um JSON mapeando uuid → recurso (`{mime, compressed, data}`, `data` sendo base64 de um gzip), incluindo o JSX fonte de verdade (`pid-intro.jsx`, a composição em si) e a biblioteca de motion (`animations-v3.jsx`, easing/interpolação), montados em tempo real por um runtime React + motor de composição por "tempo autorado" (`useComposition`/`CompositionStage`) que não faz sentido carregar em produção (pesado, e pensado pra edição/export de vídeo, não pra rodar dentro de uma página de login). A coreografia foi **extraída** (decodificado gzip+base64 por uuid, script Python ad-hoc) e **portada fielmente** pra vanilla JS/CSS — mesmas durações de cena, mesmas curvas de easing (hand-rolled, estilo Popmotion) e mesmo timing de piscada dos olhos do original; só o destino final do "voo" do ícone foi recalibrado (ver "Cena Portal" abaixo).
|
||||
|
||||
**As 4 cenas** (`PID_INTRO_CUES`/`PID_INTRO_TOTAL` em `login-intro.js` — `Build:0, Face:1, Wordmark:2, Portal:4.8`, total `5.7`): durações **aceleradas** em relação ao arquivo original (`Build`/`Face` de 2,6s/2s pra 1s cada, `Portal` de 2,3s pra ~0,9s — pedido explícito do usuário, "acelere um pouco a velocidade na qual a logo é construída"), exceto `Wordmark` (2,8s, igual ao original) — "a parte onde aparece o nome do portal deve permanecer a mesma", pedido explícito também. Os deslocamentos internos de cada cena (quando cada elemento começa/termina de animar) foram reproporcionados pra caber na duração nova, não são mais os valores originais do arquivo — só a cena Wordmark manteve os originais, já que a duração dela não mudou.
|
||||
- **Build** (1s): o contorno do corpo do ícone se desenha (`stroke-dashoffset`, `pathLength="100"` normaliza o path pra unidades 0–100 independente da geometria real), preenche a cor, a aba dourada "cai" (`easeOutBack`, dá um leve overshoot) e a "tela"/rosto do ícone abre (scale+opacity).
|
||||
- **Face** (1s): os dois olhos aparecem com "pop" (`easeOutBack`) e piscam uma vez (`pidIntroBlinkAt()` — uma janela de 220ms em que a escala vertical do olho vai de 1 a 0 e volta a 1, formando o fecha-e-abre; a mesma função é reaproveitada em 2 momentos diferentes agora, ver abaixo — o terceiro blink do original, na cena Portal, foi removido: a cena ficou curta demais pra caber um blink visível com o ícone já encolhendo/voando), o sorriso dourado se desenha (mesma técnica de `stroke-dashoffset` do corpo).
|
||||
- **Wordmark** (2,8s, **inalterada**): o ícone desliza pra esquerda (`SHIFT_X=-100px`) enquanto "P.I.D." (fonte "Space Grotesk" 700, cada letra com um "." dourado à parte) + uma régua dourada (`scaleX`) + a tagline "Portal Interno da De Paula" (fonte "DM Mono", uppercase, letter-spacing largo) aparecem — cada letra com seu próprio atraso escalonado (`CUES.Wordmark + 0.25 + i*0.13`).
|
||||
- **Portal** (~0,9s): a wordmark esmaece quase na hora (`Portal` a `Portal+0.3`), o ícone encolhe (de 160px pra 40px — o mesmo tamanho de `.sidebar__logo--icon`, ver "Logos em `static/img/`" acima) e "voa" até o canto superior esquerdo em 0,5s (`Portal+0.05` a `Portal+0.55`), e o stage inteiro (ícone+wordmark) esmaece logo depois, sobrepondo o fim do voo (`Portal+0.5` a `Portal+0.9`) — sem pausa parada entre o ícone assentar e o fade começar (ajuste de uma rodada anterior, que já tinha comprimido essa cena de 2,3s pra ~0,95s; esta rodada só encurtou mais um pouco, até ~0,9s). **Diferença deliberada em relação ao original** (além do tempo): lá o destino é um pixel fixo dentro de um frame de vídeo de exportação 1920×1080 (`logoX:-892, logoY:-496`, coordenadas que não existem em página nenhuma); aqui, `pidIntroCornerTarget()` calcula o alvo em tempo real a partir de `window.innerWidth/innerHeight`, mirando um ponto perto do canto real da janela — a ideia de "o ícone termina indo pro cabeçalho/sidebar do app" só faz sentido revisitada assim, já que o original nunca foi pensado pra rodar dentro de uma página de verdade.
|
||||
- As duas piscadas do olho (`Face+0.8`, `Wordmark+1.1`) e as três funções de easing usadas (`easeOutCubic`/`easeInOutQuad`/`easeOutBack`) seguem as fórmulas exatas extraídas de `animations-v3.jsx` — ver o código de `login-intro.js` se precisar ajustar timing, não redesenhar do zero.
|
||||
|
||||
**Fade de entrada, antes do ícone começar a se desenhar** (pedido explícito do usuário — a primeira versão fazia o overlay aparecer de repente por cima do card ainda visível, "de um modo bruto"; a duração foi ajustada de 350ms pra 500ms numa rodada seguinte, "está muito rápido... só pra ficar mais fluído"): `pidPlayLoginIntro()` aplica `.is-leaving` no `.login-card` (`login.css`, `opacity:0; transform:scale(0.98)`, transição de 500ms) e `.is-visible` no `#login-intro` (`opacity:0→1`, mesmos 500ms, `PID_INTRO_FADE_MS`) ao mesmo tempo — o card se dissolve enquanto o overlay (já na cor final sólida) sobe por cima, um cross-fade real, não uma troca instantânea. Só depois desses 500ms (`setTimeout`) é que o loop de `requestAnimationFrame` do ícone começa (`start = performance.now()` é atribuído só nesse momento, não antes).
|
||||
|
||||
**Arquivos**: `static/css/login-intro.css` (só `index.html`) — formas idênticas às já usadas em `pid-icone-escuro.svg`/`pid-logo-horizontal-escuro.svg` (hex hardcoded — `#7b5ba8`/`#c6a24a`/`#f2ede3`, não são tokens de tema, são a paleta fixa da marca, mesmo espírito de `.login-slogan` já hardcodar `#c6a24a`); a **exceção** é o fundo do overlay (`#121017`), que não é um hex da marca — é o valor fixo de `--bg-canvas` no tema escuro (`tokens.css`), usado deliberadamente em vez da cor de fundo original do arquivo fornecido (`#241c33`, roxo-tinto) pra a sequência login → animação → portal ler como uma coisa só se estruturando aos poucos, não uma troca de cenário (pedido explícito do usuário). `static/js/login-intro.js` expõe `pidPlayLoginIntro(onDone)` (global, chamada só por `auth.js`) — monta o loop de `requestAnimationFrame`, calcula cada valor (`bodyDraw`, `eyeL`, `shift`, `fly`, ...) a partir de `T` (segundos decorridos desde o início do loop, via `performance.now()`) e escreve direto nos atributos/estilo dos elementos do overlay (`#login-intro`, já presente e `hidden` no HTML de `index.html`); chama `onDone()` quando `T` atinge `PID_INTRO_TOTAL`. Fontes "Space Grotesk" (peso 700) e "DM Mono" adicionadas ao mesmo `<link>` do Google Fonts de `index.html`, junto de "Bree Serif"/"Pinyon Script" já usadas ali.
|
||||
|
||||
**Fluxo de navegação**: `auth.js`, no sucesso do `POST /api/auth/login/`, chama `pidPlayLoginIntro(() => { sessionStorage.setItem("pid_reveal_portal", "1"); window.location.href = "portal.html"; })` em vez de navegar direto — a navegação só acontece depois da animação inteira (não há como "pular" a animação hoje, nem foi pedido).
|
||||
|
||||
**"A barra lateral surgindo da esquerda para a direita, e em seguida o resto da tela"** (pedido explícito do usuário sobre como a tela Principal deveria surgir depois da animação, refinado duas vezes: a primeira versão só escondia `.main-content` e deixava a sidebar sempre visível desde o início, sem nenhuma entrada própria; a segunda versão deu à sidebar um fade + deslize sutil de 16px, considerado "ainda não satisfatório" — pequeno demais pra ler como "surgindo da esquerda pra direita"): `static/js/portal-reveal.js` (só `portal.html`, incluído `defer` logo depois de `theme.js` — mesmo padrão de "script que roda como IIFE de topo antes da primeira pintura pra evitar flash", ver "Ordem de `<script>`" acima) checa a `sessionStorage` marcada por `auth.js`; se presente, remove a marca (não sobrevive a um F5) e aplica **duas** classes em `<html>` antes do `DOMContentLoaded`: `pid-entering-sidebar` (esconde só `.sidebar`, `opacity:0` + `transform:translateX(-100%)` — a largura inteira dela, não um deslize de poucos pixels, pra realmente ler como um slide de fora da tela) e `pid-entering` (esconde `.main-content`, o `<div>` que envolve topbar **e** conteúdo da página). As duas são removidas **em sequência**, não juntas: `pid-entering-sidebar` sai primeiro (120ms depois do `DOMContentLoaded`), a sidebar desliza da esquerda pra direita ao longo de 420ms (`.sidebar` em `layout.css` tem uma `transition` própria — `opacity 420ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1)`, mais longa e com uma curva de "chegada" suave, não `var(--transition-base)` — genérica demais pra um movimento desse tamanho); só depois de esperar essa mesma duração (420ms) é que `pid-entering` sai, revelando o resto do app num fade, garantindo que as duas entradas não se sobreponham. Acessar `portal.html` direto (sem passar pelo login) nunca aciona nada disso, já que a `sessionStorage` só é setada no caminho de login bem-sucedido.
|
||||
|
||||
Testado pelo usuário em três rodadas (funcional) — ajustes até agora: a cor do overlay (era `#241c33`, virou `#121017`), o fade de entrada antes do ícone começar a se desenhar (não existia, overlay aparecia de repente; a duração foi ajustada depois de 350ms pra 500ms, "muito rápido... só pra ficar mais fluído"), a compressão da cena Portal (era 2,3s com pausa parada, foi pra 0,95s corrida numa rodada e depois ~0,9s), a aceleração de Build/Face (de 2,6s/2s cada pra 1s cada, Wordmark mantida em 2,8s de propósito) e a entrada da sidebar em `portal.html` (de um fade sutil de 16px pra um slide de fora da tela inteiro, `translateX(-100%)`, 420ms). Ainda falta conferir o posicionamento do "voo" final em diferentes tamanhos de tela/com a sidebar colapsada.
|
||||
|
||||
49
plano.md
49
plano.md
@ -978,6 +978,55 @@ Uma primeira versão tentou resolver isso em `Usuario.save()` (model), mas foi a
|
||||
|
||||
**Complemento no mesmo dia**: usuário reportou visualmente que usuários inativos ainda apareciam nos dois widgets de vinculação (dual-select de "Usuários sob liderança" e de "Usuários do Escritório" em Perfis de Acesso) — pediu que usuário inativo nunca seja exibido em nenhum dos dois painéis (nem disponível, nem já vinculado). Corrigido: `listaParaPainelUsuarios()` (`profiles.js`) agora filtra `usuariosCacheAtual` por `is_active` antes de separar entre disponível/vinculado (removido também o selo "Inativo" que antes marcava um usuário inativo ainda vinculado, já que esse caso não deve mais aparecer); `fillLideradosChecklist()` (`users-admin.js`) ganhou o mesmo filtro. No modal "Gerenciar Usuário" (`account.js`) já não era um problema — `GET /api/usuarios-resumo/` só devolve usuários ativos.
|
||||
|
||||
### 73. Nova identidade visual "P.I.D." — favicon, login e sidebar
|
||||
|
||||
Usuário forneceu uma nova marca (`C:\Users\Depaula\Documents\Projetos\LOGOS\pid-marca`, ver `pid-marca-leiame.md`) e pediu a adoção progressiva no Portal, mantendo o logo cursivo "D De Paula Contadores" só nos documentos/PDFs gerados pela aplicação (contrato, procuração, recibo do Indicador de Desempenho, simulação de custo de contratação) — decisão explícita: esses documentos são emitidos como se o próprio escritório os tivesse gerado, carregam a identidade dele perante o cliente, não a do Portal como ferramenta interna.
|
||||
|
||||
- **Favicon**: trocado de `favicon.png` (variante antiga do "D") pra `pid-icone-escuro.svg` (ícone quadrado da marca nova, variante fundo escuro) nas 11 páginas.
|
||||
- **Login (`index.html`)**: o card ficou **congelado escuro nos dois temas** (tokens dedicados `--login-card-bg`/`--login-field-bg`/`--login-border`/`--login-text-*` em `tokens.css`, nunca redefinidos em `:root[data-theme="light"]` — mesmo padrão da sidebar) — pedido explícito depois de uma primeira tentativa (só a caixa de login/senha escura) não ter sido o que o usuário queria; só o fundo da página ao redor do card continua claro/escuro por tema. A logo alterna entre `pid-icone.svg`/`pid-icone-escuro.svg` conforme `data-theme` (`pidSyncLoginLogo()` em `theme.js`), e o texto "Portal De Paula" virou "Portal Interno da De Paula". Um slogan da marca ("Grandes aplicações de todos os tamanhos.", fonte "Pinyon Script"/dourado `#c6a24a`) foi adicionado — testado primeiro no topbar de `portal.html`, removido de lá a pedido do usuário, e reintroduzido no login (rodapé, depois movido pra logo abaixo do título), tamanho ajustado até ficar legível sem competir com o título.
|
||||
- **Sidebar** (10 shells): `sidebar__brand` passou a ter duas logos sempre no DOM, sobrepostas com `position:absolute` dentro de um container de altura fixa, alternando por `opacity`+`scale()` (crossfade, não troca de `src`) conforme a sidebar está expandida (`pid-logo-horizontal-escuro.svg`, assinatura com texto) ou colapsada (`pid-icone-escuro.svg`, só o símbolo) — sempre as variantes "-escuro", já que a sidebar é sempre escura nos dois temas. Tamanho da logo expandida aumentado em duas rodadas (176px/70% → 220px/92% → 250px/96% da largura útil) até o subtítulo "PORTAL INTERNO DA DE PAULA" ficar legível.
|
||||
|
||||
Ver `CLAUDE.md` ("Logos em `static/img/`") pro estado final detalhado de cada arquivo.
|
||||
|
||||
### 74. Animação de intro pós-login (porta de `pid-intro-escuro.html`)
|
||||
|
||||
Usuário forneceu um segundo arquivo da mesma pasta de marca, `pid-intro-escuro.html` — um bundle de "Design Canvas" (Anthropic) com uma animação de apresentação da marca P.I.D. (composição em 4 cenas: o ícone se desenha, ganha rosto, desliza pra revelar o wordmark "P.I.D." + tagline, e por fim voa/esmaece). Pediu pra reproduzir essa animação como transição entre o login e a tela Principal: ao clicar "Entrar" com sucesso, a animação toca por inteiro e só depois a tela Principal aparece, "pela barra lateral primeiro".
|
||||
|
||||
O arquivo fornecido não é HTML/CSS simples — é um bundle auto-contido do editor de canvas com um runtime próprio (React + motor de composição por tempo autorado "OM", fontes e o JSX fonte embutidos como blobs base64/gzip dentro de um `<script type="__bundler/manifest">`). Decodificado (script Python ad-hoc, gzip+base64 por uuid) pra extrair o JSX de verdade (`pid-intro.jsx`) e a biblioteca de easing/interpolação (`animations-v3.jsx`) — essas fórmulas na íntegra permitiram portar a coreografia **fielmente** (mesmas durações de cena, mesmas curvas de easing hand-rolled tipo Popmotion, mesmo timing de blink dos olhos) pra vanilla JS/CSS, sem carregar o runtime React/canvas original (pesado demais e não pensado pra produção).
|
||||
|
||||
- **Cenas** (mesma duração do original, 9.7s no total): Build (2.6s, contorno do ícone se desenha, aba dourada cai, tela do "rosto" abre) → Face (2s, olhos aparecem com pop e piscam, sorriso dourado se desenha) → Wordmark (2.8s, ícone desliza pra esquerda enquanto "P.I.D." + régua dourada + "Portal Interno da De Paula" aparecem) → Portal (2.3s, wordmark some, ícone encolhe e "voa" até o canto superior esquerdo real da janela — não as coordenadas de um frame de vídeo 1920×1080 do arquivo original, recalibradas pra mirar onde a logo colapsada da sidebar (`.sidebar__logo--icon`, 40px) realmente fica — e a cena inteira esmaece).
|
||||
- **Arquivos novos**: `static/css/login-intro.css` (só `index.html`) e `static/js/login-intro.js` (motor de animação — easing/`animate`/`clamp`/render por `requestAnimationFrame`, tudo portado das fórmulas extraídas). Cores/formas idênticas às já usadas em `pid-icone-escuro.svg`/`pid-logo-horizontal-escuro.svg` (hardcoded, não são tokens de tema — é a paleta fixa da marca). Fontes "Space Grotesk" (wordmark) e "DM Mono" (tagline) adicionadas ao `<link>` de fontes de `index.html`, junto de "Bree Serif"/"Pinyon Script" já usadas ali.
|
||||
- **Fluxo**: `auth.js`, no sucesso do POST de login, chama `pidPlayLoginIntro(onDone)` em vez de navegar direto — só ao final da animação (`onDone`) marca `sessionStorage.pid_reveal_portal="1"` e navega pra `portal.html`.
|
||||
- **"Aparecendo primeiro pela barra lateral"**: novo `static/js/portal-reveal.js` (só `portal.html`, IIFE de topo tipo `theme.js`) — se a sessionStorage tiver a marca, aplica `html.pid-entering` antes da primeira pintura (evita flash) e remove a classe ~350ms depois do `DOMContentLoaded`. `layout.css` esconde `.main-content` (topbar+conteúdo) enquanto essa classe está presente, sem afetar `.sidebar` — como a sidebar não é tocada, ela fica visível o tempo todo e "aparece primeiro", com o resto do app surgindo num fade logo depois. Acesso direto a `portal.html` (sem passar pelo login) não aciona nada disso, já que a sessionStorage nunca é setada nesse caminho.
|
||||
|
||||
**Ainda não testado num navegador de verdade** — a próxima rodada deve conferir o resultado visual completo (timing, posição do "fly" final em diferentes tamanhos de tela, e o crossfade da sidebar) antes de considerar fechado.
|
||||
|
||||
**Três ajustes no mesmo dia, depois do primeiro teste real** (funcional, mas com pontos a melhorar): (1) a cor de fundo do overlay (`#241c33`, roxo-tinto do arquivo original) destoava do fundo real do Portal — trocada pra `#121017`, o mesmo valor de `--bg-canvas` no tema escuro, pra a sequência login→animação→portal ler como uma coisa só; (2) o overlay aparecia de repente por cima do card de login ainda visível ("de um modo bruto") — agora o card se dissolve (`.login-card.is-leaving`) enquanto o overlay sobe (`.login-intro.is-visible`), um cross-fade de 350ms, e só depois disso o ícone começa a se desenhar; (3) a cena final (Portal) tinha uma pausa parada depois do ícone já ter chegado ao canto até o fade acontecer — comprimida de 2,3s pra 0,95s (wordmark some quase na hora, ícone voa em 0,6s, tudo esmaece logo em seguida, sem intervalo morto) — duração total da animação caiu de 9,7s pra 8,35s.
|
||||
|
||||
**Quarto ajuste, mesmo dia**: a revelação da tela Principal (rodada 74) só escondia `.main-content`, deixando a sidebar sempre visível desde o início (sem nenhuma entrada própria) — usuário pediu mais fluidez, com a sidebar de fato aparecendo antes do resto. `portal-reveal.js` passou a aplicar duas classes em sequência: `pid-entering-sidebar` (esconde só a sidebar, com um leve `opacity`+`translateX(-16px)`) sai primeiro, 120ms depois do `DOMContentLoaded`; só 200ms depois disso é que `pid-entering` (esconde `.main-content`) sai, revelando o resto do app.
|
||||
|
||||
**Quinto e sexto ajustes, rodada seguinte**: (5) usuário pediu pra acelerar a construção do ícone — `Build` e `Face` (2,6s/2s no original) foram pra **1s cada**, `Wordmark` ("a parte onde aparece o nome do portal") ficou **igual** (2,8s, pedido explícito de não mexer), e `Portal` ("a parte na qual ele some") foi arredondada pra **~1s** também — total da animação caiu de 8,35s pra 5,7s; os deslocamentos internos de cada cena precisaram ser reproporcionados pra caber nas durações novas (não é só trocar `CUES`, os offsets tipo `Build+1.15` etc. também mudaram), e o terceiro blink do olho (na cena Portal) foi removido por não caber mais visivelmente numa cena tão curta. (6) A entrada da sidebar em `portal.html` (ajuste anterior, `opacity`+`translateX(-16px)`) foi considerada "ainda não satisfatória" — pequena demais pra ler como "a barra lateral surgindo da esquerda pra direita". Trocada por um slide de verdade: `translateX(-100%)` (a largura inteira da sidebar, não 16px) com uma transição própria de 420ms e curva de chegada suave (`cubic-bezier(0.16, 1, 0.3, 1)`, não `var(--transition-base)`); o tempo de espera antes de revelar o resto do app também subiu de 200ms pra 420ms, pra não sobrepor as duas entradas.
|
||||
|
||||
**Sétimo ajuste, rodada seguinte**: o fade de entrada (card se dissolvendo + overlay subindo, antes do ícone começar a se desenhar) estava "muito rápido" — a duração (350ms, tanto em `login.css`/`login-intro.css` quanto em `PID_INTRO_FADE_MS` de `login-intro.js`) subiu pra **500ms**, um ajuste pequeno de propósito ("bem pouco, só pra ficar mais fluído").
|
||||
|
||||
### 75. Logo da sidebar vira link pra "Principal", com os olhos do ícone piscando ao clicar
|
||||
|
||||
Usuário pediu duas coisas sobre a marca da sidebar (`sidebar__brand`, presente nos 10 shells): (1) transformá-la num botão/link que navegue pra `portal.html` (tela Principal) e (2) uma animação de piscar nos olhos do ícone (o "disquete") ao clicar.
|
||||
|
||||
`.sidebar__brand` deixou de ser `<div>` e virou `<a href="portal.html" id="sidebar-brand-link">` — mudança de tag que não quebra nada, já que todo CSS do crossfade (rodada 20/72) é por classe. O ponto difícil: as duas logos ali (`pid-logo-horizontal-escuro.svg` expandida, `pid-icone-escuro.svg` colapsada) eram `<img src="...svg">`, e uma `<img>` é uma imagem opaca — não dá pra CSS/JS da página alcançar elementos internos dela (os olhos) pra animar. Solução: **inlinear** o markup das duas logos como `<svg>` de verdade, direto no HTML dos 10 shells (os arquivos `.svg` continuam existindo em `static/img/`, só não são mais referenciados por essa parte da sidebar — favicon continua usando o arquivo normalmente).
|
||||
|
||||
Dentro do SVG inline, os dois olhos (círculo creme + glint escuro) ficam cada um num `<g class="sidebar-icon-eye__lid">` (renomeada pra `.pid-icon-eye` na rodada seguinte, ver abaixo) sem nenhum `transform` de atributo XML — detalhe técnico importante: um `transform` CSS aplicado a um elemento que já tem `transform` de atributo **substitui** o atributo inteiro (perderia a posição do olho). `static/js/sidebar-brand.js` (novo, incluído nos 10 shells) escuta o clique: ignora cliques modificados (ctrl/cmd/shift/meio, deixa abrir em nova aba normal), senão previne a navegação, adiciona `.is-blinking` nos olhos (dispara `@keyframes pidSidebarBlink` em `layout.css`, `scaleY(1)→0.05→1`, 200ms) e só navega de fato 260ms depois — tempo da piscada terminar de tocar antes da página trocar, mesmo espírito já usado na animação de intro do login (rodada 74).
|
||||
|
||||
### 76. Mesma piscada no ícone do login + logo do login deixa de alternar por tema
|
||||
|
||||
Usuário pediu duas coisas: (1) o mesmo efeito de piscar do olho (rodada 75) também no ícone do card de login, ao clicar; (2) usar a **mesma logo nos dois temas** no login (parar de alternar `pid-icone.svg`/`pid-icone-escuro.svg` conforme `data-theme`).
|
||||
|
||||
(2) foi resolvida primeiro, e simplificou (1): já que o card do login é congelado escuro nos dois temas desde uma rodada anterior, a alternância de logo por tema nunca fez muito sentido — removida (`pidSyncLoginLogo()` tirada de `theme.js`, os atributos `data-logo-dark`/`data-logo-light` tirados de `index.html`); a logo do login agora sempre usa as cores de `pid-icone-escuro.svg`, sem checagem de tema nenhuma. Isso deixou `pid-icone.svg` (a variante clara) sem nenhum consumidor no Portal.
|
||||
|
||||
Pra (1), mesmo problema técnico da rodada 75 (não dá pra animar dentro de um `<img>`) — o ícone do login virou `<button type="button" id="login-logo-btn">` com o SVG inline dentro (igual à sidebar), e `static/js/login-logo-blink.js` (novo, só `index.html`) dispara a piscada ao clicar — sem `preventDefault`/delay/navegação, já que estamos na própria tela de login, é só um toque decorativo.
|
||||
|
||||
**Refatoração de nomes, pra reaproveitar entre os dois lugares**: como agora dois contextos diferentes (sidebar e login) piscam o mesmo ícone, `.sidebar-icon-eye__lid`/`pidSidebarBlink` (que moravam em `layout.css`, não carregado por `index.html`) foram renomeados pra `.pid-icon-eye`/`pidIconBlink` e movidos pra `base.css` (único CSS comum às duas telas) — `layout.css` e os 10 shells foram atualizados pra usar o nome novo.
|
||||
|
||||
## Roadmap / próximos passos
|
||||
|
||||
Nenhuma pendência explícita em aberto no momento, exceto a limitação conhecida
|
||||
|
||||
@ -109,6 +109,33 @@ svg {
|
||||
}
|
||||
}
|
||||
|
||||
/* Olhos do ícone "P.I.D." (o disquete) piscando ao clicar — usado tanto na
|
||||
logo da sidebar (`sidebar-brand.js`, `layout.css`) quanto no ícone do
|
||||
card de login (`login-logo-blink.js`), por isso mora aqui em vez de num
|
||||
CSS específico de página. Cada olho é um <g class="pid-icon-eye"> sem
|
||||
nenhum transform de atributo XML (a posição já vem dos cx/cy dos
|
||||
círculos) — importante porque um transform de CSS aplicado a um elemento
|
||||
que já tem transform de atributo SUBSTITUI o atributo inteiro, perdendo a
|
||||
posição; `transform-box:fill-box` faz o scaleY girar em torno do próprio
|
||||
olho, não da origem do SVG. */
|
||||
.pid-icon-eye {
|
||||
transform-box: fill-box;
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.pid-icon-eye.is-blinking {
|
||||
animation: pidIconBlink 200ms ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes pidIconBlink {
|
||||
0%, 100% {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
50% {
|
||||
transform: scaleY(0.05);
|
||||
}
|
||||
}
|
||||
|
||||
/* scrollbar discreta */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
|
||||
@ -19,21 +19,55 @@
|
||||
gap: var(--space-4);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
/* Duração/curva própria (não var(--transition-base)) só pra entrada em
|
||||
portal.html vinda do login (ver .pid-entering-sidebar abaixo) — um
|
||||
slide precisa de mais tempo e uma curva com "chegada" suave pra ler
|
||||
como um movimento de verdade, não um fade genérico de microinteração. */
|
||||
transition: opacity 420ms ease, transform 420ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.sidebar__brand {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 92px;
|
||||
padding: var(--space-2) 0 var(--space-3);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebar__brand:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 2px;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
/* Duas marcas em cima uma da outra (não uma só redimensionada) — a horizontal
|
||||
tem texto (ilegível encolhida), o ícone é só o símbolo quadrado. O
|
||||
cross-fade (opacity + scale) entre elas, em vez de trocar o `src` na hora,
|
||||
é o que deixa a transição expandir/recolher fluida em vez de brusca. */
|
||||
.sidebar__logo {
|
||||
width: 200px;
|
||||
max-width: 60%;
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
object-fit: contain;
|
||||
transition: width var(--transition-base);
|
||||
transition: opacity var(--transition-base), transform var(--transition-base);
|
||||
}
|
||||
|
||||
.sidebar__logo--full {
|
||||
width: 250px;
|
||||
max-width: 96%;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
|
||||
.sidebar__logo--icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -50%) scale(0.85);
|
||||
}
|
||||
|
||||
.sidebar__nav {
|
||||
@ -248,8 +282,14 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.app-shell.is-collapsed .sidebar__logo {
|
||||
width: 44px;
|
||||
.app-shell.is-collapsed .sidebar__logo--full {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -50%) scale(0.85);
|
||||
}
|
||||
|
||||
.app-shell.is-collapsed .sidebar__logo--icon {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
|
||||
.app-shell.is-collapsed .nav-item-row {
|
||||
@ -307,6 +347,24 @@
|
||||
|
||||
.main-content {
|
||||
min-width: 0;
|
||||
transition: opacity var(--transition-base);
|
||||
}
|
||||
|
||||
/* Ligado só em portal.html, só quando se chega ali logo depois da animação
|
||||
de intro do login (ver portal-reveal.js) — duas classes, removidas em
|
||||
sequência pelo JS: primeiro a sidebar desliza de fora da tela (esquerda
|
||||
pra direita, `translateX(-100%)` — toda a largura dela, não um deslize
|
||||
sutil de poucos pixels, pra realmente ler como "a barra lateral surgindo"
|
||||
em vez de só um fade) até a posição final; só depois o resto do app
|
||||
aparece num fade (`pid-entering`), em vez das duas coisas surgirem ao
|
||||
mesmo tempo. */
|
||||
html.pid-entering-sidebar .sidebar {
|
||||
opacity: 0;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
html.pid-entering .main-content {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
@ -344,16 +402,28 @@
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.app-shell .sidebar__logo {
|
||||
width: 44px;
|
||||
.app-shell .sidebar__logo--full {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -50%) scale(0.85);
|
||||
}
|
||||
|
||||
.app-shell .sidebar__logo--icon {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
|
||||
.app-shell.is-expanded-mobile {
|
||||
grid-template-columns: var(--sidebar-width) 1fr;
|
||||
}
|
||||
|
||||
.app-shell.is-expanded-mobile .sidebar__logo {
|
||||
width: 200px;
|
||||
.app-shell.is-expanded-mobile .sidebar__logo--full {
|
||||
opacity: 1;
|
||||
transform: translate(-50%, -50%) scale(1);
|
||||
}
|
||||
|
||||
.app-shell.is-expanded-mobile .sidebar__logo--icon {
|
||||
opacity: 0;
|
||||
transform: translate(-50%, -50%) scale(0.85);
|
||||
}
|
||||
|
||||
.app-shell.is-expanded-mobile .nav-item__label,
|
||||
|
||||
164
static/css/login-intro.css
Normal file
164
static/css/login-intro.css
Normal file
@ -0,0 +1,164 @@
|
||||
/* Animação de intro pós-login — portada de pid-intro-escuro.html (composição
|
||||
por cenas Build/Face/Wordmark/Portal, ver CLAUDE.md "Animação de intro do
|
||||
login"). Cores e formas idênticas às do resto da marca P.I.D. já usada no
|
||||
Portal (mesmos hex de pid-icone-escuro.svg/pid-logo-horizontal-escuro.svg),
|
||||
hardcoded aqui como nesses SVGs — não são tokens de tema, são a paleta fixa
|
||||
da marca. Só usado em index.html. */
|
||||
|
||||
.login-intro {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 200;
|
||||
/* Mesmo tom de --bg-canvas (tema escuro, valor fixo — não var(), já que o
|
||||
card do login e a animação são congelados escuros nos dois temas, ver
|
||||
"Card de login" em login.css) — não a cor de fundo original do arquivo
|
||||
fornecido (#241c33, roxo-tinto), pra a transição login → animação →
|
||||
portal ler como uma coisa só se estruturando aos poucos, não uma troca
|
||||
de cenário. */
|
||||
background: #121017;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 500ms ease;
|
||||
}
|
||||
|
||||
.login-intro.is-visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.login-intro__stage {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.login-intro__icon {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
flex: none;
|
||||
overflow: visible;
|
||||
transform: translate(0, 0) scale(1);
|
||||
}
|
||||
|
||||
.login-intro__body {
|
||||
fill: #7b5ba8;
|
||||
fill-opacity: 0;
|
||||
stroke: #7b5ba8;
|
||||
stroke-width: 1.4;
|
||||
stroke-linejoin: round;
|
||||
stroke-dasharray: 100;
|
||||
stroke-dashoffset: 100;
|
||||
stroke-opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__tab {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__tab rect:first-child {
|
||||
fill: #c6a24a;
|
||||
}
|
||||
|
||||
.login-intro__tab rect:last-child {
|
||||
fill: #7b5ba8;
|
||||
}
|
||||
|
||||
.login-intro__screen {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__screen rect {
|
||||
fill: #241c33;
|
||||
}
|
||||
|
||||
.login-intro__eye {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__eye circle {
|
||||
fill: #f2ede3;
|
||||
}
|
||||
|
||||
.login-intro__eye .login-intro__glint {
|
||||
fill: #241c33;
|
||||
}
|
||||
|
||||
.login-intro__smile {
|
||||
fill: none;
|
||||
stroke: #c6a24a;
|
||||
stroke-width: 3;
|
||||
stroke-linecap: round;
|
||||
stroke-dasharray: 100;
|
||||
stroke-dashoffset: 100;
|
||||
stroke-opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__wordmark {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 14px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__letters {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.login-intro__letter {
|
||||
display: inline-block;
|
||||
font-family: "Space Grotesk", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 3rem;
|
||||
letter-spacing: 0.03em;
|
||||
color: #f2ede3;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.login-intro__dot {
|
||||
color: #c6a24a;
|
||||
}
|
||||
|
||||
.login-intro__rule {
|
||||
width: 220px;
|
||||
height: 3px;
|
||||
background: #c6a24a;
|
||||
transform-origin: left center;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
.login-intro__tagline {
|
||||
font-family: "DM Mono", ui-monospace, monospace;
|
||||
font-size: 0.85rem;
|
||||
letter-spacing: 0.22em;
|
||||
text-transform: uppercase;
|
||||
color: rgba(242, 237, 227, 0.62);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.login-intro__stage {
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.login-intro__icon {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.login-intro__letter {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.login-intro__rule {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.login-intro__tagline {
|
||||
font-size: 0.65rem;
|
||||
letter-spacing: 0.16em;
|
||||
}
|
||||
}
|
||||
@ -13,8 +13,8 @@
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 380px;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
background: var(--login-card-bg);
|
||||
border: 1px solid var(--login-border);
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-lg);
|
||||
padding: var(--space-6) var(--space-5);
|
||||
@ -23,12 +23,39 @@
|
||||
align-items: center;
|
||||
gap: var(--space-5);
|
||||
animation: pidScaleIn 200ms ease;
|
||||
transition: opacity 500ms ease, transform 500ms ease;
|
||||
}
|
||||
|
||||
/* Login bem-sucedido: o card se dissolve (em vez de a animação de intro só
|
||||
aparecer por cima dele de repente) — ver pidPlayLoginIntro() em
|
||||
login-intro.js, que aplica esta classe e só começa a desenhar o ícone
|
||||
depois que essa transição (mesma duração, 500ms, PID_INTRO_FADE_MS)
|
||||
termina. */
|
||||
.login-card.is-leaving {
|
||||
opacity: 0;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* O ícone é um <svg> inline dentro de um <button> (não mais <img>) — só
|
||||
assim dá pra CSS/JS alcançar os olhos e piscar ao clicar
|
||||
(login-logo-blink.js). Mesma logo nos dois temas de propósito (ver
|
||||
comentário em "Logos em static/img/" no CLAUDE.md) — não alterna mais por
|
||||
data-theme. */
|
||||
.login-card__logo-btn {
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-card__logo {
|
||||
width: 200px;
|
||||
height: auto;
|
||||
object-fit: contain;
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
}
|
||||
|
||||
.login-heading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-1);
|
||||
}
|
||||
|
||||
.login-card__title {
|
||||
@ -36,7 +63,19 @@
|
||||
font-size: 1.3rem;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--text-primary);
|
||||
color: var(--login-text-primary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Slogan da marca, discreto — fonte script "Pinyon Script" (ver
|
||||
pid-marca-leiame.md), logo abaixo do título (.login-heading tem um gap bem
|
||||
menor que o gap:var(--space-5) que .login-card usa entre seus próprios
|
||||
filhos diretos, senão o slogan ficaria longe demais do título pra parecer
|
||||
uma assinatura). Menor que o título (1.3rem) pra não competir com ele. */
|
||||
.login-slogan {
|
||||
font-family: "Pinyon Script", cursive;
|
||||
font-size: 1.2rem;
|
||||
color: #c6a24a;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -56,15 +95,15 @@
|
||||
.field label {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary);
|
||||
color: var(--login-text-secondary);
|
||||
}
|
||||
|
||||
.field__control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-2);
|
||||
background: var(--bg-canvas);
|
||||
border: 1px solid var(--border-subtle);
|
||||
background: var(--login-field-bg);
|
||||
border: 1px solid var(--login-border);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0 var(--space-3);
|
||||
transition: border-color var(--transition-fast);
|
||||
@ -75,7 +114,7 @@
|
||||
}
|
||||
|
||||
.field__control svg {
|
||||
color: var(--text-muted);
|
||||
color: var(--login-text-muted);
|
||||
}
|
||||
|
||||
.field__control input {
|
||||
@ -85,17 +124,22 @@
|
||||
outline: none;
|
||||
padding: var(--space-3) 0;
|
||||
font-size: 0.95rem;
|
||||
color: var(--login-text-primary);
|
||||
}
|
||||
|
||||
.field__control input::placeholder {
|
||||
color: var(--login-text-muted);
|
||||
}
|
||||
|
||||
.field__toggle {
|
||||
color: var(--text-muted);
|
||||
color: var(--login-text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--space-1);
|
||||
}
|
||||
|
||||
.field__toggle:hover {
|
||||
color: var(--text-secondary);
|
||||
color: var(--login-text-secondary);
|
||||
}
|
||||
|
||||
.field__error {
|
||||
@ -124,7 +168,7 @@
|
||||
|
||||
.login-help {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
color: var(--login-text-muted);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@ -42,6 +42,18 @@
|
||||
--sidebar-hover-bg: #221e2c;
|
||||
--sidebar-border: #2c2836;
|
||||
|
||||
/* Card de login (index.html) é sempre escuro, nos dois temas — mesma lógica
|
||||
da sidebar acima. Só o fundo da página ao redor do card (.login-page)
|
||||
continua acompanhando o tema claro/escuro; o card em si (e tudo dentro
|
||||
dele) usa estas cores fixas em vez de --bg-surface/--bg-canvas/--text-*,
|
||||
que se invertem por tema. Não redefinir em :root[data-theme="light"]. */
|
||||
--login-card-bg: #1a1721;
|
||||
--login-field-bg: #121017;
|
||||
--login-border: #2c2836;
|
||||
--login-text-primary: #f5f3f8;
|
||||
--login-text-secondary: #a9a3b8;
|
||||
--login-text-muted: #726c81;
|
||||
|
||||
--overlay-scrim: rgba(10, 8, 14, 0.72);
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
|
||||
--shadow-md: 0 8px 24px rgba(0, 0, 0, 0.35);
|
||||
|
||||
@ -1,11 +1,3 @@
|
||||
/* Título "Portal De Paula" no topbar da tela inicial — não é widget, mas
|
||||
widgets.css é o único CSS próprio de portal.html, então fica aqui. */
|
||||
#portal-title {
|
||||
font-family: "Bree Serif", serif;
|
||||
font-weight: 400;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.widgets-section {
|
||||
margin-top: var(--space-7);
|
||||
}
|
||||
|
||||
11
static/img/pid-icone-escuro.svg
Normal file
11
static/img/pid-icone-escuro.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="P.I.D. — Portal Interno da De Paula">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 815 B |
11
static/img/pid-icone.svg
Normal file
11
static/img/pid-icone.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" role="img" aria-label="P.I.D. — Portal Interno da De Paula">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#4B2E75"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#4B2E75"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#F2EDE3"></rect>
|
||||
<circle cx="24" cy="38" r="5" fill="#241C33"></circle>
|
||||
<circle cx="40" cy="38" r="5" fill="#241C33"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#F2EDE3"></circle>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 815 B |
15
static/img/pid-logo-horizontal-escuro.svg
Normal file
15
static/img/pid-logo-horizontal-escuro.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 80" width="300" height="80" role="img" aria-label="P.I.D. — Portal Interno da De Paula">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -64,7 +64,10 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
redirectOn401: false,
|
||||
body: { username, password },
|
||||
});
|
||||
pidPlayLoginIntro(() => {
|
||||
sessionStorage.setItem("pid_reveal_portal", "1");
|
||||
window.location.href = "portal.html";
|
||||
});
|
||||
} catch (e) {
|
||||
errorEl.textContent = e.message || "Login ou senha inválidos.";
|
||||
if (submitBtn) submitBtn.disabled = false;
|
||||
|
||||
197
static/js/login-intro.js
Normal file
197
static/js/login-intro.js
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Animação de intro pós-login — porta fiel da composição de
|
||||
* pid-intro-escuro.html (motor "OM" de animação por cena/tempo autorado,
|
||||
* ver CLAUDE.md "Animação de intro do login" para a extração original).
|
||||
* Durações das cenas ACELERADAS em relação ao original (pedido explícito do
|
||||
* usuário): Build e Face de 2,6s/2s pra 1s cada; Wordmark mantida em 2,8s
|
||||
* (é a parte "onde aparece o nome do portal", pedida pra não mudar); Portal
|
||||
* (a parte em que ele some) de ~1s. As fórmulas de easing/animate/blink
|
||||
* abaixo são a tradução 1:1 das do original (animations-v3.jsx), só os
|
||||
* deslocamentos de tempo dentro de cada cena foram reproporcionados pra
|
||||
* caber na duração nova; o "fly" final foi recalibrado pro canto superior
|
||||
* esquerdo REAL da janela (onde a logo colapsada da sidebar mora,
|
||||
* `.sidebar__logo--icon`, 40px) em vez das coordenadas de um frame de vídeo
|
||||
* 1920x1080 do arquivo original, que não correspondem a nada nesta página.
|
||||
*/
|
||||
|
||||
const PID_INTRO_CUES = { Build: 0, Face: 1, Wordmark: 2, Portal: 4.8 };
|
||||
const PID_INTRO_TOTAL = 5.7;
|
||||
const PID_INTRO_FADE_MS = 500;
|
||||
|
||||
const PID_INTRO_EASING = {
|
||||
easeOutCubic: (t) => (--t) * t * t + 1,
|
||||
easeInOutQuad: (t) => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),
|
||||
easeOutBack: (t) => {
|
||||
const c1 = 1.70158;
|
||||
const c3 = c1 + 1;
|
||||
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
|
||||
},
|
||||
};
|
||||
|
||||
function pidIntroClamp(v, min, max) {
|
||||
return Math.max(min, Math.min(max, v));
|
||||
}
|
||||
|
||||
function pidIntroAnimate({ from = 0, to = 1, start = 0, end = 1, ease = PID_INTRO_EASING.easeInOutQuad }) {
|
||||
return (t) => {
|
||||
if (t <= start) return from;
|
||||
if (t >= end) return to;
|
||||
const local = (t - start) / (end - start);
|
||||
return from + (to - from) * ease(local);
|
||||
};
|
||||
}
|
||||
|
||||
function pidIntroBlinkAt(t0, T) {
|
||||
const d = T - t0;
|
||||
if (d < 0 || d > 0.22) return 1;
|
||||
return Math.abs(Math.cos((d / 0.22) * Math.PI));
|
||||
}
|
||||
|
||||
function pidIntroCornerTarget(iconSize, finalSize, margin) {
|
||||
const cx = window.innerWidth / 2;
|
||||
const cy = window.innerHeight / 2;
|
||||
return {
|
||||
x: margin + finalSize / 2 - cx,
|
||||
y: margin + finalSize / 2 - cy,
|
||||
};
|
||||
}
|
||||
|
||||
function pidPlayLoginIntro(onDone) {
|
||||
const overlay = document.getElementById("login-intro");
|
||||
const icon = document.getElementById("login-intro-icon");
|
||||
const stage = document.getElementById("login-intro-stage");
|
||||
const wordmark = document.getElementById("login-intro-wordmark");
|
||||
if (!overlay || !icon || !stage || !wordmark) {
|
||||
onDone();
|
||||
return;
|
||||
}
|
||||
|
||||
const body = icon.querySelector(".login-intro__body");
|
||||
const tab = icon.querySelector(".login-intro__tab");
|
||||
const screen = icon.querySelector(".login-intro__screen");
|
||||
const eyeL = icon.querySelector(".login-intro__eye--l");
|
||||
const eyeR = icon.querySelector(".login-intro__eye--r");
|
||||
const smile = icon.querySelector(".login-intro__smile");
|
||||
const letters = Array.from(wordmark.querySelectorAll(".login-intro__letter"));
|
||||
const rule = wordmark.querySelector(".login-intro__rule");
|
||||
const tagline = wordmark.querySelector(".login-intro__tagline");
|
||||
|
||||
const { easeOutCubic, easeInOutQuad, easeOutBack } = PID_INTRO_EASING;
|
||||
const CUES = PID_INTRO_CUES;
|
||||
|
||||
const bodyDrawFn = pidIntroAnimate({ start: CUES.Build + 0.05, end: CUES.Build + 0.45, ease: easeInOutQuad });
|
||||
const bodyFillFn = pidIntroAnimate({ start: CUES.Build + 0.3, end: CUES.Build + 0.55, ease: easeOutCubic });
|
||||
const tabDropFn = pidIntroAnimate({ from: -18, to: 0, start: CUES.Build + 0.4, end: CUES.Build + 0.65, ease: easeOutBack });
|
||||
const tabFadeFn = pidIntroAnimate({ start: CUES.Build + 0.4, end: CUES.Build + 0.55, ease: easeOutCubic });
|
||||
const screenFn = pidIntroAnimate({ start: CUES.Build + 0.6, end: CUES.Build + 0.95, ease: easeOutCubic });
|
||||
|
||||
const eyeLFn = pidIntroAnimate({ start: CUES.Face + 0.05, end: CUES.Face + 0.35, ease: easeOutBack });
|
||||
const eyeRFn = pidIntroAnimate({ start: CUES.Face + 0.15, end: CUES.Face + 0.45, ease: easeOutBack });
|
||||
const smileFn = pidIntroAnimate({ start: CUES.Face + 0.35, end: CUES.Face + 0.65, ease: easeInOutQuad });
|
||||
|
||||
const shiftFn = pidIntroAnimate({ start: CUES.Wordmark - 0.35, end: CUES.Wordmark + 0.7, ease: easeOutCubic });
|
||||
// Cena Portal comprimida (ver comentário de PID_INTRO_TOTAL acima): a
|
||||
// wordmark some quase na hora, o ícone voa rápido e o stage inteiro
|
||||
// desaparece logo depois, sem pausa parada no meio.
|
||||
const flyFn = pidIntroAnimate({ start: CUES.Portal + 0.05, end: CUES.Portal + 0.55, ease: easeOutCubic });
|
||||
const wordmarkOutFn = pidIntroAnimate({ from: 1, to: 0, start: CUES.Portal, end: CUES.Portal + 0.3, ease: easeOutCubic });
|
||||
const stageFadeFn = pidIntroAnimate({ from: 1, to: 0, start: CUES.Portal + 0.5, end: CUES.Portal + 0.9, ease: easeOutCubic });
|
||||
|
||||
const ruleFn = pidIntroAnimate({ start: CUES.Wordmark + 0.85, end: CUES.Wordmark + 1.6, ease: easeInOutQuad });
|
||||
const tagFn = pidIntroAnimate({ start: CUES.Wordmark + 1.15, end: CUES.Wordmark + 1.9, ease: easeOutCubic });
|
||||
|
||||
const letterFns = letters.map((_, i) => {
|
||||
const s = CUES.Wordmark + 0.25 + i * 0.13;
|
||||
return {
|
||||
o: pidIntroAnimate({ start: s, end: s + 0.5, ease: easeOutCubic }),
|
||||
y: pidIntroAnimate({ from: 26, to: 0, start: s, end: s + 0.6, ease: easeOutCubic }),
|
||||
};
|
||||
});
|
||||
|
||||
const SHIFT_X = -100;
|
||||
const ICON_SIZE = 160;
|
||||
const FINAL_ICON_SIZE = 40;
|
||||
const FINAL_SCALE = FINAL_ICON_SIZE / ICON_SIZE;
|
||||
const CORNER_MARGIN = 40;
|
||||
|
||||
// O card de login se dissolve enquanto o overlay (já na cor final,
|
||||
// #121017) surge por cima — só depois dessa transição (mesma duração,
|
||||
// PID_INTRO_FADE_MS) é que o ícone começa a se desenhar; sem isso, o
|
||||
// overlay aparecia de repente por cima do card ainda visível.
|
||||
const loginCard = document.querySelector(".login-card");
|
||||
if (loginCard) loginCard.classList.add("is-leaving");
|
||||
overlay.hidden = false;
|
||||
void overlay.offsetWidth;
|
||||
overlay.classList.add("is-visible");
|
||||
|
||||
let start;
|
||||
|
||||
function frame(now) {
|
||||
const T = Math.min((now - start) / 1000, PID_INTRO_TOTAL);
|
||||
|
||||
const bodyDraw = bodyDrawFn(T);
|
||||
body.style.strokeDashoffset = String(100 * (1 - bodyDraw));
|
||||
body.style.strokeOpacity = bodyDraw > 0.001 ? "1" : "0";
|
||||
body.style.fillOpacity = String(bodyFillFn(T));
|
||||
|
||||
const tabDrop = tabDropFn(T);
|
||||
tab.setAttribute("transform", `translate(0 ${tabDrop})`);
|
||||
tab.style.opacity = String(tabFadeFn(T));
|
||||
|
||||
const screenP = screenFn(T);
|
||||
const screenScaleY = pidIntroClamp(screenP * 1.2, 0, 1);
|
||||
screen.setAttribute("transform", `translate(32 41) scale(${screenP} ${screenScaleY}) translate(-32 -41)`);
|
||||
screen.style.opacity = String(pidIntroClamp(screenP * 2, 0, 1));
|
||||
|
||||
const blink = Math.min(
|
||||
pidIntroBlinkAt(CUES.Face + 0.8, T),
|
||||
pidIntroBlinkAt(CUES.Wordmark + 1.1, T)
|
||||
);
|
||||
const sL = eyeLFn(T);
|
||||
const sR = eyeRFn(T);
|
||||
eyeL.setAttribute("transform", `translate(24 38) scale(${sL} ${sL * blink})`);
|
||||
eyeL.style.opacity = String(pidIntroClamp(sL, 0, 1));
|
||||
eyeR.setAttribute("transform", `translate(40 38) scale(${sR} ${sR * blink})`);
|
||||
eyeR.style.opacity = String(pidIntroClamp(sR, 0, 1));
|
||||
|
||||
const smileP = smileFn(T);
|
||||
smile.style.strokeDashoffset = String(100 * (1 - smileP));
|
||||
smile.style.strokeOpacity = smileP > 0.001 ? "1" : "0";
|
||||
|
||||
const shift = shiftFn(T);
|
||||
const fly = flyFn(T);
|
||||
const lockupX = SHIFT_X * shift;
|
||||
const lockupScale = 1 - 0.2 * shift;
|
||||
const target = pidIntroCornerTarget(ICON_SIZE, FINAL_ICON_SIZE, CORNER_MARGIN);
|
||||
const logoX = lockupX + (target.x - lockupX) * fly;
|
||||
const logoY = (target.y - 0) * fly;
|
||||
const logoScale = lockupScale + (FINAL_SCALE - lockupScale) * fly;
|
||||
icon.style.transform = `translate(${logoX}px, ${logoY}px) scale(${logoScale})`;
|
||||
|
||||
wordmark.style.opacity = String(pidIntroClamp(shift * 1.4, 0, 1) * wordmarkOutFn(T));
|
||||
|
||||
letters.forEach((el, i) => {
|
||||
el.style.opacity = String(letterFns[i].o(T));
|
||||
el.style.transform = `translateY(${letterFns[i].y(T)}px)`;
|
||||
});
|
||||
|
||||
rule.style.transform = `scaleX(${ruleFn(T)})`;
|
||||
|
||||
const tag = tagFn(T);
|
||||
tagline.style.opacity = String(tag);
|
||||
tagline.style.transform = `translateY(${(1 - tag) * 12}px)`;
|
||||
|
||||
stage.style.opacity = String(stageFadeFn(T));
|
||||
|
||||
if (T < PID_INTRO_TOTAL) {
|
||||
requestAnimationFrame(frame);
|
||||
} else {
|
||||
onDone();
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
start = performance.now();
|
||||
requestAnimationFrame(frame);
|
||||
}, PID_INTRO_FADE_MS);
|
||||
}
|
||||
19
static/js/login-logo-blink.js
Normal file
19
static/js/login-logo-blink.js
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Ícone "P.I.D." do card de login (`#login-logo-btn`) — clicar faz os olhos
|
||||
* do disquete piscarem (`.pid-icon-eye`/`pidIconBlink` em base.css, mesmo
|
||||
* mecanismo da logo da sidebar em sidebar-brand.js). Sem navegação nenhuma
|
||||
* aqui — já estamos na tela de login, é só um toque de graça ao clicar no
|
||||
* mascote, não um atalho pra lugar nenhum.
|
||||
*/
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const btn = document.getElementById("login-logo-btn");
|
||||
if (!btn) return;
|
||||
|
||||
btn.addEventListener("click", () => {
|
||||
btn.querySelectorAll(".pid-icon-eye").forEach((eye) => {
|
||||
eye.classList.remove("is-blinking");
|
||||
void eye.getBoundingClientRect();
|
||||
eye.classList.add("is-blinking");
|
||||
});
|
||||
});
|
||||
});
|
||||
35
static/js/portal-reveal.js
Normal file
35
static/js/portal-reveal.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Revelação de entrada em portal.html após a animação de intro do login
|
||||
* (ver login-intro.js/CLAUDE.md "Animação de intro do login"). Só dispara
|
||||
* quando index.html marcou sessionStorage antes de navegar — acesso direto/
|
||||
* recarregamento normal da página não passa por isso. A checagem roda como
|
||||
* IIFE de topo (mesmo padrão de theme.js/applyStoredTheme) pra aplicar as
|
||||
* classes antes da primeira pintura, evitando um flash do conteúdo já
|
||||
* visível antes de escondê-lo.
|
||||
*
|
||||
* Duas classes, removidas em sequência (não juntas): primeiro
|
||||
* `pid-entering-sidebar` sai (a sidebar desliza/aparece), só depois
|
||||
* `pid-entering` sai (o resto do app aparece num fade) — pedido explícito
|
||||
* do usuário pra ficar mais fluido, em vez das duas coisas surgirem juntas.
|
||||
*/
|
||||
(function pidRevealSetup() {
|
||||
if (sessionStorage.getItem("pid_reveal_portal") !== "1") return;
|
||||
sessionStorage.removeItem("pid_reveal_portal");
|
||||
document.documentElement.classList.add("pid-entering", "pid-entering-sidebar");
|
||||
})();
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const html = document.documentElement;
|
||||
if (!html.classList.contains("pid-entering")) return;
|
||||
requestAnimationFrame(() => {
|
||||
setTimeout(() => {
|
||||
html.classList.remove("pid-entering-sidebar");
|
||||
// Espera o slide da sidebar terminar (mesma duração de .sidebar em
|
||||
// layout.css, 420ms) antes de revelar o resto — as duas entradas não
|
||||
// devem se sobrepor.
|
||||
setTimeout(() => {
|
||||
html.classList.remove("pid-entering");
|
||||
}, 420);
|
||||
}, 120);
|
||||
});
|
||||
});
|
||||
28
static/js/sidebar-brand.js
Normal file
28
static/js/sidebar-brand.js
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Logo da sidebar (`#sidebar-brand-link`, presente nos 10 shells) — link de
|
||||
* verdade pra `portal.html` (tela Principal), com os olhos do ícone
|
||||
* piscando antes de navegar. A navegação é adiada (`setTimeout`) só o
|
||||
* suficiente pra a piscada (`.pid-icon-eye`/`pidIconBlink` em base.css,
|
||||
* 200ms) terminar de tocar antes da página trocar; ctrl/cmd/shift/clique do
|
||||
* meio continuam abrindo em nova aba normalmente (não intercepta esses
|
||||
* casos).
|
||||
*/
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const brand = document.getElementById("sidebar-brand-link");
|
||||
if (!brand) return;
|
||||
|
||||
brand.addEventListener("click", (event) => {
|
||||
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
||||
event.preventDefault();
|
||||
|
||||
brand.querySelectorAll(".pid-icon-eye").forEach((eye) => {
|
||||
eye.classList.remove("is-blinking");
|
||||
void eye.getBoundingClientRect();
|
||||
eye.classList.add("is-blinking");
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
window.location.href = brand.getAttribute("href");
|
||||
}, 260);
|
||||
});
|
||||
});
|
||||
@ -24,17 +24,6 @@ const PID_COLOR_THEMES = [
|
||||
}
|
||||
})();
|
||||
|
||||
function pidSyncLoginLogo() {
|
||||
const img = document.getElementById("login-logo");
|
||||
if (!img) return;
|
||||
const theme = document.documentElement.getAttribute("data-theme") || "dark";
|
||||
const src = theme === "light" ? img.dataset.logoLight : img.dataset.logoDark;
|
||||
if (src) img.src = src;
|
||||
}
|
||||
|
||||
pidSyncLoginLogo();
|
||||
document.addEventListener("pid:theme-changed", pidSyncLoginLogo);
|
||||
|
||||
function pidToggleTheme() {
|
||||
const current = document.documentElement.getAttribute("data-theme") || "dark";
|
||||
const next = current === "dark" ? "light" : "dark";
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Acessos Gerais</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -16,9 +16,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -497,6 +530,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Calendário Individual</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -17,9 +17,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -633,6 +666,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Simulação de Custo de Contratação</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -16,9 +16,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -619,6 +652,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Importação de Plano de Saúde</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -17,9 +17,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -697,6 +730,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,27 +5,40 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Login</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Bree+Serif&display=swap" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Bree+Serif&family=Pinyon+Script&family=Space+Grotesk:wght@700&family=DM+Mono&display=swap" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/login.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/login-intro.css' %}" />
|
||||
<script src="{% static 'js/theme.js' %}" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="login-page">
|
||||
<div class="login-card">
|
||||
<img
|
||||
class="login-card__logo"
|
||||
id="login-logo"
|
||||
src="{% static 'img/logo-branco.png' %}"
|
||||
data-logo-dark="{% static 'img/logo-branco.png' %}"
|
||||
data-logo-light="{% static 'img/logo.png' %}"
|
||||
alt="De Paula Contadores"
|
||||
/>
|
||||
<p class="login-card__title">Portal De Paula</p>
|
||||
<button type="button" class="login-card__logo-btn" id="login-logo-btn" aria-label="P.I.D.">
|
||||
<svg class="login-card__logo" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="login-heading">
|
||||
<p class="login-card__title">Portal Interno da De Paula</p>
|
||||
<p class="login-slogan">"Grandes aplicações de todos os tamanhos."</p>
|
||||
</div>
|
||||
|
||||
<form id="login-form" class="login-form" novalidate>
|
||||
<div class="field">
|
||||
@ -72,7 +85,41 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="login-intro" id="login-intro" hidden aria-hidden="true">
|
||||
<div class="login-intro__stage" id="login-intro-stage">
|
||||
<svg class="login-intro__icon" id="login-intro-icon" viewBox="0 0 64 64">
|
||||
<path class="login-intro__body" d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" pathLength="100"></path>
|
||||
<g class="login-intro__tab">
|
||||
<rect x="22" y="4" width="20" height="16"></rect>
|
||||
<rect x="34" y="7" width="5" height="10"></rect>
|
||||
</g>
|
||||
<g class="login-intro__screen"><rect x="12" y="26" width="40" height="30" rx="2"></rect></g>
|
||||
<g class="login-intro__eye login-intro__eye--l">
|
||||
<circle r="5"></circle>
|
||||
<circle class="login-intro__glint" cx="2" cy="-1.8" r="1.6"></circle>
|
||||
</g>
|
||||
<g class="login-intro__eye login-intro__eye--r">
|
||||
<circle r="5"></circle>
|
||||
<circle class="login-intro__glint" cx="2" cy="-1.8" r="1.6"></circle>
|
||||
</g>
|
||||
<path class="login-intro__smile" d="M25 47 q7 6 14 0" pathLength="100"></path>
|
||||
</svg>
|
||||
|
||||
<div class="login-intro__wordmark" id="login-intro-wordmark">
|
||||
<div class="login-intro__letters">
|
||||
<span class="login-intro__letter">P<span class="login-intro__dot">.</span></span>
|
||||
<span class="login-intro__letter">I<span class="login-intro__dot">.</span></span>
|
||||
<span class="login-intro__letter">D<span class="login-intro__dot">.</span></span>
|
||||
</div>
|
||||
<div class="login-intro__rule"></div>
|
||||
<div class="login-intro__tagline">Portal Interno da De Paula</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/login-logo-blink.js' %}"></script>
|
||||
<script src="{% static 'js/login-intro.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Indicador de Desempenho</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -17,9 +17,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -873,6 +906,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Links & Ferramentas</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -17,9 +17,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -483,6 +516,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Perfis de Acesso</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -16,9 +16,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -548,6 +581,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,10 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Bree+Serif&display=swap" rel="stylesheet" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -16,13 +13,47 @@
|
||||
<link rel="stylesheet" href="{% static 'css/widgets.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/ramais-lookup.css' %}" />
|
||||
<script src="{% static 'js/theme.js' %}" defer></script>
|
||||
<script src="{% static 'js/portal-reveal.js' %}" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -209,8 +240,6 @@
|
||||
<button type="button" class="icon-btn" id="sidebar-toggle" aria-label="Alternar menu">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16" stroke-linecap="round"/></svg>
|
||||
</button>
|
||||
<h1 class="topbar__title" id="portal-title">Portal De Paula</h1>
|
||||
|
||||
<div class="topbar__actions">
|
||||
<button type="button" class="btn-ghost" id="ramais-btn">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4c0 9 7 16 16 16l3-4-6-3-2 2c-3-1.5-5-3.5-6-6l2-2-3-6z" stroke-linejoin="round"/></svg>
|
||||
@ -480,6 +509,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Ramais</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -17,9 +17,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -698,6 +731,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Portal De Paula — Usuários</title>
|
||||
<link rel="icon" type="image/png" href="{% static 'img/favicon.png' %}" />
|
||||
<link rel="icon" type="image/svg+xml" href="{% static 'img/pid-icone-escuro.svg' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/tokens.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/base.css' %}" />
|
||||
<link rel="stylesheet" href="{% static 'css/layout.css' %}" />
|
||||
@ -16,9 +16,42 @@
|
||||
<body>
|
||||
<div class="app-shell" id="app-shell">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar__brand">
|
||||
<img class="sidebar__logo" src="{% static 'img/logo-branco.png' %}" alt="De Paula Contadores" />
|
||||
</div>
|
||||
<a class="sidebar__brand" href="portal.html" id="sidebar-brand-link" aria-label="Ir para a tela Principal">
|
||||
<svg class="sidebar__logo sidebar__logo--full" viewBox="0 0 300 80" aria-hidden="true" focusable="false">
|
||||
<g transform="translate(8,8) scale(1)">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</g>
|
||||
<text x="86" y="42" font-family="'Space Grotesk',Helvetica,Arial,sans-serif" font-size="34" font-weight="700" letter-spacing="1.4" fill="#F2EDE3">P.I.D.</text>
|
||||
<text x="88" y="61" font-family="'DM Mono',ui-monospace,monospace" font-size="9.5" letter-spacing="2.6" fill="#C6A24A">PORTAL INTERNO DA DE PAULA</text>
|
||||
</svg>
|
||||
<svg class="sidebar__logo sidebar__logo--icon" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path d="M10 4 h34 l14 14 v40 a2 2 0 0 1 -2 2 H8 a2 2 0 0 1 -2 -2 V6 a2 2 0 0 1 2 -2 z" fill="#7B5BA8"></path>
|
||||
<rect x="22" y="4" width="20" height="16" fill="#C6A24A"></rect>
|
||||
<rect x="34" y="7" width="5" height="10" fill="#7B5BA8"></rect>
|
||||
<rect x="12" y="26" width="40" height="30" rx="2" fill="#241C33"></rect>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="24" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="26" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<g class="pid-icon-eye">
|
||||
<circle cx="40" cy="38" r="5" fill="#F2EDE3"></circle>
|
||||
<circle cx="42" cy="36.2" r="1.6" fill="#241C33"></circle>
|
||||
</g>
|
||||
<path d="M25 47 q7 6 14 0" stroke="#C6A24A" stroke-width="3" fill="none" stroke-linecap="round"></path>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
<nav class="sidebar__nav">
|
||||
<ul class="nav-list">
|
||||
@ -599,6 +632,7 @@
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script src="{% static 'js/sidebar-brand.js' %}"></script>
|
||||
<script src="{% static 'js/dual-select.js' %}"></script>
|
||||
<script src="{% static 'js/profiles.js' %}"></script>
|
||||
<script src="{% static 'js/auth.js' %}"></script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user