/* ============================================================================
   RANCO concept demos — SHARED skeleton.
   Load order: ibix-base.css -> shared.css -> motion-kit.css -> [theme].css
   This file carries fonts, the fluid type scale, the spacing/ease tokens and
   every structural class the three concepts share. Each theme file supplies
   ONLY the colour tokens + section backgrounds + its one signature move — the
   skeleton (header, hero, stat band, services list, trust wall, QHSE, contact,
   footer) is written once here so the three concepts are the same building
   with different paint, not three different buildings.

   Token contract every [theme].css must define before this file's classes
   make sense:
     --ink --ink-2 --ink-3        dark surfaces
     --paper --paper-2            light surfaces
     --txt --txt-dim --txt-faint  on-dark text
     --ink-txt --ink-dim          on-paper text
     --navy --blue                RANCO's own brand colours (logo — never edited)
     --blue-link                  on-paper small text/links (brand blue fails
                                   4.5:1 on paper, see CLIENT-FACTS.md)
     --accent --accent-hi --accent-btn   the concept's own signal colour, in a
                                   large/decorative shade, an on-dark small-text
                                   shade and a white-text-safe button shade
     --line --line-ink            hairlines on dark / on paper
   Every ratio below was produced by design/snippets/contrast-check.py — see
   the @contrast annotations in each [theme].css, not typed from memory (D-16).
   ========================================================================= */

/* --- 1 · fonts (self-hosted, Latin only, these demos are English-only by
   owner instruction 2026-08-04: "remove arabic as there is no need for now".
   RANCO's own Arabic wordmark still ships inside the logo SVG — that is part
   of the mark, not page copy, and is untouched.

   Typeface pair, changed 2026-08-05 (owner: "change fonts for all 3, pick a
   good font you believe will be best"). IBM Plex Sans is OUT.

   Display: SCHIBSTED GROTESK. Body: INTER. Both self-hosted variable OFL
   files (~95KB combined — inside the DP12 budget). Why this pair: Schibsted
   Grotesk carries authority at 80px+ display sizes where IBM Plex Sans went
   flat and wide; Inter is the most legible face on the house list at the
   14–17px sizes the service rows and register content live at. Ajyal pairs
   Schibsted with Figtree for body — this build uses Inter instead, on
   purpose: Ajyal and RANCO are both Eastern Province rig-movers, and the two
   sites should share a register, not an identity.

   Each file is a variable font, so it gets ONE @font-face with a font-weight
   RANGE — never one rule per weight, which would make the browser download
   the same file twice or synthesise a fake bold. Ranges below match the
   file's own fvar axis, checked with fontTools: Schibsted Grotesk's Latin
   subset only carries 400–900 (no light weights in this subset); Inter
   carries the full 100–900. Fallback metrics generated with fontpie against
   these exact files — pasted verbatim, not estimated. */
@font-face{
  font-family:'Schibsted Grotesk';
  font-style:normal; font-weight:400 900; font-display:swap;
  src:url('../fonts/schibsted-grotesk-var-latin.woff2') format('woff2');
}
@font-face{
  font-family:'Schibsted Grotesk Fallback';
  font-style:normal; font-weight:400; src:local('Arial');
  ascent-override:92.54%; descent-override:24.43%; line-gap-override:0.00%; size-adjust:105.53%;
}
@font-face{
  font-family:'Inter';
  font-style:normal; font-weight:100 900; font-display:swap;
  src:url('../fonts/inter-latin-var.woff2') format('woff2');
}
@font-face{
  font-family:'Inter Fallback';
  font-style:normal; font-weight:400; src:local('Arial');
  ascent-override:89.79%; descent-override:22.36%; line-gap-override:0.00%; size-adjust:107.89%;
}

/* --- 2 · tokens shared by all three concepts ------------------------------- */
:root{
  --body-latin:'Inter','Inter Fallback',Arial,sans-serif;
  --display-latin:'Schibsted Grotesk','Schibsted Grotesk Fallback',Arial,sans-serif;
  --mono:ui-monospace,'Cascadia Mono','SF Mono',Consolas,'Liberation Mono',monospace;
  --body: var(--body-latin);
  --display: var(--display-latin);

  --ease:cubic-bezier(.22,1,.36,1);
  --wrap:1280px;
  --gut:clamp(20px,4.5vw,64px);

  /* spacing scale (design/snippets/layout-primitives.css, R 01 §2) */
  --space-3:1rem; --space-4:1.5rem; --space-5:2rem; --space-6:3rem;
  --space-7:4rem; --space-8:6rem; --space-9:8rem;

  /* fluid type ladder (design/snippets/type-scale.css, verified @360/@1440) */
  --step-0:  clamp(1rem, calc(0.958rem + 0.185vw), 1.125rem);      /* 16 / 18   body */
  --step-1:  clamp(1.188rem, calc(1.125rem + 0.278vw), 1.375rem);  /* 19 / 22   lead */
  --step-2:  clamp(1.375rem, calc(1.25rem + 0.556vw), 1.75rem);    /* 22 / 28   h3 */
  --step-3:  clamp(1.625rem, calc(1.438rem + 0.833vw), 2.188rem);  /* 26 / 35   h2 */
  --step-4:  clamp(1.938rem, calc(1.667rem + 1.204vw), 2.75rem);   /* 31 / 44   h1 inner */
  --step-5:  clamp(2.25rem, calc(1.854rem + 1.759vw), 3.438rem);   /* 36 / 55   statement */
  --lh-latin:1.5; --lh-display:1.05;

  --z-header:50; --z-overlay:60;
}

html{ font-size:100% }
body{ line-height:var(--lh-latin) }

body{
  font-family:var(--body); font-size:var(--step-0);
  background:var(--paper); color:var(--ink-txt);
  font-optical-sizing:auto; text-rendering:optimizeLegibility;
}
h1,h2,h3{ font-family:var(--display); font-weight:700; letter-spacing:-.02em; line-height:var(--lh-display) }
::selection{ background:var(--accent); color:#fff }
:focus-visible{ outline:2px solid var(--accent-hi, var(--accent)); outline-offset:3px }

/* Section colour context. Every content section carries ONE of these so every
   child component (chips, cards, rows, stats) resolves its muted/line/border
   tokens against the surface it is ACTUALLY painted on — never a single
   global "muted grey" guessed to work everywhere. Background colour itself is
   still set per section, per theme, in [theme].css. */
.on-dark{ color:var(--txt); --body-muted:var(--txt-dim); --card-line:var(--line);
  --card-bg:transparent; --row-line:var(--line); --chip-line:var(--line); --chip-txt:var(--txt);
  --stat-line:var(--line); --stat-label:var(--txt-dim); --logo-grid-line:var(--line) }
.on-paper{ color:var(--ink-txt); --body-muted:var(--ink-dim); --card-line:var(--line-ink);
  --card-bg:transparent; --row-line:var(--line-ink); --chip-line:var(--line-ink); --chip-txt:var(--ink-txt);
  --stat-line:var(--line-ink); --stat-label:var(--ink-dim); --logo-grid-line:var(--line-ink) }

.wrap{ max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut) }
.mono{ font-family:var(--mono); font-size:.72rem; letter-spacing:.14em; text-transform:uppercase }

.kicker{
  font-family:var(--mono); font-size:.72rem; letter-spacing:.18em; text-transform:uppercase;
  display:flex; align-items:center; gap:14px; margin-bottom:22px; color:var(--accent-hi, var(--accent));
}
.kicker::after{ content:""; height:1px; width:64px; background:currentColor; opacity:.55 }
.on-paper .kicker{ color:var(--navy) }

/* buttons — extends the base .btn (nowrap, min-height) */
.btn{ font-family:var(--display); font-weight:600; font-size:.95rem; letter-spacing:.01em;
  padding:15px 28px; border-radius:4px; min-height:48px }
.btn-solid{ background:var(--accent-btn, var(--accent)); color:#fff }
.btn-solid:hover{ filter:brightness(1.08); transform:translateY(-1px) }
.btn-navy{ background:var(--navy); color:#fff }
.btn-navy:hover{ filter:brightness(1.12); transform:translateY(-1px) }
.btn-ghost{ border-color:rgba(255,255,255,.5); color:#fff }
.btn-ghost:hover{ border-color:#fff; background:rgba(255,255,255,.08) }
.btn-outline-ink{ border-color:var(--card-line,var(--line-ink)); color:inherit }
.btn-outline-ink:hover{ background:var(--ink-txt); color:var(--paper); border-color:var(--ink-txt) }

/* --- 3 · header ------------------------------------------------------------- */
#top-bar{ position:sticky; top:0; z-index:var(--z-header); background:var(--header-bg,var(--paper));
  border-bottom:1px solid var(--header-line,var(--line-ink)) }
.tb-in{ max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut);
  height:76px; display:flex; align-items:center; justify-content:space-between; gap:20px }
.brand{ display:flex; align-items:center; line-height:1 }
.brand img{ height:36px; width:auto }
/* Concept B: the logo sits in its own white lockup chip so it never touches
   the dark shell directly — the mark stays exactly as drawn either way. */
.brand-chip{ background:#fff; border-radius:6px; padding:9px 16px;
  box-shadow:0 1px 2px rgba(0,0,0,.08) }
.tb-nav{ display:flex; gap:28px }
.tb-nav a{ font-family:var(--display); font-weight:500; font-size:.9rem;
  color:var(--nav-txt,var(--ink-dim)); padding:8px 0; position:relative }
.tb-nav a::after{ content:""; position:absolute; inset-inline-start:0; bottom:2px; height:1.5px; width:0;
  background:var(--accent); transition:width .3s var(--ease) }
.tb-nav a:hover{ color:var(--nav-txt-hover,var(--ink-txt)) }
.tb-nav a:hover::after{ width:100% }
@media (max-width:860px){ .tb-nav{ display:none } }
.tb-right{ display:flex; align-items:center; gap:10px }
.tb-cta{ padding:11px 20px; min-height:42px; font-size:.86rem }
@media (max-width:560px){ .tb-cta{ display:none } }

/* --- 3b · smart header (hide on scroll down, reappear on scroll up) --------
   Transform-only, JS-driven (js/header-scroll.js) — the .hide class is NEVER
   present without JS, so a no-JS visitor simply never sees it move: the
   header's default state IS visible, this only ever takes it away. Honours
   prefers-reduced-motion via ibix-base.css's global transition-duration
   collapse (still shows/hides, just without the slide). */
#top-bar{ transition:transform .32s var(--ease); will-change:transform }
#top-bar.hide{ transform:translateY(-100%) }

/* --- 3c · "What we offer" nav dropdown --------------------------------------
   Real <a href="#services"> label (works with JS off — nothing is ever
   unreachable) plus a separate disclosure <button aria-expanded> that reveals
   the seven services. Opens on: pointer-fine hover (decoration only), a JS
   click/tap toggle (.open, robust for touch), and — when JS never ran at all —
   a :focus-within fallback so keyboard users still get SOMETHING. Escape and
   click-outside close it (js/nav-drop.js); the toggle itself never traps focus. */
.nav-drop{ position:relative; display:flex; align-items:center }
.nav-drop-link{ font-family:var(--display); font-weight:500; font-size:.9rem;
  color:var(--nav-txt,var(--ink-dim)); padding:8px 0; position:relative }
.nav-drop-link::after{ content:""; position:absolute; inset-inline-start:0; bottom:2px; height:1.5px; width:0;
  background:var(--accent); transition:width .3s var(--ease) }
.nav-drop-link:hover{ color:var(--nav-txt-hover,var(--ink-txt)) }
.nav-drop-link:hover::after{ width:100% }
.nav-drop-toggle{ display:inline-flex; align-items:center; justify-content:center;
  width:26px; height:26px; padding:0; margin-inline-start:1px; border-radius:4px;
  background:none; border:0; color:var(--nav-txt,var(--ink-dim)); cursor:pointer }
.nav-drop-toggle:hover{ color:var(--nav-txt-hover,var(--ink-txt)) }
.nav-drop-toggle::before{ content:""; width:0; height:0; margin:0 auto;
  border-inline:4px solid transparent; border-top:5px solid currentColor;
  transition:transform .2s var(--ease) }
.nav-drop.open .nav-drop-toggle::before{ transform:rotate(180deg) }
/* invisible bridge so the mouse can travel from the link row down into the
   panel without crossing a dead zone and losing :hover mid-way */
.nav-drop::after{ content:""; position:absolute; top:100%; inset-inline:0; height:14px }
.nav-drop-menu{ list-style:none; position:absolute; top:100%; inset-inline-start:0; margin-top:14px;
  min-width:250px; padding:8px; border-radius:8px;
  background:var(--header-bg,var(--paper)); border:1px solid var(--header-line,var(--line-ink));
  box-shadow:0 18px 40px -14px rgba(10,12,16,.35);
  opacity:0; visibility:hidden; transform:translateY(-6px);
  transition:opacity .18s var(--ease), transform .18s var(--ease), visibility 0s linear .18s;
  pointer-events:none; z-index:var(--z-overlay) }
.nav-drop-menu li + li{ margin-top:1px }
.nav-drop-menu a{ display:block; padding:10px 12px; border-radius:5px;
  font-family:var(--display); font-weight:500; font-size:.86rem; color:var(--nav-txt,var(--ink-dim)) }
.nav-drop-menu a:hover, .nav-drop-menu a:focus-visible{
  color:var(--nav-txt-hover,var(--ink-txt)); background:rgba(127,127,127,.12) }
@media (hover:hover) and (pointer:fine){
  .nav-drop:hover .nav-drop-menu{ opacity:1; visibility:visible; transform:none; pointer-events:auto; transition-delay:0s }
}
.nav-drop.open .nav-drop-menu{ opacity:1; visibility:visible; transform:none; pointer-events:auto; transition-delay:0s }
html:not(.js) .nav-drop:focus-within .nav-drop-menu{ opacity:1; visibility:visible; transform:none; pointer-events:auto; transition-delay:0s }

/* --- 4 · hero ---------------------------------------------------------------- */
#hero{ position:relative; overflow:hidden; background:var(--ink); --header-h:76px }
/* #top-bar is position:sticky, not fixed — it still occupies its own row in
   flow, so a naive 100svh hero UNDER it always overhangs the fold by the
   header's own height (design/snippets README's documented defect #2).
   Subtract it here rather than trusting a fixed-header assumption. */
#hero.hero-full{ min-height:calc(100vh - var(--header-h)); min-height:calc(100svh - var(--header-h));
  display:flex; align-items:center }
/* short-laptop trim — placed here, AFTER the base padding rule below in the
   SAME file, so it cannot be silently outranked by source order the way a
   later theme file already did once on this project (see hero-in comment). */
.hero-media{ position:absolute; inset:0 }
.hero-media picture, .hero-media img{ width:100%; height:100%; object-fit:cover }
.hero-scrim{ position:absolute; inset:0; pointer-events:none }
.hero-grid{ position:absolute; inset:0; pointer-events:none; opacity:.35;
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,.035) 0 1px, transparent 1px 120px),
    repeating-linear-gradient(0deg, rgba(255,255,255,.035) 0 1px, transparent 1px 120px) }
.hero-in{ position:relative; z-index:2; width:100%; max-width:var(--wrap); margin-inline:auto;
  padding:clamp(120px,16vh,168px) var(--gut) clamp(150px,19vh,196px) }
/* Re-specified AFTER the rule above, in the SAME file, on purpose: a later
   file silently deleting this exact guardrail by source order is a named
   pitfall in design/snippets/README.md's own validation log. */
@media (max-height:820px){
  .hero-in{ padding-block:clamp(72px,11vh,110px) clamp(48px,7vh,72px) }
}
/* Hero display measure, fixed 2026-08-05 (owner: "text isn't nicely laid
   out here or on the other"). Measured on a-nightshift.html at 1440px before
   the fix: font-size 84.6px with line-height 82.9px — leading TIGHTER than
   the font size — inside a 15ch (761px) box, wrapping "Built for Saudi
   Arabia's heavy work." to "Built for Saudi / Arabia's / heavy work.",
   stranding "Arabia's" alone. text-wrap:balance was already on and did not
   fix it — the box was simply too narrow for a 6-word headline to break
   well, whatever the balance algorithm chooses inside it. Widened the
   measure (15ch -> 22ch) AND dropped the size a step so the natural wrap
   is a clean two-line break in both concept A and concept B's headline
   (different copy, same class) at every checked width (1440/1366/1024/768/
   390): "Built for Saudi / Arabia's heavy work." and "Our fleet. Our
   people. / Ready for the work." Leading moved from .98 (tighter than the
   type size) to 1.02, inside the 0.95–1.05 usable range for multi-line
   grotesk display. */
.hero-h{ color:#fff; font-size:clamp(2.05rem, min(6vw, 8.6vh), 5.4rem); line-height:1.02;
  letter-spacing:-.02em; max-width:22ch; text-wrap:balance }
/* Lead paragraph: comfortably looser leading than the display (1.7 vs the
   display's 1.02) and a measure that keeps lines inside the ~55–70 character
   readable range rather than running the full hero column. */
.hero-sub{ margin-top:22px; max-width:52ch; color:#DDE1E6; font-size:clamp(1rem,1.3vw,1.14rem); line-height:1.7 }
.hero-actions{ margin-top:34px; display:flex; flex-wrap:wrap; gap:16px; align-items:center }
.hero-tagline{ margin-top:30px; color:#fff; font-family:var(--mono); font-size:.7rem;
  letter-spacing:.18em; text-transform:uppercase; opacity:.78 }

/* numbered service strip along the hero's bottom edge — echoes the Ajyal
   tab-strip, static (no auto-advance JS): seven real anchors to #services */
.hero-foot{ position:relative; z-index:3; border-top:1px solid rgba(255,255,255,.14) }
/* Inside the full-bleed cinematic hero (concepts A/B) the strip must be
   PINNED to the hero's own bottom edge and taken out of flow — otherwise it
   is a second flex item beside .hero-in in #hero's row-flex container and
   both fight for width instead of stacking (measured: this was silently
   pushing the CTA below the fold at 1024x700, qa.py hero-fit). Concept C's
   #service-strip re-uses the same .hero-foot markup as an ordinary in-flow
   section, so the absolute rule is scoped to .hero-full only. */
#hero.hero-full .hero-foot{ position:absolute; inset-inline:0; inset-block-end:0 }
.hs-tabs{ max-width:var(--wrap); margin-inline:auto; padding:0 var(--gut);
  display:grid; grid-template-columns:repeat(7,1fr); column-gap:clamp(8px,1.6vw,20px) }
/* padding-inline-start is NOT optional here. Each cell carries a hairline rule
   on its inline-start edge, and with `padding:16px 0` the label sat 1px from
   that rule — measured [0,1,1,1,1,1,1] across the seven cells, i.e. the text
   was touching the divider. The owner's words: "its fully on the left ...
   needs a gap from the left" (2026-08-05). The FIRST cell keeps zero inset so
   its label still aligns with the headline and the page gutter above it; the
   other six are inset from their own rule. */
.hs-tab{ display:flex; flex-direction:column; gap:8px; padding:16px 0 18px; color:#fff;
  padding-inline-start:20px;
  border-inline-start:1px solid rgba(255,255,255,.16) }
.hs-tab:first-child{ border-inline-start:0; padding-inline-start:0 }
.hs-tab-i{ font-family:var(--mono); font-size:.66rem; letter-spacing:.12em; color:var(--accent-hi,var(--accent)) }
/* text-wrap:balance added 2026-08-05 (same typography pass as .hero-h): at
   seven columns the longer service names ("Construction & Contracting",
   "Transportation & Logistics") wrap, and the default greedy wrap stranded
   the LAST word alone ("Construction &" / "Contracting"). Balance moves the
   break to the ampersand instead ("Construction" / "& Contracting") so the
   second line is never a single orphaned word. */
/* ...and `balance` alone was NOT enough (owner, 2026-08-05: "still same issue
   with the strip"). Measured cause: `.hs-tabs` is capped at `max-width:var(--wrap)`
   (1280px), so from 1280px upward the seven columns are frozen at ~147px no
   matter how wide the screen gets — at 1920px the label box is still 147px.
   "Construction & Contracting" needs ~175px at this size, so two of the seven
   wrap and five do not: measured cell heights were [16, 32], which is exactly
   the ragged row the owner could see.

   The font cannot go smaller (12.5px is already the floor for a label), and
   widening the strip past --wrap would break alignment with every other section.
   So instead every label RESERVES two lines. The wrapped ones then sit in a row
   that matches the rest, and the strip reads as a deliberate grid rather than an
   accident. Below 1180px the grid drops to four columns, each label fits on one
   line, and the reservation is released so the strip does not carry dead space
   on a phone. */
.hs-tab-t{ font-family:var(--display); font-weight:600; font-size:.78rem; line-height:1.3;
  text-wrap:balance; min-block-size:2.6em }
@media (max-width:1180px){ .hs-tab-t{ min-block-size:0 } }
.hs-tab:hover .hs-tab-t{ color:var(--accent-hi,var(--accent)) }
/* Breakpoint moved 900px -> 1180px 2026-08-05: at 1024px-wide viewports the
   seven-column grid left ~146px per tab, which balance alone could not save
   for three-word names ("Heavy Equipment Rental", "Pipeline & Maintenance")
   — there is no even split of three words that avoids a short word landing
   alone. Four columns at 1024 give each tab enough room that every label
   (measured 1440/1366/1024/768/390) is a single line or an ampersand-led
   pair, never a lone word. */
@media (max-width:1180px){
  .hs-tabs{ grid-template-columns:repeat(4,1fr); row-gap:4px }
  .hs-tab:nth-child(4n+1){ border-inline-start:0 }
}
@media (max-width:560px){
  .hs-tabs{ grid-template-columns:repeat(2,1fr) }
  .hs-tab:nth-child(odd){ border-inline-start:0 }
}

/* --- 5 · stat band ------------------------------------------------------------ */
#stats{ padding-block-start:clamp(56px,8vh,84px); padding-block-end:clamp(56px,8vh,84px) }
.stats-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:var(--space-6) var(--space-4) }
@media (max-width:860px){ .stats-grid{ grid-template-columns:repeat(2,1fr) } }
.stat{ border-inline-start:2px solid var(--stat-line,var(--line)); padding-inline-start:22px }
.stat b{ display:block; font-family:var(--display); font-weight:700; letter-spacing:-.02em;
  font-size:clamp(1.7rem,2.9vw,2.6rem); line-height:1; font-variant-numeric:tabular-nums; min-height:1em }
.stat span{ display:block; margin-top:10px; font-size:.86rem; line-height:1.5; color:var(--stat-label,var(--txt-dim)) }
.stat em{ font-style:normal; color:var(--accent-hi,var(--accent)) }
.stat--pending{ border-style:dashed; opacity:.85 }
.stat--pending b{ letter-spacing:.06em }

/* --- 6 · split section (about / QHSE image pairs) ----------------------------- */
.split{ display:grid; grid-template-columns:minmax(0,5.6fr) minmax(0,6.4fr); gap:clamp(36px,5vw,80px); align-items:start }
.split.split-rev{ grid-template-columns:minmax(0,6.4fr) minmax(0,5.6fr) }
.split.split-rev .split-fig{ order:2 }
@media (max-width:860px){ .split, .split.split-rev{ grid-template-columns:1fr } .split.split-rev .split-fig{ order:0 } }
.split-copy h2{ font-size:var(--step-4); max-width:17ch }
.split-lead{ margin-top:24px; font-size:var(--step-1); line-height:1.65; font-weight:500; max-width:52ch }
.split-body{ margin-top:16px; max-width:58ch; color:var(--body-muted); line-height:1.65 }
.pull{ margin-top:26px; font-family:var(--display); font-weight:600; font-size:var(--step-2);
  line-height:1.32; max-width:30ch; border-inline-start:3px solid var(--accent); padding-inline-start:clamp(16px,2.4vw,26px) }
.chip-rail{ margin-top:30px; display:flex; flex-wrap:wrap; gap:10px }
.chip{ font-family:var(--mono); font-size:.68rem; letter-spacing:.12em; text-transform:uppercase;
  border:1px solid var(--chip-line,var(--line-ink)); border-radius:999px; padding:9px 16px;
  display:inline-flex; align-items:center; min-height:24px; color:var(--chip-txt,inherit) }
.split-fig figure{ border-radius:6px; overflow:hidden; background:var(--paper-2); aspect-ratio:4/3 }
.split-fig img{ width:100%; height:100%; object-fit:cover }

/* --- 7 · services index -------------------------------------------------------- */
#services .svc-head{ display:flex; flex-wrap:wrap; justify-content:space-between; align-items:flex-end;
  gap:18px; margin-bottom:32px }
#services .svc-head h2{ font-size:var(--step-3); max-width:22ch }
.svc-index{ list-style:none }
.svc-row{ display:grid; grid-template-columns:44px 1fr; gap:20px; align-items:start;
  padding-block:24px; border-top:1px solid var(--row-line,var(--line-ink)) }
.svc-row:last-child{ border-bottom:1px solid var(--row-line,var(--line-ink)) }
.svc-row.has-tile{ grid-template-columns:44px 1fr auto }
@media (max-width:640px){ .svc-row.has-tile{ grid-template-columns:44px 1fr } .svc-tile{ display:none } }
.svc-i{ font-family:var(--mono); font-size:.78rem; letter-spacing:.1em; padding-top:4px; color:var(--accent-hi,var(--accent)) }
.svc-t h3{ font-size:var(--step-2); font-weight:600 }
.svc-t p{ margin-top:8px; max-width:56ch; color:var(--body-muted); line-height:1.6; font-size:.96rem }
.svc-tile{ width:104px; border-radius:6px; overflow:hidden; aspect-ratio:4/3 }
.svc-tile img{ width:100%; height:100%; object-fit:cover }

/* --- 8 · trust / logo wall ------------------------------------------------------ */
#trust .trust-head{ margin-bottom:34px }
#trust .trust-head h2{ font-size:var(--step-3); max-width:26ch }
#trust .trust-lead{ margin-top:16px; max-width:58ch; color:var(--body-muted) }
.logo-wall{ margin-top:32px; display:grid; grid-template-columns:repeat(auto-fit,minmax(140px,1fr)); gap:2px;
  background:var(--logo-grid-line,var(--line-ink)); border:1px solid var(--logo-grid-line,var(--line-ink)) }
.logo-tile{ background:#fff; display:flex; align-items:center; justify-content:center; padding:22px 18px; min-height:96px }
.logo-tile img{ max-height:38px; width:auto; max-width:100% }
.trust-foot{ margin-top:28px; display:flex; flex-wrap:wrap; gap:12px; align-items:center }

/* --- 9 · QHSE ------------------------------------------------------------------- */
#qhse .qhse-cards{ margin-top:32px; display:flex; flex-direction:column; gap:14px }
.q-card{ border:1px solid var(--card-line,var(--line-ink)); border-inline-start:3px solid var(--accent);
  border-radius:6px; padding:22px 24px; background:var(--card-bg,transparent) }
.q-card h3{ font-size:1.02rem; font-weight:700; display:flex; gap:14px; align-items:baseline }
.q-card h3 i{ font-style:normal; font-family:var(--mono); font-size:.64rem; letter-spacing:.12em; color:var(--accent-hi,var(--accent)) }
.q-card p{ margin-top:8px; color:var(--body-muted); font-size:.92rem; line-height:1.6 }

/* --- 10 · contact ----------------------------------------------------------------- */
#contact .con-head h2{ font-size:var(--step-4) }
#contact .con-head p{ margin-top:14px; max-width:52ch; color:var(--body-muted) }
.con-grid{ margin-top:44px; display:grid; grid-template-columns:repeat(3,1fr); gap:18px }
@media (max-width:860px){ .con-grid{ grid-template-columns:1fr } }
.con-card{ border:1px solid var(--card-line,var(--line-ink)); border-radius:6px; padding:26px; background:var(--card-bg,transparent) }
.con-card .mono{ display:block; margin-bottom:14px; color:var(--accent-hi,var(--accent)) }
.con-card h3{ font-size:1.04rem }
.con-num{ display:block; margin-top:10px; font-family:var(--display); font-weight:700;
  font-size:clamp(1.1rem,1.7vw,1.4rem); font-variant-numeric:tabular-nums }
.con-acts{ margin-top:18px; display:flex; flex-wrap:wrap; gap:10px }
.con-mail{ display:block; margin-top:8px; word-break:break-word }
.con-office{ margin-top:36px; display:flex; flex-wrap:wrap; gap:10px 28px; color:var(--body-muted); font-size:.9rem }

/* --- 11 · footer -------------------------------------------------------------------- */
/* Grid rule (playbook): brand + link columns on row 1, legal line spans
   1/-1 on row 2 — never 1fr auto 1fr with the legal line in the middle. */
#site-footer{ padding-block-start:var(--space-7); padding-block-end:var(--space-5) }
.foot-grid{ display:grid; grid-template-columns:minmax(220px,1.3fr) repeat(3,minmax(150px,1fr));
  gap:var(--space-6) var(--space-5) }
@media (max-width:860px){
  .foot-grid{ grid-template-columns:1fr 1fr }
  .foot-brand{ grid-column:1/-1 }
}
@media (max-width:560px){ .foot-grid{ grid-template-columns:1fr } }

.foot-logo{ display:inline-flex; line-height:1; border-radius:6px }
.foot-logo img{ height:34px; width:auto }
.foot-tagline{ margin-top:16px; font-family:var(--mono); font-size:.68rem;
  letter-spacing:.16em; text-transform:uppercase; color:var(--footer-muted,inherit) }
.foot-creds{ margin-top:14px; max-width:34ch; font-size:.78rem; line-height:1.6; color:var(--footer-muted,inherit) }

.foot-h{ font-family:var(--display); font-weight:700; font-size:.82rem; letter-spacing:.02em; margin-bottom:14px }
/* #site-footer-scoped, not a bare .foot-col — two of these columns are <nav>
   elements, and ibix-base.css's own landmark reset (`#site-footer nav{
   display:block }`, (1,0,1)) otherwise outranks a plain class rule (0,1,0)
   and collapses the column back to inline running text. */
#site-footer .foot-col{ display:flex; flex-direction:column; gap:6px; min-width:0 }
/* WCAG 2.2 target minimum is 24x24 and the design brief treats it as
   never-traded. A footer link at .86rem renders ~19px tall, so the row
   needs an explicit floor — same pattern as .ibix-credit below. The gap
   is reduced to 6px so the columns do not grow taller for it. */
.foot-col a{ font-size:.86rem; color:var(--footer-muted,inherit); line-height:1.4;
  display:inline-flex; align-items:center; min-height:24px }
.foot-col a:hover{ color:var(--footer-accent,var(--accent)) }

.foot-addr{ font-size:.86rem; line-height:1.6; color:var(--footer-muted,inherit); max-width:30ch }
.foot-link-plain{ display:inline-flex; align-items:center; min-height:24px;
  margin-top:10px; font-size:.86rem; color:var(--footer-muted,inherit);
  word-break:break-word }
.foot-link-plain:hover{ color:var(--footer-accent,var(--accent)) }

.foot-legal-row{ grid-column:1/-1; margin-top:var(--space-5); padding-top:var(--space-4);
  border-top:1px solid var(--footer-line,var(--line-ink));
  display:flex; flex-wrap:wrap; justify-content:space-between; align-items:center; gap:14px 24px }
.foot-legal{ font-size:.84rem; color:var(--footer-muted,inherit) }
/* mandatory footer credit — whole phrase is the link, visible underline at
   rest, hover state, clears the 24px WCAG target (playbook rule, all four
   points enforced by qa.py's ibix-credit check) */
.ibix-credit{ display:inline-flex; align-items:center; min-height:24px;
  text-decoration:underline; text-underline-offset:2px; color:inherit }
.ibix-credit:hover{ color:var(--footer-accent,var(--accent)) }

/* --- 11b · careers band ------------------------------------------------------------- */
#careers .careers-in{ display:grid; grid-template-columns:minmax(0,6.4fr) minmax(0,5.6fr);
  gap:clamp(28px,4vw,64px); align-items:center }
@media (max-width:860px){ #careers .careers-in{ grid-template-columns:1fr } }
#careers h2{ font-size:var(--step-4); max-width:18ch }
#careers .careers-lead{ margin-top:18px; max-width:56ch; font-size:var(--step-1); line-height:1.6;
  color:var(--body-muted) }
#careers .careers-themes{ margin-top:26px; display:flex; flex-wrap:wrap; gap:10px }
#careers .careers-actions{ margin-top:8px; display:flex; align-items:center }
@media (max-width:860px){ #careers .careers-actions{ margin-top:28px } }

/* --- 12 · concept chrome (demo only) --------------------------------------------------- */
/* Demo chrome — a STATIC bar at the very top of the document, not a fixed
   overlay. It was position:fixed bottom-left, which put it permanently on top
   of the hero's service strip: measured 2026-08-05 covering "Rig Moving" and
   "Heavy Equipment Rental" at desktop, and after being nudged up by 90px it
   simply collided with different items at 768px and 390px, because the strip's
   height changes with its column count. A fixed overlay above a variable-height
   element is a guess that has to be re-made at every breakpoint; putting the
   pill in normal flow removes the collision entirely, at any width, forever.
   It scrolls away with the page, which is right — it is our label, not RANCO's
   content, and the gallery link is in the footer too. */
.concept-pill{ margin:0; padding:10px var(--gut); text-align:center;
  background:#101319; color:#fff; font-family:var(--mono); font-size:.68rem;
  letter-spacing:.12em; text-transform:uppercase; }
.concept-pill a{ text-decoration:underline; color:#fff; display:inline-flex; align-items:center; min-height:24px }
@media (max-width:720px){ .concept-pill{ font-size:.62rem; padding:8px 12px } }
