/* ==================================================================================================================
   Metal Craft Engineering, mockup B2: the BRIGHT theme (round B2, T1, 24 Oct 2026). An override stylesheet the
   integrator links LAST on every page, after style.css, tabs.css, carousel.css and scrollwin.css. It sets the token
   table of style.css and tabs.css first; the few rules after it use the same selector (or the same specificity) as the
   rule they replace and never more. Nothing here changes layout, type, motion, markup or wording.
   Direction (judge, 24 Oct): steel-grey neutrals with one accent per division; the forge intro and the hero stay dark,
   a band of the shop across the top of a light page. No pills, no dots, no glows, no gradient beyond the faint
   page-head wash (and the gradient style.css already draws: the nav's ember bar).
   Left alone on purpose: --red, --red-2 and --glow (the Forge reads --red from <html> to paint the live render, which
   must keep its colour), --brand-red (the logo stays red), the intro, footage and viewer tokens (--fade-rgb,
   --media-tint, --intro-bg, --vignette, --ember-heat, --chip-bg, --dialog-bg, --backdrop,
   --dialog-shadow, --shader-warm, --on-accent), which only ever paint inside the dark islands (2).
   Round B3 (B5, 25 Oct 2026, the client's revision on this version): the board (a light page with a barely visible
   grain, 10), the Forge heroes on the board with the scene drawn light behind the text, full width as before (3), the
   logo without its ink plate and 18% larger (7, style.css), faint drafting patterns on the alternating bands (10).
   ================================================================================================================== */

/* 1. Light tokens. A near-neutral paper, pale steel bands, near-white plates; never pure white. Contrast: THEME.md. */
:root{
  color-scheme:light;
  /* Surfaces and lines */
  --bg:#f2f2ef;--bg-2:#e5e6e4;--surface:#fafaf8;--surface-2:#d9dad8;
  --line:rgba(20,21,24,.12);--line-2:rgba(20,21,24,.22);
  --txt:#141518;--txt-2:#44454b;--txt-3:#5e5f66;
  /* The interface accent, deepened for AA on every light surface (4.77:1 or more; 5.97:1 on paper; white on it 6.7:1),
     the small-text tint of it (7:1 or more), and its alphas. */
  --accent:#b5182f;--accent-2:#8f1426;--accent-txt:#8a1127;--red-txt:#8a1127;
  --accent-a05:rgba(181,24,47,.05);--accent-a08:rgba(181,24,47,.07);--red-a08:rgba(181,24,47,.07);
  --accent-a10:rgba(181,24,47,.08);--accent-a22:rgba(181,24,47,.2);
  /* Division tones (the tabs): the same deepened pair; their glows off. */
  --tone-engineering:#b5182f;--tone-bridges:#974410;--tone-engineering-glow:transparent;--tone-bridges-glow:transparent;
  /* Hot metal, a shade deeper so a hovered edge, the nav's ember bar and the scroll and carousel embers read on paper. */
  --warm:rgba(207,80,38,.85);--spark-core:#e0632f;
  /* Surface roles: photo placeholder and mat (steel, not black), fields, phone menu, footer band, page-head wash
     (the steel band with 2.5% of the tone, opaque). */
  --media-bg:#d9dad8;--field-bg:#fdfdfc;--menu-bg:#f2f2ef;--ftr-bg:#e5e6e4;--wash:#e4e1e0;
  /* Text and edge roles: placeholder text (5.7:1), a hovered field's border, the reticle's case (paper under a dark stroke). */
  --txt-ph:#5e5f66;--field-edge-hover:rgba(20,21,24,.62);--ret-case:#f2f2ef;
  /* Plate fills: an outlined plate has no fill; hovered, a 5% ink tint. --plate-dark (a secondary plate over footage,
     and tabs.css's switch and sub-tab fill) goes clear here, so the closing call to action, the header quote plate and
     the tabs are outlined plates on paper and steel; the hero sets it back (2). tabs.css's --tab-hover is computed from
     --txt, so it is ink at 50% already. */
  --plate-ghost:transparent;--plate-ghost-hover:rgba(20,21,24,.05);--plate-hover:rgba(20,21,24,.05);--plate-dark:transparent;
  /* New in this theme: the 3:1 edge of an outlined plate and of a field, the board colour the video head's band is cut
     from, and the board margin round that band (0: edge to edge). Round B3: the hero's subline is ink now that the
     Forge heroes are board (3), and the ink plate under the red mark is gone (7). */
  --line-3:rgba(20,21,24,.5);--paper:#f2f2ef;--frame:0px;--txt-hero:#2b2c31
}
html[data-segment="bridges"]{
  --accent:#974410;--accent-2:#75340b;--accent-txt:#72330b;--red-txt:#72330b;
  --accent-a05:rgba(151,68,16,.05);--accent-a08:rgba(151,68,16,.07);--red-a08:rgba(151,68,16,.07);
  --accent-a10:rgba(151,68,16,.08);--accent-a22:rgba(151,68,16,.2);
  --warm:rgba(196,116,22,.9);--spark-core:#d8862a;--wash:#e3e2df
}

/* 2. Dark islands. Where the page shows dark renders or footage it keeps the dark theme's own tokens, so everything
   inside renders as in B2-client: the opening screen, the video page head, project tiles (their caption sits on the
   photo), the label over a video, the photo viewer. `color` is set again because body's dark text would otherwise be
   inherited as a computed value. Round B3: the Forge stage (.forge) and the Forge heroes (.hero) left this list; the
   scene is drawn on the board and the hero's text takes the light tokens (3). */
:is(.page-head--media,.tile,.chip,.photo-viewer){
  color-scheme:dark;color:var(--txt);
  --bg:#09090a;--bg-2:#0e0e10;--surface:#131316;--surface-2:#19191d;
  --line:rgba(255,255,255,.08);--line-2:rgba(255,255,255,.15);--line-3:rgba(255,255,255,.15);
  --txt:#f4f4f2;--txt-2:#b6b6bc;--txt-3:#8d8d95;
  --accent:#e0243d;--accent-2:#c41d34;--accent-txt:#eb7081;--red-txt:#eb7081;--focus:var(--accent);
  --accent-a05:rgba(224,36,61,.05);--accent-a08:rgba(224,36,61,.08);--accent-a10:rgba(224,36,61,.1);--accent-a22:rgba(224,36,61,.22);
  --warm:rgba(255,122,82,.6);--spark-core:#ffe4c0;--ret-case:#09090a;--media-bg:#050506;--field-bg:#0b0b0d;
  --plate-ghost:rgba(255,255,255,.04);--plate-ghost-hover:rgba(255,255,255,.1);--plate-hover:rgba(255,255,255,.08);
  --plate-dark:rgba(18,18,21,.62)
}
html[data-segment="bridges"] :is(.page-head--media,.tile,.chip,.photo-viewer){
  --accent:#bd5a1a;--accent-2:#a54c16;--accent-txt:#d4946a;--red-txt:#d4946a;
  --accent-a05:rgba(189,90,26,.05);--accent-a08:rgba(189,90,26,.08);--accent-a10:rgba(189,90,26,.1);--accent-a22:rgba(189,90,26,.22);
  --warm:rgba(255,178,96,.6)
}

/* 3. The Forge heroes on the board (round B3, second pass: the owner, 26 Oct 02:55, "hero section should not be a
   cutout ... like original ... just turn the dark background to white", with the floor grid in red; build-patches\
   B6-HERO.md v2). The hero keeps B2-bright's full-width geometry exactly (style.css: full screen, the text left and the
   subject beside it on landscape screens, the text low and the subject above it upright): the Forge stage, fixed and
   full screen behind the page as before, fills the hero behind the text, and B6 draws the scene on the board tone
   (#f2f2ef) with a red floor grid. No window, no plate, no dark band: the stage and the hero take the light tokens, so
   the stage's ground and the still's are board too. The hero's shade (style.css .hero-shade, the original fades for
   type over the scene) is drawn in the board tone: it lifts the red floor grid behind the text block to a light wash
   and fades the scene into the page at the hero's foot, so no band shows where the board section below begins. The
   opening screen and the video page head (railway-bridges/projects) stay dark; the head keeps its full-width band,
   square at its top-left (T8, Q14 item 3: with --frame 0 a top-left cut showed as a light triangle under the steel
   header). An engine without polygon fill rules gets the band as in B2-client. */
.forge~main .hero{--fade-rgb:242,242,239}
/* Stacked heroes (upright screens: phones and tablets; QA Q5 item 1): the stage stays put while the page scrolls, so
   the subject above the text slides under it. The text block carries a soft board backing, full width: from 32 px above
   the eyebrow it rises from clear to 88% board and holds to the hero's foot (the backing scrolls with the text, the
   scene behind it does not), so over the darkest steel the ink stays at 12:1 and --txt-2 at 6.6:1. Not a plate and
   no cut-out: the scene above the text is untouched at rest. Landscape screens keep the subject beside the text. */
@media (orientation:portrait){
  .forge~main .hero-in{background:linear-gradient(rgba(var(--fade-rgb),0),rgba(var(--fade-rgb),calc(.88 * var(--hin-wash,1))) 32px) left bottom/100% calc(100% - var(--hdr) - var(--hin-gap,80px) + 32px) no-repeat}
}
/* Phones up to 480 px wide, held upright (QA Q9 ruling 1, "HE phone hero"): every Forge hero keeps a usable band for
   the scene above its text, as the home does. With scripts the text block's top padding grows from the header plus
   80 px to the header plus 220 px (--hin-gap): the engine and fitStill frame the subject in the band between the header
   and the eyebrow, so where the text is long (Heavy Engineering: a two-line eyebrow, a five-line lede) the band is still
   about 190 px; where the text is short (the home) the hero's free height already sets the band and nothing moves. The
   two calls to action sit side by side, 44 px plates whose labels may take two lines, so the text block is one row
   shorter. Without scripts round B2's still band (tabs.css) keeps its own geometry. */
@media (max-width:480px) and (orientation:portrait){
  html.js .forge~main .hero{--hin-gap:220px}
  html.js .forge~main .hero-in{padding-top:calc(var(--hdr) + var(--hin-gap))}
  .forge~main .hero .actions{display:grid;grid-template-columns:1fr 1fr;gap:8px}
  .forge~main .hero .actions .btn{height:2.75rem;padding:0 .625rem;gap:6px;font-size:.875rem;line-height:1.15;white-space:normal;text-align:center}
}
/* 375 px and narrower (360-wide Android phones, the common phone here; build 4 item 15b): the heading and both calls to
   action must land in the first screen (360 x 740) as they do at 390 and 414. Type sizes and strings stay; the room
   comes from the band and the spacing: the band shrinks to its floor (--hin-gap 152 px gives the engine a region of
   about 121 px), the space round the headline and above the buttons tightens (12/8 px and 14 px), the lede's leading
   steps from 1.55 to 1.45, and the lede is 1 px smaller (15.8 px at 360), which keeps it inside the gutters and saves it
   a line on Heavy Engineering (six lines to five at 360). (15c: no overhang into the gutter.) */
@media (max-width:375px) and (orientation:portrait){
  html.js .forge~main .hero{--hin-gap:152px}
  .forge~main .hero h1{margin:12px 0 8px}
  .forge~main .hero .lede{font-size:calc(1.05rem - 1px);line-height:1.45}
  .forge~main .hero .actions{margin-top:14px}
}
/* The opening screen on the white board too (owner, 26 Oct 11:30: "revert the start animation also but with white
   background"; B6): it left the dark islands (2), its ground is the board with no dark vignette or warm flash, and while
   it plays (html.intro-live) the stage keeps that ground, so nothing flashes as the canvas fades in over it. */
:root{--intro-bg:var(--paper);--vignette:transparent;--shader-warm:transparent}
html.intro-live .forge{background:var(--intro-bg)}
/* B18 (owner, 26 Oct 14:50, ruling OPENING-CONTINUOUS). The ember field shows with the mark: the engine draws it before its
   scenes are built and sets html.forge-field after its first frame, which is the board, so the canvas shows at once and
   the embers fade in on it. On the click the solid mark cross-fades into its particle M (opacity only: the burn-out's
   brightness and blur turned the red mark pink on the white board) and its canvas is freed once that is done (intro.js).
   Upright screens: the board backing behind the hero text fades in with the header and the shade after the intro
   instead of appearing in the reveal frame (--hin-wash scales its 88%). */
html.forge-field .forge canvas{opacity:1;transition:none}
html.forge-field .mc-intro{background:transparent}
.mc-intro.entered .intro-logo canvas{filter:none;transition:opacity .8s ease .05s}
@property --hin-wash{syntax:'<number>';inherits:false;initial-value:1}
@keyframes mc-wash{from{--hin-wash:0}}
@media (prefers-reduced-motion:no-preference) and (orientation:portrait){html.intro-done:not(.from-site) .forge~main .hero-in{animation:mc-wash 1.4s cubic-bezier(.33,1,.68,1) backwards}}
@supports (clip-path:polygon(evenodd,0 0,1px 0,0 1px)){
.page-head--media::after{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background:var(--paper);
  --t:calc(var(--hdr) + var(--frame));--l:var(--frame);--r:calc(100% - var(--frame));--b:calc(100% - var(--frame));--c:var(--cut-xl,14px);
  clip-path:polygon(evenodd,0 0,100% 0,100% 100%,0 100%,0 0,
    var(--l) var(--t),var(--r) var(--t),var(--r) calc(var(--b) - var(--c)),calc(var(--r) - var(--c)) var(--b),
    var(--l) var(--b),var(--l) var(--t))}
}

/* 4. The header is a solid steel band at every scroll position (style.css leaves it clear until scrolled, over the hero
   footage; here the band sits on top of the dark one). */
.hdr,.hdr.scrolled,body.menu-open .hdr{background:var(--bg-2);border-bottom-color:var(--line)}

/* 5. Outlined plates (secondary buttons, the menu button, filters, icon buttons) and fields take a 3:1 edge (--line-3):
   at --line-2 they would read as 1.6:1 on paper. Primary buttons need nothing: style.css fills .btn with --txt (ink)
   and labels it --bg (paper), and a hover fills it with the accent, white label. */
.btn-ghost,.menu-btn,.filters button,.icon-btn{--edge:var(--line-3)}
.field input,.field textarea{border-color:var(--line-3)}

/* 6. (Removed by T8 at integration: the client logos in B2-bright are T2's ink-graded files, so no filter is needed.) */

/* 7. The red mark on the board (round B3, owner item 8: "remove the black background from the logo"). Round B2's ink
   plate round the header and footer marks is gone: the brand red #e0243d reads on its own, 4.2:1 on the board
   (#f2f2ef) and 3.7:1 on the steel header and footer bands (#e5e6e4), above the 3:1 a graphic needs, and the wordmark
   beside it is ink (17:1). The mark is 18% larger (style.css, The logo), its 3D sprite re-rendered for the board (A6:
   matted edges, no dark fringe, the colour grade in the file; worst frame 3.1:1 on the steel band). */

/* 8. Integration (T8, B2-bright), the theme devil's must-fix items (themes\DEVIL.md, phase 1 verdicts 03:30).
   a) Hot metal deeper than the resting edge. A hovered outlined plate's edge (--warm) was fainter on paper than its
      resting --line-3 (3.18 engineering, 2.83 bridges, against 3.34), so a hover looked as if the plate cooled. Opaque
      and deeper per division: 4.95 and 5.05 on paper, 4.43 and 4.52 on steel, still oranger than the accent, so the
      nav's accent-to-warm bar reads as heat. The dark islands (2) keep their own --warm. The card carousel's embers
      draw over its photographs, so the carousel keeps B2-client's hot coral (amber on bridges pages) for them, and
      only its outlined control plates take the deep warm for their hover edge (devil phase 2, P2-2).
   b) No friction embers on paper. An ember is emitted light; on the light window plate it printed as a red scratch
      whose hot head was its faintest part. The windows keep their fades and scrollbar. (The card carousel's embers
      draw only over its photographs, so they stay, in their own colour: a.)
   c) The Forge still under the solid header on phones (devil phase 1, 16, and phase 2, P2-1): no theme rule. B2-client's
      tabs.js fitStill (P2, 06:0x) now places every still where the engine frames the loop, under the header and its
      tab strips and clear of the hero text, so the steel header no longer cuts the subject. T8's interim rules (the
      still layer moved under the header, then drawn at 90%) were removed so they cannot fight that placement.
   d) The reticle over a dark island (restored from B2-bright on the owner's instruction, 26 Oct 11:27). It lives on
      <body>, outside the dark islands, so over the opening screen, the video head or a project tile its ink stroke
      would vanish and only the paper case show. While the pointer is over one, the reticle takes the dark theme's
      stroke and case; everywhere else it stays ink on paper (in the photo viewer app.js moves it into the dialog). */
:root{--warm:#b4441c}
html[data-segment="bridges"]{--warm:#9a560c}
.carousel--cards{--warm:rgba(255,122,82,.6)}
html[data-segment="bridges"] .carousel--cards{--warm:rgba(255,178,96,.6)}
.carousel--cards .icon-btn{--warm:#b4441c}
html[data-segment="bridges"] .carousel--cards .icon-btn{--warm:#9a560c}
.win-sparks{display:none}
body:has(:is(.page-head--media,.tile):hover) .reticle{--txt:#f4f4f2;--ret-case:#09090a}

/* 9. QA fixes (T8, from qa\Q14\FINDINGS.md).
   a) A client logo cell's hover fill: style.css fills it with --surface, 1.07:1 on paper, so the hover did not show
      (devil item 11). Pale steel instead, the colour of the bands.
   b) Print, the theme's part (P1 adds the base print block to style.css): the paper and steel bands, the plates and the
      page-head wash print plain white. style.css's print block (P1) sets its paper tokens on html:root; the dark islands
      (2) declare their own dark tokens on the element, so they would print light type on white paper. In print they
      take the same paper values (and the light accents), one step more specific than (2). */
.logos a:hover,.logos a.touch-hover{background:var(--bg-2)}
@media print{
  :root,html[data-segment="bridges"]{--bg:#fff;--bg-2:#fff;--surface:#fff;--ftr-bg:#fff;--wash:#fff;--menu-bg:#fff;--paper:#fff;--field-bg:#fff}
  html :is(.mc-intro,.page-head--media,.tile,.chip,.photo-viewer){color-scheme:light;
    --bg:#fff;--bg-2:#fff;--surface:#fff;--surface-2:#f2f2f2;--line:rgba(0,0,0,.14);--line-2:rgba(0,0,0,.3);--line-3:rgba(0,0,0,.3);
    --txt:#111;--txt-2:#333;--txt-3:#555;--media-bg:#fff;--field-bg:#fff;
    --plate-ghost:transparent;--plate-ghost-hover:transparent;--plate-hover:transparent;--plate-dark:transparent;
    --accent:#b5182f;--accent-2:#8f1426;--accent-txt:#8a1127;--red-txt:#8a1127;--focus:var(--accent)}
  html[data-segment="bridges"] :is(.mc-intro,.page-head--media,.tile,.chip,.photo-viewer){
    --accent:#974410;--accent-2:#75340b;--accent-txt:#72330b;--red-txt:#72330b}
}

/* 10. The board and its quiet patterns (round B3; owner: "add a very subtle, non-AI-looking background to other
   sections ... so the site does not look too plain"; files and measurements by B8, build-patches\B8-notes.md). Two
   hand-drawn SVG tiles, plain ink strokes, no filter, noise, gradient or blend, served as files (img-src 'self'), drawn
   at their own size:
   - board-grain-v2.svg (336 px, grain v2): B8's fibres (same seed, layout and stroke widths, regenerated with
     make-textures.py's board_grain(ops=(.010,.015,.020))), at 1.0 to 2.0% ink. B8's 0.45 to 1.05% tile read as flat
     off-white (QA Q1), and Firefox's rasteriser dropped those strokes altogether (QA Q15), so round B3 first drew it three
     times and now draws the stronger tile twice (--board-grain): once at the origin and once offset by 131 x 67 px (not
     half a tile, so no 168 px lattice), adding fibres between. Measured on the board: Chromium 7 code levels at the
     darkest fibre (8 at 150%), Firefox 4 (8 at 150%), fibres on 6% and 2.4% of the pixels; --txt-3 keeps 5.3:1 over
     the darkest (B5-notes.md, grain v2). It is the base of every light surface that is board or band: the page, the steel header, the
     alternate bands, the footer, the phone menu, and on the Forge pages the sections that cover the stage (they must be
     opaque, so they carry it themselves). Never on near-white plates, fields, photos, the viewer, the map or the hero
     (the scene draws its own floor there).
   - drafting-grid.svg (192 px): a drawing-office rule, a 1 px line every 48 px at 4% ink and every 192 px at 6%. The
     one visible pattern. Page heads (second pass, QA Q1; anti-slop P3-4) take only its 192 px major lines
     (drafting-grid-major.svg, the same 6% stroke), set as a drawing sheet: a vertical line on the content column's left
     edge and a horizontal one on the headline's first baseline (.84 em down the h1, measured). That layer is the h1's
     ::before, absolutely placed at the h1's own top and reaching 2000 px up and down inside the page head (which clips
     it, isolated, so it sits over the wash and under the type), so its lines follow the headline whatever stands above
     it (a breadcrumb, a longer eyebrow). Body sections: by opt-in only, .sec--grid on at
     most one section of a page (anti-slop 9, 26 Oct: the grid by position landed on whatever section came second;
     build.py puts it on the home Capabilities and the About Resources sections); never on the first section under a
     hero, the closing call to action, behind the projects map, a table, photo grids, the logo strip, scrolling windows
     or the enquiry form (data and photos keep a plain ground). A gridded surface is opaque under
     its grid, so the grain never shows through it: one pattern at a time (devil's review). Checked at 1440 and 1920 at
     100, 125 and 150% scaling (Windows display scaling): no moire, the 1 px lines only alternate a device pixel in
     weight at 125 and 150%, under 6% ink.
   Forced colours, "more contrast" and print turn both off. axe-core reports text over a background image as
   "incomplete" (bgImage), not as a violation; the contrast over the textured pixels is in B5-notes.md. */
:root{--tex-grain:url(assets/textures/board-grain-v2.svg);--tex-grid:url(assets/textures/drafting-grid.svg);--tex-grid-major:url(assets/textures/drafting-grid-major.svg);
  --board-grain:var(--tex-grain),var(--tex-grain)}
body,.hdr,.sec--alt,.ftr,.menu,:where(.forge~main>.hero~*){background-image:var(--board-grain);background-position:0 0,131px 67px}
.page-head:not(.page-head--media) h1::before{content:"";position:absolute;left:0;right:0;z-index:-1;height:4000px;margin-top:-2000px;pointer-events:none;
  background:var(--tex-grid-major) max(var(--gut),50vw - var(--wrap) / 2 + var(--gut)) calc(2000px + .84em)}
main>.sec.sec--grid{background:var(--bg) var(--tex-grid)}
@media (forced-colors:active),(prefers-contrast:more),print{:root{--tex-grain:none;--tex-grid:none;--tex-grid-major:none}}
/* B16 (owner 26 Oct 13:30, ruling DECLUTTER-EXCEPT-DETAIL): less crowding on the ten pages build.py marks main.calm (home, the six
   division pages, gallery, clients, contact); About, Certifications and the RDSO page keep their density. One step more air on the
   existing scale (gaps, section and stage padding, head margins, list rows), text measure capped near 68 characters, and panels inside
   a scrolling window drawn as rows of that one plate instead of plates in a plate. Components, breakpoints and tokens unchanged. */
main.calm{--gap:clamp(24px,2.2vw,40px)}
main.calm .sec{padding-block:clamp(104px,12.5vw,192px)}
main.calm .proc{padding-block:clamp(80px,9.5vw,136px)}
main.calm .proc:first-child{padding-top:0}
main.calm .proc:has(+.media-pair){padding-bottom:0}
main.calm .sec-head{margin-bottom:clamp(48px,6vw,88px)}
main.calm .feature-copy .lede{margin-bottom:36px}
main.calm .lede+.ticks{margin-top:32px}
main.calm .ticks li{padding-block:18px}
main.calm .ticks li::before{top:calc(1.35em + 4px)}
main.calm .facts>div{gap:24px;padding-block:22px}
main.calm :is(.prose,.panel,.feature-copy,.split) p:not(.lede){max-width:68ch}
main.calm .prose ul.ticks{margin:28px 0 32px;padding-left:0;list-style:none}
main.calm .prose .ticks li+li{margin-top:0}
main.calm .prose .ticks+p{margin-top:0}
main.calm .win .panels{gap:0 clamp(28px,3vw,48px)}
main.calm .win .panel{--edge:transparent;--fill:transparent;clip-path:none;padding:24px 0 8px;border-top:1px solid var(--line)}
