/* ==========================================================================
   GeoTopX — geotopx.io, what this page adds on top of the prototype's sheet.

   estilos-letreiro.css carries the prototype's own layout and is loaded first.
   This file adds the frame the owner asked to bring over from the previous
   holding page - a rule at the top, a rule under the mark, and a rule under
   the ticker - and themes the browser surfaces the prototype left at their
   defaults.

   Dark only, and committed rather than defaulted: the use scene is a screen
   somebody watches for a moment, and the ticker's whole legibility is built on
   a near-black ground.

   THE PAGE IS ONE SCREEN AND MUST STAY ONE SCREEN. The body is a flex column
   with overflow hidden, so anything added here takes its height out of the
   hero. Header and footer are deliberately shallow, and the paragraph is the
   first thing to go when the viewport is short - the sentence above it already
   carries the meaning, and the ticker is what the page exists to show.
   ========================================================================== */

:root {
  --moldura-ink: #c9d5e2;
  --moldura-muted: #7f8c99;
  --moldura-line: rgba(255, 255, 255, 0.105);
  --moldura-ground: rgba(3, 6, 10, 0.72);
}

/* ------------------------------------------------------- 1. as duas bordas */

.borda {
  flex: 0 0 auto;
  position: relative;
  z-index: 3;
  border-bottom: 1px solid var(--moldura-line);
  background-color: var(--moldura-ground);
}

.borda--pe {
  border-bottom: 0;
  border-top: 1px solid var(--moldura-line);
}

/*
 * The inset grows with the window instead of stopping at 2rem.
 *
 * The max-width only bites above 76rem, so between a phone and a 1216-pixel
 * window the only thing holding these two lines off the edge was the padding.
 * The ticker runs edge to edge by design, and these lines are the only margin
 * the composition has.
 *
 * Halved twice on the owner's reading: 6, 8, 12 and 16, from 24, 32, 48 and
 * 64.
 *
 * The padding adds to the max-width's inset rather than disappearing into it,
 * and it is worth stating because the opposite is the natural guess: with
 * border-box the padding sits INSIDE the 76rem box, so the text lands at
 * (viewport - 1216) / 2 + padding. At 1440 that is 128 pixels, not 144, and at
 * 1920 it is 368, not 384. Every width moves when these values move.
 */
.borda__linha {
  width: 100%;
  max-width: 76rem;
  margin-inline: auto;
  padding: 0.5rem 0.375rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.25rem 1.5rem;
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--moldura-muted);
}

@media (min-width: 30rem) {
  .borda__linha {
    padding-inline: 0.5rem;
  }
}

@media (min-width: 48rem) {
  .borda__linha {
    padding-inline: 0.75rem;
    font-size: 0.8125rem;
  }
}

@media (min-width: 64rem) {
  .borda__linha {
    padding-inline: 1rem;
  }
}

.borda__linha p {
  margin: 0;
}

.borda__dominio {
  color: var(--moldura-ink);
  font-weight: 600;
  letter-spacing: 0.01em;
}

.borda__estado {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

/*
 * The one live signal in the frame. It is small and far from the ticker's own
 * indicator - opposite corners of the screen - so the two do not compete.
 */
.pulso {
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 999px;
  background-color: #91ffd0;
  box-shadow: 0 0 0 0 rgba(145, 255, 208, 0.5);
  animation: pulso 2.8s cubic-bezier(0.22, 1, 0.36, 1) infinite;
}

@keyframes pulso {
  0% {
    box-shadow: 0 0 0 0 rgba(145, 255, 208, 0.5);
  }

  55%,
  100% {
    box-shadow: 0 0 0 0.5rem rgba(145, 255, 208, 0);
  }
}

/* The previous holding page silenced this dot when the visitor asks for less
   motion and this one had lost that, so the WebGL field stopped while a green
   ring kept expanding in the corner every 2.8 seconds. The dot stays; only its
   beating goes. */
@media (prefers-reduced-motion: reduce) {
  .pulso {
    animation: none;
  }
}

.borda__contato a {
  display: inline-flex;
  align-items: center;
  color: #91ebff;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.28em;
  text-decoration-color: rgba(145, 235, 255, 0.38);
  transition: color 150ms cubic-bezier(0.22, 1, 0.36, 1),
              text-decoration-color 150ms cubic-bezier(0.22, 1, 0.36, 1);
}

.borda__contato a:hover {
  color: #c4f3ff;
  text-decoration-color: currentColor;
}

/* ------------------------------------------------ 2. os dizeres sob a marca */

/*
 * The mark and the words are one object, centred as one, with the drawer
 * pinned below.
 *
 * The prototype has two rows: the mark in a flexible row 1, centred inside it,
 * and the drawer in row 2. Adding the words as a third row put them on top of
 * the Ajustes tab and 102 pixels below the mark, so they read as a caption for
 * the button rather than for the logo. Splitting the flexible space around
 * them instead only moved the problem: the pair drifted to the top of the
 * screen with a void underneath.
 *
 * Two siblings cannot be centred as one, so they are not siblings any more.
 * .bloco-central holds both, takes the flexible row, and centres itself in it.
 */
.brand-wrap {
  grid-template-rows: minmax(0, 1fr) auto;
}

/*
 * align-self: stretch is the whole fix for the drawer, and it is worth saying
 * why a one-word declaration was load-bearing.
 *
 * .brand-wrap carries align-items: center from the prototype, so this block was
 * not stretched to its row: its height came from its own content and it was
 * merely centred in whatever space the row had. Opening Ajustes grows row 2 and
 * shrinks row 1, but a content-sized block does not shrink with it - at 900x600
 * the row went 355 to 167 while the block stayed 343 and overflowed 88 pixels
 * above and 88 below, putting the words through the panel and the mark off the
 * top of the screen. Twelve of eighteen viewports did this.
 *
 * Stretching makes the row's height the block's height, and a definite height
 * is what the mark's max-height: 100% needs to mean anything. Without it that
 * percentage resolved against a height derived from the mark itself, which is
 * circular and caps nothing - the same trap that once let the mark run into the
 * ticker, fixed then with a viewport-unit ceiling that treats the symptom.
 */
.bloco-central {
  grid-row: 1;
  align-self: stretch;
  height: 100%;
  /* min-height 0 is what lets the mark's max-height:100% shrink it on a short
     screen instead of pushing the ticker off the bottom. */
  min-height: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.geotopx-logo {
  /* Inside a flex column now: the prototype's grid placement no longer
     applies, and the width rules it carries still do. */
  flex: 0 1 auto;
  min-height: 0;
  /* Now measured against the row rather than against the mark's own content.
     contain keeps the drawing whole while the box gives up height: the box
     stays as wide as the design asks and the transparent margin it leaves sits
     over the same dark ground, so nothing shows. */
  max-height: 100%;
  object-fit: contain;
}

.dizeres {
  position: relative;
  z-index: 3;
  /*
   * The rule tracks the mark's own width so it reads as underlining the logo
   * rather than as a box drawn around the text.
   *
   * The mark is min(70vw, 920px), so the rule follows the same 70vw and the
   * same ceiling - a flat 58rem was 928 pixels against a 700-pixel mark on a
   * 1000-pixel screen, and the overhang looked like a mistake. The 21rem floor
   * is for phones, where 70vw is 273 pixels and a rule that narrow would
   * squeeze the sentence into five lines; down there reading wins over
   * alignment.
   */
  width: min(100%, max(21rem, min(58rem, 70vw)));
  /* Close to the mark on purpose: this is the gap that says the two belong
     together. Everything loose goes into the flexible rows instead. */
  margin: clamp(1rem, 2.4vh, 1.75rem) auto 0;
  padding: clamp(0.875rem, 2vh, 1.5rem) 1.5rem 0;
  text-align: center;
  /* The rule the owner asked for, under the mark and above the words. It is
     the width of the text rather than of the screen because the composition
     is centred: a full-width rule under a centred block reads as a divider
     between sections, which these are not. */
  border-top: 1px solid var(--moldura-line);
  /* Nothing here may sit over the drag surface of the ticker. */
  pointer-events: none;
}

.dizeres a {
  pointer-events: auto;
}

/*
 * The two sizes are the ones the previous page used, read off it in a browser
 * rather than remembered: 34px and 16px at 1440, 22.65px and 15px at 390, both
 * at weight 400. Rebuilding this page I had shrunk the first to 19px - a
 * reduction of 44% - and the owner read it as a caption instead of a
 * statement, which at that size it was.
 *
 * Neither page has ever rendered the face it names. This one asks for Inter
 * and the previous one for Archivo, and no font file is published by either,
 * so both fall back to the same ui-sans-serif. The difference the eye caught
 * was size, never family.
 */
.dizeres__conducao {
  /* Its own measure inside a wider rule: the previous page held this sentence
     to 30 characters and it rendered 550 pixels across, which is the shape it
     was written for. */
  max-width: 30ch;
  margin: 0 auto;
  font-size: clamp(1.375rem, 1.05rem + 1.5vw, 2.125rem);
  line-height: 1.28;
  letter-spacing: -0.02em;
  font-weight: 400;
  text-wrap: balance;
  color: #e4ecf5;
}

.dizeres__detalhe {
  margin: clamp(0.75rem, 1.6vh, 1.25rem) auto 0;
  max-width: 62ch;
  /* 15px on a phone, 16px from 48rem up: the previous page's values. */
  font-size: 0.9375rem;
  line-height: 1.65;
  /* balance, not pretty. Centred text makes an uneven rag obvious, and pretty
     only protects the last line - this block was ending on two words under
     four full ones. balance evens every line of a short block, which is what
     this is. */
  text-wrap: balance;
  /* Lifted off the prototype's --muted: that value is tuned for the small
     labels inside the ticker, where the ground is darker than it is here. */
  color: #9fadbc;
}

.dizeres__detalhe abbr {
  text-decoration: none;
  border-bottom: 1px dotted rgba(255, 255, 255, 0.22);
  cursor: help;
}

.dizeres__detalhe i {
  font-style: italic;
}

@media (min-width: 48rem) {
  .dizeres__detalhe {
    font-size: 1rem;
  }
}

.controls-drawer {
  grid-row: 2;
}

/* ------------------------------------------- 3. quando a tela é baixa demais */

/*
 * A short screen is not a small screen, and this is the failure that proves
 * it: at 1280x800 the block ran straight through the Ajustes tab and into the
 * ticker. The width keeps feeding the type scale while the height that must
 * hold the mark, the words, the tab, the ticker and two rules does not, and a
 * wide-but-short window is the most common laptop there is.
 *
 * The budget at 1280x800, measured in the browser rather than derived: the two
 * rules take 35 pixels each and the ticker 133, leaving 597 for the hero. The
 * mark is 252 and the words with the paragraph want 323 on top of the gaps, so
 * something has to go, and it is the paragraph: the sentence above it carries
 * the meaning, and the ticker is what the page exists to show.
 *
 * The ticker figure is the one to re-read before touching these thresholds. Its
 * height is set from JavaScript and follows the Top-N the visitor picks: 133 at
 * Top-1, which is where the page loads, and up to 245 at Top-5. The prototype's
 * stylesheet still declares 214 and that value never reaches the screen.
 *
 * The thresholds are in rem, not pixels, and deliberately: the type, the gaps
 * and the widths are all in rem, so a visitor who enlarges their root text grew
 * everything the budget has to hold while a pixel threshold stayed put and kept
 * the paragraph on a screen with no room for it. At the default 16-pixel root
 * these three numbers are still 860, 780 and 560.
 */
@media (max-height: 53.75rem) {
  .dizeres__detalhe {
    display: none;
  }
}

/*
 * Shorter still, and the sentence itself gives up a size step. At 1280x720 the
 * hero is 517 pixels - 720 less the two 35-pixel rules and the 133-pixel
 * ticker - and the mark with the sentence at full size wanted more of it than
 * the composition can spare.
 */
@media (max-height: 48.75rem) {
  /*
   * And the mark itself yields, on a ceiling in viewport units.
   *
   * The reason has changed since this rule was written, and it is worth saying
   * so. It went in because max-height:100% was measured against a box whose
   * height came from the mark itself - circular, clamping nothing, which is how
   * the mark once stayed 265 pixels tall at 1440x620 and ran 18 pixels into the
   * Ajustes tab. .bloco-central now has a definite height, so that percentage
   * finally means the row and the circularity is gone.
   *
   * The viewport ceiling stays anyway, for a different job: it is what shapes
   * the resting composition on a short screen, holding the mark to a third of
   * the height so the sentence under it has room. The row is the second bound,
   * and it only binds while the drawer is open.
   *
   * width:auto lets the box hug the shrunken image instead of letterboxing it
   * inside the old width, and the rule under the mark follows the same ceiling
   * so it keeps matching what it underlines.
   */
  .geotopx-logo {
    width: auto;
    /* Both ceilings, not one. 34vh is the resting composition on a short
       screen and stays exactly as it was; 100% is the row, and it only binds
       while the drawer is open, when the row is smaller than 34vh. Written as
       a single max-height because the later declaration would otherwise
       replace the earlier one outright. */
    max-height: min(100%, 34vh);
  }

  .dizeres {
    width: min(100%, max(21rem, min(58rem, 70vw, 118vh)));
  }

  .dizeres__conducao {
    font-size: clamp(1.125rem, 0.95rem + 0.9vw, 1.625rem);
    max-width: 34ch;
  }

  .dizeres {
    margin-top: clamp(0.5rem, 1.4vh, 0.875rem);
    padding-top: clamp(0.625rem, 1.4vh, 1rem);
  }
}

@media (max-height: 35rem) {
  .dizeres {
    display: none;
  }

  .borda__estado {
    display: none;
  }
}

/* ------------------------- 3b. quando nem uma tela inteira é suficiente */

/*
 * One screen is the rule, and here is the case where keeping it costs more than
 * it is worth.
 *
 * A landscape phone at 667x375 running Top-5 spends 245 pixels on the ticker and
 * 70 on the two rules, leaving 60 for everything else. The open drawer needs
 * 134. It was not merely cramped: .hero clips what does not fit, so the panel
 * and the drawer's own close tab were cut off the top of the screen and the
 * visitor was left with a control they could not shut. Measured at 667x375,
 * 740x360, 844x390 and 915x412.
 *
 * No arrangement fits 134 pixels into 60. So on a screen this short, and only
 * while the drawer is actually open, the page stops being a fixed single screen
 * and scrolls - which is what every other page does when a viewport is too
 * small, and what the reflow rule asks for. Closing the drawer restores the
 * single screen, and no viewport that can hold the drawer ever scrolls: the
 * body only exceeds its height when the content genuinely does not fit.
 */
@media (max-height: 35rem) {
  body.gaveta-aberta {
    overflow-y: auto;
  }

  /*
   * min-content, not auto: the hero keeps taking the space that is left over,
   * and only refuses to go below what its contents actually need. Where the
   * drawer already fits - a short screen showing Top-1, say - nothing changes
   * and the page does not scroll. It grows past the screen only when the
   * contents genuinely do not fit, which is the moment scrolling is the right
   * answer rather than an annoyance.
   */
  body.gaveta-aberta .hero {
    min-height: min-content;
    overflow: visible;
  }

  body.gaveta-aberta .brand-wrap,
  body.gaveta-aberta .bloco-central {
    height: auto;
  }

  /* The mark keeps a share of the screen rather than the share of a box that no
     longer has a height of its own. */
  body.gaveta-aberta .geotopx-logo {
    max-height: 30vh;
  }

  /*
   * The ticker declares touch-action:none so its own horizontal drag is not
   * fought by the browser, and while the page never scrolled that cost nothing.
   * Now it does scroll, and the ticker covers most of a 360-pixel screen, so a
   * finger landing there could not move the page at all: the visitor was left
   * looking at a page that would not scroll where they were touching it.
   * pan-y hands vertical gestures back to the browser and leaves the horizontal
   * drag exactly as it was.
   */
  body.gaveta-aberta .ticker-viewport {
    touch-action: pan-y;
  }
}

/* ------------------------------- 3bis. o que a gaveta aberta pede emprestado */

/*
 * Stopping the overflow was not the same as making it look right.
 *
 * With the drawer open the mark is the only thing in the block that can give up
 * height, and it gave up all of it: measured on the published page, 103 pixels
 * tall at 900x600 and 345 at 1440x620, from 726 and 750. Nothing overlapped -
 * it had simply been squeezed to a smear while the words beside it kept every
 * pixel they had.
 *
 * So the words lend the space instead, in the order the page already uses when
 * it runs short. The paragraph goes first, always, because it is the part the
 * page gives up first anyway and a visitor working the controls is not reading
 * it. On a screen too short for both, the sentence goes as well - but only from
 * 48rem wide up: a narrow phone was never the problem, its mark does not shrink
 * at all, and taking the words there would cost something and buy nothing.
 *
 * Both rules are scoped to .gaveta-aberta, so the resting page never sees them.
 *
 * Measured with the drawer open, before and after: 1600x900 and 1440x900 keep
 * the mark whole at 920x258 instead of 920x160; 900x600 goes from 103x29 to
 * 597x168; 800x600 from 369x104 to 726x204; 1440x620 from 345x97 to 750x211.
 * No viewport loses anything it had.
 */
body.gaveta-aberta .dizeres__detalhe {
  display: none;
}

@media (min-width: 48rem) and (max-height: 41.25rem) {
  body.gaveta-aberta .dizeres {
    display: none;
  }
}

/* ----------------------------------------- 3c. o que só o leitor de tela lê */

/*
 * Out of sight, not out of the accessibility tree: display:none and
 * visibility:hidden would take it from the screen reader too, which is the one
 * audience it exists for.
 */
.apenas-leitor {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --------------------------------------------- 4. as superfícies do navegador */

::selection {
  background-color: rgba(145, 235, 255, 0.28);
  color: #f6f9fc;
}

/*
 * The two ticker speed buttons are named explicitly because loading later is
 * not enough to win: the prototype's own .ticker-speed-btn:focus-visible is one
 * class more specific, and source order only decides ties. Those two buttons
 * kept a 1-pixel translucent outline while every other control took the cyan
 * one, which is the difference between seeing where the focus is and not.
 */
:focus-visible,
.ticker-speed-btn:focus-visible {
  outline: 2px solid #91ebff;
  outline-offset: 2px;
  border-radius: 3px;
}

/*
 * hidden alone does nothing here. The prototype sets #glCanvas { display:block }
 * and an id beats the browser's own [hidden] { display:none }, so efeito.js
 * could mark the canvas hidden - on a WebGL failure, or when the visitor asks
 * for less motion - and the element stayed in the page: transparent after a
 * failure, or frozen on its last painted frame. The script's comment said the
 * canvas came out of the page. Now it does.
 */
#glCanvas[hidden] {
  display: none;
}

* {
  scrollbar-color: rgba(255, 255, 255, 0.16) transparent;
  scrollbar-width: thin;
}
