/* exp35 . section stylesheet owned by the herocopy builder.
   Tokens only, no hard-coded colours. All 7 themes.

   Scope: the hero COPY only. .hero-film, the herograph SVG, the HDR layers and
   the H1's prompt column are owned elsewhere and are not touched here. The
   film scrim is tuned against a .52-opacity graph; this file adds no scrim,
   no plate and no shadow to compensate. Contrast is held by the ink tokens
   below, which are the same measured figures hero-v2.css already uses. */


/* ==========================================================================
   1. THE SUBHEAD — the plan's sentence pair
   PLAN-35-IA §7 Section 1 replaces a 108-character line with a 152-character
   one. Left at exp33's 52ch measure that sets in four lines and pushes the
   CTA row down out of the one-viewport budget.
   Opening the measure to 64ch puts it back to three lines, so the whole
   change costs the band zero height. 64ch is inside the 68ch prose measure
   and lands just under the H1's own line length at 1440, so the size ramp
   still reads top-down instead of two blocks of equal width.
   CONTRAST IS TIGHTENED, NOT RELAXED. hero-v2.css sets .78 of the ink token,
   a figure measured against the theme GROUND (8.7:1 on paper, 10.5:1 on the
   near-blacks) before the herograph was raised to .52 opacity. Measured now
   against the painted pixels -- ground plus field plus graph plus scrim, worst
   pixel inside the text rects, at the verification beat -- the plan's longer
   sentence covers one more pixel of a graph card edge than exp33's shorter one
   did, and .78 lands at 6.94:1 on night. That pixel is fixed: it reads 6.94 at
   every measure from 52ch to 64ch, so it is the sentence, not the measure.
   .82 puts it at 7.35 and lifts brutal to 8.01 and acid to 7.61, with no theme
   made worse. No scrim, no plate and no shadow were added to buy it: the film
   scrim is tuned and belongs to the graph, not to this file.

   MEASURE IS NOW THE CRAFT LAYER'S TOKEN. Founder review item 14 sets a body
   measure of 50-62 characters. --measure-hero is the craft layer's own 58ch;
   the fallback below keeps that number if the layer is ever absent.
   THE SELECTOR CARRIES A THEME ATTRIBUTE FOR A REASON. themes.css sets
   `html[data-theme="terminal"] .hero-sub{max-width:62ch}`, which is (0,2,1) and
   therefore beat the old (0,2,0) `.hero33 .hero-sub{max-width:64ch}` outright:
   measured, the tube's subhead box was 772.46px = 62ch exactly, so the 64ch this
   file used to declare had never once applied on the site's default theme, and
   the paragraph above it describing a 64ch measure was describing a rule that
   lost. The pair below is (0,3,1) on every theme, attributed and unattributed,
   so the measure is now actually the measure.
   ========================================================================== */
html[data-theme] .hero33 .hero-sub,
html:not([data-theme]) .hero33 .hero-sub{max-width:var(--measure-hero,58ch);}
.hero33 .hero-sub{color:rgba(var(--ink-rgb),.82);}

/* ==========================================================================
   1b. THE MARK, INSIDE THE SENTENCE . TERMINAL ONLY
   Founder ruling: "in hero can you highlight word 'proof' in copy as our logo,
   and with hdr?" -- so the first word of the subhead is the WORDMARK, set where
   the sentence names the product, and not one word of prose that mysteriously
   got brighter.

   EVERYTHING HERE IS THE HEADER MARK'S OWN IDENTITY, QUOTED FROM ITS SOURCE.
   Nothing below was chosen for this element; each line is the declaration that
   already makes .wordmark look like .wordmark on the tube, with the file and the
   reason it exists:
     font-family  site.css `body{font-family:var(--prose)}`. .wordmark declares
                  no family, so --prose IS the mark's face. It is PINNED here
                  rather than inherited because themes.css
                  `html[data-font="bricolage"] .hero-sub` swaps the SUBHEAD's
                  face and does not swap the wordmark's -- inheriting would let
                  the visitor's font switch pull the mark off the mark.
     font-weight  site.css `.wordmark{font-weight:600}`, re-asserted by
                  themes.css `html[data-theme="terminal"] .wordmark`.
     text-transform  themes.css `html[data-theme="terminal"] .wordmark
                  {text-transform:uppercase}`. This is the tube's mark and the
                  tube's mark is caps. It transforms the RENDERING only: the
                  word stays `Proof` to selection, to find-in-page, to the
                  clipboard and to a screen reader.
     letter-spacing  themes.css `html[data-theme="terminal"] .wordmark
                  {letter-spacing:0}`. The subhead is already `normal`, so this
                  is a no-op today and a pin tomorrow: if the prose layer ever
                  takes tracking, the mark keeps the mark's.
   The EMISSION is not here. It is assets/hdr-event.css section 7.3, in the same
   declaration block as the wordmark's period, so the inline mark cannot drift
   off the period's tier, aperture, fallback or kill switch -- it is the same
   rule. See 7.5 there for why it rests and never flares.

   THE ONE NUMBER THAT IS NOT QUOTED IS THE SIZE, and it is an optical
   correction, not a new treatment. The header mark is 1.28rem beside 0.92rem
   nav links; inline it has to sit on the sentence's own baseline, at the
   sentence's own size, and all-caps at 1em beside lowercase reads oversized.
   Space Grotesk measured at the subhead's own 19.44px: cap height 13.61px
   (.700em), x-height 9.50px (.489em), ascender 13.61px. So at 1em every one of
   the five letterforms stands at the ascender line for the whole width of the
   word, at 600 weight, in the theme's saturated green -- one word carrying more
   vertical mass than any other word on the line. At .94em the caps come to
   12.79px, just under the ascenders of `builds`, and the line's colour evens
   out. Both were rendered and looked at; .94em is the one where the eye reads
   the sentence and recognises the mark, rather than reading the mark first.
   The word's advance goes 50.88px -> 56.98px, and the paragraph sets in the
   same three lines at the same 93.28px height, so the correction costs the
   hero band nothing.
   ========================================================================== */
html[data-theme="terminal"] .hero33 .hero-sub .hero-wm{
  font-family:var(--prose);
  font-weight:600;
  text-transform:uppercase;
  letter-spacing:normal;
  font-size:.94em;
  /* THE ELEMENT'S OWN RESTING COLOUR, declared for the same reason site.css
     declares `.wordmark .dot{color:var(--signal)}` and not for the shipped
     paint: hdr-event.css 7.3 fills the glyph through -webkit-text-fill-color,
     which wins, so this line is inert while background-clip:text works. It is
     what the glyph FALLS BACK to when it does not -- 7.3's @supports-not block
     returns the fill to currentColor, and currentColor has to be the mark's
     green rather than the sentence's ink, or a browser with no text clip would
     silently drop the highlight the founder asked for and leave a slightly
     heavier word. Same colour, same token, same green as the period. */
  color:var(--signal);
}


/* ==========================================================================
   2. PHONE
   The subhead gives up its measure cap entirely — hero-v2.css already
   top-weights the phone hero and sets the phone body size.
   ========================================================================== */
@media (max-width:760px){
  .hero33 .hero-sub{max-width:none;}
}


/* ==========================================================================
   3. THE BLOCK CURSOR, SYNCHRONISED WITH THE GRAPH . founder review item 4
   "normal green while idle; brief HDR/emissive flash when the graph begins;
   smooth phosphor decay rather than a hard flash. The subconscious message
   becomes: the statement just executed."

   hero-v2.css owns the cursor's geometry, its resting bloom and the transition
   that makes the fall a decay. This file owns the three things that had to be
   decided against files loaded EARLIER in the cascade, which is why they live
   here and not there:

   4.1 IDLE IS HDR, BY RULING, AND ONLY HERE.
       History, because this rule has been written twice and reversed once.
       assets/hdr-event.css section 7.1 painted this cursor from the PQ RESTING
       raster at all times, on the argument that a beam is always on the cursor.
       A pass through this file took it off, citing the brief's flat acceptance
       criterion -- "Nothing is HDR at rest" -- and left an SDR halo in its
       place, so the block was lit only during the ~90ms strike and its ~620ms
       fall. The founder, who wrote that brief, overruled that reading:
       "blinking cursor should use hdr all the time like before."
       So --pq-rest goes back on, with no class and no clock, and it is the only
       classless HDR carrier left in the build.

       WHY THIS ONE. A blinking cursor is the one element on the page that is
       CONTINUOUSLY ALIVE -- the page's idle animation, the tell that a machine
       is sitting at a prompt waiting. Luminance as a state channel says
       "computation is happening"; a caret that blinks says the machine is up.
       Those are different sentences and the page is entitled to both.
       IT IS NOT THE ONLY ONE. The founder's instruction names three carriers in
       one sentence -- "blinking cursor ... same as request demo and the proof
       logo" -- and the other two got their resting tier back at the same time,
       in hdr-event.css sections 7.2 and 7.3. What did NOT come back is anything
       he did not name: the hero action brackets (7.2b) and the tube's own h1
       cursor on the nine pages with no graph (7.1). The exception list is
       closed, it is three long, and it is written out at the top of
       hdr-event.css and on the --pq-rest token itself.

       WHAT IT COSTS IN SDR: nothing, measured. pq-term-rest decodes to
       (43,255,111) -- #2BFF6F at dE2000 0.000 -- which is exactly the --signal
       hero-v2.css already paints under it. See 4.3 for why the raster is TILED
       rather than stretched, which is what makes that "nothing" exact.

       WHAT IT COSTS IN EMISSION: the resting tile is 1000 nits nominal against
       the event tile's 10000, at the same chromaticity, and the blink halves
       the duty cycle on top of that. The strike is a decade above its own floor.

   4.2 THE EVENT KEEPS THE BASELINE. hdr-event.css section 1 used to restore
       transform:translateY(.1em) scaleX(1.14) during the flash -- the .1em was
       part of the old geometry and hero-v2.css has since deleted it, so leaving
       that rule alone would drop the block 7.36px off the baseline at the exact
       instant a visitor is looking at it. This file's event rule scales only,
       and the dead translate has now been removed at its source as well.

   4.3 THE RESTING RASTER IS STRETCHED, NOT TILED, AND IT IS NOT A STYLE
       PREFERENCE -- IT IS THE ONLY FORM THAT SURVIVES SDR DECODE.
       The tile is 8x8 and uniform, so `background-size:auto; repeat` looks like
       the safer way to fill a 29.44 x 51.52 block: no resampling, no edge blend
       against the outside of the texture. It is not. Measured, same page load,
       deviceScaleFactor 4, against the block painted from background-color
       alone:

         background-size:100% 100%; no-repeat   199 / 677376 bytes, max delta 2
         background-size:auto;      repeat    48455 / 677376 bytes, max delta 117

       and the tiled block does not come out green: it renders rgb(97,255,227),
       a cyan, against the rgb(43,255,111) underneath it. Chromium takes a
       different path for a repeated pattern than for a stretched draw, and the
       PQ -> sRGB decode this tile was solved for does not survive it. This is
       the same family of failure as tagging #2BFF6F naively and getting pure
       green back: with PQ media the decode is part of the declaration, and any
       change to how the image is drawn has to be re-measured, not reasoned about.

       So the resting raster is painted exactly the way the event paints it, and
       the 199 residual bytes are +/-1 rounding in the near-black pixels of the
       halo, not on the block: the caret's own pixels are byte-identical to the
       flat colour. Nothing about the resting frame moves in SDR.
   ========================================================================== */
html[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after{
  /* THE RESTING HDR TIER. 1000 nits nominal, over hero-v2.css's --signal
     background-color, which is the colour this tile decodes to in SDR.
     DO NOT change background-size or background-repeat here without re-running
     the A/B in 4.3 -- see the cyan. */
  background-image:var(--pq-rest);
  background-size:100% 100%;
  background-repeat:no-repeat;
}

/* the two beats that light the cursor. hb-wake is the graph WAKING (the founder's
   "when the graph begins"); hx-cursor is the graph's own verification beat,
   published by assets/herograph.js. Both land on the same treatment, because
   both mean the same thing: the machine just did something. */
html.hb-wake[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after,
html.hx-wake[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after,
html.hx-cursor[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after{
  animation:none;                 /* the blink stops: a half-lit block becomes lit */
  opacity:1;
  background-image:var(--pq-src); /* the EVENT raster, ~10000 nits nominal */
  background-size:100% 100%;
  background-repeat:no-repeat;
  /* the SDR tell, and on an SDR display the whole event: a hard core with two
     bloom rings. Static while the class is on -- the event is two class toggles,
     never a per-frame keyframe track. */
  box-shadow:0 0 22px 5px rgba(var(--pq-green-rgb),.9),
             0 0 54px 15px rgba(var(--pq-green-rgb),.42);
  transform:scaleX(1.12);
  /* ATTACK IS FAST, DECAY IS SLOW, and the asymmetry is free: a transition uses
     the timing declared in the state it is moving TO. This 90ms sits on the
     EVENT rule, so it governs the strike; hero-v2.css's 620ms sits on the base
     rule, so it governs the fall. Symmetric timing was measurably wrong -- the
     bloom was still climbing at .867 of peak 400ms in, which reads as a lamp
     warming up rather than as a cursor striking. */
  transition:box-shadow .09s linear,transform .09s linear;
}
/* THE HDR TAIL. Measured decay of the SDR bloom after the class drops:
   .867 peak -> .660 at 60ms -> .533 at 150ms -> .450 at 300ms -> .420 at 620ms.
   The super-luminant raster cannot be interpolated -- background-image is not an
   animatable value between two urls -- so the tier change is always a step, and
   if it stepped at the top of that curve an HDR display would see the one thing
   this whole treatment is against: a hard cut. The event tile is held for a
   further 240ms instead and hands over at roughly the half-way point of the
   bloom's fall, where the still-falling halo covers the join.
   WHAT IT HANDS OVER TO IS NOW THE RESTING TIER, NOT DARKNESS, which makes the
   step a decade rather than everything, and puts the cursor back exactly where
   the visitor found it: lit. Everything else about this state is the resting
   state. */
html.hb-tail[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after{
  animation:none;opacity:1;
  background-image:var(--pq-src);
  background-size:100% 100%;
  background-repeat:no-repeat;
}
/* the decay: hero-v2.css transitions box-shadow over 620ms and transform over
   240ms, so removing the class falls off like phosphor instead of cutting. The
   blink restarts from its lit step, so there is no dark frame at the join. */

@media (prefers-reduced-motion: reduce){
  /* no flash at all: the driver in partials/herocopy.html does not schedule one,
     and this is the belt to that brace if a class ever arrives from elsewhere. */
  html.hb-wake[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after,
  html.hx-wake[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after,
  html.hx-cursor[data-theme="terminal"] .hero33 .hero-copy h1 .h1-em::after{
    box-shadow:0 0 10px -1px rgba(var(--signal-rgb),.42);
    transform:none;
  }
}

/* The hero disclosure, for assistive tech. The visible label lives inside
   .hero-film, which is aria-hidden, so the fact would never be announced.
   Visually hidden, not display:none -- display:none is not announced either. */
.hero-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);border:0;}
