/* uraeus.pt — page rules. Behaviour only; every value comes from the tokens.
   Anything that hides an element is gated behind the .js class that motion.js adds,
   so the page renders completely with JavaScript disabled. */

/* the documented page cap: past 1680px the page padding grows so the CONTENT column caps
   at --max-page while full-bleed photographs, the nav band and the footer keep bleeding
   edge to edge. Never a boxed page. */
@media (min-width:1680px){
  :root{--page-pad:calc((100vw - var(--max-page))/2 + 64px)}
}

/* The nav band is fixed and 84px tall, so every in-page anchor was landing with its own heading
   underneath it. All eleven of them target one of these five ids. #top resolves to a negative
   offset and clamps to 0, which is where it was going anyway. */
#top,#work,#process,#studio,#contact{scroll-margin-top:84px}

/* hero heights with a fallback for browsers without svh */
.hero{min-height:78vh}
.hero.hero-tall{min-height:92vh}
@supports (min-height:1svh){
  .hero{min-height:78svh}
  .hero.hero-tall{min-height:92svh}
}

/* 44px touch targets with no visual change: a centred, invisible hit extension */
.hit{position:relative}
.hit::after{content:"";position:absolute;left:50%;top:50%;width:max(100%,44px);height:max(100%,44px);transform:translate(-50%,-50%)}

/* photographs on hover: the paper is nudged, never lit */
.js .ph img,.js img.ph{transition:transform var(--dur-reveal) var(--ease-paper)}
.js .ph:hover img,.js img.ph:hover{transform:scale(1.025)}
@media (prefers-reduced-motion:reduce){
  .js .ph img,.js img.ph{transition:none}
  .js .ph:hover img,.js img.ph:hover{transform:none}
}

/* small hand-drawn marks: a 4-frame "boil" (flipbook wiggle), ~3fps.
   Frame 1 shows statically without JS; reduced motion freezes on frame 1. */
.sketch-boil g{opacity:0}
.sketch-boil g:first-child{opacity:1}
.js .sketch-boil g{animation:uraeus-boil 1.2s steps(1,end) infinite}
.js .sketch-boil g:nth-child(2){animation-delay:-.9s}
.js .sketch-boil g:nth-child(3){animation-delay:-.6s}
.js .sketch-boil g:nth-child(4){animation-delay:-.3s}
@keyframes uraeus-boil{0%{opacity:1}25%{opacity:0}}
@media (prefers-reduced-motion:reduce){.js .sketch-boil g{animation:none}}

/* the same boil on the handwritten blue words (BoilWord in Hero.jsx): five stacked instances
   of the word, per-letter re-set, cycled as a flipbook. Frame 1 shows without JS. */
.boil-word{position:relative;display:inline-block}
.boil-word>span{white-space:pre;display:inline-block}
.boil-word>span+span{position:absolute;left:0;top:0;opacity:0}
.boil-word .bl{display:inline-block}
.js .boil-word>span{animation:uraeus-boil5 1.5s steps(1,end) infinite}
.js .boil-word>span:nth-child(2){animation-delay:-1.2s}
.js .boil-word>span:nth-child(3){animation-delay:-.9s}
.js .boil-word>span:nth-child(4){animation-delay:-.6s}
.js .boil-word>span:nth-child(5){animation-delay:-.3s}
@keyframes uraeus-boil5{0%{opacity:1}20%{opacity:0}}
@media (prefers-reduced-motion:reduce){.js .boil-word>span{animation:none}}

/* Type over a full-bleed photograph. The banner's own left-to-right scrim stays light, so the
   photograph keeps its brightness; the readable contrast comes from a pool of shade sitting
   directly behind the words, fading out on every axis. No edge, no panel, no container. */
.banner-shade{position:relative}
/* The box the pool is drawn in. It used to be -60%/-30%/-70%/-70%, which is 190% of the text
   block wide and 240% tall — the shade reached most of the way across the photograph and far
   above and below the words, which is what made it read as a dark panel rather than as protection
   for the type. This box is 136% x 168%, so the falloff still has room to be soft but the dark
   part stays behind the text. */
.banner-shade::before{content:"";position:absolute;left:-22%;right:-14%;top:-34%;bottom:-34%;
  z-index:-1;pointer-events:none;background:var(--banner-shade)}
/* On a narrow column the text fills more of the width, so the pool has to widen with it.
   Only the geometry moves; the shade's colour stops stay in tokens/surfaces.css. */
@media (max-width:899px){
  :root{--banner-shade-w:100%;--banner-shade-h:72%;--banner-shade-x:44%}
}

/* The handwritten blue word inside a banner standfirst gets its own pool of light — the same
   device as the banner shade, inverted. It is needed because Uraeus Blue is a dark hue: measured
   against the photograph it sat at 1.1:1, and no amount of lightening the shade or stacking a
   text-shadow fixes that (a shadow plateaus below 2:1). A wash does, because it lifts the ground
   the word sits on rather than trying to outline the word.
   Falls away on every axis, so there is no edge and no panel. isolation:isolate keeps the -1
   behind the word instead of behind the banner shade.

   --banner-word-wash is the strength, 0 to 1, and it is 0 by default: the lighter shade alone was
   enough for the studio, and at full strength the pool reads as a light patch behind the word.
   Set it to 1 in tokens/surfaces.css to turn the pool on. Nothing else changes. */
.blue-on-photo{position:relative;isolation:isolate}
.blue-on-photo::before{content:"";position:absolute;left:-.55em;right:-.55em;top:-.34em;bottom:-.26em;
  z-index:-1;pointer-events:none;
  background:radial-gradient(ellipse 56% 52% at 50% 50%,
    rgba(244,230,205,calc(.97 * var(--banner-word-wash,0))) 0%,
    rgba(244,230,205,calc(.88 * var(--banner-word-wash,0))) 30%,
    rgba(244,230,205,calc(.66 * var(--banner-word-wash,0))) 52%,
    rgba(244,230,205,calc(.34 * var(--banner-word-wash,0))) 74%,
    rgba(244,230,205,calc(.10 * var(--banner-word-wash,0))) 89%,
    rgba(244,230,205,0) 100%)}

/* Moved verbatim out of the inline <style> block in index.html, which sat immediately after this
   file's own <link> — appended here so it keeps exactly that position in the cascade. It is here
   rather than inline so the Content-Security-Policy needs no hash and no 'unsafe-inline' for
   stylesheets. The grain overlay lives in this block; it is not decoration, it is the page. */
html{scroll-behavior:smooth}
body{margin:0;overflow-x:hidden;position:relative}
body::after{content:"";position:fixed;inset:0;pointer-events:none;z-index:90;background-image:var(--grain)}
a{border-bottom:0}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
