/* lockwoodsky.com — site layer.
   Sits on top of the brand kit (fonts.css, tokens.css, reset.css). Nothing here
   invents a colour — every value is a token. Where the kit was missing a value
   (the cool band tint, the cool hairline, non-warm body text) those were added
   to the KIT on 2026-08-05 rather than invented here, so t3's tool pages and any
   future surface inherit the same answer. See brand/docs/07-amendments.md.

   COLOUR DOCTRINE (Eien, 2026-08-05). The page palette is the FULLMARK's dot
   field. The four dot rows carry the whole look; Kelly is reserved for
   interaction and for the one thing on screen that should pop. This is what
   ties the logo to the page instead of leaving it stuck on top of it.

   PAPER AND THE WARM GREYS ARE BANNED ON SCREEN. `paper #FAF8F3`, `gray-75
   #F2F0EC` and `gray-150 #E6E3DE` are warm; under a cool teal system they read
   as beige, which was the single biggest cause of the site looking dated. Bands
   use `surface-tint`, rules use `surface-hair`. The one place paper is still
   right is the Etsy banner, because Etsy's own chrome is warm and we do not
   control it — see amendments §A.

   THE DOT FIELD ITSELF IS LOGO-ONLY (BRAND-SYSTEM rule 6). We take the field's
   COLOURS, never its dots. No dot patterns as background, decoration or divider. */

:root {
  --deep:   var(--ls-color-field-row4);
  --mid:    var(--ls-color-field-row3);
  --bright: var(--ls-color-field-row2);
  --pale:   var(--ls-color-field-row1);
  --tint:   var(--ls-color-surface-tint);
  --tint-2: var(--ls-color-surface-tintDeep);
  --hair:   var(--ls-color-surface-hair);
  --body:   var(--ls-color-text-body);
  --muted:  var(--ls-color-text-muted);
  --kelly:  var(--ls-color-kelly);
  --ink:    var(--ls-color-ink);

  --wrap: 1180px;
  --ease: cubic-bezier(.22,.61,.36,1);
}

/* ------------------------------------------------------------------ base */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--ls-color-white);
  color: var(--body);
  font-family: var(--ls-font-body);
  -webkit-font-smoothing: antialiased;
}
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 28px; }

h1, h2, h3, h4 {
  font-family: var(--ls-font-display);
  font-variation-settings: var(--ls-fontVariation-display);
  font-weight: 800; color: var(--deep);
  letter-spacing: -0.02em; line-height: 1.08;   /* sentence case — BRAND §4 */
}
h1 { font-size: clamp(34px, 4.4vw, 54px); }
h2 { font-size: clamp(28px, 3.4vw, 40px); }
h3 { font-size: 19px; letter-spacing: -0.01em; }
p { line-height: 1.65; }
.lede { font-size: clamp(17px, 1.5vw, 20px); color: var(--muted); line-height: 1.6; }

a { color: var(--mid); text-decoration: none; }

/* Inline prose links get a drawn underline that grows on hover — never the
   browser's. Cards and buttons opt out entirely. */
.prose a {
  background-image: linear-gradient(var(--kelly), var(--kelly));
  background-size: 0% 2px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size .3s var(--ease), color .2s var(--ease);
}
.prose a:hover { color: var(--deep); background-size: 100% 2px; }

.eyebrow {
  font-family: var(--ls-font-mono); font-weight: 500;
  font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--mid);
}
.mono-label {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--mid);
}

/* ---------------------------------------------------------------- header */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255,255,255,.88);
  backdrop-filter: saturate(1.6) blur(10px);
  border-bottom: 1px solid var(--hair);
}
/* LOGO SIZE + ALIGNMENT (Eien, 2026-08-05). It was 26px and read as a footnote.
   The reference sets `.navlinks{align-items:baseline}` — the nav text sits on the
   WORDMARK's baseline, not on the centre of the whole mark. Because the full mark
   is wordmark + dot field stacked, its optical baseline is well below its box
   centre, so centre-aligning made the logo look both small and floating.
   The mark is now 46px and the nav is nudged onto its baseline. */
.site-head .inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px; min-height: 88px;
}
.brand { display: flex; align-items: center; }
.brand img { display: block; height: 46px; width: auto; }
.site-nav { align-items: baseline; padding-bottom: 2px; }

/* NAV IS UPPERCASE (Eien, 2026-08-05) — as the brand reference had it. Not a
   heading, so BRAND §4's sentence-case rule doesn't apply; this is UI chrome. */
.site-nav { display: flex; gap: 2px; }
.site-nav a {
  position: relative;
  font-family: var(--ls-font-mono); font-weight: 500;
  font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--deep); padding: 10px 13px; border-radius: 6px;
  transition: color .2s var(--ease), background .2s var(--ease);
}
/* the "you are here" / hover indicator is KELLY — this is the pop, and green
   reading as the active state is exactly what Kelly is reserved for. */
.site-nav a::after {
  content: ""; position: absolute; left: 13px; right: 13px; bottom: 5px;
  height: 2px; background: var(--kelly);
  transform: scaleX(0); transform-origin: left;
  transition: transform .28s var(--ease);
}
.site-nav a:hover { background: var(--tint); }
.site-nav a:hover::after, .site-nav a[aria-current="page"]::after { transform: scaleX(1); }

/* MOBILE HEADER. Five nav items plus the mark measure ~477px, so at 390px the
   logo was being pushed clean off the header and ABOUT was clipped. Rather than
   hide navigation behind a hamburger — five items is not enough to justify one,
   and a burger hides the whole product range on the device most visitors use —
   the header becomes two rows and the nav strip scrolls if it must. */
@media (max-width: 680px) {
  .site-head .inner { flex-direction: column; height: auto; gap: 0; padding-top: 12px; }
  .brand { align-self: flex-start; }
  .site-nav {
    width: 100%; margin-top: 6px;
    overflow-x: auto; scrollbar-width: none;
    justify-content: space-between;
  }
  .site-nav::-webkit-scrollbar { display: none; }
  .site-nav a { padding: 10px 8px; font-size: 11.5px; letter-spacing: .09em; }
  .site-nav a::after { left: 8px; right: 8px; }
}

/* --------------------------------------------------------------- buttons */
/* BUTTON TEXT IS UPPERCASE (Eien, 2026-08-05). */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--ls-font-mono); font-weight: 500;
  font-size: 12.5px; letter-spacing: .1em; text-transform: uppercase;
  padding: 15px 24px; border-radius: 8px; border: 1px solid transparent;
  cursor: pointer;
  transition: background .22s var(--ease), color .22s var(--ease),
              border-color .22s var(--ease), transform .22s var(--ease),
              box-shadow .22s var(--ease);
}
.btn .arw { transition: transform .28s var(--ease); }
.btn:hover .arw { transform: translateX(4px); }
/* Kelly on hover with the label flipped to INK — white on Kelly is 2.42:1 and
   fails WCAG. BRAND §3 rule 3, not optional. */
.btn-primary { background: var(--deep); color: var(--ls-color-white); }
.btn-primary:hover {
  background: var(--kelly); color: var(--ink);
  transform: translateY(-2px); box-shadow: 0 10px 26px -12px rgba(14,46,58,.55);
}
.btn-secondary { background: var(--ls-color-white); color: var(--deep); border-color: var(--hair); }
.btn-secondary:hover {
  background: var(--kelly); color: var(--ink); border-color: var(--kelly);
  transform: translateY(-2px);
}
.btn:focus-visible { outline: 3px solid var(--bright); outline-offset: 3px; }
.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 30px; }

/* -------------------------------------------------------------- sections */
.section { padding: clamp(56px, 7vw, 90px) 0; }
.band { background: var(--tint); border-block: 1px solid var(--hair); }
.section-head { max-width: 64ch; margin-bottom: 38px; }
.section-head h2 { margin: 10px 0 12px; }

/* ------------------------------------------------------------------ hero */
.hero { padding: clamp(46px, 6vw, 78px) 0 clamp(38px, 5vw, 62px); }
.hero-grid {
  display: grid; grid-template-columns: 1.05fr .95fr;
  gap: clamp(30px, 5vw, 56px); align-items: center;
}
@media (max-width: 940px) { .hero-grid { grid-template-columns: 1fr; } }
.hero h1 { margin: 14px 0 18px; }
.hero .lede { max-width: 50ch; }

/* Compact inline trust row — deliberately NOT the tall band it replaced. */
.trustrow {
  display: flex; flex-wrap: wrap; gap: 12px 28px;
  margin-top: 30px; padding-top: 22px; border-top: 1px solid var(--hair);
}
.trustrow span {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--ls-font-mono); font-weight: 500;
  font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase; color: var(--mid);
}
.trustrow .icon { width: 15px; height: 15px; }

/* --------------------------------------------------------- the live demo */
/* Demonstrates the single thing every product does: type once, the rest
   computes. Driven by the REAL category split from the Wedding Budget sheet and
   labelled as a demonstration, so it illustrates without misrepresenting
   (PORTFOLIO-LAW §5). */
.demo {
  background: var(--ls-color-white); border: 1px solid var(--hair); border-radius: 14px;
  box-shadow: 0 26px 60px -34px rgba(14,46,58,.45); overflow: hidden;
}
.demo-top {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 18px; background: var(--deep); color: var(--ls-color-white);
}
.demo-top .t {
  font-family: var(--ls-font-mono); font-weight: 500;
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
}
.demo-top .dots { display: flex; gap: 5px; }
.demo-top .dots i { width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,.26); }
.demo-body { padding: 20px 18px 22px; }
.demo-field label {
  display: block; font-family: var(--ls-font-mono); font-weight: 500;
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--mid); margin-bottom: 7px;
}
.demo-input {
  display: flex; align-items: center; gap: 2px;
  border: 2px solid var(--hair); border-radius: 9px; padding: 10px 14px;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.demo-input:focus-within { border-color: var(--bright); box-shadow: 0 0 0 4px rgba(31,168,168,.15); }
.demo-input .cur, .demo-input input {
  font-family: var(--ls-font-display); font-variation-settings: 'opsz' 32;
  font-weight: 800; font-size: 26px; color: var(--deep); letter-spacing: -0.02em;
}
.demo-input input { border: 0; outline: 0; width: 100%; background: transparent; }
.demo-rows { margin-top: 18px; border-top: 1px solid var(--hair); }
.demo-row { padding: 9px 0; border-bottom: 1px solid var(--hair); }
.demo-row .line { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.demo-row .nm { font-size: 13.5px; color: var(--body); }
.demo-row .amt {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 13.5px;
  color: var(--deep); font-variant-numeric: tabular-nums;
}
.demo-row .bar { height: 3px; border-radius: 2px; background: var(--tint-2); overflow: hidden; margin-top: 6px; }
.demo-row .bar i {
  display: block; height: 100%; background: var(--bright);
  transform-origin: left; transition: transform .55s var(--ease);
}
.demo-total {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-top: 14px; padding-top: 13px; border-top: 2px solid var(--deep);
}
.demo-total .v {
  font-family: var(--ls-font-display); font-variation-settings: 'opsz' 32;
  font-weight: 800; font-size: 24px; color: var(--deep); font-variant-numeric: tabular-nums;
}
.demo-foot {
  padding: 11px 18px; background: var(--tint); border-top: 1px solid var(--hair);
  font-family: var(--ls-font-mono); font-size: 10.5px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted); text-align: center;
}

/* ----------------------------------------------------- hero work lines */
/* Replaces the budget calculator. Hovering (or focusing) a line expands it and
   reveals what that part of the studio actually does — interactive in the sense
   Eien asked for: things move and reveal, rather than sitting still. Also fixes
   the narrowness problem, because all three lines of work are visible at once
   instead of the hero implying we only make spreadsheets. */
.worklines { display: grid; gap: 0; border-top: 1px solid var(--hair); }
.worklines--page { max-width: 900px; }
.wl {
  display: block; padding: 20px 4px 20px 0; border-bottom: 1px solid var(--hair);
  color: inherit; position: relative;
  transition: padding-left .34s var(--ease), background .34s var(--ease);
}
.wl::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--kelly); transform: scaleY(0); transform-origin: top;
  transition: transform .34s var(--ease);
}
.wl-h { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.wl-t {
  font-family: var(--ls-font-display); font-variation-settings: var(--ls-fontVariation-display);
  font-weight: 800; font-size: clamp(22px, 2.3vw, 30px); color: var(--deep);
  letter-spacing: -0.02em;
  transition: color .28s var(--ease), transform .34s var(--ease);
}
.wl-n {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--mid); white-space: nowrap;
}
/* grid-template-rows 0fr -> 1fr animates a reveal without knowing its height */
.wl-d { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .38s var(--ease); }
.wl-d-i { overflow: hidden; font-size: 15px; color: var(--muted); line-height: 1.6; }
.wl-go {
  display: block; margin-top: 10px;
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--deep);
}
.wl:hover, .wl:focus-visible { padding-left: 18px; background: var(--tint); outline: none; }
.wl:hover::before, .wl:focus-visible::before { transform: scaleY(1); }
.wl:hover .wl-t, .wl:focus-visible .wl-t { color: var(--deep); }
.wl:hover .wl-d, .wl:focus-visible .wl-d { grid-template-rows: 1fr; }
.wl:hover .wl-d-i, .wl:focus-visible .wl-d-i { padding-top: 10px; }
.wl:hover .arw { transform: translateX(5px); }

/* ----------------------------------------------------------------- cards */
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(276px, 1fr)); gap: 22px; }
/* Product grid packs tighter so the current four sit on ONE row rather than
   three-plus-an-orphan. auto-fit keeps it correct as the catalogue grows. */
.cards--tight { grid-template-columns: repeat(auto-fit, minmax(244px, 1fr)); }
.card {
  display: flex; flex-direction: column;
  background: var(--ls-color-white); border: 1px solid var(--hair); border-radius: 13px;
  padding: 22px; color: inherit;
  transition: transform .26s var(--ease), border-color .26s var(--ease), box-shadow .26s var(--ease);
}
/* NO UNDERLINE ANYWHERE INSIDE A CARD (Eien, 2026-08-05). The previous rule was
   a blanket a:hover{text-decoration:underline}, so touching a card underlined
   every line of text inside it. */
.card, .card:hover, .card * { text-decoration: none; }
a.card:hover {
  transform: translateY(-4px); border-color: var(--kelly);
  box-shadow: 0 18px 42px -26px rgba(14,46,58,.5);
}
.card h3 { margin-bottom: 8px; }
.card p { color: var(--muted); font-size: 14px; flex: 1; }
.card .price {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 13px;
  letter-spacing: .04em; color: var(--deep); margin-top: 16px;
}
.card .go {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 14px;
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--mid);
  transition: color .2s var(--ease);
}
.card .go .arw { transition: transform .28s var(--ease); }
a.card:hover .go { color: var(--deep); }
a.card:hover .go .arw { transform: translateX(5px); }

.card .shotwrap {
  margin: -22px -22px 18px; overflow: hidden;
  border-bottom: 1px solid var(--hair); background: var(--tint);
  border-radius: 12px 12px 0 0;
}
/* Padding-box ratio rather than `aspect-ratio`. The image is absolutely
   positioned, so its intrinsic 2000x2000 can never size the card even if this
   rule fails to load or the property is unsupported — the failure mode that
   produced 2000px-tall cards in a real browser on 2026-08-05. */
.card .shotwrap { position: relative; padding-top: 100%; }
.card .shotwrap img {
  position: absolute; inset: 0;
  display: block; width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s var(--ease);
}
a.card:hover .shotwrap img { transform: scale(1.04); }

.tagrow { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.tag {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 10.5px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--mid);
  border: 1px solid var(--hair); border-radius: 999px; padding: 5px 10px;
  background: var(--ls-color-white);
}

/* ------------------------------------------------------------ step/icon */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr)); gap: 22px; }
/* Icon rows carry 14px of their own padding on every side, so they need far
   less grid gap than cards do or the block turns airy. 4px/8px between boxes
   reads as ~32px/36px between text blocks.

   The -14px lives HERE, on the container, not on each row. Only the grid's
   outer edges need to be pulled back for the text to sit flush with the
   container; putting it on every row made neighbours overlap by 6px on both
   axes. Rows keep their padding and claim real layout space, so a hover
   background can only ever paint inside its own row. */
.steps--icons { gap: 4px 8px; margin: 0 -14px; }
.steps--icons .iconrow { margin: 0; }
.stepcard {
  background: var(--ls-color-white); border: 1px solid var(--hair); border-radius: 13px;
  padding: 22px; position: relative; overflow: hidden;
  transition: transform .26s var(--ease), border-color .26s var(--ease), box-shadow .26s var(--ease);
}
/* a Kelly rule wipes across the top on hover — the same "you touched this"
   language as the nav indicator and the work lines */
.stepcard::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--kelly); transform: scaleX(0); transform-origin: left;
  transition: transform .32s var(--ease);
}
.stepcard:hover {
  transform: translateY(-4px); border-color: var(--hair);
  box-shadow: 0 16px 38px -26px rgba(14,46,58,.5);
}
.stepcard:hover::after { transform: scaleX(1); }
.stepcard .n { transition: color .26s var(--ease); }
.stepcard:hover .n { color: var(--kelly); }
.stepcard .n {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: .14em; color: var(--bright);
}
.stepcard h3 { margin: 8px 0; }
.stepcard p { color: var(--muted); font-size: 14px; }

.iconrow {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 14px; border-radius: 11px;
  transition: background .26s var(--ease);
  /* No negative margin. The padding buys a generous hover target and is real
     layout space, so the painted hover background can never escape its own
     row. The old `margin:-14px` bled on all four sides: it pushed the hover
     box up over the heading above (Eien, 2026-08-05) and made neighbouring
     boxes overlap by 6px. Flush text alignment is now the grid's job — see
     .steps--icons. */
  margin: 0;
}
.iconrow:hover { background: var(--ls-color-white); }
.iconrow .icon { transition: transform .3s var(--ease), color .26s var(--ease); }
.iconrow:hover .icon { transform: translateY(-2px) scale(1.08); color: var(--kelly); }
.iconrow .icon { width: 22px; height: 22px; color: var(--mid); flex: none; margin-top: 2px; }
.iconrow .txt { color: var(--muted); font-size: 14px; }
.iconrow .txt strong { color: var(--deep); display: block; font-weight: 700; margin-bottom: 3px; font-size: 15px; }
.icon { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; }

/* -------------------------------------------------------------- dark cta */
.cta { background: var(--deep); color: var(--ls-color-white); padding: clamp(52px, 6vw, 74px) 0; }
.cta h2 { color: var(--ls-color-white); }
.cta .lede { color: rgba(255,255,255,.74); }
.cta .eyebrow { color: var(--pale); }
/* The primary button rests in --deep, which IS this band's background, so on the
   dark band it rendered as a dark rectangle on a dark rectangle with only the
   label visible. It inverts here. */
.cta .btn-primary { background: var(--ls-color-white); color: var(--deep); }
.cta .btn-primary:hover { background: var(--kelly); color: var(--ink); }
.cta .btn-secondary { background: transparent; color: var(--ls-color-white); border-color: rgba(255,255,255,.32); }
.cta .btn-secondary:hover { background: var(--kelly); color: var(--ink); border-color: var(--kelly); }
/* centred closer — the left-aligned version left half the dark band empty */
.cta .wrap { text-align: center; }
.cta .section-head { margin-left: auto; margin-right: auto; }
.cta .actions { justify-content: center; }

/* ------------------------------------------------------------------ faq */
.faq details { border-top: 1px solid var(--hair); }
.faq details:last-child { border-bottom: 1px solid var(--hair); }
.faq summary {
  cursor: pointer; list-style: none; padding: 18px 0; color: var(--deep);
  font-weight: 650; font-size: 16px; display: flex; justify-content: space-between; gap: 16px;
  transition: color .2s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; font-family: var(--ls-font-mono); color: var(--mid);
  transition: transform .3s var(--ease); flex: none;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq summary:hover { color: var(--kelly); }
.faq details p { color: var(--muted); padding-bottom: 18px; font-size: 15px; max-width: 68ch; }

/* --------------------------------------------------------------- footer */
.site-foot { border-top: 1px solid var(--hair); padding: 52px 0 32px; background: var(--tint); }
.site-foot .cols { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: 34px; }
@media (max-width: 720px) { .site-foot .cols { grid-template-columns: 1fr; } }
.site-foot .mark { height: 30px; width: auto; margin-bottom: 14px; display: block; }
.site-foot h4 {
  font-family: var(--ls-font-mono); font-weight: 500; font-size: 11px;
  letter-spacing: .13em; text-transform: uppercase; color: var(--mid); margin-bottom: 12px;
}
/* reset.css only zeroes list padding for `ul[role="list"]` — a modern reset
   convention that requires the explicit attribute. These lists don't carry it,
   so the browser's default padding-inline-start: 40px applied and the links sat
   massively indented under their headings instead of flush with them. */
.site-foot ul { list-style: none; display: grid; gap: 9px; margin: 0; padding: 0; }
.site-foot li { margin: 0; }
.site-foot a { display: inline-block; transition: color .2s var(--ease), transform .2s var(--ease); }
.site-foot a:hover { color: var(--kelly); transform: translateX(3px); }
.site-foot a { color: var(--body); font-size: 14px; transition: color .2s var(--ease); }
.site-foot a:hover { color: var(--kelly); }
.site-foot .legal {
  display: flex; flex-wrap: wrap; gap: 8px 22px; margin-top: 36px; padding-top: 20px;
  border-top: 1px solid var(--hair);
  font-family: var(--ls-font-mono); font-size: 11px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}

/* -------------------------------------------------------- scroll reveal */
/* Reveal-on-scroll is OPT-IN via the .js class that the script puts on <html>.
   Defaulting .rv to opacity:0 hid real content from anyone whose JavaScript
   failed to run — an entire page of products, invisible, with no error. Content
   must never depend on script to be seen; the animation is the enhancement. */
.js .rv { opacity: 0; transform: translateY(18px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
.js .rv.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .rv { opacity: 1; transform: none; transition: none; }
  .btn:hover, a.card:hover { transform: none; }
  .demo-row .bar i, .card .shotwrap img { transition: none; }
}
