/* ============================================================
   Tech True Point hero: "ribbon" (homepage transformation step 1,
   owner brief 2026-07-14). Premium black / blue / gold.
   Fully scoped under .rh so the rest of the site is untouched.

   Palette (owner brief):
     near-black #050505 · navy #12335F · royal blue #2A6BE2 (artwork-sampled)
     carolina #7BAFD4 · gold #D4A84F · text #F7F9FC

   Fallback discipline: .rh-fallback (pure CSS gradients, later a
   captured still) is the default visual. The WebGL canvas fades in
   over it only after the first rendered frame (.rh-live). No-JS,
   reduced-motion, phones, and WebGL failure all keep the fallback.
   ============================================================ */

/* artwork-matched royal blue family overrides the old cyan accents
   (sampled from the owner's reference mock 2026-07-14) */
:root {
  --primary: #1D6BE8;
  --primary-dark: #0549B4;
  --accent: #2A6BE2;
  --baby: #6FA5EF;
  --baby-soft: #9FC2F5;
}

.rh .container,
body.story-dark .site-header .container { max-width: 1560px; }

/* Hero palette lives on the PAGE, not on .rh: the service strip moved out of
   the hero (2026-07-14 refinement) and still consumes these vars. Scoping them
   to .rh would leave .rh-cat with unresolved colors. */
body.story-dark {
  --rh-bg: #050505;
  --rh-navy: #12335F;
  --rh-blue: #2A6BE2;
  --rh-carolina: #7BAFD4;
  --rh-gold: #D4A84F;
  --rh-gold-soft: #DDBA6E;
  --rh-text: #F7F9FC;
  --rh-muted: #AFC0D4;
  --rh-line: rgba(123, 175, 212, 0.16);
}

.rh {
  position: relative;
  display: flex;
  flex-direction: column;
  /* fold-fit: viewport minus the 104px sticky header. The hero is now copy
     only; the service strip sits in its own section directly below. */
  min-height: calc(100svh - 104px);
  overflow: clip;
  background: var(--rh-bg);
}

/* homepage page background: near-black so the hero and the sections
   below share one canvas (loads after styles.css, so this wins) */
body.story-dark .bg {
  background:
    radial-gradient(90% 60% at 78% -8%, rgba(18, 51, 95, 0.55) 0%, rgba(5, 5, 5, 0) 60%),
    radial-gradient(70% 55% at 8% 30%, rgba(18, 51, 95, 0.28) 0%, rgba(5, 5, 5, 0) 65%),
    linear-gradient(180deg, #050505 0%, #040507 100%);
}
body.story-dark .bg::after { display: none; }

/* ---------- visual layer ---------- */
.rh-visual { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.rh-canvas {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  opacity: 0; transition: opacity .8s var(--ease);
}
.rh.rh-live .rh-canvas { opacity: 1; }

/* Boot / no-JS / WebGL-failure poster: the approved artwork itself, FULL-BLEED
   (not right-weighted as before). This is first paint and the permanent visual
   when WebGL is unavailable, so it must match the live look. The shader
   cross-fades over it once its first frame is drawn (.rh-live). */
.rh-fallback {
  position: absolute; inset: 0;
  opacity: 1; transition: opacity .8s var(--ease), visibility 0s .9s;
  background:
    url("../assets/hero-art1.webp") center center / cover no-repeat,
    var(--rh-bg);
}
.rh.rh-live .rh-fallback { opacity: 0; visibility: hidden; }

/* Readability without a hard left/right curtain: a soft radial pool behind the
   copy column only, so the text floats inside one full-bleed environment
   rather than sitting beside a masked-off panel. */
.rh-visual::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(70% 82% at 20% 50%, rgba(5, 5, 7, 0.88) 0%, rgba(5, 5, 7, 0.45) 40%, rgba(5, 5, 7, 0) 64%);
}
@media (max-width: 899px) {
  /* on phones the copy sits over a full-bleed field; darken the whole top */
  .rh-visual::after {
    background: linear-gradient(180deg, rgba(5,5,7,0.82) 0%, rgba(5,5,7,0.35) 42%, rgba(5,5,7,0) 72%);
  }
}

/* ---------- copy (centered in the space above the category row) ---------- */
.rh-inner {
  position: relative; z-index: 1; width: 100%;
  flex: 1 1 auto; display: flex; align-items: center;
  padding-top: var(--s-4); padding-bottom: var(--s-3);
}
.rh-copy { max-width: 74rem; }
/* lift the composition out of the dead space under the header, and pull it
   slightly left (owner brief item 1). The X shift stays at -16px: .container
   only carries 24px of left padding and is full-width at <=1560, so a deeper
   shift clips the first glyph at 1280. */
@media (min-width: 900px) {
  .rh-copy { transform: translate(-16px, -76px); }
}

.rh-eyebrow {
  display: block;
  font-size: clamp(.88rem, .95vw, 1.35rem); font-weight: 600;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--rh-gold-soft);
  margin-bottom: var(--s-2);
}

/* Longer, sentence-style headline (2026-07-23 rewrite, ~83 characters incl.
   the "moving forward." span). The old 3.4-6.9rem scale was tuned for a
   3-word-per-line lockup; at that size this longer sentence wraps to 4-5
   lines even at 1280+ and overflows into 6+ on phones. Re-measured against
   the ACTUAL rendered headline in a real browser (not estimated): the fixed
   1184px .rh-copy column holds this sentence in <=3 lines up to ~78px, and
   the 342px mobile column at 390px holds it in <=5 lines up to ~36px, so
   both ends of this clamp sit a few px inside those measured limits. */
.rh h1 {
  color: var(--rh-text);
  font-size: clamp(2.75rem, 4.6vw, 4.75rem);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin-bottom: var(--s-4);
  text-shadow: 0 2px 40px rgba(5, 7, 12, 0.55); /* lift off the ribbons */
}
.rh h1 .rh-blue {
  color: #3B82F6; /* electric brand blue, a touch brighter over the dark field */
  text-shadow: 0 0 34px rgba(59, 130, 246, 0.45);
}

/* Supporting paragraph: larger and higher-contrast (owner 2026-07-19). */
.rh-lead {
  color: #CBD8E8;
  font-size: clamp(1.25rem, 1.35vw, 1.5rem); line-height: 1.65;
  max-width: 620px;
  margin-bottom: var(--s-6);
}

/* ---------- CTAs (height + padding up ~15%, owner brief item 7) ---------- */
.rh-cta { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-2); }
.rh-cta .btn-lg { padding: 1.32rem 2.42rem; font-size: clamp(1.1rem, .95vw, 1.45rem); }
.rh-cta .btn svg { width: 18px; height: 18px; }

.rh .rh-btn-primary {
  background: linear-gradient(180deg, #1D6BE8 0%, #0549B4 100%);
  color: #fff;
  border: 1px solid rgba(80, 140, 240, 0.45);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 10px 30px -8px rgba(29, 107, 232, 0.50);
}
.rh .rh-btn-primary:hover {
  transform: translateY(-2px); color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 14px 36px -8px rgba(29, 107, 232, 0.65);
}
/* Secondary CTA: stronger gold so it never reads as disabled (owner
   2026-07-19). Brighter fill, solid gold border, bright gold text. */
.rh .rh-btn-gold {
  background: rgba(212, 168, 79, 0.12);
  color: #F4DFA6;
  border: 1px solid rgba(221, 186, 110, 0.85);
  box-shadow: inset 0 1px 0 rgba(255, 235, 180, 0.18), 0 8px 24px -10px rgba(212, 168, 79, 0.40);
}
.rh .rh-btn-gold:hover {
  transform: translateY(-2px);
  background: rgba(212, 168, 79, 0.22);
  border-color: #E9C877;
  color: #FCEFC6;
  box-shadow: inset 0 1px 0 rgba(255, 235, 180, 0.28), 0 14px 34px -10px rgba(212, 168, 79, 0.55);
}

/* ---------- service strip: its OWN black section directly below the hero
   (owner brief item 10; it used to overlay the liquid visual and fight the
   artwork). Items stay UNBOXED: no card backgrounds, faint separators only,
   subtle blue underline on hover. ---------- */
.svc-strip {
  position: relative; z-index: 1;
  background: var(--rh-bg);
  padding: var(--s-6) 0 var(--s-8);
}

.rh-cats {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: repeat(4, 1fr);
  margin: 0;
}
.rh-cat {
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: .75rem; padding: var(--s-3) var(--s-3) 1.4rem;
  border-left: 1px solid rgba(123, 175, 212, 0.10); /* very faint separator */
  color: var(--rh-text);
  transition: transform .25s var(--ease);
}
.rh-cat:first-child { border-left: 0; }
/* icon / title / description all up a step (owner brief item 11) */
.rh-cat svg { width: 44px; height: 44px; color: var(--rh-gold); }
/* min-height = 2 lines so the descriptions align across the row: at the new
   size two titles wrap ("Web Design & Development") and two do not, which
   left the row visibly ragged. */
.rh-cat strong {
  font-weight: 650; font-size: clamp(1.3rem, 1.2vw, 1.75rem); letter-spacing: -0.01em;
  line-height: 1.25; min-height: 2.5em;
}
.rh-cat span { font-size: clamp(1.05rem, .95vw, 1.4rem); color: var(--rh-muted); line-height: 1.5; }
/* thin carolina underline that draws left to right */
.rh-cat::before {
  content: ""; position: absolute; left: 18%; right: 18%; bottom: 0; height: 2px;
  background: linear-gradient(90deg, var(--rh-carolina), var(--rh-blue));
  border-radius: 2px;
  transform: scaleX(0); transform-origin: left center;
  transition: transform .35s var(--ease);
}
/* soft blue glow pooled beneath the lifted item (kept, but dialled back so the
   underline stays the hover signal rather than the glow) */
.rh-cat::after {
  content: ""; position: absolute; left: 24%; right: 24%; bottom: -8px; height: 12px;
  background: radial-gradient(50% 100% at 50% 0%, rgba(42, 107, 226, 0.28), transparent 70%);
  filter: blur(6px);
  opacity: 0; transition: opacity .25s var(--ease);
  pointer-events: none;
}
/* .rh-cat is now a non-interactive credibility strip (plain divs, not links):
   the lift/underline/glow hover treatment below was written for the old
   <a class="rh-cat"> and is dropped so a stationary div never signals it is
   clickable. Selectors were already generic (".rh-cat", never "a.rh-cat"),
   so no other adjustment was needed for the div markup to render identically. */

/* Bottom indicator (owner 2026-07-19): a quiet capability line low in the
   hero, sitting above the fade. Gold dividers, uppercase, restrained. */
.rh-ticker {
  position: absolute; left: 0; right: 0; bottom: 26px; z-index: 1;
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: .55rem 1.1rem; padding: 0 var(--s-3);
  font-size: clamp(.72rem, .78vw, .92rem); font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--rh-muted); pointer-events: none;
}
.rh-ticker span { color: #D9E4F1; }
.rh-ticker i { width: 5px; height: 5px; border-radius: 50%; background: var(--rh-gold);
  box-shadow: 0 0 8px rgba(212, 168, 79, 0.7); display: inline-block; }
/* On small screens the hero is content-height, so an absolutely-positioned
   bottom ticker collides with the CTAs. Put it back in normal flow, below the
   buttons, inside the copy column. */
@media (max-width: 899px) {
  .rh-ticker {
    position: static; margin: var(--s-5) 0 var(--s-3); justify-content: flex-start;
    letter-spacing: .12em; gap: .4rem .7rem; padding: 0 var(--s-3);
  }
}

/* smooth handoff into the next section */
.rh-fade {
  position: absolute; left: 0; right: 0; bottom: 0; height: 140px; z-index: 0;
  background: linear-gradient(180deg, rgba(5, 5, 5, 0) 0%, rgba(5, 5, 5, 0.9) 100%);
  pointer-events: none;
}

/* ---------- header: transparent over the black canvas ---------- */
body.story-dark .site-header {
  background: rgba(5, 5, 5, 0.35);
  border-bottom-color: rgba(247, 249, 252, 0.06);
}
/* logo +20% (74 -> 89px), so the bar grows 84 -> 104px to hold it without
   crowding (owner brief item 8). .rh min-height tracks this number. */
@media (min-width: 900px) {
  body.story-dark .nav { height: 104px; }
}
body.story-dark .site-header .brand-logo { height: 66px; }
/* Laptop band 900-1199: the +20% logo (223px wide) + 3.2rem gaps + 6 links +
   the CTA crowd a single row here. This band keeps the previous tighter
   chrome; the brief's bump lands at >=1200 where it fits.
   MUST come after the 89px rule above — same specificity, so source order
   decides. */
@media (min-width: 900px) and (max-width: 1199px) {
  body.story-dark .nav { height: 88px; }
  body.story-dark .site-header .brand-logo { height: 56px; }
  body.story-dark .nav-links { gap: 1.9rem; }
  .rh { min-height: calc(100svh - 88px); }
}
/* below 900 the nav is the base 70px bar (styles.css) and the hamburger shares
   the row, so the logo stays conservative here — the +20% is a desktop
   composition call, and a 67px logo plus its drop-shadow crowds a 70px bar. */
/* 1200-1439: the 66px step above is sized for >=1440. At 1200 it renders 265px
   wide and leaves an 11px gap to "Home". */
@media (min-width: 1200px) and (max-width: 1439px) { body.story-dark .site-header .brand-logo { height: 56px; } }
@media (max-width: 899px) { body.story-dark .site-header .brand-logo { height: 50px; } }
@media (max-width: 560px) { body.story-dark .site-header .brand-logo { height: 44px; } }

/* Sticky shrink on the homepage: a SLIGHT, proportional reduction per tier.
   Without these overrides the base rule (styles.css) collapsed the tall
   story-dark bar from 104px to 58px, a 46px jump of a sticky-at-top header
   that shoved the whole page up and thrashed layout every frame while the
   WebGL hero ran (owner: "top bar gets stuttery when you scroll"). An ~18px
   shrink reads as "condensed" without the lurch. Must follow the height
   ladder above so source order wins. */
@media (min-width: 900px) {
  body.story-dark .site-header.is-stuck .nav { height: 86px; }
  body.story-dark .site-header.is-stuck .brand-logo { height: 56px; }
}
@media (min-width: 900px) and (max-width: 1199px) {
  body.story-dark .site-header.is-stuck .nav { height: 74px; }
  body.story-dark .site-header.is-stuck .brand-logo { height: 48px; }
}
@media (min-width: 1800px) {
  body.story-dark .site-header.is-stuck .nav { height: 100px; }
  body.story-dark .site-header.is-stuck .brand-logo { height: 66px; }
}
/* nav: 15-16px links with more air between them */
body.story-dark .nav-links { gap: 3.2rem; }
body.story-dark .nav-links a { font-size: clamp(0.9375rem, .9vw, 1rem); }
@media (min-width: 900px) { body.story-dark .nav-cta { padding: 1rem 1.7rem; font-size: 1.02rem; } }
body.story-dark .nav-links a { position: relative; }
/* minimal blue indicator under the active page */
body.story-dark .nav-links a[aria-current="page"]::after {
  content: ""; position: absolute; left: 50%; transform: translateX(-50%);
  bottom: -8px; width: 22px; height: 2px; border-radius: 2px;
  background: var(--rh-blue, #2A6BE2);
}
/* calm the Get a Quote glow further (owner brief item 9): near-flat button,
   just an inset top light and a whisper of lift */
body.story-dark .nav-cta,
body.story-dark .nav-cta:hover {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.12), 0 2px 8px -6px rgba(29, 107, 232, 0.22);
}

/* ============================================================
   Mobile (<900px): headline and CTAs first, static visual behind,
   compact height, no horizontal overflow.
   ============================================================ */
@media (max-width: 899px) {
  .rh { min-height: auto; padding: var(--s-6) 0 0; }
  .rh-inner { padding-top: var(--s-4); }
  /* phones: the artwork full-bleed behind the copy (the shader draws over it on
     capable devices; this is the boot / no-WebGL state). */
  .rh-fallback {
    background:
      url("../assets/hero-art1.webp") center center / cover no-repeat,
      var(--rh-bg);
  }
  /* Phones show the art full-bleed BEHIND the copy (no left/right split), so
     the vertical ramp must darken the top too: it used to start fully
     transparent, leaving the eyebrow + headline sitting on the brightest gold
     particles. The art still reads as texture underneath. */
  .rh-visual::after {
    background: linear-gradient(180deg,
      rgba(5, 5, 5, 0.80) 0%,
      rgba(5, 5, 5, 0.72) 35%,
      rgba(5, 5, 5, 0.62) 55%,
      rgba(5, 5, 5, 0.86) 100%);
  }
  .rh h1 { font-size: clamp(2rem, 8vw, 2.4rem); }
  .rh-lead { font-size: 1.125rem; max-width: 100%; }
  .rh-cta .btn { flex: 1 1 auto; min-width: 0; }
  .svc-strip { padding: var(--s-6) 0; }
  .rh-cats { grid-template-columns: repeat(2, 1fr); margin: 0; row-gap: var(--s-4); }
  .rh-cat { padding: var(--s-3) var(--s-2) 1.1rem; }
  .rh-cat:nth-child(odd) { border-left: 0; }
  .rh-cat svg { width: 34px; height: 34px; }
  .rh-cat strong { font-size: 1.05rem; }
  .rh-cat span { font-size: .9rem; }
}

/* very narrow phones: single column categories */
@media (max-width: 380px) {
  .rh-cats { grid-template-columns: 1fr; }
  .rh-cat { border-left: 0; }
}

/* reduced motion: the canvas now renders ONE settled frame (a polished static
   state that matches the live art), so it must stay in the layout. js draws
   once and adds .rh-live, which reveals the canvas and hides the gradient
   poster (transitions are disabled here, so the swap is instant). If WebGL is
   unavailable, .rh-live is never added and the gradient poster remains, which
   is the correct no-WebGL static state. */
@media (prefers-reduced-motion: reduce) {
  .rh-canvas { display: block; }
}

/* ============================================================
   Below-the-fold gold pass (transformation step 2, 2026-07-14).
   Homepage only (this stylesheet loads on index.html): brings the
   existing sections onto the hero's black / blue / gold system.
   Markup untouched; overrides ride on body.story-dark scope.
   ============================================================ */

/* eyebrow pills: gold voice */
body.story-dark .eyebrow {
  color: var(--rh-gold-soft, #DDBA6E);
  border-color: rgba(212, 168, 79, 0.30);
  background: rgba(212, 168, 79, 0.05);
}
body.story-dark .eyebrow::before {
  background: #D4A84F;
  box-shadow: 0 0 8px rgba(212, 168, 79, 0.8);
}

/* buttons: match the hero exactly */
body.story-dark .btn-primary {
  background: linear-gradient(180deg, #1D6BE8 0%, #0549B4 100%);
  color: #fff;
  border: 1px solid rgba(80, 140, 240, 0.45);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 10px 30px -8px rgba(29, 107, 232, 0.50);
}
body.story-dark .btn-primary:hover {
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 14px 36px -8px rgba(29, 107, 232, 0.65);
}
body.story-dark .btn-ghost {
  background: rgba(212, 168, 79, 0.06);
  color: var(--rh-gold-soft, #DDBA6E);
  border: 1px solid rgba(212, 168, 79, 0.50);
}
body.story-dark .btn-ghost:hover {
  background: rgba(212, 168, 79, 0.14);
  border-color: rgba(221, 186, 110, 0.75);
  color: #F3DCA8;
}

/* cards: quieter panels, gold instruments */
body.story-dark .card {
  background: rgba(255, 255, 255, 0.030);
  border-color: rgba(150, 175, 205, 0.13);
}
body.story-dark .card .ico {
  background: rgba(212, 168, 79, 0.07);
  border-color: rgba(212, 168, 79, 0.35);
  color: #D4A84F;
  box-shadow: none;
}
body.story-dark .card-hover:hover .ico {
  background: rgba(212, 168, 79, 0.16);
  color: #F3DCA8;
  box-shadow: 0 10px 26px -8px rgba(212, 168, 79, 0.45);
}
body.story-dark .card-hover:hover {
  border-color: rgba(212, 168, 79, 0.35);
  box-shadow: var(--shadow), 0 0 44px rgba(212, 168, 79, 0.10);
}

/* numbered value panels + featured card + checkmarks: gold */
body.story-dark .value-num { color: #D4A84F; }
body.story-dark .price-card.featured {
  border-color: rgba(212, 168, 79, 0.40);
  box-shadow: var(--shadow), 0 0 44px rgba(212, 168, 79, 0.12);
}
body.story-dark .price-tag {
  color: #1A1204;
  background: linear-gradient(180deg, #EDCB86, #D4A84F);
  box-shadow: 0 8px 20px -6px rgba(212, 168, 79, 0.7);
}
body.story-dark .feature-list li::before {
  background: rgba(212, 168, 79, 0.10) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23D4A84F' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/12px no-repeat;
  border-color: rgba(212, 168, 79, 0.35);
}

/* capability chips: gold icons, calm text */
body.story-dark .pill { border-color: rgba(150, 175, 205, 0.16); }
body.story-dark .pill svg { color: #D4A84F; }
body.story-dark .tag { border-color: rgba(150, 175, 205, 0.16); }

/* CTA band: black glass with a navy heart and gold edge light */
body.story-dark .cta-band {
  background:
    radial-gradient(120% 130% at 80% 0%, rgba(18, 51, 95, 0.75), rgba(5, 6, 10, 0.85)),
    #05060A;
  border-color: rgba(212, 168, 79, 0.32);
  box-shadow: var(--shadow-lg), 0 0 60px rgba(212, 168, 79, 0.10);
}
body.story-dark .cta-band .eyebrow { background: rgba(212, 168, 79, 0.08); }

/* large desktops (27-32 inch monitors): the chrome scales up too. Kept above
   the base tier now that the base logo is 89px / bar 104px. */
@media (min-width: 1800px) {
  body.story-dark .nav { height: 122px; }
  body.story-dark .site-header .brand-logo { height: 78px; }
  body.story-dark .nav-links { gap: 3.8rem; }
  body.story-dark .nav-cta { padding: 1.15rem 2.1rem; font-size: 1.2rem; }
  .rh { min-height: calc(100svh - 122px); }
  /* The copy sits in a CENTRED 1560px container, so past ~1800 the headline
     pushes right while a viewport-% mask stays put: at 2560 "Business
     Results." ran ~460px past the old transparent point and landed on the lit
     ribbon. Ramp extended to follow the copy without burying the artwork. */
  .rh-visual::after {
    background: linear-gradient(90deg,
      rgba(5, 5, 5, 0.97) 0%,
      rgba(5, 5, 5, 0.94) 28%,
      rgba(5, 5, 5, 0.82) 42%,
      rgba(5, 5, 5, 0.52) 53%,
      rgba(5, 5, 5, 0.20) 61%,
      rgba(5, 5, 5, 0) 68%);
  }
  .svc-strip { padding: var(--s-8) 0 var(--s-12); }
  .rh-cat svg { width: 52px; height: 52px; }
  .rh-cat { padding-top: var(--s-4); gap: .9rem; }
}
