@breathe-ds/ui 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -142
  3. package/components/Accordion.tsx +17 -14
  4. package/components/AnchorNav.tsx +33 -21
  5. package/components/Avatar.tsx +37 -0
  6. package/components/BackgroundVideo.tsx +14 -14
  7. package/components/BottomNav.tsx +70 -69
  8. package/components/Breadcrumb.tsx +45 -0
  9. package/components/BreatheMark.tsx +12 -24
  10. package/components/Button.tsx +12 -12
  11. package/components/Byline.tsx +103 -0
  12. package/components/CaptionBand.tsx +74 -0
  13. package/components/Card.tsx +5 -5
  14. package/components/Container.tsx +4 -4
  15. package/components/CtaCard.tsx +52 -0
  16. package/components/Curtain.tsx +152 -0
  17. package/components/FactStrip.tsx +55 -0
  18. package/components/Footer.tsx +169 -77
  19. package/components/Header.tsx +32 -17
  20. package/components/Heading.tsx +86 -0
  21. package/components/InfoCard.tsx +116 -0
  22. package/components/LanguageSwitcher.tsx +139 -0
  23. package/components/List.tsx +81 -0
  24. package/components/Lockup.tsx +38 -55
  25. package/components/MapCard.tsx +158 -0
  26. package/components/MediaCard.tsx +266 -0
  27. package/components/PageVideoHero.tsx +53 -53
  28. package/components/PersonChip.tsx +49 -0
  29. package/components/Pill.tsx +42 -0
  30. package/components/PillList.tsx +21 -48
  31. package/components/ProfessionalCard.tsx +341 -0
  32. package/components/ProfessionalModal.tsx +243 -0
  33. package/components/Rows.tsx +131 -0
  34. package/components/SectionKicker.tsx +3 -3
  35. package/components/TestimonialCard.tsx +138 -0
  36. package/components/Text.tsx +31 -0
  37. package/components/Timeline.tsx +69 -0
  38. package/components/VideoInviteCard.tsx +168 -0
  39. package/components/VideoStoryCard.tsx +382 -0
  40. package/components/icons.tsx +6 -6
  41. package/components/marks/creeta.tsx +22 -22
  42. package/components/marks/ttcab.tsx +13 -13
  43. package/package.json +28 -5
  44. package/theme.css +88 -22
  45. package/tokens/creeta.css +14 -12
  46. package/tokens/neutral.css +16 -10
  47. package/tokens/ttcab.css +9 -8
  48. package/components/Cortina.tsx +0 -152
package/theme.css CHANGED
@@ -1,40 +1,106 @@
1
1
  /*
2
2
  @breathe-ds/ui — theme.css (tokens-first, v0.1)
3
3
 
4
- Contrato de tokens da família Cuidado Global (ecossistema RTA/Mariangela).
5
- As CORES são PAPÉIS: o valor de cada uma vem de uma CSS var `--cg-*` que
6
- CADA SITE define (ttcab petróleo/creme, creeta petróleo/névoa/magenta…).
7
- Assim os sites herdam a MESMA estrutura e nomes, com a própria paleta.
4
+ Token contract of the Cuidado Global family (RTA/Mariangela ecosystem).
5
+ COLORS are ROLES: the value of each one comes from a `--cg-*` CSS var that
6
+ EACH SITE defines (ttcab petrol/cream, creeta petrol/mist/magenta…).
7
+ This way the sites inherit the SAME structure and names, with their own palette.
8
8
 
9
- Uso no globals.css de um site (Tailwind v4):
9
+ Usage in a site's globals.css (Tailwind v4):
10
10
  @import "tailwindcss";
11
11
  @import "@breathe-ds/ui/theme.css";
12
- @import "@breathe-ds/ui/tokens/ttcab.css"; (ou defina os --cg-* inline)
12
+ @import "@breathe-ds/ui/tokens/ttcab.css"; (or define the --cg-* inline)
13
13
 
14
- Escalas fixas (tipografia-papel, raio, motion) são compartilhadas aqui.
15
- Contrastes medidos de cada paleta: ver README.md e os arquivos tokens/*.
14
+ Fixed scales (typography roles, radius, motion) are shared here.
15
+ Measured contrasts of each palette: see README.md and the tokens/* files.
16
16
  */
17
17
  @theme {
18
- /* ── Cores (papéis) — valor vem dos --cg-* do site ── */
19
- --color-surface: var(--cg-surface); /* fundo base */
20
- --color-surface-panel: var(--cg-surface-panel); /* painel escuro (footer/CTA) */
21
- --color-ink: var(--cg-ink); /* texto principal / títulos */
22
- --color-ink-soft: var(--cg-ink-soft); /* texto secundário */
23
- --color-ink-body: var(--cg-ink-body); /* corpo de leitura */
24
- --color-action: var(--cg-action); /* CTA/destaque — nunca texto puro */
25
- --color-action-text: var(--cg-action-text); /* texto na cor de ação (AA) */
26
- --color-on-action: var(--cg-on-action); /* texto SOBRE a cor de ação (botão) */
27
- --color-line: var(--cg-line); /* hairlines/bordas */
28
-
29
- /* ── Tipografia (papéis; família real vem dos --cg-font-*) ── */
18
+ /* ── Colors (roles) — value comes from the site's --cg-* ── */
19
+ --color-surface: var(--cg-surface); /* base background */
20
+ --color-surface-panel: var(--cg-surface-panel); /* dark panel (footer/CTA) */
21
+ --color-card: var(--cg-card, #ffffff); /* raised surface: cards, pills, menus over the page */
22
+ --color-ink: var(--cg-ink); /* primary text / headings */
23
+ --color-ink-soft: var(--cg-ink-soft); /* secondary text */
24
+ --color-ink-body: var(--cg-ink-body); /* body copy */
25
+ --color-action: var(--cg-action); /* CTA/highlight — never plain text */
26
+ --color-action-text: var(--cg-action-text); /* text in the action color (AA) */
27
+ --color-on-action: var(--cg-on-action); /* text ON the action color (button) */
28
+ --color-line: var(--cg-line); /* hairlines/borders */
29
+
30
+ /* ── Typography (roles; actual family comes from --cg-font-*) ── */
30
31
  --font-heading: var(--cg-font-heading, system-ui, sans-serif);
31
32
  --font-body: var(--cg-font-body, Arial, system-ui, sans-serif);
32
33
 
33
- /* ── Raio ── */
34
+ /* ── Radius ── */
34
35
  --radius-xl: 24px;
35
36
  --radius-2xl: 28px;
36
37
  --radius-pill: 9999px;
37
38
 
38
- /* ── Motion — curva assinatura da família ── */
39
+ /* ── Motion — the family's signature curve ── */
39
40
  --ease-cg: cubic-bezier(0.2, 0.8, 0.2, 1);
40
41
  }
42
+
43
+ /* ── Base behaviour the whole family shares ──
44
+ Smooth scrolling for anchors (AnchorNav, "On this page", BottomNav); off
45
+ for people who asked for reduced motion. The header sticks at the top
46
+ (~5rem) and, on phones, the BottomNav sticks at the bottom: without this
47
+ padding the control that receives keyboard focus would stop hidden behind
48
+ them (WCAG 2.4.11). Anchored sections may still add their own scroll-margin. */
49
+ @layer base {
50
+ html {
51
+ scroll-behavior: smooth;
52
+ scroll-padding-top: 6rem;
53
+ scroll-padding-bottom: 7rem;
54
+ }
55
+ @media (prefers-reduced-motion: reduce) {
56
+ html {
57
+ scroll-behavior: auto;
58
+ }
59
+ }
60
+ }
61
+
62
+ /* Outbound/anchor arrow on links: takes a small step toward where the link
63
+ goes, on hover. Used by Footer, List, Byline, PersonChip, PillList. */
64
+ @media (prefers-reduced-motion: no-preference) {
65
+ .cg-arrow-go {
66
+ transition: transform 150ms var(--ease-cg);
67
+ }
68
+ a:hover .cg-arrow-go,
69
+ .group:hover .cg-arrow-go {
70
+ transform: translate(2px, -2px);
71
+ }
72
+ .cg-arrow-down {
73
+ transition: transform 150ms var(--ease-cg);
74
+ }
75
+ a:hover .cg-arrow-down,
76
+ .group:hover .cg-arrow-down {
77
+ transform: translateY(2px);
78
+ }
79
+ }
80
+
81
+ /* ── BreatheMark: the symbol "breathes" (scale pulse); off under reduced motion ── */
82
+ @keyframes breathe-mark-inhale {
83
+ 0%, 100% { transform: scale(0.93); }
84
+ 50% { transform: scale(1.05); }
85
+ }
86
+ .breathe-mark__g {
87
+ transform-box: fill-box;
88
+ transform-origin: center;
89
+ animation: breathe-mark-inhale var(--breathe-dur, 6s) cubic-bezier(0.37, 0, 0.63, 1) infinite;
90
+ }
91
+ .breathe-mark--static .breathe-mark__g { animation: none; }
92
+ @media (prefers-reduced-motion: reduce) { .breathe-mark__g { animation: none; } }
93
+
94
+
95
+ /* ── Lockup entrance: symbol (scale + slight turn) → name (slides in) → tagline.
96
+ Same vocabulary as the Curtain; under reduced motion only a short fade. ── */
97
+ .cg-lockup--entrance .cg-lockup__mark{ animation: cg-lockup-mark 500ms var(--ease-cg,cubic-bezier(.2,.8,.2,1)) var(--cg-entrance-delay,0ms) both; }
98
+ .cg-lockup--entrance .cg-lockup__name{ animation: cg-lockup-name 420ms var(--ease-cg,cubic-bezier(.2,.8,.2,1)) calc(var(--cg-entrance-delay,0ms) + 420ms) both; }
99
+ .cg-lockup--entrance .cg-lockup__tag{ animation: cg-lockup-tag 360ms ease calc(var(--cg-entrance-delay,0ms) + 700ms) both; }
100
+ @keyframes cg-lockup-mark{ from{ opacity:0; transform:scale(.6) rotate(-16deg); } }
101
+ @keyframes cg-lockup-name{ from{ opacity:0; transform:translateX(-8px); } }
102
+ @keyframes cg-lockup-tag{ from{ opacity:0; transform:translateY(4px); } }
103
+ @media (prefers-reduced-motion:reduce){
104
+ .cg-lockup--entrance .cg-lockup__mark, .cg-lockup--entrance .cg-lockup__name, .cg-lockup--entrance .cg-lockup__tag{ animation: cg-lockup-fade 240ms ease var(--cg-entrance-delay,0ms) both; }
105
+ @keyframes cg-lockup-fade{ from{ opacity:0; } }
106
+ }
package/tokens/creeta.css CHANGED
@@ -1,21 +1,23 @@
1
1
  /*
2
- Paleta Creeta (clínica RTA em Floripa) — petróleo + névoa + magenta.
3
- Valores do novo.creeta. Contrastes medidos (fórmula WCAG):
4
- - surface #eef3f4 / ink #144753 ............ ~9,1:1 (AAA)
5
- - surface #eef3f4 / ink-soft #52707a ....... ~4,7:1 (AA)
6
- - action #ab2781 (magenta) é o CTA ("Agendar"); texto sobre ele = branco.
2
+ Creeta palette (RTA clinic in Floripa) — petrol + mist + magenta.
3
+ Values from novo.creeta. Measured contrasts (WCAG formula):
4
+ - surface #eef3f4 / ink #144753 ............ ~9.1:1 (AAA)
5
+ - surface #eef3f4 / ink-soft #266675 ....... 5.79:1 (AA) — the site's "teal-escuro":
6
+ second tone of two-tone headings, eyebrows, strong links
7
+ - surface #eef3f4 / ink-body #1e4f5b ....... 8.07:1 (AAA)
8
+ - action #ab2781 (magenta) is the CTA ("Agendar"); text on it = white.
7
9
  */
8
10
  :root {
9
- --cg-surface: #eef3f4; /* névoa */
10
- --cg-surface-panel: #144753; /* petróleo */
11
- --cg-ink: #144753; /* petróleo */
12
- --cg-ink-soft: #52707a;
11
+ --cg-surface: #eef3f4; /* mist */
12
+ --cg-surface-panel: #144753; /* petrol */
13
+ --cg-card: #ffffff; /* cards, pills and menus over the page */
14
+ --cg-ink: #144753; /* petrol */
15
+ --cg-ink-soft: #266675; /* teal-escuro */
13
16
  --cg-ink-body: #1e4f5b;
14
17
  --cg-action: #ab2781; /* magenta (Agendar) */
15
- --cg-action-text: #8f1f6c; /* magenta mais escuro p/ texto */
16
- --cg-on-action: #ffffff; /* branco sobre magenta */
18
+ --cg-action-text: #8f1f6c; /* darker magenta for text */
19
+ --cg-on-action: #ffffff; /* white on magenta */
17
20
  --cg-line: rgb(20 71 83 / 0.16);
18
21
  --cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand */
19
22
  --cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree */
20
23
  }
21
- CSS
@@ -1,21 +1,27 @@
1
1
  /*
2
- Paleta NEUTRA — o padrão do Breathe. O design system é neutro de propósito:
3
- a cor vem de CADA aplicação (ttcab, creeta…). Use isto como base e sobrescreva
4
- os --cg-* no :root do seu site. Monocromático (cinza/quase-preto) pra deixar
5
- claro que é um placeholder "traga sua cor".
6
- - surface #ffffff / ink #18181b ............ ~17:1 (AAA)
7
- - surface #ffffff / ink-soft #71717a ....... ~4,8:1 (AA)
2
+ NEUTRAL palette — the Breathe default. The design system is neutral on
3
+ purpose: color comes from EACH application (ttcab, creeta…). Use this as the
4
+ base and override the --cg-* in your site's :root. Monochrome (gray/near-black)
5
+ to make it clear it is a "bring your own color" placeholder.
6
+ The page is a light gray and the cards are white: the family is tonal (mist on
7
+ creeta, cream on ttcab), so the neutral palette is too — a white page would
8
+ swallow the white cards.
9
+ - surface #f4f4f5 / ink #18181b ............ 16.1:1 (AAA)
10
+ - surface #f4f4f5 / ink-soft #65656e ....... 5.25:1 (AA)
11
+ - surface #f4f4f5 / ink-body #3f3f46 ....... 9.5:1 (AAA)
12
+ - card #ffffff / ink-soft #65656e .......... 5.77:1 (AA)
8
13
  */
9
14
  :root {
10
- --cg-surface: #ffffff;
15
+ --cg-surface: #f4f4f5; /* page: light gray, so white cards read */
11
16
  --cg-surface-panel: #18181b;
17
+ --cg-card: #ffffff;
12
18
  --cg-ink: #18181b;
13
- --cg-ink-soft: #71717a;
19
+ --cg-ink-soft: #65656e;
14
20
  --cg-ink-body: #3f3f46;
15
21
  --cg-action: #18181b;
16
22
  --cg-action-text: #52525b;
17
23
  --cg-on-action: #ffffff;
18
24
  --cg-line: rgb(0 0 0 / 0.12);
19
- --cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand (fixo da família) */
20
- --cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree (fixo da família) */
25
+ --cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand (fixed across the family) */
26
+ --cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree (fixed across the family) */
21
27
  }
package/tokens/ttcab.css CHANGED
@@ -1,20 +1,21 @@
1
1
  /*
2
- Paleta TTCAB (petróleo + creme). Contrastes medidos:
3
- - surface #fbf5e9 / ink #144753 ............ 9,41:1 (AAA)
4
- - surface #fbf5e9 / ink-soft #54707a ....... 4,86:1 (AA)
5
- - surface #fbf5e9 / ink-body #1e4f5b ....... 8,32:1 (AAA)
6
- - surface #fbf5e9 / action-text #9a5d07 .... 4,90:1 (AA)
7
- - surface-panel #144753 / surface (texto) .. 9,41:1 (AAA)
8
- - action #f6a22a é DECORATIVO/CTA — nunca texto sobre creme.
2
+ TTCAB palette (petrol + cream). Measured contrasts:
3
+ - surface #fbf5e9 / ink #144753 ............ 9.41:1 (AAA)
4
+ - surface #fbf5e9 / ink-soft #54707a ....... 4.86:1 (AA)
5
+ - surface #fbf5e9 / ink-body #1e4f5b ....... 8.32:1 (AAA)
6
+ - surface #fbf5e9 / action-text #9a5d07 .... 4.90:1 (AA)
7
+ - surface-panel #144753 / surface (text) ... 9.41:1 (AAA)
8
+ - action #f6a22a is DECORATIVE/CTA — never text on cream.
9
9
  */
10
10
  :root {
11
11
  --cg-surface: #fbf5e9;
12
12
  --cg-surface-panel: #144753;
13
+ --cg-card: #ffffff; /* cards, pills and menus over the page */
13
14
  --cg-ink: #144753;
14
15
  --cg-ink-soft: #54707a;
15
16
  --cg-ink-body: #1e4f5b;
16
17
  --cg-action: #f6a22a;
17
- --cg-on-action: #144753; /* ink sobre orange */
18
+ --cg-on-action: #144753; /* ink on orange */
18
19
  --cg-action-text: #9a5d07;
19
20
  --cg-line: rgb(20 71 83 / 0.16);
20
21
  --cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand */
@@ -1,152 +0,0 @@
1
- "use client";
2
-
3
- import { useEffect, useRef, useState, type CSSProperties, type ReactNode } from "react";
4
- import { BreatheMark } from "./BreatheMark";
5
-
6
- type Props = {
7
- /** Nome da marca (ex.: "creeta", "TTCAB", "Breathe"). */
8
- name: ReactNode;
9
- /** Linha abaixo do nome (ex.: "Centro de Reequilíbrio Toracoabdominal"). */
10
- tagline?: ReactNode;
11
- /** Símbolo à esquerda do nome. Padrão: o BreatheMark (anel + ponto). Cada
12
- * site injeta o seu logotipo aqui. */
13
- logo?: ReactNode;
14
- /** Quando `name` é um wordmark svg: altura dele como fração da altura do
15
- * símbolo, do manual da marca (ex.: `CREETA_LOCKUP.wordmarkPerSymbol`). */
16
- wordmarkRatio?: number;
17
- /** Lado do símbolo. Padrão `left`; o TTCAB é `right` (`TTCAB_LOCKUP.symbolSide`). */
18
- symbolSide?: "left" | "right";
19
- /** Chave do sessionStorage (quando há o script de cabeça). */
20
- storageKey?: string;
21
- /** Chamado quando a cortina termina de subir. */
22
- onDone?: () => void;
23
- className?: string;
24
- };
25
-
26
- /**
27
- * Cortina de entrada da família Cuidado Global — tela cheia, na cor do site
28
- * (tokens surface/ink), com o logotipo + nome se formando no centro e a
29
- * tagline embaixo; depois ela sobe e mostra a página. Espelha a `Cortina` do
30
- * creeta, mas neutra: a paleta e o logotipo vêm de cada app.
31
- *
32
- * - É toda em CSS (estilo embutido): sem JavaScript ela sobe do mesmo jeito,
33
- * então nunca fica presa na frente do site.
34
- * - Não recebe clique nem foco e não existe para leitor de tela (aria-hidden).
35
- * - Com movimento reduzido (ou impressão) não aparece.
36
- * - Para aparecer só na 1ª visita da sessão, ponha `cortinaHeadScript()` no
37
- * <head> (antes da pintura): em visita repetida o <html> já nasce com
38
- * data-cg-cortina="vista" e a cortina não é desenhada — sem piscar.
39
- *
40
- * Ao terminar de subir, o <html> ganha data-cg-cortina-fim (para o topo das
41
- * páginas "pousar" só depois dela, nunca numa troca de tela) e chama onDone.
42
- */
43
- export function Cortina({ name, tagline, logo, wordmarkRatio, symbolSide = "left", storageKey, onDone, className }: Props) {
44
- const el = useRef<HTMLDivElement>(null);
45
- const [gone, setGone] = useState(false);
46
-
47
- useEffect(() => {
48
- const node = el.current;
49
- if (!node) return;
50
- const aoTerminar = (e: AnimationEvent) => {
51
- if (e.animationName !== "cg-cortina-sobe") return;
52
- document.documentElement.setAttribute("data-cg-cortina-fim", "");
53
- try {
54
- if (storageKey) sessionStorage.setItem(storageKey, "1");
55
- } catch {
56
- /* sessionStorage bloqueado: a cortina só aparece de novo, nada quebra */
57
- }
58
- onDone?.();
59
- setGone(true);
60
- };
61
- node.addEventListener("animationend", aoTerminar);
62
- return () => node.removeEventListener("animationend", aoTerminar);
63
- }, [onDone, storageKey]);
64
-
65
- if (gone) return null;
66
-
67
- return (
68
- <div ref={el} className={`cg-cortina${className ? ` ${className}` : ""}`} aria-hidden="true">
69
- <style>{CORTINA_CSS}</style>
70
- {/* Símbolo à esquerda: ele abraça o bloco nome+tagline. À direita (TTCAB):
71
- ele encosta no nome, na mesma linha, e a tagline fica embaixo — senão
72
- o símbolo iria parar depois da tagline, longe do wordmark. */}
73
- {(() => {
74
- const mark = <span className="cg-cortina__mark">{logo ?? <BreatheMark size={60} duration={5} />}</span>;
75
- const nameEl = (
76
- <span
77
- className="cg-cortina__name"
78
- style={wordmarkRatio ? ({ "--cg-wordmark": `calc(var(--cg-cortina-mark) * ${wordmarkRatio})` } as CSSProperties) : undefined}
79
- >
80
- {name}
81
- </span>
82
- );
83
- const tag = tagline ? <span className="cg-cortina__tag">{tagline}</span> : null;
84
- return symbolSide === "right" ? (
85
- <div className="cg-cortina__lockup cg-cortina__lockup--right">
86
- <span className="cg-cortina__row">{nameEl}{mark}</span>
87
- {tag}
88
- </div>
89
- ) : (
90
- <div className="cg-cortina__lockup">
91
- {mark}
92
- <span className="cg-cortina__text">{nameEl}{tag}</span>
93
- </div>
94
- );
95
- })()}
96
- </div>
97
- );
98
- }
99
-
100
- /**
101
- * Script para o <head> (antes da pintura): marca a cortina como vista nesta
102
- * sessão, para não repetir ao navegar nem ao recarregar. Sem ele, a cortina
103
- * aparece a cada carregamento.
104
- * // Next (app/layout):
105
- * <script dangerouslySetInnerHTML={{ __html: cortinaHeadScript("cg-cortina") }} />
106
- */
107
- export function cortinaHeadScript(storageKey = "cg-cortina") {
108
- const k = JSON.stringify(storageKey);
109
- return `try{var d=document.documentElement;if(sessionStorage.getItem(${k})){d.setAttribute('data-cg-cortina','vista')}else{sessionStorage.setItem(${k},'1')}}catch(e){}`;
110
- }
111
-
112
- const CORTINA_CSS = `
113
- .cg-cortina{
114
- --cg-cortina-mark: clamp(40px,7.4vw,60px); /* altura do símbolo */
115
- position:fixed; inset:0 0 -40px; padding-bottom:40px;
116
- z-index:120; display:grid; place-items:center;
117
- border-radius:0 0 32px 32px;
118
- background:var(--color-surface,#fff); color:var(--color-ink,#14323a);
119
- box-shadow:0 24px 60px -20px rgba(0,0,0,.28);
120
- pointer-events:none;
121
- animation:cg-cortina-sobe 700ms cubic-bezier(.77,0,.175,1) 2200ms both;
122
- }
123
- /* gap ≈ 1/3 do corpo do nome: o anel é curvo, então o vão óptico lê um pouco maior que o geométrico */
124
- .cg-cortina__lockup{ display:flex; align-items:center; gap:clamp(10px,1.6vw,16px); padding:0 24px; }
125
- .cg-cortina__lockup--right{ flex-direction:column; align-items:flex-start; }
126
- .cg-cortina__row{ display:flex; align-items:center; gap:clamp(10px,1.6vw,16px); }
127
- .cg-cortina__lockup--right .cg-cortina__name{ animation-name:cg-cortina-nome-dir; }
128
- .cg-cortina__mark{ display:inline-flex; color:var(--color-ink,#14323a);
129
- animation:cg-cortina-mark 700ms var(--ease-cg,cubic-bezier(.2,.8,.2,1)) both; }
130
- /* símbolo ~1.25× o corpo do nome (a caixa do SVG é justa ao glifo), fluido.
131
- Por altura: um símbolo injetado não-quadrado (TTCAB) mantém a proporção. */
132
- .cg-cortina__mark svg{ height:var(--cg-cortina-mark); width:auto; }
133
- .cg-cortina__text{ display:flex; flex-direction:column; min-width:0; }
134
- .cg-cortina__name{
135
- font-family:var(--font-heading,system-ui,sans-serif);
136
- font-weight:700; font-size:clamp(2rem,6vw,3rem); line-height:1; letter-spacing:-.02em;
137
- animation:cg-cortina-nome 600ms var(--ease-cg,cubic-bezier(.2,.8,.2,1)) 480ms both;
138
- }
139
- .cg-cortina__tag{
140
- margin-top:.55rem; font-family:var(--font-body,system-ui,sans-serif);
141
- font-size:clamp(.8rem,2.4vw,1rem); line-height:1.3; color:var(--color-ink-soft,#54707a);
142
- animation:cg-cortina-tag 500ms ease 820ms both;
143
- }
144
- @keyframes cg-cortina-sobe{ to{ transform:translateY(-100%); visibility:hidden; } }
145
- @keyframes cg-cortina-mark{ from{ opacity:0; transform:scale(.6) rotate(-16deg); } }
146
- @keyframes cg-cortina-nome{ from{ opacity:0; transform:translateX(-8px); } }
147
- @keyframes cg-cortina-nome-dir{ from{ opacity:0; transform:translateX(8px); } }
148
- @keyframes cg-cortina-tag{ from{ opacity:0; transform:translateY(4px); } }
149
- html[data-cg-cortina="vista"] .cg-cortina{ display:none; }
150
- @media (prefers-reduced-motion:reduce){ .cg-cortina{ display:none; } }
151
- @media print{ .cg-cortina{ display:none; } }
152
- `;