/* Metal Craft Engineering — mockup B: the division tabs. Loaded after style.css; adds to it, never restyles it.
   Three pieces, all built by build.py: the header's two-tab division switch (nav.seg-switch), the home page's tabbed
   division section (.seg-tabs tablist + .seg-panel tabpanels) and the sub-tab strip on division pages (nav.seg-sub).
   The active tab is marked with aria-current (links) or aria-selected (tabs); html[data-segment] (boot.js, before the
   first paint) picks the page tone, so a remembered choice never flashes. Every tab is a cut-corner steel plate, as the
   buttons are: square, with the top-left and bottom-right corners chamfered and the edge drawn by the background so it
   follows the cut. No pills, no dots, no glows. The chosen tab is edged in the page's tone (--accent, the interface
   accent, which follows html[data-segment]) with its label in the tone lightened for small text (--red-txt, 7:1 or more
   on the dark fill): an edge, never a fill, so it never reads as the call to action. A hovered tab gets a light edge, a
   keyboard-focused one a 2 px light edge in the same plate shape (an outline would be clipped away with the corners).
   Every colour is a style.css token, or one of the two below made from them. No inline styles: the CSP forbids them. */

/* Header height now includes the tab strips where they sit under the bar (phones: the division strip; division pages:
   the sub-tab row), so everything style.css offsets by --hdr (hero and page-head padding, the mobile menu, anchor
   scroll margins) clears them. The bar itself keeps its old height (--hdr-bar). */
:root{--hdr-bar:72px;--hdr-seg:0px;--hdr-sub:0px;--hdr:calc(var(--hdr-bar) + var(--hdr-seg) + var(--hdr-sub))}
/* The light edge of a hovered tab (half the text colour, so a theme that moves --txt moves it too): light, never the
   tone, so a hovered tab never looks like a second chosen one. */
:root{--tab-hover:color-mix(in srgb,var(--txt) 50%,transparent)}
.hdr-in{height:var(--hdr-bar)}
html:has(.seg-sub){--hdr-sub:calc(2.25rem + 12px)}

/* The plates: style.css's cut-corner plate (its clip-path and background stack), on the two-tab plates and on
   each sub-tab. --edge, --fill and --ew are registered there, so a state change fades. A tab cell's own edge (--seg-c,
   below) is registered here for the same reason. */
@property --seg-c{syntax:"<color>";inherits:false;initial-value:transparent}
.seg-switch,.seg-tabs,.seg-sub a{--cut:var(--cut-sm);--edge:var(--line-2);--fill:transparent;--ew:1px;border:0;border-radius:0;
  clip-path:polygon(var(--cut) 0,100% 0,100% calc(100% - var(--cut)),calc(100% - var(--cut)) 100%,0 100%,0 var(--cut));
  background:linear-gradient(var(--edge),var(--edge)) top/100% var(--ew) no-repeat,linear-gradient(var(--edge),var(--edge)) bottom/100% var(--ew) no-repeat,
    linear-gradient(var(--edge),var(--edge)) left/var(--ew) 100% no-repeat,linear-gradient(var(--edge),var(--edge)) right/var(--ew) 100% no-repeat,
    linear-gradient(to bottom right,transparent 50%,var(--edge) 0 calc(50% + var(--ew)),transparent 0) top left/var(--cut) var(--cut) no-repeat,
    linear-gradient(to bottom right,transparent calc(50% - var(--ew)),var(--edge) 0 50%,transparent 0) bottom right/var(--cut) var(--cut) no-repeat,var(--fill)}

/* Two-tab plates (the header switch, its strip on phones, the home tablist): one plate edged in a hairline, its two
   cells flush on it, so the plate's chamfers are theirs. A cell's own edge is an inset shadow for the straight sides and,
   at the plate's chamfer, the same diagonal the plate's edge uses. The hairline between the cells is the second cell's
   left line, dropped beside a first cell that has an edge of its own. */
.seg-switch a,.seg-tab{--seg-c:transparent;--seg-cw:1px;--seg-sep:var(--line-2);position:relative;display:inline-flex;align-items:center;justify-content:center;margin:0;border:0;border-radius:0;color:var(--txt-2);white-space:nowrap;box-shadow:inset 0 0 0 var(--seg-cw) var(--seg-c);transition:--seg-c .25s,color .25s}
:is(.seg-switch a,.seg-tab):first-child{background:linear-gradient(to bottom right,transparent 50%,var(--seg-c) 0 calc(50% + var(--seg-cw)),transparent 0) top left/var(--cut) var(--cut) no-repeat}
:is(.seg-switch a,.seg-tab):last-child{background:linear-gradient(to bottom right,transparent calc(50% - var(--seg-cw)),var(--seg-c) 0 50%,transparent 0) bottom right/var(--cut) var(--cut) no-repeat,linear-gradient(var(--seg-sep),var(--seg-sep)) left/1px 100% no-repeat}
:is(.seg-switch a,.seg-tab):is(:hover,.touch-hover){--seg-c:var(--tab-hover);color:var(--txt)}
:is(.seg-switch a[aria-current],.seg-tab[aria-selected="true"]){--seg-c:var(--accent);color:var(--red-txt)}
:is(.seg-switch a,.seg-tab):focus-visible{--seg-c:var(--txt);--seg-cw:2px}
/* slop-ok: outline-none replaced by designed :focus-visible (the cell's own edge, 2 px and light, in the plate's shape) */
:is(.seg-switch a,.seg-tab):focus-visible{outline:none}
:is(.seg-switch a:is([aria-current],:hover,.touch-hover,:focus-visible),.seg-tab:is([aria-selected="true"],:hover,.touch-hover,:focus-visible))+*{--seg-sep:transparent}

/* The header switch (961 px and wider): a 40 px plate beside the nav (44 px on a touch screen), filled as a plate over
   footage (--plate-dark, as the quote plate beside it) so its labels hold over the Forge behind a transparent header. */
.seg-switch{display:flex;flex:none;--fill:var(--plate-dark)}
.seg-switch a{min-height:2.5rem;padding:0 .875rem;font-size:.92rem;line-height:1.2}
@media (pointer:coarse){.seg-switch a{min-height:44px}}
/* Header fit, 961 to 1920 px, with the header's "Request a quote" plate (.hdr-quote, about 140 px) at the right end.
   Round B3.1 widened the bar (the 18% larger logo, a sixth nav item "Projects" and the Certifications drop-down's
   chevron), so the steps moved, measured against the content column's edge with 17 px to spare for a classic
   scrollbar: the quote plate steps aside from 961 to 1339 px (it stays in the menu and in every page's closing call to
   action; below 961 px style.css hides it); up to 1199 px the switch, the nav links and the bar's gaps tighten as
   before; up to 1099 px they tighten one step more (no gap between the nav links, .45rem a side, .86rem type), so the
   bar keeps to one line at 961 px. Nothing in the bar shrinks to fit (logo, nav, switch and quote keep their widths):
   the steps make the room. */
@media (min-width:961px){.hdr-in>:is(.logo,.nav,.seg-switch,.hdr-quote){flex-shrink:0}}
@media (min-width:961px) and (max-width:1339px){.hdr-in>.hdr-quote{display:none}}
/* (style.css insets the nav underline to the same .6rem and .45rem at these widths: change both together.) */
@media (min-width:961px) and (max-width:1199px){.hdr-in{gap:20px}.hdr .nav :is(a,.nav-dd-btn){padding:.5rem .6rem}.seg-switch a{padding-inline:.55rem;font-size:.85rem}}
@media (min-width:961px) and (max-width:1099px){.hdr-in{gap:12px}.hdr .nav{gap:0}.hdr .nav :is(a,.nav-dd-btn){padding:.5rem .45rem;font-size:.86rem}.seg-switch a{padding-inline:.4rem}}

/* Phones and tablets (the nav is in the menu): the switch is the same plate, full width between the page gutters, fixed
   directly under the header bar. It is part of the header, so it stays while the page scrolls: the bar keeps the
   strip's height below it (--hdr-seg), so the header's own background and bottom line take the strip in. Each tab is
   half the plate and 44 px tall, a full thumb-size target. */
@media (max-width:960px){
  :root{--hdr-seg:52px}
  .hdr-in{margin-bottom:var(--hdr-seg)}
  .seg-switch{position:absolute;left:var(--gut);right:var(--gut);top:var(--hdr-bar);display:grid;grid-template-columns:1fr 1fr;height:44px}
  .seg-switch a{min-height:44px;padding:0 10px;font-size:.88rem;letter-spacing:-.01em}
  /* On a division page the sub-tab row sits under the division strip. Once the page is scrolled it folds away (back at
     the top of the page, or as soon as one of its tabs takes keyboard focus), so while reading the fixed header is the
     bar and the strip alone. --hdr keeps the full height, so nothing on the page moves when it folds. */
  .hdr .seg-sub{overflow:hidden;transition:height .3s var(--ease),opacity .2s}
  .hdr.scrolled .seg-sub:not(:focus-within){height:0;opacity:0}
  /* Scrolling down tucks the division strip away as well (tabs.js sets .seg-tuck), so while reading the fixed header is
     the bar alone; scrolling back up, or reaching the top, brings the strip back, and so does keyboard focus on one of
     its tabs. Tucked, it takes no taps. */
  .hdr-in{transition:margin-bottom .3s var(--ease)}
  .seg-switch{transition:opacity .2s,transform .3s var(--ease)}
  .hdr.seg-tuck:not(:has(.seg-switch:focus-within)) .hdr-in{margin-bottom:0}
  .hdr.seg-tuck .seg-switch:not(:focus-within){opacity:0;transform:translateY(-12px);pointer-events:none}
  /* The phone menu opens under the bar alone: both strips step aside while it is open, and the menu's own top space
     (style.css, from --hdr) counts the bar only. */
  body.menu-open .hdr-in{margin-bottom:0}
  body.menu-open .seg-switch{visibility:hidden;opacity:0}
  body.menu-open .hdr .seg-sub{height:0;opacity:0;visibility:hidden}
  .menu{--hdr:var(--hdr-bar)}
}
/* Phones on their side (short screens; F2 for Q16, 26 Oct): the switch moves up into the header bar, beside the menu
   button, as on a computer, so the fixed header is the bar alone (it took a third of a 390 px screen with the strip
   under it) and the hero's headline and buttons stay on the first screen. In the bar it never tucks away. */
@media (max-width:960px) and (orientation:landscape) and (max-height:500px){
  :root{--hdr-seg:0px}
  .hdr-in{margin-bottom:0}
  .seg-switch{position:static;display:flex;height:auto;margin-left:auto;flex:none}
  .seg-switch a{min-height:44px;padding:0 .875rem}
  .hdr-in>.menu-btn{margin-left:0}
  .hdr.seg-tuck .seg-switch:not(:focus-within){opacity:1;transform:none;pointer-events:auto}
}
@media (max-width:640px){:root{--hdr-bar:64px}}
/* Narrow phones: the labels keep the 14 px floor; tighter padding keeps "Heavy Engineering" (117 px at 14 px) on one
   line in its half of the plate down to 320 px (a 140 px cell). */
@media (max-width:400px){.seg-switch a{padding:0 6px}}

/* Division pages: Overview | Projects completed | Specialised facilities (| RDSO requirements), a row of small plates
   under the header bar, on the switch's fill; the current page's plate is edged in the tone, its label in the tone's
   tint. build.py wraps the links in a .wrap, so the first plate lines up with the logo. The plates sit 4 px under
   the bar with 8 px below them: 36 px plates on a desktop (a 48 px row), 44 px on a touch screen (56 px); below 961 px,
   where the division strip's own 8 px sits above the row, 44 px plates with 4 px above and below (52 px). */
.seg-sub{height:var(--hdr-sub)}
.seg-sub>.wrap{display:flex;gap:8px;align-items:flex-start;height:100%;padding-top:4px;overflow-x:auto;scrollbar-width:none;overscroll-behavior-x:contain}
.seg-sub>.wrap::-webkit-scrollbar{display:none}
.seg-sub a{position:relative;display:inline-flex;align-items:center;flex:none;min-height:2.25rem;padding:0 1rem;--fill:var(--plate-dark);font:500 .85rem/1.2 var(--sans);letter-spacing:-.01em;white-space:nowrap;color:var(--txt-2);transition:--edge .25s,--fill .25s,color .25s}
.seg-sub a:hover,.seg-sub a.touch-hover{--edge:var(--tab-hover);color:var(--txt)}
.seg-sub a[aria-current]{--edge:var(--accent);color:var(--red-txt)}
.seg-sub a:focus-visible{--edge:var(--txt);--ew:2px}
/* slop-ok: outline-none replaced by designed :focus-visible (a 2 px light edge in the plate's own shape) */
.seg-sub a:focus-visible{outline:none}
@media (pointer:coarse){html:has(.seg-sub){--hdr-sub:56px}.seg-sub a{min-height:44px}}
@media (max-width:960px){html:has(.seg-sub){--hdr-sub:52px}.seg-sub a{min-height:44px}}
/* Phones: the row scrolls sideways, so its edges fade over the page gutter to show there is more (a mask: only its
   alpha counts); tabs.js brings the current page's plate into view (centred, or the row to its end). */
@media (max-width:960px){.seg-sub>.wrap{--fade:var(--gut);-webkit-mask-image:linear-gradient(90deg,transparent,var(--bg) var(--fade),var(--bg) calc(100% - var(--fade)),transparent);mask-image:linear-gradient(90deg,transparent,var(--bg) var(--fade),var(--bg) calc(100% - var(--fade)),transparent)}}
/* Phones: 14 px labels (the floor for text on a phone) with tight padding and gaps, so as much of the row shows as the
   labels allow: from about 400 px wide the fourth Railway Bridges plate (RDSO requirements) shows past the third. */
@media (max-width:640px){.seg-sub>.wrap{gap:4px}.seg-sub a{padding:0 .5rem;font-size:.875rem}}

/* Home: the tabbed division section, directly after the hero. Both panels are served visible (crawlers and readers
   without scripts get both, stacked, as two doors). With scripts, html[data-segment] (set before the first paint) shows
   only the chosen panel through CSS until tabs.js marks the other one hidden, so nothing shifts when the script mounts.
   The tablist is the header switch's plate at button size (44 px tall, an 8 px cut), on the page's own background. */
.seg-tabs{--cut:var(--cut-md);display:flex;width:max-content;max-width:100%;margin-bottom:clamp(32px,4vw,56px)}
.seg-tab{min-height:44px;padding:0 1.25rem;font:500 .95rem/1.2 var(--sans);letter-spacing:-.01em;cursor:pointer}
/* A deep link (#railway-bridges, #heavy-engineering) lands with the eyebrow and the tab row in view above the panel. */
.seg-panel{scroll-margin-top:calc(var(--hdr) + 150px)}
.seg-panel:focus-visible{outline-offset:12px}
html.js:not([data-segment="bridges"]) .seg-panel[data-seg="bridges"],html.js[data-segment="bridges"] .seg-panel[data-seg="engineering"]{display:none}
html:not(.js) .seg-tabs{display:none}
html:not(.js) .seg-panel+.seg-panel{margin-top:clamp(56px,8vw,104px);padding-top:clamp(56px,8vw,104px);border-top:1px solid var(--line)}
/* Phones: the tablist spans the column, each tab half of it; a label that needs two lines centres in its cell. */
@media (max-width:640px){
  .seg-tabs{display:grid;grid-template-columns:1fr 1fr;width:auto}
  .seg-tab{padding:6px .5rem;font-size:.88rem;white-space:normal;text-align:center}
}

/* Reduced motion: the tabs change state at once, and a division page's strips fold without sliding. */
@media (prefers-reduced-motion:reduce){.seg-switch,.seg-switch a,.seg-tab,.seg-sub a,.hdr .seg-sub,.hdr-in{transition:none}}
/* High Contrast: the system drops the drawn edges, so each plate is a plain bordered box; the current tab is underlined
   and keyboard focus is the system's highlight outline. */
@media (forced-colors:active){
  .seg-switch,.seg-tabs,.seg-sub a{clip-path:none;border:1px solid ButtonText}
  .seg-switch a+a,.seg-tab+.seg-tab{border-left:1px solid ButtonText}
  :is(.seg-switch a[aria-current],.seg-tab[aria-selected="true"],.seg-sub a[aria-current]){text-decoration:underline 2px;text-underline-offset:4px}
  :is(.seg-switch a,.seg-tab,.seg-sub a):focus-visible{outline:2px solid Highlight;outline-offset:-4px}
}

/* Clients: the rows of the chosen division are lit by a faint wash (the page-head wash, --accent-a05) behind them, set
   flush with the other rows; the others stay readable, only their names step back a shade. No stripe and no shift (as
   in mockup A). Rows without a division (not yet assigned) are left alone. */
.rowi[data-seg]{transition:background .3s}
.rowi.seg-on{background:linear-gradient(90deg,var(--accent-a05),transparent 60%)}
.rowi.seg-off :is(h3,.rowi-t){color:var(--txt-2)}

/* Heavy Engineering capabilities: a 500 px company photograph (the ash silo) in a process media slot is never drawn wider
   than its own pixels. */
.proc-media--native{width:100%;max-width:500px;justify-self:center}
/* Division homes (the Forge stage on a division page): the division's still image holds the stage, in the same files and
   framing as style.css's still path, so the hero is never empty while the engine starts (intro.js starts it as soon as
   the page is interactive). The canvas sits over it, and as the loop fades in (html.forge-on, 0.8 s) the still fades out
   on the same curve, a cross-fade with no frame of bare background; it fades back if the loop stops (a lost context).
   Reduced motion, no WebGL and a failed engine keep style.css's still (html.forge-still); without scripts style.css
   shows it too. Its file is preloaded in the page's head (build.py). */
html.js:has(.seg-sub):not(.forge-still) .forge::before{content:"";position:absolute;inset:0;background:var(--bg) url(assets/img/forge/still-v6-eng-1600.webp) 40% 40%/cover no-repeat;transition:opacity .8s ease}
html.js[data-segment="bridges"]:has(.seg-sub):not(.forge-still) .forge::before{background-image:url(assets/img/forge/still-v6-bridges-1600.webp)}
@media (min-width:1700px){html.js:has(.seg-sub):not(.forge-still) .forge::before{background-image:url(assets/img/forge/still-v6-eng-2560.webp)}html.js[data-segment="bridges"]:has(.seg-sub):not(.forge-still) .forge::before{background-image:url(assets/img/forge/still-v6-bridges-2560.webp)}}
@media (orientation:portrait){html.js:has(.seg-sub):not(.forge-still) .forge::before{background-image:url(assets/img/forge/still-v6-eng-p-1080.webp);background-position:50% 40%}html.js[data-segment="bridges"]:has(.seg-sub):not(.forge-still) .forge::before{background-image:url(assets/img/forge/still-v6-bridges-p-1080.webp)}}
html.js.forge-on:has(.seg-sub):not(.forge-still) .forge::before{opacity:0}
html:has(.seg-sub) .forge canvas{position:relative}
/* Every still of the Forge (the home's and the division homes', while the loop starts; style.css's for reduced motion,
   no WebGL and a failed engine): tabs.js (fitStill) places it as the engine frames the loop, its subject in the space
   the hero text leaves, under the header and its tab strips with the same gap as the loop's subject, and fades the
   image's edges that then fall on screen (two mask layers, intersected, are the image's own box; a mask: only its alpha
   counts). Each selector matches one of the still rules it adjusts, a step more specific. With no space left, or room
   only for a thumbnail, the still keeps the cover fit and it and the loop are dimmed to a quarter behind the hero text
   (.still-dim). From mockup A (segment.css), which has the same stills. */
html.js:has(.seg-sub):not(.forge-still) .forge.still-fit::before,html.js.from-site:not(.forge-still):not(:has(.seg-sub)) .forge.still-fit::before,html:is(:not(.js),.forge-still) .forge.still-fit::before{
  background-size:var(--still-w) var(--still-h);background-position:var(--still-x) var(--still-y);
  -webkit-mask:linear-gradient(90deg,transparent,var(--bg) var(--still-fl),var(--bg) var(--still-fr),transparent) var(--still-x) 0/var(--still-w) 100% no-repeat,linear-gradient(transparent,var(--bg) var(--still-ft),var(--bg) var(--still-fb),transparent) 0 var(--still-y)/100% var(--still-h) no-repeat;-webkit-mask-composite:source-in;
  mask:linear-gradient(90deg,transparent,var(--bg) var(--still-fl),var(--bg) var(--still-fr),transparent) var(--still-x) 0/var(--still-w) 100% no-repeat,linear-gradient(transparent,var(--bg) var(--still-ft),var(--bg) var(--still-fb),transparent) 0 var(--still-y)/100% var(--still-h) no-repeat;mask-composite:intersect}
/* (The dim state takes effect at once: the still's own fade is for its cross-fade with the loop, not for this.) */
html:is(.js,.forge-still):not(.forge-on) .forge.still-dim::before{opacity:.25;transition:none}
html.forge-on .forge.still-dim canvas{opacity:.25}
/* No JavaScript, phones held upright (640 px and narrower): fitStill cannot run, so the hero draws the still itself in
   the space its text leaves, where fitStill would put it. A flex filler (.hero::before) takes the hero's free height
   above the text and reaches down to 12 px above the eyebrow (the text block's top padding is the header's height plus
   80 px); under the header and a 13 px gap its content box is the band, across the column. The subject is sized to the
   band's height or the column's width, whichever allows less (the image's height that makes the subject as tall as the
   band, or as wide as the column, from each still's subject box: the same numbers as fitStill's), its top at the band's
   top; the band's edges fade. The stage's own still steps aside. The filler only takes free height, so the text does not
   move. Where the band would leave room for a thumbnail only, the stage's still stays instead, dimmed to a quarter
   behind the text as in .still-dim. The cut-offs are measured: the band's height must allow a subject 30% as wide as
   the column (fitStill's rule), with the pages' hero text and the no-JS header (its nav row) as they are; re-measure
   them if either grows. A division home dims under 381 px wide, or up to 480 px wide under 820 px tall, or up to 640 px
   under 870 px tall; the Heavy Engineering home (longer text) also up to 420 px wide under 900 px tall; the home up to
   380 px wide under 720 px tall, up to 480 px under 690 px, or up to 640 px under 760 px. */
@media (max-width:640px) and (orientation:portrait){
  html:not(.js) .forge::before{content:none}
  html:not(.js) .forge~main .hero::before{content:"";flex:1 0 0;min-height:calc(var(--hdr) + 68px);margin:0 var(--gut) calc(-1 * (var(--hdr) + 68px));padding-top:calc(var(--hdr) + 13px);
    background:url(assets/img/forge/still-v6-eng-p-1080.webp) 50% 24%/auto min(208.3%,calc((100vw - 2 * var(--gut)) * 1.85)) no-repeat content-box;
    -webkit-mask:linear-gradient(transparent calc(var(--hdr) + 13px),var(--bg) calc(var(--hdr) + 33px),var(--bg) calc(100% - 20px),transparent),linear-gradient(90deg,transparent,var(--bg) 6%,var(--bg) 94%,transparent);-webkit-mask-composite:source-in;
    mask:linear-gradient(transparent calc(var(--hdr) + 13px),var(--bg) calc(var(--hdr) + 33px),var(--bg) calc(100% - 20px),transparent),linear-gradient(90deg,transparent,var(--bg) 6%,var(--bg) 94%,transparent);mask-composite:intersect}
  html:not(.js)[data-segment="bridges"] .forge~main .hero::before{background-image:url(assets/img/forge/still-v6-bridges-p-1080.webp);background-position:50% 25.9%;background-size:auto min(276.2%,calc((100vw - 2 * var(--gut)) * 2.469))}
}
@media (max-width:380px) and (orientation:portrait),(max-width:480px) and (max-height:819px) and (orientation:portrait),(min-width:481px) and (max-width:640px) and (max-height:869px) and (orientation:portrait){
  html:not(.js):has(.seg-sub) .forge~main .hero::before{content:none}
  html:not(.js):has(.seg-sub) .forge::before{content:"";opacity:.25}
}
@media (max-width:420px) and (max-height:899px) and (orientation:portrait){
  html:not(.js)[data-segment="engineering"]:has(.seg-sub) .forge~main .hero::before{content:none}
  html:not(.js)[data-segment="engineering"]:has(.seg-sub) .forge::before{content:"";opacity:.25}
}
@media (max-width:380px) and (max-height:719px) and (orientation:portrait),(min-width:381px) and (max-width:480px) and (max-height:689px) and (orientation:portrait),(min-width:481px) and (max-width:640px) and (max-height:759px) and (orientation:portrait){
  html:not(.js):not(:has(.seg-sub)) .forge~main .hero::before{content:none}
  html:not(.js):not(:has(.seg-sub)) .forge::before{content:"";opacity:.25}
}
