/* Dunime — "Sightline" v1.0
   Ink #17130F · Paper #FDFCFA · Signal #CB6440 / #E98664
   Type: Instrument Sans (headings + wordmark), Bricolage Grotesque (body, UI, nav),
   IBM Plex Mono (labels, counters, data). The split is deliberate; see PROJECT.md 6.
   Component styling is authored inline in the markup; this file holds only what
   inline styles cannot express: resets, keyframes, pseudo-states, media queries. */

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;overflow-x:clip}
body{margin:0;overflow-x:clip;background:#FDFCFA;color:#17130F;font-family:'Bricolage Grotesque',Helvetica,Arial,sans-serif;font-weight:400;line-height:1.55;-webkit-font-smoothing:antialiased}
a{color:#17130F;text-decoration-color:#CB6440;text-underline-offset:.25em}
a:hover{color:#B45330}
/* Signal as text needs 4.5:1. #B45330 clears it on paper; on ink the lighter
   Tint is the readable one, so dark sections keep that. */
[style*="background:#17130F"] a:hover{color:#E98664}
::selection{background:#E98664;color:#17130F}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
input{font:inherit;color:inherit}
@keyframes dnm-cue{0%,100%{transform:translateY(0);opacity:.3}50%{transform:translateY(8px);opacity:1}}
@keyframes dnm-irisout{from{clip-path:circle(0% at 50% 46%)}to{clip-path:circle(150% at 50% 46%)}}
@keyframes dnm-fadeup{from{opacity:0;transform:translate3d(0,24px,-60px)}to{opacity:1;transform:none}}
/* Native cross-document transitions. 15 static pages is exactly the case these
   were designed for; browsers without support just navigate as before. */
@view-transition{navigation:auto}

/* Scoped, not blanket. The old rule killed every transition including nav
   contrast and hover states, which are not motion. Scroll scenes and the
   entrance animations are what reduced-motion users actually need stopped. */
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;animation-iteration-count:1!important}
  [data-scene] *,[data-reveal],[data-intro],[data-intro-mark]{transition-duration:.01ms!important}
  @view-transition{navigation:none}
}
@media (max-width:860px){[data-article-grid]>div{grid-template-columns:1fr!important}[data-article-grid] aside{position:static!important;top:auto!important}}

/* Anchor targets sit under the fixed nav without this. One rule covers the 43
   section ids across the legal pages plus every in-page anchor elsewhere, so no
   markup needs a scroll-margin of its own. */
main [id] { scroll-margin-top: 104px; }

/* The About facts strip has a fixed set of four. It draws its hairlines by showing a
   grey container background through 1px gaps, so any empty auto-fill track renders as
   a grey ghost cell. Explicit counts at each step instead. */
@media (max-width:900px){ [data-facts]{grid-template-columns:repeat(2,minmax(0,1fr))!important} }
@media (max-width:560px){ [data-facts]{grid-template-columns:minmax(0,1fr)!important} }

/* WCAG 2.4.1: let keyboard users past the repeated nav. Visible only on focus. */
.skip{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden}
.skip:focus{left:8px;top:8px;width:auto;height:auto;z-index:200;padding:12px 18px;background:#17130F;color:#FDFCFA;font-family:'IBM Plex Mono',ui-monospace,Menlo,monospace;font-size:12px;letter-spacing:.12em;text-transform:uppercase;text-decoration:none}
main:focus{outline:none}

[hidden] { display: none !important; }
:focus-visible { outline: 2px solid #CB6440; outline-offset: 3px; }

/* Navigation is UI, not data. The brand kit reserves IBM Plex Mono for descriptors,
   labels and data — putting the menu and footer links in tracked uppercase mono made
   them read stiff and out of flow. They inherit that mono from their container, so
   correcting it here fixes all 15 pages without touching a single inline style.
   Mono stays where it belongs: eyebrows, counters, outputs, meta. */
[data-nav-bar] a[data-navlink],
footer a {
  font-family: 'Bricolage Grotesque', Helvetica, Arial, sans-serif;
  text-transform: none;
  font-weight: 500;
  letter-spacing: .004em;
  font-size: 13.5px;
}
footer a { font-size: 14.5px; font-weight: 400; letter-spacing: 0; }

/* Navigation collapse. Originally 760px, raised to 860px on 2026-08-05 after
   measuring tablets: at 768px the horizontal nav is 753px wide — 15px of slack —
   so an iPad Mini (744px) clips it, and its links compute to 33px tall on a
   touch screen against a 44px minimum. 860px covers every phone plus tablet
   portrait; tablet landscape keeps the horizontal bar. */
[data-navtoggle] { display: none; }
@media (max-width: 860px) {
  [data-navtoggle] {
    display: grid; place-items: center; gap: 5px;
    width: 44px; height: 44px; margin-left: auto; padding: 0;
  }
  [data-navtoggle] span { display: block; width: 20px; height: 1.5px; background: currentColor; transition: transform .3s ease, opacity .2s ease; }
  [data-nav-bar][data-open] [data-navtoggle] span:first-child { transform: translateY(3.25px) rotate(45deg); }
  [data-nav-bar][data-open] [data-navtoggle] span:last-child  { transform: translateY(-3.25px) rotate(-45deg); }

  [data-nav-bar] > div:last-of-type {
    /* absolute, not fixed: the nav is already position:fixed, so it is the
       containing block and top:100% means "just below the nav". Under
       position:fixed, 100% would resolve against the viewport instead. */
    position: absolute; left: 0; right: 0; top: 100%;
    visibility: hidden;
    /* !important because the panel carries inline display:flex/align-items:center/gap
       from the desktop nav, which would otherwise win over these. */
    flex-direction: column; align-items: stretch !important; gap: 0 !important;
    padding: 4px clamp(16px, 4vw, 56px) 18px;
    background: rgba(253, 252, 250, .98);
    -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
    border-bottom: 1px solid rgba(23, 19, 15, .1);
    transform: translateY(-115%); transition: transform .32s cubic-bezier(.16, .9, .2, 1), visibility .32s;
  }
  [data-nav-bar][data-open] > div:last-of-type { transform: none; visibility: visible; }

  /* 48px targets, and ink type regardless of what chrome() set for the dark-section
     state — the panel is always paper, so white links would vanish into it. */
  [data-nav-bar] a[data-navlink] {
    display: flex; align-items: center; min-height: 48px;
    padding: 0 !important; font-size: 13px !important;
    border-bottom: 1px solid rgba(23, 19, 15, .08);
  }
  [data-nav-bar] a[data-navlink="contact"] { border: 0; margin-top: 10px; justify-content: center; min-height: 50px; background: #CB6440; }
  [data-nav-bar][data-open] a[data-navlink] { color: #17130F !important; }
}

/* Tablet landscape and any coarse-pointer device above the collapse point: the
   desktop nav links compute to 33px tall, which is not a touch target. */
@media (pointer: coarse) and (min-width: 861px) {
  [data-nav-bar] a[data-navlink] { display: flex; align-items: center; min-height: 44px; }
}

/* The services rail is a desktop interaction. Measured at 390×844 it needed 1018px
   of horizontal travel driven by 591px of vertical scroll — a 0.58 ratio, so the
   cards moved ~1.7× faster than the finger, versus ~0.7× on desktop. Rather than
   inflate the section height (more scrolling, which we just cut), the rail becomes
   a plain vertical stack on touch widths. site.js skips track() here too. */
@media (max-width: 860px) {
  [data-scene="track"] { height: auto !important; }
  [data-scene="track"] > div { position: static !important; height: auto !important; overflow: visible !important; padding-block: clamp(72px, 12vw, 120px); }
  [data-rail] {
    flex-direction: column !important;
    transform: none !important;
    padding-left: clamp(20px, 5vw, 80px) !important;
    padding-right: clamp(20px, 5vw, 80px);
    gap: 18px !important;
  }
  [data-card] { width: auto !important; }
  [data-railbar] { display: none; }
}

/* Touch ergonomics. Measured at 390px: form fields rendered 14–15px, footer links
   22px tall, the consent checkbox 13×15. Inline links inside prose are left alone
   on purpose — they cannot be 44px without breaking the line they sit in. */
@media (max-width: 860px) {
  /* Below 16px, iOS Safari zooms the viewport on focus and does not zoom back. */
  input, select, textarea { font-size: 16px !important; }
  input[type="checkbox"] { width: 20px !important; height: 20px !important; flex: none; }
  footer a.sh1 { display: flex; align-items: center; min-height: 44px; }
  [data-nav-bar] a[data-nav="home"] { min-height: 44px; align-items: center; }
  /* The globe is decorative and took 90% of the width on a page whose job is a
     form. Give the form the room; the globe stays, smaller. */
  [data-globe] { max-width: 260px; max-height: 260px; margin-inline: auto; }
}

/* services.html board.
   1. The nav is position:sticky, which at narrow widths stacks to 335px and pins
      44% of the viewport above the panel you are trying to read.
   2. The 4fr/7fr split that fixed the desktop layout has no auto-fit fallback, so
      it stayed two columns on a phone — measured 118px + 207px at 390px wide.
      Stack it. `:has()` reaches the grid container, which carries no class. */
@media (max-width:900px){
  [data-board] nav[aria-label="Services"],
  nav[aria-label="Services"]{position:static!important;top:auto!important}
  div:has(> nav[aria-label="Services"]){grid-template-columns:minmax(0,1fr)!important}
}

/* Progressive enhancement. The page must stay readable if site.js never runs.
   `js` is set on <html> in the head and removed again by the script tag's onerror,
   so a failed load falls back to plain visible content instead of a black screen.
   `intro` is set only on the home page, and only once per browser session. */
/* The overlay is dismissed by CSS, never by JS. It used to be removed in
   site.js, so a single parse error there left the entire site stuck behind a
   black screen (this happened — a broken string literal, 2026-08-05). An
   animation cannot fail that way, and `forwards` holds the end state. */
[data-intro] { opacity: 0; visibility: hidden; }
html.intro [data-intro] {
  opacity: 1; visibility: visible;
  animation: dnm-introout .55s cubic-bezier(.16, .9, .2, 1) .95s forwards;
}
@keyframes dnm-introout { to { opacity: 0; visibility: hidden; } }
html:not(.js) [data-reveal] { opacity: 1 !important; transform: none !important; }

/* generated pseudo-state rules (hover / focus) */
.x1:hover{background:#E98664;color:#17130F}
.x2:hover{border-color:#E98664;background:rgba(233,134,100,.09)}
.x3:hover{color:#B45330}
.x4:hover{border-color:rgba(203,100,64,.55);box-shadow:0 30px 60px -34px rgba(23,19,15,.35)}
.x5:hover{color:#FDFCFA;border-color:rgba(233,134,100,.6)}
.x6:hover{color:#E98664}
.x7:focus{border-color:#E98664}
.x8:focus{border-bottom-color:#E98664}
.x9:hover{border-color:#CB6440;color:#B45330}
.xa:hover{border-color:#E98664}

/* shell (nav / footer) pseudo-states */
.sh1:hover{color:#B45330}
.sh2:hover{border-color:#CB6440;background:rgba(203,100,64,.07)}
