/* Jarrod Morris Music
   Section architecture after lukecombs.com.
   Sun-faded vintage treatment of Jarrod's own paper / black / ink / teal identity. */

/* ============================================================
   TOKENS
   ============================================================ */
:root {
  --paper:      #E7DFCF;
  --paper-warm: #F0EADD;
  --ink:        #38312A;
  --black:      #17130F;
  --accent:     #5E9490;
  --accent-ink: #35615F;

  /* Jarrod's original brand turquoise, undimmed. A deliberate exception to the
     aged palette, requested for the hero call to action so it pops against the
     video. Black text on it measures 8.2:1. Do not spread it across the site:
     everything else stays on --accent / --accent-ink. */
  --turquoise:  #09C0C9;

  /* Product photography ships on white studio backgrounds. Tiling it on a cream
     token leaves a visible white rectangle inside a cream card, so merch tiles
     use true white. Second approved exception, scoped to .shop-card__media. */
  --white:      #FFFFFF;

  /* The podcast slider is a deliberate one to one replica of the hero slide on
     thejarrodmorrisvibe.com, so it keeps that site two colours rather than
     mapping them onto the aged palette. Third and fourth approved exceptions,
     scoped to .pod-feat__tagline and .pod-feat__art. */
  --jmv-blue:   #46C4E9;
  --jmv-border: #262626;

  /* alpha variants, derived from the six above */
  --ink-muted:   rgb(56 49 42 / 72%);
  --paper-muted: rgb(231 223 207 / 70%);
  --rule:        rgb(56 49 42 / 18%);
  --rule-light:  rgb(231 223 207 / 20%);

  --font-display: 'Bebas Neue', Impact, sans-serif;
  --font-body: 'Jost', -apple-system, BlinkMacSystemFont, sans-serif;

  /* The LOGO is the driver here. Set these two and the header sizes itself
     around them via padding. Do not tie the logo to viewport width or to the
     hero, or it changes size with the banner instead of staying a fixed mark. */
  --logo-h-top: 100px;      /* branding size, top of page. 200x200 source, so
                               this is an exact 2x downscale and stays sharp. */
  --logo-h-scrolled: 60px;  /* compact bar, once scrolled. Kept large enough
                               that the mark stays legible rather than dropping
                               to a token icon. */
  --logo-h-mobile: 72px;    /* phones: the header is solid and takes real space
                               there, so a 100px mark ate too much of the screen.
                               The body offset below is derived from this. */
  --header-pad-y: 10px;
  --header-h: 56px;         /* floor for the compact bar */
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --section-y: clamp(4rem, 10vw, 8rem);
  --maxw: 1440px;
}

/* ============================================================
   RESET + BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  letter-spacing: 0.6px;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 0.92;
  margin: 0;
}

p { margin: 0; }

:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 3px;
}

/* ============================================================
   UTILITIES
   ============================================================ */
.section { padding: var(--section-y) var(--gutter); position: relative; }

.section--paper { background: var(--paper); color: var(--ink); }
.section--warm  { background: var(--paper-warm); color: var(--ink); }
.section--dark  { background: var(--black); color: var(--paper); }
.section--dark h1, .section--dark h2, .section--dark h3 { color: var(--paper); }

.section__inner { max-width: var(--maxw); margin: 0 auto; }

.section__head { margin-bottom: clamp(2rem, 5vw, 3.5rem); }

/* Clear breathing room between the eyebrow and the heading below it. */
.section__head .eyebrow { display: block; margin-bottom: 0.55rem; }

/* Optical left alignment. The eyebrow's glyphs start flush with its box, but
   Bebas Neue caps carry left side bearing, so a heading's ink sits a few pixels
   right of the eyebrow above it and the two read as misaligned.
   The bearing differs per letter, so a single global value would fix one
   heading and push others past flush. These are measured per first letter,
   expressed in em so they hold at any heading size. */
.section__head .display { margin-left: calc(var(--optical-left, 0em) * -1); }

#tour    { --optical-left: 0.009em; }  /* T */
#music   { --optical-left: 0.036em; }  /* M */
#shop    { --optical-left: 0.036em; }  /* H, which measures identical to M */
#videos  { --optical-left: 0.009em; }  /* V */
#contact { --optical-left: 0.027em; }  /* C */
/* #podcast needs none: its T measures flush at 0. */

.display {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 0.92;
  font-size: clamp(3rem, 12vw, 7rem);
}

.eyebrow {
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.22em;
  font-size: 0.75rem;
  color: var(--accent-ink);
}

.section--dark .eyebrow { color: var(--accent); }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* Scroll reveal is gated behind the `js` class set inline in <head>, so content
   stays visible if JS never runs. Do NOT move this into unconditional CSS. */
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity .7s ease, transform .7s ease; }
.js .reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

/* ============================================================
   VINTAGE TREATMENT
   Every layer here is decorative. The page must read correctly
   with all of it removed. Nothing in this block may capture
   pointer events.
   ============================================================ */

/* Stacking order, deliberate:
     1  .grain      page-wide noise
     2  .hero       lifted ABOVE the grain so the video plays completely clean
     3  .site-header
   The rest of the site sits below the grain and keeps its texture. */
.grain {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
}

/* Fine dot texture so --black is never a flat field. Dark sections only. */
.section--dark::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.5;
  background-image: radial-gradient(rgb(231 223 207 / 6%) 1px, transparent 1px);
  background-size: 4px 4px;
}

.section--dark > * { position: relative; z-index: 1; }

/* Worn divider. Uneven rather than a clean 1px line. */
.rule {
  height: 2px;
  border: 0;
  margin: 0;
  background:
    linear-gradient(90deg,
      var(--rule) 0 18%, transparent 18% 20%,
      var(--rule) 20% 61%, transparent 61% 62%,
      var(--rule) 62% 100%);
}

.section--dark .rule {
  background:
    linear-gradient(90deg,
      var(--rule-light) 0 18%, transparent 18% 20%,
      var(--rule-light) 20% 61%, transparent 61% 62%,
      var(--rule-light) 62% 100%);
}

/* ---- faded print treatment ----
   Warms shadows toward brown and lifts highlights toward cream. Applied via a
   class so any single image can opt out with .treated--off. */
.treated {
  filter: sepia(0.32) saturate(0.72) contrast(0.92) brightness(1.04);
  mix-blend-mode: multiply;
}

.section--dark .treated { mix-blend-mode: normal; filter: sepia(0.3) saturate(0.7) contrast(0.95) brightness(0.96); }

/* Hero art sits on black and is full bleed, so it takes the darker variant
   plus a warm vignette rather than the multiply blend. */
.hero__img.treated,
.hero__video.treated { mix-blend-mode: normal; filter: sepia(0.34) saturate(0.68) contrast(0.98) brightness(0.82); }

/* Per-image opt-out. MUST out-specify every .treated variant above, including
   the (0,2,0) context rules `.section--dark .treated` and `.hero__img.treated`.
   A bare `.treated--off` is only (0,1,0) and silently loses to both, which is
   the whole point of this class, so keep these compound selectors. */
.treated.treated--off,
.section--dark .treated.treated--off,
.hero__img.treated.treated--off,
.hero__video.treated.treated--off {
  filter: none;
  mix-blend-mode: normal;
}

/* No vignette or scrim over the hero: the footage plays clean.
   Removed deliberately. If hero text ever becomes hard to read over a
   brighter clip, add a shadow to .hero__title / .hero__eyebrow rather than
   reinstating a full-bleed overlay on the video. */

/* ---- ink bleed on display type ----
   Tight low-opacity offset. Restrained on purpose. No distress font. */
.display, .hero__title, .music__title {
  text-shadow: 1px 1px 0 rgb(94 148 144 / 22%);
}

@media (prefers-reduced-motion: no-preference) {
  .treated { transition: filter .3s ease; }
}

/* Turn the whole treatment layer off for the legibility check in Task 10. */
html[data-treatment='off'] .grain,
html[data-treatment='off'] .section--dark::before { display: none; }

html[data-treatment='off'] .treated { filter: none; mix-blend-mode: normal; }
html[data-treatment='off'] .display,
html[data-treatment='off'] .hero__title,
html[data-treatment='off'] .music__title { text-shadow: none; }

/* ============================================================
   HEADER
   ============================================================ */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 3;
  height: auto;
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--header-pad-y) var(--gutter);
  background: transparent;
  transition: background .3s ease, border-color .3s ease;
  border-bottom: 1px solid transparent;
}

.site-header.is-scrolled {
  background: var(--black);
  border-bottom-color: var(--rule-light);
}

/* Standalone pages have no hero for the header to sit over, so it is solid and
   compact from the start. Kept separate from .is-scrolled, which JS toggles on
   scroll position and would strip at the top of the page. */
.site-header--solid {
  background: var(--black);
  border-bottom-color: var(--rule-light);
}

.site-header--solid .site-header__logo img { height: var(--logo-h-scrolled); }

/* Clears the fixed solid header on pages that have no banner for it to sit over.
   The header is logo + vertical padding + border, but never shorter than
   --header-h, so this must respect that floor or content tucks under the bar. */
.page {
  padding-top: max(
    var(--header-h),
    calc(var(--logo-h-scrolled) + (var(--header-pad-y) * 2) + 1px)
  );
}

/* ============================================================
   PAGE BANNER (standalone pages)
   Shorter than the home hero, but the same idea: full-bleed art with the
   transparent header over it, going solid on scroll.
   ============================================================ */
.page-hero {
  position: relative;
  z-index: 2;                 /* above .grain, below .site-header, as on the home hero */
  min-height: clamp(300px, 42vh, 480px);
  display: flex;
  align-items: flex-end;
  padding: 0 var(--gutter) clamp(2rem, 5vw, 3.5rem);
  overflow: hidden;
  background: var(--black);
}

.page-hero__img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 40%;
}

/* Keeps the heading readable over whatever the photograph is doing underneath. */
.page-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgb(23 19 15 / 82%) 0%, rgb(23 19 15 / 20%) 55%, transparent 100%);
}

.page-hero__inner {
  position: relative;
  z-index: 1;
  max-width: var(--maxw);
  width: 100%;
  margin: 0 auto 0 0;
  text-align: left;
}

.page-hero__eyebrow { color: var(--accent); margin-bottom: 0.6rem; }
.page-hero__title { color: var(--paper); }

/* Large at the top of the page so the mark carries the branding, shrinking to
   the compact bar once the user scrolls. */
.site-header__logo img {
  height: var(--logo-h-top);
  width: auto;
  transition: height .3s ease;
}

.site-header.is-scrolled .site-header__logo img { height: var(--logo-h-scrolled); }

.nav { display: flex; gap: clamp(1rem, 2.5vw, 2.25rem); }

.nav a {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--paper);
  padding: 6px 0;
  border-bottom: 1px solid transparent;
}

.nav a:hover, .nav a:focus-visible { border-bottom-color: var(--accent); }

.nav-toggle {
  display: none;
  background: none;
  border: 0;
  padding: 10px;
  cursor: pointer;
}

.nav-toggle__bar {
  display: block;
  width: 26px; height: 2px;
  background: var(--paper);
  transition: transform .3s ease, opacity .3s ease;
}

.nav-toggle__bar + .nav-toggle__bar { margin-top: 7px; }

.site-header.nav-open .nav-toggle__bar:first-child { transform: translateY(4.5px) rotate(45deg); }
.site-header.nav-open .nav-toggle__bar:last-child  { transform: translateY(-4.5px) rotate(-45deg); }

/* ============================================================
   HERO
   ============================================================ */
.hero {
  position: relative;
  /* Above .grain (z 1), below .site-header (z 3). Creates a stacking context so
     the video, title and social rail keep their own internal order while the
     whole hero sits clear of the page grain. */
  z-index: 2;
  min-height: 88svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 0 var(--gutter) clamp(3rem, 8vw, 6rem);
  overflow: hidden;
  background: var(--black);
}

.hero__img,
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 30%;
}

/* The loop is primary; the still is only for reduced-motion users. */
.hero__img { display: none; }

@media (prefers-reduced-motion: reduce) {
  .hero__video { display: none; }
  .hero__img { display: block; }
}

/* Hugs the left gutter rather than centring in a max-width column. Above about
   1600px the auto margins were pushing the title ~473px in from the edge, which
   read as centred. `margin-right: auto` keeps the cap without the left inset. */
.hero__inner {
  position: relative;
  z-index: 1;
  max-width: var(--maxw);
  width: 100%;
  margin: 0 auto 0 0;
  text-align: left;
}

.hero__eyebrow { color: var(--accent); margin-bottom: 0.75rem; }

.hero__title { color: var(--paper); margin-bottom: 1.75rem; }

.btn {
  display: inline-block;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  padding: 14px 30px;
  background: var(--accent);
  color: var(--black);
  border: 1px solid var(--accent);
  transition: background .25s ease, color .25s ease;
}

.btn:hover, .btn:focus-visible { background: transparent; color: var(--accent); }

/* Hero call to action: full-strength brand turquoise, no dimming. */
.btn--brand { background: var(--turquoise); border-color: var(--turquoise); color: var(--black); }
.btn--brand:hover, .btn--brand:focus-visible { background: transparent; color: var(--turquoise); }

/* Looks like a button, is not one. For states with nothing to click, such as a
   private date. Cancels the hover and pointer affordances so it never reads as
   interactive. */
.btn--static { cursor: default; }
.btn--static:hover, .btn--static:focus-visible { background: transparent; color: var(--accent-ink); }
.section--dark .btn--static:hover { background: transparent; color: var(--accent); }

.btn--ghost { background: transparent; color: var(--accent-ink); border-color: var(--accent-ink); }
.btn--ghost:hover, .btn--ghost:focus-visible { background: var(--accent-ink); color: var(--paper); }

.section--dark .btn--ghost { color: var(--accent); border-color: var(--accent); }
.section--dark .btn--ghost:hover { background: var(--accent); color: var(--black); }

.social-rail {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(3rem, 8vw, 6rem);
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  margin: 0; padding: 0;
  list-style: none;
}

.social-rail a { color: var(--paper); font-size: 1.05rem; }
.social-rail a:hover, .social-rail a:focus-visible { color: var(--accent); }

/* ============================================================
   TOUR
   ============================================================ */
.tour__tabs { display: flex; gap: 1.75rem; margin-bottom: 2rem; }

.tour__tab {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 0 0 8px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-muted);
}

.tour__tab.is-active { color: var(--ink); border-bottom-color: var(--accent); }

.tour__status { color: var(--ink-muted); padding: 1.5rem 0; }

.tour__link { color: var(--accent-ink); border-bottom: 1px solid var(--accent-ink); }

.tour-row {
  display: grid;
  grid-template-columns: 130px 1fr auto;
  gap: 1.5rem;
  align-items: center;
  padding: 1.4rem 0;
  border-bottom: 1px solid var(--rule);
}

.tour-row__date {
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1;
  letter-spacing: 0.02em;
}

.tour-row__year { display: block; font-family: var(--font-body); font-size: 0.7rem; letter-spacing: 0.16em; color: var(--ink-muted); }

.tour-row__venue { font-weight: 500; }

.tour-row__city { font-size: 0.86rem; color: var(--ink-muted); }

.tour-row__cta { justify-self: end; }

.tour-row__none { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--ink-muted); }

.tour__more { margin-top: 2rem; }

.tour__toggle-wrap { margin-top: 1.75rem; }

/* .btn sets display:inline-block, which beats the UA `[hidden]` rule, so the
   attribute alone would not hide this button. */
.tour__toggle[hidden] { display: none; }

/* Desktop shows the full list, so the control never appears there. */
.tour__toggle { display: none; }

@media (max-width: 900px) {
  .tour__toggle { display: inline-block; }

  /* Collapsed state trims the list to the first five dates. The trailing
     "all past dates" link is a <p>, not a .tour-row, so it is unaffected. */
  .tour__list.is-collapsed .tour-row:nth-child(n+6) { display: none; }
}

@media (max-width: 720px) {
  .tour-row { grid-template-columns: 1fr; gap: 0.5rem; }
  .tour-row__cta { justify-self: start; margin-top: 0.5rem; }
}

/* ============================================================
   MUSIC
   ============================================================ */
/* Featured release: art left, title + platform icons right. */
.album-feature {
  display: grid;
  grid-template-columns: minmax(260px, 460px) 1fr;
  gap: clamp(2rem, 6vw, 5rem);
  align-items: center;
}

.album-feature__art { width: 100%; height: auto; }

.album-feature__title {
  font-size: clamp(2rem, 5vw, 3.25rem);
  color: var(--paper);
  margin-bottom: 0.6rem;
}

.album-feature__status {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  color: var(--paper-muted);
  margin-bottom: 2rem;
}

/* Circular platform buttons, after the reference site. */
.dsp-icons { display: flex; flex-wrap: wrap; gap: 0.9rem; list-style: none; margin: 0; padding: 0; }

.dsp-icons a {
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--black);
  font-size: 1.35rem;
  transition: background .25s ease, color .25s ease, transform .25s ease;
}

.dsp-icons a:hover, .dsp-icons a:focus-visible {
  background: var(--turquoise);
  color: var(--black);
  transform: translateY(-2px);
}

/* Heading row carries the carousel arrows, so the thumbnails below stay flush
   with the section gutter instead of being pushed right by an inline button. */
.music__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.album-car__nav { display: flex; gap: 0.6rem; }

/* A class selector beats the UA `[hidden] { display: none }`, so the attribute
   alone would not hide this. Needed for the JS that hides dead arrows. */
.album-car__nav[hidden] { display: none; }

/* Back catalogue carousel */
.album-car {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(150px, 1fr);
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin-top: clamp(3rem, 7vw, 5rem);
}

.album-car::-webkit-scrollbar { display: none; }

.album-car__item {
  scroll-snap-align: start;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

.album-car__item img {
  width: 100%; height: auto;
  opacity: 0.55;
  transition: opacity .25s ease, outline-color .25s ease;
  outline: 2px solid transparent;
  outline-offset: 2px;
}

.album-car__item:hover img,
.album-car__item:focus-visible img { opacity: 1; }

.album-car__item.is-active img { opacity: 1; outline-color: var(--turquoise); }

.album-car__cap {
  display: block;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--paper-muted);
  margin-top: 0.6rem;
}

.album-car__btn {
  flex: none;
  width: 40px; height: 40px;
  background: transparent;
  border: 1px solid var(--rule-light);
  color: var(--paper);
  cursor: pointer;
  transition: background .25s ease, color .25s ease, border-color .25s ease;
}

.album-car__btn:hover, .album-car__btn:focus-visible {
  background: var(--paper); color: var(--black); border-color: var(--paper);
}

.music__more { margin-top: 2.5rem; }

@media (max-width: 860px) {
  .album-feature { grid-template-columns: 1fr; }
  .album-feature__art { max-width: 380px; }
}

/* ============================================================
   SHOP
   ============================================================ */
/* A sentence, not a word. Left at the .display clamp it renders at 7rem and
   dwarfs every other section heading. Same treatment and same clamp as
   .podcast__title, which is a near identical length. */
.shop__title { font-size: clamp(2rem, 5.5vw, 4rem); }

.shop__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
}

.shop-car__nav { display: flex; gap: 0.6rem; }
.shop-car__nav[hidden] { display: none; }

.shop-car__btn {
  width: 40px; height: 40px;
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--ink);
  cursor: pointer;
  transition: background .25s ease, color .25s ease, border-color .25s ease;
}

.shop-car__btn:hover, .shop-car__btn:focus-visible {
  background: var(--ink); color: var(--paper-warm); border-color: var(--ink);
}

.shop-car {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(230px, 1fr);
  gap: clamp(1rem, 2.5vw, 2rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.shop-car::-webkit-scrollbar { display: none; }

.shop-card { scroll-snap-align: start; display: flex; flex-direction: column; }

.shop-card__media {
  background: var(--white);
  border: 1px solid var(--rule);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  overflow: hidden;
  transition: border-color .25s ease;
}

.shop-card:hover .shop-card__media,
.shop-card a:focus-visible .shop-card__media { border-color: var(--accent-ink); }

.shop-card__media img {
  width: 100%; height: 100%;
  object-fit: contain;
  transition: transform .3s ease;
}

.shop-card:hover .shop-card__media img { transform: scale(1.04); }

/* These live inside the card's <a>, so they must be block to stack and to let
   the vertical margins apply at all. */
.shop-card__media { display: grid; }

.shop-card__name {
  display: block;
  font-family: var(--font-body);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  line-height: 1.4;
  color: var(--ink);
  margin-top: 1rem;
}

.shop-card__price {
  display: block;
  font-size: 0.82rem;
  color: var(--accent-ink);
  margin-top: 0.35rem;
}

.shop__more { margin-top: 2.5rem; }

/* ============================================================
   VIDEOS
   ============================================================ */
.videos__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }

/* The videos section is centred, unlike the rest of the site, matching the
   reference layout. Everything here is centred as a block so the heading,
   player, rail and button share one axis. */
.videos__head {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 1.25rem;
}

.videos .section__inner { display: flex; flex-direction: column; align-items: center; }

.videos__more { text-align: center; }

/* Featured player: one large video, thumbnails below swap it. */
.video-feature { max-width: 1040px; width: 100%; margin-inline: auto; text-align: center; }

.video-feature__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--black);
  border: 1px solid var(--rule-light);
}

.video-feature__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
  display: block;
}

.video-feature__title {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 3vw, 2.1rem);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--paper);
  margin-top: 1.1rem;
}

/* Thumbnail rail */
.vcar {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(220px, 1fr);
  gap: clamp(1rem, 2.5vw, 1.75rem);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin-top: clamp(2.5rem, 6vw, 4rem);
  max-width: 1040px;
  width: 100%;
  margin-inline: auto;
}

.vcar::-webkit-scrollbar { display: none; }

.vcard {
  scroll-snap-align: start;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

.vcard__media {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  outline: 2px solid transparent;
  outline-offset: 2px;
  transition: outline-color .25s ease;
}

.vcard__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0.55;
  transition: opacity .25s ease, transform .3s ease;
}

.vcard:hover .vcard__media img,
.vcard:focus-visible .vcard__media img { opacity: 1; transform: scale(1.03); }

.vcard.is-active .vcard__media { outline-color: var(--turquoise); }
.vcard.is-active .vcard__media img { opacity: 1; }

/* Play affordance so a still reads as a video */
.vcard__media::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 46px; height: 46px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgb(231 223 207 / 88%);
  transition: background .25s ease;
}

.vcard__media::before {
  content: '';
  position: absolute;
  z-index: 1;
  top: 50%; left: 50%;
  transform: translate(-40%, -50%);
  border-style: solid;
  border-width: 8px 0 8px 13px;
  border-color: transparent transparent transparent var(--black);
}

.vcard:hover .vcard__media::after { background: var(--turquoise); }

.vcard__title {
  display: block;
  font-family: var(--font-body);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  line-height: 1.4;
  color: var(--paper-muted);
  margin-top: 0.9rem;
}

.vcard.is-active .vcard__title { color: var(--paper); }

.videos__more { margin-top: 2.5rem; }

/* ============================================================
   PODCAST
   ============================================================ */
/* "The Jarrod Morris Vibe" is far longer than the one-word headings elsewhere,
   so it gets its own smaller ceiling rather than the 7rem display default. */
.podcast__title { font-size: clamp(2rem, 5.5vw, 4rem); }

.podcast__intro { margin-top: 1.25rem; max-width: 56ch; color: var(--ink-muted); }

.pod-follow {
  margin-top: clamp(2.5rem, 6vw, 4rem);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: clamp(1rem, 3vw, 2rem);
}

.pod-follow__label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--ink-muted);
}

.pod-links { display: flex; flex-wrap: wrap; gap: 0.75rem; list-style: none; margin: 0; padding: 0; }

.pod-links a {
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink);
  font-size: 1.05rem;
  transition: background .25s ease, color .25s ease, border-color .25s ease;
}

.pod-links a:hover, .pod-links a:focus-visible {
  background: var(--ink); color: var(--paper); border-color: var(--ink);
}


/* ============================================================
   CONTACT
   ============================================================ */
.contact-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
  max-width: 900px;
}

.contact-card {
  padding-top: 1.5rem;
  border-top: 2px solid var(--rule);
}

.contact-card__logo {
  width: 88px;
  height: 88px;
  object-fit: contain;
  margin-bottom: 1.25rem;
}

/* The Atomic mark ships as a white circle on an opaque black square with no
   alpha channel. Clipping to a circle drops the corners so it sits on the cream
   ground instead of showing a black box. */
.contact-card__logo--round { border-radius: 50%; }

.contact-card__role {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 3vw, 1.9rem);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1;
  color: var(--ink);
}

.contact-card__org {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-muted);
  margin-top: 0.6rem;
}

/* Sits tight under the company name: the two belong together as one block. */
.contact-card__email {
  display: inline-block;
  margin-top: 0.3rem;
  font-size: 0.95rem;
  color: var(--accent-ink);
  border-bottom: 1px solid transparent;
  /* Addresses are long and must not spill out of a narrow card. */
  word-break: break-word;
  transition: color .25s ease, border-color .25s ease;
}

/* Underline on hover only, so the address reads clean but still behaves like a
   link when pointed at. */
.contact-card__email:hover, .contact-card__email:focus-visible {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

@media (max-width: 720px) {
  .contact-grid {
    grid-template-columns: 1fr;
    /* Stacked, the blocks need their own breathing room since the rule between
       them is dropped below. */
    gap: 2.75rem;
  }

  /* Side by side the two top rules read as a deliberate pair. Stacked they do
     not: the second becomes a stray line mid-column, so only the first is kept
     as the divider under the heading. */
  .contact-card + .contact-card { border-top: 0; padding-top: 0; }
}

/* ============================================================
   TACK ROOM
   ============================================================ */
/* Banner with no photograph behind it. Shorter than the booking banner, since
   there is no image to give it presence. */
.page-hero--plain {
  min-height: clamp(220px, 30vh, 340px);
  border-bottom: 3px solid var(--turquoise);
}

.page-hero--plain::after { background: none; }

.tackroom__status {
  display: inline-block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--black);
  background: var(--turquoise);
  padding: 8px 16px;
  margin-bottom: 1.75rem;
}

.tackroom__lede {
  font-size: clamp(1.05rem, 2.2vw, 1.3rem);
  line-height: 1.6;
  max-width: 58ch;
  margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

/* Three across rather than auto-fit. There are five items, and a four-column
   track strands the fifth alone on its own row; three gives a balanced 3 + 2. */
.tackroom__list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  list-style: none;
  margin: 0 0 clamp(3rem, 7vw, 4.5rem);
  padding: 0;
  max-width: 1000px;
}

@media (max-width: 860px) { .tackroom__list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .tackroom__list { grid-template-columns: 1fr; } }

.tackroom__list li { padding-top: 1.25rem; border-top: 2px solid var(--rule); }

.tackroom__item {
  font-family: var(--font-display);
  font-size: clamp(1.2rem, 2.4vw, 1.55rem);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1;
  color: var(--ink);
}

.tackroom__desc {
  margin-top: 0.6rem;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--ink-muted);
}

.tackroom__notify { padding-top: 2.25rem; border-top: 2px solid var(--rule); max-width: 480px; }

.tackroom__notify-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-muted);
  margin-bottom: 1rem;
}

/* Reuses the lead capture form shell, but on a light section rather than over
   photography, so the input needs a visible edge.
   The compound selector is deliberate: .leadgen__form's `margin: … auto …`
   is declared later in this file, so at equal specificity it would win and
   re-centre the form, leaving it indented from the label and note around it. */
.tackroom__notify .tackroom__form {
  margin: 0;
  max-width: 420px;
}

.tackroom__form input { border: 1px solid var(--rule); }

.tackroom__note {
  margin-top: 0.9rem;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
}

/* ============================================================
   LEAD CAPTURE
   ============================================================ */
.leadgen {
  position: relative;
  overflow: hidden;
  background: var(--black);
  border-top: 3px solid var(--turquoise);
  border-bottom: 3px solid var(--turquoise);
  padding: clamp(3.5rem, 8vw, 6rem) var(--gutter);
}

/* Four photographs across, desaturated and dropped back so they read as a
   texture band rather than competing with the form on top. */
.leadgen__strip {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

.leadgen__strip img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 30%;
  filter: grayscale(1) brightness(0.4) contrast(1.05);
}

/* The strip brightness varies per photo, so a scrim guarantees the heading and
   the turquoise subhead stay legible whatever imagery is swapped in. */
.leadgen::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(75% 120% at 50% 50%, rgb(23 19 15 / 78%) 0%, rgb(23 19 15 / 55%) 100%);
}

.leadgen__inner {
  position: relative;
  z-index: 1;
  max-width: 560px;
  margin: 0 auto;
  text-align: center;
}

.leadgen__title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 6vw, 3.4rem);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 0.95;
  color: var(--paper);
}

.leadgen__sub {
  margin-top: 0.75rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--turquoise);
}

.leadgen__form {
  display: flex;
  max-width: 420px;
  margin: 1.75rem auto 0;
}

.leadgen__form input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--white);
  border: 0;
  padding: 15px 18px;
}

.leadgen__form input::placeholder {
  color: var(--ink-muted);
  text-transform: uppercase;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
}

.leadgen__form input:focus-visible {
  outline: 2px solid var(--turquoise);
  outline-offset: 2px;
}

.leadgen__form button {
  flex: none;
  width: 58px;
  background: var(--turquoise);
  color: var(--black);
  border: 0;
  cursor: pointer;
  font-size: 1rem;
  transition: filter .25s ease;
}

.leadgen__form button:hover, .leadgen__form button:focus-visible { filter: brightness(1.12); }

.leadgen__note {
  margin-top: 1rem;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--paper-muted);
}

/* ============================================================
   BOOKING
   ============================================================ */
.bform__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem 1.75rem; }
.bfield { display: flex; flex-direction: column; gap: 0.4rem; }
.bfield--wide { grid-column: 1 / -1; }

.bfield span { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.16em; color: var(--ink-muted); }

.bfield input, .bfield select, .bfield textarea {
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--paper-warm);
  border: 1px solid var(--rule);
  padding: 12px 14px;
  width: 100%;
}

.bfield input:focus-visible, .bfield select:focus-visible, .bfield textarea:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 1px;
}

.bform__note { margin: 1.75rem 0 1rem; font-size: 0.8rem; color: var(--ink-muted); }

@media (max-width: 720px) { .bform__grid { grid-template-columns: 1fr; } }

/* ============================================================
   FOOTER
   ============================================================ */
/* Compact centred stack at every width: label, socials, copyright. The logo was
   removed, and with it the reason for the old three-across row. */
.foot { background: var(--black); color: var(--paper); padding: clamp(2.5rem, 5vw, 3.5rem) var(--gutter); }

.foot__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.55rem;
}

.foot__follow {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--paper-muted);
}

.social-rail--row { position: static; flex-direction: row; gap: 1.6rem; }

.foot__meta { font-size: 0.75rem; color: var(--paper-muted); }

.foot__meta a { color: var(--accent); }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 900px) {
  /* On phones the header stops floating over the artwork. A 100px logo sitting
     on moving video read as muddled, so the bar goes solid and page content
     starts beneath it instead of behind it. */
  .site-header {
    background: var(--black);
    border-bottom-color: var(--rule-light);
  }

  /* Height must stay constant here. If the logo shrank on scroll the header
     would get shorter while the content offset below it did not, opening a
     strip of bare page background between the two. Both states use the same
     mobile size for that reason. */
  .site-header__logo img,
  .site-header.is-scrolled .site-header__logo img { height: var(--logo-h-mobile); }

  /* Offset every page by the solid header's height. Applied to body rather than
     .hero so the booking banner clears it too. Must stay derived from
     --logo-h-mobile or the offset and the header drift apart. */
  body { padding-top: calc(var(--logo-h-mobile) + (var(--header-pad-y) * 2) + 1px); }

  .nav-toggle { display: block; }

  .nav {
    /* Anchored to the header itself, not to a fixed token, because the header
       height now changes between its tall top state and the compact scrolled
       state. top:100% keeps the dropdown flush in both. */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 0;
    background: var(--black);
    border-bottom: 1px solid var(--rule-light);
    max-height: 0;
    overflow: hidden;
    transition: max-height .35s ease;
  }

  .site-header.nav-open .nav { max-height: 70vh; }

  .site-header.nav-open { background: var(--black); }

  .nav a { padding: 16px var(--gutter); border-bottom: 1px solid var(--rule-light); }

  /* Hero rail only. The footer rail is a --row variant that sets its own
     spacing, and this margin-top was pushing its icons off-centre. */
  .hero .social-rail { position: static; flex-direction: row; margin-top: 2rem; }

  .hero { justify-content: flex-end; }
}

@media (max-width: 480px) {
  .tour__tabs { gap: 1.1rem; }
  .tour__tab { font-size: 0.7rem; letter-spacing: 0.12em; }
}

/* ============================================================
   PODCAST SLIDER
   The hero carousel from thejarrodmorrisvibe.com, brought over
   to run the podcast section in place of the card row.

   Its structure and motion carry over unchanged: absolutely
   stacked slides crossfading on opacity over 600ms, a feature
   block pinned bottom left over a bottom-weighted gradient,
   round arrows at centre height, dots bottom centre.

   Two things do not carry over. It is a block inside a section
   rather than a full-bleed hero, so the 100vh becomes a bounded
   clamp. And its dark-site colours map onto this palette, with
   --accent for the button rather than --turquoise, which is
   reserved for the hero call to action.
   ============================================================ */
.pod-slider {
  position: relative;
  /* Load bearing. With aspect-ratio set and no width pinned, a min-height that
     exceeds the natural height makes the browser solve the ratio the other way
     and derive WIDTH from height, which pushed this 420px wide inside a 390px
     screen and scrolled the page sideways. */
  width: 100%;
  /* 16:9 to match the 1280x720 episode thumbnails exactly, so background-size
     cover has nothing to crop and each still is shown whole and centred. The
     floor is for phones, where 16:9 of a 335px column is 188px and far too
     short for the caption block; there the image does crop, horizontally. */
  aspect-ratio: 16 / 9;
  min-height: 300px;
  max-height: 720px;
  overflow: hidden;
  border-radius: 10px;
  background: var(--black);
}

.pod-slide {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  opacity: 0;
  pointer-events: none;
  transition: opacity .6s ease;
}

.pod-slide.is-active { opacity: 1; pointer-events: auto; }

.pod-slide__bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-repeat: no-repeat;
}

/* JMV's exact gradient stops. */
.pod-slide__grad {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    rgb(0 0 0 / 25%) 0%,
    rgb(0 0 0 / 0%) 35%,
    rgb(0 0 0 / 90%) 100%);
}

.pod-slide__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  /* JMV exactly: 0 var(--pad) 70px, where --pad is clamp(20px, 3vw, 50px).
     The bottom is a flat 70px there, not clamped. */
  padding: 0 clamp(20px, 3vw, 50px) 70px;
}

.pod-feat { max-width: 560px; }

/* The branded episode card, laid over the backdrop. Both images belong to the
   slide: the backdrop is the scene, this is the thumbnail with the show's
   lockup on it. JMV's values, including the 28% crop bias that keeps faces in
   frame when squarish art is cut to 16:9. */
.pod-feat__art {
  display: block;
  width: 230px;
  /* The width/height attributes on the img are presentational hints that set
     height directly, and aspect-ratio is ignored when both are specified. */
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  object-position: center 28%;
  border: 1px solid var(--jmv-border);
  border-radius: 14px;
  margin-bottom: 14px;
}

.pod-feat__desc {
  color: var(--white);
  font-size: 16px;
  line-height: 1.5;
  margin-bottom: 15px;
}

.pod-feat__actions {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

/* JMV's white pill, not this site's .btn. Deliberate: the ask was a one to one
   replica of the podcast slide, so the button keeps its own styling rather
   than picking up the aged palette. */
.pod-feat__watch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--white);
  color: var(--black);
  border: 0;
  border-radius: 9999px;
  padding: 11px 22px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  transition: opacity .15s ease;
}

.pod-feat__watch:hover,
.pod-feat__watch:focus-visible { opacity: 0.9; }

.pod-feat__play {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--black);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Drawn in CSS rather than U+25B6, which iOS and Android turn into a colour
   emoji. JMV does the same and for the same reason. */
.pod-feat__play::before {
  content: '';
  border-style: solid;
  border-width: 5px 0 5px 8px;
  border-color: transparent transparent transparent var(--white);
  margin-left: 2px;
}

.pod-feat__tagline {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--jmv-blue);
}

.pod-slider__arrow {
  position: absolute;
  /* JMV puts these at 50%. That works on a 100vh hero, where the caption block
     sits well below the midpoint. This box is 556px, so 50% lands on the
     thumbnail. Raised to centre them on the open picture above the caption. */
  top: 34%;
  transform: translateY(-50%);
  z-index: 5;
  width: 46px;
  height: 46px;
  border: 0;
  border-radius: 50%;
  background: rgb(23 19 15 / 45%);
  color: var(--paper);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
  opacity: 0.75;
  transition: opacity .15s ease;
}

.pod-slider__arrow:hover,
.pod-slider__arrow:focus-visible { opacity: 1; }

.pod-slider__arrow--prev { left: 15px; }
.pod-slider__arrow--next { right: 15px; }

.pod-slider__dots {
  position: absolute;
  bottom: 18px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  gap: 10px;
}

.pod-slider__dots button {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgb(231 223 207 / 40%);
  cursor: pointer;
}

.pod-slider__dots button.is-on { background: var(--paper); }

/* JMV's own breakpoint and value for the thumbnail. It does not shrink the
   description or the tagline on mobile, so neither do we. */
@media (max-width: 809px) {
  .pod-feat__art { width: 170px; margin-bottom: 12px; }
}

@media (max-width: 560px) {
  /* The podcast site's hero is the full screen on a phone: a tall portrait
     panel with the caption sitting on the bottom of it. A 16:9 strip is the
     wrong shape for that. It squeezed the backdrop to a sliver and left the
     caption no room, which is what made mobile read as broken.
     Portrait here instead, so the picture has somewhere to be and the caption
     lands at the bottom the way it does there. */
  .pod-slider {
    /* No ratio here. JMV sizes its hero with height alone (100vh, floor 620px)
       and lets the width be the screen, which is what makes it fit. A ratio
       plus a min-height is what broke this. */
    aspect-ratio: auto;
    height: 100svh;
    min-height: 620px;
    max-height: none;
    /* Edge to edge, as the podcast site hero is. Breaking out of the section
       gutter is not cosmetic: it returns the ~40px that was forcing the button
       and the tagline onto separate rows, so they sit on one line as there. */
    width: auto;
    margin-inline: calc(var(--gutter) * -1);
    border-radius: 0;
  }

  /* Kept, not hidden: JMV shows them at this width. Back to its 50% too. The
     34% above is only needed for the short desktop box; this panel is 844px,
     where the caption starts at 512 and 50% clears it. */
  .pod-slider__arrow { display: block; top: 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .pod-slide { transition: none; }
}

/* ============================================================
   SIGNUP STEP TWO
   Opens only after the email is already saved, so every exit
   path here is harmless and none of them warn.
   ============================================================ */
.signup {
  width: min(560px, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--paper-warm);
  color: var(--ink);
}

.signup::backdrop { background: rgb(23 19 15 / 72%); }

.signup__form { position: relative; padding: clamp(1.5rem, 4vw, 2.5rem); }

.signup__close {
  position: absolute;
  top: 8px; right: 12px;
  border: 0;
  background: none;
  font-size: 1.75rem;
  line-height: 1;
  color: var(--ink-muted);
  cursor: pointer;
  padding: 6px 10px;
}

.signup__close:hover, .signup__close:focus-visible { color: var(--ink); }

.signup__title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 5vw, 2.5rem);
  margin-bottom: 0.4rem;
}

.signup__sub { color: var(--ink-muted); font-size: 0.95rem; margin-bottom: 1.5rem; }

.signup__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
}

.signup__field--wide { grid-column: 1 / -1; }

.signup__field { display: flex; flex-direction: column; gap: 0.35rem; }

.signup__field span {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--accent-ink);
}

.signup__field input {
  font-family: var(--font-body);
  font-size: 1rem;
  padding: 11px 12px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}

.signup__field input:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 1px; }

.signup__note { min-height: 1.2em; margin-top: 0.9rem; font-size: 0.85rem; color: var(--accent-ink); }

.signup__submit { width: 100%; margin-top: 0.35rem; cursor: pointer; }

.signup__skip {
  display: block;
  width: 100%;
  margin-top: 0.85rem;
  border: 0;
  background: none;
  font-family: var(--font-body);
  font-size: 0.8rem;
  color: var(--ink-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.signup__skip:hover, .signup__skip:focus-visible { color: var(--ink); }

@media (max-width: 480px) {
  .signup__grid { grid-template-columns: 1fr; }
}
