/* ==========================================================================
   KodeYak — the masthead
   Chunk 2 of the rebuild. Self-contained, like scene.css, so it can be tuned
   or dropped without touching the background. Colour and motion come from
   tokens.css — never a raw hex here.

   THE SHAPE. A full-width rail with a dropped shoulder on the left carrying the
   lockup, chamfered up to a thinner rail carrying the nav. Six points, driven
   by four variables so the whole silhouette is tunable from one place:

       0,0 ─────────────────────────────────────────── 100%,0
        │                                                 │
        │                        ┌────────────────────────┘  <- short
        │            (shoulder+chamfer, short)
        │           ╱  <- the chamfer
        └──────────┘  <- tall
        0,tall     shoulder,tall
   ========================================================================== */

/* The silhouette. Change these four and everything follows — both clipped
   layers read the same numbers, so the lit edge can never drift out of register
   with the panel it is tracing.

   Declared on :root rather than on .masthead because the bar is now fixed, and
   things outside it need its height: see scroll-padding-top below. */
:root {
  --mh-tall: 72px;                          /* left shoulder, holds the lockup */
  --mh-short: 44px;                         /* right rail, holds the nav       */
  --mh-shoulder: clamp(232px, 26vw, 320px); /* width before the chamfer starts */
  --mh-chamfer: 30px;                       /* horizontal run of the diagonal  */
}

/* PINNED. Fixed, not sticky: sticky needs the element in normal flow, and this
   one sits over the backdrop rather than above it in the document.

   Because it is fixed it covers the top of whatever it overlaps, so anything
   the browser scrolls TO must be offset or it lands underneath. That is not
   hypothetical — the skip link targets #main, and without this the first thing
   a keyboard user jumps to would be hidden behind the bar. scroll-padding-top
   fixes it for the skip link and for every future in-page anchor at once. */
html { scroll-padding-top: calc(var(--mh-tall) + var(--ky-space-6)); }

.masthead {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 5;
  height: var(--mh-tall);
}

/* Both layers share one silhouette. --mh-grow pushes the bottom boundary down
   by a hair on the edge layer, and the sliver that peeks out below the panel
   IS the lit line — which is why it follows the chamfer for free. A border
   could not: borders are rectangular, and clip-path would cut it off anyway.

   The box is deliberately taller than .masthead. clip-path clips, it never
   expands, so without the extra room the grown edge would be cut off flush at
   the bottom of the tall block and the line would vanish exactly there. */
.masthead__edge,
.masthead__panel {
  position: absolute;
  inset: 0 0 -6px;
  pointer-events: none;
  clip-path: polygon(
    0 0,
    100% 0,
    100% calc(var(--mh-short) + var(--mh-grow, 0px)),
    calc(var(--mh-shoulder) + var(--mh-chamfer)) calc(var(--mh-short) + var(--mh-grow, 0px)),
    var(--mh-shoulder) calc(var(--mh-tall) + var(--mh-grow, 0px)),
    0 calc(var(--mh-tall) + var(--mh-grow, 0px))
  );
}

/* The lit edge, lit from the RIGHT for the same reason as the panel sheen —
   the bloom is off-frame right, so the edge has to catch brightest there and
   fall away toward the shoulder. Lighting it from the left, as it was first
   built, put the highlight at the darkest corner of the artwork and read as a
   drawn border rather than an edge catching light. */
.masthead__edge {
  --mh-grow: 1.5px;
  background: linear-gradient(90deg,
    rgba(var(--ky-rgb-gridlit), .20) 0%,
    rgba(var(--ky-rgb-gridlit), .34) 42%,
    rgba(var(--ky-rgb-bone), .52) 76%,
    rgba(var(--ky-rgb-bone), .68) 100%);
}

/* The glass itself: not quite opaque, so the planet stays faintly present
   behind it, plus a real backdrop blur so what shows through reads as frosted
   rather than as a low-opacity overlay. The top-left sheen is the same
   reflective-corner move the glass panels use in the design system.

   The base is ABYSS (--ky-glass-900) throughout — no fall to Ink. Ink is the
   deepest step and read as a black bar sitting on the artwork rather than as
   part of the system; Abyss is the panel ground the design board uses for
   glass, and it carries the navy the planet's own terminator is painted in.
   Only the alpha moves down the bar, so the depth is Abyss over artwork rather
   than a second colour.

   THE LIGHT COMES FROM THE RIGHT. The bloom is the scene's light source and it
   sits right-of-frame, so the sheen is anchored there — a highlight on the
   top-left would be lit by nothing. Kept faint: this is a reflection catching
   the ground, not a gradient in its own right.

   THE ALPHAS CAME DOWN from .93/.86 on 2026-08-04, to let the artwork read
   through and make the glass look like glass. The binding constraint is the nav
   links, which are bone-400 and sit at the thin end of the bar over the
   brightest part of the picture. Measured on the rendered page with the content
   hidden: at .88/.81 they hold 6.39:1 and the lockup 12.11:1. At .78 the links
   fall to 5.76 and at .70 to 4.73, which is close enough to the AA floor to be
   an accident waiting for a new photograph. Re-measure if the artwork changes —
   this bar sits over a FIXED strip of it, so a new cut moves the number. */
.masthead__panel {
  background:
    radial-gradient(120% 180% at 100% 0%, rgba(var(--ky-rgb-bone), .055), transparent 58%),
    linear-gradient(180deg, rgba(var(--ky-rgb-panel), .88), rgba(var(--ky-rgb-panel), .81));
  -webkit-backdrop-filter: blur(14px) saturate(115%);
          backdrop-filter: blur(14px) saturate(115%);
}

/* ---- Content ------------------------------------------------------------
   Sits above the clipped layers, never inside them. Each side is centred in
   its own band — the lockup in the tall shoulder, the nav in the short rail —
   which is why this is two fixed-height flex rows rather than one.           */

.masthead__inner {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--ky-space-6);
}

.masthead__brand {
  display: flex;
  align-items: center;
  height: var(--mh-tall);
  padding-inline-start: var(--ky-gutter);    /* the marks are tight-cropped — all clear space is ours */
  color: var(--ky-text);        /* the marks are fill: currentColor */
  flex: 0 0 auto;
}
.masthead__brand svg { display: block; width: 100%; height: auto; }

/* Both marks are now cropped tight to their ink (horiz 1036x201, icon 301x223,
   zero padding), so these widths are the mark's real rendered width — no
   artboard padding to divide out. Clear space is supplied by the layout, which
   is where it belongs: it can then differ between the masthead, a footer and an
   OG card instead of being frozen into the file. */
.masthead__lockup { display: block; width: clamp(150px, 14.5vw, 196px); }
.masthead__mark   { display: none; width: 34px; }

.masthead__nav {
  display: flex;
  align-items: center;
  height: var(--mh-short);
  padding-inline-end: var(--ky-gutter);
  min-width: 0;
}
/* THE LIST IS A POPOVER, and on wide screens these declarations are what stop
   it behaving like one. A UA hides a closed popover with `display: none` and
   gives an open one `position: fixed`, auto margins, a border, padding and a
   Canvas background — every one of which is overridden here, so at this width
   the element is an ordinary flex row that happens to carry the attribute.
   An author declaration beats the UA sheet, which is the whole mechanism.

   Consequence worth knowing: because `display` is set unconditionally here, the
   list is ALWAYS in the accessibility tree at this width, open or not. Only the
   narrow block below reintroduces the popover behaviour. */
.masthead__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: clamp(var(--ky-space-4), 2.4vw, var(--ky-space-8));
  position: static;
  inset: auto;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  border: 0;
  overflow: visible;
  background: none;
  color: inherit;
}

/* The invoker. Hidden until the narrow block turns it on. */
.masthead__menu-btn { display: none; }

/* Ubuntu, not Tilt Neon: this is glass, so the face is sans — but Tilt Neon
   ships at a single 400 weight with no medium, and nav items need one. Tilt
   Neon stays display-only. */
/* One face and one weight for the links and the button that reveals them, so
   the collapsed state does not read as a different control family. */
.masthead__nav a,
.masthead__menu-btn {
  font-family: var(--ky-font-tech);
  font-weight: var(--ky-weight-medium);
  font-size: var(--ky-text-small);
  letter-spacing: .08em;
  color: var(--ky-text-muted);
  text-decoration: none;
  white-space: nowrap;
  position: relative;
  padding-block: var(--ky-space-2);
  transition: color var(--ky-duration-fast) var(--ky-ease);
}
.masthead__nav a:hover { color: var(--ky-text); }

/* cool-300, a step lighter than --ky-text-accent. Moving the light source to
   the right put the sheen directly under the nav, and the accent (cool-400)
   fell to 6.31:1 there — still AA, but it would have been the system's second
   sub-AAA pair, and the first was a deliberate, documented exception. The
   lighter step measures 9.40:1 on the same ground. It also reads brighter than
   the resting links rather than merely different, which is the right hierarchy
   for "you are here". The state is not carried by colour alone in any case —
   the lit rule below is always on for the current page. */
.masthead__nav a[aria-current="page"] { color: var(--ky-cool-300); }

/* The hover rule lights rather than underlines — same idea as the masthead's
   own lit edge, scaled down. Drawn on a pseudo-element so it can grow from the
   centre; text-decoration cannot animate this way. */
.masthead__nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent, rgba(var(--ky-rgb-gridlit), .9), transparent);
  transform: scaleX(0);
  transition: transform var(--ky-duration-base) var(--ky-ease);
}
.masthead__nav a:hover::after,
.masthead__nav a[aria-current="page"]::after { transform: scaleX(1); }

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

/* Focus sits OUTSIDE the control, never inset, in a hue outside both brand
   poles — so focus never reads as accent or link. */
.masthead a:focus-visible {
  outline: var(--ky-focus-width) solid var(--ky-focus);
  outline-offset: var(--ky-focus-offset);
  border-radius: 2px;
}

/* ---- Narrow ---------------------------------------------------------------
   The lockup gives way to the icon-only mark, which buys back ~170px for the
   nav, and the shoulder tightens to match. These are separately drawn marks —
   the favicon-grade icon is optically corrected with heavier strokes — so this
   is a swap, never a scale.                                                   */

@media (max-width: 720px) {
  :root {
    --mh-tall: 60px;
    --mh-short: 40px;
    --mh-shoulder: 96px;
    --mh-chamfer: 22px;
  }
  .masthead__lockup { display: none; }
  .masthead__mark { display: block; }
  .masthead__nav a,
  .masthead__menu-btn { font-size: 0.8125rem; letter-spacing: .04em; }
  .masthead__links { gap: var(--ky-space-4); }
}

/* ---- Narrower still: the nav collapses ------------------------------------
   480px, and the number is measured rather than picked. The four labels need
   ~347px; add the icon mark (34px), both gutters (48px) and a minimum gap and
   the row stops fitting at about 453px. Below that the masthead CLIPS the
   overflow — no sideways scroll, no warning, the last item just is not there —
   so this breakpoint is a correctness fix, not a preference.

   Re-measure it if a label changes length or a fifth item arrives. Nothing here
   derives the number for you.                                                  */

@supports selector(:popover-open) {
  @media (max-width: 480px) {
    /* NO CHROME — just the mark, in the lighter ink (Joe, 2026-09-15). The
       outlined pill read as a second control next to the panel it opens.

       border-radius STAYS even with no border to show it: this button is
       focusable, and tokens.css draws the focus ring with
       :where(a, button, [tabindex]):focus-visible, which follows the radius.
       Take the radius away and the ring goes square on a round-shouldered bar.

       --ky-text, not --ky-text-muted, is the whole of the change: it is the
       lightest ink on glass, so there is deliberately NO hover or open state
       here. There is nowhere lighter to go, the panel appearing is the feedback,
       and this button only exists below 480px — a width where hover is not a
       thing anyone has. (The open state used to be styled with
       :has(.masthead__links:popover-open). Worth remembering why it could not be
       [aria-expanded="true"]: popovertarget's expanded state is implicit, real
       for a screen reader and invisible to an attribute selector. CLAUDE.md.) */
    .masthead__menu-btn {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background: none;
      border: 0;
      border-radius: var(--ky-radius-pill);
      color: var(--ky-text);
      /* Square-ish and sized to the rail it sits in: --mh-short is 40px at this
         width, so the button fills it. 40px also clears WCAG 2.5.8's 24px
         minimum target with room — the icon itself is only 18x12. */
      min-width: 40px;
      min-height: 40px;
      padding: 0;
      cursor: pointer;
    }

    /* currentColor, so the bars follow the button's colour transition. */
    .masthead__burger { display: block; fill: currentColor; }

    /* Back to being a popover: hidden when closed, a panel when open. */
    .masthead__links:not(:popover-open) { display: none; }

    .masthead__links:popover-open {
      display: flex;
      flex-direction: column;
      align-items: stretch;
      gap: var(--ky-space-2);
      position: fixed;
      top: calc(var(--mh-short) + var(--ky-space-3));
      right: var(--ky-gutter);
      left: auto;
      bottom: auto;
      margin: 0;

      /* ⚠ EVERY STEP HERE MUST EXIST IN THE SCALE — 1,2,3,4,6,8,12,16,24,32.
         The first version of this rule asked for --ky-space-5, which is not a
         token; an undefined var() does not fall back, it INVALIDATES the whole
         declaration, so padding and gap both silently reverted and the panel
         shrank to the width of its longest label with the text spilling past
         the background. It looks like an overflow bug and it is a typo.
         CLAUDE.md flags this; it is the second time it has bitten. */
      min-width: 200px;
      padding: var(--ky-space-4) var(--ky-space-6);

      /* PLAIN RECTANGLE, no chamfer — the cut was reading as fussy at this size
         and a dropdown is not one of the system's machined screens. Deliberate
         (Joe, 2026-09-15), not an oversight to tidy back up.

         The plate is painted straight onto this element now, and the pseudo it
         used to need is gone: background and border-radius do NOT clip a
         descendant's focus ring the way clip-path does, so the links keep their
         rings without a separate layer. Only overflow:hidden/clip or clip-path
         would take them. */
      border-radius: var(--ky-radius-panel);
      background:
        radial-gradient(120% 180% at 100% 0%, rgba(var(--ky-rgb-bone), .055), transparent 58%),
        linear-gradient(180deg, rgba(var(--ky-rgb-panel), .96), rgba(var(--ky-rgb-panel), .93));
      backdrop-filter: blur(14px) saturate(115%);
      box-shadow: 0 12px 32px rgba(var(--ky-rgb-void), .34);
      overflow: visible;
    }

    /* Full-width rows, so the whole line is the target rather than just the
       glyphs — the reason align-items is stretch above. */
    .masthead__links:popover-open a {
      display: block;
      padding-block: var(--ky-space-2);
    }
  }
}

/* ---- Skip link ----------------------------------------------------------- */

/* A pill, like the buttons — it is a control, not a screen. And a plain
   border-radius keeps its focus ring, which matters more here than anywhere:
   this control exists ONLY when focused. */
.skip {
  position: absolute;
  left: -9999px;
  z-index: 10;
  background: var(--ky-glass-800);
  color: var(--ky-bone-100);
  font-family: var(--ky-font-tech);
  font-size: var(--ky-text-small);
  padding: var(--ky-space-3) var(--ky-space-4);
  border-radius: var(--ky-radius-pill);
}
.skip:focus {
  left: var(--ky-space-4);
  top: var(--ky-space-4);
  outline: var(--ky-focus-width) solid var(--ky-focus);
  outline-offset: var(--ky-focus-offset);
}
