/* ==========================================================================
   FRONTGRADE  ·  fg2 PAGE HEADER
   The sitewide header contract as one component, shared by every page family
   that is not the interior pattern. Nine templates print this band:

     page--fg2-capability      the four capability pages
     page--fg2-mission         the six mission area pages
     page--fg2-news            the news and insights hub
     page--fg2-events          the events page
     page--fg2-document        the legal documents
     node--fg2-article         news, blog and press release
     _fg2-catalog              the product catalog landings
     commerce-product          product detail
     views-view--global-search the search results page

   Requires tokens.css and components.css to be loaded first. Attached by
   frontgrade/fg2-page-header, which those nine templates attach by name.
   --------------------------------------------------------------------------
   WHAT THIS FILE IS FOR. Those families each drew their own hero: a full
   bleed photograph under a two-gradient scrim, a hand-written breadcrumb in a
   per-family class (.cap-crumbs, .mi-crumbs, .fg-news-crumbs) at 12px, and a
   headline resolving to the --fs-h1 primitive rather than to the page
   headline role. This file replaces all of them with the one band the tokens
   contract specifies: a drawn ground, one trail at one size with Home always
   present, a 32px mark slot, and the headline at the --fg-h1 role clamp.

   IT IS THE CONTRACT'S ANATOMY, NOT A SECOND DESIGN. Every measurement below
   is either a role token from tokens.css section 14 or a value carried from
   the reference implementation, the interior hero v2 in interior.css sections
   2, 3 and 3a. Where a number appears as a literal here it is because that
   number is a literal there, and the source line is named beside it.

   ONE FILE, ONE NAMESPACE, AND THAT IS THE POINT OF IT. The band was built
   twice in parallel, once as .fg-pagehead here and once as .fg-phead in
   fg2/css/pagehead.css, because two conversions of the same contract were in
   flight at the same time. Two files stating one contract is the exact fault
   the consistency pass exists to prevent, so the second file's three rules
   that this one did not have (the last-crumb ellipsis cap, the document meta
   line and the bracket form of the mark) were brought here, its five
   templates were repointed at these class names, and it was deleted. Nothing
   in the anatomy differed between the two: same drawn grounds, same declared
   stack order, same token values.

   WHY IT IS A SEPARATE FILE AND NOT NINE EDITS. The families load different
   page stylesheets, so the same band written into each would be nine copies
   drifting apart from the first design change onward. It is also why this
   file cannot simply be interior.css: every rule in that file is scoped under
   .fg-interior, which the node wrappers put on a node's root element, and
   that class also carries interior.css's own prose, heading and component
   rules, which are written for a page built out of the interior paragraph
   components. These pages are not built that way.

   IT MUST WIN AGAINST TWO LEGACY SHEETS, AND IT DOES SO ON SPECIFICITY.
   styles/dist/base.css sets element level type for a white page (body p is
   #121212 at 20px) and styles/dist/component.css carries the previous site's
   breadcrumb, including a rule that replaces the Home link's text with an
   18x18 mask image at font-size 0. Both are loaded on these families. The
   selectors below are built to outrank them, and each place that needed extra
   weight says why beside itself.

   CONTRAST. Ratios are the sRGB relative-luminance formula tokens.css states,
   against the exact surface the text sits on.
     --text-display   on --surface-base   17.90:1   the headline
     --text-muted     on --surface-base    5.57:1   lede, trail links, prose
     --text-secondary on --surface-base    5.57:1   the trail's plain segments
     --accent         on --surface-base    5.22:1   the eyebrow
   The band draws a geometric ground under its own copy, so every backdrop it
   can produce is enumerated in interior.css section 3a, one table per
   variant. The tightest figure across the three is 4.54:1 against a 4.5
   minimum, and every figure there is computed with the scrim ignored.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. THE BAND

   THE HEADER CLEARANCE IS NOT IN THIS BAND, AND THAT IS DELIBERATE. The site
   header is fixed and transparent (components.css section 10). Every page
   that prints this band prints a .fg-header-offset spacer above it, which is
   how the reference implementation's band is cleared too, rather than baking
   the header's height into this band's padding. Two reasons. The band then
   matches the contract's section 6 table exactly, value for value, instead of
   carrying a padding and a floor that no other implementation of the anatomy
   has. And the clearance stays a markup decision, so these templates render
   correctly against any stylesheet that implements the contract, not only
   against this one.

   The spacer's height is --header-offset and its one conditional case, a page
   carrying a system message, is in admin-context.css. It is worth knowing
   that the spacer reached no page at all until this pass: it was printed on
   {% if not page.pre_content %} and the messages region is never empty, so
   what actually cleared the header was an empty message strip's padding, at
   109px on a phone and 128px on a desktop. The visible gap above this band is
   therefore 17px and 36px smaller than it was, at --header-offset-mobile 73px
   and --header-offset 92px.

   THE FLOOR IS A FLOOR, NOT A HEIGHT. Every page in these four families
   prints a trail, a mark and a headline at display scale, so the rendered
   band is taller than its floor on every page measured; the floor only guards
   the shortest possible stack. svh rather than vh because vh on a mobile
   browser is the height the viewport has with the toolbars retracted; the vh
   line above each svh line is the fallback for a browser that does not know
   the unit and is deliberately the same number.
   -------------------------------------------------------------------------- */

.fg-pagehead {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: flex-start;
  min-height: max(300px, 32vh);
  min-height: max(300px, 32svh);
  padding-block: var(--fg-band-pad-top) var(--fg-band-pad-bottom);
  background: var(--surface-base);
  border-bottom: var(--border-hairline-w) solid var(--border-hairline);

  /* The band's own padding is the only thing between the site header and the
     first line of the page, so it is named rather than left to a section
     token that also spaces bands from each other. interior.css:232. */
  --fg-band-pad-top: clamp(20px, 0.9rem + 1.1vw, 30px);
  --fg-band-pad-bottom: clamp(40px, 1.9rem + 2.2vw, 64px);
}


/* --------------------------------------------------------------------------
   2. THE COPY STACK

   ORDER IS DECLARED, NOT INHERITED FROM THE MARKUP. That is what lets one
   stylesheet serve four templates that emit different subsets of the stack:
   the events page has no eyebrow, the news hub and the capability pages carry
   a button row, and the mark below the trail is drawn as this container's
   ::before, which is a flex item like any other child and would otherwise be
   laid out above the trail the template prints first.

     1  the trail          always present
     2  the mark           the accent rule OR the eyebrow, exactly one
     3  the headline
     4  the lede           optional
     5  the meta line      optional, a dated document's own line
     6  the actions        optional, see below

   SLOTS 5 AND 6 ARE ADDITIONS TO THE CONTRACT'S FOUR, AND BOTH ARE
   DELIBERATE. The legal documents state their date with the document rather
   than in page furniture, and three families carry either approved hero
   buttons or the pending markers that stand in for copy they have not been
   given. Dropping either would be a content decision made inside a header
   conversion. Both sit below the lede, so nothing above the headline changes
   and the mobile fold budget in section 7 of the contract is untouched.

   The search results page puts its query field in this same region of the
   stack; that order is declared in search.css, on that page's own class, so
   this file does not need to know the field exists.
   -------------------------------------------------------------------------- */

.fg-pagehead > .fg-container {
  position: relative;
  z-index: 3;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.fg-pagehead > .fg-container > .fg-pagehead__crumbs  { order: 1; }
.fg-pagehead > .fg-container::before                 { order: 2; }
.fg-pagehead > .fg-container > .fg-pagehead__eyebrow { order: 2; }
.fg-pagehead > .fg-container > .fg-h1                { order: 3; }
.fg-pagehead > .fg-container > .fg-pagehead__lede    { order: 4; }
.fg-pagehead > .fg-container > .fg-pagehead__meta    { order: 5; }
.fg-pagehead > .fg-container > .fg-pagehead__actions { order: 6; }


/* --------------------------------------------------------------------------
   3. THE TRAIL

   IT IS THE RENDERED SYSTEM BREADCRUMB, printed from a single render of the
   breadcrumb block, so Home is its first item on every page and the trail
   cannot disagree with the site's own idea of where the page sits. The four
   hand-written trails these templates carried before are exactly what the
   contract's section 10 lists as out of contract.

   ONE LANDMARK. The rendered block already emits
   <nav role="navigation" aria-labelledby="system-breadcrumb">, so the slot
   that holds it is a plain container carrying the class and never a second
   <nav>. Every rule below is class based for that reason.

   THE INNER NAV IS FLATTENED so the list's own flex row is the only layout in
   play, which is what interior.css:172 does with the same markup.

   WHY THESE SELECTORS NAME THE BLOCK'S OWN CLASSES. styles/dist/component.css
   styles this markup for the previous site, and several of its rules score
   higher than a two class selector:
     .breadcrumb > li.breadcrumb-item + .breadcrumb-item::before   (0,3,2)
     .breadcrumb > li:nth-child(2):before                          (0,3,1)
     .breadcrumb-item:first-child > a[href="/"]                    (0,3,1)
   The last of those is the one that matters most: it sets font-size 0 on the
   Home link and paints an 18x18 house mask in its place, so the word Home
   disappears and the trail's first item stops being 14px type. Naming
   .breadcrumb and .breadcrumb-item here is what outranks all three.
   -------------------------------------------------------------------------- */

.fg-pagehead .fg-pagehead__crumbs {
  margin: 0 0 var(--fg-crumb-gap);
  padding-block: 0;
  max-width: 100%;
  background: transparent;
  font-size: var(--fg-crumb);          /* 14px */
  line-height: var(--fg-crumb-line);   /* 22px, the trail's own line box */
  color: var(--text-secondary);
}

/* The block ships a visually hidden heading and a nav element around the
   list. Neither draws anything, and flattening the nav keeps the list's own
   flex row as the only layout. The heading is held out of flow here as well
   as by its own .visually-hidden rule, because the fg2 sheets do not define
   that class and a page reaching this band without core's stylesheet would
   otherwise print the word Breadcrumb above the trail. */
.fg-pagehead .fg-pagehead__crumbs nav { display: contents; }

.fg-pagehead .fg-pagehead__crumbs h2 {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.fg-pagehead .fg-pagehead__crumbs .breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: inherit;
  line-height: inherit;
  letter-spacing: normal;
  text-transform: none;
}

/* THE ITEMS ARE BLOCKS, NOT INLINE FLEX ROWS, AND THAT IS WHAT MAKES THE CAP
   BELOW WORK. text-overflow applies to a block container and not to a flex
   one, so an item laid out as inline-flex cannot carry an ellipsis. The row
   is unchanged either way: the list is the flex container, its column gap is
   the space between two items, and the separator carries its own margin on
   the side the gap does not fall. */
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item {
  display: block;
  margin: 0;
  padding: 0;
  min-width: 0;
  color: var(--text-secondary);        /* 5.57:1 on --surface-base */
}

/* One separator between two items and none anywhere else. The legacy sheet
   draws this glyph in #fff and hides it on the second item; both of those
   rules are outranked here rather than left to fight the flex gap. */
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item + .breadcrumb-item::before {
  content: "/";
  display: inline-block;
  margin: 0 var(--space-2) 0 0;
  color: var(--border-ui);
}

/* THE LAST CRUMB IS CAPPED, AND THAT IS A FOLD RULE MEASURE.

   The site's breadcrumb carries the current page as its last segment, and on
   the article, product, catalog and document families that segment is the
   page title: a hundred character news headline, or a product's full
   descriptive name. Left to run it wraps the trail to several lines at 390,
   and every one of those lines is spent out of the budget the headline needs
   to paint inside the first viewport. Measured on the article family before
   the cap: the trail ran to a second line and the headline started 24.9px
   lower than the canon page starts its own.

   The cap is a display constraint and nothing else. The trail is still the
   single rendered block, Home is still its first item, and the current page
   is still in it and still announced in full to a screen reader, because
   text-overflow elides the painted glyphs and does not touch the text. */
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item:last-child {
  max-width: min(100%, 30ch);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A CRUMB THAT IS A LINK HAS TO LOOK UNLIKE THE CRUMB THAT IS NOT.

   Measured on 51 pages before this rule: every crumb link and the non-link
   current-page item computed the same rgb(125,137,163) at the same weight with
   text-decoration-line: none. Link against surrounding text measured 1.00:1.
   Nothing at all marked the trail as navigable, which fails WCAG 1.4.1
   outright, since there was no colour cue to be the sole cue.

   THE TREATMENT IS G183, WHICH IS THE TECHNIQUE FOR A LINK THAT CARRIES NO
   RESTING UNDERLINE. It has two halves and needs both:

     1. the link is --text-display against the current item's --text-muted,
        which measures 3.22:1 between the two and clears the 3:1 the technique
        asks for. --text-primary was the other candidate and measures 2.91:1,
        which does not, so the display tone is the one that works.
     2. an underline appears on hover AND on focus, so the distinction does not
        rest on colour for a pointer or a keyboard.

   Both tones still clear their own ground comfortably: --text-display is
   17.90:1 on --surface-base and --text-muted is 5.57:1, so making the links
   brighter costs the trail nothing in legibility. The trail stays quiet
   because nothing else about it moves: same 14px role, same weight, same
   separator, no resting underline.

   :link and :visited are named as well as the bare selector because the
   legacy sheet states this colour on both arms, and a bare `a` ties with the
   arm rather than beating it. */
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item a,
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item a:link,
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item a:visited {
  color: var(--text-display);          /* 17.90:1 on --surface-base, 3.22:1 against the current crumb */
  text-decoration: none;
  text-underline-offset: var(--fg-link-offset);
  transition: color var(--dur-quick) var(--ease-standard);
}

.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item a:hover,
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item a:focus-visible {
  color: var(--accent-text-safe);      /* 5.22:1 on --surface-base */
  text-decoration: underline;
}

/* The current page is the one crumb that is not a link, and it keeps the quiet
   tone. Naming it here rather than leaving it to inherit is what makes the
   3.22:1 above a property of the pair rather than an accident of the wrapper. */
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item:last-child {
  color: var(--text-muted);            /* 5.57:1 on --surface-base */
}

/* HOME IS A WORD HERE, NOT A HOUSE. component.css replaces the first link's
   text with a mask image at font-size 0, which takes the trail's first item
   out of the 14px role, drops its hit area to 18x18, and leaves a page whose
   trail begins with an unlabelled glyph. The reset below is the whole of that
   rule undone, and it is scoped to this band so nothing outside it moves. */
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item:first-child > a[href="/"],
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item:first-child > a[href="/"]:link,
.fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item:first-child > a[href="/"]:visited {
  -webkit-mask-image: none;
  mask-image: none;
  background-color: transparent;
  background-image: none;
  width: auto;
  height: auto;
  font-size: inherit;
  line-height: inherit;
  vertical-align: baseline;
  text-indent: 0;
  display: inline;
}


/* --------------------------------------------------------------------------
   4. THE MARK SLOT, ALWAYS 32px TALL

   This is the load-bearing constraint the contract states: the headline
   starts at the same distance below whichever mark the page carries.

     form one, no section named   a 2px rule plus a 30px gap
     form two, a section named    12px of type at leading none plus a 20px gap

   The switch withdraws the rule wherever an eyebrow prints, so the slot holds
   one mark and not two. A browser without :has() draws both rather than
   losing either, which is the same trade interior.css:283 takes.
   -------------------------------------------------------------------------- */

.fg-pagehead > .fg-container::before {
  content: "";
  display: block;
  width: var(--space-10);              /* 64px */
  height: 2px;
  margin-bottom: calc(var(--space-7) - var(--space-05));   /* 30px, total 32 */
  background: var(--accent);           /* 5.22:1 on --surface-base, non-text */
}

.fg-pagehead > .fg-container:has(.fg-pagehead__eyebrow)::before { display: none; }

/* THE EYEBROW IS THE GLOBAL ONE. Family, weight, letter spacing, case and
   colour all come from .fg-eyebrow in components.css, which is the component
   the contract's type role table describes. Only the two values that make the
   32px slot are set here: leading none, already the global value and restated
   so the arithmetic is readable, and a 20px gap in place of the global 12.
   12 + 20 = --fg-mark-slot, which is the same 32px the accent rule above
   makes out of 2 + 30. */
.fg-pagehead .fg-pagehead__eyebrow {
  margin: 0 0 calc(var(--fg-mark-slot) - var(--fg-eyebrow));   /* 20px */
  max-width: 100%;
  font-size: var(--fg-eyebrow);        /* 12px */
  line-height: 1;
  text-transform: var(--fg-eyebrow-case);
}

/* THE BRACKET FORM OF THE MARK, contract section 6. Five families derive the
   section name and the page's depth from the breadcrumb's own links rather
   than authoring an eyebrow per page, and print it as [ 02 SECTION ]. The
   brackets and the index are real elements marked aria-hidden in the
   template, so the accessible name of the row is the section name alone;
   they are elements rather than generated content because generated content
   is exposed in the accessibility tree and cannot be hidden from there.

   IT IS A MODIFIER, NOT THE BASE, because the other four families print an
   approved editorial string in this slot and that string is set in the body
   face at the contract's own eyebrow tracking. Both forms are 12px, leading
   none, uppercase and 20px clear of the headline, so the mark slot is 32px
   whichever one a page carries. */
.fg-pagehead .fg-pagehead__eyebrow--mark {
  display: flex;
  align-items: center;
  gap: 0.62em;
  font-family: var(--font-mono);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.16em;
  color: var(--accent);                /* 5.22:1 on --surface-base */
}

/* The brackets and the index are the quiet grey, not the orange, so the row
   holds one accent and the section name is the thing carrying it. */
.fg-pagehead .fg-pagehead__eyebrow-bracket { color: var(--text-secondary); }  /* 5.57:1 */

.fg-pagehead .fg-pagehead__eyebrow-idx {
  color: var(--text-secondary);        /* 5.57:1 on --surface-base */
  letter-spacing: 0.10em;
  padding-inline-end: 0.62em;
  border-inline-end: 1px solid var(--border-ui);
}

.fg-pagehead .fg-pagehead__eyebrow-text { min-width: 0; overflow-wrap: break-word; }


/* --------------------------------------------------------------------------
   5. THE HEADLINE, THE LEDE AND THE ACTIONS

   THE HEADLINE TAKES THE ROLE CLAMP, NOT THE PRIMITIVE. .fg-h1 on its own
   resolves to --fs-h1, which is the smaller 40 to 72 setting; the page
   headline role is --fg-h1, 52 to 104. Shipping a page headline that resolves
   to --fs-h1 is the last row of the contract's out of contract table, and all
   four of these families were doing it.

   THE HEADLINE IS ONE UNIT. It is a single text node, so the accessible name,
   text selection and a copy of the line are the sentence they read as. The
   reference implementation splits it one word to a span so its own arrival
   animation has something to attach to; these pages arrive through the shared
   reveal in motion.js, which works on the whole element, so there is nothing
   here for a split to carry and it is not made.

   The static state is the complete one: fully visible, and no rule in this
   file names an animation.
   -------------------------------------------------------------------------- */

.fg-pagehead .fg-h1 {
  margin: 0;
  max-width: var(--fg-h1-measure);     /* min(100%, 16ch) */
  font-size: var(--fg-h1);             /* 52 -> 104       */
  line-height: var(--lh-display);      /* leading none    */
  overflow-wrap: break-word;
  color: var(--text-display);          /* 17.90:1 on --surface-base */
}

/* Some families print the headline one word to a span so a line can arrive in
   sequence; inline-block is what lets a word carry a transform. The space
   between two spans is a real text node, so the accessible name, the text
   selection and a copy of the line are the sentence they read as. */
.fg-pagehead .fg-hw { display: inline-block; }

.fg-pagehead .fg-pagehead__lede {
  margin: var(--space-5) 0 0;
  max-width: var(--measure-body);      /* 620px */
  color: var(--text-muted);            /* 5.57:1 on --surface-base */
}

/* A dated document states its date with the document, not in page furniture.
   It sits below the lede, so nothing is added above the headline and the
   mobile fold budget is untouched. */
.fg-pagehead .fg-pagehead__meta {
  margin: var(--space-5) 0 0;
  color: var(--text-secondary);        /* 5.57:1 on --surface-base */
}

/* The button row and, on the events page, the pending markers that stand in
   for copy that has not been written. Same step off the copy above it that
   the media band gave them, so nothing about the buttons themselves moves. */
.fg-pagehead .fg-pagehead__actions {
  margin-top: clamp(24px, 1.3rem + 1.2vw, 36px);
  max-width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
}

/* base.css gives every paragraph a 1rem margin top and bottom, which inside
   a flex column would sit on top of the gap above. The gap is the rhythm
   here, so the element margin goes. */
.fg-pagehead .fg-pagehead__actions p { margin: 0; }


/* --------------------------------------------------------------------------
   6. THE DRAWN GROUND  ·  three variants, one switch

   THE GROUND IS DRAWN, NEVER PHOTOGRAPHED. Everything below is an inline SVG
   or a CSS gradient carried in this file: no request, no asset, no image from
   the node. That is the whole point of the conversion for these four
   families, each of which was loading a full-bleed JPEG, and three of which
   were loading the same full-bleed JPEG.

   HOW TO SWITCH IT. The template prints one attribute on the band,
   data-fg-hero-art, and the three accepted values are signal, beacon and
   typo. A band that carries no attribute gets signal, because the default
   variant's block also matches :not([data-fg-hero-art]).

   WHICH FAMILY TAKES WHICH, and why:
     capability   signal   the trace system is the literal drawing of what a
                           capability page sells
     mission      beacon   bloom and planes read as environment and depth,
                           which is what a mission area is
     news hub     typo     near zero ornament, so the headline and the dense
                           card grid under it carry the page
     events       typo     the events page is the hub's listing sibling and
                           shares its ground on purpose, not by omission

   FOUR LAYERS, IN A FIXED ORDER. The band isolates, so the order is the whole
   of the stacking question and it is stated as z-index on every layer rather
   than left to document order:

     z 0   ::before             the field: hairlines, planes, bloom, grain
     z 1   .fg-pagehead__art    the accent layer, one orange mark per page
     z 2   ::after              the scrim
     z 3   > .fg-container      the copy

   THE VARIANT BLOCKS BELOW ARE CARRIED FROM interior.css, LITERAL FOR
   LITERAL, with only the selector changed. They are the same three grounds,
   so they are the same three sets of custom properties and the same contrast
   tables, and copying them rather than reworking them is what keeps the two
   bands the same drawing. The two files therefore have to move together;
   extracting the three blocks into one sheet both can read is the right end
   state and is noted for the coordinator in migration/verify/HEADERS-B1.md.

   EVERY MARK IS AN OPAQUE LITERAL, AND THAT IS THE CONTRAST ARGUMENT. The
   full derivation, the palette and the per variant tables are in interior.css
   section 3a and are not restated here, because a second copy of a table is a
   second thing to keep true. The figures are unchanged: the tightest anywhere
   in the three is 4.54:1, the eyebrow row over grain on beacon's lightest
   plane, against a 4.5 threshold, and every figure is computed with the scrim
   ignored so the guarantee does not depend on where a mark falls.
   -------------------------------------------------------------------------- */

/* THE FIELD. */
.fg-pagehead::before {
  content: "";
  position: absolute;
  inset: var(--fg-hero-field-inset, 0);
  z-index: 0;
  pointer-events: none;
  background-image: var(--fg-hero-art-image);
  background-size: var(--fg-hero-art-size);
  background-position: var(--fg-hero-art-position);
  background-repeat: var(--fg-hero-art-repeat);
}

/* THE ACCENT LAYER. One empty element, emitted by every one of the four
   templates, holding no content and taking no focus. */
.fg-pagehead__art {
  position: absolute;
  inset: var(--fg-hero-accent-inset, 0);
  z-index: 1;
  pointer-events: none;
  background-image: var(--fg-hero-accent-image);
  background-size: var(--fg-hero-accent-size);
  background-position: var(--fg-hero-accent-position);
  background-repeat: no-repeat;
}

/* THE SCRIM. The same zone on every variant, so the copy column is held back
   from the art by a layer that does not know what is under it. */
.fg-pagehead::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: var(--fg-hero-scrim);
}

.fg-pagehead {
  --fg-hero-scrim: linear-gradient(90deg,
    rgba(9, 12, 20, 0.88) 0%,
    rgba(9, 12, 20, 0.80) 38%,
    rgba(9, 12, 20, 0.58) 64%,
    rgba(9, 12, 20, 0.30) 86%,
    rgba(9, 12, 20, 0.16) 100%);
}


/* ---- VARIANT: signal  ·  the electronics backbone -----------------------
   THE DEFAULT, and the most literal drawing of what the company makes: a
   trace system. Orthogonal runs with chamfered corners, square pads at the
   turns, a quiet reference hairline behind them, and one run in the accent
   carrying a pad of its own. The homepage draws connection as arcs between
   platforms; a board is the same system at the other end of the scale, and
   an interior page is where that reads.

   CHAMFERS, NOT RIGHT ANGLES, because a routed trace is never mitred square;
   the 45 degree corner is the one detail that stops this reading as a chart
   grid. Every run is a single stroke of one literal, so a run crossing a run
   resolves to whichever is painted later and never to a lighter sum.        */
.fg-pagehead:not([data-fg-hero-art]),
.fg-pagehead[data-fg-hero-art="signal"] {
  --fg-hero-art-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.012 0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 340' preserveAspectRatio='xMidYMid slice'%3E%3Cg fill='none' stroke='%2310141d' stroke-width='1'%3E%3Cpath d='M0 84H1200M0 256H1200M368 0V340M884 0V340'/%3E%3C/g%3E%3Cg fill='none' stroke='%23131721' stroke-width='1.6'%3E%3Cpath d='M0 292H188L244 236H648L700 184H1200'/%3E%3Cpath d='M0 148H96L152 92H520L568 44H1200'/%3E%3Cpath d='M264 340V284L316 232H1200'/%3E%3Cpath d='M0 208H72L124 156H436L484 204H1200'/%3E%3Cpath d='M1104 0V340'/%3E%3C/g%3E%3Cg fill='%23151923'%3E%3Crect x='240' y='232' width='9' height='9'/%3E%3Crect x='696' y='180' width='9' height='9'/%3E%3Crect x='148' y='88' width='9' height='9'/%3E%3Crect x='564' y='40' width='9' height='9'/%3E%3Crect x='312' y='228' width='9' height='9'/%3E%3Crect x='480' y='200' width='9' height='9'/%3E%3Crect x='1100' y='160' width='9' height='9'/%3E%3C/g%3E%3C/svg%3E");
  --fg-hero-art-size: 220px 220px, cover;
  --fg-hero-art-position: 0 0, center;
  --fg-hero-art-repeat: repeat, no-repeat;
  --fg-hero-accent-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 340' preserveAspectRatio='xMidYMid slice'%3E%3Cpath d='M0 320H132L200 252H592L656 188H1200' fill='none' stroke='%23281618' stroke-width='2'/%3E%3Crect x='195' y='247' width='11' height='11' fill='%23281618'/%3E%3Crect x='651' y='183' width='11' height='11' fill='%23281618'/%3E%3C/svg%3E");
  --fg-hero-accent-size: cover;
  --fg-hero-accent-position: center;
}

/* ---- VARIANT: beacon  ·  bloom and planes -------------------------------
   Tone and light. A low orange bloom sits in the lower right of the band and
   two planes cut on the site's shear angle step up the surface ladder over
   it, so the band reads as depth rather than as drawing. The single orange
   is the bloom and the one hairline edge on the upper plane's leading side.

   THE BLOOM IS THE BOTTOM LAYER, which is a contrast decision as much as a
   compositional one: the planes paint over it at full opacity, so no pixel is
   ever bloom composited onto a plane and the table needs no row for a mix
   that cannot occur.

   THE PLANE STOPS ARE HARD. Every colour stop pair shares a position, so
   there is no ramp between two surfaces and no band of intermediate values.
   The only ramp in the variant is the bloom, and section 3a states why that
   one is still enumerable.                                                  */
.fg-pagehead[data-fg-hero-art="beacon"] {
  --fg-hero-art-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.012 0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E"),
    linear-gradient(100deg, transparent 0 72%, #131928 72% 100%),
    linear-gradient(100deg, transparent 0 52%, #0e1220 52% 100%),
    radial-gradient(78% 132% at 68% 104%, #1f1317 0%, #141015 40%, #090c14 76%, #090c14 100%);
  --fg-hero-art-size: 220px 220px, 100% 100%, 100% 100%, 100% 100%;
  --fg-hero-art-position: 0 0, center, center, center;
  --fg-hero-art-repeat: repeat, no-repeat, no-repeat, no-repeat;
  --fg-hero-accent-inset: -10% 0;
  --fg-hero-accent-image:
    linear-gradient(100deg, transparent 0 71.9%, #281618 71.9% 72.06%, transparent 72.06% 100%),
    linear-gradient(100deg, transparent 0 51.94%, #281618 51.94% 52.02%, transparent 52.02% 100%);
  --fg-hero-accent-size: 100% 100%, 100% 100%;
  --fg-hero-accent-position: center, center;
}

/* ---- VARIANT: typo  ·  the type is the hero -----------------------------
   Near zero ornament. Two quiet vertical hairlines set the band's measure,
   one accent rule stands at the foot of the first of them, and the grain
   keeps the ground from reading as flat black. Everything else is the
   headline, which is set a full step larger here than on the other two
   variants and is the only thing in the band with any weight.               */
.fg-pagehead[data-fg-hero-art="typo"] {
  --fg-hero-art-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.012 0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)'/%3E%3C/svg%3E"),
    linear-gradient(#151923, #151923),
    linear-gradient(#151923, #151923);
  --fg-hero-art-size: 220px 220px, 1px 100%, 1px 100%;
  --fg-hero-art-position: 0 0, 56% 0, 74% 0;
  --fg-hero-art-repeat: repeat, no-repeat, no-repeat;
  --fg-hero-accent-image: linear-gradient(#281618, #281618);
  --fg-hero-accent-size: 2px 38%;
  --fg-hero-accent-position: calc(56% - 1px) 100%;
}


/* --------------------------------------------------------------------------
   7. THE PROSE COLOUR FLOOR  ·  the one rule in this file below the header

   WHAT IS WRONG WITHOUT IT. styles/dist/base.css is written for a white page
   and sets type on the elements themselves:

     body p { font-size: 1.25rem; line-height: 1.75; color: #121212;
              margin-top: 1rem; margin-bottom: 1rem }

   .fg-prose in components.css sets the reading colour and size on the
   CONTAINER, so a paragraph inside it never inherits either: the element
   rule matches the paragraph directly and wins against inheritance no matter
   how weak it is. Measured on /capabilities/microelectronics before this
   rule, the capability overview computed rgb(18, 18, 18) on the band's
   rgb(9, 12, 20), which is 1.04:1. The copy was there and could not be read.

   WHY IT IS NOT A COLOUR PATCH. A size alone does not reproduce a rendering
   and neither does a colour alone, so this lands the whole Body row of the
   contract's type table: --fg-body, --lh-prose, --text-muted. The paragraph
   rhythm is restated as a token because zeroing base.css's 1rem margins
   without replacing them would run the overview's paragraphs together.

   SCOPE. .fg-page is on the <main> of the four page templates that had this
   defect, capability, mission, news hub and events, and nowhere else, so the
   rule reaches them and no other page even though this file is now attached
   by nine templates. The other five carry their own reading colour in their
   own family stylesheets. Two classes also outrank body p, which is (0,0,2),
   with room to spare.

   base.css IS NOT EDITED. It is a built artefact of the previous site and it
   is loaded on every page; changing it is a sitewide change made from a
   dist directory, which is not what a header conversion should do.
   -------------------------------------------------------------------------- */

.fg-page .fg-prose :where(p, li, dd, dt, figcaption, blockquote) {
  color: var(--text-muted);            /* 5.57:1 on --surface-base */
  font-size: var(--fg-body);           /* 16 -> 17 */
  line-height: var(--lh-prose);        /* 1.75     */
}

.fg-page .fg-prose :where(p, ul, ol) { margin: 0 0 var(--space-5); }
.fg-page .fg-prose > :last-child     { margin-bottom: 0; }


/* --------------------------------------------------------------------------
   8. THE BAND'S PROPORTIONS, ONE STEP PER BREAKPOINT

   The floor and the viewport fraction come down together, exactly as
   interior.css:1889 onward brings them down and at exactly its values. The
   floor stops a short headline collapsing the band on a wide, shallow window;
   the fraction stops the floor itself eating a small screen. The header's own
   clearance is not in these figures because it is not in this band; the
   .fg-header-offset spacer above it carries that and steps to its mobile
   height on its own rule at 1024px in components.css.

     >= 1025px   max(300px, 32svh)
     <= 1024px   max(280px, 30svh)
     <=  768px   max(240px, 28svh)
     <=  480px   max(220px, 26svh)

   THE SCRIM WIDENS AS THE COPY DOES. On a wide band the copy occupies about
   the left half and the art has the rest; below 768px the copy is the whole
   column, so the scrim's opaque end is carried right until the art is a
   margin note rather than a field the headline sits in. Nothing about the
   contrast tables changes here: every figure in them is computed with the
   scrim ignored, and a scrim can only take a backdrop towards
   --surface-base, which is the best row in every one of them.
   -------------------------------------------------------------------------- */

@media (max-width: 1024px) {
  .fg-pagehead {
    min-height: max(280px, 30vh);
    min-height: max(280px, 30svh);
  }
}

@media (max-width: 768px) {
  .fg-pagehead {
    min-height: max(240px, 28vh);
    min-height: max(240px, 28svh);
    --fg-hero-scrim: linear-gradient(90deg,
      rgba(9, 12, 20, 0.94) 0%,
      rgba(9, 12, 20, 0.90) 54%,
      rgba(9, 12, 20, 0.62) 78%,
      rgba(9, 12, 20, 0.14) 100%);
  }
}

@media (max-width: 480px) {
  .fg-pagehead {
    min-height: max(220px, 26vh);
    min-height: max(220px, 26svh);
  }

  /* THE TRAIL IS HELD TO ITS OWN LINE BOX AT THE FOLD-CRITICAL WIDTH.
     --fg-crumb-line is 22px, one line, and every pixel the trail takes past
     it comes straight out of the headline's budget. At the 30ch cap a three
     crumb trail whose last segment is an article title still ran to two
     lines here; at 20ch it fits the line box. A deeper trail still wraps,
     and that is the right trade: a page five levels down has short display
     type and can afford the second line, while eliding its ancestors would
     cost the reader the path itself. */
  .fg-pagehead .fg-pagehead__crumbs .breadcrumb .breadcrumb-item:last-child {
    max-width: min(100%, 20ch);
  }
}


/* --------------------------------------------------------------------------
   9. THE LONG HEADLINE STEP DOWN

   WHAT THIS ANSWERS. Contract section 7 states one rule without exception:
   at 390 the page title paints inside the first viewport. Two published
   article titles cannot meet it at the role's own scale. Measured at 390 by
   844 across all 142 published news and blog nodes, 140 pass; the two that
   do not are 160 and 180 characters long and set 13 and 15 lines of display
   type. The overrun is the headline itself and not the anatomy above it: the
   band puts the h1's top within a pixel of where the canon page /about puts
   its own, so these two pages have the canon's exact budget and spend all of
   it on their own length.

   WHY A STEP AND NOT AN EXCEPTION. The rule the pages break is a rule about
   what a reader sees on a phone, and a stylesheet can honour it without
   asking anyone to rewrite a published headline. The alternative on the
   table was to admit documented exceptions, which would leave the site's own
   stated rule failing on live pages and would fail again the next time an
   editor writes a long title, because nothing would be watching.

   WHAT IT DOES NOT DO. It does not change the scale of a normal title. The
   modifier is put on the element by the template, which is the only place
   that can count characters, and only above the thresholds below; every
   other page in every family resolves --fg-h1 exactly as before, which is
   what the closing sweep measures at all four widths.

   WHY IT IS SCOPED TO 480 AND BELOW. That is where the rule it answers
   applies. Above it the role clamp is untouched on every page on the site,
   so a headline is the contract's own size wherever the contract states a
   size for it. The step therefore lands at a breakpoint this file already
   steps the band at, rather than introducing one.

   THE STEPS ARE FACTORS OF THE ROLE, NOT NEW SIZES. --fg-h1 is still the
   only place a page headline's scale is stated; a step is a fraction of
   whatever that token resolves to, so moving the role moves these with it.

     over 144 characters   x 0.84   43.9px at 390   .fg-h1--long
     over 220 characters   x 0.64   33.5px at 390   .fg-h1--xlong, a guard
                                                    rather than an answer to
                                                    a live page: no published
                                                    title is near it

   Thresholds are character counts on the rendered title, taken from the
   corpus rather than chosen: the longest title that clears the fold unaided
   is 144 characters and the shortest that does not is 160, so the first
   threshold sits inside that gap and no page that passes today is touched by
   this rule. The template that counts is where each threshold is applied.
   -------------------------------------------------------------------------- */

@media (max-width: 480px) {
  .fg-pagehead .fg-h1--long  { font-size: calc(var(--fg-h1) * 0.84); }
  .fg-pagehead .fg-h1--xlong { font-size: calc(var(--fg-h1) * 0.64); }
}


/* --------------------------------------------------------------------------
   9b. THE LONG HEADLINE STEP DOWN, ON THE WIDE BAND

   WHAT THIS ANSWERS. Section 9 above answers one rule, at 390, about whether
   the headline paints inside the first viewport. It says nothing about the
   wide band, and above 480 the role clamp is applied to every title at its
   full value however long the title is. Measured across all 142 published
   news and blog nodes at 1440 by 900, with the fonts settled: the h1 computes
   to 104px on every one of them, and 130 of the 142 draw a pagehead taller
   than 60 percent of the viewport. The worst is 1,724.6px, 191.6 percent of
   the viewport, 14 lines of display type from a 180 character title; the
   whole first screen and most of a second is the headline.

   THE TWO LADDERS ARE INDEPENDENT AND CANNOT REACH EACH OTHER. Section 9 is
   inside max-width 480 and reads .fg-h1--long and .fg-h1--xlong; this block
   is inside min-width 481 and reads .fg-h1--step2 to --step5. The template
   computes both from the same character count against different thresholds,
   because the two are calibrated against different things. Nothing here
   applies at 390 and nothing there applies at 1440, so the fold ladder's
   corpus result, 142 of 142 clearing the fold, is untouched by this block.

   WHY THE COLUMN STEPS AS WELL AS THE SIZE. --fg-h1-measure is stated in ch,
   so it is a column measured in characters and the line count a title sets is
   a property of that measure and not of the type size. Shrinking the type
   alone shrinks the column with it and the title keeps its line count exactly;
   the band gets shorter only in proportion to the size, which does not reach
   the budget on the long titles. Widening the column in ch is what removes
   lines. Each step therefore redefines both, and the two together are what
   the pairs below were solved for.

   THE PAIRS ARE MEASURED, NOT CHOSEN. Twenty candidate pairs were applied to
   the live h1 on all 142 articles at 1440 by 900 and the resulting band
   height read back off the rendered page. Each threshold in the template is
   one character below the SHORTEST title its pair fails on, rather than the
   longest it passes: length alone does not decide line count, because a title
   of long words wraps worse than a title of short ones at the same count, so
   the boundary has to clear the worst title at every length below it. That is
   why the thresholds are 42, 69, 98 and 179 rather than round numbers.

   Measured result per step over the corpus, after the change:

     class          factor  measure   size   n    column   worst band  worst %
     (none)          1.00     16ch   104px    7     754px     479.1px    53.2
     .fg-h1--step2   0.88     24ch  91.5px   32     995px     516.0px    57.3
     .fg-h1--step3   0.72     28ch  74.9px   60     950px     513.8px    57.1
     .fg-h1--step4   0.65     36ch  67.6px   42   1,102px     539.0px    59.9
     .fg-h1--step5   0.52     40ch  54.1px    1     980px     539.0px    59.9

   Corpus totals at 1440 by 900, before and after: bands over the 60 percent
   budget 130 then 0; tallest band 1,724.6px then 539px; tallest as a share of
   the viewport 191.6 percent then 59.9 percent; mean band 855px then 439px;
   most lines in one headline 14 then 5. At 390 by 844, nothing moved at all:
   the same two h1 sizes, the same band height on all 142 pages, and the fold
   rule still passing 142 of 142.

   NEITHER A SIZE NOR A MEASURE IS RESTATED. --fg-h1 is still the only place a
   page headline's scale is stated and --fg-h1-measure the only place its
   column is; a step is a fraction of the first and a redefinition of the
   second, so moving either token moves every step with it. The column stays
   well inside the container, which is 1,392px at 1440, so the headline is
   still a column rather than the full width of the band.

   THE FLOOR IS THE SECTION HEADING. The smallest step resolves to 54.1px at
   1440, which is clear of the 44px --fg-h2 role, so a stepped page headline
   never reads as smaller than a section heading on the same page.

   IT REACHES ARTICLE PAGEHEADS AND NOTHING ELSE, because the classes are put
   on the element by node--fg2-article.html.twig and no other template in the
   theme emits them. Search space: every .twig under templates/ and every rule
   under fg2/css. The homepage headline is not in this file's scope at all.
   -------------------------------------------------------------------------- */

/* THE FLOOR IS STATED IN THE RULE, NOT ASSUMED BY THE FACTORS. The block above
   records the invariant this ladder was solved under: "a stepped page headline
   never reads as smaller than a section heading on the same page", which held
   because the smallest step resolved to 54.1px against a 104px base. The base
   is now the 32 -> 58 --fg-h1 role, and the same factors put steps 3, 4 and 5
   at 41.8, 37.7 and 30.2px at 1440, all of them under the 44px --fg-h2 role.
   That inversion is visible on any article long enough to take step 3: the
   page headline renders smaller than the section headings below it.

   Flooring each step at --fg-h2 restores the stated invariant without naming a
   new size. The ladder still steps wherever it is above the floor, so step 2
   keeps its own value, and every step moves with the two tokens rather than
   needing to be resolved again if either is retuned. */
@media (min-width: 481px) {
  .fg-pagehead .fg-h1--step2 {
    --fg-h1-measure: min(100%, 24ch);
    font-size: max(var(--fg-h2), calc(var(--fg-h1) * 0.88));
  }
  .fg-pagehead .fg-h1--step3 {
    --fg-h1-measure: min(100%, 28ch);
    font-size: max(var(--fg-h2), calc(var(--fg-h1) * 0.72));
  }
  .fg-pagehead .fg-h1--step4 {
    --fg-h1-measure: min(100%, 36ch);
    font-size: max(var(--fg-h2), calc(var(--fg-h1) * 0.65));
  }
  .fg-pagehead .fg-h1--step5 {
    --fg-h1-measure: min(100%, 40ch);
    font-size: max(var(--fg-h2), calc(var(--fg-h1) * 0.52));
  }
}
