/* ==========================================================================
   Duminguz home -- DGZ_homePage2

   Figma kTQ4xLTJJ16sMcs4JTvRRg, node 2348:246. Authored at 1920 x 1080.

   FLUID, since 2026-09-23. Three rebuilds got here and the last two matter:

     1. a fixed 16:9 stage that scaled whole, like a poster;
     2. a full-viewport stage with the composition ANCHORED to the edges but
        still positioned in absolute design-pixel coordinates;
     3. this -- a flow layout whose spacing is a set of RELATIONSHIPS.

   Why (2) was not enough: its vertical rhythm was still fixed numbers, so a
   window of a different height left a hole in the middle or crushed the top
   and bottom, and its unit followed `min(vw, vh)`, which shrank the type when
   a window got shorter. Type has left that unit entirely -- it is fluid on its
   own terms in brand.css -- and what remains on `--dgz-u` is drawing: the
   frame border and the mark.

   THE COST, accepted knowingly: the page no longer reproduces the frame pixel
   for pixel. It matches at the reference size and holds the relationships
   everywhere else. Five of the six pages in the Ronaldo plan carry
   variable-length content and could never have been fixed compositions, so
   this system was needed regardless.

   THE LAYOUT IS THE ART DIRECTOR'S. Reproduce it; do not "improve" it here.
   ========================================================================== */

:root {
  /* Frame_window is drawn in orchid, a brandbook colour. Confirmed from the
     file 2026-09-23: `border: 20px solid #A24795`. */
  --hero-frame: var(--dgz-orchid);
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body.dgz-hero {
  margin: 0;
  background: var(--dgz-ink);
  color: #fff;
  font-family: var(--dgz-font-body);
  overflow: hidden;
}

/* --------------------------------------------------------------------------
   The stage -- the viewport
   -------------------------------------------------------------------------- */
.stage {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: 100dvh;                  /* so a mobile browser's chrome cannot clip it */
  overflow: hidden;
  background: var(--dgz-ink);

  /* THE RENDERED HEIGHT OF THE ARTWORK -- the vertical coordinate system.

     João, 2026-09-23: "o texto precisa permanecer na proporcao relativa a
     altura, com relacao a imagem, ou seja, alinhado ao topo. Se a imagem
     reduz o tamanho, a distancia entre os objetos reduz proporcionalmente."

     `cover` scales the art by max(vw/1920, vh/1080), so its rendered height
     is max(56.25vw, 100vh). Because it is anchored to the top, a block at
     design y sits at `y/1080 * --img-h` from the top of the window. The
     headline keeps its place across the character's hair, and the gaps
     between blocks shrink with the ARTWORK rather than with the window.

     VERTICAL ONLY. Horizontal stays on the viewport, because on a window
     narrower than the art's aspect the art is cropped at the SIDES, and
     anything anchored to the painting's left or right edge is cropped with
     it -- which is exactly what happened on the first attempt. */
  --img-h: max(56.25vw, 100vh);

  /* Side inset, on the window. Floor so it survives a phone, fluid middle,
     the design's 260 as the ceiling. */
  --pad: clamp(1.25rem, 9vw, 16.25rem);

  /* Top and bottom content margin -- ONE value, measured from the INSIDE of
     the frame, used by both ends. João: "a margem de conteudo superior e
     inferior devem ser iguais."

     It is deliberately a single custom property rather than two matching
     numbers: two numbers that happen to agree drift the first time one of
     them is tuned, and this pair is the thing the eye checks first on a
     framed composition. The roles line and the foot are the two blocks that
     belong to the FRAME rather than to the painting, which is why they share
     it while the headline and the mark stay anchored to the artwork. */
  --edge: clamp(1rem, 5vh, 3.5rem);
}

/* The art covers from the TOP, centred horizontally, growing with the width. */
.stage__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  opacity: .8;
  pointer-events: none;
}

/* Frame_window / Rectangle -- inset 0, a 20px border, over everything.
   No asset. The file states a plain border, and a border scales exactly and
   re-colours in one line, where an SVG has to be re-exported for either. The
   two corner details (Detail1, Details2) are drawn vectors and are NOT here
   yet -- see DuminguzHUB/portfolio/duminguz-art/ui/components.md section 3. */
.stage__frame {
  position: absolute;
  inset: 0;
  border: calc(20 * var(--dgz-u)) solid var(--hero-frame);
  pointer-events: none;
  z-index: 2;
}

/* Detail1 and Details2 -- the two drawn corner vectors, exported 2026-09-23.

   They sit at OPPOSITE corners, which is why the straight runs between them
   are the Rectangle border rather than drawn: Detail1 is filled and holds the
   top left, Details2 is outline only and holds the bottom right. Boxes are
   the SVGs' own, in design pixels, so they ride --dgz-u with the border. */
.stage__details {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 3;
}

.stage__detail {
  position: absolute;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

/* Detail1 -- filled, top left */
.stage__detail--a {
  left: calc(6 * var(--dgz-u));
  top: calc(6 * var(--dgz-u));
  width: calc(165 * var(--dgz-u));
  height: calc(469 * var(--dgz-u));
  background-image: url("../img/hero/frame-detail-a.svg");
}

/* Details2 -- outline only, bottom right */
.stage__detail--b {
  right: calc(3 * var(--dgz-u));
  bottom: calc(50 * var(--dgz-u));
  width: calc(330 * var(--dgz-u));
  height: calc(516 * var(--dgz-u));
  background-image: url("../img/hero/frame-detail-b.svg");
}

/* --------------------------------------------------------------------------
   The foot -- pinned to the WINDOW, not to the painting

   The only part of the composition that is not canvas-relative, and it is a
   deliberate exception. On a window shorter than 16:9 the backdrop is cropped
   at the bottom, so anything positioned against the artwork down there leaves
   the screen with it. An email address and three profile links that scroll out
   of reach are a bug, not a composition.
   -------------------------------------------------------------------------- */
.stage__foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(20 * var(--dgz-u) + var(--edge));
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(.75rem, 1.6vh, 2.25rem);
}

/* --------------------------------------------------------------------------
   Type

   Every block takes a NAMED STYLE from the scale in brand.css. Nothing here
   sets a size, a weight or a tracking -- only position and colour.
   -------------------------------------------------------------------------- */

.stage__roles,
.stage__pitch h1,
.stage__pitch p,
.stage__mail {
  margin: 0;
  color: #fff;
}

/* --------------------------------------------------------------------------
   Positions

   Vertical: a share of `--img-h`, so it tracks the artwork.
   Horizontal: the window, via `--pad`.
   -------------------------------------------------------------------------- */

/* Caption_DGZ, centred at the top.

   It belongs to the FRAME, not to the painting: it sits in the band between
   the purple bar and the top of the character's hair, so it is measured from
   the border rather than as a share of the artwork. Anchoring it to the art
   pushed it down on a short window, which read as too much padding. */
.stage__roles {
  position: absolute;
  top: calc(20 * var(--dgz-u) + var(--edge));
  left: var(--pad);
  right: var(--pad);
  text-align: center;
  text-wrap: balance;
}

/* Holds the left edge of the window; its height follows the artwork. */
.stage__pitch {
  position: absolute;
  left: var(--pad);
  top: calc(23.8 * var(--img-h) / 100);     /* 257 / 1080 */
}

/* EVERY break in this block is authored with <br>, and nothing here wraps.

   Third time this has been paid for. Relying on a box width to produce a
   break means the break belongs to the font metrics, not to the design:
   Chakra Petch re-broke it once by setting 1.5x wider than TT Carvist, and
   `text-wrap: balance` -- inherited from the h1 rule in brand.css -- re-broke
   it again by splitting the lines evenly instead of greedily. With `nowrap`,
   a face that stops fitting overflows visibly instead of quietly recomposing
   the headline. */
.stage__pitch {
  white-space: nowrap;
  text-wrap: nowrap;
  color: #fff;
}

/* H2_DGZ. Two blocks with a gap, not one wrapped line: the break after
   "pixels..." is authored, and the second half is the one set in sky blue.

   The gaps are in `em` now rather than design pixels, so they scale with the
   type they separate rather than with the window. That is what keeps the
   block reading as one thing at every size. */
.stage__pitch h1 > span {
  display: block;
}

.stage__pitch-b {
  margin-top: .75em;
  color: var(--dgz-blue);
}

.stage__pitch p {
  margin-top: 1em;
}

/* Duminguz_Logo_Colored. Three stacked groups, which is how the neon is built
   -- they are not duplicates. It is drawing, so it rides --dgz-u and is capped
   at the size it was drawn, with a floor so it does not vanish. */
/* Holds the right edge of the painting, and its size is a share of the
   painting too, so it keeps its place against the artwork rather than against
   the window. */
.stage__logo {
  position: absolute;
  right: var(--pad);
  top: calc(21.8 * var(--img-h) / 100);     /* 235 / 1080 */
  /* Sized off the artwork too, so it keeps its scale against the painting.
     Capped in `vh` because it is a drawing: one that does not fit the window
     should shrink, where a paragraph should not. */
  width: min(calc(47.2 * var(--img-h) / 100), 42vh);
  aspect-ratio: 1;
}

.stage__logo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.stage__mail {
  text-decoration: none;
  white-space: nowrap;
}

.stage__mail:hover,
.stage__mail:focus-visible { color: var(--dgz-blue); }

/* --------------------------------------------------------------------------
   The three buttons -- the Empty family of the button component set.

   ALL THREE ARE IDENTICAL. The frame draws LinkedIn differently because it is
   demonstrating the hover state on one of them, not because that button is
   special -- confirmed by Joao 2026-09-23.

   The state IS the colour: the set encodes rest, hover and pressed as three
   colours rather than three shades of one, and the same sequence runs through
   every button type. Nothing here changes size or position, so the row never
   shifts under the cursor.
   -------------------------------------------------------------------------- */
.stage__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(1.5rem, 7.5vw, 9rem);
}

/* Empty -- at rest */
.stage__links a {
  position: relative;
  text-decoration: none;
  color: var(--dgz-blue);
  transition: color .2s ease;
}

/* EmptyHover -- the type takes the accent and a vector underlines it.
   Focus gets the same treatment: on a frameless button the hover state is the
   only thing that says "this is a link", so a keyboard visitor needs it too. */
.stage__links a:hover,
.stage__links a:focus-visible { color: var(--dgz-clay); }

/* The underline -- `ButtonLine.svg`, exported 2026-09-23. It is ONE colour
   with a step in it, not the two-toned rule read off the component-set
   screenshot: a short high run on the left, a diagonal, then a long low run.
   `aspect-ratio` holds that 201:8 proportion, so the step keeps its angle at
   every size instead of flattening.

   Drawn always and revealed by state, so it is not fetched at the moment the
   cursor arrives. */
.stage__links a::after {
  content: "";
  position: absolute;
  left: -6%;
  right: -10%;
  top: calc(100% + .18em);
  aspect-ratio: 201 / 8;
  background: url("../img/hero/button-line.svg") no-repeat center / 100% 100%;
  opacity: 0;
  transition: opacity .2s ease;
}

.stage__links a:hover::after,
.stage__links a:focus-visible::after { opacity: 1; }

/* EmptyPressed -- while the click is HELD, and nothing else. `:active` is the
   whole implementation: it cannot persist after release, which is exactly what
   a toggled class would get wrong.

   COLOUR IS PROVISIONAL: the `response` role, orchid. The set draws
   EmptyPressed in a magenta visibly hotter than orchid and its hex has not
   been read yet -- one line when it is. */
.stage__links a:active { color: var(--dgz-orchid); }

/* --------------------------------------------------------------------------
   Portrait -- DGZ_homePageMOBILE, Figma 2350:481.

   His own 9:16 frame, not a reflow of the landscape one: the pitch is right
   aligned and the mark drops below it rather than sitting beside it.
   -------------------------------------------------------------------------- */
@media (max-aspect-ratio: 1 / 1) {
  .stage {
    /* The mobile frame is authored at 1080 wide, so a design pixel is 1/1080
       of the viewport rather than 1/1920. */
    --dgz-u: clamp(0.34px, 0.0925926vw, 1px);
    /* The 9:16 art covers by max(vw/1080, vh/1920). */
    --img-h: max(177.7778vw, 100vh);
    --pad: clamp(1rem, 7.4vw, 5rem);
  }

  /* The frame rotates 90 rather than being drawn twice. João: "ao mudar o
     layout para versao mobile, o frame gira 90 graus." The border is uniform
     and therefore rotation-invariant, so only the details turn: the box is
     laid out landscape and spun, which is exact because 1920x1080 rotated is
     1080x1920 with no remainder. */
  .stage__details {
    inset: auto;
    top: 50%;
    left: 50%;
    width: 100vh;
    height: 100vw;
    transform: translate(-50%, -50%) rotate(90deg);
  }

  /* The pitch holds the RIGHT edge here, not the left. */
  .stage__pitch {
    left: auto;
    right: var(--pad);
    top: calc(17.4 * var(--img-h) / 100);
    text-align: right;
    /* On a phone the authored lines can be wider than the screen, so the one
       place the block is allowed to wrap is here -- clipped type would be
       worse than a re-broken line. */
    white-space: normal;
    text-wrap: nowrap;
  }

  .stage__logo {
    left: auto;
    right: var(--pad);
    top: calc(46.1 * var(--img-h) / 100);
    width: min(40vw, 30vh);
  }

  /* At the readable floor this line is wider than a phone, so it wraps. A
     legible size that wraps beats a composed line nobody can read. */
  .stage__roles {
    top: calc(5.5 * var(--img-h) / 100);
    white-space: normal;
  }
}

@media (prefers-reduced-motion: reduce) {
  .stage__links a,
  .stage__links a::after,
  .stage__mail { transition: none; }
}
