/* Base layout, reset, header/nav/footer, buttons, cards. Loaded on every page.
   Landing-page-only rules (parallax hero, ticker, section-specific layout) live in
   landing.css instead, so they can never leak onto /faq/, /contact/, or the legal
   pages. Breakpoints used anywhere in this file: 640 / 768 / 900 only. */

*, *::before, *::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--jd-black);
  color: var(--jd-white);
  font-family: var(--jd-font-body);
  font-size: var(--jd-size-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

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

a {
  color: inherit;
}

h1, h2, h3, h4 {
  font-family: var(--jd-font-display);
  font-weight: 400;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  line-height: 1.05;
  margin: 0 0 var(--jd-space-3);
}

h1 { font-size: var(--jd-size-h1); }
h2 { font-size: var(--jd-size-h2); }
h3 { font-size: var(--jd-size-h3); }

p {
  margin: 0 0 var(--jd-space-3);
  color: var(--jd-white-dim);
}

.jd-container {
  width: 100%;
  max-width: var(--jd-max-width);
  margin-inline: auto;
  padding-inline: var(--jd-space-4);
}

.jd-section {
  padding-block: var(--jd-section-padding);
}

.jd-section--raised {
  background: var(--jd-charcoal);
}

.jd-text-accent {
  color: var(--jd-red);
  text-shadow: var(--jd-pop-shadow);
}

.jd-input {
  font-family: var(--jd-font-body);
  font-size: 1rem;
  padding: 0.75em 1em;
  border-radius: var(--jd-radius);
  border: 1px solid var(--jd-charcoal-line);
  background: var(--jd-black);
  color: var(--jd-white);
}

.jd-input:focus-visible {
  outline: 3px solid var(--jd-gold);
  outline-offset: 1px;
}

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

/* Skip link */
.jd-skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--jd-gold);
  color: var(--jd-black);
  padding: var(--jd-space-2) var(--jd-space-3);
  z-index: 1000;
  font-weight: 700;
}

.jd-skip-link:focus {
  left: var(--jd-space-3);
  top: var(--jd-space-3);
}

/* Focus visibility everywhere — motion effects must never remove this */
a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 3px solid var(--jd-gold);
  outline-offset: 2px;
}

/* Buttons */
.jd-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--jd-space-2);
  font-family: var(--jd-font-display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-size: 1rem;
  padding: 0.9em 1.6em;
  border-radius: var(--jd-radius);
  border: 2px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: transform var(--jd-duration-fast) var(--jd-ease-standard),
    background-color var(--jd-duration-fast) var(--jd-ease-standard);
}

.jd-btn:hover {
  transform: translateY(-2px);
}

.jd-btn--primary {
  background: var(--jd-red);
  color: var(--jd-white);
}

.jd-btn--primary:hover {
  background: var(--jd-red-dark);
}

.jd-btn--gold {
  background: var(--jd-gold);
  color: var(--jd-black);
}

.jd-btn--gold:hover {
  background: var(--jd-gold-deep);
}

.jd-btn--outline {
  background: transparent;
  color: var(--jd-white);
  border-color: var(--jd-white);
}

.jd-btn--outline:hover {
  border-color: var(--jd-gold);
  color: var(--jd-gold);
}

/* The header's persistent shortcut — pill-shaped (every other button is a
   rectangle) so its silhouette alone marks it as different, on top of living
   outside the header bar entirely (see .jd-header__deals). Red by default to
   match the rest of the button system, gold on hover to tie it to the price
   color instead. Lives in the header in place of a cart icon (which wrongly
   implied direct in-site checkout — this site has none; it jumps to the
   Buy-It-Now section instead). The pulse is a slow, low-amplitude glow, not a
   throb — meant to catch the eye once in a while, not demand it. */
.jd-btn--pop {
  background: var(--jd-red);
  color: var(--jd-white);
  border-radius: 999px;
  padding: 0.6em 1.4em;
  font-size: 1.1rem;
  animation: jd-pop-glow 2.8s ease-in-out infinite;
}

.jd-btn--pop:hover {
  background: var(--jd-gold);
  color: var(--jd-black);
  animation-play-state: paused;
}

@keyframes jd-pop-glow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(247, 247, 245, 0.45); }
  50% { box-shadow: 0 0 0 7px rgba(247, 247, 245, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .jd-btn--pop {
    animation: none;
  }
}

/* Cards */
.jd-card {
  background: var(--jd-charcoal-raised);
  border: 1px solid var(--jd-charcoal-line);
  border-radius: var(--jd-radius);
  padding: var(--jd-space-4);
}

/* Header */
.jd-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--jd-black);
  border-bottom: 1px solid var(--jd-charcoal-line);
}

.jd-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--jd-space-4);
  height: var(--jd-header-height);
}

/* The badge is deliberately oversized and breaks out of the header strip — a
   crest/seal pinned to the corner, not a logo confined inside a breadcrumb-sized
   box.

   Its top edge is pinned to match the "View Deals" button's top edge (so it
   overlaps the announcement bar above by the same amount the button does),
   which turned out to need more than just reusing the button's "taller than
   the row, let align-items: center do the work" technique: centering aligns
   *centers*, not top edges, and the logo (clamp 84–132px) and button (clamp
   56–88px) are different heights, so self-centering each one independently
   left their tops ~22px apart rather than matching. Fixed by giving the logo
   the exact same computed top offset the button gets from its own centering
   — same formula, just written explicitly — so the tops track each other at
   every viewport width instead of only by coincidence at one. */
.jd-header__logo {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 100%;
  /* Must match the img's own width clamp below exactly (not just be "roughly
     similar") — this reserves the flex space the nav starts after, so a
     mismatch here isn't cosmetic, it lets the nav links start before the
     logo's real visual right edge and overlap it, which is exactly what
     happened with the old clamp(90px, 11vw, 140px) once the image's width
     was fixed to its correct, considerably wider, aspect ratio. */
  width: clamp(165.9px, 21.725vw, 260.7px);
  flex-shrink: 0;
}

.jd-header__logo img {
  position: absolute;
  left: 0;
  /* Center the logo in the bar by its own height clamp (must mirror the
     height clamp on the next line exactly). The bar's height is this clamp
     + 20px (see --jd-header-height), so this resolves to ~10px at every
     width — the badge sits fully inside the bar. */
  top: calc((var(--jd-header-height) - clamp(84px, 11vw, 132px)) / 2);
  height: clamp(84px, 11vw, 132px);
  /* Explicit width clamp — height's clamp values scaled by the logo's real
     316:160 ratio — rather than width: auto or aspect-ratio, because neither
     actually took effect here: the site-wide `img { max-width: 100% }` reset
     (near the top of this file) resolves that percentage against this image's
     containing block, .jd-header__logo, and silently capped the rendered
     width to whatever THAT happened to be (0 at one point while debugging,
     then a flatly wrong 140px) regardless of width/aspect-ratio. max-width:
     none below is what actually fixes it; the explicit clamp just replaces
     the auto-sizing this image was never going to get anyway. */
  width: clamp(165.9px, 21.725vw, 260.7px);
  max-width: none;
}

/* Overflows the header bar like the logo badge, at a deliberately smaller
   scale so the logo still reads as the bigger of the two — but WITHOUT the
   logo's position:absolute + fixed-width-wrapper trick. That trick needs the
   wrapper's reserved width to match the button's actual rendered width, and
   here it didn't (a clamp() guess vs. the button's real ~133px), which is
   what left a large dead gap between the arrow and the button. Plain flexbox
   does this correctly with no guessing: .jd-header__social is a fixed 64px
   tall (see above) with align-items: center, so simply giving the button a
   height taller than that centers it and lets it overflow symmetrically
   above/below on its own — no absolute positioning, no reserved width, and
   its footprint in the flex row exactly matches its real rendered width, so
   the neighboring arrow sits directly against it via the row's normal gap. */
.jd-header__social .jd-btn--pop {
  /* Hidden on the narrowest screens: logo + social icons + this pill + the
     burger add up to ~474px, which pushed the header (and the page) past a
     360px phone's right edge. The mobile nav's "Buy It Now" link and the
     hero's own CTA carry the same action there. */
  display: none;
  height: clamp(56px, 8vw, 88px);
  flex-shrink: 0;
}

@media (min-width: 640px) {
  .jd-header__social {
    gap: var(--jd-space-3);
  }

  .jd-header__social .jd-btn--pop {
    display: inline-flex;
  }
}

/* Points at the "View Deals" shortcut. Desktop only (matches .jd-nav's own
   breakpoint) — the header is tight enough on tablet/mobile without adding
   another element, and the button is already prominent there on its own.
   justify-content: flex-end pins the arrow to the right edge of its slot, so
   its tip sits snug against the button rather than floating in the middle of
   the reserved space. */
.jd-header__arrow {
  display: none;
  color: var(--jd-gold);
  width: 88px;
  flex-shrink: 0;
}

@media (min-width: 900px) {
  .jd-header__arrow {
    display: flex;
    align-items: center;
    justify-content: flex-end;
  }
}

/* Stroke "write-on" reveal: dasharray longer than the path itself (~80 units)
   starts fully offset (invisible), draws in, holds, erases, and repeats —
   drawing the shaft first and the arrowhead last each cycle, in path-defined
   order. The 0%/100% keyframes match (both hidden) so consecutive loops don't
   visibly jump. JS (motion.js) counts iterations and swaps in
   .jd-header__arrow-path--done after ~10 loops, which kills the animation and
   forces the fully-drawn state — a pure-CSS iteration-count would just as
   easily have ended mid-cycle (hidden, or half-erased), and the arrow's whole
   job is to keep pointing at the button once it settles. */
.jd-header__arrow-path {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: jd-arrow-draw 1.8s ease-in-out 0.4s infinite;
}

.jd-header__arrow-path--done {
  animation: none;
  stroke-dashoffset: 0;
}

@keyframes jd-arrow-draw {
  0% { stroke-dashoffset: 100; }
  25% { stroke-dashoffset: 0; }
  65% { stroke-dashoffset: 0; }
  90% { stroke-dashoffset: 100; }
  100% { stroke-dashoffset: 100; }
}

@media (prefers-reduced-motion: reduce) {
  .jd-header__arrow-path {
    animation: none;
    stroke-dashoffset: 0;
  }
}

.jd-nav {
  display: none;
  align-items: center;
  gap: var(--jd-space-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.jd-nav a {
  text-decoration: none;
  font-family: var(--jd-font-display);
  font-size: 0.9rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.jd-nav a:hover {
  color: var(--jd-gold);
}

.jd-header__social {
  display: flex;
  align-items: center;
  /* Tighter on phones — at 320px wide the logo + icons + burger otherwise
     run a few px past the screen edge. Roomier from 640px up. */
  gap: var(--jd-space-2);
  /* Without an explicit height here, .jd-header__deals's height:100% below
     resolves to nothing (a % height needs a parent with a definite height) and
     the button ends up positioned by flex auto-sizing instead of anchored to
     the header bar — which is what put it further down than intended. */
  height: 100%;
}

.jd-header__social a {
  display: inline-flex;
}

.jd-nav-toggle {
  display: inline-flex;
  background: none;
  border: none;
  color: var(--jd-white);
  padding: var(--jd-space-2);
}

@media (min-width: 900px) {
  .jd-nav {
    display: flex;
  }
  .jd-nav-toggle {
    display: none;
  }
}

.jd-nav--mobile {
  display: flex;
  flex-direction: column;
  gap: var(--jd-space-3);
  padding: var(--jd-space-4);
  background: var(--jd-charcoal);
  border-bottom: 1px solid var(--jd-charcoal-line);
}

.jd-nav--mobile[hidden] {
  display: none;
}

@media (min-width: 900px) {
  .jd-nav--mobile {
    display: none !important;
  }
}

/* Announcement bar. Was black-on-gold (9.77:1 contrast — excellent, the same
   reason caution signage uses black-on-yellow) until asked for white text
   instead. White-on-gold measures 1.89:1, well under the 4.5:1 WCAG AA
   minimum — a real regression, not just a style change — so the background
   moved to --jd-red instead (white-on-red measures 4.97:1, passing, and
   matches the button system) rather than keeping gold with white on it. */
.jd-announcement {
  background: var(--jd-red);
  color: var(--jd-white);
  font-family: var(--jd-font-display);
  text-transform: uppercase;
  font-size: 1rem;
  letter-spacing: 0.02em;
}

.jd-announcement__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--jd-space-3);
  padding-block: var(--jd-space-2);
  text-align: center;
}

.jd-announcement .jd-btn {
  padding: 0.4em 1em;
  font-size: 0.75rem;
}

/* Footer */
.jd-footer {
  background: var(--jd-charcoal);
  border-top: 1px solid var(--jd-charcoal-line);
  padding-block: var(--jd-space-6);
}

.jd-footer__grid {
  display: grid;
  gap: var(--jd-space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) {
  .jd-footer__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 900px) {
  .jd-footer__grid {
    grid-template-columns: 2fr repeat(4, 1fr);
  }
}

.jd-footer h4 {
  color: var(--jd-gold);
  font-size: 1rem;
  margin-bottom: var(--jd-space-3);
}

.jd-footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--jd-space-2);
}

.jd-footer a {
  text-decoration: none;
  color: var(--jd-white-dim);
}

.jd-footer a:hover {
  color: var(--jd-white);
}

.jd-footer__bottom {
  margin-top: var(--jd-space-6);
  padding-top: var(--jd-space-4);
  border-top: 1px solid var(--jd-charcoal-line);
  color: var(--jd-white-dim);
  font-size: var(--jd-size-small);
}

/* Placeholder marker — small dev/staff-visible ribbon, not a customer-facing label */
[data-placeholder="true"] {
  outline: 1px dashed var(--jd-gold);
  outline-offset: 4px;
  position: relative;
}

/* Generic simple page (FAQ/Contact/legal) */
.jd-simple-page {
  padding-block: var(--jd-space-7);
  max-width: 760px;
}

.jd-simple-page h2 {
  margin-top: var(--jd-space-6);
}

.jd-placeholder-banner {
  background: var(--jd-charcoal-raised);
  border: 1px dashed var(--jd-gold);
  color: var(--jd-gold);
  padding: var(--jd-space-3) var(--jd-space-4);
  border-radius: var(--jd-radius);
  margin-bottom: var(--jd-space-5);
  font-size: var(--jd-size-small);
}

/* ---- Dynamic zoom sweep ----------------------------------------------------
   The desktop layout reads best on a canvas ~2000px wide (empirically: a
   1600px screen at 80% browser zoom "snaps into place" — 1600 / 0.8 = 2000),
   and the tablet-band layout reads best with room up to the 1280px content
   width rather than blown up edge-to-edge. So the page is laid out on the
   band's canvas and scaled down continuously to fit — exactly like the user
   picking the perfect Ctrl/Cmd-minus level for their screen:

     < 768px      phones                 native, untouched
     768–899px    tablet band            zoom = width / 1280 (floor 0.65)
     900–1999px   desktops               zoom = width / 2000
     2000px+      big monitors, 2K/4K    native

   The continuous value comes from the inline script in templates/base.html,
   via --site-zoom on the root element; it recomputes on resize. The media
   queries below are only the no-JS fallback — flat midpoints per band. The
   canvas constants live in base.html; keep the two in sync. Scoped to the
   public site: only base.html loads this file — the dashboard (dash.css)
   and /djadmin/ are unaffected. */

:root {
  --site-zoom: 1;
}

@media (min-width: 768px) and (max-width: 899px) {
  :root {
    --site-zoom: 0.7; /* no-JS fallback only — JS overrides continuously */
  }
}

@media (min-width: 900px) and (max-width: 1999px) {
  :root {
    --site-zoom: 0.8; /* no-JS fallback only — JS overrides continuously */
  }
}

body {
  zoom: var(--site-zoom);
}
