/* extras.css */

/* THE SEAM — the one signature element.
   Every section join is a visible green hairline, not a flat break.
   Rationale (build with intent, not as decoration): nothing hidden — the joins
   are where the value is; and it's literally true to the subject's math
   (a manifold is charts joined along seams). */
.wp-block-separator.is-style-seam {
  border: 0;
  height: 2px;
  max-width: var(--wp--style--global--wide-size);
  margin-inline: auto;
  background: linear-gradient(90deg,
    transparent 0%,
    var(--wp--preset--color--seam) 15%,
    var(--wp--preset--color--seam) 85%,
    transparent 100%);
  opacity: 0.9;
}

/* Optional enhancement (nice-to-have, not required): a subtle fold at center.
   Keep it restrained. */
.wp-block-separator.is-style-seam::after {
  content: "";
  display: block;
  width: 10px; height: 10px;
  margin: -5px auto 0;
  background: var(--wp--preset--color--seam);
  transform: rotate(45deg);
  opacity: 0.6;
}

/* Quality floor */
/* Inline-SVG link :visited paint guard. Chrome repaints the fill of visited
   SVG <a> elements; descendants that inherit fill flicker dark depending on
   the viewer's browsing history, and DevTools hides it (visited-link privacy
   reports the unvisited value) — verify with screenshots. fill/stroke are on
   the small whitelist of properties :visited rules may set. */
svg a:visited { fill: inherit; stroke: inherit; }
.skip-link { position:absolute; left:-9999px; }
.skip-link:focus { left:1rem; top:1rem; position:fixed; z-index:99; background:var(--wp--preset--color--ground); color:var(--wp--preset--color--paper); padding:.5rem 1rem; }
:where(a,button,input,select,textarea):focus-visible { outline:2px solid var(--wp--preset--color--seam); outline-offset:2px; }
@media (prefers-reduced-motion: reduce) { *,*::before,*::after { animation:none!important; transition:none!important; scroll-behavior:auto!important; } }

/* ══════════════════════════════════════════════════════════════
   CONTROL PANEL — edit color values HERE; every rule below
   consumes them. Rebranding should never require editing the
   rules themselves.
   ══════════════════════════════════════════════════════════════ */
:root {
  /* Per-surface muted/accent pairs. The paper/ink pair's dual-surface
     ceiling is under 20.25, so no single mid-tone can pass AA on both
     surface classes — every muted token carries a variant per surface.
     Both full palettes + the light-variant recipe: PALETTES.md.
     Ratios computed 2026-07-19 (WCAG relative luminance). */
  --ss-on-light-dim:  #5E636B; /* muted text on bone #E9E3D6 — 4.73:1 */
  --ss-on-light-seam: #007400; /* accent text on bone         — 4.69:1 (ISD green, on-light cut) */
  --ss-on-dark-dim:   #8A8F98; /* muted text on ink #12141A   — 5.67:1 */
  --ss-on-dark-seam:  #009300; /* accent text on ink          — 4.54:1 (ISD brand green, sampled from the live site 2026-08-07; 4.535 is 0.8% above AA — do NOT darken this hex) */
  --ss-bone:          #E9E3D6; /* the bone value itself, addressable when
                                  ground has been re-pointed (band scope) */
  --ss-band-dark:     #20242E; /* ISD skin isd.4: BAND fill — bands invert
                                  from bone panels to elevated-ink panels.
                                  bone text on it 12.14:1 · dim 4.78:1 ·
                                  band seam 4.51:1 · vs page 1.19:1 (the
                                  border-block rule supplies the boundary) */
  --ss-on-band-seam:  #00A100; /* accent green on the band fill — 4.51:1
                                  (#009300 only reaches 4.11 there) */
  --ss-panel-dark:    #1B1E26; /* elevated field/panel fill on the ink
                                  page (1.1:1 vs page — the rule border
                                  supplies the boundary); field text
                                  13.03:1, placeholder dim 5.13:1 */
}

/* ══════════════════════════════════════════════════════════════
   SINGLE-SURFACE TOKENS — simple-dark variant, hardcoded.
   The dual-surface toggle mechanism (toggle.js, FOUC guard,
   [data-theme="dark"] re-pointing) is REMOVED; the dark values are
   baked into theme.json's palette, so core's preset classes resolve
   them everywhere without touching saved page markup.
   Contrast table (WCAG AA, computed 2026-07-19):
     page (bg ink #12141A): ground text (bone) 14.40 · dim #8A8F98
       5.67 · seam #009300 4.54 · rule border 1.76 (hairline,
       decorative only)
     ground-bg bands (isd.4): ELEVATED-INK panels #20242E on the ink
       page; paper token resolves bone on them 12.14 · scoped dim
       #8A8F98 4.78 · scoped seam #00A100 4.51 (band rule below).
       The bone-band era values live in git history.
   ══════════════════════════════════════════════════════════════ */

:root { color-scheme: dark; }

/* Ground-background bands (footer, banner, pov) are the opposite
   surface class from the page: with ground baked to bone, they are
   BONE panels on the ink page, and their paper-colored text resolves
   ink (the inversion travels with the palette, markup untouched).
   Their muted/accent tokens re-point to the on-LIGHT pair so any
   dim/seam text inside a band stays AA against the bone fill.
   BUTTONS are excluded (:not) even though they carry the same
   class: a button never holds dim/seam text, and re-pointing seam
   at the button would paint its focus ring — drawn 2px OUTSIDE the
   button, on the PAGE surface — with the wrong-surface value
   (audit find: 2.42:1/2.85:1). Excluded, the ring resolves at page
   scope: 4.54 on ink; rings inside bands take the band-scoped seam
   against the bone fill: 4.69. */
/* isd.4 — BAND INVERSION. Design direction: the bone bands read as white
   blocks against the dark scheme; retire them. Bands now
   resolve as elevated-ink panels and their paper-colored text resolves BONE —
   the whole flip rides the preset tokens, serialized markup untouched (the
   same mechanism this file already used for the bone-band era). Buttons stay
   excluded and get their own skin below. */
.has-ground-background-color:not(.wp-element-button) {
  --wp--preset--color--ground: var(--ss-band-dark);
  --wp--preset--color--paper:  var(--ss-bone);
  --wp--preset--color--dim:    var(--ss-on-dark-dim);  /* 4.78 on band */
  --wp--preset--color--seam:   var(--ss-on-band-seam); /* 4.51 on band */
  border-block: 1px solid var(--wp--preset--color--rule);
}

/* Links inside a ground band: theme.json's link color (ground) wins
   over the band's inherited paper by targeting the <a> directly —
   ground-on-ground is invisible (1.00:1; audit find on the banner
   CTA, latent since v0.3). Re-point band links to paper, which
   resolves ink against the bone band fill (14.4:1). Buttons keep
   their own paper text; core's site-title inherit rule already
   agrees with this. */
.has-ground-background-color a:where(:not(.wp-element-button)) {
  color: var(--wp--preset--color--paper); /* resolves bone in the inverted band */
}

/* isd.4 — buttons wear the legacy green (the old site's button color),
   with INK text: 4.535:1 (white text on this green fails at 4.06 — the
   adjusted-for-eyes version of the old habit). Focus ring resolves at page
   scope: 4.54 on ink. Scope note: if a button ever lands INSIDE a band, its
   paper text would resolve bone (3.17 on green — fails); keep buttons on the
   page surface or revisit. */
.wp-element-button.has-ground-background-color {
  --wp--preset--color--ground: #009300;
}

/* Header wordmark (text logo): plain link, no underline, inherits colors. */
.ss-wordmark a { text-decoration: none; color: inherit; }

/* Form controls on the ink page: color-scheme:dark alone half-flips
   plugin form fields (UA-dark backgrounds under plugin-authored
   light-mode text — audit find: 1.83:1 typed text in FluentForm).
   Own both sides of every control on tokens; the :where() keeps
   specificity at the element level while `body` in the compound
   lifts it above plugin base rules regardless of load order. */
body :where(input, textarea, select) {
  background-color: var(--ss-panel-dark);
  color: var(--wp--preset--color--ground);
  border-color: var(--wp--preset--color--rule);
}
body :where(input, textarea, select)::placeholder {
  color: var(--wp--preset--color--dim);
  opacity: 1;
}

/* ============================================================
   MOBILE PASS — every rule below is core-class + preset-token
   only. Root side padding rides in theme.json (it belongs to the
   layout system), where useRootPaddingAwareAlignments keeps
   alignfull bands full-bleed. Fixes in the order a visitor
   meets them.
   ============================================================ */

/* 7a — The menu button. Core renders a bare ~20px icon with no
   visible label; on the dark page it reads as a stray glyph
   rather than a control. Scale it to a real tap target and name
   it. The word arrives via ::after so core's own icon and its
   aria wiring stay untouched — decoration, not markup surgery. */
.wp-block-navigation__responsive-container-open {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.5rem 0.85rem;
  color: var(--wp--preset--color--ground);
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.wp-block-navigation__responsive-container-open::after { content: "Menu"; }
.wp-block-navigation__responsive-container-open svg { width: 1.6rem; height: 1.6rem; }

/* 7b — THE BUG THIS PASS EXISTS FOR. The overlay sheet ignored the
   theme entirely: core defaults it to a light background, so
   opening the menu on a dark page threw a full-screen white flash.
   These are the same preset tokens the body uses, so the sheet
   follows the palette for free — no JS, no second source of truth
   for surface state.
   Specificity note, because this selector looks absurd and isn't:
   core ships a default-overlay rule at (0,5,0) —
     .wp-block-navigation:not(.has-background)
     .wp-block-navigation__responsive-container.is-menu-open
     :not(.disable-default-overlay) { background-color: #fff }
   — which fires whenever the nav block carries no background
   ATTRIBUTE. A plain .is-menu-open rule is (0,2,0) and loses.
   Mirroring core's selector exactly and prefixing :root lands
   (0,6,0), which wins on specificity rather than on load order —
   so it cannot break if the enqueue order ever changes. !important
   would also work and would teach the next reader nothing.
   Why not just set overlayBackgroundColor on the block instead?
   Because block attributes are STATIC preset slugs; they cannot
   follow the toggle. The colors have to come from the custom
   properties. */
:root .wp-block-navigation:not(.has-background)
  .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
  background-color: var(--wp--preset--color--paper);
}
:root .wp-block-navigation:not(.has-text-color)
  .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
  color: var(--wp--preset--color--ground);
}
.wp-block-navigation__responsive-container.is-menu-open :is(a, button, .wp-block-navigation-item__content) {
  color: var(--wp--preset--color--ground);
}

/* 7c — Menu items sat at body size inside a full-screen sheet,
   which wastes the format and leaves tap targets under the 44px
   guideline. lg plus vertical padding gets both. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  font-size: var(--wp--preset--font-size--lg);
  padding-block: 0.4em;
}

/* 7d/isd.16 — VERTICAL COMPRESSION, ALL WIDTHS. Client review:
   spacing read as excessive, and the Contact map and lower Services
   sections were landing below a FALSE BOTTOM — a void big enough that
   readers assume the page ended and never scroll. The scale shipped
   50=4rem 60=6.5rem 70=10rem; sections used 60 top+bottom = 208px
   between sections. Narrow the steps once, every consumer adjusts:
   50 4rem→2.5rem · 60 6.5rem→3rem · 70 10rem→4rem. This supersedes the
   old ≤600px override (3.5/5rem), which is now LOOSER than desktop —
   one set of values, all widths. Token 40 (2.5rem) is untouched: it is
   also the global blockGap and column gutter. */
:root {
  --wp--preset--spacing--50: 2.5rem;
  --wp--preset--spacing--60: 3rem;
  --wp--preset--spacing--70: 4rem;
}

/* isd.16 — bind section headings to their section bodies. blockGap
   (2.5rem) between an h2 and its first content block read as the
   heading floating alone (part of the same false-bottom complaint).
   The eyebrow→heading binding below is the other half of this. */
main h2 + *:not(h2):not(h3) { margin-block-start: 1rem; }

/* 8 — Mobile overlay: wrapped menu labels. A label long enough to
   wrap centred its BOX while the text inside stayed left-aligned,
   so line two began at the box's left edge and read as staggered.
   Scoped to the OPEN OVERLAY only; desktop bar untouched. `:root`
   prefix beats core's (0,5,0) overlay rules without !important —
   same technique as 7b.
   isd.12 ADDENDUM — the two rules below were centring items inside
   the menu LIST, but the list itself was still parked at the left
   edge: core lays the open sheet out through a WRAPPER div
   (__responsive-container-content, flex column, align-items:
   flex-start), so the shrink-wrapped 72px-wide list hugged the left
   and "centred items" was invisible (measured at 452px: UL box
   x 24–96 on a 452px sheet). Centring the WRAPPER is the missing
   parent-level rule; the earlier two keep multi-line labels tidy
   within it. */
:root .wp-block-navigation__responsive-container.is-menu-open
      .wp-block-navigation__responsive-container-content {
  align-items: center;
}
:root .wp-block-navigation__responsive-container.is-menu-open
      .wp-block-navigation__container {
  align-items: center;
}
:root .wp-block-navigation__responsive-container.is-menu-open
      .wp-block-navigation-item {
  text-align: center;
}
:root .wp-block-navigation__responsive-container.is-menu-open
      .wp-block-navigation-item__content {
  text-wrap: balance;
}

/* ISD SKIN — legacy page texture (isd.2). pinstriped_suit.jpg was the OLD
   site's <html> background (measured live 2026-08-07); 26KB tile, now a
   theme asset. It darkens/keeps the ink field — bone text
   at 14.4:1 has margin to spare; the solid paper color remains underneath as
   fallback. Remove this one rule to retire the texture. */
body {
  background-image: url(pinstriped_suit.jpg);
  background-repeat: repeat;
}

/* ═══════════ isd.6 — accessibility + mechanical polish ═══════════
   Each issue below was confirmed at computed styles before its rule
   was written. */

/* Caption contrast — figcaption was inheriting core's #555: 2.47:1 on ink, an
   AA violation live on /about/. Captions join the mono label grammar:
   dim (5.67:1), small, left-aligned. */
.wp-block-image figcaption, .wp-element-caption {
  color: var(--wp--preset--color--dim);
  font-family: var(--wp--preset--font-family--mono);
  font-size: var(--wp--preset--font-size--sm);
  text-align: left;
}

/* Form submit skin — FluentForm's submit ships its own blue pill (measured
   rgb(26,126,251)/white/7px). Skin it to the button system: legacy green,
   INK text (4.535:1 — white on this green fails at 4.06), square. */
.fluentform .ff-btn-submit, .fluentform button[type=submit] {
  /* !important is deliberate and scoped: FluentForm emits per-form generated
     CSS (measured winning over theme-tier rules) — a third-party paint war,
     not an in-house specificity mistake. */
  background-color: #009300 !important;
  color: #12141A !important;
  border: none !important;
  border-radius: 0 !important;
  font-weight: 700;
  font-family: var(--wp--preset--font-family--body);
  /* isd.17 (client request): BIGGER. */
  padding: 1rem 3rem;
  font-size: 1.2rem;
}

/* isd.22 — form success message. FluentForm's stock confirmation is an
   unstyled hairline box that reads as a wireframe leftover. Dress it in
   the site's card language: band fill, hairline frame, a green seam
   edge on the left as the "confirmed" accent, body type with air.
   !important where FluentForm's own generated CSS competes. */
.fluentform .ff-message-success {
  background: var(--ss-band-dark) !important;
  border: 1px solid var(--wp--preset--color--rule) !important;
  border-left: 4px solid #009300 !important;
  border-radius: 0 !important;
  padding: 1.25rem 1.5rem !important;
  color: var(--ss-bone) !important;
  font-size: var(--wp--preset--font-size--base);
  line-height: 1.55;
  box-shadow: none !important;
}

/* isd.20 — submit placement. The button must stay INSIDE the <form>
   element to submit, so it cannot be moved into another column in
   markup. An earlier cut slid it into the left column with a transform;
   once the vertical spacing tightened it floated in dead space and read
   as a bug. Now: normal flow, but at side-by-side width the wrapper
   (which spans the form's column) shifts half a row left so the button
   centers under BOTH columns — a conventional closing action for the
   whole section. Below 782px (columns stacked) it stays centered in
   normal flow. */
.fluentform .ff_submit_btn_wrapper { text-align: center; margin-top: 2.5rem; }
@media (min-width: 782px) {
  .fluentform .ff_submit_btn_wrapper {
    transform: translateX(calc(-50% - var(--wp--preset--spacing--40) / 2));
  }
}

/* Separator width — core ships .wp-block-separator:not(.is-style-wide):not(
   .is-style-dots){width:100px} which outranked the intent rule at the top of
   this file: every seam separator has been rendering as a 100px dash. Win on
   specificity, size to the CONTENT measure so the line agrees with a real
   edge, and retire the center diamond (clutter at full width). */
:root hr.wp-block-separator.is-style-seam:not(.is-style-wide):not(.is-style-dots) {
  width: 100%;
  max-width: var(--wp--style--global--content-size);
}
.wp-block-separator.is-style-seam::after { content: none; }

/* Square corners — the only rounded shapes on an all-square site
   were core's button pill and the form fields. */
.wp-element-button, .wp-block-button__link { border-radius: 0; }
body :where(input, textarea, select) { border-radius: 0; }

/* Label binding — one blockGap (2.5rem) was carrying every vertical
   relationship, so labels floated 40px from what they label. Mono eyebrows
   pull their heading close; dim mono labels pull their value close. */
p.has-mono-font-family.has-sm-font-size + h2,
p.has-mono-font-family.has-sm-font-size + h3 { margin-top: 0.5rem; }
h3 + p.has-dim-color.has-mono-font-family,
h3 + p.has-mono-font-family.has-sm-font-size { margin-top: 0.35rem; } /* isd.14: role lines lost .has-dim-color (contrast fix) — keep them bound */
p.has-dim-color.has-mono-font-family.has-sm-font-size + p { margin-top: 0.4rem; }

/* ═══════════ isd.8 — gold hover language + frames ═══════════
   On the legacy site ALL nav hover/active states and tile hover
   borders were gold #FFDC2D (22 CSS rules) — the logo's gold was systemic.
   Restored as directly as the block stack allows. Contrast: 13.6:1 on ink,
   11.5:1 on bands. */
.wp-block-navigation a:hover, .wp-block-navigation a:focus { color: #FFDC2D; }
.wp-block-navigation .current-menu-item > a { color: #FFDC2D; }
.has-rule-border-color:hover { border-color: #FFDC2D; }
.ss-wordmark a:hover { color: #FFDC2D; }

/* Photo frames: every content image gets a quiet 1px slate frame —
   anchors images to the grid on the dark page. Framed iframes carry
   their own. */
main .wp-block-image img { border: 1px solid var(--wp--preset--color--rule); }

/* ═══════════ isd.9 — presentation cleanup ═══════════ */

/* ss-tabs: the old site's green-tab widget, reborn (story + portfolio).
   Active tab: legacy green + ink text (4.535). Inactive: bone on band-dark
   (12.1). Panels: solid band-dark so the widget stands off the page.
   No-JS fallback: panels simply stack. */
.ss-tabs-nav { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1rem; }
.ss-tab {
  background: var(--ss-band-dark);
  color: var(--ss-bone);
  border: 1px solid var(--wp--preset--color--rule);
  padding: 0.5rem 1.1rem;
  font-family: var(--wp--preset--font-family--display);
  font-size: var(--wp--preset--font-size--lg);
  letter-spacing: 0.02em;
  cursor: pointer;
  border-radius: 0;
}
.ss-tab:hover, .ss-tab:focus-visible { border-color: #FFDC2D; }
.ss-tab[aria-selected="true"] { background: #009300; color: #12141A; border-color: #009300; }
.ss-tabpanel {
  background: var(--ss-band-dark);
  border: 1px solid var(--wp--preset--color--rule);
  padding: var(--wp--preset--spacing--30);
}
.ss-tabpanel > :first-child { margin-top: 0; }
.ss-tabpanel h3 { font-family: var(--wp--preset--font-family--display); font-size: var(--wp--preset--font-size--lg); margin: 0.75rem 0 0.25rem; }
.ss-tabpanel img { border: 1px solid var(--wp--preset--color--rule); max-width: 100%; height: auto; }

/* Cards stand off the page: bordered card groups get the
   band fill instead of transparency. */
.wp-block-group.has-rule-border-color { background: var(--ss-band-dark); }

/* Nav dividers between menu items — desktop bar only, not the
   mobile overlay. */
@media (min-width: 600px) {
  /* symmetric padding + zero flex gap = each label optically centered
     between its divider lines (isd.10 refinement) */
  .wp-block-navigation .wp-block-navigation__container { gap: 0; }
  .wp-block-navigation .wp-block-navigation-item { padding-inline: var(--wp--preset--spacing--20); }
  .wp-block-navigation .wp-block-navigation-item + .wp-block-navigation-item {
    border-left: 1px solid var(--wp--preset--color--rule);
  }
}

/* Frame exception: centered hero/brand art (transparent PNGs) — a frame box
   around floating logo art reads as a mistake. Content photos stay framed. */
main .wp-block-image.aligncenter img { border: none; }

/* ═══════════ isd.11 — mobile trio (from phone-width review) ═══════════ */

/* 1. The hero title overflowed a phone screen at its 3rem floor —
   "steeldetailing.com" in Bebas is wider than 390px at that size, and an
   overflowing centered line reads as left-stuck. Shrink the floor on
   phones; it re-centers itself. */
@media (max-width: 480px) {
  /* !important matches core's own !important on preset size classes */
  .has-3-xl-font-size { font-size: 2.3rem !important; }
}

/* 2. Center the header stack on phones: logo row centers, menu button
   centers under it (it was wrapping to the left edge). */
@media (max-width: 600px) {
  header .wp-block-group.alignwide { justify-content: center; }
  header .wp-block-group.alignwide > .wp-block-group { justify-content: center; }
  .wp-block-navigation__responsive-container-open { margin-inline: auto; }
}

/* 3. THE THREE-LINE HAMBURGER. Core's icon is literally two bars (an
   equals sign, verified: two <path> rects). Hide it; draw a real one —
   three 2px bars in currentColor — and keep the "Menu" word. */
.wp-block-navigation__responsive-container-open svg { display: none; }
.wp-block-navigation__responsive-container-open::before {
  content: "";
  display: inline-block;
  width: 1.4rem;
  height: 1rem;
  background-image:
    linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor);
  background-size: 100% 2px;
  background-position: 0 0, 0 50%, 0 100%;
  background-repeat: no-repeat;
}
