/* =====================================================================
   VAL STUDIO — THE MARK

   >>> THE ONE PLACE THE MARK'S SIZE IS WRITTEN DOWN. <<<

   The mark used to be copied into five stylesheets — core/site.css for
   the interior pages and an inline block in index.html and each of the
   three labs pieces — which meant "make the logo smaller" was five edits
   and any one of them could be missed. It is one file now, and every
   page that shows a mark links it:

     index.html, labs/ContactAureole.html, labs/Miscible.html,
     labs/Nodal.html, labs/ProceduralBreath.html and labs/Rocky.html link it
     directly; core/site.css @imports it, so the seventeen pages that link
     core/site.css get it without a second tag of their own.

   WHAT THE MARK IS. One letter — the V — drawn as TWO ELEMENTS FILLED
   WITH currentColor AND CUT BY clip-path. The polygons are in
   core/brand-mark.css, which every page loads immediately before this
   file, and which is the only place a number describing the shape is
   allowed to live. See assets/LOGO-SPEC.md for what those numbers mean;
   every one of them is a share of the cap height, so --logo-h below
   sizes the whole drawing and nothing else needs a pixel value.

   WHY clip-path AND NOT A MASK. The mark it replaces was three files —
   val-v/a/l.svg — referenced as mask-image. Those files are still on
   disk and still in use, but NOT BY THE MARK: assets/val-v.svg and
   val-a.svg are the pager's and the reel's arrows (.pager-mark in
   core/site.css, .reel-mark in core/reel.css), which borrow the old
   letterforms as chevrons. Nothing here touches them.

   This mark loads no file at all. Two clip-path polygons in the same
   point order transition into one another natively, which is what the
   press state is built on in phase two — a mask cannot do that, and a
   mask of a single letter would also be a network round trip for a
   shape that is eight numbers long. currentColor still fills it, so the
   mark answers `color` exactly as the old one did and the .ic hover glow
   still finds real content to glow around.

   PHASE ONE IS PLACEMENT ONLY. The structure below is the final one —
   the box, the two arms, the rest polygons. It carries no states: no
   spread on hover, no press morph, no wordmark. Hover is the plain
   .ic rule every other corner uses (core/site.css), and nothing here
   restates it.

   The two numbers in CONFIG are the only ones meant to be edited.
===================================================================== */

/* ==== CONFIG ==========================================================
   THE CORNERS' HEIGHT, AND THE MARK'S. Edit here and nowhere else.
====================================================================== */
:root{
  /* THE THREE CONTROLS' SIZE. The height every corner CONTROL is drawn
     at — the menu button, the sound's crest, and the line CONTACT (and
     the back link) is set on. Written here because this is the one
     stylesheet every page with corners already loads: index.html links
     it and core/site.css imports it, so the home page and the interior
     pages read one number instead of carrying three that happen to be
     close. Each control's own rule takes it from here — --menu-box in
     core/site.css and index.html, the #snd wave in both, #contactBtn in
     core/contact.css.

     THE WORD IS THE ONE CONTROL NOT DRAWN AT THIS HEIGHT, on purpose.
     For CONTACT this number is its font size, so its capitals come out
     at about seven-tenths of it: a whole word carries more weight than a
     glyph of the same height, and matched this way it reads as one of
     the set rather than as the loudest thing on the frame. */
  --corner-h: 12px;

  /* THE MARK'S SIZE — its cap height, and the whole of "bigger" and
     "smaller", because every other number in the drawing is a share of
     it (core/brand-mark.css).

     IT IS NO LONGER var(--corner-h). It was, while the mark was three
     letters: at 12px the old mark was about 59px wide, so it held the
     corner on width and the shared height was all it needed. One letter
     is 1.034 × its own cap height — 12.4px at the controls' height —
     and that is a fifth of the footprint the corner used to carry.

     16px is that corner given back to it, and the number was arrived at
     by looking rather than by arithmetic — the mark, the burger, the
     crest and CONTACT stood in a row at 12, 14, 15, 16, 17, 18 and 20,
     and 16 is where the V stops being a fourth control and starts being
     the identity, without yet out-weighing the row.

     WHY IT IS BIGGER THAN THE BURGER AND STILL LEVEL WITH IT. The
     burger's three rules use every edge of its 12px box; the V is two
     diagonals with a large empty counter between them, so a third of
     its box is the only ink in it. Matching the two boxes — which is
     what --logo-h: var(--corner-h) did — matches the drawings on paper
     and leaves the V visibly lighter on screen. A third taller is what
     it costs to make the two read as the same weight.

     At 12 the V is a chevron in a set of chevrons. At 18 and above it
     is the loudest thing on the frame, which is the one thing the
     CONTACT note below says the corners must not be.

     A whole pixel, not a fraction: the mark's terminals are cut
     horizontally (assets/LOGO-SPEC.md), so a fractional cap height
     lands those two cuts on a half pixel and greys them. The diagonals
     are antialiased either way, which is why the width is allowed to
     come out at 16.54.

     It is TOP-ALIGNED with the burger opposite it rather than centred on
     it — see #brand in core/site.css. Both are anchored at --chrome-pad,
     so the V's cap line and the burger's top rule are the same line, and
     the 5px the V runs past the burger's box is its near-closed foot,
     which carries almost no ink. Lining up the heavy ends is what makes
     two glyphs of different heights read as one row. */
  --logo-h: 16px;
}
/* ==== end CONFIG ====================================================== */

/* THE BOX. One letter, so there is nothing to space and nothing to lay
   out — the old flex row and its two gaps are gone with the A and the L.
   Width is the cap height times the letter's own aspect (103.40 / 100,
   --mark-ratio), so the box is the ink and the corner grid can measure
   it. */
.mark{
  position:relative;display:block;
  width:calc(var(--logo-h) * var(--mark-ratio));
  height:var(--logo-h);
  /* THE COLOUR TRAVELS AT THE SAME RATE THE LINK'S DOES. The lit colour
     is set on this element (see AND IT LIGHTS below) rather than left to
     the link, and an element with no transition of its own would jump
     while the glow around it faded — .ic gives the link
     color var(--dur-med), so this matches it. */
  transition:color var(--mark-dur-out) var(--mark-ease);
}

/* THE TWO ARMS. Both are the FULL box, stacked, each showing only its
   own polygon. Full-size rather than cut to their own widths for a
   reason that phase two depends on: --mark-spread is a percentage, and a
   percentage in translateX resolves against the element's own width, so
   an arm that is the whole box steps out by a share of the cap height —
   which is how every other number in the drawing is stated. Cut to fit,
   the same token would mean two different distances. */
.mark i{
  position:absolute;inset:0;
  background:currentColor;
  /* THE RESTING RULE CARRIES THE *OUT* DURATION, and each state below
     restates it as the in. That is this site's motion vocabulary — an
     exit at about 65% of its entrance (--dur-med over --dur-slow is
     .42 / .62) — written the way core/site.css already writes it for
     the waterline: the state the element returns TO owns the leaving. */
  transition:transform var(--mark-dur-out) var(--mark-ease),
             clip-path var(--mark-dur-out) var(--mark-ease);
}
.mark .l{clip-path:var(--arm-l-rest)}
.mark .r{clip-path:var(--arm-r-rest)}

/* ---------- under the pointer, and under the keyboard ------------------
   THE ARMS STEP APART. The V opens: the hairline between the two feet
   goes from 0.60 of the cap to 8.60, and nothing else about the mark
   changes. The colour is NOT restated here — it is still the plain
   .ic:hover the menu button, the sound crest and CONTACT all use
   (core/site.css, and each labs piece's own copy). The spread is an
   addition to what the corner already does, not a replacement for it.

   --mark-spread is a percentage, and a percentage in translateX
   resolves against the element's own width. Each arm is the whole
   103.40-wide box (see THE TWO ARMS above), so 3.87% of it is 4.00 of
   the cap — the number assets/LOGO-SPEC.md states, in the units it
   states it in. */
#brand a:hover .mark i,
#brand a:focus-visible .mark i{transition-duration:var(--mark-dur-in)}
#brand a:hover .mark .l,
#brand a:focus-visible .mark .l{transform:translateX(calc(-1 * var(--mark-spread-corner)))}
#brand a:hover .mark .r,
#brand a:focus-visible .mark .r{transform:translateX(var(--mark-spread-corner))}

/* AND IT LIGHTS, SAID HERE RATHER THAN INHERITED. Every page lights its
   corner controls with .ic:hover, and the mark used to take its colour
   from that by inheritance alone: the arms are background:currentColor,
   currentColor is the link's colour, and the link's colour was whatever
   token that page's own .ic:hover named. It works on all twenty-three
   pages today — and it is one missing token away from a mark that stops
   lighting with nothing anywhere to explain why.

   --mark-lit (core/brand-mark.css) asks for each page's own token in
   turn and ends in a literal, so this can never resolve to nothing. It
   is set on .mark rather than on the link so the link keeps its own
   colour and its own glow from .ic:hover exactly as before — this adds
   a guarantee under the mark, it does not take the corner's behaviour
   away from the page.

   WHAT THIS DOES NOT FIX, because it is not a cascade problem: on the
   six pages that carry their own chrome, the resting and lit colours are
   the SAME HUE at different alpha — Rocky rests at rgba(238,240,244,.56)
   and lights to #eef0f4. Over a dark frame that is a clear lift. Over a
   bright frame of a running piece the resting colour has already
   composited most of the way to the lit one and the change is close to
   invisible. Making that read means those pages choosing a lit colour
   that differs in more than alpha, which is a decision about each
   piece's palette and not something this stylesheet should take. */
#brand a:hover .mark,
#brand a:focus-visible .mark{color:var(--mark-lit);transition-duration:var(--mark-dur-in)}

/* ---------- pressed -----------------------------------------------------
   THE TWO STROKES STRAIGHTEN AND CLOSE INTO ONE BAR. Both arms take
   their bar polygon and the spread returns to 0, so the gap that means
   "boundary" everywhere else on this site goes to nothing. The ink area
   does not change, which is why the bar lands at exactly two stroke
   widths.

   Rest and bar are four-point polygons given in the same order, which
   is the whole reason the mark is clip-path and not a mask: the browser
   interpolates them point by point with no script, no frame loop and no
   path-morph library.

   THE CLICK STILL NAVIGATES — nothing here calls preventDefault, and
   the morph plays underneath the veil that is already covering the
   change (interceptNavigation in core/site.js). On a page whose mark
   links to where it already is, core/site.js returns early and never
   navigates; the press simply releases and the arms travel back to
   rest, which is the same gesture played backwards.

   These selectors are deliberately the same shape as the hover ones
   above, so the two carry identical specificity and source order
   decides. Pressed is written second, so pressed wins while the
   pointer is down. */
#brand a:active .mark i{transition-duration:var(--mark-dur-in)}
#brand a:active .mark .l{transform:translateX(0);clip-path:var(--arm-l-bar)}
#brand a:active .mark .r{transform:translateX(0);clip-path:var(--arm-r-bar)}

/* ---------- the reveal --------------------------------------------------
   THE WHOLE WORD, BEHIND THE WHOLE PAGE. Resting on the mark fades the
   wordmark up in the centre of the viewport at --reveal-opacity. It is
   a whisper behind the page, not a second logo: it never takes a
   pointer, it is never in the accessibility tree, and it sits below the
   content, the menu, the chrome and the cursor — see --reveal-z in
   core/brand-mark.css for why that layer is a per-page number.

   ONE ELEMENT PER PAGE, and core/brand-reveal.js is the only thing that
   makes one. The class on <html> rather than a selector reaching from
   the mark to this element is not a shortcut: this element is a child
   of <body> and the mark is inside .corner, which carries a filter, so
   no combinator connects them and :has() would put an invalidation
   check on a document that may be running a shader.

   IT COSTS NOTHING WHILE IT IS NOT SHOWING. Three things in order of
   how much they buy: visibility:hidden means it is never painted and
   never composited, so a page rendering every frame behind it does no
   work on its account; contain means it cannot make the page around it
   lay out again; and content-visibility, where the browser can defer it
   discretely, skips the subtree layout too.

   THE ORDER OF THOSE TWO MATTERS. visibility is the one that carries
   the exit, because it is a discrete property that can be given a 0s
   duration and a DELAY — so the word stays visible for exactly as long
   as the fade lasts and disappears the moment it is done.
   content-visibility cannot be delayed that way without
   transition-behavior:allow-discrete, which is why it is under an
   @supports and why visibility is not.

   brand-reveal.js does not even create the element on a touch screen or
   under reduced motion. */
#wordmark{
  position:fixed;left:50%;top:50%;
  z-index:var(--reveal-z);
  width:var(--reveal-width);
  transform:translate(-50%,-50%);
  pointer-events:none;
  /* layout only, NOT paint: the blur plate below stands outside this
     box on purpose, and contain:paint would clip it back to it. */
  contain:layout style;
  visibility:hidden;
  /* visibility is discrete, so it is given 0s and DELAYED by the length
     of the fade: going out it holds the element renderable until the ink
     and the blur have both finished, and coming in it flips at once. */
  transition:visibility 0s linear var(--mark-dur-out);
}
html.mark-lit #wordmark{visibility:visible;transition:visibility 0s}

/* ---- the ink ----
   The word is inline SVG rather than a mask over currentColor, unlike
   the mark: a mask-image is allowed to be read as alpha OR as
   luminance, and the delivered file paints fill="currentColor", which
   an external SVG resolves to black — fine under alpha, invisible
   under luminance. Inline, currentColor means the page's ink and there
   is nothing to interpret. It is also the same six shapes, with the
   same names, that the loader needs one at a time.

   THE FADE IS ON THE WORD, NOT ON THE WRAPPER, and that is what makes
   the blur possible. An element at opacity .12 is a group composited at
   .12, and a backdrop-filter inside such a group is composited with it —
   the page would be blurred and then that blur laid over the unblurred
   page at twelve percent, which is no blur at all. Wrapper stays opaque;
   the ink carries its own opacity and the plate carries its own radius. */
#wordmark svg{
  display:block;width:100%;height:auto;fill:currentColor;
  opacity:0;
  transition:opacity var(--mark-dur-out) var(--mark-ease);
}
html.mark-lit #wordmark svg{
  opacity:var(--reveal-opacity);
  transition-duration:var(--mark-dur-in);
}

/* ---- the page going soft behind it ----
   A bounded plate, not the viewport: this is the home page and the sea
   is running underneath, so the blurred region is a box around the word
   and no more. --reveal-mask takes its edges off so it never reads as a
   rectangle — if it ever does, widen the mask, not the radius.

   Under @supports because a browser without backdrop-filter should get
   the reveal exactly as it is rather than an empty box: no plate is
   built at all, and the word simply fades up over an unblurred page. */
@supports (backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px)){
  #wordmark::before{
    content:"";position:absolute;
    inset:calc(-1 * var(--reveal-bleed-y)) calc(-1 * var(--reveal-bleed-x));
    -webkit-backdrop-filter:blur(0px);backdrop-filter:blur(0px);
    -webkit-mask-image:var(--reveal-mask);mask-image:var(--reveal-mask);
    transition:-webkit-backdrop-filter var(--mark-dur-out) var(--mark-ease),
               backdrop-filter var(--mark-dur-out) var(--mark-ease);
  }
  html.mark-lit #wordmark::before{
    -webkit-backdrop-filter:blur(var(--reveal-blur));backdrop-filter:blur(var(--reveal-blur));
    transition-duration:var(--mark-dur-in);
  }
}

/* Where the browser can hold a discrete property through a transition,
   the element leaves layout as well, and only once the fade has
   finished — allow-discrete is what keeps it renderable for the length
   of the exit instead of snapping it away mid-fade. Without support the
   rules above are the whole behaviour, which is correct, just less
   thrifty. */
@supports (transition-behavior:allow-discrete){
  #wordmark{
    content-visibility:hidden;
    transition:visibility 0s linear var(--mark-dur-out),
               content-visibility var(--mark-dur-out) allow-discrete;
  }
  html.mark-lit #wordmark{
    content-visibility:visible;
    transition:visibility 0s,content-visibility 0s;
  }
}

/* ---------- no pointer to rest -----------------------------------------
   A tap plays the press morph and follows the link, which is the whole
   of the gesture on a phone. The reveal is a hover state with no tap
   equivalent, so there is nothing to show and it is not drawn. */
@media (hover:none){
  #wordmark{display:none}
}

/* ---------- reduced motion ---------------------------------------------
   Everything off: no spread, no morph, no reveal. The mark rests, and
   resting is all it does.

   This turns the STATES off rather than the transitions. core/site.css
   already collapses every transition on the site to .01ms under this
   setting, deliberately and site-wide, and nothing here carves an
   exception into that — without the rules below the arms would still
   arrive at the spread and the bar, instantly, which is the jump that
   rule exists to prevent. */
@media (prefers-reduced-motion:reduce){
  #brand a:hover .mark i,
  #brand a:focus-visible .mark i,
  #brand a:active .mark i{transform:none}
  #brand a:active .mark .l{clip-path:var(--arm-l-rest)}
  #brand a:active .mark .r{clip-path:var(--arm-r-rest)}
  #wordmark{display:none}
}

/* The box around it. Padding only — the colour is the page's business,
   because the home page, the interior pages and the Works section
   each rest the mark at a different grey.

   This padding is what the labs pieces draw the mark with. The site's
   own pages — index.html and core/site.css — take it back to 0, so the
   mark sits exactly on the corner grid the other three corners do (see
   "the four corners" in core/site.css). */
#brand a{display:block;padding:5px 2px}
