/* ============================================================
   HB-STYLES — CSS custom de hugobran.co, externalizado do header.
   Servido via jsDelivr a partir de github.com/hugg3d/fw-assets
   ============================================================ */

/* ------------------------------------------------------------
   FONTS: aplica "auger-mono" + feature ss01 (Angular Forms).
   O <link> do Typekit continua no header (tem de lá estar);
   este bloco só consome a font que ele carrega.
   html body (0-0-2) e nao body (0-0-1): a FW declara este mesmo token
   ao nivel do body, e num empate de especificidade ganha quem vem
   depois no documento. No portal a folha deles fica depois da nossa e
   os headings caiam para a Space Mono do tema.
   ------------------------------------------------------------ */
html body {
  --font-family-heading: "auger-mono", monospace;
  font-feature-settings: "ss01" on !important;
}
h1, h2, h3, h4, h5, h6 {
  font-style: normal;
  font-feature-settings: "ss01" on;
}
h1 { font-weight: 900; }
h2 { font-weight: 700; }
h3 { font-weight: 500; }
h4 { font-weight: 400; }
h5 { font-weight: 300; }
h6 { font-weight: 200; }

/* ------------------------------------------------------------
   BRAND TOKENS: paleta oficial do brandbook (FIXA, não muda com
   o tema). Declarada 1x; qualquer bloco custom herda via :root.
   ------------------------------------------------------------ */
:root {
  /* Paleta oficial (brandbook) */
  --digital-blue: #0031ff;
  --verified-blue: #0066ff;
  --ultramarine-blue: #011596;
  --paper-white: #fdfbf1;
  --redacted-black: #05040f;
  --highlighter-pen: #e3ff04;
  /* Utilitário (fora do brandbook) */
  --paper-border: #d0c9b8;
  /* Blur partilhado: header (FW) + switcher do gtranslate. Vivem no
     :root e nao no .header porque o wrapper do widget e' montado no
     <body> — fora do header, nao herdava dali. */
  --header-blur-amount: 24px;
  --header-blur-opacity: 0.03;   
    /* Máscara do logo: usada pelo .header__logo, .checkout__logo e
     .password__logo. No :root porque serve as três superfícies.
     Atenção: o URL tem o hash do ficheiro — muda a cada upload
     novo do logo. */
  --hb-logo-mask: url('https://imgproxy.fourthwall.dev/QdavVw4tyIWNN3Errw93X_Y6ZCva-X9_RruCTwAA90Y/w:320/sm:1/enc/bYy-aLNmwGInKb95/9xiAzPYDFF-dLQpg/1B0v91UyJR21S40C/d5fk9ozza1UXlUmr/X1rqf482uWJTS05E/ZSqU4x42F8PDim8N/2_6u5mXDUdWonxGy/8lFBRk0wJCcf6Qzm/ZJXgGxEMO-ktRf7P/pLK997XkKdaOQUJS/y9POoRsrzNzwBOjx/CpE6k3HW61TZfrrB/0725Yk1EMIDbzCNT/ufbQG90OnBGttpXI/lDY-joAdOvv9TmQB/Onyo_P1O3z-gdJfd.svg') no-repeat center / contain; 
}

/* ------------------------------------------------------------
   COLOR-SCHEME: alinha widgets nativos do browser (popups de
   select, scrollbars nativas, etc.) com o tema ativo.
   ------------------------------------------------------------ */
:root[data-scheme="dark"] { color-scheme: dark; }
:root[data-scheme="light"] { color-scheme: light; }

/* ------------------------------------------------------------
   SCROLLBARS: theme-aware. Thumb = primary (azul brand),
   track = background. Hover = on-background.
   ------------------------------------------------------------ */
/* Firefox */
html {
  scrollbar-width: thin;
  scrollbar-color: var(--color-primary) var(--color-background);
}
/* WebKit (Chrome/Safari/Edge) */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--color-background); }
::-webkit-scrollbar-thumb {
  background: var(--color-primary);
  border-radius: 8px;
  border: 3px solid var(--color-background);
}
::-webkit-scrollbar-thumb:hover {
  background: var(--color-on-background);
}
::-webkit-scrollbar-corner { background: var(--color-background); }

/* ------------------------------------------------------------
   HEADER: blur subtil + hover. Os valores do blur estao no :root
   (BRAND TOKENS) porque sao partilhados com o switcher de lingua.
   O hover fica ancorado no #fw-section-header, que so existe na
   loja: no portal o header fica solido, de proposito.
   ------------------------------------------------------------ */
.header {
  border-color: transparent !important;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
#fw-section-header .header:hover {
  background-color: rgba(var(--color-on-background-rgb), 0.05) !important;
  border-color: rgba(var(--color-on-background-rgb), 0.15) !important;
}

/* ------------------------------------------------------------
   GRID BG: padrão de grelha subtil (6% opacity) em toda a página.
   ------------------------------------------------------------ */
body::before {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: -999;
  background-image:
    linear-gradient(to right, var(--color-on-background) 1px, transparent 1px),
    linear-gradient(to bottom, var(--color-on-background) 1px, transparent 1px);
  background-size: 20px 20px;
  opacity: 0.06;
}

/* ------------------------------------------------------------
   HYPERLINKS DE CONTEÚDO: verified-blue + underline.
   Ancorado em .rich-text (portal) e .html-formatter (loja) — o
   wrapper exterior muda com a superfície, o .rich-text não.
   No hover: cor fixada e opacity a 1. A FW declara um a:hover
   próprio que ganha, e o resultado era um cinzento lavado.
   ------------------------------------------------------------ */
:is(.html-formatter, .rich-text) a {
  color: var(--verified-blue);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
  transition: opacity 0.2s ease, text-decoration-thickness 0.2s ease;
}
:is(.html-formatter, .rich-text) a:hover,
:is(.html-formatter, .rich-text) a:focus {
  color: var(--verified-blue) !important;
  opacity: 1;
  text-decoration-thickness: 4px;
  text-shadow: 0.02em 0 0 currentColor, -0.02em 0 0 currentColor;
}
/* Link dentro de um redacted: sobre o fundo azul usa a cor de contraste.
   Os dois selectores porque na loja o highlight vem de .revealed e no
   portal da classe do body — sem o segundo, o link mudava de cor
   sozinho ao entrar e sair da zona do observer. */
:is(.html-formatter, .rich-text) .redacted.revealed a,
body.hb-redacted-static :is(.html-formatter, .rich-text) .redacted a {
  color: var(--color-on-primary) !important;
}
/* Hover apaga o highlight: o link volta ao azul. */
@media (hover: hover) {
  :is(.html-formatter, .rich-text) .redacted.revealed:hover a,
  body.hb-redacted-static :is(.html-formatter, .rich-text) .redacted:hover a {
    color: var(--verified-blue) !important;
  }
}

/* ------------------------------------------------------------
   BACKLIGHT: gradiente radial que segue o cursor (desktop only).
   A <div class="backlight"> e o JS do mousemove ficaram no header;
   aqui está só a apresentação. Se este CSS não carregar, a div
   fica simplesmente invisível — falha segura.
   ------------------------------------------------------------ */
.backlight {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: -111;
    pointer-events: none;
    background: radial-gradient(
        circle 40vw at var(--x, 50%) var(--y, 50%),
        color-mix(in srgb, var(--color-on-background) 7%, transparent),
        transparent 60%
    );
}
@media (max-width: 768px) { .backlight { display: none; } }

/* ------------------------------------------------------------
   MOBILE NAV (<=639px) + LOGO via CSS mask (adapta à cor do tema).
   ATENÇÃO: o opacity:0 da img e a máscara do ::after têm de viver
   SEMPRE no mesmo ficheiro. Separados, um cenário de falha parcial
   deixava o logo invisível; juntos, se este CSS não carregar, a
   img original reaparece — falha segura.
   O ::after é inset:0, logo NÃO TEM CAIXA PRÓPRIA: herda a do
   contentor, que por sua vez depende da <img> — e essa está a
   opacity:0. No portal o .header__logo é item flex e colapsa a 0 de
   largura, pelo que a máscara fica sem onde pintar e o logo
   desaparece (só no portal; na loja a <img> dá largura). Daí a
   largura explícita abaixo: sem ela o logo some-se e nada no CSS o
   denuncia.
   O URL da máscara está no :root (BRAND TOKENS) como --hb-logo-mask,
   partilhado com o .checkout__logo e o .password__logo. Tem o hash
   do ficheiro: muda a cada upload novo do logo, e há um só sítio
   para o actualizar.
   ------------------------------------------------------------ */
@media (max-width: 639px) {
  .header__list.list.list--horizontal {
    flex-wrap: nowrap !important;
    gap: 12px !important;
  }
  .header__list.list.list--horizontal .list__item {
    padding: 0 2px !important;
  }
  /* Portal: .header__right-nav é grid-auto-flow:column com gap 24px
     da FW. Com 4 itens são 72px só de espaçamento e dá scroll lateral.
     Selector com o pai (0-2-0): no portal a folha da FW vem depois da
     nossa e um empate 0-1-0 perdia. */
  .header__section--right .header__right-nav { gap: 14px; }
}
/* Logo com máscara — todas as superfícies. A largura é o que muda
   entre elas; o mecanismo é o mesmo. */
.header__logo,
.checkout__logo,
.password__logo {
  position: relative;
}
.header__logo img,
.checkout__logo img,
.password__logo img {
  opacity: 0;
}
.header__logo::after,
.checkout__logo::after,
.password__logo::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: var(--color-on-background);
  -webkit-mask: var(--hb-logo-mask);
  mask: var(--hb-logo-mask);
  pointer-events: none;
}
/* Larguras: o ::after é inset:0 e não tem caixa própria (ver cabeçalho).
   Header: só no portal, onde a <img> a opacity:0 não dá largura.
   Checkout e password: o contentor é flex full-width e a máscara
   esticava com ele. */
.header__section--left .header__logo,
.header__section--middle .header__logo {
  width: 100px;
}
.checkout__logo,
.password__logo {
  width: 120px;
  margin: 0 auto;
}

/* ------------------------------------------------------------
   CHEVRONS: rodam 180° quando o dropdown está aberto
   (hover nos menus do site).
   ------------------------------------------------------------ */
.header__list-item .header__link-icon svg,
.footer__list-item .footer__link-icon svg {
  transition: transform 0.25s ease;
}
.header__list-item:hover .header__link-icon svg,
.footer__list-item:hover .footer__link-icon svg {
  transform: rotate(180deg);
}

/* ------------------------------------------------------------
   UI: botões/tabs radius 6px + badge visible@sm força display.
   ------------------------------------------------------------ */
.button, .tab { border-radius: 6px !important; }
.plan-cards__card-badge.visible\@sm { display: inline-flex !important; }

.plus-tax-label { font-size: 0.75em; opacity: 0.6; }

/* ------------------------------------------------------------
   BADGES: cor primária + heading font + radius 4px.
   ------------------------------------------------------------ */
.badge {
  background-color: var(--color-primary) !important;
  color: var(--color-on-primary) !important;
  border-color: var(--color-primary) !important;
  border-radius: 4px;
  font-family: var(--font-family-heading) !important;
}

/* ------------------------------------------------------------
   STICKY BAR (/supporters, deslogado)
   A barra é grid e a FW dava-lhe 2 colunas iguais (~159px cada
   num ecrã de 370px). O botão ficava espremido, quebrava em 2
   linhas e era ELE a ditar a altura da barra.
   1fr auto -> o botão ocupa só o que precisa, o resto vai para o texto.
   ------------------------------------------------------------ */
@media (max-width: 639px) {
  .sticky-bar {
    grid-template-columns: 1fr auto !important;
    align-items: center !important;
  }
  .sticky-bar > .button { white-space: nowrap !important; }
}

/* Texto a 2 linhas com reticências.
   ÂMBITO IMPORTANTE: só o span curto (.hidden@sm) e só em mobile,
   onde ele é o visível. O -webkit-line-clamp obriga a mexer no
   display, e a FW usa display:none para alternar os dois spans —
   aplicar isto a ambos fazia aparecer o texto longo em mobile.
   O @ da classe tem de ser escapado: .hidden\@sm
   ------------------------------------------------------------ */
@media (max-width: 639px) {
  .sticky-bar > span.hidden\@sm {
    display: -webkit-box !important;
    -webkit-line-clamp: 2 !important;
    -webkit-box-orient: vertical !important;
    overflow: hidden !important;
    overflow-wrap: anywhere !important;
    min-width: 0 !important;
  }
}

/* ------------------------------------------------------------
   STICKY ADD TO CART (desktop): passa de barra full-width a card
   ancorado à direita, com slide de baixo.
   ------------------------------------------------------------ */
@media (min-width: 640px) {
  .sticky-add-to-cart {
    display: block !important;
    width: auto !important;
    max-width: 480px !important;
    left: auto !important;
    right: 24px !important;
    bottom: -120px;
    transition: bottom 0.3s ease-in-out !important;
  }
  .sticky-add-to-cart.is-visible { bottom: 6px !important; }
}

/* ------------------------------------------------------------
   CHECKOUT P.M.: esconde o cartao do plano mensal e centra o anual.
   Ancorado no data-testid — a FW acrescentou .plan-cards__container
   e a versao posicional (> a:first-child) deixou de casar.
   Par do auto-click anual no script PLANOS (header).
   ------------------------------------------------------------ */
.plan-cards [data-testid="Checkout.PlanCard.Monthly"] { display: none !important; }
.plan-cards__container { display: flex !important; justify-content: center; }
.plan-cards [data-testid="Checkout.PlanCard.Annual"] { flex: 0 1 320px; }

/* ------------------------------------------------------------
   PRECOS ANUALIZADOS: o .plan__price e' flex e cada <span> vira um
   item rigido — em block o texto flui e centra-se como na loja.
   O riscado leva display:block porque a quebra natural e' gananciosa:
   enche a 1a linha ate' ao fim e so' o (+IVA) e' que desce.
   .plan__nominal-price so' existe na variante com intro offer, por
   isso os restantes cards ficam intactos.
   ------------------------------------------------------------ */
.plan__price[data-annualized] {
  display: block;
  text-align: center;
}
.plan__price[data-annualized] .plan__nominal-price {
  display: block;
}

/* ------------------------------------------------------------
   REDACTED: highlight da marca com hover-reveal; a conversão de
   [r]...[/r] em spans e o IntersectionObserver estão no header.
   ------------------------------------------------------------ */
.redacted {
  color: var(--color-on-background);
  background-color: transparent;
  padding: 0 2px;
  border-radius: 2px;
  cursor: help;
  transition: background-color 0.3s ease, color 0.3s ease;
}
.redacted.revealed {
  color: var(--color-background);
  background-color: var(--color-primary);
}

/* Portal: highlight sempre visível, sem scroll reveal. A classe vem
   do JS, pelo path. O observer continua a pôr .revealed; esta regra
   não depende dela. */
body.hb-redacted-static .redacted {
  color: var(--color-background);
  background-color: var(--color-primary);
}

/* Hover só onde há rato. Os dois selectores porque na loja o
   highlight vem de .revealed e no portal vem da classe do body. */
@media (hover: hover) {
  .redacted.revealed:hover,
  body.hb-redacted-static .redacted:hover {
    color: var(--color-on-background);
    background-color: transparent;
  }
}

/* ------------------------------------------------------------
   SCROLL REVEAL: fade-up + hover scale; a lógica JS está no footer.
   Esconde APENAS o que o JS marcou (data-hb-sr). Conteúdo injetado
   tarde pela FW (recent-posts, tiktoks, reviews, cookie banner)
   nunca passa pelo JS, logo nunca é marcado, logo nunca fica preso
   invisível.
   ------------------------------------------------------------ */
body.scroll-animate [data-hb-sr] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.6s ease-out, transform 0.6s ease-out;
}
body.scroll-animate .is-visible {
  opacity: 1 !important;
  transform: translateY(0);
}
@media (hover: hover) {
  body.scroll-animate .tile.is-visible:hover,
  body.scroll-animate .product-card.is-visible:hover,
  body.scroll-animate .collection-card.is-visible:hover,
  body.scroll-animate [class*="card"].is-visible:hover,
  body.scroll-animate [class*="grid"] > *.is-visible:hover {
    transform: translateY(0) scale(1.0055);
  }
  .button:hover, .tab:hover { transform: scale(1.02); opacity: 0.9; }
  .button--primary:hover { color: var(--color-on-primary); }
  .button--secondary:hover { color: var(--color-on-secondary); }
  .button, .tab { transition: transform 0.3s ease-out, opacity 0.3s ease-out; }
}

/* ------------------------------------------------------------
   GTRANSLATE (visual): widget floating-glass igual ao header
   nativo do FW. Reutiliza --header-blur-amount + --header-blur-opacity
   para ficar sincronizado com qualquer ajuste ao header floating.
   Universal selector força theme-aware color (sobrepõe o color
   inline #fdfbf1 das settings do widget no header) — SEM este
   bloco, o texto do switcher fica branco sobre fundo claro.
   ------------------------------------------------------------ */
.gtranslate_wrapper {
  position: fixed;
  bottom: 6px;
  left: 6px;
  z-index: 9999;
  display: inline-flex;
  align-items: center;
  font-size: 11px;
}

/* ------------------------------------------------------------
   GTRANSLATE vs STICKY BAR (/supporters, deslogado)
   Ambos sao position:fixed no canto inferior esquerdo, logo a
   barra tapava o widget. A barra so existe para quem nao tem
   sessao iniciada e e' irma do wrapper no <body>, por isso o
   :has() cobre exactamente esse caso — sem JS, sem medir alturas.
   79px = 73 da barra + os mesmos 6 de folga que o widget tem ao
   fundo do ecra quando esta sozinho. Com sessao iniciada a barra
   nao existe, a regra nao casa, e o widget volta aos 6px.
   ------------------------------------------------------------ */
body:has(.sticky-bar) .gtranslate_wrapper {
  bottom: 79px;
}

/* ------------------------------------------------------------
   SWITCHER DE LÍNGUA (comportamento): desliza de baixo (sem fade),
   sem mexer no transform do widget. Esconde enquanto o CTA sticky
   está visível; reaparece só depois de o CTA sair.
   ------------------------------------------------------------ */
@media (max-width: 639px) {
  body:has(.sticky-add-to-cart.is-visible) .gtranslate_wrapper {
    bottom: -100px;
    pointer-events: none;
    transition: bottom 0.3s ease 0s;
  }
}

.gtranslate_wrapper .gt_switcher {
  /* position + z-index explicitos: defensivo o filter/backdrop-filter abaixo cria
     um contexto de empilhamento proprio. Com position:static esse
     contexto era pintado como conteudo em fluxo e o widget ficava por
     baixo de elementos da pagina, apesar do z-index 9999 do wrapper. */
  position: relative;
  z-index: 1;
  font-family: inherit !important;
  font-size: inherit !important;
  background-color: rgba(var(--color-background-rgb), var(--header-blur-opacity, 0.03)) !important;
  border: 1px solid rgba(var(--color-on-background-rgb), var(--header-blur-opacity, 0.03)) !important;
  border-radius: 4px;
  padding: 4px 8px;
  backdrop-filter: blur(var(--header-blur-amount, 24px));
  -webkit-backdrop-filter: blur(var(--header-blur-amount, 24px));
  filter: saturate(1.2);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.gtranslate_wrapper .gt_switcher:hover {
  background-color: rgba(var(--color-on-background-rgb), 0.08) !important;
  border-color: rgba(var(--color-on-background-rgb), 0.15) !important;
}
/* Força cor do texto em tudo (sobrepõe inline color do gtranslate).
   Não afecta flags (img/svg com fill próprio). */
.gtranslate_wrapper * {
  color: var(--color-on-background) !important;
}
.gtranslate_wrapper .gt_switcher .gt_option {
  font-family: inherit !important;
  font-size: inherit !important;
}
.gtranslate_wrapper .gt_options {
  background-color: rgba(var(--color-background-rgb), 0.92) !important;
  border: 1px solid rgba(var(--color-on-background-rgb), 0.1) !important;
  border-radius: 6px;
  backdrop-filter: blur(var(--header-blur-amount, 24px));
  -webkit-backdrop-filter: blur(var(--header-blur-amount, 24px));
}
.gtranslate_wrapper .gt_option:hover,
.gtranslate_wrapper .gt_options a:hover {
  background-color: rgba(var(--color-on-background-rgb), 0.01) !important;
}

@media (max-width: 768px) {
  .gtranslate_wrapper {
    right: 0;
    left: 0;
    margin: 0 auto;
    width: fit-content;
    bottom: 6px;
    justify-content: center;
  }

  /* ------------------------------------------------------------
     GTRANSLATE vs DRAWER (mobile)
     O widget e' fixed com z-index alto, logo flutuava por cima do
     menu lateral e tapava o CTA. O FW poe .scroll-lock no <html>
     enquanto o drawer esta aberto — usamos isso para o esconder.
     ------------------------------------------------------------ */
  html.scroll-lock .gtranslate_wrapper {
    opacity: 0;
    pointer-events: none;
  }
}

/* Par do EXCLUDED_PATHS (TRANSLATE PROTECTION, header): esconde o
   switcher nas paginas onde o gtranslate esta desligado. */
body[data-no-translate-page] .gtranslate_wrapper {
  display: none !important;
}

/* ------------------------------------------------------------
   GT ARROW: substitui a seta do gtranslate pelo chevron nativo
   do FW (path copiado do DOM do header) via mask, pintado
   theme-aware. Rotação 180 horária a combinar com os chevrons
   do site. SVG desduplicado via custom property.
   ------------------------------------------------------------ */
.gtranslate_wrapper .gt_switcher .gt_selected a::after {
  --hb-gt-chevron: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M6.683 11.634.436 4.494l1.128-.988 6.248 7.14a.25.25 0 0 0 .376 0l6.248-7.14 1.128.988-6.247 7.14a1.75 1.75 0 0 1-2.634 0Z'/></svg>") no-repeat 50% / 9px;
  background-image: none !important;
  background-color: var(--color-on-background);
  mask: var(--hb-gt-chevron);
  -webkit-mask: var(--hb-gt-chevron);
}
.gtranslate_wrapper .gt_switcher .gt_selected a.open::after {
  transform: rotate(180deg) !important;
}

/* ============================================================
   BRAND POLISH (todos CSS, sem JS). Dependem dos BRAND TOKENS
   no :root acima. Verificados contra conflitos com header/footer.
   ============================================================ */

/* Modal de cancelamento: os dois paineis medem 364px num ecra de 360
   e empurram o conteudo para fora. Ja empilham correctamente — falta
   so nao ultrapassarem a largura disponivel. */
@media (max-width: 639px) {
  .subscription-cancel-modal__left,
  .subscription-cancel-modal__right {
    max-width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box;
  }
}

/* "No badges": ::before gerado pela FW com :not(:has(.badges__list-item)).
   Nao usar :empty — o <ul> tem espacos em branco e nunca casa.
   #id para ganhar a especificidade deles. */
#hidden.badges__list-items:not(:has(.badges__list-item))::before,
#visible.badges__list-items:not(:has(.badges__list-item))::before {
  content: "Sem emblemas" !important;
}

/* ::SELECTION: seleção de texto = marcador highlighter-pen (brand). */
::selection { background-color: var(--highlighter-pen); color: var(--redacted-black); }
::-moz-selection { background-color: var(--highlighter-pen); color: var(--redacted-black); }

/* FOCUS RING: anel verified-blue no foco por teclado (a11y + "verificado"). */
:focus-visible { outline: 2px solid var(--verified-blue); outline-offset: 2px; }

/* Toggle de tema: o .header__link do tema pinta o :focus com cinzento,
   e o ícone ficava acinzentado depois do clique até se clicar fora.
   Foco de rato não precisa de indicação; foco de teclado usa o anel
   :focus-visible global (bloco FOCUS RING acima). */
.hb-scheme-toggle:focus:not(:focus-visible) {
  color: inherit;
}

/* ...mas nos campos de texto desenha-se no WRAPPER, nao no input: o
   input tem dimensoes e border-radius diferentes da caixa visivel, e o
   anel ficava desalinhado (e deixava botoes irmaos de fora). */
.input__field:focus, .input-field__input:focus,
.search-header__input:focus, .search-bar__input:focus,
.textarea__field:focus, .ql-editor:focus {
  outline: none !important;
  box-shadow: none !important;
}

.input:focus-within,
.input-field:focus-within,
.search-header__form:focus-within,
.search-bar__form:focus-within,
.textarea:focus-within,
.ql-container:focus-within {
  outline: 2px solid var(--verified-blue);
  outline-offset: 2px;
  border-radius: 6px;
}

/* CARET: cursor de escrita digital nos campos de texto. */
input, textarea, [contenteditable] { caret-color: var(--color-primary); }

/* CARET PISCANTE: cursor decorativo. Cor = primary do tema (azul light /
   amarelo dark). Dentro do terminal usa verified-blue p/ se ver nos 2 painéis. */
.hb-caret {
  display: inline-block;
  width: 4px;
  height: 1.1em;
  margin-left: 3px;
  vertical-align: -0.18em;
  background-color: var(--color-primary);
  animation: hb-caret-blink 1.05s steps(1, end) infinite;
}
.hb-terminal .hb-caret { background-color: var(--verified-blue); }
@keyframes hb-caret-blink { 50% { opacity: 0; } }
