/* ==========================================================================
   Greenebrick, v30-juphero
   Built to the numbers measured off juphero.framer.website and /work, which
   are recorded in work/personal-site/brief.md under v30-juphero. Written from
   an empty file. Framer builds this in React with Framer Motion; this matches
   the look only, in plain CSS and one vanilla script.

   Every size runs from its measured 414 value to its measured 1440 value on
   a straight line: clamp(min, a + b*vw, max) with b = (max - min) / 1026.
   ========================================================================== */

/* The type, fixed 2026-09-27: the type switcher's pairing B, now the only one.
   Oswald 600 display, IBM Plex Sans text, IBM Plex Mono labels. All SIL OFL 1.1,
   Latin subset, self-hosted (the CSP blocks Google Fonts); licences beside them. */
@font-face { font-family: 'Oswald'; src: url('../fonts/Oswald-600.latin.woff2') format('woff2');
             font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'IBM Plex Sans'; src: url('../fonts/IBMPlexSans-VF.latin.woff2') format('woff2');
             font-weight: 400 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'IBM Plex Mono'; src: url('../fonts/IBMPlexMono-400.latin.woff2') format('woff2');
             font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'IBM Plex Mono'; src: url('../fonts/IBMPlexMono-500.latin.woff2') format('woff2');
             font-weight: 500; font-style: normal; font-display: swap; }

:root {
  /* ---- palette: LIGHT. The site ran dark navy; it now runs on warm
     off-white. Every rule reads these names, so the flip happens here once.
     The names are kept from the dark build and their roles are unchanged:
     --white is the strongest ink (headings, the button fill), --ground the
     page, --t1 to --t3 body to dim, --cyan the accent. On light, the
     "white" is ink and the "cyan" is a deep teal. ------------------------- */
  --ground:  #F4F2EC;   /* page, warm off-white                         */
  --panel:   #ECEAE3;   /* the menu panel, image mats                   */
  --teal:    #D6E6EA;   /* the arrow square inside a dark button        */
  --white:   #16212C;   /* strongest ink: headings, button fill         */
  --t1:      #3B4652;   /* body            8.2:1 on the ground          */
  --t2:      #56626F;   /* secondary       5.6:1                        */
  --t3:      #5E6B77;   /* dim             4.9:1                        */
  --cyan:    #1F5E72;   /* accent: eyebrows, links, the step dot  6.4:1 */
  --line:    rgba(22, 33, 44, .13);
  --glass:   linear-gradient(180deg, #FDFCF9 0%, #F8F7F2 100%);   /* a card */
  --dots:    rgba(22, 33, 44, .10);     /* the step card's dot field      */
  --glow:    rgba(40, 88, 115, .10);    /* soft teal light under a column */
  --bloom:   rgba(124, 194, 215, .32);  /* the page-head streaks          */
  --field:   rgba(22, 33, 44, .025);
  --bg:      radial-gradient(ellipse 120% 60% at 20% 0%, #FAF8F3 0%, rgba(250, 248, 243, 0) 60%),
             linear-gradient(180deg, #F6F4EE 0%, #F1F0EA 55%, #ECEEEC 100%);
  /* light-page shadows: larger, softer, lower opacity than anything a dark
     page needs, and cool rather than black so they read as depth */
  --shadow-1: 0 1px 2px rgba(22, 33, 44, .04), 0 14px 36px -16px rgba(22, 33, 44, .14);
  --shadow-2: 0 1px 2px rgba(22, 33, 44, .05), 0 34px 80px -34px rgba(22, 33, 44, .26);
  --line-strong: rgba(22, 33, 44, .55);   /* a boundary that must read (field outlines): 3:1 on the ground */
  --grade:   13 19 23;                    /* the photo grades, as rgb channels for rgb(var(--grade) / a) */
  --scrim:   rgba(4, 7, 14, .55);         /* behind the open menu */

  /* ---- radii, exactly the reference's ---------------------------------- */
  --r-card: 8px;
  --r-btn:  6px;
  --r-sq:   4px;

  /* ---- type: pairing B, made permanent 2026-09-27 ---------------------
     Oswald's caps are .81 of the em against Koulen's .714, so the display scale
     runs at .85 of the Koulen build's (width parity: Oswald sets 19% wider per
     em). Plex Sans's x-height is .518, near Manrope's, so text runs 4% larger. */
  --f-display: 'Oswald', 'Arial Narrow', sans-serif;
  --f-text:    'IBM Plex Sans', -apple-system, BlinkMacSystemFont, Arial, sans-serif;
  --f-label:   'IBM Plex Mono', ui-monospace, Menlo, monospace;
  --f-title:    var(--f-text);    /* card titles, the menu links, the contact values */
  --f-num:      var(--f-label);   /* the 01 / 02 / 03 numbers                        */
  --f-eyebrow:  var(--f-label);   /* eyebrows                                        */
  --f-wordmark: var(--f-label);   /* the GREENEBRICK wordmark in the nav            */
  --f-footmark: var(--f-label);   /* the name in the footer lockup                   */
  --display-w: 600;  --display-lh: .98; --display-case: uppercase;  --hero-ls: -.006em; --h2-ls: -.004em;
  --title-w: 600;    --title-lh: 1.12;  --title-case: none;         --title-ls: -.01em;   --reach-ls: -.01em;
  --num-w: 500;      --num-ls: 0;       --num-dot-gap: 0;
  --body-w: 450;     --body-lh: 1.45;   --body-ls: 0;     --measure: 33em;
  --eyebrow-w: 500;  --eyebrow-ls: .22em;
  --hero-eyebrow-size: var(--t-eyebrow); --hero-eyebrow-ls: var(--eyebrow-ls);   /* the hero's, which also carries a 56px rule */
  --phead-eyebrow-size: clamp(15px, 12.58px + .5848vw, 21px);                   /* a page head's, set a step above a section's */
  --wm-k: .36;                        /* wordmark tracking, and the indent that balances it. Kept from the
                                         2026-09-27 nav changes rather than B's older .30 and smaller size */
  --footmark-size: clamp(20px, 17.58px + .5848vw, 26px); --footmark-w: 400; --footmark-ls: .30em; --footmark-case: uppercase;
  --cta-fit: 6.35;                    /* how many cap widths "Your Website." takes: sizes the CTA heading to fit */
  --t-hero:    calc(clamp(68px, 38.95px + 7.0175vw, 140px) * .85);
  --t-h2:      calc(clamp(54px, 27.37px + 6.4327vw, 120px) * .85);
  --t-title:   clamp(26px, 19.54px + 1.559vw, 42px);
  --t-num:     clamp(24px, 19.96px + .9747vw, 34px);
  --t-state:   clamp(32px, 28.77px + .7797vw, 40px);
  --t-q:       calc(clamp(20px, 16.77px + .7797vw, 28px) * 1.02);
  --t-btn:     clamp(20px, 18.39px + .3899vw, 24px);
  --t-body:    calc(clamp(16px, 12.77px + .7797vw, 24px) * 1.04);
  --t-eyebrow: clamp(14px, 12.79px + .2924vw, 17px);
  --t-small:   16px;
  --t-label:   13px;                                      /* small-caps labels, tracked .14em */

  /* ---- space ------------------------------------------------------------ */
  --pad:  20px;          /* side padding at every width */
  --gap:  20px;          /* grid gap at every width     */
  --head: 68px;          /* header height               */
  --sec:  clamp(80px, 48.7px + 7.57vw, 157px);   /* section to section, 157 at 1440 */
  --sp-head: clamp(32px, 28px + 1.1vw, 48px);    /* a section head to its content, everywhere */
  --sp-copy: 24px;                                /* between blocks of copy inside a section  */
  --sp-title: 12px;                               /* a card title to its body copy            */
  --pad-card: 32px;                               /* inside every card; 20 below 1024         */

  /* ---- motion, measured ------------------------------------------------- */
  --ease-in:   cubic-bezier(.16, 1, .3, 1);     /* scroll-in, 1000ms       */
  --ease-load: cubic-bezier(.44, 0, .56, 1);    /* hero load and buttons   */
  --dur-fast: .2s;                              /* colour and underline on hover        */
  --dur:      .3s;                              /* buttons, cards, icons, the logo haze */
}
@media (max-width: 1023px) { :root { --pad-card: 20px; } }
@media (max-width: 480px) { :root { --t-eyebrow: 12.5px; --eyebrow-ls: .14em; --hero-eyebrow-size: 12px; --hero-eyebrow-ls: .08em; --phead-eyebrow-size: 13px; } }   /* pairing B's phone step: the long mono eyebrows stay on one line */

/* ---- the dark scope. The footer, the photo hero and the photo CTA are
   dark on purpose; inside them the
   same names take the dark build's values back, so every rule reads right
   without an override of its own. ------------------------------------------- */
.on-dark {
  --ground: #090E1A; --panel: #0F172A; --teal: #002439;
  --white: #FFFFFF; --t1: #CBD5E1; --t2: #94A3B8; --t3: #7385A0; --cyan: #A6ECFF;
  --line: rgba(203, 213, 225, .14);
  color: var(--t1);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; overflow-x: clip; scroll-behavior: smooth; }
/* reduced motion: every transition and animation on the page resolves at once */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}
body {
  margin: 0; background: var(--bg); background-color: var(--ground); color: var(--t1);
  font-family: var(--f-text); font-size: var(--t-small); font-weight: 500;
  line-height: 1.5; letter-spacing: .2px; -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; height: auto; }
h1, h2, h3, h4, p, figure, ol, ul { margin: 0; }
ol, ul { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
:focus-visible { outline: 2px solid var(--cyan); outline-offset: 4px; border-radius: 4px; }
.btn:focus-visible, .head__cta:focus-visible, .wcard:focus-visible { outline-offset: 5px; }

.skip { position: absolute; left: -9999px; top: 8px; z-index: 100; background: var(--white);
        color: var(--ground); padding: 12px 18px; border-radius: var(--r-btn); font-weight: 700; }
.skip:focus { left: 8px; }

/* ================================================================ type == */

.t-hero  { font-family: var(--f-display); font-weight: var(--display-w); font-size: var(--t-hero);
           line-height: var(--display-lh); letter-spacing: var(--hero-ls); text-transform: var(--display-case); color: var(--white); }
.t-h2    { font-family: var(--f-display); font-weight: var(--display-w); font-size: var(--t-h2);
           line-height: var(--display-lh); letter-spacing: var(--h2-ls); text-transform: var(--display-case); color: var(--white); }
.t-title { font-family: var(--f-title); font-weight: var(--title-w); font-size: var(--t-title);
           line-height: var(--title-lh); letter-spacing: var(--title-ls); text-transform: var(--title-case); color: var(--white); }
.t-num   { font-family: var(--f-num); font-weight: var(--num-w); font-size: var(--t-num);
           line-height: .9; letter-spacing: var(--num-ls); }
.t-body  { font-size: var(--t-body); font-weight: var(--body-w); line-height: var(--body-lh); letter-spacing: var(--body-ls); color: var(--t1); max-width: var(--measure); }   /* 34em: no body line past about 75 characters */
.t-eyebrow { font-family: var(--f-eyebrow); font-size: var(--t-eyebrow); font-weight: var(--eyebrow-w); line-height: 1.4; letter-spacing: var(--eyebrow-ls);
             text-transform: uppercase; color: var(--cyan); }
/* the reference writes its eyebrows as //ABOUT. The slashes are drawn here,
   so the string itself stays the copy. */
.t-eyebrow::before { content: "//"; }
.lines > span { display: block; }
h1, h2, h3, .t-hero, .t-h2, .t-title { text-wrap: balance; }
p, dd { text-wrap: pretty; }

.pad { padding-inline: var(--pad); }
/* every section is its own positioned layer, painted in source order, so a
   decorative light that runs past the bottom of one section is always
   covered by the next rather than laid over its text */
main > section { position: relative; }

/* ============================================================= buttons == */
/* 59 tall at 1440 and 48 at 414, padding 15 30 15 70, radius 6, with a 49
   square at radius 4 inset 5 on the left holding the arrow. */

.btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  min-height: clamp(48px, 43.56px + 1.0721vw, 59px);
  padding: 0 30px 0 clamp(62px, 58.77px + .7797vw, 70px);
  border-radius: var(--r-btn);
  font-size: var(--t-btn); font-weight: 700; line-height: 1.2; letter-spacing: -.2px; text-transform: uppercase;
  background: var(--white); color: var(--ground);
  transition: background var(--dur) var(--ease-load), box-shadow var(--dur) var(--ease-load), color var(--dur) var(--ease-load);
}
.btn__sq {
  position: absolute; left: 5px; top: 5px; bottom: 5px; aspect-ratio: 1 / 1;
  display: grid; place-items: center; border-radius: var(--r-sq);
  background: var(--teal); color: var(--white);
  transition: transform var(--dur) var(--ease-load);
}
.btn__sq svg { width: 20px; height: 20px; }
.btn:hover { box-shadow: 0 0 0 4px color-mix(in srgb, var(--cyan) 30%, transparent); }   /* the accent at 30%: visible on the light ground and on a photo */
.btn:hover .btn__sq { transform: translateX(3px); }

/* ============================================================== header == */

.head {
  position: fixed; inset: 0 0 auto 0; z-index: 40; height: var(--head);
  padding: 0 var(--pad); display: flex; align-items: center; justify-content: space-between; gap: 20px;
  background: linear-gradient(var(--ground) 10%, transparent 100%);
}
.brand { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; color: var(--white); transition: color var(--dur-fast) ease-out; }
.brand:hover { color: var(--cyan); }
.brand__mark { flex: none; }   /* the 04 Bond mark, square; sized per context below */
.brand__mark svg { width: 100%; height: 100%; display: block; }
.brand__name { font-family: var(--f-footmark); font-size: var(--footmark-size); font-weight: var(--footmark-w); line-height: 1; letter-spacing: var(--footmark-ls);
               text-transform: var(--footmark-case); padding-top: 4px; }   /* as the footer sets it; the nav overrides below */
/* The nav wordmark, on v21-tradecraft's treatment: no mark, wide-tracked caps in
   the label face (IBM Plex Mono since 2026-09-27), 400, 1.0.
   The footer keeps the mark and the name above. */
.head .brand__name, .hero__bar .brand__name {
  font-family: var(--f-wordmark); font-size: var(--wm); font-weight: 400; line-height: 1;
  letter-spacing: calc(var(--wm-k) * 1em); text-indent: calc(var(--wm-k) * 1em); text-transform: uppercase; padding-top: 0; }
/* v21's clamp(13px, 1.15vw, 17px), one step up: v30's nav is taller and its
   links are 600 caps, and at 13 to 16.5px the 400 name read lighter than them.
   The indent balances the tracking's trailing gap so the box, and the focus
   ring around it, sit evenly on the letters; on its own it also pushes the G
   .30em right of the content edge (measured 3.9 to 5px). The link is pulled
   back by the same .30em, so the ink starts on the edge and the ring stays even. */
/* 2026-09-27: the name up 25% from clamp(14px, 1.25vw, 18px), then 8% more with the
   tracking opened from .30em to .36em (and --mk-gap .62 to .72 to match), and the Bond mark
   ahead of it. The mark now starts the link, so the link sits on the content
   edge with no pull-back; the .30em indent now falls between mark and G, and
   the flex gap is what is left of --mk-gap once the indent is counted.
   --mk: the mark is a solid square and reads larger than its box, so it is set
   under the cap height, not to it. */
.head .brand, .hero__bar .brand { --wm: var(--wm-size, clamp(19px, 1.6875vw, 24.25px)); --mk: .64; --mk-gap: .72;
  gap: calc(var(--wm) * (var(--mk-gap) - var(--wm-k))); }
.head .brand__mark, .hero__bar .brand__mark { width: calc(var(--wm) * var(--mk)); height: calc(var(--wm) * var(--mk));
  translate: 0 calc(var(--wm) * .027); }   /* centring left it .6px above the baseline; this sets it on the baseline, top under the cap line */
.head__right { display: flex; align-items: center; gap: 46px; }
/* the reference's CONTACT: a 1px white outline, 150x40, radius 6 */
.head__cta {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 34px;
  border-radius: var(--r-btn); box-shadow: inset 0 0 0 1px var(--white); color: var(--white);
  font-size: var(--t-small); font-weight: 800; letter-spacing: .08em; text-transform: uppercase;   /* tracked as the nav links beside it */
  transition: background var(--dur) var(--ease-load), color var(--dur) var(--ease-load);
}
.head__cta:hover { background: var(--white); color: var(--ground); }
.burger { position: relative; width: 44px; height: 44px; display: grid; place-items: center; color: var(--white); }
.burger__lines { position: relative; width: 40px; height: 22px; }
.burger__lines span { position: absolute; right: 0; height: 2px; background: currentColor; border-radius: 1px;
                      transition: transform .45s var(--ease-in), width .45s var(--ease-in), opacity var(--dur-fast) ease-out, top .45s var(--ease-in); }   /* the menu's own motion family, with the panel */
.burger__lines span:nth-child(1) { top: 0; width: 40px; }
.burger__lines span:nth-child(2) { top: 10px; width: 30px; }
.burger__lines span:nth-child(3) { top: 20px; width: 40px; }
.menu-open .burger { color: var(--cyan); }
.menu-open .burger__lines span:nth-child(1) { top: 10px; width: 30px; transform: rotate(45deg); }
.menu-open .burger__lines span:nth-child(2) { opacity: 0; }
.menu-open .burger__lines span:nth-child(3) { top: 10px; width: 30px; transform: rotate(-45deg); }
@media (max-width: 809px) { .head__cta { display: none; } }

/* ================================================================ menu == */
/* A 504px panel from the right on the --panel ground. :target opens it with no script;
   the script takes over and adds focus handling and Escape. */

.menu { position: fixed; inset: 0; z-index: 30; pointer-events: none; }
.menu__scrim { position: absolute; inset: 0; background: var(--scrim); opacity: 0;
               transition: opacity .5s var(--ease-in); }
.menu__panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(504px, 100%);
  background: var(--panel); padding: 110px var(--pad) 40px;
  display: flex; flex-direction: column; align-items: flex-end;
  transform: translateX(100%); visibility: hidden;
  transition: transform .6s var(--ease-in), visibility 0s linear .6s;
}
.menu__panel .t-eyebrow { margin-bottom: 18px; font-size: 24px; }
.menu__links a { display: block; text-align: right; font-family: var(--f-title); font-weight: var(--title-w); font-size: var(--t-title);
                 line-height: var(--title-lh); letter-spacing: var(--title-ls); text-transform: var(--title-case); color: var(--white);
                 padding-block: 9px; transition: color var(--dur-fast) ease-out; }
.menu__links a:hover, .menu__links a[aria-current="page"] { color: var(--cyan); }
.menu:target, .menu-open .menu { pointer-events: auto; }
.menu:target .menu__scrim, .menu-open .menu__scrim { opacity: 1; }
.menu:target .menu__panel, .menu-open .menu__panel { transform: none; visibility: visible;
                                                      transition: transform .6s var(--ease-in), visibility 0s; }
.menu__close { position: absolute; top: 12px; right: 12px; width: 44px; height: 44px; display: grid; place-items: center;
               color: var(--cyan); }
.menu__close svg { width: 26px; height: 26px; }
.menu__close:hover { color: var(--white); }
.burger { transition: color var(--dur-fast) ease-out; }
.burger:hover { color: var(--cyan); }
.js .menu__close { display: none; }   /* with the script the burger itself becomes the X */

/* ============================================================== streaks == */
/* soft light behind the page heads; on the light ground a muted teal bloom */
.streaks { position: absolute; inset: 0 0 auto 0; height: 520px; overflow: hidden; pointer-events: none; }
.streaks::before {
  content: ""; position: absolute; left: 12%; top: -180px; width: 70%; height: 520px;
  background: repeating-linear-gradient(60deg, transparent 0 90px, var(--bloom) 125px 140px, transparent 175px 260px);
  filter: blur(26px);
  -webkit-mask-image: radial-gradient(ellipse 50% 50% at 50% 40%, #000, transparent 75%);
          mask-image: radial-gradient(ellipse 50% 50% at 50% 40%, #000, transparent 75%);
}

/* ================================================================ hero == */
/* v21-tradecraft's hero, on v30's type: one photograph inset on all sides at
   the card radius, the nav laid over it, and the whole copy stack bottom left
   in white. The bar and the copy are both in flow in a column, so the copy
   can never ride up under the nav: the card grows to whatever the copy needs
   and 80vh is only the floor. */
.hero { background: transparent; padding: 16px; }
.hero__card { position: relative; overflow: hidden; border-radius: var(--r-card);
              display: flex; flex-direction: column; min-height: 80vh; background: var(--ground); }
/* <picture> must not become a positioned box of its own, or the img inside
   loses the card as its containing block */
.hero picture { display: contents; }
.hero__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%; }
/* v21's two-direction grade, copied as it is: a top pass over the first 42%
   for the nav, a bottom ramp under the copy stack, and a flat .40 over all */
.hero__grade { position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgb(var(--grade) / .52) 0%, rgb(var(--grade) / .30) 24%, rgb(var(--grade) / 0) 42%),
    linear-gradient(to top, rgb(var(--grade) / .80) 0%, rgb(var(--grade) / .34) 46%, rgb(var(--grade) / .10) 70%),
    rgb(var(--grade) / .40); }
.hero__bar { position: relative; z-index: 3; flex: none; display: flex; align-items: center; justify-content: space-between;
             gap: 24px; padding: 14px 30px 0; }
.hero__nav { position: absolute; left: 50%; top: 14px; transform: translateX(-50%); display: flex; gap: 40px; }
.hero__nav a, .head__nav a { display: inline-flex; align-items: center; min-height: 44px; font-size: var(--t-small); font-weight: 700;
               letter-spacing: .08em; text-transform: uppercase; color: var(--white);
               background-image: linear-gradient(currentColor, currentColor); background-size: 0 2px;
               background-position: 0 calc(100% - 8px); background-repeat: no-repeat;
               transition: background-size var(--dur) var(--ease-in), color var(--dur-fast) ease-out; }
.hero__nav a:hover, .head__nav a:hover { background-size: 100% 2px; color: var(--cyan); }
/* The inner pages' header has no photograph behind it, so its links sit in the
   ink token on the ground; the current page keeps the underline at rest. */
.head__nav { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: flex; gap: 40px; }
.head__nav a[aria-current="page"] { background-size: 100% 2px; }
.hero__bar-right { display: flex; align-items: center; gap: 24px; }
.hero__copy { position: relative; z-index: 2; margin-top: auto; padding: 36px 30px 56px; }
.hero__inner { max-width: 900px; }
.hero__eyebrow { display: flex; align-items: center; gap: 20px; margin-bottom: 28px; }
.hero__eyebrow::after { content: ""; height: 1px; width: 56px; background: currentColor; opacity: .6; flex: none; }
/* the words go white: cyan measured 3.9:1 over the brightest roof at 390.
   The slashes and the rule keep the accent. */
.hero__eyebrow { color: var(--white); font-size: var(--hero-eyebrow-size); letter-spacing: var(--hero-eyebrow-ls); }
.hero__eyebrow::before, .hero__eyebrow::after { color: var(--cyan); }
.hero h1 { margin-bottom: 28px; }
.hero__sub { margin-bottom: 28px; font-size: var(--t-state); font-weight: 700; line-height: 1.2; letter-spacing: -.01em; color: var(--white); }
.hero__body { max-width: 620px; margin-bottom: 32px; color: var(--white); }
.hero__btns { display: flex; flex-wrap: wrap; align-items: center; gap: 28px; }
.hero__link { display: inline-flex; align-items: center; min-height: 44px; font-size: var(--t-btn); font-weight: 700;
              text-transform: uppercase; letter-spacing: -.2px; color: var(--white);
              text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 8px;
              transition: text-decoration-thickness var(--dur-fast) ease-out, color var(--dur-fast) ease-out; }
.hero__link:hover { color: var(--cyan); text-decoration-thickness: 2px; }
/* below 1080 the centred links would collide with the brand and the button:
   the burger takes over, in the hero and in the fixed header alike */
@media (max-width: 1079px) { .hero__nav, .head__nav { display: none; } }
@media (max-width: 809px) {
  .hero__card { min-height: 0; }
  .hero__bar { padding: 8px 20px 0; }   /* the copy's 20, so the wordmark sits on the copy's edge */
  .hero__copy { padding: 120px 20px 32px; }
  .hero__btns .btn { width: 100%; }
}

/* ============================================================ sections == */

.sec { position: relative; padding: var(--sec) var(--pad) 0; }
.sec__head { text-align: center; margin-bottom: var(--sp-head); }
.sec__head .t-eyebrow, .steps__head .t-eyebrow, .faq__head .t-eyebrow { margin-bottom: 4px; }

/* each photograph's focal point, kept in frame wherever its box crops it */
.fp--plumber    { object-position: 68% 40%; }   /* the pump dial and the hands on it */
.fp--builder    { object-position: 58% 40%; }   /* the saw and both hands            */
.fp--hvac       { object-position: 42% 50%; }   /* the technician and the unit       */
.fp--landscaper { object-position: 70% 55%; }   /* the shears closing                */

/* ================================================================ work == */

.phead { position: relative; padding: calc(var(--head) + clamp(80px, 58.4px + 5.26vw, 160px)) var(--pad) 0; }
.phead > :not(.streaks) { position: relative; }
.phead__eyebrow { display: flex; align-items: center; gap: 12px; margin-bottom: 8px;
                  font-family: var(--f-eyebrow); font-size: var(--phead-eyebrow-size); font-weight: var(--eyebrow-w); line-height: 1.4; letter-spacing: var(--eyebrow-ls);
                  text-transform: uppercase; color: var(--t2); }
.phead__eyebrow::before { content: "//"; }
.phead__lead { margin-top: var(--sp-copy); }
/* the first content under a page head sits one head-to-content space below it,
   as it does under a section head, not a whole section away */
.phead + .sec { padding-top: var(--sp-head); }
.phead + .bio { margin-top: var(--sp-head); }

.wsec { padding: var(--sp-head) var(--pad) 0; }   /* the portfolio page's grid section; on the home page .sec carries the same side padding */
.wgrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); align-items: start; }
.wcard { display: flex; flex-direction: column; gap: var(--gap); border-radius: var(--r-card); }
.wcard__media { position: relative; aspect-ratio: 690 / 597; border-radius: var(--r-card); overflow: hidden; box-shadow: var(--shadow-2); }
.wcard__info { padding: var(--pad-card); border-radius: var(--r-card); background: var(--glass); box-shadow: var(--shadow-1);
               transition: box-shadow var(--dur) var(--ease-load); }
.wcard:hover .wcard__info, .wcard:focus-visible .wcard__info { box-shadow: var(--shadow-2); }
/* v21's square logo plates. A light haze at rest; hover and keyboard focus lift
   it over .45s. Reduced motion shows the plate clear, with no transition. */
.wgrid .wcard__media { aspect-ratio: 1 / 1; }
.wcard__media--logo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wcard__media--logo::after { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: color-mix(in srgb, var(--ground) 22%, transparent); transition: opacity var(--dur) var(--ease-load); }
.wcard:hover .wcard__media--logo::after, .wcard:focus-visible .wcard__media--logo::after { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .wcard__media--logo::after { opacity: 0; } }
.wcard__info .t-title { margin-bottom: var(--sp-title); }
.wcard__info .t-body { color: var(--white); }
.wcard--empty .wcard__media { display: grid; place-items: center; background: transparent;
                              border: 1px dashed var(--line); box-shadow: none; }
.wcard--empty .t-eyebrow { color: var(--t1); }
.wcard--empty .t-eyebrow::before { content: none; }
@media (max-width: 809px) {
  .wgrid { grid-template-columns: minmax(0, 1fr); }
  .wcard__media { aspect-ratio: 374 / 366; }
}

/* ============================================================== steps == */
/* Three cards stacked, 01 over 02 over 03, full content width, each sized to
   its own content and revealed by the shared [data-in] rise and fade. */

.steps { position: relative; padding: var(--sec) 0 0; }
.steps__head { padding: 0 var(--pad); margin-bottom: var(--sp-head); }
.steps__head h2 { max-width: 1100px; }
.steps__track { display: grid; gap: var(--gap); padding: 0 var(--pad); }
.step { position: relative; padding: var(--pad-card); border-radius: var(--r-card); background: var(--glass); box-shadow: var(--shadow-1);
        overflow: hidden; display: flex; flex-direction: column; }
.step::after {   /* the fine dot field the reference lays under its step art */
  content: ""; position: absolute; right: 0; top: 0; width: 45%; height: 100%; pointer-events: none;
  background-image: radial-gradient(var(--dots) 1px, transparent 1.2px); background-size: 12px 12px;
  -webkit-mask-image: linear-gradient(to left, #000, transparent);
          mask-image: linear-gradient(to left, #000, transparent);
}
.step > * { position: relative; }
.step__n { color: var(--t1); }
.step__n::after { content: "."; color: var(--cyan); margin-left: var(--num-dot-gap, 4px); }
.step h3, .step--photo h2 { margin: 52px 0 var(--sp-title); }
.step .t-body { font-size: calc(var(--t-body) + 2px); line-height: calc(var(--body-lh) + .1); }   /* 26px on 39 at 1440, on the shared 34em measure */
/* the services: the same card with its photograph beside the copy. The frame is
   the photographs' own 4:3, so nothing is cropped; the dot field gives way to it */
.step--photo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--sp-head); align-items: start; }
.step--photo::after { content: none; }
.step__copy { display: flex; flex-direction: column; }
.step__media { border-radius: var(--r-card); overflow: hidden; aspect-ratio: 4 / 3; }
.step__media img { width: 100%; height: 100%; object-fit: cover; }
.phead + .steps { padding-top: var(--sp-head); }
@media (max-width: 1023px) {
  .step h3, .step--photo h2 { margin-top: 40px; }
  .step--photo { grid-template-columns: minmax(0, 1fr); gap: var(--sp-copy); }
}

/* ================================================================= faq == */

.faq { position: relative; display: grid; grid-template-columns: minmax(auto, 1fr) minmax(0, 880px); gap: 40px; padding: var(--sec) var(--pad) 0; }
.faq::before {   /* the teal light the reference holds under its left column */
  content: ""; position: absolute; left: 0; top: 10%; width: 50%; height: 80%; pointer-events: none;
  background: radial-gradient(ellipse 60% 55% at 30% 50%, var(--glow), transparent 70%);
}
.faq > * { position: relative; }
.faq__head { align-self: start; position: sticky; top: calc(var(--head) + 40px); }
.faq__head h2 { max-width: 560px; }
.faq--page { padding-top: calc(var(--head) + clamp(80px, 58.4px + 5.26vw, 160px)); }
.faq--page .phead__lead { margin-top: var(--sp-copy); }
.faq__list { counter-reset: q; --acc-gap: clamp(20px, 11.8px + 1.4vw, 32px); }   /* number to question: 20 at 390, 32 at 1440 */
.acc { counter-increment: q; }
.acc summary { display: grid; grid-template-columns: calc(var(--t-num) * 1.6) minmax(0, 1fr) 24px; gap: var(--acc-gap); align-items: baseline;
               padding: 20px 0; cursor: pointer; list-style: none; min-height: 44px; }
.acc summary::-webkit-details-marker { display: none; }
.acc summary::before { content: counter(q, decimal-leading-zero) "."; font-family: var(--f-num); font-weight: var(--num-w); font-size: var(--t-num);
                       line-height: .9; letter-spacing: var(--num-ls); color: var(--t3); transition: color var(--dur-fast) ease-out; }
.acc__q { font-size: calc(var(--t-q) + 2px); font-weight: 700; line-height: 1.4; color: var(--t3); transition: color var(--dur-fast) ease-out; }
.acc summary:hover .acc__q, .acc[open] .acc__q, .acc summary:hover::before, .acc[open] summary::before { color: var(--white); }
.acc__icon { position: relative; width: 24px; height: 24px; align-self: start; margin-top: 8px; color: var(--t1); }
.acc__icon::before, .acc__icon::after { content: ""; position: absolute; left: 4px; right: 4px; top: 11px; height: 2px;
                                        background: currentColor; border-radius: 1px; transition: transform var(--dur) var(--ease-load); }
.acc__icon::after { transform: rotate(90deg); }
.acc[open] .acc__icon::after { transform: rotate(0); }
/* the answer starts where the question does: the number column plus the gap */
.acc__a { padding: 0 24px 20px calc(var(--t-num) * 1.6 + var(--acc-gap)); max-width: var(--acc-measure, none); }   /* measured by the list column, not the 34em body cap */
.acc__a.t-body { font-size: clamp(18px, 15.58px + .585vw, 24px); }
@media (max-width: 1023px) {
  .faq { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .faq__head { position: static; }
  .acc__a { padding-left: 0; padding-right: 0; max-width: var(--acc-measure-narrow, 32em); }   /* one column: held near 72 characters */
}

/* ================================================================= cta == */
/* Was a drawn light burst on an empty dark panel. On the light site it is a
   photograph instead, inset and rounded like the hero and graded with the
   same two-direction ramp, so the white type sits on a measured ground. */
.cta { position: relative; margin: var(--sec) 16px 0; min-height: clamp(560px, 440px + 25vw, 760px); border-radius: var(--r-card);
       display: grid; grid-template-columns: minmax(0, 1fr); place-items: center; text-align: center; padding: var(--sec) var(--pad); overflow: hidden; background: var(--ground); }
.cta__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 64% 45%; }   /* the belt and hammer: kept in frame at 390, where only ~40% of the width shows */
.cta__grade { position: absolute; inset: 0;
  background:
    radial-gradient(ellipse 70% 60% at 50% 50%, rgb(var(--grade) / .35), rgb(var(--grade) / 0) 75%),
    linear-gradient(to top, rgb(var(--grade) / .70) 0%, rgb(var(--grade) / .30) 60%, rgb(var(--grade) / .45) 100%),
    rgb(var(--grade) / .35); }
.cta__in { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; }
.cta h2, .cs-cta h2 { max-width: 1320px; font-size: min(var(--t-hero), calc((100vw - 64px) / var(--cta-fit))); }
/* "Your Website." is held on one line, and at the hero's 68px floor that line
   is 345px, wider than a 390 card. The cap only bites below about 420. */
.cta__lines { margin: 16px 0 var(--sp-copy); font-size: var(--t-body); font-weight: 600; line-height: 1.4; color: var(--white); }
.cta .btn { min-width: 280px; }
@media (max-width: 480px) {
  .cta { padding: var(--sec) 16px; }
  .cta .btn, .cs-cta .btn { width: 100%; min-width: 0; padding-right: 16px; white-space: nowrap; font-size: 17px; }
}

/* =============================================================== about == */

.bio { display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: 60px; align-items: start;
       margin: var(--sec) var(--pad) 0; padding: var(--pad-card); border-radius: var(--r-card);
       background: var(--glass); box-shadow: var(--shadow-1); }
.bio figure { border-radius: var(--r-card); overflow: hidden; }
.bio figure img { width: 100%; aspect-ratio: 360 / 514; object-fit: cover; filter: saturate(0); }
.bio__text p + p { margin-top: var(--sp-copy); }
.bio__text .bio__first { font-size: var(--t-q); font-weight: 700; line-height: 1.4; color: var(--white); }
@media (max-width: 1023px) { .bio { grid-template-columns: minmax(0, 1fr); gap: var(--sp-copy); } }

/* ============================================================= contact == */

.reach { display: grid; justify-items: center; gap: var(--sp-head); padding: var(--sp-head) var(--pad) 0; }
/* email and phone: two centred columns, the label over its value; one column below 768 */
.reach__list { display: grid; grid-template-columns: auto auto; column-gap: clamp(48px, 16px + 8.3vw, 136px); row-gap: var(--sp-head); text-align: center; }
.reach__item .t-eyebrow { margin-bottom: 8px; font-size: calc(var(--t-eyebrow) + 3px); }
.reach .formcard { width: 100%; max-width: 690px; }
.reach__value { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--f-title); font-size: calc(var(--t-num) + 3px);
                font-weight: var(--title-w); line-height: .9; letter-spacing: var(--reach-ls); text-transform: var(--title-case); color: var(--white); white-space: nowrap;
                transition: color var(--dur-fast) ease-out; }
.reach__value:hover { color: var(--cyan); }
.formcard { padding: var(--pad-card); border-radius: var(--r-card); background: var(--glass); box-shadow: var(--shadow-1); }
.formcard > .t-eyebrow { margin-bottom: var(--sp-copy); }
.fauxform { display: grid; gap: var(--gap); margin-bottom: var(--pad-card); }
.fauxform__pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--gap); }
.field { display: grid; gap: 8px; }
.field__label { font-size: var(--t-label); font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--t1); }
.field__box { display: block; height: 52px; border-radius: var(--r-btn); background: var(--field);
              box-shadow: inset 0 0 0 1px var(--line-strong); }   /* a field boundary must read: 3:1 */
.field__box--tall { height: 132px; }
@media (max-width: 767px) { .reach__list { grid-template-columns: minmax(0, auto); } }
@media (max-width: 480px) { .fauxform__pair { grid-template-columns: minmax(0, 1fr); } }

/* ============================================================== footer == */
/* Ported from v29-industrial (brand, a Contact column, a Pages column, the
   bottom bar) and re-mapped to v30's tokens. v29's Space Mono labels become
   v30's small-caps label (700, +.14em, --t2); its white-at-.85 links
   become --t1 on the --t-eyebrow step; its 60 / 58 / 40 padding becomes
   --sp-head and --pad; its 34px link rows become 44 for touch. v29 lays it on
   a gradient; here it is the dark close to the light page. */
.foot { margin-top: var(--sec); padding: calc(var(--sp-head) * 1.125) var(--pad) calc(var(--pad) * 1.5);
        background: var(--ground); border-top: 1px solid var(--line); }   /* dark on purpose: the markup carries .on-dark */
.foot__top { display: grid; grid-template-columns: auto auto auto; justify-content: space-between; gap: var(--sp-head) 40px; align-items: start;
             max-width: var(--foot-w); margin-inline: auto; }
/* the group is capped and centred; the tagline shares the cap so it starts under the brand */
.foot { --foot-w: 1100px; }
/* The footer lockup since the Plex Mono name (2026-09-27): the mark scales with the name at
   .68 of its size, 17.7px at 26px and 13.6px at 20px, just under Plex Mono's .71em cap height,
   because the solid square reads larger than its box. Set on the baseline: centring rode it
   about 3px high against the name's 4px top padding. The .42em gap is a little wider than
   the name's tracking, so the two read as one lockup. */
.foot .brand { align-items: baseline; gap: calc(var(--footmark-size) * .42); }
.foot .brand__mark { width: calc(var(--footmark-size) * .68); height: calc(var(--footmark-size) * .68); }
.t-mono { font-family: var(--f-text); font-size: var(--t-label); font-weight: 700; line-height: 1.4; letter-spacing: .14em;
          text-transform: uppercase; color: var(--t2); }
.foot .t-mono { margin-bottom: 8px; font-size: 15px; }
.foot__list { display: grid; }
.foot__list a { display: inline-flex; align-items: center; min-height: 44px; font-size: clamp(18px, 15.6px + .6vw, 24px); font-weight: 500;
                letter-spacing: .01em; color: var(--t1); transition: color var(--dur-fast) ease-out; }
.foot__list a:hover { color: var(--white); }
.foot__list a[aria-current="page"] { color: var(--white); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 6px; }
.foot__bottom { margin-top: calc(var(--sp-head) * 1.5); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
                max-width: var(--foot-w); margin-inline: auto; }
.foot__bottom .t-mono { margin: 0; font-size: 15px; }
@media (max-width: 899px) {
  .foot__top { grid-template-columns: minmax(0, 1fr); gap: var(--sp-head); }
  .foot__bottom { margin-top: calc(var(--sp-head) * .75); }
}

/* ============================================================== motion == */
/* site.js adds .motion to <html> only when motion is allowed, and only that
   class enables a hidden state. No script, or reduced motion: everything is
   visible and still. */

@media (prefers-reduced-motion: no-preference) {
  .motion .load { opacity: 0; transform: scale(.9); transform-origin: 0 50%;
                  transition: opacity .7s var(--ease-load) .4s, transform .7s var(--ease-load) .4s; }
  .motion.loaded .load { opacity: 1; transform: none; }
  .motion [data-in] { opacity: 0; transform: translateY(140px);
                      transition: opacity 1s var(--ease-in), transform 1s var(--ease-in); }
  .motion [data-in].is-in { opacity: 1; transform: none; }
}

/* =================================================================== 404 == */
.nf { min-height: 70svh; }
.nf__link { color: var(--cyan); text-decoration: underline; text-underline-offset: 4px; transition: color var(--dur-fast) ease-out;
            padding: 11px 7px; margin: 0 -7px; }   /* inline padding grows the hit area to 44px; the negative margin holds the words in place */
.nf__link:hover { color: var(--white); }
.nf__btn { margin-top: var(--sp-head); }
