/* As faces, aqui dentro e nao por @import.

   Um @import e uma cascata em serie: o browser so sabe que fonts.css existe
   depois de ter recebido e lido esta folha, e so entao pede os woff2. Em frio,
   a fonte do corpo so era pedida aos 946 ms.

   Dois pares eram byte a byte identicos, inter-0 com inter-1 e bodoni-0 com
   bodoni-1, e cada um era descarregado duas vezes. Os @font-face de peso
   diferente apontam agora ao mesmo ficheiro, porque e o mesmo ficheiro. */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url(/fonts/bricolage-0.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/inter-0.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(/fonts/inter-0.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/mono-0.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Bodoni Moda';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/fonts/bodoni-0.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Bodoni Moda';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/fonts/bodoni-0.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ---------------------------------------------------------------- tokens */
:root {
  --paper:      #FAFAF7;
  --surface:    #F1F1EC;
  --ink:        #101014;
  --ink-2:      #3A3A44;
  --ink-3:      #6B6B78;
  --accent:     #4D3DF7;
  --ring:       #4D3DF7;
  --highlight:  #B8F227;
  --hairline:   rgba(16, 16, 20, 0.10);

  /* the dark product room */
  --room-stage:  #0C0B0A;
  --room-ink:    #F2EFEA;
  --room-ink-2:  rgba(242, 239, 234, 0.72);
  --room-ink-3:  rgba(242, 239, 234, 0.62);
  --room-line:   rgba(242, 239, 234, 0.14);

  --display: "Bricolage Grotesque", Inter, system-ui, sans-serif;
  --body:    Inter, system-ui, -apple-system, sans-serif;
  --mono:    "JetBrains Mono", ui-monospace, monospace;
  --serif:   "Bodoni Moda", Didot, Georgia, serif;

  --instant: 100ms cubic-bezier(0.2, 0, 0.4, 1);
  --quick:   220ms cubic-bezier(0.2, 0, 0.2, 1);
  --smooth:  400ms cubic-bezier(0.16, 1, 0.3, 1);
  --slow:    800ms cubic-bezier(0.16, 1, 0.3, 1);

  --gutter: clamp(24px, 4.2vw, 56px);
  --max:    1344px;
}

/* ------------------------------------------------------------------ base */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font: 400 1.0625rem/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  /* clip, nunca hidden: `hidden` faz do body uma caixa de scroll, e a partir
     daí é ela que as animações `view()` passam a medir. Como o body nunca
     rola, o progresso ficava preso em zero e tudo o que tem data-reveal
     ficava invisível para sempre. `clip` corta na mesma sem criar scroller. */
  overflow-x: clip;
}
img { max-width: 100%; display: block; }
a { color: var(--accent); text-decoration: none; }
/* So a linha. Em abreviado, `a:hover` (0,1,1) ganhava a todas as classes
   que declararam a propria geometria (0,1,0) e repunha espessura e cor: o
   endereco de correio saltava de 2px e 6px de distancia para automatico e
   3px no instante em que o rato lhe tocava. */
a:hover { text-decoration-line: underline; }
a:not([class]):hover { text-underline-offset: 3px; }
::selection { background: rgba(77, 61, 247, 0.18); }
/* Cada sala fixa a sua paleta, por isso a seleccao tem de a acompanhar: o
   indigo a 16% sobre #0E0E0F ou #0C0B0A nao se distingue do fundo, e e nas
   salas que estao os textos mais longos do site. */
.room--ui ::selection, .room--hnm ::selection { background: rgba(242, 239, 234, 0.24); }
.room--yet ::selection { background: rgba(168, 44, 142, 0.18); }
body.consult ::selection { background: rgba(227, 178, 60, 0.26); }
/* O anel de foco e um token proprio, e nao o acento, porque as salas fixam a
   propria paleta e nao herdam o tema. O indigo do papel claro mede 6,04:1 sobre
   ele e depois cai para 3,06 na sala do AirMouse, 3,11 na do Her Next Move e
   2,86 na consultoria, onde falha o minimo de 3:1 que um indicador de foco tem
   de ter. Quem navega por teclado deixava de ver onde estava, justamente na
   pagina que pede para alguem escrever. Cada clima passa a dar um anel que se
   ve sobre ele. */
:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; border-radius: 2px; }

.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.skip {
  position: absolute; left: var(--gutter); top: -64px; z-index: 100;
  background: var(--ink); color: var(--paper); padding: 10px 20px;
  border-radius: 999px; font: 600 0.875rem var(--body); transition: top var(--instant);
}
.skip:focus { top: 16px; text-decoration: none; }

/* ------------------------------------------------------------ typography */
.eyebrow {
  margin: 0; font: 400 0.8125rem/1.4 var(--mono);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3);
}
.hero-title {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: min(clamp(3.5rem, 9.5vw, 9rem), 13.4vw);
  line-height: 0.92; letter-spacing: -0.03em; color: var(--ink);
  font-variation-settings: "opsz" 48, "wdth" 100, "wght" 760;
}
.hero-title span { display: block; }
.display {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(2.5rem, 5vw, 5rem); line-height: 1;
  letter-spacing: -0.025em; color: var(--ink);
}
.h2 {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(2rem, 4vw, 3.5rem); line-height: 1.05;
  letter-spacing: -0.02em; color: var(--ink);
}
.lead {
  font: 400 clamp(1.25rem, 1.8vw, 1.5rem)/1.5 var(--body);
  color: var(--ink-2); max-width: 34em;
}
.prose { margin: 0; max-width: 56ch; }

/* --------------------------------------------------------- marker accent */
.mark { position: relative; display: inline-block; }
.mark i {
  position: absolute; inset: 0.04em -0.1em 0 0; background: var(--highlight);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 300ms cubic-bezier(0.2, 0, 0.2, 1) 150ms;
}
.mark b { position: relative; font-weight: inherit; color: var(--ink); }

/* -------------------------------------------------------------- controls */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--accent); color: #fff; font: 600 1.0625rem var(--body);
  border-radius: 999px; padding: 16px 32px;
  transition: background-color var(--instant), transform var(--instant);
}
.btn:hover { background: #3A2BD4; text-decoration: none; }
.btn:active { transform: scale(0.98); }
.btn--light { background: var(--room-ink); color: var(--room-stage); }
.btn--light:hover { background: #fff; }
.btn--ghost {
  background: none; color: var(--ink); border: 1px solid rgba(16,16,20,0.18);
  font: 600 0.9375rem var(--body); padding: 10px 20px; border-radius: 999px;
}
.btn--ghost:hover { background: var(--surface); text-decoration: none; }

/* ------------------------------------------------------------ structure */
header.top {
  max-width: var(--max); margin: 0 auto; padding: 24px var(--gutter);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.wordmark {
  font-family: var(--display); font-weight: 700; font-size: 1.375rem;
  letter-spacing: -0.02em; color: var(--ink);
  font-variation-settings: "opsz" 24, "wdth" 100, "wght" 700;
  transition: font-variation-settings var(--quick);
}
.wordmark:hover { font-variation-settings: "opsz" 24, "wdth" 88, "wght" 800; text-decoration: none; }
nav a { font: 400 0.9375rem var(--body); color: var(--ink-2); }

section { padding-top: clamp(80px, 10vw, 128px); }
.hero {
  position: relative; min-height: 86vh; display: flex; flex-direction: column;
  justify-content: center; overflow: clip; padding: clamp(48px, 7vw, 96px) 0;
}
.hero-glow {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(640px at 72% 18%, rgba(77, 61, 247, 0.06), transparent 70%);
}

.rule-list { list-style: none; margin: 0; padding: 0; }
.rule-list > li { border-top: 1px solid var(--hairline); }

.facts {
  list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
  gap: 32px 24px;
}
.facts li {
  border-top: 1px solid var(--hairline); padding-top: 16px;
  display: flex; flex-direction: column; gap: 10px;
}
.facts strong {
  font-family: var(--display); font-weight: 700; font-size: 1.375rem;
  letter-spacing: -0.015em; line-height: 1.15; color: var(--ink);
}

.manifesto { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: clamp(40px, 5vw, 56px); }
.manifesto li {
  border-top: 1px solid var(--hairline); padding-top: 32px; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: 16px 64px; align-items: start;
}
.manifesto h2 {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.75rem, 3.2vw, 3rem); line-height: 1.1;
  letter-spacing: -0.02em; color: var(--ink);
}

.spec { margin: 0; max-width: 880px; display: flex; flex-direction: column; }
/* A coluna do rotulo levava 200px e a do valor 96 a 360px de ecra: uma
   palavra a ocupar o dobro da frase que a explica. A medida certa nao vem da
   viewport, porque a ficha e a largura toda em baixo e metade em cima; vem do
   proprio contentor. */
.spec { container-type: inline-size; }
.spec > div {
  border-top: 1px solid var(--hairline); padding: 16px 0;
  display: grid; grid-template-columns: 1fr; gap: 6px;
}
@container (min-width: 480px) {
  /* 104 e nao 168: o rotulo mais largo do site mede 70,7px de tinta, e uma
     grelha maximiza as pistas antes de as flexionar, por isso os 97px vazios
     saiam sempre da frase. */
  .spec > div { grid-template-columns: 104px minmax(0, 1fr); gap: 20px; align-items: baseline; }
}
.spec > div:last-child { border-bottom: 1px solid var(--hairline); }
.spec dt { font: 400 0.8125rem/1.7 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.spec dd { margin: 0; font: 400 0.9375rem/1.7 var(--mono); color: var(--ink); }

.mail {
  align-self: flex-start; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.75rem, 4vw, 3.5rem); letter-spacing: -0.015em;
  line-height: 1.15; color: var(--accent); overflow-wrap: anywhere;
  text-decoration: underline 2px; text-underline-offset: 6px;
}

/* -------------------------------------------------- the product room */
.room {
  margin-top: clamp(80px, 10vw, 128px); background-color: var(--room-stage);
  transition: background-color var(--smooth);
}
.room .inner {
  max-width: var(--max); margin: 0 auto;
  padding: clamp(80px, 10vw, 128px) var(--gutter);
  transition: opacity var(--smooth);
}
.room, .room h1, .room h2, .room h3 { color: var(--room-ink); }
.room p, .room dd { color: var(--room-ink-2); }
.room .eyebrow, .room figcaption { color: var(--room-ink-3); }
.room .serif { font-family: var(--serif); font-weight: 500; letter-spacing: -0.01em; }
/* A mesma trava em vw que o heroi tem. Sem ela, a 320px o nome da sala mede
   48px contra 42,9 do titulo da pagina: a seccao gritava mais alto do que a
   casa, e a 360, que e o Android mais comum, empatavam. */
.room h2.serif { font-size: min(clamp(3rem, 6vw, 5.5rem), 10.4vw); line-height: 1.02; margin: 0; }
.room h2.serif.sub { font-size: clamp(1.75rem, 3vw, 2.5rem); line-height: 1.1; margin: 0; }
/* A sala tinha dois niveis abaixo do titulo e gastava o mais pequeno nos dois:
   "Point your phone here", um h3 dentro de uma nota de rodape, media o mesmo
   que "Everything it does". */
.room h3.serif { font-size: clamp(1.25rem, 1.8vw, 1.5rem); line-height: 1.2; margin: 0; }
/* Only the page's own title gets display size; a subsection never outranks it. */
.room > .inner > section { padding-top: 0; }
/* A sala levava o padding da `section` por cima do da sua `.inner`: 256px em
   cima contra 128 em baixo, a 1280. Um sitio nao tem o dobro do ar de um lado,
   e a pagina inicial perdia 378px de altura morta em tres salas. */
section.room { padding-top: 0; }
.room .rule-list > li { border-top-color: var(--room-line); }
.room .steps { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; }
.room .steps li {
  border-top: 1px solid var(--room-line); padding: 24px 0;
  display: grid; grid-template-columns: 56px 1fr; gap: 16px;
  /* O mesmo mecanismo que ja acerta o numeral da lista de funcionalidades. */
  align-items: baseline;
}
.room .steps li:last-child { border-bottom: 1px solid var(--room-line); }
/* Em abreviado, `font` poe tambem a familia, e `.room .steps h3` (0,2,1)
   ganhava a `.room--ui h3` (0,1,1): o titulo do passo saia em Inter e o
   paragrafo 25px abaixo dele em SF. */
.room .steps h3 { margin: 0; font-family: var(--body); font-weight: 600;
  font-size: 1.25rem; line-height: 1.3; }
.room--ui .steps h3, .room--yet .steps h3 { font-family: var(--ui); }
/* A unica prosa do site sem medida: 85 caracteres por linha a 880px. */
.room .steps p { max-width: 56ch; }
.room .steps span { font: 400 0.8125rem/1.7 var(--mono); letter-spacing: 0.08em; color: var(--room-ink-3); }
.room .num { font: 400 0.8125rem/1.7 var(--mono); letter-spacing: 0.08em; color: var(--room-ink-3); }

.refusals { list-style: none; margin: clamp(32px,4vw,48px) 0 0; padding: 0; display: flex; flex-direction: column; gap: clamp(32px, 4vw, 48px); }
.refusals li {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: 12px 64px; align-items: baseline;
}
.refusals .word {
  position: relative; display: inline-block; justify-self: start;
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(2.25rem, 4.5vw, 3.5rem); line-height: 1.05; color: var(--room-ink);
}
.refusals .word i {
  position: absolute; left: -0.08em; right: -0.08em; top: 54%; height: 1px;
  background: rgba(242, 239, 234, 0.9); transform: scaleX(0);
  transform-origin: left center; transition: transform var(--smooth);
}
/* Uma regra absoluta a 54% da caixa acerta na palavra enquanto ela couber numa
   linha. Em duas, 54% e o vao entre as duas: o filete passa por baixo da
   primeira e por cima da segunda e nao toca em nenhuma. Ha palavras que partem
   sempre, e a 375px partem quase todas.

   `text-decoration` risca todas as linhas, e a cor dela e animavel, por isso a
   revelacao mantem-se na mesma linha do tempo e com o mesmo desfasamento entre
   as quatro. O que se perde e o varrimento da esquerda para a direita, que era
   bonito e passava ao lado da palavra. */
@supports (text-decoration-thickness: 1px) {
  .refusals .word i { display: none; }
  .refusals .word {
    text-decoration: line-through;
    text-decoration-thickness: 1px;
    text-decoration-color: currentColor;
  }
}


.shot {
  margin: 0; justify-self: center; display: flex; flex-direction: column; gap: 16px;
  align-items: center; will-change: transform;
}
/* The device already carries its own frame, so no border and no crop here. */
.shot .device { width: min(400px, 84vw); height: auto; }
/* A legenda centra-se debaixo do aparelho. Alinhada ao início, a do AirMouse
   só parecia centrada porque o texto quase enchia a caixa; uma mais curta
   mais curta, ficava visivelmente à esquerda do telemóvel. */
.shot figcaption { text-align: center; }
figcaption { font: 400 0.8125rem/1.4 var(--mono); letter-spacing: 0.08em; text-transform: uppercase; }

/* --------------------------------------------------------------- footer */
.footmark { max-width: var(--max); margin: 0 auto; padding: clamp(48px,7vw,96px) var(--gutter) 8px; overflow: hidden; }
.footmark p {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: min(12.8vw, 10.5rem); line-height: 0.9; letter-spacing: -0.03em;
  color: var(--ink); white-space: nowrap;
  font-variation-settings: "opsz" 96, "wdth" 75, "wght" 300;
}
footer.site { border-top: 1px solid var(--hairline); }
footer.site .wrap {
  padding-top: 32px; padding-bottom: 32px; display: flex; align-items: center;
  justify-content: space-between; gap: 16px 32px; flex-wrap: wrap;
}
footer.site nav { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }

/* -------------------------------------------------------- article pages */
/* 64ch: a 72 a linha chegava aos 80 caracteres, e sao estas as duas paginas
   que alguem le de fio a pavio. */
.doc { max-width: 64ch; margin: 0 auto; padding: 0 var(--gutter); }
.doc h2 { font-family: var(--display); font-weight: 700; font-size: clamp(1.5rem, 3vw, 2rem); letter-spacing: -0.015em; color: var(--ink); margin: 48px 0 16px; }
.doc p { margin: 0 0 20px; }
.doc ul { margin: 0 0 16px; padding-left: 1.2em; }

/* ---------------------------------------------------------------- motion
   Everything below is additive. No rule here may be the only reason a piece
   of content is visible: without CSS, without JS, or without scroll-timeline
   support, the page reads in full. That is why the reveals live inside
   @supports and the marker/strike fills default to their finished state. */
@keyframes breathe { from { transform: scale(1); } to { transform: scale(1.06); } }
.breathe { animation: breathe 14s ease-in-out infinite alternate; }

@keyframes reveal-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
@keyframes wipe-in   { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes strike-in { from { text-decoration-color: transparent; } to { text-decoration-color: currentColor; } }
@keyframes hero-in   { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes room-in   { from { opacity: 0; } to { opacity: 1; } }

/* The marker and the strike are drawn finished; the animation only replays
   them on scroll where the browser can. */
.mark i, .refusals .word i { transform: scaleX(1); }

@media (prefers-reduced-motion: no-preference) {
  [data-hero-line] { animation: hero-in 800ms cubic-bezier(0.16, 1, 0.3, 1) both; }
  [data-hero-line]:nth-of-type(1) { animation-delay: 0ms; }
  .hero-title span:nth-child(1) { animation-delay: 80ms; }
  .hero-title span:nth-child(2) { animation-delay: 160ms; }
  .hero-title span:nth-child(3) { animation-delay: 240ms; }
  .hero .lead { animation-delay: 320ms; }
  .hero .lead + div { animation-delay: 400ms; }
}

/* O interruptor que o app.js puxa quando apanha um reveal preso. */
:root[data-reveals="off"] [data-reveal],
:root[data-reveals="off"] .room .inner { animation: none !important; opacity: 1 !important; transform: none !important; }
:root[data-reveals="off"] .mark i,
:root[data-reveals="off"] .refusals .word i { animation: none !important; transform: scaleX(1) !important; }
:root[data-reveals="off"] .refusals .word { animation: none !important; text-decoration-color: currentColor !important; }

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    [data-reveal] {
      animation: reveal-in 220ms cubic-bezier(0.2, 0, 0.2, 1) both;
      animation-timeline: view();
      animation-range: entry 0% entry 35%;
    }
    .mark i {
      animation: wipe-in 300ms cubic-bezier(0.2, 0, 0.2, 1) both;
      animation-timeline: view();
      animation-range: entry 25% entry 70%;
    }
    .refusals .word i {
      animation: wipe-in 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
      animation-timeline: view();
      animation-range: entry 30% entry 80%;
    }
    .refusals li:nth-child(2) .word i { animation-range: entry 35% entry 85%; }
    .refusals li:nth-child(3) .word i { animation-range: entry 40% entry 90%; }
    .refusals li:nth-child(4) .word i { animation-range: entry 45% entry 95%; }
    /* O mesmo tempo e o mesmo desfasamento, agora na decoracao, que segue as
       linhas todas em vez de uma regua a atravessar a caixa. */
    .refusals .word {
      text-decoration-color: transparent;
      animation: strike-in 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
      animation-timeline: view();
      animation-range: entry 30% entry 80%;
    }
    .refusals li:nth-child(2) .word { animation-range: entry 35% entry 85%; }
    .refusals li:nth-child(3) .word { animation-range: entry 40% entry 90%; }
    .refusals li:nth-child(4) .word { animation-range: entry 45% entry 95%; }
    .refusals li:nth-child(5) .word { animation-range: entry 50% entry 100%; }
    .room .inner {
      animation: room-in 400ms cubic-bezier(0.16, 1, 0.3, 1) both;
      animation-timeline: view();
      animation-range: entry 0% entry 25%;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  .mark i, .refusals .word i { transform: scaleX(1) !important; }
  .refusals .word { animation: none !important; text-decoration-color: currentColor !important; }
  .shot { transform: none !important; }
}

@media (max-width: 674px) {
  .facts { gap: 24px 16px; }
  footer.site .wrap { flex-direction: column; align-items: flex-start; }

}

/* ------------------------------------------------------------- the mark */
.wordmark { display: inline-flex; align-items: center; gap: 10px; }
.mark-glyph { flex: none; color: var(--ink); }
.mark-glyph rect { transition: transform var(--smooth); transform-origin: 32px 32px; }
.wordmark:hover .mark-glyph rect { transform: rotate(0deg); }

/* The room's own title. Explicit rather than inline, so a subsection heading
   can never outrank it, which is exactly what happened once. */
.room h1.room-title {
  font-size: clamp(3rem, 7vw, 6rem);
  line-height: 1.02;
  margin: 40px 0 0;
}

/* ====================================================================
   Shades: soft light that sits behind content, never over it.
   Every one is aria-hidden and pointer-events none.
   ==================================================================== */
.shade { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.shade--hero {
  background:
    radial-gradient(760px 520px at 78% 12%, rgba(77, 61, 247, 0.09), transparent 68%),
    radial-gradient(520px 420px at 8% 82%, rgba(184, 242, 39, 0.13), transparent 70%);
}
.shade--stage {
  background: radial-gradient(340px 240px at 50% 62%, rgba(16, 16, 20, 0.10), transparent 72%);
}
.shade--room {
  background:
    radial-gradient(680px 460px at 84% 8%, rgba(242, 239, 234, 0.07), transparent 66%),
    radial-gradient(520px 380px at 6% 92%, rgba(242, 239, 234, 0.05), transparent 70%);
}
.shade--contact {
  background: radial-gradient(620px 420px at 12% 40%, rgba(77, 61, 247, 0.08), transparent 70%);
}
.hero > .wrap, .room > .inner, #contact > .wrap { position: relative; z-index: 1; }
/* Num flex column um item encolhe ao conteudo. Sem isto o `.wrap` do heroi
   mede 864px onde toda a outra seccao mede 1232, e o titulo da casa comeca
   adentro da margem da pagina. */
.hero > .wrap, #contact > .wrap { width: 100%; }
.u-contact { position: relative; overflow: clip; padding-bottom: clamp(80px, 10vw, 128px); }

/* -------------------------------------------------------- two column split */
.split {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr));
  gap: 24px 64px; align-items: start;
}
.stack24 { display: flex; flex-direction: column; gap: 24px; }
.stack16 { display: flex; flex-direction: column; gap: 16px; }
.h3 {
  margin: 0; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.5rem, 2.6vw, 2.125rem); line-height: 1.12;
  letter-spacing: -0.015em; color: var(--ink);
}

/* ------------------------------------------------------- the slab sculpture */
.stage {
  position: relative; margin: clamp(48px, 6vw, 80px) 0 0;
  display: flex; flex-direction: column; align-items: center; gap: 20px;
}
.slabs { width: min(320px, 76vw); height: auto; position: relative; z-index: 1; }
.slab { transform-origin: 160px 130px; }
.slab-1 { transform: rotate(-9deg); }
.slab-2 { transform: rotate(-6deg); }
.slab-3 { transform: rotate(-3deg); }
.slab-4 { transform: rotate(0deg); }
@media (prefers-reduced-motion: no-preference) {
  .slab { animation: settle 9s cubic-bezier(0.16, 1, 0.3, 1) infinite; }
  .slab-1 { animation-delay: 0s; }
  .slab-2 { animation-delay: .28s; }
  .slab-3 { animation-delay: .56s; }
  .slab-4 { animation-delay: .84s; }
}
@keyframes settle {
  0%, 8%   { transform: rotate(var(--from, -9deg)) translateY(0); }
  38%, 82% { transform: rotate(0deg) translateY(-2px); }
  100%     { transform: rotate(var(--from, -9deg)) translateY(0); }
}
.slab-1 { --from: -9deg; } .slab-2 { --from: -6deg; }
.slab-3 { --from: -3deg; } .slab-4 { --from: -1deg; }

/* ------------------------------------------------------------------ tiles */
.tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: 20px; margin-top: clamp(40px, 5vw, 56px);
}
.tile {
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px;
  padding: 24px; display: flex; flex-direction: column; gap: 10px;
  box-shadow: 0 1px 2px rgba(16,16,20,.04), 0 12px 28px -18px rgba(16,16,20,.28);
  transition: transform var(--quick), box-shadow var(--quick);
}
.tile:hover { transform: translateY(-3px); box-shadow: 0 2px 4px rgba(16,16,20,.05), 0 22px 42px -22px rgba(16,16,20,.34); }
.tile strong {
  font-family: var(--display); font-weight: 700; font-size: 1.125rem;
  letter-spacing: -0.01em; color: var(--ink);
}
.tile p { margin: 0; font-size: 0.9375rem; }

/* ------------------------------------------------------- the quiet notice */
.quietcard {
  border: 1px solid var(--hairline); border-radius: 16px;
  background: linear-gradient(180deg, var(--surface), rgba(241,241,236,0));
  padding: clamp(28px, 4vw, 44px); display: flex; flex-direction: column;
  gap: 24px; align-items: flex-start; max-width: 760px;
  box-shadow: 0 1px 2px rgba(16,16,20,.03), 0 24px 48px -32px rgba(16,16,20,.30);
}
.quiet {
  font: 400 1rem var(--body); color: var(--ink-2);
  text-decoration: underline; text-underline-offset: 5px;
  text-decoration-color: rgba(16,16,20,.28);
}
.quiet:hover { color: var(--accent); text-decoration-color: currentColor; }
.quiet--light { color: var(--room-ink); text-decoration-color: rgba(242,239,234,.4); }
.quiet--light:hover { color: #fff; }

/* a little more depth on the device, now that shades are allowed */
.shot .device { filter: drop-shadow(0 40px 60px rgba(0,0,0,.45)); }

/* The header nav had no gap, so "Work" and "Notes" ran together. */
header.top nav { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }
/* At 26px four outlines turn into a smudge; the small mark carries three. */
.mark-glyph { width: 28px; height: 28px; }

/* The slab sculpture, drifting the way the app portrait breathes. */
.sculpt { width: min(420px, 82vw); height: auto; position: relative; z-index: 1; }
@media (prefers-reduced-motion: no-preference) {
  .sculpt { animation: drift 11s ease-in-out infinite alternate; }
}
@keyframes drift {
  from { transform: translateY(-6px) rotate(-0.4deg); }
  to   { transform: translateY(8px) rotate(0.4deg); }
}
.stage--block { margin-top: clamp(40px, 5vw, 64px); }
.sculpt--block { width: min(300px, 62vw); }
@media (prefers-reduced-motion: no-preference) {
  .sculpt--block { animation-duration: 14s; }
}

/* ====================================================================
   Dark theme. Every value re-measured against the new paper, because a
   palette that passed on #FAFAF7 says nothing about #1E1E25.
   The product room keeps its own near-black so it still reads as
   somewhere else, and gains hairlines to make that separation legible.
   ==================================================================== */
:root[data-theme="dark"] {
  --paper:     #1E1E25;   /* room #0C0B0A sits 1.19:1 below it */
  --surface:   #26262E;
  --ink:       #F2F2EE;   /* 14.8:1 */
  --ink-2:     #B9B9C2;   /*  8.5:1 */
  --ink-3:     #93939D;   /*  5.4:1 on paper, 4.9:1 on surface, which is
                             the pair that matters: the eyebrow inside a tile
                             sits on the lighter of the two */
  --accent:    #8B7DFF;   /*  5.1:1, the light-mode indigo fails here at 2.9 */
  --ring:      #8B7DFF;
  --accent-ink: #101014;  /* tint on top of the accent, 5.9:1 */
  --hairline:  rgba(255, 255, 255, 0.12);
}
:root[data-theme="dark"] body { color: var(--ink-2); }
/* Fora das salas. Uma sala fixa a sua paleta e o tema nao entra la dentro:
   com esta regra a valer, o botao claro da sala da YET ficava a 1,33:1. */
:root[data-theme="dark"] .btn:not(.room .btn) { color: var(--accent-ink); }
:root[data-theme="dark"] .btn:not(.room .btn):hover { background: #A99BFF; }
/* A palavra marcada chegava ao ecra invisivel e so se lia depois de a banda
   passar por baixo dela.

   No tema claro nao ha problema: a tinta e escura, e tanto o papel como a
   banda lima sao claros. No escuro havia uma contradicao: a tinta tinha de ser
   escura sobre a banda clara e clara sobre a pagina escura, e a banda cresce da
   esquerda para a direita, portanto nao ha instante em que uma so cor sirva.
   Medido: 1,15:1 antes de a banda chegar.

   Resolve-se pela banda e nao pela tinta. No escuro a marca e o indigo da casa:
   a tinta clara fica a 5,63:1 sobre ela, e a banda destaca-se do papel por
   matiz, que e como uma marca de marcador funciona. */
:root[data-theme="dark"] { --highlight: #4D3DF7; }
:root[data-theme="dark"] .room { border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
:root[data-theme="dark"] .tile,
:root[data-theme="dark"] .quietcard {
  box-shadow: 0 1px 2px rgba(0,0,0,.4), 0 18px 40px -24px rgba(0,0,0,.7);
}
:root[data-theme="dark"] .quietcard {
  background: linear-gradient(180deg, var(--surface), rgba(38,38,46,0));
}
:root[data-theme="dark"] .shade--hero {
  background:
    radial-gradient(760px 520px at 78% 12%, rgba(139, 125, 255, 0.14), transparent 68%),
    radial-gradient(520px 420px at 8% 82%, rgba(184, 242, 39, 0.10), transparent 70%);
}
:root[data-theme="dark"] .shade--stage {
  background: radial-gradient(340px 240px at 50% 62%, rgba(255, 255, 255, 0.07), transparent 72%);
}
:root[data-theme="dark"] .shade--contact {
  background: radial-gradient(620px 420px at 12% 40%, rgba(139, 125, 255, 0.12), transparent 70%);
}
:root[data-theme="dark"] .skip { background: var(--ink); color: var(--paper); }
:root[data-theme="dark"] .btn--ghost { border-color: rgba(255,255,255,0.22); }
:root[data-theme="dark"] .btn--ghost:hover { background: var(--surface); }
:root[data-theme="dark"] .quiet { text-decoration-color: rgba(255,255,255,.3); }
:root[data-theme="dark"] ::selection { background: rgba(139, 125, 255, 0.28); }
:root[data-theme="dark"] .sculpt { filter: drop-shadow(0 24px 40px rgba(0,0,0,.55)); }

/* --------------------------------------------------------- theme switch */
.themetoggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 999px; flex: none;
  border: 1px solid var(--hairline); background: none; cursor: pointer;
  color: var(--ink-2); padding: 0;
  transition: background-color var(--instant), color var(--instant), border-color var(--instant);
}
.themetoggle:hover { background: var(--surface); color: var(--ink); }
.themetoggle svg { width: 17px; height: 17px; }
.themetoggle .sun { display: none; }
:root[data-theme="dark"] .themetoggle .sun { display: block; }
:root[data-theme="dark"] .themetoggle .moon { display: none; }

/* Sem transicao de cor na troca de tema.

   O fundo desvanecia em 260 ms e a tinta trocava no primeiro fotograma: durante
   cerca de 100 ms a pagina ficava com a tinta nova sobre o fundo velho, medida
   a 1,4:1. Uma transicao que so pode ser correta se tudo mudar ao mesmo tempo,
   e que so afeta cinco seletores enquanto o resto herda de variaveis que mudam
   de imediato, e uma transicao que nao pode ser correta. A troca e instantanea.
   A classe `theme-ready` continua a ser posta em app.js e nao custa nada. */
/* the sculptures tilt under the pointer; the transition is the return home.
   The tilt lives on .tilt so the drift animation on .sculpt keeps running. */
.tilt { display: block; transition: transform 420ms cubic-bezier(0.16, 1, 0.3, 1); will-change: transform; }
.stage { cursor: default; }

.copied {
  display: block; font: 400 0.8125rem/1.4 var(--mono); letter-spacing: 0.06em;
  color: var(--ink-3); opacity: 0; transform: translateY(-4px);
  transition: opacity var(--quick), transform var(--quick); min-height: 1.2em;
}
.copied.on { opacity: 1; transform: none; }

/* the spec sheet reads better beside the instruments than under them */
/* A ficha caia para 381px quando o bloco abria em duas colunas a 861, abaixo
   da consulta de contentor dela propria, e ficava com os rotulos por cima dos
   valores durante 250px de largura de janela. Abre onde a coluna ja chega. */
.specwrap {
  display: grid; gap: clamp(32px, 5vw, 72px); align-items: center;
}
.stage--tools { margin-top: 0; order: 0; }
@media (min-width: 1120px) {
  .specwrap { grid-template-columns: 1fr 1fr; }
  .stage--tools { order: 2; }
}
.sculpt--tools { width: min(360px, 74vw); }
@media (prefers-reduced-motion: no-preference) { .sculpt--tools { animation-duration: 13s; } }

/* iOS-style app icon: continuous corners, a specular edge, and the weight of
   something sitting slightly above the page. The highlight is what makes it
   read as an icon rather than a cropped picture. */
.appicon{position:relative;display:block;line-height:0;margin:0 0 18px;
  width:72px;height:72px;
  border-radius:22.5%;
  box-shadow:0 14px 34px rgba(0,0,0,.42),0 3px 8px rgba(0,0,0,.28)}
.appicon img{display:block;width:100%;height:100%;border-radius:inherit}
.appicon--sm{width:58px;height:58px;margin:0 0 14px}
.appicon::after{content:"";position:absolute;inset:0;border-radius:inherit;
  pointer-events:none;
  background:linear-gradient(157deg,rgba(255,255,255,.16) 0%,rgba(255,255,255,.04) 26%,rgba(255,255,255,0) 46%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.30),
             inset 0 0 0 .5px rgba(255,255,255,.15),
             inset 0 -1px 0 rgba(255,255,255,.06)}
@media (prefers-color-scheme: light){
  .appicon{box-shadow:0 14px 30px rgba(23,21,20,.22),0 2px 6px rgba(23,21,20,.14)}
}

/* The AirMouse room borrows the app's typography: the product is a piece of
   software with SF on its screens, and a Didot headline was arguing with it. */
.room--ui{--ui:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text",Inter,system-ui,sans-serif}
.room--ui .serif,.room--ui .room-title,.room--ui .sub{font-family:var(--ui);
  font-weight:600;letter-spacing:-0.021em}
/* O rotulo em mono e a legenda sao a casa a nomear a sala, nao a app a
   falar: ficam na voz da casa. A face da app leva o lead, os paragrafos, as
   listas, as palavras e os botoes, que e onde o clima da sala vive. */
.room--ui .lead,.room--ui p,.room--ui li,
.room--ui .word,.room--ui h3,.room--ui .btn{font-family:var(--ui)}

/* The icon sits beside the name, a shade taller than the letters. In em, so it
   tracks the title as it scales down. */
/* Inline, não flex: em flex o título inteiro é um único item, e "Her Next
   Move" ao partir para duas linhas deixava o ícone sozinho numa linha só dele.
   Assim o ícone é a primeira coisa da primeira linha e o texto quebra à volta
   dele, como qualquer letra. */
.title-mark{display:block}
.appicon--title{display:inline-block;vertical-align:-0.19em;
  width:1.02em;height:1.02em;margin:0 .26em 0 0}

/* Platform marks on the download buttons. currentColor rather than white:
   the button owns its foreground, and the icon should never disagree with the
   label beside it. */
.btn-os{width:1.15em;height:1.15em;flex:0 0 auto;display:block}

/* This block's layout used to be inline styles, which this site's CSP drops
   on the floor. */
/* The first-open note. macOS refuses an app it has not seen notarised, and
   until the ticket arrives the two-click way past it belongs next to the
   button, not in a support page nobody opens. Remove this block and the <p>
   in air-mouse.html together once notarisation lands. */
.dl-note{margin:18px 0 0;max-width:52ch;font:400 0.8125rem/1.55 var(--body);color:var(--room-ink-3)}
.dl-note strong{font-weight:600;color:var(--room-ink)}
.dl-qr-row{display:flex;gap:28px;align-items:flex-start;flex-wrap:wrap;margin-top:38px}
/* O SVG tem viewBox, logo escala sozinho. Fixo a 296px dentro de uma coluna
   de 272 fazia a pagina rolar 32px de lado a 320. */
.dl-qr{flex:0 1 auto;max-width:100%;padding:14px;border:1px solid currentColor;border-radius:16px;opacity:.85}
.dl-qr svg{width:100%;height:auto;display:block}
.dl-qr-text{flex:1 1 260px;min-width:240px}
.dl-qr-text h3{margin:0 0 8px}
.dl-qr-text p{margin:0 0 14px}
.dl-qr-text p:last-child{margin:0}

/* This phone is a device in three-quarter view, not a flat screenshot: it is
   proportionally narrower than the capture in room 01, so matching widths
   would leave it visibly shorter. Matched on height instead. */
.room--ui .shot .device{width:min(321px, 67vw)}
/* The old file carried a wide transparent margin that happened to space the
   caption away from the phone; the crop took it with it. This puts the gap
   back deliberately, wide enough to clear the drop shadow, and centres the
   device in its column now that it no longer fills the width. */
.room--ui .shot{align-items:center}
/* The caption sits clear of the drop shadow. This belongs to every device
   shot, not just the one it was first written for: with it on one room only,
   the two rooms had 16px and 46px of breathing room and did not match. */
.shot figcaption { margin-top: 30px; }


/* ====================================================================
   The catalogue. A list, not cards: the brand has few products and a
   grid of three boxes would pad it out to look like more than it is.
   ==================================================================== */
.catalogue { list-style: none; margin: 0; padding: 0; }
.catalogue li {
  border-top: 1px solid var(--hairline); padding: 28px 0;
  display: grid; gap: 6px 32px; align-items: baseline;
  grid-template-columns: 44px minmax(160px, 1fr);
  grid-template-areas: "n name" ". what" ". plat" ". state";
}
.catalogue li:last-child { border-bottom: 1px solid var(--hairline); }
.catalogue .eyebrow { grid-area: n; }
.cat-name {
  grid-area: name; font-family: var(--display); font-weight: 700;
  font-size: clamp(1.5rem, 3vw, 2.25rem); letter-spacing: -0.02em;
  line-height: 1.1; color: var(--ink);
}
/* Tres portas, e nao tres posicoes de scroll. A ligacao era 4,3% da linha e
   sem sublinhado em repouso, portanto num ecra tatil nao havia nada que
   dissesse que aquilo era tocavel. */
.catalogue li { position: relative; }
.cat-name a { color: inherit; text-decoration: underline;
  text-decoration-color: var(--hairline); text-decoration-thickness: 1px;
  text-underline-offset: 6px; }
.cat-name a:hover { color: var(--accent); text-decoration-color: currentColor; }
.cat-name a::after { content: ""; position: absolute; inset: 0; }
.cat-name--muted { color: var(--ink-3); }
.cat-what { grid-area: what; margin: 0; max-width: 48ch; }
.cat-plat { grid-area: plat; font: 400 0.8125rem/1.6 var(--mono); color: var(--ink-3); }
.cat-state {
  grid-area: state; justify-self: start; margin-top: 6px;
  font: 400 0.75rem/1 var(--mono); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3); border: 1px solid var(--hairline);
  border-radius: 999px; padding: 7px 12px;
}
/* Only one state is a fact you can act on today, so only that one is filled. */
.cat-state--live { color: var(--ink); border-color: transparent; background: var(--highlight); }
:root[data-theme="dark"] .cat-state--live { color: #101014; }
.catnote { margin-top: 32px; color: var(--ink-3); }
.catnote em { font-style: normal; color: var(--ink-2); }

@media (min-width: 1024px) {
  .catalogue li {
    grid-template-columns: 44px minmax(200px, 300px) minmax(0, 1fr) auto;
    grid-template-areas: "n name what state" ". plat what state";
    gap: 4px 40px; align-items: start; padding: 32px 0;
  }
  .cat-state { justify-self: end; align-self: center; margin-top: 0; }
  .cat-what { align-self: center; }
}

/* ------------------------------------------------------- o topo, ao telemóvel
   Estas regras ficam no fim de propósito: `header.top nav` está definido mais
   acima com a mesma especificidade, e uma media query não ganha por ser media
   query. Escrita antes, era simplesmente ignorada.

   A 390px o cabeçalho partia-se em três linhas, com o botão de tema sozinho na
   última. Agora são duas: a marca com o botão de tema à direita, e os links por
   baixo. */
@media (max-width: 674px) {
  header.top { position: relative; padding: 18px var(--gutter) 14px; gap: 8px; }
  header.top nav { width: 100%; gap: 14px; font-size: 0.9375rem; }
  header.top nav .btn--ghost { padding: 8px 16px; }
  header.top nav .themetoggle { position: absolute; top: 14px; right: var(--gutter); }
  /* Os quatro links mais o botão não cabem numa linha a 390px, e uma terceira
     linha era pior do que a falta de um atalho. As Notes saem daqui e ficam no
     rodapé da mesma página; o catálogo e o contacto é que têm de estar à mão. */
  header.top nav > a[href$="/notes"] { display: none; }
}

/* ── The AirMouse room, in the app's own surface language ───────────
   The product went monochrome and fill-only; the page follows it, so the
   two read as one thing rather than as a page about a thing.

   Scoped to .room--ui. The rest of the site keeps the warm
   paper palette and their contours. This is the AirMouse room's voice, not
   a new house style.

   Depth here is the same two lights the app uses: a hairline gradient along
   the top edge, and a wide low-opacity shadow underneath. No borders. The
   rim needs a masked pseudo-element because CSS has no gradient
   `strokeBorder`; the mask paints the gradient into a one-pixel frame and
   punches the middle out. */
.room--ui{
  --room-stage:#0E0E0F;
  --room-ink:#F5F5F4;
  --room-ink-2:rgba(245,245,244,.62);
  --room-ink-3:rgba(245,245,244,.52);
  --room-line:rgba(255,255,255,.06);
  --am-surface:#1A1A1C;
  --am-elevated:#27272A;
  --am-radius:16px;
}

.room--ui .steps li,
.room--ui .dl-qr{
  position:relative;
  background:var(--am-surface);
  border:0;
  border-radius:var(--am-radius);
  box-shadow:0 12px 26px rgba(0,0,0,.32);
}
.room--ui .steps li::before,
.room--ui .dl-qr::before{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  padding:1px;
  pointer-events:none;
  background:linear-gradient(180deg,
    rgba(255,255,255,.09), rgba(255,255,255,.02) 26%, transparent 46%);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask-composite:exclude;
}

/* Steps were separated by rules. Cards separate themselves. */
.room--ui .steps{gap:12px}
.room--ui .steps li{padding:20px 22px}
.room--ui .steps li:last-child{border-bottom:0}
.room--ui .dl-qr{opacity:1;padding:16px}

/* The refusals list keeps its editorial rhythm. It is prose, not a control
   surface, and boxing it would flatten the one place the page slows down. */

/* Buttons answer a press the way the app does: a small, quick settle. */
.room--ui .btn{transition:transform .18s cubic-bezier(.2,.7,.3,1),background-color .18s ease}
.room--ui .btn:active{transform:scale(.97)}
.room--ui .btn--light{background:#EDEDEC;color:#0E0E0F}
.room--ui .btn--light:hover{background:#fff}

/* Neutral shadow under the icon: the warm one belonged to the old palette. */
.room--ui .appicon{box-shadow:0 14px 34px rgba(0,0,0,.45),0 3px 8px rgba(0,0,0,.30)}

@media (prefers-reduced-motion: reduce){
  .room--ui .btn{transition:none}
  .room--ui .btn:active{transform:none}
}

/* ====================================================================
   The AirMouse feature list. A disclosure list, not an accordion widget:
   `<details>` opens without JavaScript, announces itself to a screen
   reader without being told, survives printing, and the browser already
   handles the keyboard. Nothing here does anything the element does not.

   `name="airmouse-feature"` makes them exclusive, so opening one closes
   the last and the section stays a list you are reading down rather
   than a page you have unfolded to four screens tall.
   ==================================================================== */
/* Estava a repetir `max-width`, `margin: 0 auto` e a goteira dentro de uma
   `.inner` que ja tem as tres, por isso o titulo desta seccao ficava 56px mais
   adentro do que o titulo da pagina e do que as outras duas seccoes. E era a
   unica fronteira da sala sem filete. */
.u-feats { max-width: none; margin: clamp(64px, 8vw, 112px) 0 0;
  padding: clamp(48px, 6vw, 64px) 0 0; border-top: 1px solid var(--room-line); }
/* The room is dark and the default heading ink is the light theme's, which on
   this background is all but invisible. The other sections inherit the dark
   ink from a utility class; this one says so out loud. */
.u-feats .sub { color: var(--room-ink); }
.feat-lead {
  margin: 14px 0 clamp(28px,4vw,44px); max-width: 46ch;
  font-size: clamp(1rem, 1.6vw, 1.125rem); line-height: 1.55; color: var(--room-ink-2);
}

.feats { border-top: 1px solid var(--room-line); }
.feat { border-bottom: 1px solid var(--room-line); }

/* The whole row is the control. A summary is a button already, so it
   needs no role and no tabindex, only the marker taken off, which every
   engine spells differently. */
.feat > summary {
  display: grid; grid-template-columns: var(--feat-num, 1.25rem) minmax(0, 1fr) auto; align-items: baseline;
  gap: 0 clamp(16px, 2.5vw, 32px);
  padding: clamp(18px,2.4vw,26px) 0; cursor: pointer; list-style: none;
  transition: opacity var(--instant);
}
.feat > summary::-webkit-details-marker { display: none; }
/* O `opacity` compunha a linha inteira e levava o numeral de 5,30:1 para
   3,26. So o titulo tem folga para escurecer. */
.feat > summary:hover .feat-title { opacity: 0.72; }
.feat > summary:hover .feat-mark { opacity: 0.72; }
.feat > summary:focus-visible { outline: 2px solid var(--room-ink); outline-offset: 4px; border-radius: 4px; }

.feat-n {
  font-family: var(--mono); font-size: 0.75rem; letter-spacing: 0.08em;
  color: var(--room-ink-3); font-variant-numeric: tabular-nums;
}
.feat-title {
  font-family: var(--ui); font-weight: 600; letter-spacing: -0.021em;
  font-size: clamp(1.125rem, 2.2vw, 1.625rem); line-height: 1.25; color: var(--room-ink);
}

/* A cross that becomes a minus. Two rules, one rotated: cheaper than an
   icon font and it animates the only property that costs nothing. */
.feat-mark { position: relative; display: block; width: 15px; height: 15px; align-self: center; }
.feat-mark::before, .feat-mark::after {
  content: ""; position: absolute; inset: 50% 0 auto 0; height: 1.5px;
  background: var(--room-ink-2); transform: translateY(-50%);
  transition: transform var(--smooth), opacity var(--smooth);
}
.feat-mark::after { transform: translateY(-50%) rotate(90deg); }
.feat[open] .feat-mark::after { transform: translateY(-50%) rotate(0deg); opacity: 0; }

/* Words left, the app itself right. The screenshot is given a column of
   its own rather than floated: at this width a float leaves the last
   paragraph wrapping round a corner of a phone, which reads as a
   mistake. */
.feat-body {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
  gap: clamp(20px, 3vw, 48px);
  padding: 0 0 clamp(26px,3.4vw,40px);
  align-items: start;
}
/* Um so token para as duas bordas. 0,75rem era o corpo do numeral e nao o
   avanco dele, por isso cada paragrafo comecava 4,33px a esquerda do titulo
   que tem por cima, na unica lista do site cujo alinhamento e a ideia toda. */
.room--ui, .room--yet { --feat-num: 1.25rem; }
.feat-words { padding-left: calc(var(--feat-num, 1.25rem) + clamp(16px, 2.5vw, 32px)); max-width: 54ch; }
.feat-words p { margin: 0; font-size: clamp(0.9375rem,1.5vw,1.0625rem); line-height: 1.6; color: var(--room-ink-2); }
.feat-note { margin-top: 14px !important; color: var(--room-ink-3) !important; font-size: 0.9375rem !important; }

.feat-shot {
  width: 100%; height: auto; display: block; justify-self: end;
  border-radius: 20px;
  /* No border: the image carries its own rounded corner and the phone's
     own black. A hairline on top of that reads as a second frame. */
  box-shadow: 0 24px 48px rgba(0,0,0,.45);
}

/* Opening animates, once, and only what is free to animate. `details`
   has no transition of its own, so this runs on the body when it
   appears. */
@media (prefers-reduced-motion: no-preference) {
  .feat[open] .feat-body { animation: feat-open 260ms cubic-bezier(0.16, 1, 0.3, 1) both; }
}
@keyframes feat-open { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* 900 e nao 720: a 721px as palavras caem para 273px de medida, uns 31
   caracteres por linha, e o painel cresce de 478 para 1058px de altura. */
@media (max-width: 900px) {
  /* The picture goes under the words. Side by side at this width the
     phone is 120px across and shows nothing. */
  .feat-body { grid-template-columns: 1fr; }
  .feat-words { padding-left: 0; }
  .feat-shot { justify-self: start; max-width: 300px; }
}


/* ============================================================ consulting
   Página própria, com clima próprio. Não é o papel da marca nem o quase-preto
   das salas de produto: um azul-tinta, que se distingue dos dois pelo matiz e
   não só pela luminância. Medido antes de escolhido: o texto está a 15,9:1
   sobre o fundo, o acento a 9,2:1, e a transparência mais fraca a 4,8:1.

   O tema fixa-se aqui, como nas salas: uma página de serviço não muda de cara
   com o interruptor de tema da casa. */
:root {
  --cs-ground:  #0E1626;
  --cs-raise:   #131D30;
  --cs-ink:     #EDF1F7;
  --cs-ink-2:   rgba(237, 241, 247, 0.74);
  --cs-ink-3:   rgba(237, 241, 247, 0.62);
  --cs-line:    rgba(237, 241, 247, 0.14);
  --cs-accent:  #E3B23C;
}
body.consult { background: var(--cs-ground); color: var(--cs-ink-2); }
body.consult .top { color: var(--cs-ink); }
body.consult .top nav a { color: var(--cs-ink-2); }
body.consult .top nav a:hover { color: var(--cs-ink); }
body.consult .wordmark { color: var(--cs-ink); }
body.consult .btn--ghost { color: var(--cs-ink); border-color: rgba(237,241,247,0.24); }
body.consult .btn--ghost:hover { background: rgba(237,241,247,0.08); }
body.consult .skip { background: var(--cs-ink); color: var(--cs-ground); }

.consult .wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.cs-eyebrow { color: var(--cs-ink-3); }

/* o brilho é o que impede o azul de ler como uma folha de papel pintada */
.cs-hero, .cs-contact { position: relative; isolation: isolate; overflow: clip; }
.cs-glow {
  pointer-events: none;
  position: absolute; inset: -20% -10% auto -10%; height: 120%; z-index: -1;
  background:
    radial-gradient(760px 460px at 78% 6%, rgba(227, 178, 60, 0.16), transparent 68%),
    radial-gradient(620px 420px at 8% 34%, rgba(120, 160, 255, 0.14), transparent 70%);
}
.cs-glow--low { inset: auto -10% -30% -10%; height: 90%; }

.cs-hero { padding: clamp(72px, 11vw, 152px) 0 clamp(64px, 9vw, 120px); }
.cs-title {
  font-family: var(--display); font-weight: 800;
  font-size: clamp(2.9rem, 8vw, 6.4rem); line-height: 0.98;
  letter-spacing: -0.035em; color: var(--cs-ink); margin: 18px 0 0;
}
.cs-lead {
  margin: 28px 0 0; max-width: 62ch;
  font: 400 clamp(1.0625rem, 1.5vw, 1.3125rem)/1.62 var(--body); color: var(--cs-ink-2);
}
.cs-actions { margin-top: 40px; display: flex; flex-wrap: wrap; align-items: center; gap: 14px 28px; }
.cs-btn {
  display: inline-flex; align-items: center; gap: 10px;
  background: var(--cs-accent); color: #17130A;
  font: 600 1.0625rem var(--body); border-radius: 999px; padding: 16px 32px;
  transition: transform var(--instant), filter var(--quick);
}
.cs-btn:hover { filter: brightness(1.06); text-decoration: none; }
.cs-btn:active { transform: scale(0.98); }
.cs-quiet {
  color: var(--cs-ink); text-decoration: underline;
  text-decoration-color: rgba(237,241,247,0.4); text-underline-offset: 4px;
}
.cs-quiet:hover { text-decoration-color: var(--cs-accent); }

.cs-band { padding: clamp(56px, 8vw, 104px) 0; border-top: 1px solid var(--cs-line); }
.cs-band--edge { background: var(--cs-raise); }
.cs-h2 {
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.9rem, 4vw, 3.1rem); line-height: 1.06;
  letter-spacing: -0.025em; color: var(--cs-ink); margin: 0;
}
.cs-prose { margin: 0; color: var(--cs-ink-2); font-size: 1.0625rem; line-height: 1.62; max-width: 62ch; }
.cs-split { display: grid; gap: 28px 56px; margin-top: 24px; }
@media (min-width: 900px) { .cs-split { grid-template-columns: 1fr 1fr; align-items: start; } }

.cs-ways { list-style: none; margin: 32px 0 0; padding: 0; display: grid; gap: 0; }
.cs-ways li {
  align-items: baseline;
  display: grid; grid-template-columns: auto 1fr; gap: 8px 28px;
  padding: 28px 0; border-top: 1px solid var(--cs-line);
}
.cs-ways li:first-child { border-top: none; }
/* Sem `padding-top`: o numeral flutuava porque o titulo ao lado herdava a
   entrelinha do corpo, 1,6, e os 6px eram um remendo a olho. */
.cs-num { font: 400 0.8125rem var(--mono); color: var(--cs-ink-3); letter-spacing: 0.1em; }
.cs-ways h2 {
  grid-column: 2; margin: 0 0 8px; color: var(--cs-ink);
  font-family: var(--display); font-weight: 700; font-size: clamp(1.35rem, 2.4vw, 1.85rem);
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.cs-ways p { grid-column: 2; margin: 0; color: var(--cs-ink-2); line-height: 1.6; max-width: 60ch; }

.cs-audit { padding: clamp(64px, 9vw, 120px) 0; border-top: 1px solid var(--cs-line); background: var(--cs-raise); }
.cs-grid { display: grid; gap: 18px; margin-top: 44px; }
@media (min-width: 720px) { .cs-grid { grid-template-columns: 1fr 1fr; } }
.cs-card {
  border: 1px solid var(--cs-line); border-radius: 14px; padding: 24px;
  background: rgba(237, 241, 247, 0.03);
}
.cs-card p { margin: 10px 0 0; color: var(--cs-ink-2); line-height: 1.58; }
.cs-note { margin: 32px 0 0; color: var(--cs-ink-3); font-size: 0.9375rem; }

.cs-spec { margin: 32px 0 0; display: grid; gap: 0; }
.cs-spec > div {
  display: grid; gap: 4px 32px; padding: 18px 0; border-top: 1px solid var(--cs-line);
}
@media (min-width: 720px) { .cs-spec > div { grid-template-columns: 220px 1fr; align-items: baseline; } }
.cs-spec dt {
  font: 400 0.75rem var(--mono); text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--cs-ink-3);
}
.cs-spec dd { margin: 0; max-width: 62ch; color: var(--cs-ink-2); line-height: 1.55; }

.cs-contact { padding: clamp(72px, 10vw, 136px) 0 clamp(56px, 8vw, 96px); border-top: 1px solid var(--cs-line); }
.cs-mail {
  display: inline-block; margin: 24px 0 20px; color: var(--cs-accent);
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.5rem, 4.6vw, 3rem); letter-spacing: -0.02em;
  text-decoration: underline; text-underline-offset: 6px;
  text-decoration-color: rgba(227, 178, 60, 0.45);
}
.cs-mail:hover { text-decoration-color: var(--cs-accent); }

body.consult .footmark p { color: var(--cs-ink); }
.cs-footer { border-top: 1px solid var(--cs-line); }
.cs-footer .eyebrow, .cs-footer nav a { color: var(--cs-ink-3); }
.cs-footer nav a:hover { color: var(--cs-ink); }

/* O aviso de copia herda a cor do papel; no azul da consultoria ficava
   ilegivel. */
body.consult .copied { color: var(--cs-ink-3); }
body.consult .copied.on { color: var(--cs-accent); }


/* ====================================================================
   Mais duas salas. A estrutura é a mesma da sala do AirMouse (título com
   ícone, promessa, passos numerados, o aparelho ao lado, recusas, estado);
   o que muda de sala para sala é só o clima, porque um catálogo em que
   tudo se parece foi desenhado por ninguém.

   Cada sala vai buscar a lei da própria app. O que está aqui são os
   valores dessa lei, não uma paleta inventada para o site.
   ==================================================================== */

/* ------------------------------------------------------------ YET
   Superfícies quentes quase acromáticas, tinta em três níveis e um só
   acento, mulberry. A lei da app gasta uma tipografia inteira a separar
   as palavras do documento das da app: aqui o serif aparece uma vez só,
   na citação, e mais lado nenhum. */
/* A sala da YET media 1,032:1 contra o papel da pagina: entrava-se nela sem
   se dar por isso. As outras duas estao a 18:1. Um filete em cima e em baixo,
   na cor da regua da propria sala, marca a soleira sem lhe mudar o chao, que
   e o #F8F6F2 que a lei da app pede. */
.room--yet{
  --ui:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text",Inter,system-ui,sans-serif;
  --room-stage:#F8F6F2;
  --room-ink:#2D2A25;
  --room-ink-2:#6F6C66;
  /* A lei pousa a tinta terciária em #8F8C85, que sobre esta tela mede
     3,11:1. Na app ela carrega metadados grandes; aqui carrega eyebrows de
     12px em maiúsculas, e a 3,11 essas não se leem. Escurecida até 5,14,
     no mesmo matiz quente. */
  --room-ink-3:#6B6862;
  --room-line:rgba(45,42,37,.12);
  --yet-raised:#FFFFFF;
  --yet-sunken:#EFECE7;
  --yet-accent:#A82C8E;
}
.room--yet .room-title,.room--yet .sub,.room--yet .serif{font-family:var(--ui);
  font-weight:600;letter-spacing:-0.021em}
.room--yet .lead,.room--yet p,.room--yet li,
.room--yet .word,.room--yet h3,.room--yet .btn{font-family:var(--ui)}
/* A excepção, e a única: os caracteres que o documento imprimiu. */
.room--yet .quote{font-family:var(--serif);font-weight:400;letter-spacing:0}

/* Linhas com a mesma altura e a mesma silhueta: o sossego desta app vem do
   ritmo, não do ar entre as coisas. */
.room--yet .steps{gap:10px}
.room--yet .steps li{background:var(--yet-raised);border:1px solid var(--room-line);
  border-radius:14px;padding:20px 22px}
.room--yet .steps li:last-child{border-bottom:1px solid var(--room-line)}
.room--yet .shade--room{background:
  radial-gradient(680px 460px at 84% 8%, rgba(168,44,142,.055), transparent 66%),
  radial-gradient(520px 380px at 6% 92%, rgba(45,42,37,.045), transparent 70%)}
.room--yet .btn--light{background:var(--room-ink);color:var(--room-stage)}
.room--yet .btn--light:hover{background:#1C1A16}
.room--yet .quiet--light{color:var(--room-ink);text-decoration-color:rgba(45,42,37,.35)}
.room--yet .quiet--light:hover{text-decoration-color:var(--yet-accent)}
.room--yet .appicon{box-shadow:0 14px 30px rgba(23,21,20,.20),0 2px 6px rgba(23,21,20,.12)}
.room--yet .shot .device{filter:drop-shadow(0 30px 50px rgba(45,42,37,.18))}
.room--yet .btn{transition:transform .18s cubic-bezier(.2,.7,.3,1),background-color .18s ease}
.room--yet .btn:active{transform:scale(.97)}

/* O cartão de prova: o facto que a app escreveu, e por baixo os caracteres
   de onde o leu. É o argumento inteiro da app numa caixa. */
.proof{margin:clamp(28px,3.5vw,40px) 0 0;background:var(--yet-raised);
  border:1px solid var(--room-line);border-radius:16px;overflow:hidden;max-width:520px}
.proof-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 18px;padding:18px 22px}
.proof-row + .proof-row{border-top:1px solid var(--room-line)}
.proof-label{flex:1 1 auto;font:400 .75rem var(--mono);letter-spacing:.12em;
  text-transform:uppercase;color:var(--room-ink-3)}
.proof-value{font-weight:600;font-size:1.375rem;font-variant-numeric:tabular-nums;
  color:var(--room-ink)}
/* `.room p` tem um elemento na selecao e esta classe nao tinha nenhum, por isso
   a tinta secundaria da sala ganhava e a citacao saia a 4,44:1 sobre o degrau
   afundado. A citacao e a coisa mais forte do cartao: e ela que prova o numero
   por cima. Qualificada com `.room` para empatar em especificidade e ganhar
   pela ordem. */
.room .proof-quote{margin:0;padding:18px 22px;background:var(--yet-sunken);
  border-top:1px solid var(--room-line);font-size:1.0625rem;line-height:1.5;
  color:var(--room-ink)}
.proof-quote span{display:block;margin-bottom:8px;font:400 .75rem var(--mono);
  letter-spacing:.1em;text-transform:uppercase;color:var(--room-ink-3)}

/* A ilustração da YET: a folha à esquerda, a linha que a app escreve à
   direita, e um fio de um total impresso até ao valor que ela escreveu. */
.yt-fig{display:block;width:100%;height:auto}
.room--yet .shot .yt-fig{width:min(560px,88vw)}

/* --------------------------------------------------- her next move
   O palco da app é #0C0B0A, um preto com desvio quente, e o que separa dois
   planos é 1,06:1 de luminância mais um filete a 7%, nunca uma sombra. A app
   gasta o orçamento de cor todo na fotografia; aqui é a captura que a traz. */
.room--hnm{
  --room-stage:#0C0B0A;
  --room-ink:#F2EFEA;
  --room-ink-2:#B8B2A8;
  --room-ink-3:#8A847B;
  --room-line:rgba(242,239,234,.10);
  --hn-surface:#141311;
}
.room--hnm .steps{gap:10px}
.room--hnm .steps li{background:var(--hn-surface);
  border:1px solid rgba(242,239,234,.07);border-radius:20px;padding:20px 22px}
.room--hnm .steps li:last-child{border-bottom:1px solid rgba(242,239,234,.07)}
.room--hnm .btn--light{background:var(--room-ink);color:var(--room-stage)}
.room--hnm .btn--light:hover{background:#fff}
.room--hnm .btn{transition:transform .18s cubic-bezier(.2,.7,.3,1),background-color .18s ease}
.room--hnm .btn:active{transform:scale(.97)}
.room--hnm .appicon{box-shadow:0 14px 34px rgba(0,0,0,.5),0 3px 8px rgba(0,0,0,.34)}

/* O anel de foco, por clima. Medido contra o fundo de cada um. */
.room--ui  { --ring: var(--room-ink); }   /* 17,1:1 sobre #0E0E0F */
.room--hnm { --ring: var(--room-ink); }   /* 17,1:1 sobre #0C0B0A */
.room--yet { --ring: var(--yet-accent); } /* 5,7:1 sobre #F8F6F2 */
body.consult { --ring: var(--cs-accent); }

/* ====================================================================
   Peças que a página da YET trouxe, e que qualquer sala pode usar.

   A YET não tem capturas de ecrã para mostrar: o reconhecedor de texto da
   Apple não arranca no simulador, por isso ninguém a fotografou ainda a
   trabalhar. O que ela tem são diagramas desenhados à medida, e um diagrama
   não é um aparelho: não leva a sombra que faz um telemóvel pairar, porque
   essa sombra num desenho lê-se como um autocolante.
   ==================================================================== */
.figs { align-items: stretch; width: 100%; }
.fig { display: block; width: 100%; height: auto; }
.figs figcaption { text-align: left; margin-top: 18px; text-transform: none;
  letter-spacing: 0; font-family: var(--body); font-size: 0.9375rem; }
/* Uma figura larga sai da coluna e ocupa a medida toda da sala. */
.figs--wide { max-width: 720px; margin-top: clamp(28px, 3.5vw, 40px); }

/* Prosa que precisa de um título por parágrafo. Duas colunas onde há espaço,
   porque quatro parágrafos seguidos com a mesma medida são uma parede. */
.notes { display: grid; gap: clamp(28px, 3.5vw, 44px) clamp(32px, 4vw, 64px);
  margin-top: clamp(28px, 3.5vw, 40px); }
@media (min-width: 900px) { .notes { grid-template-columns: 1fr 1fr; } }
.note h3 { margin: 0 0 8px; font: 600 1.0625rem/1.35 var(--body); color: var(--room-ink); }
.note p { margin: 0; max-width: 52ch; }

/* A lista de funcionalidades numa sala clara. A régua e a tinta já vêm dos
   tokens da sala; o que não vinha era a sombra da captura, calibrada para o
   quase-preto, e o corpo sem imagem, que deixava uma coluna vazia à direita. */
.room--yet .feat-shot { box-shadow: 0 18px 34px rgba(45,42,37,.16); }
.feat-body:not(:has(.feat-shot)) { grid-template-columns: minmax(0, 1fr); }
.feat-words p + .feat-note { margin-top: 14px; }

/* Um diagrama curto ao lado de uma lista alta deixava dois terços da coluna
   vazios e a figura pequena lá em cima. Preso, acompanha a leitura dos seis
   passos e a coluna deixa de ser um vão.

   `align-self: stretch` é o que dá curso ao sticky: a grelha alinha os filhos
   ao topo, e um filho da altura do seu conteúdo não tem por onde deslizar. */
@media (min-width: 900px) {
  .figs--stick { align-self: stretch; justify-content: flex-start; }
  .figs--stick .figs-hold { position: sticky; top: clamp(24px, 9vh, 104px); }
}

/* As três coisas que um visitante deve levar da página, no cimo e não
   diluídas por dezasseis funcionalidades.

   Tokens da sala e não do site: um `.tile` aqui dentro traria a superfície do
   tema por baixo de uma sala que fixa a sua, e no tema escuro daria um cartão
   escuro sobre papel claro. O filete entre as três é o fundo a aparecer por um
   `gap` de 1px, que é como o resto do site separa coisas: nem sombra, nem
   moldura. */
.headline { list-style: none; margin: clamp(36px, 5vw, 56px) 0 0; padding: 0;
  display: grid; gap: 1px; background: var(--room-line);
  border: 1px solid var(--room-line); border-radius: 16px; overflow: hidden; }
@media (min-width: 860px) { .headline { grid-template-columns: repeat(3, 1fr); } }
.headline li { background: var(--room-stage); padding: 26px 26px 30px;
  display: flex; flex-direction: column; gap: 10px; }
.headline .n { font: 400 0.75rem var(--mono); letter-spacing: 0.12em; color: var(--room-ink-3); }
.headline strong { font: 600 1.0625rem/1.35 var(--body); color: var(--room-ink); }
.headline p { margin: 0; font-size: 0.9375rem; line-height: 1.56; color: var(--room-ink-2); max-width: 40ch; }

/* A soleira da sala clara. */
.room--yet { border-top: 1px solid var(--room-line); border-bottom: 1px solid var(--room-line); }

/* O endereco dentro de uma sala. `.mail` foi escrito para o papel da casa e
   pinta-se com o acento do site, que numa sala nao existe. A classe do copiar
   e a mesma, porque o app.js liga-se a `.mail`. */
.roommail {
  display: inline-block; margin: 4px 0 0;
  font-family: var(--display); font-weight: 700;
  font-size: clamp(1.4rem, 4vw, 2.6rem); letter-spacing: -0.02em;
  line-height: 1.15; color: var(--room-ink); overflow-wrap: anywhere;
  text-decoration: underline; text-underline-offset: 6px;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
}
.roommail:hover { text-decoration-color: currentColor; }
.room--yet .roommail { color: var(--yet-accent); }
.room--yet .roommail:hover { color: var(--yet-accent); }

/* ====================================================================
   A régua de margem.

   Cada secção do site abre da mesma maneira: um rótulo em mono a 13px e, por
   baixo dele, o título. O rótulo está a fazer o trabalho de um cabeçalho
   corrente mas vive dentro do bloco de texto, por isso lê-se como uma primeira
   linha pequena em vez de aparato.

   O site já faz isto três vezes por dentro: o catálogo pendura um numeral a
   44px ao lado da linha, um passo pendura 56, a ficha técnica pendura um `dt`.
   Pendurar o rótulo da secção ao lado do título é a mesma ideia um nível
   acima, e é o que faz uma página de dez mil pixéis ler-se como um documento.

   152px é a medida do rótulo mais comprido do site: HOW IT GETS BUILT mede
   150px de tinta a 13px de JetBrains Mono com 0,08em de espacejamento.

   Dupla classe de propósito: `utilities.css` carrega depois desta folha e
   `.u-573a89` põe `display:flex`; uma regra de uma classe só perdia o empate.

   Só nas secções de prosa. Numa lista ou numa tabela a régua rouba 208px de
   medida à coluna que carrega a frase, e era o catálogo que pagava.
   ==================================================================== */
@media (min-width: 1024px) {
  .wrap.wrap--rail {
    display: grid;
    grid-template-columns: 152px minmax(0, 1fr);
    column-gap: 56px;
    align-items: start;
  }
  .wrap.wrap--rail > * { grid-column: 2; }
  .wrap.wrap--rail > .eyebrow:first-child { grid-column: 1; grid-row: 1; }

  /* Dentro de uma régua, duas metades iguais desperdiçam a largura que a régua
     acabou de comprar e põem um título de 72px em meia página. Um documento
     põe o título à medida toda e o texto numa coluna mais estreita do que ele:
     é isso que dá forma ao bloco. */
  .wrap--rail .split { display: block; }
  .wrap--rail .split > .stack24 { max-width: 56ch; margin-top: 24px; }
  .wrap--rail .cs-split { display: block; }
  .wrap--rail .cs-split > * + * { max-width: 62ch; margin-top: 24px; }
}

/* Sete dos dez titulos da lista de funcionalidades acabavam numa palavra
   sozinha a 375px, e uma palavra sozinha debaixo de uma linha de 36 ou 48px e
   a coisa mais alta do ecra de um telemovel. */
.hero-title, .display, .h2, .manifesto h2, .cat-name,
.room h1.room-title, .room h2.serif, .room h2.serif.sub, .room h3.serif,
.feat-title, .refusals .word, .room .steps h3, .headline strong,
.cs-title, .cs-h2, .cs-ways h2, .doc h2 { text-wrap: balance; }
.prose, .lead, .cat-what, .catnote, .cs-prose, .cs-lead,
.feat-words p, .room .steps p, .doc p, .headline p { text-wrap: pretty; }

/* Tres pilulas de larguras diferentes empilhadas a esquerda de um bloco de
   1173px liam-se como uma lista irregular. Uma fila, com as tres iguais. */
.dl-row { align-self: stretch; max-width: 760px; display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.dl-row .btn { width: 100%; justify-content: center; }

/* O interruptor de tema no clima azul-tinta, onde o da casa nao se ve. */
body.consult .themetoggle { color: var(--cs-ink-2); border-color: rgba(237,241,247,.24); }
body.consult .themetoggle:hover { background: rgba(237,241,247,.08); color: var(--cs-ink); }
