/*
  nav-capsule — the capsule section indicator. Pair with nav-capsule.js.

  THEMING. The names in the block below are the only colours and faces this component borrows
  from its host. They are declared at zero specificity (:where), so a page that already defines
  --nav-text and friends wins without !important and a page that defines nothing still renders
  correctly.

  --nav-paint-* is a different tier: the script writes those every frame from the colour ramp, so
  setting one by hand does nothing. Theme --nav-amber and --nav-amber-hot instead; the ramp is
  built from them.
*/
:where(:root) {
  --nav-text: #E8EDF7;
  --nav-muted: #9AA8C4;
  --nav-amber: #F5A83C;
  --nav-amber-hot: #FFC46B;
  --nav-line: rgba(146, 166, 205, .28);
  --nav-ink: #060B18;
  --nav-font-mono: ui-monospace, "Cascadia Mono", Consolas, monospace;
  --nav-dock-h: 62px;                 /* the phone dock's height */
}


/* ---------- the bar: a horizontal row of links ---------- */
.nav-bar {
  position: relative; display: flex; gap: 22px; margin-left: auto;
  align-self: stretch; align-items: center;
  touch-action: pan-y;                       /* horizontal is ours, vertical stays the page's */
  -webkit-user-select: none; user-select: none;   /* a drag must not sweep a selection along the bar */
  cursor: grab;
}
.nav-bar a {
  position: relative; z-index: 1; display: block;    /* the glow washes behind the labels, never over them */
  color: var(--nav-muted); font-size: 14.5px; font-weight: 500; text-decoration: none;
  padding: 21px 2px 20px; cursor: pointer; -webkit-user-drag: none;
  transition: color .16s ease;
  /* NOT a nicety. A link is a flex item whose floor is min-content, which for "What we build" is the
     longest WORD, so a tight bar wraps the label onto two lines. The capsule's geometry is measured
     from these rects, so a wrapped label does not just look wrong, it sizes and places the oval
     against boxes that are the wrong shape. The component owns this, not the host. */
  white-space: nowrap;
}
.nav-bar a:hover, .nav-bar a:focus-visible { color: var(--nav-text); }
/* .is-lit, not [aria-current]: aria-current moves on the click for assistive technology, the
   colour waits for the light to arrive. See "the label waits for the light" in nav-capsule.js. */
.nav-bar a.is-lit { color: var(--nav-paint-lit, var(--nav-text)); }
.nav-bar a:focus-visible { border-radius: 8px; }
.nav-bar[data-nav-drag="1"], .nav-bar[data-nav-drag="1"] a { cursor: grabbing; }
/* THE GLOW HAS TO BE ABLE TO LEAVE THE BAR. Its gradient fades out over about 65px, so over the
   first or the last link it still has fade left when it reaches the end of the link row, and the
   clip is a hard vertical edge the reader sees. The pseudo-element therefore runs GLOW_PAD past
   each end. --nav-paint-x is measured from the bar, so the gradient's own x has to move by the same
   amount or the light would sit GLOW_PAD to the left of the pointer. */
.nav-bar::after {
  --nav-glow-pad: 70px;
  content: ""; position: absolute; top: 0; bottom: 0;
  left: calc(-1 * var(--nav-glow-pad)); right: calc(-1 * var(--nav-glow-pad)); z-index: 0;
  pointer-events: none; opacity: 0; transition: opacity .2s ease;
  /* the amber line first: where color-mix is unsupported the second declaration is invalid and
     dropped, and the glow stays amber instead of disappearing */
  background: radial-gradient(90px 26px at calc(var(--nav-paint-x) + var(--nav-glow-pad)) 50%, rgba(245, 168, 60, .26), transparent 72%);
  background: radial-gradient(90px 26px at calc(var(--nav-paint-x) + var(--nav-glow-pad)) 50%, color-mix(in srgb, var(--nav-paint-base) 26%, transparent), transparent 72%);
}
.nav-bar[data-nav-hot="1"]::after { opacity: 1; }
html.still .nav-bar::after, .nav-bar[data-nav-off="1"]::after { opacity: 0 !important; }

/* ---------- the capsule ----------
   One capsule per bar: a stadium outline whose two cap centres each ride their own damped spring,
   so the centres together draw a circle and apart an oval. It is drawn as three stacked closed
   strokes (bloom, halo, near white filament) that gain width AND alpha as the capsule opens, all
   three taking their colour from the stop the capsule is standing on. No blur filter anywhere, so
   a frame costs three strokes over a page whose GPU budget belongs to the scene. Everything that
   moves is written by nav-capsule.js, which stops the moment the springs settle. */

/* The capsule's live colour. The defaults are the old amber, so a frame painted before the first
   render (or any path where JS never runs) still looks deliberate rather than unstyled. */
[data-nav-bar] {
  --nav-paint-x: -400px;
  --nav-paint-base: var(--nav-amber);
  --nav-paint-hot: var(--nav-amber-hot);
  --nav-paint-filament: #FFF1DA;
  --nav-paint-tint: rgba(245, 168, 60, .07);
}
.nav-glow {
  position: absolute; inset: 0; width: 100%; height: 100%;
  overflow: visible; pointer-events: none; z-index: 0;
  transition: opacity .28s ease;
}
html:not(.js) .nav-glow { display: none; }
.nav-glow path {
  fill: none; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.nav-bloom { stroke: var(--nav-paint-base); }
.nav-hot { stroke: var(--nav-paint-hot); }
/* the filament is the stop's own hue pulled to near white. It used to be a fixed cream tuned to
   amber, which inside a teal or magenta capsule reads as a second, yellow light in the middle. */
.nav-filament { stroke: var(--nav-paint-filament); }
/* the bloom carries the only fill: enough to tint the field inside the capsule, so an icon the
   oval has swallowed reads as being INSIDE it rather than merely behind a passing outline.
   The alpha is set in JS and is multiplied by this path's own opacity, so see paintColour(). */
.nav-glow .nav-bloom { fill: var(--nav-paint-tint); }
/* above the first stop there is no capsule at all */
[data-nav-bar][data-nav-off="1"] .nav-glow { opacity: 0; }
html.still .nav-glow { transition: none; }

/* ---------- the phone dock ---------- */

.nav-dock {
  display: none; position: fixed; z-index: 55; left: 50%;
  bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  width: min(432px, calc(100vw - 20px));
  transform: translateX(-50%);
  transition: transform .34s cubic-bezier(.2, .7, .3, 1), opacity .24s ease;
}
.nav-dock-pill {
  position: relative; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  height: var(--nav-dock-h); padding: 0 4px; border-radius: 22px;
  border: 1px solid var(--nav-line);
  background: linear-gradient(180deg, #141F3A, #090F1F);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .07) inset, 0 -18px 34px -22px rgba(245, 168, 60, .55), 0 22px 40px -14px rgba(0, 0, 0, .92);
  touch-action: pan-y; cursor: grab;
  -webkit-user-select: none; user-select: none;
}
.nav-dock[data-nav-drag="1"] .nav-dock-pill { cursor: grabbing; }
.nav-dock-pill::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  opacity: 0; transition: opacity .2s ease;
  background: radial-gradient(84px 46px at var(--nav-paint-x) 50%, rgba(245, 168, 60, .2), transparent 70%);
  background: radial-gradient(84px 46px at var(--nav-paint-x) 50%, color-mix(in srgb, var(--nav-paint-base) 20%, transparent), transparent 70%);
}
.nav-dock[data-nav-hot="1"] .nav-dock-pill::before { opacity: 1; }
html.still .nav-dock-pill::before, .nav-dock[data-nav-off="1"] .nav-dock-pill::before { opacity: 0 !important; }
.nav-dock-tab {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-width: 44px; padding: 6px 2px 7px; border-radius: 18px;
  color: var(--nav-muted); text-decoration: none; cursor: pointer; -webkit-user-drag: none;
  -webkit-tap-highlight-color: transparent;
}
.nav-dock-tab .nav-dock-icon {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  font-size: 21px; transition: color .16s ease, transform .16s ease;
}
/* A stretched capsule swallows the icons it passes, so for the 200 ms of a long move two or three
   glyphs sit inside it. An ink halo on the glyph keeps it readable against the bloom's tint and
   makes the icon read as being INSIDE the shape rather than struck through by it. It is a static
   filter on a static element: one rasterisation at paint, nothing per frame. */
.nav-dock-tab:not(.nav-dock-go) .nav-dock-icon .i { filter: drop-shadow(0 0 2.5px var(--nav-ink)); }
.nav-dock-label {
  font-family: var(--nav-font-mono); font-size: 10px; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; line-height: 1;
  transition: color .16s ease;
}
.nav-dock-tab:hover, .nav-dock-tab:focus-visible { color: var(--nav-text); }
/* .is-lit, not [aria-current]: the label lights when the light lands, not when the tab is
   picked. aria-current still moves at once, for assistive technology. */
.nav-dock-tab.is-lit, .nav-dock-tab.is-lit .nav-dock-icon { color: var(--nav-paint-lit, var(--nav-amber-hot)); }
.nav-dock-go .nav-dock-icon { background: var(--nav-amber); color: var(--nav-ink); box-shadow: 0 4px 14px -4px rgba(245, 168, 60, .8); }
.nav-dock-go.is-lit .nav-dock-icon { background: var(--nav-amber-hot); color: var(--nav-ink); }
/* set on the label itself, so it outranks the INHERITED .is-lit colour: Start keeps the amber
   that ties it to the page's main call to action until the capsule lands, then takes its own
   stop. Give the action tab the class nav-dock-go. */
.nav-dock-go .nav-dock-label { color: var(--nav-amber-hot); }
.nav-dock-go.is-lit .nav-dock-label { color: var(--nav-paint-lit, var(--nav-amber-hot)); }
.nav-dock-tab:active .nav-dock-icon { transform: scale(.9); }
.nav-dock-tab:focus-visible { border-radius: 16px; }
html.still .nav-dock-tab:active .nav-dock-icon { transform: none; }
/* out of the way of the work order form and the footer under it */
.nav-dock.is-away { transform: translateX(-50%) translateY(calc(100% + 30px)); opacity: 0; pointer-events: none; }
html.still .nav-dock, html.still .nav-dock-tab .nav-dock-icon, html.still .nav-dock-label { transition: none; }
/* a section handed focus by a keyboard activation is a landing place, not a tab stop */
[data-nav-section][tabindex="-1"]:focus { outline: none; }


/* ---------- which bar is on ----------
   The rail needs 1160 px to fit five links beside the brand, the Pause pill, the number and the
   button. Below that the dock is the better nav anyway, so they swap there. This rule has to
   stay BELOW .nav-bar { display: flex } above: a media query adds no specificity, so if it
   ever moves up the link row comes back on phones on top of the dock. */
@media (min-width: 1160px) and (max-width: 1319px) {
  /* .nav-in used to be tightened here. It is a class on the PAGE that hosted this component first,
     not part of any markup contract, and a component that styles its host's furniture is a component
     that only works on one site. The host tightens its own header. */
  .nav-bar { gap: 16px; }
  .nav-bar a { font-size: 14px; }
}
@media (max-width: 1159px) {
  .nav-bar { display: none; }
  .nav-dock { display: block; }
  html { scroll-padding-bottom: calc(var(--nav-dock-h) + 24px + env(safe-area-inset-bottom, 0px)); }
  /* The dock retracts off the screen for the work order form and the footer, so with the script
     running there is nothing under it at the end of the page and the page pays no height for it.
     Two cases have no retract and do need the clearance: script off, and a browser that gave us
     no IntersectionObserver (the module sets html.nav-noaway when it cannot wire the retract). */
  html:not(.js) body, html.nav-noaway body {
    padding-bottom: calc(var(--nav-dock-h) + 20px + env(safe-area-inset-bottom, 0px));
  }
}
@media (max-width: 380px) {
  .nav-dock { width: calc(100vw - 14px); bottom: calc(8px + env(safe-area-inset-bottom, 0px)); }
  .nav-dock-label { font-size: 9.5px; letter-spacing: .07em; }
}


/* ---------- forced colours ----------
   The capsule is dropped here on purpose: hue must never be the only thing saying which tab you
   are on. The [aria-current] outline is the substitute, which is why picking a tab has to set it
   at once rather than waiting for the scroll spy. */
@media (forced-colors: active) {
  .nav-glow { display: none; }
  /* and the glyph halo with it. forced-colors overrides COLOUR, never filter, so the drop-shadow set
     on the glyphs above survives into high contrast; in a LIGHT high-contrast theme that is a dark
     smudge around every glyph, and the capsule it was defending the glyph against is display:none
     on the line above. The selector mirrors the one that sets it -- :not() carries its argument's
     specificity, so both are (0,4,0) -- and this one wins on source order. */
  .nav-dock-tab:not(.nav-dock-go) .nav-dock-icon .i { filter: none; }
  .nav-dock-pill { border: 1px solid CanvasText; background: Canvas; }
  .nav-dock-tab[aria-current], .nav-bar a[aria-current] { outline: 2px solid Highlight; outline-offset: 2px; }
  /* .is-lit too, and after it: outside this block .nav-dock-go.is-lit .nav-dock-icon is (0,3,0) and
     sets a custom property, which forced colours replaces with Canvas. Without this the Start disc
     goes blank at exactly the moment it is the current tab. */
  .nav-dock-go .nav-dock-icon, .nav-dock-go.is-lit .nav-dock-icon { background: Highlight; color: Canvas; }
}
