/* ============================================================
   Leather and Lines LLC — Sheridan, WY
   Design assignment (design-variation-matrix.md):
     Archetype F  — product/result-first (the work IS the hero)
     Mood         — client-mandated turquoise + saddle brown on near-black
     Type pairing — P5, serif only (Aleo), no script/italic accent
   ------------------------------------------------------------
   ALL colour lives in the :root block below. Reskinning the site
   should never require touching a rule further down this file.
   ============================================================ */

:root{
  /* ---- Channel triplets ----------------------------------------
     Single source of truth for every brand colour. The solid tokens
     below and every translucent value on the page both derive from
     these, so one edit here repaints the site — no hex and rgba pair
     can drift apart. ------------------------------------------- */
  --turq-rgb:       63 207 196;
  --turq-deep-rgb:  13 107 102;
  --leather-rgb:    107 68 41;
  --leather-lt-rgb: 169 117 74;
  --paper-rgb:      247 243 236;
  --ink-rgb:        20 16 14;
  --on-light-rgb:   27 21 18;
  --muted-rgb:      198 186 173;

  /* ---- Brand palette: turquoise / white / brown / black ---- */
  --ink:        rgb(var(--ink-rgb));   /* near-black, warmed — never pure #000 */
  --ink-2:      #1C1613;   /* raised dark surface */
  --ink-3:      #251D19;   /* card on dark */
  --paper:      rgb(var(--paper-rgb));   /* warm off-white — never pure #fff */
  --paper-2:    #EFE8DC;   /* second light ground */

  --leather:    rgb(var(--leather-rgb));   /* saddle brown — structural, not trim */
  --leather-dp: #4A2E1C;
  --leather-lt: rgb(var(--leather-lt-rgb));
  --tan:        #D8BE9E;

  --turq:       rgb(var(--turq-rgb));   /* accent on dark grounds */
  --turq-deep:  rgb(var(--turq-deep-rgb));   /* accent as TEXT on light grounds (AA) */

  /* ---- Derived text tones ---- */
  --on-dark:        var(--paper);
  --on-dark-muted: rgb(var(--muted-rgb));
  --on-dark-faint:  rgb(var(--paper-rgb) / .14);
  --on-light:   rgb(var(--on-light-rgb));
  --on-light-muted: #5A4E44;
  --on-light-faint: rgb(var(--on-light-rgb) / .14);

  /* ---- Type scale (1.25 modular) ---- */
  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: 1rem;
  --text-lg:   1.25rem;
  --text-xl:   1.563rem;
  --text-2xl:  1.953rem;
  --text-3xl:  2.441rem;
  --text-4xl:  3.052rem;

  --font-display: "Aleo", Georgia, "Times New Roman", serif;
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* ---- Spacing (8px base) ---- */
  --s1: 8px;  --s2: 16px; --s3: 24px; --s4: 32px;
  --s5: 48px; --s6: 64px; --s7: 96px; --s8: 128px;

  --wrap: 1180px;
  --radius: 10px;

  /* ---- Motion: one language — fade + rise ---- */
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-inout:    cubic-bezier(0.65, 0, 0.35, 1);

  /* ---- Photo-slot placeholder theming (dark default) ---- */
  --slot-line: rgb(var(--turq-rgb) / .42);
  --slot-bg:   rgb(var(--turq-rgb) / .05);
  --slot-text: var(--on-dark-muted);
}

/* ---------- Reset / base ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ scroll-behavior:smooth; -webkit-text-size-adjust:100%; scrollbar-gutter:stable; }
body{
  margin:0;
  background: var(--ink);
  color: var(--on-dark);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
/* The off-canvas mobile drawer sits at translateX(100%), which otherwise
   makes the document 690px wide in a 375px viewport. `clip` contains it
   without creating a scroll container, so the sticky header and smooth
   anchor scrolling keep working; `hidden` is the pre-Safari-16 fallback. */
html, body{ overflow-x:hidden; }
@supports (overflow: clip){
  html, body{ overflow-x:clip; }
}
/* height:auto is load-bearing. Every img element carries width/height attributes to
   reserve space, so without it CSS caps the width while the height ATTRIBUTE
   still applies — a 481x481 photo renders 165x481 in a mobile tile. */
img{ max-width:100%; height:auto; display:block; }
a{ color:inherit; }
h1,h2,h3,h4{
  font-family: var(--font-display);
  font-weight:700;
  line-height:1.12;
  letter-spacing:-0.015em;
  margin:0;
  text-wrap:balance;
}
p{ margin:0 0 var(--s2); }
p:last-child{ margin-bottom:0; }

.wrap{ width:min(100% - 40px, var(--wrap)); margin-inline:auto; }
@media (max-width:640px){ .wrap{ width:min(100% - 32px, var(--wrap)); } }

.section{ padding: var(--s7) 0; position:relative; }
/* The header is sticky, so an anchor jump would otherwise land with the
   heading tucked underneath it. */
section[id]{ scroll-margin-top: 84px; }
@media (max-width:760px){ .section{ padding: var(--s6) 0; } }

/* While the window is being dragged across the 900px breakpoint, the nav
   swaps from an inline row to a fixed off-canvas drawer. Its transform
   transition would otherwise animate that swap, so the menu visibly flies
   across the screen mid-resize. Suppress transitions until dragging stops.
   Animations are untouched, so the hero band keeps running. */
.is-resizing *,
.is-resizing *::before,
.is-resizing *::after{ transition: none !important; }

/* ---------- Browser surfaces ---------- */
::selection{ background: rgb(var(--turq-rgb) / .30); color: var(--on-dark); }
.section--services ::selection,
.section--about ::selection,
.section--visit ::selection{ background: rgb(var(--turq-deep-rgb) / .22); color: var(--on-light); }

/* ---------- Focus + skip link ---------- */
:focus-visible{
  outline:2px solid var(--turq);
  outline-offset:3px;
  border-radius:3px;
}
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:100;
  background: var(--turq); color: var(--ink);
  padding:12px 20px; font-weight:700; text-decoration:none;
}
.skip-link:focus{ left:12px; top:12px; }

/* ---------- Scroll progress ---------- */
.scroll-progress{
  position:fixed; inset:0 0 auto 0; height:2px; z-index:60;
  background: var(--turq);
  transform:scaleX(0); transform-origin:0 50%;
  transition:transform .12s linear;
}

/* ============================================================
   HEADER
   ============================================================ */
.header{
  position:sticky; top:0; z-index:50;
  border-bottom:1px solid transparent;
  transition: border-color .3s var(--ease-inout);
}
/* The frosted backdrop lives on a pseudo-element, never on .header itself.
   backdrop-filter makes an element the containing block for every
   position:fixed descendant, and the mobile drawer is a fixed descendant of
   the header — so with the blur on .header, the drawer was confined to the
   header's own box (128px tall) instead of covering the screen. */
.header::before{
  content:""; position:absolute; inset:0; z-index:-1;
  background: rgb(var(--ink-rgb) / .72);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  transition: background-color .3s var(--ease-inout);
}
.header.is-scrolled::before{ background: rgb(var(--ink-rgb) / .94); }
.header.is-scrolled{ border-bottom-color: var(--on-dark-faint); }
.header__inner{
  position:relative;
  display:flex; align-items:center; justify-content:space-between;
  gap: var(--s3);
  padding: 20px 0;
  transition: padding .3s var(--ease-inout);
}
.header.is-scrolled .header__inner{ padding: 12px 0; }

.logo{
  display:inline-flex; align-items:center; gap:10px;
  text-decoration:none; color: var(--on-dark);
  flex-shrink:0;
  /* Padding + matching negative margin lifts the tap target to 44px
     without changing where the wordmark sits. */
  padding:7px 0; margin:-7px 0;
}
.logo__mark{
  width:30px; height:30px; color: var(--turq);
  transition: transform .5s var(--ease-out-expo);
}
.logo:hover .logo__mark{ transform: rotate(-4deg); }
.logo__word{
  font-family: var(--font-display);
  font-weight:700; font-size:1.06rem;
  letter-spacing:.005em; white-space:nowrap;
}
.logo__amp{ color: var(--turq); }

/* ---------- Nav ---------- */
.nav{ display:flex; align-items:center; gap: var(--s3); }
/* Scoped away from .btn: `.nav a` (0,1,1) outranks `.btn--primary` (0,1,0),
   so it was repainting the CTA's label in muted stone on turquoise — a 1.01:1
   contrast ratio, i.e. invisible — and overriding its size and weight too. */
.nav a:not(.btn){
  font-size: var(--text-sm); font-weight:500;
  color: var(--on-dark-muted); text-decoration:none;
  position:relative; padding:6px 0;
  transition: color .25s var(--ease-inout);
}
.nav a:not(.btn)::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:1px;
  background: var(--turq);
  transform:scaleX(0); transform-origin:0 50%;
  transition: transform .35s var(--ease-out-expo);
}
.nav a:not(.btn):hover{ color: var(--on-dark); }
.nav a:not(.btn):hover::after{ transform:scaleX(1); }
.nav__cta{ margin-left: var(--s1); }

.nav-toggle{
  display:none; position:relative; z-index:3;
  width:44px; height:44px; padding:10px;
  background:none; border:0; cursor:pointer;
  flex-direction:column; justify-content:center; gap:5px;
}
.nav-toggle span{
  display:block; height:2px; width:100%; background: var(--on-dark);
  transition: transform .35s var(--ease-out-expo), opacity .2s linear;
}
.nav-toggle.is-active span:nth-child(1){ transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-active span:nth-child(2){ opacity:0; }
.nav-toggle.is-active span:nth-child(3){ transform: translateY(-7px) rotate(-45deg); }

@media (max-width:900px){
  .nav-toggle{ display:flex; }
  /* A compact panel hanging off the header, not a full-screen takeover.
     Anchored to .header__inner so it lines up with the page gutter and never
     covers the toggle — the X stays visible and tappable, which is what made
     the old full-bleed drawer feel like a dead end. */
  .nav{
    position:absolute; top:calc(100% + 10px); right:0; z-index:2;
    width:max-content; min-width:196px; max-width:min(70vw, 260px);
    flex-direction:column; align-items:stretch; justify-content:flex-start;
    gap:2px; padding:8px;
    background: var(--ink-2);
    border:1px solid var(--on-dark-faint);
    border-radius:14px;
    box-shadow: 0 26px 50px -26px rgb(var(--ink-rgb) / .9);
    transform-origin: top right;
    transform: translateY(-6px) scale(.97);
    opacity:0; visibility:hidden;
    transition: opacity .18s var(--ease-inout),
                transform .24s var(--ease-out-expo),
                visibility 0s linear .24s;
  }
  .nav.is-open{ opacity:1; visibility:visible; transform:none; transition-delay:0s; }
  .nav a:not(.btn){
    font-size: var(--text-base); padding:11px 13px; border-radius:9px;
    transition: background-color .2s var(--ease-inout), color .2s var(--ease-inout);
  }
  /* The sliding underline belongs on a horizontal bar, not on menu rows. */
  .nav a:not(.btn)::after{ display:none; }
  .nav a:not(.btn):hover{ background: rgb(var(--paper-rgb) / .07); color: var(--on-dark); }
  .nav__cta{ margin:6px 0 0; justify-content:center; min-height:44px; }

  .nav-scrim{
    position:fixed; inset:0; z-index:1;
    background: rgb(var(--ink-rgb) / .55);
    opacity:0; transition: opacity .2s var(--ease-inout);
  }
  .nav-scrim.is-open{ opacity:1; }
  /* Scroll lock goes on <html>, not <body>. The root carries overflow-x:clip,
     so body's overflow no longer propagates to the viewport: overflow:hidden
     on body turned body into its own scroll container, the sticky header
     re-anchored to it, and jumped to the top of the document. On the root,
     it simply freezes the viewport where it is. */
  html.nav-open{ overflow:hidden; }
}

/* ============================================================
   BUTTONS
   ============================================================ */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  font-family: var(--font-sans);
  font-size: var(--text-sm); font-weight:600; letter-spacing:.01em;
  padding: 14px 26px; border-radius: var(--radius);
  text-decoration:none; border:1px solid transparent; cursor:pointer;
  transition: transform .2s var(--ease-out-expo), background-color .25s var(--ease-inout),
              color .25s var(--ease-inout), border-color .25s var(--ease-inout),
              box-shadow .25s var(--ease-inout);
}
.btn--sm{ padding:10px 18px; font-size: var(--text-xs); }
.btn--lg{ padding:17px 34px; font-size: var(--text-base); }

.btn--primary{
  background: var(--turq); color: var(--ink); border-color: var(--turq);
  box-shadow: 0 1px 0 rgb(var(--ink-rgb) / .2);
}
.btn--primary:hover{
  background: #55E0D5; border-color:#55E0D5;
  transform: translateY(-2px);
  box-shadow: 0 10px 26px -12px rgb(var(--turq-rgb) / .7);
}
.btn--primary:active{ transform: translateY(0); }

.btn--ghost{
  background:transparent; color: var(--on-dark);
  border-color: rgb(var(--paper-rgb) / .32);
}
.btn--ghost:hover{
  border-color: var(--turq); color: var(--turq);
  transform: translateY(-2px);
}
.btn--ghost:active{ transform: translateY(0); }

.link-arrow{
  font-family: var(--font-sans); font-size: var(--text-sm); font-weight:600;
  color: var(--turq); text-decoration:none;
  display:inline-flex; align-items:center; gap:7px;
  padding:11px 0; margin:-11px 0;
}
.link-arrow::after{
  content:"\2192";
  transition: transform .3s var(--ease-out-expo);
}
.link-arrow:hover::after{ transform: translateX(4px); }

/* ============================================================
   SHARED SECTION HEADS
   ============================================================ */
.eyebrow{
  font-family: var(--font-sans);
  font-size: var(--text-xs); font-weight:700;
  letter-spacing:.16em; text-transform:uppercase;
  color: var(--turq);
  margin:0 0 var(--s2);
}
.sec-head{ max-width: 42rem; margin-bottom: var(--s6); }
.sec-head h2{ font-size: clamp(var(--text-2xl), 4vw, var(--text-3xl)); }
.sec-sub{
  margin-top: var(--s2);
  font-size: var(--text-lg);
  color: var(--on-dark-muted);
  line-height:1.55;
}

/* Light-ground sections re-theme their own tokens */
.section--services,
.section--about,
.section--visit{
  background: var(--paper);
  color: var(--on-light);
  --slot-line: rgb(var(--leather-rgb) / .38);
  --slot-bg: rgb(var(--leather-rgb) / .045);
  --slot-text: var(--on-light-muted);
}
.section--about{ background: var(--paper-2); }
.section--services .eyebrow,
.section--about .eyebrow,
.section--visit .eyebrow{ color: var(--turq-deep); }
.section--services .sec-sub,
.section--about .sec-sub,
.section--visit .sec-sub{ color: var(--on-light-muted); }
.section--services .link-arrow,
.section--about .link-arrow,
.section--visit .link-arrow{ color: var(--turq-deep); }

/* ============================================================
   HERO — Archetype F: headline, then the work, immediately
   ============================================================ */
.hero{
  padding: clamp(var(--s6), 11vh, 120px) 0 var(--s7);
  background:
    radial-gradient(120% 80% at 50% -10%, rgb(var(--leather-rgb) / .30) 0%, transparent 62%),
    radial-gradient(60% 50% at 88% 8%, rgb(var(--turq-rgb) / .10) 0%, transparent 70%),
    var(--ink);
  position:relative;
  text-align:center;
}
.hero .eyebrow{ margin-bottom: var(--s3); }
.hero__title{
  font-size: clamp(var(--text-3xl), 5.6vw, 4.1rem);
  max-width: 19ch;
  margin-inline:auto;
  letter-spacing:-0.025em;
}
.hero__sub{
  margin: var(--s3) auto 0;
  max-width: 46ch;
  font-size: var(--text-lg);
  color: var(--on-dark-muted);
}

/* ---------- Full-bleed work band (hero marquee) ----------
   Two identical sets sit end to end inside the track. The track drifts
   exactly -50%, which lands set two precisely where set one began, so the
   loop has no visible seam. Item width is held near the source images'
   native 480px: scaling this band up is what would expose their
   resolution, so it stays small and sharp. */
.hero__strip{ margin-top: var(--s6); position:relative; }

.marquee{
  overflow:hidden;
  /* Dissolve both ends into the ground instead of cutting them off. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 7%, #000 93%, transparent 100%);
}
.marquee__track{
  display:flex;
  width:max-content;
  /* A known, permanently running animation is exactly what will-change is for.
     Keeps the band off the main thread so page paints don't judder with it. */
  will-change: transform;
  animation: marquee-drift 78s linear infinite;
}
.marquee__set{
  display:flex; gap:14px; padding:0 14px 0 0; margin:0;
  list-style:none;
}
.marquee__item{
  flex:0 0 auto;
  width:268px;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius);
  overflow:hidden;
  background: var(--ink-2);
}
.marquee__item img{ width:100%; height:100%; object-fit:cover; }

@keyframes marquee-drift{
  from{ transform: translate3d(0,0,0); }
  to{   transform: translate3d(-50%,0,0); }
}

/* The band runs continuously. Only the explicit Pause/Play control stops it —
   hover-to-pause made the hero freeze whenever the cursor crossed it. The
   button is also what satisfies WCAG 2.2.2, so nothing is lost by dropping
   the hover and focus-within pauses. */
.hero__strip.is-paused .marquee__track{ animation-play-state: paused; }

.marquee__toggle{
  position:absolute; right:26px; bottom:16px;
  display:inline-flex; align-items:center; gap:8px;
  padding:14px 18px; border-radius:100px;
  font-family: var(--font-sans); font-size: var(--text-xs); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase;
  color: var(--on-dark);
  background: rgb(var(--ink-rgb) / .72);
  border:1px solid rgb(var(--paper-rgb) / .22);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  cursor:pointer;
  transition: background-color .25s var(--ease-inout), border-color .25s var(--ease-inout), color .25s var(--ease-inout);
}
.marquee__toggle:hover{ border-color: var(--turq); color: var(--turq); }

/* Drawn, not a glyph: two bars for pause, a triangle for play. */
.marquee__icon{ position:relative; display:block; width:10px; height:12px; }
.marquee__icon::before,
.marquee__icon::after{
  content:""; position:absolute; top:0; width:3px; height:12px; background: currentColor;
}
.marquee__icon::before{ left:0; }
.marquee__icon::after{ right:0; }
.is-paused .marquee__icon::after{ display:none; }
.is-paused .marquee__icon::before{
  left:1px; width:0; height:0; background:none;
  border-left:10px solid currentColor;
  border-top:6px solid transparent;
  border-bottom:6px solid transparent;
}

.visually-hidden{
  position:absolute; width:1px; height:1px; margin:-1px; padding:0;
  overflow:hidden; clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0;
}

@media (max-width:900px){
  .marquee__item{ width:196px; }
  .marquee__toggle{ right:16px; bottom:12px; padding:14px 16px; }
}

.hero__foot{
  margin-top: var(--s5);
  display:flex; flex-direction:column; align-items:center; gap: var(--s3);
}
.hero__ctas{ display:flex; gap: var(--s2); flex-wrap:wrap; justify-content:center; }
.hero__facts{
  list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; justify-content:center;
  gap: var(--s1) var(--s3);
  font-size: var(--text-sm);
  color: var(--on-dark-muted);
}
.hero__facts li{ display:flex; align-items:center; gap: var(--s3); }
.hero__facts li:not(:last-child)::after{
  content:""; width:4px; height:4px; border-radius:50%;
  background: var(--turq); opacity:.65;
}

/* ============================================================
   WORK / GALLERY
   ============================================================ */
.section--work{ background: var(--ink); padding-top: var(--s6); }
/* Fixed 3-up so six pieces read as two clean rows rather than an
   auto-fit 4 + 2 orphan row. */
.gallery{
  display:grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: var(--s3);
}
@media (max-width:900px){ .gallery{ grid-template-columns: repeat(2, minmax(0,1fr)); } }
/* Mobile stays two-up rather than dropping to one column: six full-width
   squares turned the portfolio into roughly 2000px of uninterrupted scrolling.
   Two-up more than halves that, and at ~165px a side the 481px sources render
   near 3x density — the sharpest they appear anywhere on the site. */
@media (max-width:560px){
  .gallery{ grid-template-columns: repeat(2, minmax(0,1fr)); gap: 12px; }
}
.gallery__item img{ width:100%; height:100%; object-fit:cover; }
.gallery__item{
  margin:0; aspect-ratio: 1 / 1;
  border-radius: var(--radius); overflow:hidden;
  transition: transform .4s var(--ease-out-expo), box-shadow .4s var(--ease-out-expo);
}
.gallery__item:hover{
  transform: translateY(-4px);
  box-shadow: 0 18px 40px -20px rgb(var(--ink-rgb) / .8);
}
.gallery__note{
  margin-top: var(--s4);
  font-size: var(--text-sm);
  color: var(--on-dark-muted);
}
.gallery__note a{ color: var(--turq); text-decoration:none; border-bottom:1px solid rgb(var(--turq-rgb) / .4); }
.gallery__note a:hover{ border-bottom-color: var(--turq); }

/* ============================================================
   PHOTO SLOTS + CONFIRM CHIPS  (no-fabrication markers)
   ============================================================ */
.photo-slot{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap: var(--s1);
  text-align:center; padding: var(--s3);
  border:1.5px dashed var(--slot-line);
  border-radius: var(--radius);
  background:
    repeating-linear-gradient(135deg,
      transparent 0 9px,
      var(--slot-bg) 9px 18px);
}
.photo-slot__label{
  font-family: var(--font-sans);
  font-size: var(--text-xs); font-weight:600;
  letter-spacing:.06em; text-transform:uppercase;
  color: var(--slot-text); line-height:1.6;
}
.photo-slot__label em{
  display:inline-block; margin-top:4px;
  font-style:normal; font-weight:500; text-transform:none;
  /* .78 dropped this to 3.8:1 on the light slots — under AA. .9 still reads
     as the quieter half of the label and clears 4.9:1. */
  letter-spacing:.02em; opacity:.9;
}

.confirm{
  display:inline-flex; align-items:center; gap:.35em; vertical-align:middle;
  font-family: var(--font-sans);
  /* Scaffolding, but it is on the live site until every fact is confirmed,
     so it clears the same 11px floor as real UI text. */
  font-size:.6875rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:#7A4B00; background:#FBE3B8; border:1px dashed #C79320;
  padding:4px 9px; border-radius:6px; margin-left:7px; line-height:1.4; cursor:help;
}
.confirm::before{ content:"\26A0"; font-size:.7rem; }
.confirm--block{ margin-left:0; margin-top: var(--s1); }
.placeholder-text{ font-style:italic; color: var(--on-dark-muted); }
.section--visit .placeholder-text,
.footer .placeholder-text{ color: var(--on-light-muted); }
.footer .placeholder-text{ color: var(--on-dark-muted); }

/* ============================================================
   SERVICES
   ============================================================ */
.cards{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: var(--s3);
}
.card{
  background: #fff;
  border:1px solid var(--on-light-faint);
  border-radius: var(--radius);
  padding: var(--s4);
  position:relative;
  transition: transform .4s var(--ease-out-expo), box-shadow .4s var(--ease-out-expo),
              border-color .4s var(--ease-inout);
}
/* The lift carries the card's hit area up with it, so a pointer resting in the
   bottom few pixels drops out of :hover, the card falls back, :hover re-fires,
   and it oscillates. This strip holds the hover region where it started.
   Measured: a 3px band along the bottom edge. */
.card::after{
  content:""; position:absolute; left:0; right:0; top:100%; height:6px;
}
.card:hover{
  transform: translateY(-4px);
  border-color: rgb(var(--turq-deep-rgb) / .34);
  box-shadow: 0 18px 38px -24px rgb(var(--on-light-rgb) / .5);
}
.card h3{ transition: color .35s var(--ease-inout); }
.card:hover h3{ color: var(--turq-deep); }
.card h3{
  font-size: var(--text-lg);
  margin-bottom: var(--s2);
  display:flex; align-items:center; gap: var(--s1); flex-wrap:wrap;
}
.card p{ color: var(--on-light-muted); font-size: 0.95rem; }
.card__meta{ margin-top: var(--s2); }
.card--soon{ background: transparent; border-style:dashed; }
.tag{
  font-family: var(--font-sans);
  /* Was .6rem (9.6px). Uppercase and letterspaced at that size it fails on
     any high-DPI screen; 11px is the floor for text a visitor has to read. */
  font-size:.6875rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
  color: var(--leather-dp); background: var(--tan);
  padding:5px 10px; border-radius:100px;
}

/* ============================================================
   MEMORIAL — quiet, deliberately restrained
   ============================================================ */
.section--memorial{
  background: var(--ink-2);
  padding-block: var(--s8);
}
@media (max-width:760px){ .section--memorial{ padding-block: var(--s7); } }
.memorial{ max-width: 40rem; }
.memorial h2{
  font-size: clamp(var(--text-xl), 3.2vw, var(--text-2xl));
  margin-bottom: var(--s3);
}
.memorial p{ color: var(--on-dark-muted); font-size: var(--text-base); }
.memorial__cta{ margin-top: var(--s4); }
/* the "stitch line" — leatherwork motif, used sparingly */
.memorial__rule{
  margin-top: var(--s5);
  height:1px;
  background-image: linear-gradient(90deg, var(--turq) 0 12px, transparent 12px 22px);
  background-size: 22px 1px;
  opacity:.55;
}

/* ============================================================
   ABOUT
   ============================================================ */
.about{
  display:grid;
  grid-template-columns: minmax(0,.85fr) minmax(0,1.15fr);
  gap: clamp(var(--s4), 5vw, var(--s7));
  align-items:start;
}
@media (max-width:860px){ .about{ grid-template-columns:1fr; } }
.about__portrait{
  aspect-ratio: 4/5;
  border-radius: var(--radius);
  position:sticky; top: 120px;
}
@media (max-width:860px){ .about__portrait{ position:static; aspect-ratio:3/2; } }
.about__body h2{ font-size: clamp(var(--text-2xl), 4vw, var(--text-3xl)); margin-bottom: var(--s3); }
.about__body p{ color: var(--on-light-muted); }
/* Scoped rather than !important: this only needed to outrank
   `.about__body p` (0,1,1), which one extra class does cleanly. */
.about__body .lede{
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight:500;
  color: var(--on-light);
  line-height:1.45;
  margin-bottom: var(--s3);
}
.about__aside{
  margin-top: var(--s3);
  padding-left: var(--s3);
  border-left:1px solid var(--tan);
  font-size: 0.95rem;
}
.facts{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(140px,1fr));
  gap: var(--s3);
  margin: var(--s5) 0 0;
  padding-top: var(--s4);
  border-top:1px solid var(--on-light-faint);
}
/* "Leatherwork since" wraps to two lines while its siblings don't —
   space-between keeps every year on the same baseline regardless. */
.facts > div{ display:flex; flex-direction:column; justify-content:space-between; }
.facts dt{
  font-size: var(--text-xs); font-weight:700;
  letter-spacing:.1em; text-transform:uppercase;
  color: var(--on-light-muted);
  margin-bottom:6px;
}
.facts dd{
  margin:0;
  font-family: var(--font-display);
  font-size: var(--text-lg); font-weight:600;
  color: var(--on-light);
}

/* ============================================================
   BOOKING & POLICIES  (dark ground)
   ============================================================ */
.section--booking{ background: var(--ink); }
.steps{
  list-style:none; margin:0 0 var(--s6); padding:0;
  display:grid; grid-template-columns: repeat(auto-fit, minmax(250px,1fr));
  gap: var(--s3);
  counter-reset: step;
}
.step{
  position:relative;
  padding: var(--s4);
  background: var(--ink-3);
  border:1px solid var(--on-dark-faint);
  border-radius: var(--radius);
}
.step__n{
  display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; border-radius:50%;
  background: rgb(var(--turq-rgb) / .12);
  border:1px solid rgb(var(--turq-rgb) / .4);
  color: var(--turq);
  font-family: var(--font-display); font-weight:700; font-size: var(--text-sm);
  margin-bottom: var(--s2);
}
.step h3{ font-size: var(--text-lg); margin-bottom: var(--s1); }
.step p{ color: var(--on-dark-muted); font-size:0.95rem; }

/* Eight policies, fixed 4-up: auto-fit landed on 5 and left two dead
   cells showing the divider colour. */
.policies{
  display:grid;
  grid-template-columns: repeat(4, minmax(0,1fr));
  gap:1px;
  background: var(--on-dark-faint);
  border:1px solid var(--on-dark-faint);
  border-radius: var(--radius);
  overflow:hidden;
}
@media (max-width:1000px){ .policies{ grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width:560px){ .policies{ grid-template-columns: repeat(2, minmax(0,1fr)); } }
.policy{
  background: var(--ink); padding: var(--s4);
  transition: background-color .35s var(--ease-inout);
}
.policy:hover{ background: var(--ink-3); }
.policy h3{
  font-size: var(--text-xs); font-weight:700;
  font-family: var(--font-sans);
  letter-spacing:.12em; text-transform:uppercase;
  color: var(--turq);
  margin-bottom: var(--s1);
}
.policy p{
  font-family: var(--font-display);
  font-size: var(--text-base);
  color: var(--on-dark);
  line-height:1.5;
}
.policy--age p strong{ color: var(--turq); font-weight:700; }

.carryover{
  margin-top: var(--s5);
  padding: var(--s4);
  background: rgb(var(--leather-rgb) / .16);
  border:1px solid rgb(var(--leather-lt-rgb) / .28);
  border-radius: var(--radius);
}
.carryover h3{
  font-size: var(--text-base);
  margin-bottom: var(--s1);
}
.carryover p{ color: var(--on-dark-muted); font-size:0.95rem; max-width:62ch; }

/* ============================================================
   VISIT
   ============================================================ */
.visit{
  display:grid;
  grid-template-columns: minmax(0,1fr) minmax(0,1fr);
  gap: clamp(var(--s4), 5vw, var(--s6));
  align-items:start;
}
@media (max-width:860px){ .visit{ grid-template-columns:1fr; } }
.visit__body h2{ font-size: clamp(var(--text-2xl), 4vw, var(--text-3xl)); margin-bottom: var(--s3); }
.notice{
  margin: var(--s4) 0;
  padding: var(--s3);
  background: rgb(var(--turq-deep-rgb) / .08);
  border:1px solid rgb(var(--turq-deep-rgb) / .24);
  border-radius: var(--radius);
}
.notice p{ font-size:0.95rem; color: var(--on-light-muted); }
.notice strong{ color: var(--turq-deep); }
.visit__meta{ margin: var(--s4) 0 0; display:grid; gap: var(--s3); }
.visit__meta dt{
  font-size: var(--text-xs); font-weight:700;
  letter-spacing:.1em; text-transform:uppercase;
  color: var(--on-light-muted); margin-bottom:4px;
}
.visit__meta dd{ margin:0; font-size: var(--text-base); }
.visit__meta a{ color: var(--turq-deep); text-decoration:none; border-bottom:1px solid rgb(var(--turq-deep-rgb) / .35); }

/* Booking embed: an iframe when the provider allows framing, a button when
   it doesn't. The button ships either way so the path is never dead. */
/* min-width:0 is load-bearing. As a grid item this defaults to min-width:auto,
   which refuses to shrink below its content's min-content width — and the
   frame's min-height x aspect-ratio computes a 427px min-content width. The
   item then overflowed its 343px track on mobile and got silently clipped by
   the page's overflow-x:clip. */
.booking-embed{ display:flex; flex-direction:column; gap: var(--s3); min-width:0; }
.booking-embed__frame{
  width:100%;
  aspect-ratio: 3/4;
  min-height: 380px;
  border-radius: var(--radius);
  overflow:hidden;
}
.booking-embed__frame iframe{
  display:block; width:100%; height:100%; border:0;
}
.booking-embed__cta{ align-self:flex-start; }
@media (max-width:860px){
  .booking-embed__frame{ aspect-ratio: 4/3; min-height: 320px; }
  .booking-embed__cta{ align-self:stretch; }
}

/* ============================================================
   CTA BAND — saddle brown carries real structural weight here
   ============================================================ */
.section--cta{ background: var(--leather); padding-block: var(--s7); }
.cta-band{ text-align:center; max-width: 44rem; margin-inline:auto; }
.cta-band h2{ font-size: clamp(var(--text-2xl), 4.4vw, var(--text-3xl)); }
.cta-band > p{
  margin-top: var(--s2);
  font-size: var(--text-lg);
  color: rgb(var(--paper-rgb) / .82);
}
.cta-band__actions{
  margin-top: var(--s4);
  display:flex; gap: var(--s2); justify-content:center; flex-wrap:wrap;
}
.cta-band__note{ margin-top: var(--s3); }

/* ============================================================
   FOOTER
   ============================================================ */
.footer{
  background: var(--ink);
  color: var(--on-dark-muted);
  padding: var(--s6) 0 var(--s3);
  border-top:1px solid var(--on-dark-faint);
}
.footer__inner{
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap: var(--s3);
  padding-bottom: var(--s4);
  border-bottom:1px solid var(--on-dark-faint);
}
/* The tooled badge is the real mark. It carries a lot of fine detail — the
   scrollwork, the thread spool, the LEATHERCRAFT & TATTOOS banner — none of
   which survives below roughly 100px tall, which is why the sticky header
   keeps the typographic wordmark and the badge lives down here at a size
   where it can actually be read. */
.footer__logo{ display:block; line-height:0; flex:0 0 auto; }
.footer__logo img{ width:224px; max-width:54vw; height:auto; }

.footer__nav{ display:flex; gap: var(--s3); flex-wrap:wrap; }
.footer__nav a{
  font-size: var(--text-sm); text-decoration:none; color: var(--on-dark-muted);
  padding:11px 0; margin:-11px 0;
  transition: color .25s var(--ease-inout);
}
.footer__nav a:hover{ color: var(--turq); }
.footer__grid{
  display:grid;
  grid-template-columns: repeat(auto-fit, minmax(200px,1fr));
  gap: var(--s4);
  padding: var(--s5) 0;
}
.footer__grid h3{
  font-family: var(--font-sans);
  font-size: var(--text-xs); font-weight:700;
  letter-spacing:.12em; text-transform:uppercase;
  color: var(--turq);
  margin-bottom: var(--s2);
}
.footer__grid p{ font-size:0.95rem; line-height:1.75; }
.footer__grid a{ color: var(--on-dark-muted); text-decoration:none; }
.footer__grid a:hover{ color: var(--turq); }
.footer__legal{
  padding-top: var(--s3);
  border-top:1px solid var(--on-dark-faint);
  font-size: var(--text-xs);
  color: rgb(var(--muted-rgb) / .7);
}

/* ============================================================
   MOTION — one language: everything arrives as if it is being drawn.

   Headings wipe in behind a mask, the stitch rule draws itself across,
   photographs settle out of a blur. Body copy keeps the quiet fade-and-rise
   so the authored moments stay legible against it. Every curve is the same
   exponential ease-out; only the role changes.
   ============================================================ */

/* Headings: masked wipe, rising into the window as it opens. */
.js .wipe{ clip-path: inset(0 0 100% 0); transform: translateY(.3em); }
.wipe{
  transition: clip-path .55s var(--ease-out-expo), transform .55s var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}
/* The resting inset sits outside the box so descenders are never clipped. */
.js .wipe.is-visible{ clip-path: inset(-.3em -.15em -.3em -.15em); transform:none; }

/* Photographs: out of focus, then settling. */
.js .develop{ opacity:0; transform: scale(1.05); filter: blur(14px); }
.develop{
  transition: opacity .5s var(--ease-out-expo), transform .7s var(--ease-out-expo),
              filter .55s var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}
.js .develop.is-visible{ opacity:1; transform:none; filter: blur(0); }

/* The stitch rule draws left to right. Clipping keeps the dash pattern intact,
   where scaleX would stretch each stitch as it grew. */
.js .draw-line{ clip-path: inset(0 100% 0 0); }
.draw-line{ transition: clip-path .7s var(--ease-out-expo); transition-delay: var(--d, 0ms); }
.js .draw-line.is-visible{ clip-path: inset(0 0 0 0); }

/* Step numerals arrive just behind their card. */
.js .step .step__n{ transform: scale(.72); opacity:0; }
.step__n{
  transition: transform .45s var(--ease-out-expo), opacity .35s var(--ease-out-expo);
  transition-delay: calc(var(--d, 0ms) + 110ms);
}
.js .step.is-visible .step__n{ transform:none; opacity:1; }

/* ---------- The quiet default ---------- */
/* Hidden state is scoped to .js (set by an inline script in <head>) so a
   JS-less visitor gets the full page instead of a blank one. */
.js .reveal{ opacity:0; transform: translateY(24px); }
.reveal{
  transition: opacity .5s var(--ease-out-expo), transform .5s var(--ease-out-expo);
  transition-delay: var(--d, 0ms);
}
.reveal.is-visible{ opacity:1; transform:none; }
[data-reveal-delay="1"]{ --d: 55ms; }
[data-reveal-delay="2"]{ --d: 110ms; }
[data-reveal-delay="3"]{ --d: 165ms; }
[data-reveal-delay="4"]{ --d: 220ms; }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  /* A blanket transition-duration:0 also kills colour, border and shadow
     feedback, which nobody asked to lose. Restrict transitions to the
     non-moving properties instead, so hover and focus still respond. */
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    scroll-behavior:auto !important;
    transition-property: color, background-color, border-color, box-shadow, outline-color !important;
  }
  /* Content arrives already in place — no wipe, no blur, no draw. */
  .reveal,
  .wipe,
  .develop,
  .draw-line,
  .step__n{
    opacity:1 !important;
    transform:none !important;
    clip-path:none !important;
    filter:none !important;
  }
  /* No drift at all; the band becomes a plain scrollable row instead. */
  .marquee__track{ animation:none !important; }
  .marquee{ overflow-x:auto; }
  .marquee__toggle{ display:none; }
  /* Without their transitions these would snap, so drop the displacement. */
  .btn:hover,
  .card:hover,
  .gallery__item:hover,
  .logo:hover .logo__mark,
  .link-arrow:hover::after{ transform:none !important; }
  .nav a:not(.btn)::after{ transition:none !important; }
}


/* ============================================================
   MOBILE COMPACTION
   Lives at the end of the file on purpose: these override base rules of equal
   specificity, so they have to come after them in source order. Padding and
   column count only — no type size is reduced, so nothing becomes harder to
   read than it is on desktop.
   ============================================================ */
@media (max-width:560px){
  .cards{ gap: 14px; }
  .card{ padding: 22px 20px; }
  .step{ padding: 22px 20px; }
  .steps{ gap: 14px; }
  .carryover{ padding: 20px; }
  .policy{ padding: 18px 16px; }
  .booking-embed__frame{ min-height: 260px; }
  .card h3{ margin-bottom: 10px; }
  .step h3{ margin-bottom: 6px; }
}
