/* INNA design system, extracted from the prototype's visual language */
:root {
  /* Diz ao browser em que mundo é que ele está a desenhar: os comandos que são
     dele, o do áudio à cabeça, vinham em branco leitoso no meio do escuro. */
  color-scheme: dark;
  --bg: #0a0908;
  --frame: #14110C;
  --ink: #EFE6D8;
  --ink-70: rgba(239, 230, 216, .7);
  /* .5 chegava sobre o fundo, mas dentro de um cartão o fundo é mais claro e
     caía para 4.1:1. Medido lá dentro, que é onde este cinzento vive. */
  --ink-50: rgba(239, 230, 216, .58);
  --ink-30: rgba(239, 230, 216, .38);   /* setas e traços: .3 dava 2,4:1 */
  --ink-12: rgba(239, 230, 216, .12);
  --ink-06: rgba(239, 230, 216, .06);
  --gold: #C89A55;
  /* Brand gold and text gold are not the same job. On the light theme the
     brand gold reads 3.37:1, which is fine for a border or a 40px number and
     not fine for a 14px line of text. */
  --gold-text: #C89A55;
  --on-gold: #1E1710;                /* ink, for labels sitting on gold: 6.93:1 aqui */
  --gold-soft: rgba(200, 154, 85, .16);
  --gold-border: rgba(200, 154, 85, .4);
  --green: #7FA88C;
  --danger: #E0907E;
  --danger-soft: rgba(198, 106, 90, .16);
  /**
   * A luz do ecrã tem a cor do sítio do céu onde o Sol está.
   *
   * Eram 64 chaves debaixo do mesmo dourado. O matiz vem do signo em que a
   * chave cai, que é uma coisa que acontece no céu e não uma escolha de
   * paleta, e move-se numa banda estreita à volta do ouro da marca: do rosa
   * ao ouro-oliva, um ano inteiro a atravessá-la. O ouro da marca não se
   * mexe, só a atmosfera é que muda.
   */
  --chave-h: 35;
  --rays-a: .18;
  --rays: hsla(var(--chave-h) 52% 57% / var(--rays-a));
}

/**
 * O dia: papel branco na app, papel creme onde se lê devagar.
 *
 * O logótipo é preto sobre branco, e a app de dia era creme com dourado por
 * todo o lado: parecia de outra casa, e o dourado, por estar em tudo, não
 * acendia nada. Aqui o branco dá a cara do logótipo e o dourado volta a ser o
 * acento, só onde alguma coisa está viva: a chave de agora, o que se pode
 * tocar.
 *
 * O creme não se perdeu, mudou de função. Ficou onde as pessoas param: a
 * contemplação de uma chave, o texto do mês, o diário. Branco cansa numa
 * leitura longa, e esses são os únicos sítios da app onde se lê devagar.
 */
[data-theme="light"] {
  color-scheme: light;
  --bg: #EDEDED;
  --frame: #FFFFFF;
  --papel: #F7F1E6;                  /* o creme, agora só para ler */
  --ink: #111111;
  --ink-70: rgba(17, 17, 17, .74);
  --ink-50: #5A5A5A;                 /* 7:1 sobre branco */
  --ink-30: rgba(17, 17, 17, .38);
  --ink-12: rgba(17, 17, 17, .12);
  --ink-06: rgba(17, 17, 17, .045);
  --gold: #9A6E22;
  --gold-text: #7A5620;              /* 6.4:1 sobre branco */
  /**
   * O preto do botão dourado, suavizado.
   *
   * Preto puro sobre dourado é duro, e o dourado do tema claro é claro de mais
   * para levar texto claro por cima: creme dá 3.37:1 e falha. Este castanho
   * muito escuro tira-lhe a dureza e fica em 4.67:1, acima do mínimo de 4.5 que
   * as maiúsculas de 12.8px destes botões exigem. Descer mais um tom já
   * reprovava, e um botão bonito que se lê mal não é um botão bonito.
   */
  /* Texto branco sobre o dourado, e é por isso que este dourado é mais escuro
     do que o da marca: com o dourado claro, branco por cima dava 2.4:1. */
  --on-gold: #FFFFFF;
  --gold-soft: rgba(154, 110, 34, .10);
  --gold-border: rgba(154, 110, 34, .38);
  --green: #2F6B45;
  --danger: #A33124;
  --danger-soft: rgba(163, 49, 36, .10);
  /* Os raios do fundo deixam de ser dourados: em papel branco, dourado de fundo
     lê-se como uma mancha amarela, e o dourado só deve aparecer onde acende. */
  --rays-a: .07;
  --rays: rgba(17, 17, 17, var(--rays-a));
}
/* O botão cheio precisa de um dourado que aguente branco por cima: 4.9:1. */
[data-theme="light"] .btn-gold { background: #8A6220; }
/**
 * As superfícies de leitura, em papel creme.
 *
 * Marcadas uma a uma com `leitura`, e não apanhadas por uma regra que procure
 * parágrafos: uma regra dessas transformava em creme qualquer cartão com texto
 * que alguém escrevesse a seguir, e daqui a um ano a app estava outra vez toda
 * creme sem ninguém ter decidido isso.
 *
 * São três sítios: as frequências de uma chave, o texto que a Inna escreve para
 * o mês, e as caixas onde se escreve, incluindo o diário. São os únicos onde se
 * lê ou se escreve devagar, e é a única coisa nesta app que mudou de cor por
 * causa dos olhos e não por causa da marca.
 */
[data-theme="light"] .leitura,
[data-theme="light"] .degrau-corpo,
[data-theme="light"] .field textarea,
[data-theme="light"] textarea {
  background: var(--papel);
  border-color: rgba(42, 36, 26, .12);
}
[data-theme="light"] .frame { box-shadow: 0 24px 70px rgba(0, 0, 0, .16); }
[data-theme="light"] .logo-mark { content: url("/assets/inna-logo-ink.png"); }

/* Type scale, 7 steps, in rem, so the app grows with the reader's own setting.
   Base 16px: xs 12.8 · sm 14.4 · md 16 · lg 17.6 · xl 21 · 2xl 27 · hero 88+ */
:root {
  /* O degrau mais pequeno da escala existe porque as sobrancelhas e as
     legendas precisavam dele: sem ele apareciam a 9, 9.5 e 11px, três medidas
     inventadas e duas delas no limite do legível. */
  --t-2xs: .7rem;
  --t-xs: .8rem; --t-sm: .9rem; --t-md: 1rem; --t-lg: 1.1rem;
  --t-xl: 1.3rem; --t-xxl: 1.5rem; --t-2xl: 1.7rem; --t-3xl: 2.2rem;
  --tap: 44px;                 /* minimum comfortable touch target */

  /**
   * Os cantos, em três medidas e não em sete.
   *
   * A app tinha cartões a 6, o destaque a 12, os planos a 14, a folha a 20, os
   * botões a 4 e as caixas de texto a 4: seis raios diferentes para duas
   * famílias de coisas. Uma superfície onde se pousa conteúdo arredonda de uma
   * maneira; um controlo onde se toca arredonda de outra; a folha que sobe do
   * fundo é a única que arredonda muito, porque imita uma gaveta.
   */
  /**
   * O espaço, em degraus e não a olho.
   *
   * A app tinha margens de 2, 3, 4, 6, 9, 10, 13, 22 e 26px e gaps de 5, 7, 9 e
   * 13: cada um decidido no momento em que se escreveu a regra, e nenhum
   * relacionado com o anterior. Dois cartões seguidos com 22px entre si e
   * outros dois com 26 leem-se como um erro sem que ninguém saiba dizer onde.
   *
   * Seis degraus chegam para tudo o que esta app faz, e a distância entre dois
   * elementos passa a ser uma escolha entre seis e não entre trinta.
   */
  --e-0: 2px;   /* colado: duas linhas do mesmo bloco de texto */
  --e-1: 4px;   /* dentro de uma coisa: um ícone e a sua palavra */
  --e-2: 8px;   /* entre irmãos próximos: linhas de um cartão */
  --e-3: 12px;  /* entre irmãos: cartões de uma lista */
  --e-4: 16px;  /* entre blocos do mesmo assunto */
  --e-5: 24px;  /* entre assuntos */
  --e-6: 32px;  /* respiração grande, antes de um fim ou de um recomeço */

  --r-ctrl: 8px;               /* botões, campos, separadores */
  --r-card: 12px;              /* cartões, caixas, blocos */
  --r-folha: 20px;             /* a folha que sobe do fundo */
  --r-pill: 99px;              /* cápsulas e chips */
}

* { box-sizing: border-box; }
svg { display: block; }   /* no inline-baseline gap under SVGs (throws off ray anchoring) */
[hidden] { display: none !important; }
::-webkit-scrollbar { display: none; }
html, body { margin: 0; height: 100%; }
/**
 * Os parágrafos e as listas perdem a margem que o browser lhes dá.
 *
 * Os títulos já a tinham perdido, os parágrafos não, e por isso apareciam
 * 14.4px e 17.6px de espaço no meio de ecrãs onde tudo o resto anda na escala:
 * eram os valores do próprio browser, calculados a partir do tamanho da letra e
 * alheios a qualquer decisão nossa. O espaço entre coisas é dado pelo `gap` de
 * quem as contém, que é uma medida só e não uma soma de duas.
 */
p, ul, ol, figure { margin: 0; }
body { background: var(--bg); font-family: 'Poppins', sans-serif; color: var(--ink); }
button { font-family: inherit; color: inherit; background: none; border: none; padding: 0; cursor: pointer; text-align: left; }
/* Sem color-scheme forçado: ele herda-se do :root, que já diz se estamos de dia
   ou de noite. Forçado a escuro, o calendário nativo abria preto por cima do
   papel creme, com o ícone quase invisível, e parecia partido. */
input, textarea, select { font-family: inherit; }
a { color: var(--gold); text-decoration: none; }

.stage { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: var(--e-5); position: relative; }
/* A roda por trás de tudo, só onde há ecrã a sobrar para ela. Acima dos 900 a
   app é uma página com uma medida de leitura ao meio, e o que sobra dos dois
   lados era preto por preto. Aqui a roda é o papel de parede. */
.fundo-roda { display: none; }
@media (min-width: 900px) and (display-mode: browser) {
  .fundo-roda {
    display: block; position: fixed; left: 50%; top: 50%;
    width: min(96vh, 980px); height: min(96vh, 980px); transform: translate(-50%, -50%);
    pointer-events: none; z-index: 0; opacity: .55;
  }
  .frame { position: relative; z-index: 1; background: transparent; }
  .stage { background: var(--frame); }
}
.frame {
  width: 390px; height: min(844px, calc(100dvh - 48px)); background: var(--frame);
  border-radius: 38px; overflow: hidden; position: relative;
  box-shadow: 0 30px 80px rgba(0, 0, 0, .6); display: flex; flex-direction: column;
}
@media (max-width: 560px), (display-mode: standalone) {
  /* One fixed viewport, one scroller (.screen). The shell is pinned to the real
     screen edges; the safe area is paid once, by the bars that touch those edges. */
  html, body { overflow: hidden; }
  .stage { position: fixed; inset: 0; padding: 0; min-height: 0; height: 100dvh; }
  .frame { width: 100%; height: 100%; border-radius: 0; box-shadow: none; padding: 0; }
  .nav { padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
}

/* A tira da app de testes: encostada ao topo real do ecrã, por cima de tudo,
   e a pagar ela própria a margem da barra de estado, porque passa a ser ela a
   primeira coisa que lá está. */
.tira-testes {
  flex: none; text-align: center; font-size: var(--t-2xs); font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  background: var(--danger); color: #14110C;
  padding: calc(var(--e-1) + env(safe-area-inset-top, 0px)) var(--e-2) var(--e-1);
}
.tira-testes + .topbar { padding-top: var(--e-3); }

.topbar {
  flex: none; display: flex; justify-content: center; align-items: center; position: relative;
  padding: var(--e-4) var(--e-5) 0; font-size: var(--t-xs); letter-spacing: .16em; color: var(--ink-50); font-weight: 600;
}
/* Both header controls were 17px glyphs with a click listener on them: under
   the 44px floor, and the bell was not even a button, so a keyboard could never
   reach the notices. Now they are real buttons with a fingertip around them,
   and the icon stays where it was. */
.bell {
  position: absolute; right: 15px; top: 12px;
  display: flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap);
  background: none; border: 0; padding: 0;
  color: var(--ink-70); cursor: pointer;
}
.bell-icone { position: relative; display: flex; }
@keyframes installGlow {
  0%, 72%, 100% { color: var(--ink-50); transform: none; }
  80% { color: var(--gold); transform: translateY(1.5px); }
  88% { color: var(--gold); transform: none; }
}
.install-hint {
  position: absolute; left: 15px; top: 12px;
  display: flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap);
  background: none; border: 0; padding: 0;
  color: var(--ink-50); cursor: pointer;
  animation: installGlow 5s ease-in-out infinite;
}

/**
 * O topo do ecrã é da barra de estado, e não nosso.
 *
 * Isto já estava escrito, mas trinta linhas acima da regra `.topbar`, que
 * declara `padding` em atalho: o atalho reescrevia o padding-top todo e a
 * margem de segurança nunca chegou a existir. Pior, os dois botões são
 * absolutos e ficavam a 12px do topo do ecrã, ou seja, dentro do relógio e da
 * ilha do iPhone, onde os toques pertencem ao sistema. Quem instalou a app no
 * iPhone não conseguia carregar no sino, e não havia nada no ecrã que
 * explicasse porquê.
 *
 * Fica tudo junto e depois dos dois botões, para nada disto poder voltar a ser
 * apagado por uma regra escrita mais abaixo.
 */
@media (max-width: 560px), (display-mode: standalone) {
  .topbar { padding-top: calc(var(--e-3) + env(safe-area-inset-top, 0px)); }
  .install-hint, .bell { top: calc(12px + env(safe-area-inset-top, 0px)); }
}

@media (prefers-reduced-motion: reduce) { .install-hint { animation: none; color: var(--gold); } }
/* The dot became a count: "something happened" is easy to walk past, "3" is not.
   It sits on the bell's shoulder with a ring of the surface behind it, so it
   reads as attached to the bell instead of floating near it. */
.bell-dot {
  position: absolute; top: -3px; right: -4px; width: 6px; height: 6px;
  border-radius: var(--r-pill); background: transparent;
}
.bell-dot.on {
  top: -6px; right: -7px;
  width: auto; min-width: 9px; height: 15px; padding: 0 var(--e-0);
  background: var(--gold); color: var(--frame);
  border: 1.5px solid var(--frame);
  font-size: 9px; font-weight: 700; line-height: 12px; letter-spacing: 0; text-align: center;
}

.offline-banner {
  flex: none; background: var(--danger-soft); border-bottom: 1px solid rgba(198, 106, 90, .4);
  padding: var(--e-2) var(--e-5); font-size: var(--t-2xs); line-height: 1.4; color: rgba(239, 230, 216, .85);
}

/* O conteúdo era guilhotinado a direito por baixo do "INNA METHOD": meia linha
   de texto ficava colada à barra e lia-se como se lhe passasse por baixo. Sai
   por uma dissolvência de 14px, que é o que uma folha faz ao virar. */
.screen {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 14px);
  mask-image: linear-gradient(180deg, transparent 0, #000 14px);

  flex: 1; min-height: 0;   /* contains scrolling here, keeps the nav pinned */
  overflow-y: auto; overflow-x: hidden;
  /* O dedo desce a página como sempre, e o que anda de lado é nosso: é isto que
     deixa passar de página a arrastar sem tirar o scroll a ninguém. */
  touch-action: pan-y;
  overscroll-behavior: contain;
  padding: var(--e-4) var(--e-5) var(--e-6); display: flex; flex-direction: column; gap: var(--e-4);
  position: relative; z-index: 1;   /* content slides above the fixed rays */
}
.screen.center { justify-content: center; align-items: center; text-align: center; }
.screen > * { position: relative; flex-shrink: 0; }

/* The design's signature golden ray-burst, fixed to the frame, behind the
   scrolling content, so it never adds sideways scrollable overflow. */
/**
 * The burst opens downward from an arc, the way it does in the logo, and never
 * above it: that space belongs to the antlers.
 *
 * Geometry does the cutting, not a mask. Two mask layers with `mask-composite`
 * looked right in theory and added instead of intersecting wherever the
 * property was not honoured, which put rays back above the horizon. Here the
 * element is only the half below the origin and the gradient radiates from its
 * top edge, so there is nowhere above for a ray to be drawn. It also cannot
 * ever read as rotated: the origin is pinned to the top, always.
 */
.rays {
  /**
   * O leque cresceu.
   *
   * Estava contido a 340 por 182: acabava antes de chegar às margens e morria
   * a meio caminho do texto, o que dava um brilho educado à volta do número em
   * vez da luz que a marca tem. Agora atravessa o ecrã, e as pontas apagam-se
   * lá em baixo em vez de pararem a meio: é a mesma luz, com espaço para se
   * abrir.
   */
  position: absolute; left: 50%; top: 108px; width: 560px; height: 300px;
  transform: translate(-50%, 0); pointer-events: none; z-index: 0; overflow: hidden;
  /* One layer: the arc in the middle, then full, then the tips fading out. */
  -webkit-mask-image: radial-gradient(circle 300px at 50% 0, transparent 0 46px, #000 72px 190px, transparent 296px);
  mask-image: radial-gradient(circle 300px at 50% 0, transparent 0 46px, #000 72px 190px, transparent 296px);
}
/**
 * The window stays put; the light turns behind it.
 *
 * The spin used to be on the window itself, so the whole fan swung around and
 * dragged its own shape with it. The burst is a full circle here, centred on
 * the window's origin, and it is the window that decides we only ever see the
 * part below the antlers, exactly where the logo puts it.
 */
.rays::before {
  content: ''; position: absolute; left: 50%; top: 0; width: 640px; height: 640px;
  background: repeating-conic-gradient(var(--rays) 0deg var(--raio-w) , transparent var(--raio-w) var(--raio-gap));
  animation: raysSpin var(--raio-t) linear infinite;
}
/**
 * A luz muda com a frequência que está aberta.
 *
 * Sombra: raios finos e juntos, uma luz fechada que quase não passa. Dom:
 * abre-se. Siddhi: poucos, largos e claros, e a roda quase pára. Isto não é
 * enfeite, é a tese do método a acontecer no fundo do ecrã enquanto se lê.
 */
/**
 * A mudança de leque faz-se por desvanecimento, não por interpolação.
 *
 * Registar as propriedades com @property deixaria o browser atravessar os
 * ângulos, e no papel era a solução certa; na prática há motores que aceitam a
 * declaração e depois ignoram os valores, e a luz ficava presa num só estado.
 * Um leque que às vezes não muda é pior do que um que muda depressa. Aqui
 * apaga-se, troca-se, e acende-se, que é uma coisa que funciona em todo o lado.
 */
.rays {
  --raio-w: .5deg; --raio-gap: 4.5deg; --raio-t: 240s;
  transition: opacity .24s ease;
}
/* A duração da volta não muda com a frequência: mexer nela a meio reinicia a
   rotação e o leque dá um salto, que era metade do que não estava suave. */
.rays.f-shadow { --raio-w: .34deg; --raio-gap: 2.4deg; --rays-a: .13; }
.rays.f-gift { --raio-w: .5deg; --raio-gap: 4.5deg; --rays-a: .19; }
.rays.f-siddhi { --raio-w: .95deg; --raio-gap: 8.5deg; --rays-a: .26; }
@media (prefers-reduced-motion: reduce) { .rays { transition: none; } }
.rays.a-trocar { opacity: 0; }
/**
 * A roda das 64 leva o círculo inteiro.
 *
 * O leque do logótipo é a assinatura do início, onde há um número e duas
 * hastes. Uma mandala é redonda, e um leque a abrir para baixo por trás dela
 * corta-a ao meio sem dizer nada. Aqui a luz irradia de todos os lados, que é
 * o que a roda já é.
 */
.rays.roda, .rays.center {
  width: 560px; height: 560px; transform: translate(-50%, -50%); border-radius: 50%;
  -webkit-mask-image: radial-gradient(circle, #000 0 52%, transparent 78%);
  mask-image: radial-gradient(circle, #000 0 52%, transparent 78%);
}
.rays.roda::before, .rays.center::before { top: 50%; width: 660px; height: 660px; }
.rays.center { top: 340px; }   /* celebration screens (confirmação, proof) glow lower */

/**
 * A chave aberta é um ecrã de leitura, e a luz aqui é de cabeçalho.
 *
 * Presa ao número ficava meia coroa cortada pela margem esquerda, porque o
 * número está encostado a esse lado. Ancorada ao próprio ecrã, abre do topo
 * para baixo, ilumina o bloco de identidade (número, caminho, frequências) e
 * apaga-se antes de chegar às palavras que há para ler.
 */
.rays.chave {
  top: -30px; width: 460px; height: 250px;
  -webkit-mask-image: radial-gradient(circle 250px at 50% 0, transparent 0 40px, #000 70px 150px, transparent 244px);
  mask-image: radial-gradient(circle 250px at 50% 0, transparent 0 40px, #000 70px 150px, transparent 244px);
}
.rays.chave::before { width: 540px; height: 540px; }

/* Group-photo placeholder (design's diagonal stripes) */
.photo-ph {
  height: 180px; border-radius: var(--r-card);
  background: repeating-linear-gradient(45deg, rgba(239, 230, 216, .07) 0 10px, rgba(239, 230, 216, .03) 10px 20px);
  display: flex; align-items: center; justify-content: center;
  font-family: ui-monospace, Menlo, monospace; font-size: var(--t-2xs); color: var(--ink-50);
  text-align: center; padding: 0 var(--e-5);
}

.nav {
  flex: none; display: flex; justify-content: space-around;
  padding: var(--e-3) var(--e-1) var(--e-4);
  border-top: 1px solid var(--ink-12); background: var(--frame);
}
/* The five tabs share the width instead of pushing each other out: with the
   system text at 150% on a narrow phone, the last tab used to leave the screen.
   The label shrinks to fit and ellipsises; the icon and the tap target never do. */
.nav-item {
  display: flex; flex-direction: column; align-items: center; gap: var(--e-1);
  flex: 1 1 0; min-width: 0;
  font-weight: 700; letter-spacing: .08em; color: var(--ink-50);
  font-size: min(var(--t-xs), 3.4vw);
}
.nav-item > span:last-child {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nav-item.active { color: var(--gold); }

/* type */
h1 { font-size: var(--t-2xl); font-weight: 600; line-height: 1.25; margin: 0; }
h2 { font-size: var(--t-lg); font-weight: 600; margin: 0; }
.eyebrow { font-size: var(--t-xs); letter-spacing: .2em; text-transform: uppercase; color: var(--gold-text); font-weight: 600; }
/* Sobre o herói o sobrescrito diz a mesma coisa, mais baixinho: encurtá-lo a
   "agora" deixava o número sem contexto nenhum. */
.eyebrow.miudo { font-size: var(--t-2xs); letter-spacing: .22em; color: var(--ink-50); }
.muted { color: var(--ink-70); font-size: var(--t-md); line-height: 1.55; }
.small { font-size: var(--t-sm); color: var(--ink-50); line-height: 1.45; }

/**
 * Um campo é um campo, esteja ou não dentro de um `.field`.
 *
 * As regras dos campos viviam só dentro dessa caixa, e os que estão soltos
 * (os preços em Gerir, as horas, a percentagem de cada facilitador) ficavam
 * com o preenchimento que o browser lhes dá: 3px de um lado, 10 do outro,
 * medidas que não são de ninguém e que se viam ao lado das outras.
 */
input, select, textarea {
  font: inherit; color: var(--ink); background: var(--ink-06);
  border: 1px solid var(--ink-12); border-radius: var(--r-ctrl);
  padding: var(--e-2) var(--e-3);
}
/* A caixa de escolha vinha com 3px de margem do próprio browser, que era o
   último valor da app fora da escala: alinha-se pelo topo da linha de texto
   que tem ao lado. */
input[type="checkbox"], input[type="radio"] { padding: 0; margin: var(--e-1) 0 0; }
input[type="file"] { padding: var(--e-2); }

/* buttons */
.btn {
  display: block; width: 100%; text-align: center; padding: var(--e-3); border-radius: var(--r-ctrl);
  font-size: var(--t-sm); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
/* The label on a gold button must be dark ink in both themes. In the dark one
   --frame already is ink; in the light one it is cream, which put cream on gold
   at 3.37:1. --on-gold says what it means instead of relying on a coincidence. */
.btn-gold { background: var(--gold); color: var(--on-gold); }
.btn-gold:disabled { opacity: .4; cursor: default; }
.btn-ghost { border: 1px solid var(--ink-30); color: var(--ink); font-weight: 600; }
.btn-danger { border: 1px solid rgba(198, 106, 90, .5); color: var(--danger); font-weight: 600; }
.link-gold { color: var(--gold-text); font-size: var(--t-sm); font-weight: 600; letter-spacing: .06em; }

/* cards & lists */
.card { border: 1px solid var(--ink-12); border-radius: var(--r-card); padding: var(--e-4) var(--e-4); display: flex; flex-direction: column; gap: var(--e-2); background: var(--ink-06); }
.card.gold { border-color: var(--gold-border); background: var(--gold-soft); }
.row { display: flex; align-items: center; gap: var(--e-3); }
/* Without min-width:0 a flex child refuses to go below its content width, and
   whatever sits next to it gets pushed off the screen. */
.row .grow { flex: 1; min-width: 0; }
/* Sem folga, um valor que passa para a segunda linha encosta ao rótulo e
   lê-se "EstadoReserva a aguardar pagamento". */
/**
 * Rótulo à esquerda, valor à direita, e nenhum dos dois a sair pela borda.
 *
 * O rótulo tinha `flex: none`, portanto nunca encolhia nem partia linha: com um
 * rótulo comprido ("Próximo trânsito do Sol nesta chave") empurrava a data para
 * fora do cartão e ela era cortada pela margem. Agora ambos podem partir linha,
 * e quando não cabem lado a lado passam a duas linhas em vez de a uma cortada.
 */
.kv { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--e-1) var(--e-3); font-size: var(--t-md); }
.kv span:first-child { color: var(--ink-70); min-width: 0; overflow-wrap: anywhere; }
.kv span:last-child { text-align: right; min-width: 0; overflow-wrap: anywhere; }
.divider { height: 1px; background: var(--ink-12); }

.row .grow > div { max-width: 100%; overflow-wrap: anywhere; }


/* inputs */
.field { display: flex; flex-direction: column; gap: var(--e-1); }
.field label { font-size: var(--t-xs); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-50); font-weight: 600; }
.field input, .field textarea, .field select {
  background: var(--ink-06); border: 1px solid var(--ink-12); border-radius: var(--r-ctrl);
  color: var(--ink); padding: var(--e-3); font-size: var(--t-md); width: 100%; min-height: var(--tap);
}
/* The global :focus-visible rule was being cancelled here, leaving a border
   tint of 2.15:1 as the only sign of focus. WCAG needs 3:1, and someone
   navigating by keyboard needs to actually see where they are. */
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--gold); outline-offset: 2px; border-color: var(--gold);
}
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--gold); }
.field textarea { min-height: 110px; resize: vertical; line-height: 1.5; }

/* Key info under the wheel: the rows hold a steady height so spinning the bezel
   never reflows the page, and the buttons stay where your thumb left them.
   The heights are in em, not px, so they grow with the font instead of slicing
   the last line in half when someone bumps their system text size. */
.key-info-head { min-height: 2.9em; }
.key-info-pills {
  min-height: 2em; display: flex; flex-wrap: wrap; gap: var(--e-2) var(--e-1);
  overflow: hidden; max-height: 4.4em;
}
.key-info-text {
  --lines: 3;
  margin: 0; line-height: 1.5; height: calc(var(--lines) * 1.5em); overflow: hidden;
  /* height follows line-height, so changing the face cannot slice a line */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines);
}
/* Short screens have no room for three lines plus a button; show two. */
@media (max-height: 720px) { .key-info-text { --lines: 2; } }
.clamp-1 { display: block; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* key wheel */
.wheel { display: grid; grid-template-columns: repeat(8, 1fr); gap: var(--e-2); }
.wheel button {
  aspect-ratio: 1; border-radius: var(--r-ctrl); display: flex; align-items: center; justify-content: center;
  font-size: var(--t-xs); font-weight: 600; background: var(--ink-06);
  border: 1px solid var(--ink-12); color: var(--ink-50); position: relative;
}
.wheel button.passed { background: var(--gold-soft); border-color: var(--gold-border); color: var(--gold); }
.wheel button.active { background: var(--gold); border-color: var(--gold); color: var(--on-gold); }
.wheel button.sphere::after {
  content: ''; position: absolute; bottom: 3px; left: 50%; transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%; background: var(--gold);
}
.wheel button.active.sphere::after { background: var(--frame); }

/* frequency tabs */
/**
 * Separadores que cabem, e que quando não cabem se dividem em partes iguais.
 *
 * Eram flex com quebra de linha: com quatro, o quarto passava para baixo
 * sozinho e esticava-se de margem a margem, o que o fazia parecer outra coisa,
 * um botão principal em vez do quarto de quatro. Em grelha, quatro cabem em
 * quatro colunas quando há espaço e em duas linhas de dois quando não há, e em
 * qualquer dos casos são todos do mesmo tamanho.
 */
/**
 * As cápsulas repartem o espaço, mas cada uma leva o que a palavra precisa.
 *
 * Eram três colunas iguais, e a palavra mais comprida, «automático», enchia a
 * sua de ponta a ponta a tocar na linha. Com colunas iguais não há saída: ou a
 * palavra quebra em duas linhas, que é pior, ou encosta. Aqui as cápsulas
 * crescem a partir do que têm dentro e dividem entre si o que sobra, e por isso
 * a mais comprida fica com mais espaço do que as curtas, que é o que a mão
 * espera.
 */
.tabs { display: flex; flex-wrap: wrap; gap: var(--e-2); }
.tabs button { flex: 1 1 auto; }
/* Com quatro, dois e dois: três em cima e um em baixo lê-se como um resto, e
   este quarto é um modo como os outros. */
.tabs:has(button:nth-child(4)) button { flex-basis: calc(50% - var(--e-2)); }
/**
 * A palavra não encosta à cápsula.
 *
 * As três colunas são iguais, e a mais comprida das palavras, «automático»,
 * enchia a sua de ponta a ponta: o texto ficava a tocar a linha, e uma cápsula
 * cheia até à borda lê-se como um erro de medida. Com folga aos lados e uma
 * letra ligeiramente mais apertada, a palavra mais longa passa a ter ar dos dois
 * lados, e as curtas ficam iguais porque a coluna é que manda.
 */
.tabs button {
  min-width: 0; text-align: center;
  padding: var(--e-3) var(--e-4); border-radius: var(--r-pill); border: 1px solid var(--ink-30);
  font-size: var(--t-sm); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-50);
  /* Sem quebra: «AUTOMÁ / TICO» em duas linhas é pior do que encostado, e com a
     folga nova a palavra inteira cabe na coluna. */
  white-space: nowrap;
}
.tabs button.on { border-color: var(--gold); color: var(--gold-text); }

/* misc */
/* One chip for the whole app. Cards used to carry two different chip shapes
   side by side, a key tag and a state pill, that meant the same class of thing
   and looked unrelated. Same box everywhere now; only the tone changes. */
/**
 * As marcas deixam de ser balões.
 *
 * Uma cápsula com moldura é a mesma forma de um botão, e por isso pedia um
 * toque que não existe. E crescia com o texto: "o Sol está aqui, mais 5 dias"
 * virava um objeto do tamanho de um cartão, a competir com o título ao lado.
 *
 * Fica uma barra fina à esquerda e o texto a seguir. Lê-se como uma anotação à
 * margem, que é o que uma marca é, e uma frase comprida passa a ser só uma
 * frase comprida em vez de uma caixa maior.
 */
.pill {
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .04em;
  padding: var(--e-0) 0; border: 0; border-radius: 0;
  color: var(--gold-text); background: transparent;
}
/* A barra à esquerda foi-se: era uma risca por marca, e num cartão com duas
   ficavam duas riscas verticais a dividir coisas que não estavam divididas. O
   ícone já diz onde cada marca começa, e a cor já diz o que ela é. O que a
   barra fazia mesmo era separar duas marcas seguidas, e isso passou a ser ar. */
.pill + .pill { margin-left: var(--e-2); }
.pill.dim { color: var(--ink-50); }
/* The quiet tone: a fact about the row, not a state asking to be acted on. */
/* O que está do outro lado da subscrição, dentro do cartão que o contém: a
   linha a tracejado diz que aquilo continua, em vez de ser outra caixa. */
.fechado {
  display: flex; gap: var(--e-2); align-items: flex-start;
  margin-top: var(--e-3); padding-top: var(--e-3); border-top: 1px dashed var(--ink-12);
}
.fechado svg { width: 15px; height: 15px; }
/* Colado ao que ficou por dizer, sem risco por cima: o risco fecharia o cartão
   ali e o que vem por baixo, que é livre, passaria também por fechado. */
.fechado.junto { margin-top: var(--e-0); padding-top: 0; border-top: 0; }
.fechado.junto .link-gold { margin-top: var(--e-0); }
.fechado .link-gold { margin-top: var(--e-1); }
/* O que a subscrição dá, uma coisa por linha. Era um parágrafo com vírgulas. */
.lista-oferta { list-style: none; margin: var(--e-1) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--e-2); }
.lista-oferta li { display: flex; gap: var(--e-2); align-items: flex-start; font-size: var(--t-sm); line-height: 1.4; }
.lista-oferta li > span:first-child { flex: none; color: var(--gold-text); display: flex; margin-top: var(--e-0); }
.lista-oferta svg { width: 16px; height: 16px; }

/**
 * O que se pede no início.
 *
 * O herói diz qual é a chave; isto diz o que se faz com ela. É a única coisa
 * deste ecrã que pede alguma coisa a alguém, e por isso é a única com peso de
 * cartão e uma linha dourada a fechar.
 */
.ondeh { margin: var(--e-1) 0 0; font-size: var(--t-lg); }
/* Porque é aquela e não outra. Sem isto, o destaque parece arbitrário. */
.ondeh-porque { margin: -6px 0 0; font-size: var(--t-xs); color: var(--gold-text); letter-spacing: .02em; }
/* A linha de sempre, com moldura. Nada muda de sítio: só ganha uma caixa à
   volta e o gesto por baixo. */
/**
 * O destaque e as linhas: a mesma largura por fora e o mesmo alinhamento por
 * dentro.
 *
 * Primeiro a moldura comia 15px ao conteúdo e o cartão parecia mais estreito
 * do que as linhas. Depois saiu para fora da coluna e passou a parecer mais
 * largo do que elas. Não havia terceira via com as linhas coladas à margem: a
 * caixa fica na largura de todas as outras, e é a lista que ganha por dentro o
 * mesmo respiro que a moldura tem, para as duas coisas assentarem na mesma
 * coluna de texto.
 */
.sess-linha.destaque {
  border: 1px solid var(--gold-border); border-radius: var(--r-card); background: var(--gold-soft);
  padding: var(--e-3) var(--e-4) var(--e-4); margin: 0 0 var(--e-1);
}
/* O respiro que a moldura tem por dentro passa a ser de todas as linhas: as
   caixas ficam da mesma largura e o que está dentro delas na mesma coluna. */
.grupo-chave { padding-inline: var(--e-4); }
.sess-linha.destaque .sess-calha::after { display: none; }
.sess-linha.destaque .sess-oque { font-size: var(--t-md); }
.proxima-cta {
  display: flex; align-items: center; gap: var(--e-1); margin-top: var(--e-2); align-self: stretch;
  justify-content: center; padding: var(--e-3) var(--e-3); border-radius: var(--r-ctrl);
  background: var(--gold); color: var(--on-gold);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.proxima-cta svg { width: 15px; height: 15px; }

/**
 * O cabeçalho de um bloco de chave.
 *
 * A agenda deixou de ser uma pilha de dias e passou a ser a roda: cada bloco é
 * uma chave, com o nome dela e as datas em que se dança. O da chave de agora
 * acende, e é o único que acende, porque só há uma de cada vez.
 */
/**
 * O cabeçalho de um bloco de chave é uma divisória, não um cartão.
 *
 * Tinha caixa, fundo e barra à esquerda, ou seja, tinha a mesma matéria das
 * sessões que estão por baixo dele, e lia-se como mais um objeto da lista em
 * vez de como o nome do que vem a seguir. É a mesma forma que os dias tinham:
 * um nome, um traço por baixo, e a informação da direita a acompanhar.
 */
/**
 * O nome de um bloco é um rótulo, não um objeto.
 *
 * Já teve caixa com barra à esquerda e já teve traço por baixo, e as duas
 * versões tinham matéria a mais: liam-se como mais uma coisa da lista, em cima
 * das sessões que estavam por baixo delas. Isto é a mesma forma que o mês
 * tinha, e que esta app já usa para dizer de que é a secção seguinte: letras
 * pequenas, espaçadas, sem nada à volta. O ar por cima é que faz a separação.
 */
/* O ecrã é uma coluna com 16px de intervalo entre tudo, e o rótulo apanhava
   esse intervalo por baixo como qualquer outro bloco: ficava a anunciar uma
   lista que começava um vão à frente. Anula-se o intervalo e fica colado ao que
   nomeia, com o ar todo por cima, que é onde ele separa. */
.grupo-chave {
  display: flex; align-items: baseline; gap: var(--e-2); flex-wrap: wrap;
  margin: var(--e-5) 0 calc(var(--e-3) * -1); padding: 0 0 0 var(--e-0);
}
.grupo-nome {
  background: none; border: 0; padding: 0; text-align: left;
  font-size: var(--t-sm); font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-50); line-height: 1.3;
}
.grupo-quando { font-size: var(--t-xs); color: var(--ink-50); }
/* A de agora é a única com cor, e é só o rótulo que a leva. */
.grupo-chave.agora .grupo-nome { color: var(--gold-text); }
.grupo-chave.agora .grupo-quando { color: var(--gold-text); opacity: .75; }
.screen > .grupo-chave:first-of-type { margin-top: var(--e-2); }

/* Filtrar por cidade. Mais leve do que os separadores, porque isto não muda de
   ecrã: muda o que a mesma lista mostra. Rola na horizontal quando as cidades
   forem mais do que as que cabem, em vez de partir em duas linhas. */
/* O que só é verdade hoje: o dia em que a chave abre e o dia em que fecha.
   Centrado por baixo da linha do tempo, e em dourado porque é a única coisa do
   ecrã que amanhã já não está lá. */
.momento {
  margin: -2px 0 0; text-align: center; font-size: var(--t-xs); line-height: 1.45;
  color: var(--gold-text); padding: 0 var(--e-2);
}

/* Quebrava linha em lado nenhum e 140px ficavam fora do ecrã, sem sombra nem
   seta a dizê-lo: duas das respostas à pergunta desta página não se viam. */
.filtro { display: flex; flex-wrap: wrap; gap: var(--e-2); padding: var(--e-0) 0; }
.filtro button {
  flex: none; display: inline-flex; align-items: center;
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  padding: var(--e-2) var(--e-3); border-radius: var(--r-pill); border: 1px solid var(--ink-12); background: transparent; color: var(--ink-50);
}
/* Escolhido não se diz só por cor: leva também o peso e o preenchimento, que
   sobrevivem ao modo de alto contraste e a quem não distingue o dourado. */
.filtro button.on {
  border-color: var(--gold); background: var(--gold); color: var(--on-gold);
}
@media (forced-colors: active) {
  .filtro button[aria-checked="true"], .filtro button[aria-pressed="true"] { border: 2px solid Highlight; }
}

/* A chave de agora é um filtro de outra natureza que a cidade, por isso leva o
   sol e um corte a separá-la, em vez de se misturar com os sítios. */
.filtro button.chave { gap: var(--e-1); padding-left: var(--e-3); }
.filtro button.chave svg { width: 14px; height: 14px; }
.filtro button.chave.on svg { animation: sparkBreathe 3s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .filtro button.chave.on svg { animation: none; } }
.filtro-corte { flex: none; width: 1px; align-self: stretch; margin: var(--e-1) var(--e-0); background: var(--ink-12); }

.pill.neutro { background: transparent; color: var(--ink-50); }
/* The key chip is the mandala and the number, nothing else: the word "chave"
   was the longest thing on the card and the icon is the same one the CHAVES tab
   uses, so the app teaches what it means. The word is still there for whoever
   is listening instead of looking. */
.so-leitor {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
/* Avatar backgrounds are always light pastels, so the initials need dark ink
   whatever the theme. Using --frame worked by accident in the dark theme and
   left cream on pastel (2.3:1) in the light one. */
.avatar {
  width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: var(--t-sm); color: #14110C; flex: none;
}
.keynum { font-size: 52px; font-weight: 700; color: var(--gold); line-height: 1; }
.hero-num {
  font-size: 104px; letter-spacing: -0.02em;
  text-shadow: 0 0 34px rgba(200, 154, 85, .35);
  animation: heroBreathe 5s ease-in-out infinite;
}
@keyframes heroBreathe {
  0%, 100% { text-shadow: 0 0 30px rgba(200, 154, 85, .28); }
  50% { text-shadow: 0 0 46px rgba(200, 154, 85, .5); }
}
@media (prefers-reduced-motion: reduce) { .hero-num { animation: none; } }
.spectrum { display: flex; align-items: center; gap: var(--e-2); font-size: var(--t-2xs); flex-wrap: wrap; }
.spectrum .line { flex: 1; height: 1px; min-width: 14px; background: linear-gradient(90deg, var(--ink-30), var(--gold)); }
/* The wordmark lives inside the artwork, so it carries the title on its own. */
.logo-mark { display: block; width: min(232px, 62vw); height: auto; margin: var(--e-6) auto 0; opacity: .96; }
.guest-strip { border: 1px solid var(--gold-border); border-radius: var(--r-card); padding: var(--e-3) var(--e-3); display: flex; align-items: center; gap: var(--e-2); font-size: var(--t-xs); line-height: 1.4; }

/* The six lines of a key, drawn as six lines, the Sun walks them in ~22h each,
   so this single object shows both the line you're in and the key's progress. */
.sixlines-track { display: flex; gap: var(--e-1); }
.sixline {
  flex: 1; height: 3px; border-radius: 2px; background: var(--ink-12);
  position: relative; overflow: hidden;
}
.sixline i {
  position: absolute; inset: 0 auto 0 0; display: block; width: 0;
  background: var(--gold-border); border-radius: 2px; transition: width .6s ease;
}
.sixline.done i { background: var(--gold-border); }
.sixline.now { background: var(--gold-soft); }
.sixline.now i { background: var(--gold); box-shadow: 0 0 8px rgba(200, 154, 85, .6); }
/* One timeline: past key · the six lines being walked · the key ahead.
   The track fills left→right, so the direction is read, not explained. */
.timeline { display: flex; align-items: center; gap: var(--e-2); }
.tl-meio { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--e-1); align-items: center; }
.tl-meio .sixlines-track { width: 100%; }
/* What the bar is counting. Without it the bar is a decoration and the numbers
   at its ends look like the two ends of a range. */
.tl-legenda { font-size: var(--t-xs); color: var(--ink-50); letter-spacing: .02em; text-align: center; }
/* "PASSOU" e "A SEGUIR" e os dois números são texto, e a --ink-30 dá 2,4:1 no
   escuro e 1,8:1 no claro: era decoração a fingir de palavra. */
.tl-key {
  display: flex; flex-direction: column; align-items: center; gap: var(--e-0);
  min-width: 44px; color: var(--ink-50); transition: color .2s ease;
}
.tl-quando {
  font-size: var(--t-2xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-50);
}
.tl-num { font-size: var(--t-lg); font-weight: 600; line-height: 1; }
.tl-key:hover, .tl-key:active { color: var(--gold-border); }
.tl-key.ahead { color: var(--ink-50); }         /* what comes is slightly clearer than what passed */

/* The frequency panel cross-fades between Sombra/Dom/Siddhi */
/* ---------- the ascent ----------
   Shadow, Gift and Siddhi are one energy at three frequencies, not three
   choices, so all three stay on screen: a stair you can see the top of.

   Nothing collapses. The phrases are one line each, so an accordion animated
   about twenty pixels while the block jumped underneath, which is what made it
   feel wrong. Only colour, weight and spacing change, and none of those move
   anything else on the page: that is why it reads as calm.

   The type opens as it climbs, and that difference is information, not
   decoration, so it survives reduced motion. */
/* A luz estava no topo, onde está a sombra, e desvanecia à medida que se subia
   para o siddhi: o desenho dizia o contrário do que a coisa é. Agora acende em
   baixo, onde a subida acaba. */
.subida {
  border: 1px solid var(--ink-12); border-radius: var(--r-card); overflow: hidden;
  background: linear-gradient(0deg, rgba(200, 154, 85, .11), transparent 62%);
}
/* Quando a chave é de uma das tuas esferas. Uma linha, não um cartão: é uma
   nota sobre a chave que está por cima, não uma notícia com vida própria. */
.tua-chave {
  display: flex; align-items: center; justify-content: center; gap: var(--e-2);
  margin: 0; text-align: center;
  font-size: var(--t-xs); color: var(--gold-text); line-height: 1.4;
}
.tua-chave svg { width: 14px; height: 14px; flex: none; }
.tua-chave b { font-weight: 700; }

.degrau {
  display: grid; grid-template-columns: 14px minmax(0, 1fr); align-items: start;
  width: 100%; text-align: left; background: none; border: 0;
  padding: var(--e-4) var(--e-4) var(--e-4); color: var(--ink-50);
  transition: color .45s ease, background .45s ease;
}
.degrau + .degrau { border-top: 1px solid var(--ink-06); }
/* O mesmo fio da agenda: três estações de uma linha só, e não três caixas
   empilhadas. O nó acende onde estamos. */
.degrau-calha { align-self: stretch; display: flex; justify-content: center; position: relative; }
.degrau-calha::after {
  content: ''; position: absolute; top: 15px; bottom: -16px; width: 1px; background: var(--ink-12);
}
.degrau:last-child .degrau-calha::after { display: none; }
.degrau-no {
  width: 8px; height: 8px; border-radius: 50%; margin-top: var(--e-1); flex: none; position: relative; z-index: 1;
  border: 1.5px solid var(--ink-30); background: var(--frame);
  transition: border-color .45s ease, background .45s ease, box-shadow .45s ease;
}
.degrau.on .degrau-no { border-color: var(--gold); background: var(--gold); }
.degrau[data-freq="siddhi"].on .degrau-no { box-shadow: 0 0 12px rgba(200, 154, 85, .55); }
.degrau-corpo { min-width: 0; padding-left: var(--e-2); }
.degrau-nivel {
  display: block; font-size: var(--t-2xs); font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-50);
  transition: color .45s ease, font-size .45s ease, letter-spacing .45s ease;
}
/* O nome de uma frequência é um nome, como o nome de uma chave, e escreve-se
   na mesma letra. A subida vê-se parada: cresce e ilumina-se de degrau para
   degrau, sem ser preciso abrir nenhum. */
.degrau-nome {
  display: block; font-family: var(--serif); font-weight: 400;
  letter-spacing: -.005em; line-height: 1.25; margin-top: var(--e-0);
  transition: color .45s ease;
}
/* Os três nomes ao mesmo tamanho. Crescer de degrau para degrau parecia bem
   parado e mal em movimento: ao passar de um para o outro, o texto mudava de
   corpo e a linha reflowava, e o que devia ser uma subida lia-se como um
   solavanco. A subida diz-se pelo tom, que é uma coisa que se atravessa. */
.degrau .degrau-nome { font-size: var(--t-lg); }
.degrau[data-freq="shadow"] .degrau-nome { color: var(--ink-70); }
.degrau[data-freq="gift"] .degrau-nome { color: var(--ink); }
.degrau[data-freq="siddhi"] .degrau-nome { color: var(--gold-text); }
.degrau-frase {
  /* One open at a time, and the box it opens into has a known height, so the
     transition eases toward a real number instead of a guess. Three names plus
     one phrase is a constant, which is why the block below never moves. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  height: 0; opacity: 0; overflow: hidden;
  margin-top: 0; font-family: var(--serif); color: var(--ink-70);
  font-size: var(--t-md); line-height: 1.45; letter-spacing: -.005em;
  transition: height .42s cubic-bezier(.22, 1, .36, 1),
              margin-top .42s cubic-bezier(.22, 1, .36, 1),
              opacity .34s ease .06s;
}
/* Aberto, o degrau era um bloco dourado inteiro, e um bloco no topo puxava a
   luz toda para onde está a sombra. Agora a cor entra pelo fio e apaga-se para
   a direita: lê-se como luz a vir dali, não como uma caixa selecionada. */
.degrau.on { color: var(--ink); background: linear-gradient(90deg, var(--gold-soft), transparent 88%); }
.degrau.on .degrau-nivel { color: var(--gold-text); }
.degrau.on .degrau-frase { height: 4.1rem; margin-top: var(--e-1); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .degrau, .degrau-nome, .degrau-frase { transition: none; }
}
/**
 * Dentro da chave não há acordeão nenhum.
 *
 * Com um texto de cinco linhas a escada funcionava. Com um parágrafo inteiro
 * por frequência, os dois degraus fechados eram empurrados para fora do ecrã e
 * a subida deixava de se ver, que era o único motivo para ela existir. E um
 * acordeão obriga a escolher uma e a esconder as outras duas, que é o contrário
 * do que o método diz: as três não são alternativas, são um movimento.
 *
 * Lê-se a descer. O que se ganha é não ter de decidir nada; o que se paga é o
 * ecrã ficar comprido, e é o fio à esquerda, com o nó aceso onde vamos, que
 * responde a isso.
 */
/* overflow visível, senão o rótulo colado ao topo não cola: a caixa original
   escondia o que saísse dela, e sticky dentro de uma dessas não existe. */
.subida.inteira { border: 0; background: none; border-radius: 0; overflow: visible; }
.subida.inteira .degrau-frase {
  display: block; height: auto; opacity: 1; margin-top: var(--e-2); padding-right: var(--e-0);
  -webkit-line-clamp: unset; overflow: visible;
}
.subida.inteira .degrau { padding: var(--e-1) var(--e-0) var(--e-6); }
.subida.inteira .degrau + .degrau { border-top: 0; }
.subida.inteira .degrau.on { background: none; }
.subida.inteira .degrau-calha::after { top: 16px; bottom: -30px; }
.subida.inteira .degrau:last-child .degrau-calha::after { display: none; }
/**
 * O rótulo da frequência fica colado ao topo enquanto se lê aquela parte.
 *
 * Três parágrafos longos são três ecrãs de texto, e a meio do segundo já não
 * se sabe se aquilo é o dom ou o siddhi. O nome grande passa, o rótulo fica: é
 * a única coisa que responde à pergunta "onde é que eu estou" sem se ter de
 * voltar para trás.
 */
/**
 * O rótulo deixa de ficar colado ao topo.
 *
 * Colado, tinha de levar fundo para o texto que passa por baixo não se ler
 * através dele, e esse fundo era uma faixa opaca a cortar os raios a meio.
 * Trocar uma ajuda pequena por um artefacto no meio do ecrã não compensa: onde
 * vamos já se lê pelo nó aceso no fio e pela cor do texto que está a ser lido.
 */
.subida.inteira .degrau-nivel { padding: 0 0 var(--e-0); }
/* O nó acende no que está a ser lido, e é a única coisa que se move. */
.subida.inteira .degrau .degrau-no { border-color: var(--ink-30); background: var(--frame); }
.subida.inteira .degrau.on .degrau-no { border-color: var(--gold); background: var(--gold); }
/* O rótulo cresce com a cor. É o único que pode crescer sem estragar nada: tem
   uma linha só para ele, não reflowa texto nenhum, e é o que responde à
   pergunta "mudou?" a quem vai a descer. */
.subida.inteira .degrau.on .degrau-nivel {
  color: var(--gold-text); font-size: var(--t-xs); letter-spacing: .22em;
}
/**
 * O que se está a ler acende, o resto recua.
 *
 * Num ecrã largo vêem-se duas ou três secções ao mesmo tempo, e sem isto todas
 * pedem a mesma atenção. A diferença é de tom e nada mais: nada muda de
 * tamanho, nada se remede, e por isso a passagem faz-se sem um único solavanco.
 */
.subida.inteira .degrau-frase { color: var(--ink-50); transition: color .55s ease; }
.subida.inteira .degrau.on .degrau-frase { color: var(--ink); }
.subida.inteira .degrau-nome { transition: color .55s ease; }


/* Gate-window timer: how far the Sun has walked through the current key */
.gate-timer-track { height: 2px; background: var(--ink-12); border-radius: 2px; overflow: visible; }
.gate-timer-fill {
  position: relative; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--gold-border), var(--gold));
}
.gate-timer-spark {
  position: absolute; right: -3px; top: 50%; transform: translateY(-50%);
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
  animation: sparkBreathe 2.4s ease-in-out infinite;
}
@keyframes sparkBreathe {
  0%, 100% { box-shadow: 0 0 0 0 rgba(200, 154, 85, .5); }
  50% { box-shadow: 0 0 0 6px rgba(200, 154, 85, 0); }
}
@media (prefers-reduced-motion: reduce) { .gate-timer-spark { animation: none; } }

/* ---------- motion (light, respectful) ---------- */
@keyframes fadeUp { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
@keyframes pulseGold { 0%, 100% { box-shadow: 0 0 0 0 rgba(200, 154, 85, .35); } 50% { box-shadow: 0 0 0 7px rgba(200, 154, 85, 0); } }
/* The light turns around the burst's own origin, inside a window that does not move. */
@keyframes raysSpin {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes toastUp { from { opacity: 0; transform: translate(-50%, 10px); } to { opacity: 1; transform: translate(-50%, 0); } }

.screen > *:not(.rays) { animation: fadeUp .3s ease both; }
.screen > *:nth-child(2) { animation-delay: .02s; }
.screen > *:nth-child(3) { animation-delay: .05s; }
.screen > *:nth-child(4) { animation-delay: .08s; }
.screen > *:nth-child(5) { animation-delay: .11s; }
.screen > *:nth-child(6) { animation-delay: .14s; }


.btn, .card, .nav-item, .tabs button, .wheel button { transition: transform .12s ease, background .15s ease, border-color .15s ease, color .15s ease, opacity .15s ease; }
.btn:active, .card:active { transform: scale(.985); }
.wheel button.active { animation: pulseGold 2.6s ease-in-out infinite; }
button:disabled { cursor: default; }

@media (prefers-reduced-motion: reduce) {
  .screen > *:not(.rays), .rays::before, .wheel button.active { animation: none !important; }
  .btn, .card { transition: none; }
}

/* Sticky primary CTA with the design's bottom fade */
.sticky-cta {
  position: sticky; bottom: -28px; margin: 4px -26px -28px; padding: var(--e-4) var(--e-5) var(--e-5);
  background: linear-gradient(180deg, rgba(20, 17, 12, 0), var(--frame) 38%);
  z-index: 2;
}

.toast {
  animation: toastUp .25s ease both;
  position: fixed; left: 50%; bottom: 32px; transform: translateX(-50%);
  background: var(--gold); color: var(--on-gold); padding: var(--e-3) var(--e-5); border-radius: var(--r-ctrl);
  font-size: var(--t-sm); font-weight: 600; z-index: 9999; max-width: 82vw; text-align: center;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .5); transition: opacity .4s;
}
.toast.error { background: var(--danger); }

/* Free hours offered to whoever asks for individual work */
.slot-row { display: flex; flex-wrap: wrap; gap: var(--e-2); }
.slot {
  padding: var(--e-2) var(--e-3); border-radius: var(--r-pill); border: 1px solid var(--ink-12);
  background: var(--ink-06); font-size: var(--t-xs); font-weight: 600; color: var(--ink-70);
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.slot.on { background: var(--gold); border-color: var(--gold); color: var(--on-gold); }

/* Spheres as rows: the number leads, the meaning follows */
.sphere-row {
  display: flex; align-items: center; gap: var(--e-3); width: 100%;
  border: 1px solid var(--ink-12); border-radius: var(--r-card); background: var(--ink-06);
  padding: var(--e-3) var(--e-3); margin-bottom: var(--e-2);
}
.sphere-row.sun { border-color: var(--gold-border); background: var(--gold-soft); }
.sphere-key {
  font-size: var(--t-xl); font-weight: 700; color: var(--gold); line-height: 1;
  min-width: 46px; letter-spacing: -.01em;
}
.sphere-key i { font-size: var(--t-xs); font-style: normal; color: var(--ink-50); font-weight: 600; }
.sphere-name { display: block; font-size: var(--t-md); font-weight: 600; margin-bottom: var(--e-0); }

.sky-now {
  display: flex; align-items: center; gap: var(--e-2); font-size: var(--t-xs); line-height: 1.45;
  color: var(--ink-70); padding: var(--e-0) var(--e-0) 0;
}
.sky-now b { color: var(--gold); font-weight: 600; }
.sky-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--gold); flex: none;
  animation: sparkBreathe 2.6s ease-in-out infinite; }
.sky-dot.dim { background: var(--ink-30); animation: none; }

/* Three across when they fit, two rows when the text is large. Nothing leaves
   the screen just because someone reads at 150%. */
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); gap: var(--e-2); }
.stat {
  min-width: 0; text-align: center; border: 1px solid var(--ink-12); border-radius: var(--r-card);
  background: var(--ink-06); padding: var(--e-3) var(--e-1); display: flex; flex-direction: column; gap: var(--e-0);
}
.stat b { font-size: var(--t-xl); color: var(--gold-text); font-weight: 700; line-height: 1; }
.stat span { font-size: var(--t-xs); color: var(--ink-50); }
@media (prefers-reduced-motion: reduce) { .cst-halo, .cst-danced, .sky-dot { animation: none; } }

/* The map card: the one card that is not like the others. The chart itself is
   a watermark, what you read are the words in front of it. */
.map-card {
  position: relative; overflow: hidden; width: 100%;
  border: 1px solid var(--gold-border); border-radius: var(--r-card); padding: var(--e-4);
  background: radial-gradient(120% 90% at 50% 10%, var(--gold-soft), transparent 65%), var(--ink-06);
  box-shadow: inset 0 0 40px rgba(200, 154, 85, .07);
}
.map-card-body { position: relative; display: flex; flex-direction: column; gap: var(--e-2); }
.map-card-head { display: flex; align-items: center; justify-content: space-between; }
.map-line { font-size: var(--t-lg); line-height: 1.45; color: var(--ink); }
.map-line b { color: var(--gold-text); font-weight: 600; }
/* A marca agarra-se ao seu texto. Dentro de uma coluna flex, `inline-block`
   ainda é esticado pelo `stretch` do pai, e "AGORA" aparecia como uma faixa
   dourada de ponta a ponta do cartão. */
.map-alert-tag {
  display: inline-block; align-self: flex-start; width: auto;
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--on-gold); background: var(--gold);
  border-radius: var(--r-pill); padding: var(--e-1) var(--e-2);
}
/* O relógio à esquerda, o que se lê à direita, e o resto por baixo. */
.map-card-meio { display: flex; align-items: center; gap: var(--e-3); text-align: left; }
.map-card-dito { display: flex; flex-direction: column; gap: var(--e-2); align-items: flex-start; min-width: 0; }
.map-relogio { width: 60px; height: 60px; flex: none; }
.map-relogio-sol { animation: pulsoDoSol 2.6s ease-in-out infinite; transform-origin: center; }
@keyframes pulsoDoSol { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
@media (prefers-reduced-motion: reduce) { .map-relogio-sol { animation: none; } }
.map-depois {
  font-size: var(--t-xs); color: var(--ink-50); text-align: left;
  letter-spacing: .02em; padding-top: var(--e-1); border-top: 1px solid var(--ink-06);
}
.map-alert-tag.dim { background: transparent; color: var(--gold-text); border: 1px solid var(--gold-border); }
/* An idle map is a quiet door; an alert one glows. */
.map-card.idle { border-color: var(--gold-border); background: var(--ink-06); box-shadow: none; }
.map-card.now { box-shadow: inset 0 0 44px rgba(200, 154, 85, .13), 0 0 0 1px rgba(200, 154, 85, .25); }

/* Row card: icon, title, subtitle, chevron. One pattern for every list entry,
   so nothing wraps and every row reads the same way. */
.row-card {
  display: flex; align-items: center; gap: var(--e-3); width: 100%;
  border: 1px solid var(--ink-12); border-radius: var(--r-ctrl); background: var(--ink-06);
  padding: var(--e-3) var(--e-3) var(--e-3) var(--e-4); text-align: left;
  transition: border-color .15s ease, background .15s ease;
}
.row-card:active { border-color: var(--gold-border); }
.row-card .rc-icon { color: var(--ink-50); flex: none; display: flex; }
.row-card .rc-body { flex: 1 1 auto; min-width: 0; max-width: 100%; }
.row-card .rc-title {
  /* A span is inline, and overflow/ellipsis do nothing on inline boxes, so a
     long title used to push straight out of the card. */
  display: block; max-width: 100%;
  font-size: var(--t-md); font-weight: 600; line-height: 1.3;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Two lines is a subtitle; three is a paragraph pretending to be one, and it
   pushes the value at the end into a column of its own. */
.row-card .rc-sub {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  max-width: 100%; font-size: var(--t-sm); color: var(--ink-50); line-height: 1.35; margin-top: var(--e-0);
}
.row-card .rc-end { flex: none; display: flex; align-items: center; gap: var(--e-2); color: var(--ink-30); }
.row-card .rc-value { font-size: var(--t-md); font-weight: 600; color: var(--gold-text); }
.row-card.gold { border-color: var(--gold-border); background: var(--gold-soft); }


/* Nothing tappable smaller than a fingertip, and everyone can see where they are. */
.btn, .tabs button, .nav-item, .row-card, .sphere-row, .sess-linha, .card.linha, .slot,
button[data-nav], button[data-back], .link-gold { min-height: var(--tap); }
.link-gold, button[data-back] { display: inline-flex; align-items: center; }
.nav-item { justify-content: center; }
:focus-visible {
  outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--r-ctrl);
}
.install-hint, .bell { padding: var(--e-2); margin: -8px; }   /* bigger hit area, same look */

/* Native checkboxes are 13px hit areas, give them a fingertip. */
input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--gold); flex: none; }
label.card { min-height: var(--tap); }
.avatar { font-size: var(--t-sm); }   /* never below 12px, even at 30px wide */

/* O cartão dentro da folha: grande o suficiente para se ver o que se publica,
   e curto o suficiente para os botões ficarem no ecrã. O toque longo em cima
   dele é do sistema, e é isso que guarda a imagem. */
.cartao-preview {
  display: block; width: 100%; max-height: 46vh; object-fit: contain;
  border-radius: var(--r-card);
  /* Sem fundo por trás: o cartão tem o seu, e uma caixa maior do que ele punha
     duas barras cinzentas de cada lado da imagem. */
  -webkit-touch-callout: default;
}

/* ---------- bottom sheet ---------- */
.sheet-wrap { position: fixed; inset: 0; z-index: 60; display: flex; align-items: flex-end; justify-content: center; }
.sheet-back {
  position: absolute; inset: 0; background: rgba(0,0,0,.5);
  opacity: 0; transition: opacity .22s ease; backdrop-filter: blur(2px);
}
.sheet-wrap.on .sheet-back { opacity: 1; }
.sheet {
  position: relative; width: 100%; max-width: 520px;
  background: var(--frame); border: 1px solid var(--ink-12); border-bottom: none;
  border-radius: var(--r-folha) var(--r-folha) 0 0; padding: var(--e-3) var(--e-4) calc(var(--e-4) + env(safe-area-inset-bottom));
  transform: translateY(100%); transition: transform .24s cubic-bezier(.2,.8,.3,1);
  max-height: 86dvh; overflow-y: auto;
}
.sheet-wrap.on .sheet { transform: translateY(0); }
.sheet-grip { width: 38px; height: 4px; border-radius: 2px; background: var(--ink-30); opacity: .5; margin: var(--e-0) auto var(--e-3); }
.sheet h2 { margin: 0 0 var(--e-0); font-size: var(--t-xl); }
.sheet > .small { margin: 0 0 var(--e-3); }
.sheet-opt {
  display: flex; align-items: center; gap: var(--e-3); width: 100%;
  background: var(--ink-06); border: 1px solid var(--ink-12); border-radius: var(--r-card);
  padding: var(--e-3) var(--e-3); margin-bottom: var(--e-2); text-align: left; color: inherit;
  min-height: var(--tap); transition: border-color .15s ease, background .15s ease;
}
.sheet-opt:active { border-color: var(--gold-border); background: var(--gold-soft); }
.sheet-ico { flex: none; display: flex; align-items: center; color: var(--ink-50); }
.sheet-t { display: block; font-size: var(--t-md); font-weight: 600; }
.sheet-opt .small { display: block; margin-top: var(--e-0); }
.sheet-cancel { margin-top: var(--e-1); }
@media (min-width: 720px) {
  .sheet-wrap { align-items: center; }
  .sheet { border-radius: var(--r-folha); margin: 0 var(--e-4); }
}
@media (prefers-reduced-motion: reduce) {
  .sheet, .sheet-back { transition: none; }
}

/* Provider buttons: Apple's own spec (dark, logo left, one line),
   and a slot for the button Google insists on drawing itself. */
.btn-oauth { display: flex; align-items: center; justify-content: center; gap: var(--e-2); }
.btn-oauth svg { flex: none; }
/* O espaço do botão da Google. Agora é um botão nosso e ocupa a linha toda,
   como o dourado por cima: dois botões da mesma largura lêem-se como duas
   portas para a mesma casa. */
.gbtn-slot { display: flex; min-height: var(--tap); }
.gbtn-slot > button { flex: 1 1 auto; }

@media (prefers-reduced-motion: reduce) { .seg-thumb { transition: none; } }

/* Something is actually broken. Rare by design, so it can afford to be loud. */
.card.alarm {
  border-color: rgba(198, 106, 90, .45);
  background: var(--danger-soft);
  text-align: left;
}

/* ---------- two voices ----------
   Poppins runs the interface: buttons, labels, numbers, navigation. It is
   geometric, every letter nearly a circle, which is why it disappears in a
   toolbar and turns into a wall after sixty words.
   Spectral carries what there is to read. The serifs give the line a direction
   to travel along, and the varying stroke width gives the paragraph a rhythm
   the eye can follow. */
:root { --serif: Spectral, Georgia, 'Times New Roman', serif; }

.reading {
  font-family: var(--serif);
  font-size: var(--t-lg);          /* the readings are the main event, not a caption */
  line-height: 1.68;
  color: var(--ink-70);
  letter-spacing: .002em;
  /* Wide screens must not turn a contemplation into a single long line. */
  max-width: 34em;
  text-wrap: pretty;
}
.reading em, .reading i { font-style: italic; }

.key-name {
  font-family: var(--serif);
  font-weight: 400;
  letter-spacing: -.005em;
  line-height: 1.2;
}
/* "o caminho da" é a proposta, o nome é o título: a frase lê-se inteira e o
   nome continua a ser a palavra que fica. */
.caminho .caminho-a {
  display: block; font-family: 'Poppins', sans-serif;
  font-size: var(--t-2xs); font-weight: 600; letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-50); margin-bottom: var(--e-0);
}

/* On dark, light strokes bloom and thin out; a touch more weight holds them. */
[data-theme="dark"] .reading, :root:not([data-theme="light"]) .reading { font-weight: 400; }
[data-theme="light"] .reading { font-weight: 400; color: var(--ink-70); }

/* The clamped teaser under the wheel keeps its three-line box, in the new face. */
.key-info-text.reading { font-size: var(--t-md); line-height: 1.5; }

/* Pills carry a mark, so a state can be read before it is spelled out. */
/* Sem nowrap: uma marca comprida quebra a linha como texto, em vez de esticar
   uma caixa para fora do ecrã. */
.pill { display: inline-flex; align-items: center; gap: var(--e-1); }
.pill svg { width: 13px; height: 13px; flex: none; }
/* The one that means "right now" is the only one that moves. */
/* O que está a acontecer agora acende a barra e o texto, sem caixa por baixo. */
.pill-live { background: transparent; color: var(--gold-text); }
.pill-live svg { animation: sparkBreathe 2.8s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .pill-live svg { animation: none; } }

/* The passage: the screen and the shared image use the same seal, so what a
   person sees in the app is what their friends see on Instagram. */
.seal-card { text-align: center; align-items: center; gap: var(--e-2); }
.seal {
  display: inline-flex; align-items: center; justify-content: center;
  padding: var(--e-2) var(--e-5); border-radius: var(--r-pill);
  border: 1px solid var(--gold-border); background: var(--gold-soft);
  color: var(--gold-text); font-weight: 600; font-size: var(--t-md);
  letter-spacing: .16em;
}

/* Um convite não é uma ação de moldura. Partilhar e abrir a chave são as duas
   coisas que se oferecem depois de se ler, e nenhuma delas quer o peso de um
   botão a sério ao lado do outro. */
.link-gold.solto { align-self: center; gap: var(--e-2); margin: var(--e-0) 0; }

/* A link inside a sentence has to look like part of the sentence. */
.link-inline {
  background: none; border: 0; padding: 0; font: inherit;
  color: var(--gold-text); text-decoration: underline; text-underline-offset: 3px;
}

/* Prices: a real label wrapping the input, so tapping the name focuses the box
   and a screen reader says which price it is about. */
.price-row {
  justify-content: space-between; gap: var(--e-2); margin-bottom: var(--e-2);
  min-height: var(--tap); cursor: pointer;
}
/* Unread notices, said on the way in. Gold because it is the one thing on the
   home screen that is waiting for the person, rather than offered to them. */
.aviso-tira {
  flex-direction: row; align-items: center; gap: var(--e-3); text-align: left;
  border-color: var(--gold-border); background: var(--gold-soft);
}
.aviso-sino { flex: none; color: var(--gold-text); display: flex; }
.aviso-sino svg { animation: sparkBreathe 2.8s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .aviso-sino svg { animation: none; } }
/* Duas tiras douradas empilhadas, as duas a respirar, era um semáforo. Só a
   dos avisos é que pisca: o convite para escrever pode esperar. */
.aviso-sino.calmo svg { animation: none; }
.aviso-corpo { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--e-0); }
.aviso-titulo { font-size: var(--t-sm); font-weight: 600; color: var(--ink); line-height: 1.3; }
.aviso-nota { font-size: var(--t-xs); color: var(--ink-50); }
.aviso-tira .link-gold { flex: none; }

/* Gravar a resposta acontece dentro do cartão da pergunta, sem sair do ecrã. */
.gravador { display: flex; flex-direction: column; gap: var(--e-2); }
.gravador audio { border-radius: var(--r-pill); }
details summary::-webkit-details-marker { display: none; }
details summary { list-style: none; padding: var(--e-1) 0; font-size: var(--t-xs); font-weight: 700; letter-spacing: .08em; }

/* Each price saves itself, so each price says so where it happened. */
/* Dentro de um campo em coluna a marca fica por baixo, à direita, em vez de
   roubar 20px de largura ao próprio campo. */
.field > .guardado { width: auto; justify-content: flex-end; min-height: 16px; margin-top: var(--e-0); }
.guardado { flex: none; width: 20px; display: flex; align-items: center; color: var(--gold-text); }
.guardado svg { width: 16px; height: 16px; animation: fadeUp .25s ease; }
.price-row input {
  width: 92px; text-align: right; background: var(--ink-06);
  border: 1px solid var(--ink-12); border-radius: var(--r-ctrl); color: var(--ink);
  padding: var(--e-2); font-size: var(--t-md); min-height: var(--tap);
}

/* Carregar no meio da roda selecionava as palavras «29 Compromisso ABRIR» em
   vez de abrir a chave: num rato, um clique que arrasta um pixel é um clique
   que seleciona texto. A roda é um controlo, não um parágrafo. */
#mandala, #mandala text { user-select: none; -webkit-user-select: none; }

/* O botão de entrar com a Google, desenhado por nós.
   Branco com o contorno cinzento é o que a Google pede na marca dela, e é o que
   se lê bem em cima do papel e em cima da noite. */
.btn-google {
  width: 100%; background: #fff; color: #1f1f1f;
  border: 1px solid #dadce0; border-radius: var(--r-pill);
  font-weight: 600; letter-spacing: 0; text-transform: none;
  display: flex; align-items: center; justify-content: center; gap: var(--e-2);
  min-height: var(--tap); padding: var(--e-2) var(--e-4);
  font-size: var(--t-md);
}
.btn-google:active { background: #f5f5f5; }
.btn-google svg { flex: none; }

/* O nascimento de alguém, dentro do cartão dessa pessoa. Dois campos lado a
   lado em cima, o sítio em baixo à largura toda, e todos com min-width zero: um
   seletor com o mundo inteiro lá dentro empurra a grelha para fora do ecrã se o
   deixarem medir-se pelo conteúdo. */
.nasc-bloco { display: grid; gap: var(--e-2); border-top: 1px dashed var(--ink-12); padding-top: var(--e-3); }
.nasc-par { display: grid; grid-template-columns: 1.35fr 1fr; gap: var(--e-2); }
.nasc-bloco .field { min-width: 0; }
.nasc-bloco input, .nasc-bloco select { width: 100%; min-width: 0; padding: var(--e-2); }
.nasc-bloco .small { letter-spacing: 0; text-transform: none; }

/* A cancelled thing should look cancelled, not like everything else. */
.pill.danger { color: var(--danger); }
.sess-manage { text-align: left; gap: var(--e-2); }

.photo-preview { margin-top: var(--e-2); display: flex; flex-direction: column; gap: var(--e-1); }
.photo-preview img { width: 100%; border-radius: var(--r-ctrl); display: block; }

/* ---------- the 64, as a board ----------
   A list says what you have. The board says what you have against what there
   is, and that is what makes the next one feel worth going to. */
.bingo {
  /* Not a fixed 8 columns: the cells are tap targets, so they cannot go below
     44px, and eight of those plus gaps are wider than the screen. Let the grid
     fit as many as fit, which is 6 on a phone and 12 on a laptop. */
  display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  gap: var(--e-1); margin: var(--e-1) 0 var(--e-2);
}
.bingo-cell {
  aspect-ratio: 1; border-radius: var(--r-ctrl); min-height: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--t-xs); font-weight: 600;
  background: var(--ink-06); border: 1px solid var(--ink-12); color: var(--ink-30);
  transition: transform .18s ease, border-color .18s ease;
}
.bingo-cell.danced {
  background: var(--gold-soft); border-color: var(--gold-border); color: var(--gold-text);
  font-weight: 700;
}
/* Where the Sun is right now, danced or not: the one you could still catch. */
.bingo-cell.now {
  border-color: var(--gold); color: var(--gold-text);
  box-shadow: 0 0 12px rgba(200, 154, 85, .3);
}
.bingo-cell:active { transform: scale(.92); }
/* A quiet icon button, for actions that live beside a title. */
.icon-btn {
  flex: none; display: flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap); border-radius: 50%;
  background: var(--ink-06); border: 1px solid var(--ink-12); color: var(--ink-70);
}
.icon-btn:active { border-color: var(--gold-border); color: var(--gold-text); }

/* The key index, inside the search sheet. */
.busca-resultados { max-height: 58vh; overflow-y: auto; margin: 4px -4px 10px; padding: 0 var(--e-1); }
.busca-linha {
  display: flex; align-items: center; gap: var(--e-3); width: 100%; text-align: left;
  background: none; border: 0; border-bottom: 1px solid var(--ink-06);
  padding: var(--e-2) var(--e-1); min-height: var(--tap); color: inherit;
}
.busca-linha:last-child { border-bottom: 0; }
.busca-linha:active { background: var(--gold-soft); }
.busca-num {
  flex: none; width: 38px; text-align: center;
  font-weight: 700; font-size: var(--t-lg); color: var(--gold-text);
}
.busca-num.now { text-shadow: 0 0 14px rgba(200, 154, 85, .5); }
.busca-linha .small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.busca-linha svg { flex: none; color: var(--gold-text); }

/* ---------- desktop ----------
   The phone frame is the right shape for a phone and a costume on a laptop:
   at 1512px it left three quarters of the screen empty and made a working
   product look like a demo. Above 900px the shell becomes a page.

   Reading screens still hold a comfortable measure, because a line of text
   1400px wide is unreadable no matter how much room there is. The one place
   that genuinely wants the whole width is the admin, which is a workbench. */
@media (min-width: 900px) and (display-mode: browser) {
  .stage { align-items: stretch; padding: 0; }
  .frame {
    width: 100%; height: 100dvh; max-width: none;
    border-radius: 0; box-shadow: none;
  }
  .topbar { padding: var(--e-4) var(--e-6) 0; }
  .bell { right: 21px; top: 14px; }
  .install-hint { left: 21px; top: 14px; }

  /* Content keeps a measure; the rays follow it instead of the window. */
  .screen { padding: var(--e-5) var(--e-6) calc(var(--e-6) + var(--e-2)); align-items: center; }
  .screen > * { width: 100%; max-width: 620px; }

  /* The tab bar leaves the bottom and becomes a real top navigation. */
  .nav {
    justify-content: center; gap: var(--e-2); padding: var(--e-2) var(--e-4);
    border-top: 0; border-bottom: 1px solid var(--ink-12); order: -1;
  }
  .nav-item {
    flex: 0 0 auto; flex-direction: row; gap: var(--e-2); padding: var(--e-2) var(--e-3);
    border-radius: var(--r-pill); font-size: var(--t-xs);
  }
  .nav-item.active { background: var(--gold-soft); }

  /* More room on a desktop, same proportions: a window twice as wide as tall.
     Só o modo base cresce; a roda e a chave têm medidas suas. */
  .rays:not(.roda):not(.center):not(.chave) {
    top: 168px; width: 700px; height: 380px;
    -webkit-mask-image: radial-gradient(circle 380px at 50% 0, transparent 0 58px, #000 88px 240px, transparent 376px);
    mask-image: radial-gradient(circle 380px at 50% 0, transparent 0 58px, #000 88px 240px, transparent 376px);
  }
  .rays:not(.roda):not(.center):not(.chave)::before { width: 800px; height: 800px; }
}

/* The admin is a workbench, not a reading screen: here the measure gets out of
   the way, and the sections sit side by side instead of five screens deep. */
@media (min-width: 900px) and (display-mode: browser) {
  .screen.wide > * { max-width: 1120px; }
  .screen.wide .painel-duplo {
    display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-3) var(--e-6); align-items: start;
  }
  .screen.wide .painel-duplo > h2 { grid-column: 1 / -1; margin-top: var(--e-2); }
}

/* ---------- the hero ----------
   The antlers are the mark's own, lifted straight out of the logo, so the
   number is held by the brand instead of sitting next to it. They read as
   wings without being wings, which is what the mark already does.

   They breathe against the number rather than with it: half a cycle behind, so
   the pair looks alive instead of mechanical. */
/* O `button { text-align: left }` global ganhava aqui dentro: o nome parecia
   centrado porque enche a linha, mas "o caminho da" por cima ficava encostado
   à esquerda da caixa. */
/**
 * As hastes precisam de céu por cima.
 *
 * Sobem para fora da caixa do número, portanto o espaço que a caixa reserva não
 * é o espaço que elas ocupam: ficavam a oito pixels do "chave ativa agora", que
 * é meia respiração. O bloco inteiro desce, e a margem de cima do ecrã fica com
 * o mesmo ar da de baixo.
 */
.linha-chave { margin-top: var(--e-1); }
.heroi-bloco {
  text-align: center; display: flex; flex-direction: column; align-items: center;
  gap: var(--e-0); padding: var(--e-0) 0; margin-top: var(--e-5);
}
.heroi { display: flex; flex-direction: column; align-items: center; gap: var(--e-0); text-align: center; }
.heroi-num { position: relative; display: flex; align-items: center; justify-content: center; }
/* In the logo the antlers sit above the burst, small, and it is the burst that
   fills the space below them. They were flanking the number at half height and
   as wide as it, which read as two horns on a number instead of the mark. */
.haste {
  position: absolute; top: 0; width: clamp(34px, 11vw, 51px); height: auto;
  --sobe: -20%;
  pointer-events: none;
  filter: drop-shadow(0 0 20px rgba(200, 154, 85, .35));
  animation: hasteRespira 5s ease-in-out infinite;
  animation-delay: -2.5s;   /* against the number, not with it */
}
/* Outside the number, not on top of it: they hold, they do not cover. */
.haste.esq { right: 100%; margin-right: var(--e-1); transform-origin: right bottom; }
.haste.dir { left: 100%; margin-left: var(--e-1); transform-origin: left bottom; }
[data-theme="light"] .haste.esq { content: url("/assets/haste-esquerda-ink.png"); }
[data-theme="light"] .haste.dir { content: url("/assets/haste-direita-ink.png"); }
@keyframes hasteRespira {
  0%, 100% { transform: translateY(var(--sobe)) scale(1) rotate(0deg); opacity: .62; }
  50%      { transform: translateY(calc(var(--sobe) - 2%)) scale(1.045) rotate(var(--tilt, 0deg)); opacity: .85; }
}
.haste.esq { --tilt: -1.6deg; }
.haste.dir { --tilt: 1.6deg; }
@media (prefers-reduced-motion: reduce) {
  .haste { animation: none; transform: translateY(var(--sobe)); }
}

/**
 * A bancada do herói: seis maneiras de pôr as hastes no número.
 *
 * Cada variante mexe só no que a distingue, e herda o resto do herói a sério,
 * para a comparação ser honesta. Vive aqui em baixo, longe das regras da app,
 * porque é um ecrã de ensaio e não uma parte dela.
 */
.heroi-bloco.proto { margin-top: var(--e-3); padding-top: 56px; }

/* 2. Por cima, ao meio, como no logótipo: as hastes deixam de flanquear. */
.v-cima .haste { top: auto; bottom: 100%; margin: 0 0 -6px; --sobe: 0%; }
.v-cima .haste.esq { right: 50%; margin-right: -2px; }
.v-cima .haste.dir { left: 50%; margin-left: -2px; }

/* 3. As mesmas, mais pequenas e mais juntas: uma coroa em vez de um par. */
.v-cima-min .haste { top: auto; bottom: 100%; width: clamp(24px, 7.5vw, 36px); margin: 0 0 -4px; --sobe: 0%; }
.v-cima-min .haste.esq { right: 50%; margin-right: -6px; }
.v-cima-min .haste.dir { left: 50%; margin-left: -6px; }

/* 4. Por cima e afastadas: abrem o espaço onde o número entra. */
.v-cima-abre .haste { top: auto; bottom: 100%; margin: 0 0 -2px; --sobe: 0%; }
.v-cima-abre .haste.esq { right: 50%; margin-right: 14px; }
.v-cima-abre .haste.dir { left: 50%; margin-left: 14px; }

/* 5. O tamanho da 3 com o afastamento da 4: pequenas, e com céu entre elas.
   O afastamento é o mesmo em pixéis, e não em proporção: o que se quer é a
   mesma abertura, não a mesma relação com o tamanho da haste. */
.v-min-abre .haste { top: auto; bottom: 100%; width: clamp(24px, 7.5vw, 36px); margin: 0 0 -4px; --sobe: 0%; }
.v-min-abre .haste.esq { right: 50%; margin-right: 14px; }
.v-min-abre .haste.dir { left: 50%; margin-left: 14px; }

/* 5. Coladas ao topo do número, sem folga: lê-se como uma só forma. */
.v-colada .haste { top: auto; bottom: 100%; width: clamp(28px, 9vw, 42px); margin: 0 0 -14px; --sobe: 0%; }
.v-colada .haste.esq { right: 50%; margin-right: -10px; }
.v-colada .haste.dir { left: 50%; margin-left: -10px; }

/* 6. Sem hastes, para se ver quanto é que elas estão mesmo a dar. */
.v-nua .haste { display: none; }

/* A key still waiting to be written, in the editor's picker. */
.por-escrever {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--gold); box-shadow: 0 0 8px rgba(200, 154, 85, .5);
}

/* ---------- the agenda, as a calendar ----------
   Days lead and dates are spelled out. The old screen put a bare key number
   under the word AGOSTO, which reads as the fourth of August however it was
   meant, so a key is now never a loose number here. */
.eyebrow.mes { margin-top: var(--e-3); }
.dia-cabeca {
  display: flex; align-items: baseline; gap: var(--e-1) var(--e-2); flex-wrap: wrap;
  padding: var(--e-0) 0 var(--e-0) var(--e-0); border-bottom: 1px solid var(--ink-12); margin-bottom: var(--e-0);
}
.dia-nome {
  font-size: var(--t-md); font-weight: 600; color: var(--ink);
}
/* Only the first letter: `capitalize` would give "16 De Agosto". */
.dia-nome::first-letter { text-transform: uppercase; }
/* It moves to its own line rather than breaking in the middle of itself. */
.dia-rel { font-size: var(--t-xs); color: var(--gold-text); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }

/* A day is a thread and the sessions hang off it.
   Every session used to be the same grey box with the same border: a whole day
   in the Gerês and a Tuesday evening looked identical, and eight of them in a
   row were eight identical rectangles. There is no box now. The hour says where
   on the thread, and the dot is the only thing that lights, when the Sun is in
   that key. */
.sess-fio { display: flex; flex-direction: column; }
.sess-linha {
  display: grid; grid-template-columns: minmax(46px, auto) 14px minmax(0, 1fr) 18px; align-items: start;
  padding: var(--e-0) var(--e-4) var(--e-5); text-align: left; background: none; border: 0; border-radius: var(--r-ctrl);
}
/* Sem caixa, a linha deixou de se parecer com um comando. A seta à direita diz
   que isto abre, e ao mesmo tempo dá um fim à linha em vez de a deixar a
   esvair-se em branco a meio do ecrã. */
.sess-seta { align-self: start; margin-top: var(--e-0); color: var(--ink-30); display: flex; transition: color .15s ease, transform .15s ease; }
.sess-linha:hover .sess-seta, .sess-linha:active .sess-seta { color: var(--gold-text); transform: translateX(2px); }
.sess-linha:hover, .sess-linha:active { background: var(--ink-06); box-shadow: 0 0 0 6px var(--ink-06); }
/* The hour leads, because that is the question a calendar answers. Where the
   list does not group by day, the day rides above it: on the home "11:00" alone
   never said which day, which is the first thing anyone wants to know. */
.sess-quando { display: flex; flex-direction: column; padding-top: var(--e-0); }
.sess-dia {
  font-size: var(--t-2xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-50); line-height: 1.4;
}
/* A hora era dourada como tudo o resto. Nesta lista o dourado passa a querer
   dizer uma coisa só: isto diz-te respeito a ti. A hora é informação, e lê-se
   melhor em tinta cheia do que em cor. */
.sess-hora {
  font-size: var(--t-md); font-weight: 700; color: var(--ink); letter-spacing: .01em;
}
/* The thread is drawn by the column it belongs to, which stretches to the row's
   own height. Hanging it off the row with a hard left offset meant the hour
   column could never grow: at 200% text the hour outgrew its 46px and the line
   ended up in the middle of it. */
.sess-calha { align-self: stretch; display: flex; justify-content: center; position: relative; }
.sess-calha::after {
  content: ''; position: absolute; top: 16px; bottom: -8px; width: 1px; background: var(--ink-12);
}
/* Com o dia por cima, o nó desce para ficar em frente à hora. */
.sess-linha:has(.sess-dia) .sess-no { margin-top: var(--e-5); }
.sess-linha:has(.sess-dia) .sess-calha::after { top: 32px; }
.sess-fio > .sess-linha:last-child .sess-calha::after { display: none; }
.sess-no {
  width: 9px; height: 9px; border-radius: 50%; margin-top: var(--e-1); flex: none;
  border: 1.5px solid var(--ink-30); background: var(--frame); position: relative; z-index: 1;
}
/* The one the Sun is in, today. Nothing else on the row moves or glows. */
.sess-no.agora { border-color: var(--gold); background: var(--gold); box-shadow: 0 0 10px rgba(200, 154, 85, .5); }
/**
 * As sessões da chave de agora, a outra cor.
 *
 * Numa agenda com três semanas à frente, as que se dançam nesta janela são as
 * únicas que dizem respeito ao que a app está a mostrar no início. Estavam
 * marcadas só no número, que obriga a procurar. A linha inteira ganha um
 * banho de dourado que se apaga para a direita, o nome vem em tinta cheia, e
 * as outras ficam calmas por comparação, sem lhes tirar nada.
 */
/* O banho de dourado ocupa a linha e nada mais: tinha oito pixels de sangria
   para cada lado, e era isso que fazia estas linhas parecerem maiores do que o
   cartão em destaque e do que as linhas ao lado. A largura é a mesma de todas;
   o que a distingue é a cor. */
.sess-linha.ativa {
  background: linear-gradient(90deg, var(--gold-soft), transparent 76%);
  border-radius: var(--r-card);
}
.sess-linha.ativa .sess-oque { color: var(--ink); }
.sess-linha.ativa .sess-hora { color: var(--gold-text); }
.sess-linha.ativa:hover, .sess-linha.ativa:active {
  background: linear-gradient(90deg, var(--gold-soft), var(--ink-06) 76%);
}

/* Onde já tenho lugar: o nó fecha-se a dourado, sem brilhar. O :not() não é
   zelo, é o defeito que isto teve: sendo uma regra mais específica, apagava o
   sol das sessões que são a minha e a de agora ao mesmo tempo. A marca "tens
   lugar" é que diz o resto, e o título fica em tinta como todos os outros. */
.sess-linha.minha .sess-no:not(.agora) { border-color: var(--gold); background: var(--gold-soft); }
.sess-corpo { min-width: 0; display: flex; flex-direction: column; gap: var(--e-0); padding-left: var(--e-1); }
/* O título é a maior coisa da linha: é o que se lê a seguir a saber onde é. */
.sess-oque { font-size: var(--t-md); font-weight: 600; color: var(--ink); line-height: 1.3; }
.sess-lugares { color: var(--ink-50); }
/* Which key, riding the title line in gold. Not a chip: a chip would compete
   with the seats and the state, and this is not a state. */
/* O número da chave à frente do nome, como no herói e no marcador da roda: é a
   chave que decide o que se dança, e era uma legenda ao lado do título. */
/* A chave é taxonomia, não é um estado teu: fica em tinta, e o dourado fica
   para o que é da pessoa que está a ler. */
.sess-chave {
  display: inline-flex; align-items: center; padding: var(--e-0) var(--e-2);
  border: 1px solid var(--ink-12); border-radius: var(--r-pill);
  font-size: var(--t-2xs); font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-50); white-space: nowrap; vertical-align: 2px;
}
/* Uma sessão individual não tem número: tem duas palavras, e a caixa do número
   não lhe serve. */
.sess-chave.so-tua { border-color: var(--ink-12); color: var(--ink-50); }
/* Who and where are two lines, not one with a dot between them: when the place
   wrapped, the separator was left dangling at the end of the name's line. */
/* O nome não se corta para caber o estado da sala ao lado: se não couberem os
   dois, o estado desce de linha. Um nome truncado é uma pessoa mal tratada. */
.sess-quem { display: flex; align-items: center; gap: var(--e-1); flex-wrap: wrap; min-width: 0; font-size: var(--t-xs); color: var(--ink-70); }
.sess-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sess-onde { font-size: var(--t-xs); color: var(--ink-50); line-height: 1.3; overflow-wrap: anywhere; }
/* A cidade é o eixo por onde esta lista se procura: mesma coordenada em todas
   as linhas, e legível, em vez de ser o último bocado de uma frase livre. */
.sess-cidade {
  font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  /* Maiúsculas com espaçamento pedem menos corpo do que o texto ao lado, mas
     em em davam 11.776px, que não é degrau nenhum: é o degrau abaixo. */
  color: var(--ink); font-size: var(--t-2xs);
}
/* Onde e quantos lugares lêem-se juntos, e um puxado para a direita fecha a
   linha: a informação estava toda encostada à esquerda, com metade do ecrã em
   branco por baixo do nome. */
.sess-fim { display: flex; align-items: center; gap: var(--e-2) var(--e-3); flex-wrap: wrap; margin-top: var(--e-1); }
.sess-fim .sess-onde { flex: 0 1 auto; }
/* Encostadas à esquerda desde que a marca passou a ter uma barra desse lado:
   empurrada para a direita, a barra ficava a meio da linha sem nada para
   marcar. Agora alinha com o texto de que está a falar. */
.sess-marcas { display: flex; flex-wrap: wrap; gap: var(--e-1) var(--e-3); }
/* Past a certain text size a single chip is wider than the row it sits in. It
   wraps inside its own border rather than hanging over the edge. */
.sess-marcas .pill { max-width: 100%; white-space: normal; }

/* The other card in the app: one person, or one thing, listed. A mark or an
   avatar on the left, the name and its detail in the middle, the action on the
   right. Eleven screens were spelling this out with inline styles, each with
   its own font size, which is why no two lists looked quite alike. */
.card.linha { flex-direction: row; align-items: center; gap: var(--e-3); text-align: left; }
.card.linha + .card.linha { margin-top: var(--e-2); }
.linha-corpo { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: var(--e-0); }
.linha-nome { font-size: var(--t-sm); font-weight: 600; color: var(--ink); line-height: 1.3; overflow-wrap: anywhere; }
.linha-nota { font-size: var(--t-xs); color: var(--ink-50); line-height: 1.35; overflow-wrap: anywhere; }
/* Whatever sits on the right keeps its size, and never squeezes the name. */
.card.linha > .link-gold, .card.linha > .pill, .card.linha > .avatar,
.card.linha > .small, .card.linha > input, .card.linha > svg { flex: none; }
label.card.linha { cursor: pointer; }
.card.linha > svg { color: var(--ink-30); }

/* Said once, at the top, instead of on every card. */
.sol-agora {
  flex-direction: row; align-items: center; gap: var(--e-3); text-align: left;
  border-color: var(--gold-border); background: var(--gold-soft);
}
.sol-agora .sol-icone { flex: none; color: var(--gold-text); display: flex; }
.sol-agora .sol-icone svg { width: 22px; height: 22px; animation: sparkBreathe 3s ease-in-out infinite; }
.sol-agora .grow { min-width: 0; display: flex; flex-direction: column; gap: var(--e-0); }
.sol-linha { font-size: var(--t-sm); }
.sol-linha b { color: var(--gold-text); }
@media (prefers-reduced-motion: reduce) { .sol-agora .sol-icone svg { animation: none; } }

/**
 * O interruptor da presença.
 *
 * Dois lados, um aceso de cada vez, e nenhum aceso enquanto ninguém disse nada.
 * O apagado fica visível mas quieto: é a pergunta ainda por responder, não um
 * erro. O verde e o vermelho só aparecem depois de alguém escolher, para o
 * ecrã não parecer cheio de faltas antes de a sala abrir.
 */
.presenca { display: inline-flex; flex: none; border: 1px solid var(--ink-12); border-radius: var(--r-pill); overflow: hidden; }
.presenca button {
  display: grid; place-items: center; width: 38px; height: 32px;
  color: var(--ink-50); background: transparent; transition: background .12s, color .12s;
}
.presenca button + button { border-left: 1px solid var(--ink-12); }
.presenca svg { width: 17px; height: 17px; stroke-width: 2; }
.presenca[data-estado="veio"] [data-veio="1"] { background: color-mix(in oklab, var(--green) 18%, transparent); color: var(--green); }
.presenca[data-estado="faltou"] [data-veio="0"] { background: color-mix(in oklab, var(--danger) 16%, transparent); color: var(--danger); }

/**
 * O mês, com o Sol no sítio onde ele está.
 *
 * A coluna de datas era uma lista de dias iguais, e um mês já a meio parecia
 * todo por acontecer. As janelas que passaram recuam sem desaparecer (são o
 * caminho já feito), a de agora acende com o sol por cima do dia.
 */
/**
 * O mês tem três tempos, e cada um tem a sua cor.
 *
 * O que passou não desaparece: é o caminho já feito, e por isso recua em vez de
 * se apagar. A data dessas janelas fica em tinta fraca, para se ver de relance
 * onde é que o mês já vai sem ter de ler nenhuma delas.
 */
.mes-linha.passou { opacity: .8; }
/* A data recua na cor, não na transparência: transparente de mais, uma janela
   que já passou deixava de se poder ler, e ler o passado é metade do assunto
   deste bloco. */
.mes-linha.passou .sess-dia, .mes-linha.passou .sess-hora { color: var(--ink-50); }
.mes-linha.agora .sess-dia, .mes-linha.agora .sess-hora { color: var(--gold-text); }
.mes-linha .sess-quando { position: relative; }
/* O sol por baixo do dia, e não por cima: em cima empurrava a linha e ficava
   colado ao mês da linha anterior. */
.mes-sol { display: block; margin-top: var(--e-0); color: var(--gold); line-height: 0; }
.mes-sol svg { width: 15px; height: 15px; animation: solRespira 4s ease-in-out infinite; }
@keyframes solRespira {
  0%, 100% { opacity: .75; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.12); }
}
@media (prefers-reduced-motion: reduce) { .mes-sol svg { animation: none; } }

/**
 * Os dois planos da subscrição, lado a lado.
 *
 * Sem débito automático, o que distingue o anual não é o desconto: é ser um
 * pagamento em vez de doze. Por isso está ao lado e não escondido atrás de um
 * seletor.
 */
.planos { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-2); margin: var(--e-1) 0 var(--e-0); }
.planos .plano {
  display: flex; flex-direction: column; gap: var(--e-0); padding: var(--e-3) var(--e-2);
  border: 1px solid var(--gold-border); border-radius: var(--r-card); background: transparent; text-align: center;
}
.planos .plano.recomendado { background: var(--gold-soft); }
.plano-preco { font-size: var(--t-lg); font-weight: 700; color: var(--gold-text); }
.plano-nota { font-size: var(--t-xs); color: var(--ink-50); line-height: 1.3; }
.kv-lista { display: flex; flex-direction: column; gap: var(--e-1); margin: var(--e-0) 0; }

/**
 * O anel do ano.
 *
 * As 64 na ordem do Sol. As dançadas acendem com a cor da própria chave, e a
 * de hoje pulsa devagar, porque é a única que está a acontecer agora.
 */
.anel-ano { display: block; width: min(300px, 78vw); height: auto; margin: var(--e-2) auto 0; }
.anel-numero { fill: var(--gold-text); font-size: 34px; font-weight: 700; font-family: var(--fonte-titulo, inherit); }
.anel-legenda { fill: var(--ink-50); font-size: var(--t-2xs); letter-spacing: .1em; text-transform: uppercase; }
.anel-sol { fill: var(--gold); animation: solRespira 4s ease-in-out infinite; transform-origin: center; }
@media (prefers-reduced-motion: reduce) { .anel-sol { animation: none; } }

/* A porta no fim do texto da chave: o que fazer com o que se acabou de ler. */
.porta { display: flex; flex-direction: column; gap: var(--e-3); }
.porta .row { align-items: center; }

/* "é hoje às 10:00": a véspera de uma sessão lida sem fazer contas. */
.agora-e {
  display: inline-flex; align-items: center; gap: var(--e-2); margin: -4px 0 10px;
  color: var(--gold-text); font-size: var(--t-sm); font-weight: 600;
}
.agora-e svg { width: 15px; height: 15px; }

/* Passos numerados: o que acontece, pela ordem por que acontece. */
.passos { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: var(--e-2); }
.passos li { font-size: var(--t-sm); line-height: 1.55; color: var(--ink-70, var(--ink)); }
.passos b { color: var(--gold-text); }

/**
 * As linhas de uma lista entram uma atrás da outra.
 *
 * O ecrã inteiro já entrava assim; as listas apareciam de uma vez, todas ao
 * mesmo tempo, o que dá um estalo em vez de um movimento. São 30ms entre
 * linhas: chega para o olho seguir a lista de cima a baixo e não chega para
 * alguém esperar por ela.
 */
.sess-fio > * { animation: fadeUp .26s ease both; }
.sess-fio > *:nth-child(2) { animation-delay: .03s; }
.sess-fio > *:nth-child(3) { animation-delay: .06s; }
.sess-fio > *:nth-child(4) { animation-delay: .09s; }
.sess-fio > *:nth-child(5) { animation-delay: .12s; }
.sess-fio > *:nth-child(n+6) { animation-delay: .15s; }
@media (prefers-reduced-motion: reduce) { .sess-fio > * { animation: none; } }

/* ---------- bancada de dev: protótipos, não é app ---------- */
.ico-grelha { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: var(--e-3); }
.ico-cel {
  display: flex; flex-direction: column; align-items: center; gap: var(--e-1); padding: var(--e-3) var(--e-1);
  border: 1px solid var(--ink-06); border-radius: var(--r-card); color: var(--ink);
}
.ico-cel .ico-p, .ico-cel .ico-m { color: var(--ink-50); }
.mapa-svg { display: block; width: min(340px, 88vw); height: auto; margin: 0 auto; }

.subida-mapa { display: flex; flex-direction: column; gap: var(--e-4); }
.subida-bloco { display: flex; flex-direction: column; gap: var(--e-2); }
.subida-esferas { display: flex; flex-wrap: wrap; gap: var(--e-2); }
.esfera-degrau { display: flex; flex-direction: column; align-items: center; gap: var(--e-1); width: 66px; }
.esfera-bola {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  background: oklch(72% .12 var(--h)); color: #14110C; font-weight: 700; font-size: var(--t-md);
}
.esfera-linha { font-size: var(--t-2xs); font-weight: 600; opacity: .7; }
.esfera-nome { font-size: var(--t-2xs); color: var(--ink-50); text-align: center; line-height: 1.25; }

.marca-demo { display: flex; flex-wrap: wrap; gap: var(--e-2); align-items: center; margin-top: var(--e-1); }
.m-linha, .m-barra, .m-fundo { display: inline-flex; align-items: center; gap: var(--e-1); font-size: var(--t-xs); font-weight: 600; }
.m-linha { color: var(--gold-text); }
.m-linha svg { width: 14px; height: 14px; }
.m-barra { color: var(--ink); padding-left: var(--e-2); border-left: 2px solid var(--gold); }
.m-barra svg { width: 14px; height: 14px; color: var(--gold-text); }
.m-fundo { color: var(--ink); background: var(--ink-06); padding: var(--e-1) var(--e-2); border-radius: var(--r-ctrl); }
.m-fundo svg { width: 14px; height: 14px; color: var(--gold-text); }
.m-titulo { font-size: var(--t-md); line-height: 1.5; }
.m-sep { color: var(--ink-30); margin: 0 var(--e-1); }
.m-suave { color: var(--ink-50); }
.m-vivo { color: var(--gold-text); white-space: nowrap; }
.m-vivo svg { width: 14px; height: 14px; vertical-align: -2px; }
.m-num { display: flex; align-items: baseline; gap: var(--e-2); }
.m-num b { font-size: 26px; color: var(--gold-text); line-height: 1; }
.m-num span { font-size: var(--t-xs); color: var(--ink-50); }

/**
 * Um chip é para tocar; uma marca é para ler.
 *
 * Ficaram com a mesma classe durante algum tempo, e quando as marcas deixaram
 * de ter cápsula os meses do arquivo, que se carregam, ficaram sem forma de
 * botão. A cápsula pertence a quem responde ao dedo.
 */
.chip {
  display: inline-flex; align-items: center; gap: var(--e-1); white-space: nowrap;
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .06em;
  padding: var(--e-1) var(--e-3); border-radius: var(--r-pill); border: 1px solid var(--gold-border);
  color: var(--gold-text); background: transparent;
}

/**
 * A ação que vive no cabeçalho de um ecrã.
 *
 * Um alvo de 40px com o ícone lá dentro, à direita do título. É onde a mão
 * procura num telemóvel, e é a diferença entre uma ação que existe e uma ação
 * que se encontra.
 */
.acao-topo {
  display: grid; place-items: center; width: 40px; height: 40px; flex: none;
  border: 1px solid var(--gold-border); border-radius: 50%;
  color: var(--gold-text); background: transparent;
}
.acao-topo svg { width: 19px; height: 19px; }
.acao-topo:active { background: var(--gold-soft); }

/* Uma ação de cabeçalho que não tem título ao lado: encosta-se ao canto direito
   da linha onde nasce, sem empurrar nada. */
.acao-canto { position: absolute; top: 14px; right: 0; }
.screen > .acao-canto { align-self: flex-end; position: static; margin-top: -46px; }

/* A mesma ação, mais pequena, quando vive numa linha de sobrancelha. */
.acao-topo.pequena { width: 32px; height: 32px; }
.acao-topo.pequena svg { width: 15px; height: 15px; }

/**
 * Os dois gestos da chave de agora, lado a lado e centrados como um par.
 *
 * O primeiro tinha `grow` e esticava-se, o que empurrava os dois para a
 * direita: o par ficava descentrado sem nada no ecrã a explicar porquê. Aqui
 * nenhum dos dois cresce, e o conjunto centra-se no meio.
 */
.acoes-chave { justify-content: center; gap: var(--e-1) var(--e-5); flex-wrap: wrap; }
.acoes-chave .link-gold { flex: none; }

/**
 * O ecrã vazio, com a mesma forma em todo o lado.
 *
 * Centrado e com ar à volta, porque um vazio que ocupa uma linha no topo lê-se
 * como um erro de carregamento. O ícone é grande e apagado: dá corpo ao espaço
 * sem competir com a frase que diz o que ali vai viver.
 */
.vazio {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--e-2); padding: var(--e-5) var(--e-4);
}
.vazio-ico { color: var(--ink-30); }
.vazio-ico svg { width: 30px; height: 30px; }
.vazio-titulo { font-size: var(--t-md); font-weight: 600; color: var(--ink); margin: 0; }
.vazio .btn { width: auto; margin-top: var(--e-1); }

/**
 * As três sessões individuais: o nome primeiro.
 *
 * O nome é o que se está a escolher, e estava do tamanho de uma etiqueta com o
 * preço ao lado a puxar o olho. Aqui é ele que manda, na serifa dos nomes desta
 * app; a duração e o preço vêm por baixo, numa linha só, que é o que se lê
 * depois de já se ter decidido qual das três é.
 */
.ind-nome {
  font-family: Spectral, Georgia, serif; font-size: var(--t-xl);
  color: var(--ink); line-height: 1.2;
}
.ind-meta { font-size: var(--t-xs); color: var(--gold-text); letter-spacing: .04em; }

/* Um título que também é um botão: o ano abre a escolha das temporadas. */
.titulo-seletor { display: flex; align-items: center; gap: var(--e-2); color: var(--ink); background: none; }
.titulo-seletor svg { width: 18px; height: 18px; color: var(--gold-text); transform: rotate(90deg); }

/**
 * Onde estou a olhar, num botão só.
 *
 * A fila de cápsulas com uma por cidade cabia enquanto foram três. Com dez ou
 * vinte ocupava meio ecrã antes de se ver uma sessão, e a agenda passava a
 * perguntar em vez de mostrar. Isto diz o sítio e o número, e abre a lista toda
 * quando é preciso mudar.
 */
.filtro-sitio {
  display: flex; align-items: center; gap: var(--e-2);
  padding: var(--e-3); border: 1px solid var(--ink-12); border-radius: var(--r-card);
  background: var(--ink-06); color: var(--ink); font-size: var(--t-sm); font-weight: 600;
  text-align: left; width: 100%;
}
.filtro-sitio svg { width: 17px; height: 17px; color: var(--gold-text); flex: none; }
.filtro-sitio svg:last-child { color: var(--ink-30); transform: rotate(90deg); }
.filtro-conta { color: var(--ink-50); font-weight: 400; }

/**
 * A troca de página feita pelo dedo é animada por nós, e não pelo browser.
 *
 * Tentou-se pela transição de páginas do browser, com uma marca no html a dizer
 * o sentido. Não serve: essa transição fotografa o ecrã no instante em que é
 * chamada, e nesse instante a página antiga ainda está a meio de sair. O que
 * faltava não era a direcção, era o tempo: entre soltar o dedo e haver
 * conteúdo novo há um ecrã inteiro a carregar, e no perfil isso são seis
 * pedidos. Está tudo em `swipeEntreAbas` e em `render`, no app.js.
 */

/**
 * A bancada do início: o hexagrama e a frase.
 *
 * Ficaram duas ideias de dez, e o que se compara agora são maneiras de as
 * cruzar. Regras só desta sala de ensaios, debaixo de `.proto-inicios`, que não
 * tocam em nada da app.
 */
.proto-palco {
  border: 1px dashed var(--ink-12); border-radius: var(--r-card);
  padding: var(--e-5) var(--e-3); margin-top: var(--e-2);
  display: flex; flex-direction: column; align-items: center; overflow: hidden;
}
.proto-inicios .p-centro {
  display: flex; flex-direction: column; align-items: center; gap: var(--e-2); text-align: center; width: 100%;
}
.proto-inicios .p-esq { align-items: flex-start; text-align: left; }
.proto-inicios .p-duas { display: flex; align-items: center; gap: var(--e-4); width: 100%; }
.proto-inicios .p-linha-chave { display: flex; align-items: baseline; gap: var(--e-2); flex-wrap: wrap; justify-content: center; }

/* As seis linhas, com a do Sol acesa. */
.proto-inicios .p-hexa { display: flex; flex-direction: column; }
.proto-inicios .p-hexa-linha { display: flex; gap: 12px; height: var(--alt); flex: none; }
.proto-inicios .p-hexa-linha i { background: var(--cor); border-radius: 3px; }
.proto-inicios .p-hexa-linha b { width: 22px; }
.proto-inicios .p-hexa-linha.viva i { box-shadow: 0 0 14px var(--gold-soft); }

/* A frase, que é o outro herói. */
.proto-inicios .p-frase {
  font-family: var(--serif); font-size: clamp(21px, 6vw, 28px); line-height: 1.3;
  color: var(--ink); margin: 0; max-width: 26ch;
}
.proto-inicios .p-frase.grande { font-size: clamp(26px, 8vw, 38px); line-height: 1.22; }
.proto-inicios .p-frase.pequena { font-size: clamp(17px, 4.6vw, 21px); color: var(--ink-70); }

/* O hexagrama por trás do texto. */
.proto-inicios .p-fundo { position: relative; width: 100%; display: flex; justify-content: center; }
.proto-inicios .p-fundo-hexa {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  opacity: .12; pointer-events: none;
}

/* A etiqueta da linha e a escada das três frequências. */
.proto-inicios .p-tag {
  font-size: var(--t-2xs); letter-spacing: .16em; text-transform: uppercase; font-weight: 700;
  color: var(--gold-text); border: 1px solid var(--gold-border); border-radius: var(--r-pill);
  padding: 3px var(--e-2);
}
.proto-inicios .p-escada { display: flex; flex-direction: column; gap: 2px; align-items: center; }
.proto-inicios .p-escada span {
  font-size: var(--t-sm); color: var(--ink-30); letter-spacing: .1em; text-transform: uppercase;
}
.proto-inicios .p-escada span.viva {
  color: var(--gold-text); font-weight: 700; font-size: var(--t-lg); letter-spacing: .04em;
  text-transform: none; font-family: var(--serif);
}

/* As seis linhas de pé, a ler-se como tempo. */
.proto-inicios .p-hexa-deitado { display: flex; gap: 10px; align-items: flex-end; height: 96px; }
.proto-inicios .p-hexa-deitado span { display: flex; flex-direction: column; gap: 8px; width: 15px; height: 100%; }
.proto-inicios .p-hexa-deitado i { flex: 1; background: var(--ink-12); border-radius: 4px; }
.proto-inicios .p-hexa-deitado span.viva i { background: var(--gold); box-shadow: 0 0 16px var(--gold-soft); }

/* O início inteiro: três maneiras de dar corpo à chave sem tirar o ecrã à frase. */
.proto-palco.ecra { align-items: stretch; padding: var(--e-4) var(--e-4) var(--e-5); gap: var(--e-4); }
.proto-palco.ecra > * { width: 100%; }
/* A capitular a sério: o número flutua e o texto corre à volta dele, como numa
   página impressa. Em coluna ao lado, a frase ficava presa a metade da largura
   e partia-se em sete linhas. */
.p-final-capitular { display: flex; flex-direction: column; gap: var(--e-1); }
.p-final-capitular .keynum {
  float: left; font-size: clamp(58px, 18vw, 84px); line-height: .82;
  margin: 6px var(--e-3) 0 0; font-weight: 700;
}
.p-final-capitular .p-frase::after { content: ''; display: block; clear: both; }
/* Num ecrã inteiro a frase divide o espaço com o resto, e o tamanho da bancada
   dos heróis, onde ela estava sozinha, deixa de servir. */
.proto-palco.ecra .p-frase { max-width: none; }
.proto-palco.ecra .p-frase.grande { font-size: clamp(21px, 6vw, 28px); line-height: 1.28; }
/* A capitular a um terço: abre a frase sem ser o assunto dela. */
.p-final-capitular.miuda .keynum { font-size: clamp(30px, 9vw, 40px); line-height: .95; margin-top: 4px; }

/* O número dentro do nome, numa etiqueta só. */
.p-final-etiqueta { display: flex; flex-direction: column; gap: var(--e-2); }
.p-etiqueta {
  font-size: var(--t-2xs); letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-50); font-weight: 600;
}
.p-etiqueta b { color: var(--gold-text); font-weight: 700; font-size: var(--t-xs); }

/* O selo na margem, à altura da primeira linha. */
.p-final-margem { display: flex; gap: var(--e-3); align-items: flex-start; }
.p-final-margem-dito { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--e-1); }
.p-selo {
  flex: none; width: 40px; height: 40px; margin-top: 14px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--gold-border); border-radius: 50%;
  color: var(--gold-text); font-weight: 700; font-size: var(--t-md);
}

.p-final-fundo { position: relative; padding: var(--e-4) 0; }
.p-final-marca {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: clamp(150px, 46vw, 230px); font-weight: 700; color: var(--gold);
  opacity: .12; line-height: 1; pointer-events: none; user-select: none;
}
.p-final-frente { position: relative; display: flex; flex-direction: column; gap: var(--e-2); }
.p-final-topo { display: flex; align-items: center; justify-content: center; gap: var(--e-4); }
.p-final-topo-dito { display: flex; align-items: baseline; gap: var(--e-2); flex-wrap: wrap; }
