/* ==========================================================================
   iROLEWIN — site stylesheet

   Palette and shape are read from creativecapes.com's own CSS variables rather
   than eyeballed. One correction worth recording, because the first pass got it
   wrong: that site's typography is Raleway throughout (base, heading, logo and
   nav are all the same variable). The candy "Life Savers" face appears only in
   the Judge.me review widget's carousel title, which is a third-party component
   and not the brand's own type.

   Two deliberate departures from the reference, both for readability:

   1. Its primary button is white on #40b3d4 — 2.44:1, well under the 4.5:1
      minimum. We keep the bright sky but set the label in a dark navy (5.7:1).
   2. Sky is a surface colour here, never text on a light background. Where an
      accent has to carry text, --accent-text is a deepened sky that clears 3:1
      at display size.
   ========================================================================== */

:root {
  /* The palette is fixed and light. Without this, Chrome's forced dark mode
     inverts the page and the black logo mark vanishes against a black header. */
  color-scheme: only light;

  --ink: #213b89;         /* brand navy: headings, links, dark sections */
  --ink-soft: #464e54;    /* secondary copy */
  --gray: #5c5c5c;        /* body copy */
  --line: #e7e1d4;

  --accent: #40b3d4;      /* bright sky — surfaces only */
  --accent-dark: #2b98b6;
  --accent-text: #2a8fae; /* deepened sky, legible as display-size text */
  --on-accent: #172c52;   /* label colour on sky and lime fills */
  --lime: #a7de35;
  --gold: #fdb813;
  --green: #1c8a5a;
  --warn: #c0392b;

  /* Chart series — four distinguishable hues, the lime deepened so a 9px bar
     stays visible on white. Violet, not teal, for the fourth: a sea-teal sits
     too close to the sky of series 2 at bar weight. */
  --series-1: #213b89;
  --series-2: #40b3d4;
  --series-3: #7cb518;
  --series-4: #8a5cd6;

  --bg: #fff;
  --bg-alt: #faf2e6;
  --white: #fff;

  /* The reference squares everything off: 3px on buttons, no pill radii. */
  --radius: 3px;
  --radius-sm: 2px;

  --shadow: 0 1px 3px rgba(33, 59, 137, .07);
  --shadow-lg: 0 12px 34px rgba(33, 59, 137, .11);

  --wrap: 1200px;

  /* One family, as on the reference — hierarchy comes from weight and size
     rather than a second face. */
  --font-display: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-serif: 'Playfair Display', Georgia, 'Times New Roman', serif;
  --font: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  background: var(--bg);
  color: var(--gray);
  font-size: 1.0625rem;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
}

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

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

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  margin: 0 0 .5em;
  line-height: 1.12;
  letter-spacing: -.022em;
  font-weight: 800;
}
h1 { font-size: clamp(2.3rem, 5.4vw, 3.9rem); line-height: 1.06; letter-spacing: -.032em; }
h2 { font-size: clamp(1.75rem, 3.5vw, 2.6rem); }
h3 { font-size: 1.3rem; line-height: 1.28; font-weight: 700; }
h4 { font-weight: 700; }
p { margin: 0 0 1em; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 22px; }
.section { padding: 104px 0; }
.section--tight { padding: 60px 0; }
.center { text-align: center; }
.muted { color: var(--gray); }
.lead { font-size: 1.16rem; line-height: 1.58; color: var(--ink-soft); max-width: 58ch; }
.center .lead { margin-left: auto; margin-right: auto; }

/* Section label. Like the reference's button treatment: uppercase, widely
   tracked, and in the brand navy rather than the sky, which is too light to
   carry 12px text on a pale background. */
.eyebrow {
  display: block;
  font-family: var(--font);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink);
  margin-bottom: 14px;
}

/* Breaks a block out of .wrap to the full viewport width. */
.bleed { width: 100vw; margin-left: calc(50% - 50vw); }

/* Image beside copy, edge to edge, with the media column bleeding off the
   page. Asymmetric on purpose — a 50/50 split reads as a template. */
.feature { display: grid; grid-template-columns: 1.02fr .98fr; align-items: center; }
.feature__media { aspect-ratio: 1 / 1; overflow: hidden; background: var(--bg-alt); }
.feature__media img { width: 100%; height: 100%; object-fit: cover; }
.feature__body { padding: 0 clamp(24px, 5vw, 88px); max-width: 620px; }
.feature--flip .feature__media { order: 2; }
@media (max-width: 900px) {
  .feature { grid-template-columns: 1fr; }
  .feature__media { order: -1; aspect-ratio: 4 / 3; }
  .feature__body { padding: 40px 22px 0; max-width: none; }
}

/* ---------- buttons ---------- */
/* Square, uppercase, tracked — the reference's button shape. The lift on hover
   is dropped in favour of a colour change, which suits a flat, squared button
   better than it suited a pill. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  padding: 15px 26px;
  border-radius: var(--radius);
  border: 2px solid transparent;
  font: inherit;
  font-weight: 700;
  font-size: .84rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
  white-space: nowrap;
}

.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover { background: var(--accent-dark); color: var(--on-accent); }

.btn--dark { background: var(--ink); color: #fff; }
.btn--dark:hover { background: #182c66; }

.btn--ghost { background: transparent; border-color: var(--ink); color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: #fff; }

.btn--white { background: #fff; color: var(--ink); }
.btn--white:hover { background: var(--bg-alt); }

.btn--block { width: 100%; }
.btn--lg { padding: 17px 32px; font-size: .9rem; }
.btn--sm { padding: 11px 18px; font-size: .72rem; }

.btn-note { display: block; font-size: .72rem; font-weight: 500; letter-spacing: .02em;
  text-transform: none; opacity: .8; margin-top: 3px; }

/* ---------- header ---------- */
.header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(255, 255, 255, .94);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.header__inner { position: relative; display: flex; align-items: center; gap: 22px; height: 68px; }

.logo { display: flex; align-items: center; gap: .55em; font-family: var(--font-display); font-weight: 800; font-size: 1.32rem; letter-spacing: -.02em; color: var(--ink); }
/* The supplied mark: knocked out of its white background, and trimmed above its
   baked-in tagline. That tagline is already set as real text — beside the mark in
   the header, beneath it in the footer — and at this size it would print about
   five pixels tall, an illegible smudge under a legible duplicate. */
.logo__img { display: block; height: 42px; width: auto; flex: none; }
.logo__tag { font-family: var(--font); font-size: .66rem; font-weight: 700; color: var(--gray); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }

/* Centred on the header rather than pushed right: it is out of flow so the
   logo and CTA keep their corners, and it sits in the middle of the viewport
   instead of the middle of whatever space they leave. */
.nav { display: flex; align-items: center; gap: 22px; position: absolute; left: 50%; top: 0; height: 100%; transform: translateX(-50%); }
.nav a { font-size: .9rem; font-weight: 600; color: var(--ink-soft); white-space: nowrap; }
@media (max-width: 1180px) { .logo__tag { display: none; } }
@media (max-width: 1100px) { .nav { gap: 16px; } .nav a { font-size: .85rem; } }
/* The homepage swaps its corner button for a 240px search field, which the
   centred nav shares the row with. Seven top-level links leave too little
   clearance at around 1050px, so the field gives up width first: at 190px the
   placeholder still reads, and nothing sits on top of it. */
@media (max-width: 1100px) { .header--search .hsearch { width: min(190px, 24vw); } }
.nav a:hover, .nav a[aria-current] { color: var(--ink); }

/* The Shop dropdown. The collections ride behind this one entry instead of
   sitting on the row, which is what makes the row fit at all.

   It opens on hover and on keyboard focus. `:focus-within` is enough for the
   keyboard because the toggle is a real link to the shop page: tabbing lands on
   it, which opens the panel, and the next Tab steps into the links now that they
   are no longer `display:none`. No JavaScript, and the toggle still navigates if
   someone clicks it rather than dipping into the menu.

   `align-self: stretch` makes the wrapper as tall as the header, so `top: 100%`
   puts the panel exactly on the header's bottom edge without a magic offset, and
   keeps the whole strip between the toggle and the panel as hover area. */
.navdrop { position: relative; display: flex; align-items: center; align-self: stretch; }
.navdrop__toggle { display: inline-flex; align-items: center; gap: 5px; }
.navdrop__caret { transition: transform .18s ease; }
.navdrop:hover .navdrop__caret, .navdrop:focus-within .navdrop__caret { transform: rotate(180deg); }
.navdrop.is-current > .navdrop__toggle { color: var(--ink); }
.navdrop__menu {
  display: none;
  position: absolute; top: 100%; left: -20px; z-index: 60;
  min-width: 226px; margin: 0; padding: 7px 0;
  list-style: none; text-align: left;
  background: var(--white); border: 1px solid var(--line);
  border-radius: 4px; box-shadow: var(--shadow-lg);
}
.navdrop:hover .navdrop__menu, .navdrop:focus-within .navdrop__menu { display: block; }
.navdrop__menu a { display: block; padding: 9px 20px; }
.navdrop__menu a:hover, .navdrop__menu a[aria-current] { background: var(--bg-alt); color: var(--ink); }

.header__cta { margin-left: auto; }

/* ---------- homepage header search ---------- */
/* The homepage trades the header button for a field. It sits in the button's
   corner, 40px tall against a 68px row, and opens a suggestion panel as soon as
   there is something to suggest. */
.hsearch {
  position: relative; flex: none;
  display: flex; align-items: center; gap: 8px;
  margin-left: auto;
  width: min(240px, 26vw); height: 40px; padding: 0 12px;
  background: var(--white);
  border: 1px solid var(--line); border-radius: var(--radius);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.hsearch:focus-within { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(33, 59, 137, .12); }
.hsearch__icon { flex: none; color: var(--gray); }
.hsearch input {
  flex: 1; min-width: 0; padding: 0; border: 0; background: none;
  font: inherit; font-size: .88rem; color: var(--ink);
  /* Plus Jakarta Sans draws a space about 2px wide at this size, which makes
     even the placeholder read as one word. Widening it here only costs the few
     characters a customer would ever type. */
  word-spacing: .16em;
  -webkit-appearance: none; appearance: none;
}
.hsearch input:focus { outline: none; }
.hsearch input::placeholder { color: var(--gray); }
.hsearch input::-webkit-search-cancel-button,
.hsearch input::-webkit-search-decoration { -webkit-appearance: none; }

/* Anchored right so it opens away from the centred nav, into the empty corner.
   A panel centred on a 240px field would run off the right edge of the page. */
.hsearch__menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 70;
  width: 340px; max-width: calc(100vw - 44px);
  max-height: min(58vh, 400px); overflow-y: auto;
  margin: 0; padding: 6px 0; list-style: none;
  background: var(--white); border: 1px solid var(--line);
  border-radius: 4px; box-shadow: var(--shadow-lg);
}
.hsearch__menu[hidden] { display: none; }
.hsearch__opt { display: flex; align-items: baseline; gap: 12px; padding: 9px 14px; cursor: pointer; }
.hsearch__opt b { font-size: .84rem; font-weight: 600; line-height: 1.35; color: var(--ink); }
.hsearch__meta { flex: none; margin-left: auto; font-size: .72rem; color: var(--gray); white-space: nowrap; }
.hsearch__opt.is-active, .hsearch__opt:hover { background: var(--bg-alt); }

@media (max-width: 980px) {
  /* Down here the row grows a second line, so the fixed 68px that clips
     everything else has to give way. The box then spans the width, which is
     also the width of a thumb. */
  .header--search .header__inner { height: auto; flex-wrap: wrap; row-gap: 9px; padding-block: 10px; }
  .header--search .hsearch { order: 3; flex-basis: 100%; width: 100%; margin-left: 0; }
  .header--search .hsearch__menu { left: 0; right: 0; width: auto; }
}

/* ---------- TK search ---------- */
/* The code a customer reads off a video and types in here, so the placeholder is
   an example code rather than the word "Search". The typed text is uppercased
   for display only — the value stays as typed and search.js normalises it — but
   the placeholder opts back out, because an example code set in caps reads as
   shouting. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.tksearch { display: flex; align-items: stretch; background: var(--white);
  width: min(420px, 100%); border: 1px solid var(--line); border-radius: var(--radius);
  overflow: hidden; box-shadow: var(--shadow); }
.tksearch:focus-within { border-color: var(--ink); box-shadow: 0 0 0 3px rgba(33, 59, 137, .12); }
.tksearch input { flex: 1; min-width: 0; border: 0; background: none;
  padding: 15px 6px 15px 20px; font: inherit; font-size: 1rem; font-weight: 700;
  color: var(--ink); text-transform: uppercase; letter-spacing: .04em; }
.tksearch input::placeholder { text-transform: none; font-weight: 400; letter-spacing: 0; color: var(--gray); }
.tksearch input:focus { outline: none; }
.tksearch button { display: inline-flex; align-items: center; gap: 7px; flex: none;
  border: 0; background: var(--accent); color: var(--on-accent); padding: 0 20px; cursor: pointer;
  font: inherit; font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.tksearch button:hover { background: var(--accent-dark); }

/* The box, folded behind a one-line prompt. Open, it is the largest thing in the
   hero and painted the same sky blue as the primary button beside it — the wrong
   hierarchy for a lookup most visitors never use. A <details> collapses it with
   no JavaScript, and the browser supplies the focus, the keyboard activation and
   the announced expanded state. */
.tkfind { margin-top: 26px; }
.tkfind__toggle { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: .88rem; font-weight: 600; color: var(--ink-soft); list-style: none; }
.tkfind__toggle::-webkit-details-marker { display: none; }
.tkfind__toggle::after { content: '\2192'; transition: transform .15s ease; }
.tkfind[open] .tkfind__toggle::after { transform: rotate(90deg); }
.tkfind__toggle:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.tkfind .tksearch { margin-top: 14px; }

/* The 404, where the prompt sits under a centred button rather than in a column
   of copy. */
.tkfind--center { margin-top: 44px; text-align: center; }
.tkfind--center .tksearch { margin-inline: auto; }

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

@media (max-width: 640px) {
  .tksearch input { padding: 13px 4px 13px 16px; font-size: .95rem; }
  .tksearch button { padding: 0 15px; }
  .tksearch button span { display: none; }
}

.burger { display: none; margin-left: auto; background: none; border: 0; cursor: pointer; padding: 8px; }
.burger span { display: block; width: 22px; height: 2px; background: var(--ink); margin: 5px 0; border-radius: 2px; }

@media (max-width: 980px) {
  /* The panel anchors to the header, not to the inner row, and spans it edge
     to edge — so the row cannot be a positioned ancestor down here. */
  .header__inner { position: static; }
  .nav {
    display: none;
    position: absolute; top: 68px; left: 0; right: 0;
    transform: none; height: auto; align-items: stretch;
    flex-direction: column; gap: 0;
    background: var(--white);
    border-bottom: 1px solid var(--line);
    padding: 8px 22px 18px;
    box-shadow: var(--shadow-lg);
  }
  .nav.is-open { display: flex; }
  .nav a { padding: 12px 0; border-bottom: 1px solid var(--line); }
  /* Inside the burger panel the collections expand inline rather than staying
     folded: they are one level deep, so a nested toggle would cost a tap to
     reach links that can just as well be visible. */
  .navdrop { display: block; align-self: auto; }
  .navdrop__toggle { display: flex; width: 100%; }
  .navdrop__caret { display: none; }
  .navdrop__menu {
    display: block; position: static;
    min-width: 0; padding: 0 0 4px 14px;
    border: 0; box-shadow: none; background: none;
  }
  .navdrop__menu a { padding: 10px 0; border-bottom: 0; font-size: .85rem; }
  .burger { display: block; }
  .header__cta { display: none; }
}

/* ---------- announcement ---------- */
.announce {
  background: var(--ink);
  color: #fff;
  text-align: center;
  font-size: .8rem;
  padding: 10px 16px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.announce strong { color: var(--gold); }
.announce a { color: #fff; text-decoration: underline; text-underline-offset: 3px; margin-left: 10px; }
.announce a:hover { color: var(--gold); }

/* ---------- promo strip ---------- */
/* The reference runs a second, louder bar between the nav and the hero. It is a
   different job from the announcement bar above it: that one states a standing
   fact, this one points at something you might act on this week. */
.promo {
  background: var(--lime);
  color: var(--on-accent);
  text-align: center;
  font-size: .82rem;
  font-weight: 700;
  padding: 11px 16px;
  letter-spacing: .02em;
}
.promo a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.promo a:hover { text-decoration-thickness: 2px; }

/* ---------- hero ---------- */
/* A full-bleed photograph with the copy laid over it, which is the reference's
   shape and was the biggest thing ours was not doing: our first version ran a
   two-column split with a product cut-out on the right.

   The scrim is two layers. A flat wash over the whole frame guarantees a floor
   under the type wherever it lands, and a left-weighted gradient then darkens
   the side the copy actually occupies — a single uniform overlay dark enough to
   save the headline would have flattened the picture to do it. The bottom stop
   stays light so the child and the dog are still legible as a photograph. */
.hero { position: relative; display: flex; align-items: center; overflow: hidden;
  min-height: min(74vh, 640px); background: var(--ink); }
/* hero-wide.jpg is mirrored in the image pipeline (tools/process_images.py,
   HERO_WIDE_MIRROR). These horizontal percentages are mirrored with it, so the
   window still covers the same part of the scene it did before the flip. */
.hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 48% 30%; }
.hero__scrim { position: absolute; inset: 0;
  background:
    linear-gradient(90deg, rgba(13,27,54,.88) 0%, rgba(13,27,54,.70) 44%, rgba(13,27,54,.24) 80%, rgba(13,27,54,.12) 100%),
    linear-gradient(rgba(13,27,54,.30), rgba(13,27,54,.30)); }
.hero__inner { position: relative; width: 100%; padding-top: 78px; padding-bottom: 78px; }
.hero__copy { max-width: 620px; color: #fff; }
.hero__eyebrow {
  display: inline-block;
  background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.4);
  border-radius: var(--radius);
  padding: 7px 14px;
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  margin-bottom: 22px;
}
.hero h1 { color: #fff; }

/* Homepage banner: the supplied sky-and-capes photograph, with the copy centred
   in its open sky. The scrim is only a whisper at the top — enough to keep the
   white kicker above 4.5:1 on bright sky, not enough to tint the photograph. */
.hero--banner { display: block; height: clamp(560px, 56vw, 880px); min-height: 0; background: #2f8fd6; text-align: center; }
.hero--banner .hero__bg { object-position: 50% 45%; }
.hero--banner::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(10,35,70,.22), rgba(10,35,70,.08) 36%, transparent 56%);
}
.hero__banner-copy { position: relative; z-index: 1; padding-top: clamp(44px, 6vw, 92px); color: #fff; }
.hero__kicker {
  margin: 0 0 clamp(10px, 1.2vw, 18px);
  font-family: var(--font); font-size: clamp(.66rem, 1.15vw, .95rem);
  font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: #fff;
}
.hero__display {
  margin: 0; font-family: var(--font-serif); font-weight: 500;
  font-size: clamp(2.1rem, 6.4vw, 6.5rem); line-height: 1.02;
  letter-spacing: -.01em; color: #fff; text-transform: none;
}
/* The reference sets the line as one; below tablet width it has to break, and
   it reads better broken at the comma than leaving "Me." alone on a line. */
/* One line at every width: the phone keeps the break hidden too, and the stacked
   layout below sizes the type to fit instead. */
.hero__break { display: none; }
@media (max-width: 700px) {
  .hero__kicker { font-size: .58rem; letter-spacing: .14em; }
}
.hero--banner .btn { margin-top: clamp(24px, 2.8vw, 40px); padding: 20px 46px; }
@media (max-width: 700px) { .hero--banner .btn { padding: 13px 30px; font-size: .8rem; } }

@media (max-width: 700px) {
  /* The phone shot is the five children, framed 4:3. The tall hero can only
     show about half its width, which cut two of them out, so on a phone the
     copy and the photo stack: the copy sits on a blue field and the photo runs
     full width beneath it, whole and never cropped.

     The field is painted in two layers — the sky's own left-to-right gradient
     underneath, a dark wash on top for white type. The wash is measured in
     pixels, not percentages: the copy block is a fixed ~222px tall while the
     photo below it grows with the viewport, so a percentage fade would still
     be dark where the two meet on a wide phone. Ending it at 190px leaves the
     bottom of the panel exactly the photo's top edge, and no seam shows. */
  .hero--banner {
    height: auto;
    display: flex; flex-direction: column;
    background:
      linear-gradient(180deg, rgba(8,28,58,.62) 0, rgba(8,28,58,.18) 100px, rgba(8,28,58,0) 220px),
      linear-gradient(90deg, #2484db, #479cec);
  }
  .hero--banner::after { display: none; }
  /* The <picture> is display:contents (see the card media rules below), so the
     image itself is the flex item — the order has to sit on the <img>. */
  .hero--banner .hero__bg {
    order: 2;
    position: static; display: block;
    width: 100%; height: auto; aspect-ratio: 4 / 3;
    object-fit: contain;
    /* The photo is a plain sky at its top, which is the same sky the panel is
       painted with — but the browser's colour-managed decode drifts a few
       values from the CSS, enough to draw a faint line where they meet. Fading
       the first 48px of the photo into the panel erases the line at the cost
       of a strip of empty sky nobody was looking at. */
    -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 48px);
    mask-image: linear-gradient(180deg, transparent 0, #000 48px);
  }
  .hero__banner-copy { order: 1; padding-top: 120px; padding-bottom: 26px; }
  /* "Role Different, Role Me." on one line. The string measures 10.7em in
     Playfair, so dividing the content width by 11 leaves a hair to spare, and
     the cap stops it growing into wallpaper on a big phone. */
  .hero__banner-copy .hero__display {
    font-size: clamp(1.3rem, calc((100vw - 72px) / 11), 2.5rem);
    white-space: nowrap;
  }
  .hero--banner .btn { margin-top: 18px; }
}
/* Halloween page band: the supplied group photograph, lettering baked in. A
   phone shows the whole 4:3 frame. A desktop takes a 2:1 crop of the top of the
   frame (halloween-banner-wide), because whole it stands taller than the
   viewport; the ratio is repeated here so the space is reserved before the
   desktop file loads rather than against the phone file's 4:3. */
.bannerband { display: block; background: #14120e; }
.bannerband img { display: block; width: 100%; height: auto; }
@media (min-width: 701px) { .bannerband img { aspect-ratio: 2 / 1; } }
/* Gold rather than the sky accent: --accent-text is tuned for type on white and
   lands under 3:1 against the scrim. */
.hero h1 span { color: var(--gold); }
.hero .lead { color: rgba(255,255,255,.9); }
.hero__actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.hero__proof { display: flex; flex-wrap: wrap; gap: 22px; margin-top: 30px; padding-top: 24px;
  border-top: 1px solid rgba(255,255,255,.25); }
.hero__proof div { font-size: .84rem; color: rgba(255,255,255,.8); }
.hero__proof b { display: block; font-size: 1.3rem; color: #fff; font-weight: 800; }
/* The hero sits on a dark photo, so the prompt has to be light and its hover
   lighten rather than darken. */
.hero__copy .tkfind { margin-top: 26px; }
.hero__copy .tkfind__toggle { color: rgba(255,255,255,.85); }
.hero__copy .tkfind__toggle:hover { color: #fff; }
/* A translucent ghost button, because the solid one is a dark navy outline that
   disappears into the scrim. */
.hero .btn--ghost { border-color: rgba(255,255,255,.55); color: #fff; }
.hero .btn--ghost:hover { background: #fff; border-color: #fff; color: var(--ink); }

@media (max-width: 900px) {
  /* At this width the copy fills the frame, so a left-weighted gradient no
     longer covers it — the scrim has to be heavy everywhere. */
  .hero { min-height: 0; }
  .hero__scrim { background:
    linear-gradient(180deg, rgba(13,27,54,.62) 0%, rgba(13,27,54,.80) 60%, rgba(13,27,54,.88) 100%); }
  /* A portrait box over a landscape frame shows about a third of the width, and
     a centred crop lands on the gap between the child and the dog. Shifting the
     window toward the child puts the costume — the thing being sold — in frame
     instead. The child is mirrored into the right half, hence 68% not 32%. */
  .hero__bg { object-position: 68% 38%; }
  .hero__inner { padding-top: 56px; padding-bottom: 60px; }
  .hero__copy { max-width: none; }
}

/* ---------- product rail ---------- */
/* The reference's two product blocks are carousels with Previous / Next and a
   View all link; ours were static grids. Scroll snap does the moving, so with
   JavaScript off this is still a swipeable strip rather than a dead row — the
   arrows are an enhancement, not the mechanism. */
.rail {
  display: grid; grid-auto-flow: column; gap: 20px;
  grid-auto-columns: calc((100% - 60px) / 4);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-behavior: smooth;
  padding-bottom: 6px;
  /* The row is a scroller, but a visible scrollbar under a card grid reads as a
     mistake; the arrows and the clipped card are the affordance instead. */
  scrollbar-width: none;
}
.rail::-webkit-scrollbar { display: none; }
.rail > * { scroll-snap-align: start; }
.railhead { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 30px; flex-wrap: wrap; }
.railhead__text { max-width: 620px; }
.railhead__nav { display: flex; align-items: center; gap: 10px; }
.railbtn {
  width: 40px; height: 40px; display: grid; place-items: center;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  color: var(--ink); cursor: pointer; font-size: 1rem; line-height: 1;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.railbtn:hover:not(:disabled) { background: var(--ink); border-color: var(--ink); color: #fff; }
.railbtn:disabled { opacity: .35; cursor: default; }
@media (max-width: 1000px) { .rail { grid-auto-columns: calc((100% - 40px) / 3); } }
@media (max-width: 760px) { .rail { grid-auto-columns: calc((100% - 20px) / 1.35); } }
@media (max-width: 460px) { .rail { grid-auto-columns: 82%; } }

/* Amazon look slides under the banner. Two large photographs are visible at a
   time (568×284 on a 1440 screen, four times the area of a four-up thumbnail
   row) and the track slides left one frame every four seconds. A phone shows
   one frame and slides every three. The whole slide is a link, but the CTA
   still names the destination, so a tap on a photograph never feels like an
   accident. The trailing clones of the first two slides are what make the
   wrap-around invisible. */
.lookshow { position: relative; }
.lookshow__frame { position: relative; overflow: hidden; }
.lookshow__track {
  display: flex; gap: 20px;
  transition: transform .65s cubic-bezier(.33, 0, .2, 1);
  will-change: transform;
}
.lookshow__slide {
  position: relative; flex: 0 0 calc((100% - 20px) / 2);
  display: block; aspect-ratio: 2 / 1;
  overflow: hidden; border-radius: var(--radius-sm); background: #0d1b36;
}
.lookshow__slide img { width: 100%; height: 100%; object-fit: cover; }
.lookshow__slide:hover img { transform: scale(1.03); transition: transform .8s ease; }
.look__cta {
  position: absolute; right: 16px; bottom: 16px;
  display: inline-flex; align-items: center;
  padding: 12px 20px; border-radius: var(--radius-sm);
  background: #fff; color: var(--ink);
  font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  transition: background .15s ease;
}
.lookshow__slide:hover .look__cta { background: var(--bg-alt); }
.lookshow__arrow {
  position: absolute; top: 50%; z-index: 3;
  width: 46px; height: 46px; margin-top: -23px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: rgba(255,255,255,.9); color: var(--ink);
  font-size: 1.2rem; line-height: 1; cursor: pointer;
  transition: background .15s ease;
}
.lookshow__arrow:hover { background: #fff; }
.lookshow__arrow--prev { left: 16px; }
.lookshow__arrow--next { right: 16px; }
.lookshow__dots {
  position: absolute; left: 50%; bottom: 16px; z-index: 3;
  transform: translateX(-50%);
  display: flex; gap: 2px;
}
.lookshow__dot {
  width: 24px; height: 24px; padding: 0; border: 0; background: none;
  display: grid; place-items: center; cursor: pointer;
}
.lookshow__dot::after {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: rgba(255,255,255,.55);
  box-shadow: 0 0 4px rgba(10,30,60,.35);
  transition: background .2s ease, transform .2s ease;
}
.lookshow__dot.is-active::after { background: #fff; transform: scale(1.4); }

/* The phone carousel: one frame, sliding left every three seconds. */
@media (max-width: 760px) {
  .lookshow__track { gap: 0; }
  .lookshow__slide { flex: 0 0 100%; }
  .lookshow__arrow { width: 38px; height: 38px; margin-top: -19px; font-size: 1rem; }
  .lookshow__arrow--prev { left: 10px; }
  .lookshow__arrow--next { right: 10px; }
  .lookshow__dots { bottom: 10px; }
  .look__cta { right: 12px; bottom: 12px; padding: 10px 16px; }
}
@media (prefers-reduced-motion: reduce) {
  .lookshow__track { transition: none; }
  .lookshow__slide:hover img { transform: none; }
}

/* ---------- pain point / empathy ---------- */

/* ---------- paired image + text ---------- */
/* The reference alternates these down the page — picture left on one, right on
   the next — so the eye zigzags instead of running down a single column. */
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; }
.pair--flip .pair__media { order: 2; }
/* Our feature images are studio cut-outs on white, not photographs with their
   own backgrounds, so without an edge the white square floats on the cream
   section as a hard bright block. The same hairline the product cards use makes
   it read as a plate instead. */
.pair__media { background: #fff; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.pair__media img { display: block; width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.pair__body h2 { font-size: clamp(1.5rem, 2.8vw, 2.15rem); }
.pair__list { list-style: none; padding: 0; margin: 26px 0 0; display: grid; gap: 20px; }
.pair__list li { display: grid; grid-template-columns: 17px 1fr; gap: 14px; align-items: start; }
/* A gold bolt rather than one of the shared icons, which are stroked dark grey
   and read as damage control beside a bullet that is meant to sell. Drawn as an
   SVG, not the ⚡ character: that is a colour emoji, so it ignores `color` and
   renders differently on every platform. */
.pair__list svg { margin-top: 5px; }
.pair__list b { display: block; color: var(--ink); font-size: 1rem; margin-bottom: 3px; }
.pair__list span { font-size: .94rem; color: var(--gray); }
.pair__steps { list-style: none; padding: 0; margin: 26px 0 0; display: grid; gap: 22px; counter-reset: pairstep; }
.pair__steps li { display: grid; grid-template-columns: 46px 1fr; gap: 16px; align-items: start; }
.pair__steps li::before {
  counter-increment: pairstep; content: counter(pairstep, decimal-leading-zero);
  font-family: var(--font-display); font-size: 1.6rem; font-weight: 800; line-height: 1;
  letter-spacing: -.04em; color: var(--ink); font-variant-numeric: tabular-nums;
}
@media (max-width: 860px) {
  .pair { grid-template-columns: 1fr; gap: 30px; }
  .pair--flip .pair__media { order: 0; }
}

/* ---------- how it works / trust bar ---------- */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px; }
.step { border-top: 2px solid var(--ink); padding-top: 20px; }
.step__n {
  display: block; font-family: var(--font-display); font-size: 2rem; font-weight: 800;
  line-height: 1; letter-spacing: -.04em; color: var(--ink); font-variant-numeric: tabular-nums;
}
.step h3 { margin: 12px 0 8px; font-size: 1.15rem; }
.step p { margin: 0; font-size: .95rem; color: var(--ink-soft); }
@media (max-width: 760px) { .steps { grid-template-columns: 1fr; gap: 26px; } }

.trustbar { background: var(--ink); color: #fff; padding: 26px 0; }
.trustbar__row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px 26px; }
/* A gold tick rather than an icon: the shared SVGs are stroked in dark grey for
   white panels and would disappear on navy. */
.trustbar__row span { display: flex; align-items: center; gap: 10px; font-size: .87rem; font-weight: 600; }
.trustbar__row span::before { content: ""; flex: none; width: 7px; height: 7px; background: var(--gold); }
@media (max-width: 860px) { .trustbar__row { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .trustbar__row { grid-template-columns: 1fr; } }

/* ---------- stars ---------- */
.stars { display: inline-flex; align-items: center; gap: 7px; font-size: .88rem; color: var(--gray); font-weight: 500; }
.stars__svg { flex: none; display: block; }
.stars--sm { font-size: .8rem; }

/* ---------- product grid ---------- */
.grid { display: grid; gap: 26px; }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1000px) { .grid--4 { grid-template-columns: repeat(2, 1fr); } .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .grid--4, .grid--3 { grid-template-columns: 1fr; } }

.card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.card:hover { border-color: var(--ink); box-shadow: var(--shadow-lg); }

/* <picture> exists only to carry the WebP <source>; it must not become a box,
   or the percentage sizes and aspect-ratio on the <img> inside resolve against a
   zero-width inline parent and the image collapses. Every place a responsive
   image is dropped in has to name its wrapper here, or that one slot collapses:
   the shop grid (.card__media), the banner (.hero), the two feature blocks
   (.pair__media), and the gifts/halloween hero art (.hero__art). */
.card__media picture, .hero picture, .bannerband picture,
.pair__media picture, .hero__art picture, .lookshow__slide picture { display: contents; }

/* White, not a tint: the product shots are cut out onto white, so any tint here
   would show up as a visible square behind each one. */
.card__media { position: relative; background: #fff; aspect-ratio: 1 / 1; overflow: hidden; }
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.card:hover .card__media img { transform: scale(1.04); }

.card__badge {
  position: absolute; top: 12px; left: 12px;
  background: var(--ink); color: #fff;
  font-size: .66rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  padding: 6px 10px; border-radius: var(--radius);
}
.card__badge--hot { background: var(--accent); color: var(--on-accent); }

.card__body { padding: 20px 20px 22px; display: flex; flex-direction: column; flex: 1; }
.card__title { font-family: var(--font-display); font-size: 1.12rem; font-weight: 700; margin: 0 0 6px; line-height: 1.3; }
.card__title a:hover { color: var(--accent-text); }
.card__meta { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.card__short { font-size: .875rem; color: var(--gray); margin: 0 0 14px; }
.card__foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.price { font-size: 1.22rem; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; color: var(--ink); }
.price small { font-size: .76rem; font-weight: 500; color: var(--gray); display: block; letter-spacing: 0; }

/* One product promoted out of the grid: bigger frame, copy sitting over the
   image rather than under it, so the section has a focal point. */
.card--feature { grid-column: span 2; grid-row: span 2; position: relative; }
.card--feature .card__media { aspect-ratio: auto; flex: 1; min-height: 320px; }
.card--feature .card__body {
  position: absolute; inset: auto 0 0 0;
  background: linear-gradient(to top, rgba(33, 59, 137, .94), rgba(33, 59, 137, 0));
  color: #fff; padding: 34px 26px 24px;
}
.card--feature .card__title { font-size: clamp(1.4rem, 2.4vw, 1.95rem); }
.card--feature .card__title a { color: #fff; }
.card--feature .card__short { color: rgba(255, 255, 255, .82); }
.card--feature .price { color: #fff; }
.card--feature .price small { color: rgba(255, 255, 255, .72); }
.card--feature .stars { color: rgba(255, 255, 255, .88); }
.card--feature .btn--ghost { border-color: rgba(255, 255, 255, .6); color: #fff; }
.card--feature .btn--ghost:hover { background: #fff; border-color: #fff; color: var(--ink); }
@media (max-width: 1000px) { .card--feature { grid-column: span 2; grid-row: span 1; } }

/* ---------- editorial spotlight (New Arrivals / Special Offers) ---------- */
/* A listing promoted above the ordinary cards, with the supplied lifestyle
   photograph beside the copy rather than a product cut-out: on these two pages
   the photograph is the argument. Still the white box the shop uses, so the
   pages read as part of the shop rather than as a campaign microsite.

   The media column is the wider of the two because the photographs are 2:1 —
   a narrow column would crop the wing tips off both sides. */
.spot { display: grid; grid-template-columns: 1.32fr 1fr;
  background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; }
.spot + .spot { margin-top: 28px; }
.spot__media { position: relative; background: var(--bg-alt); }
.spot__media picture { display: contents; }
.spot__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* A product photograph is square on white, not a 2:1 lifestyle shot. Letterbox
   it into the column instead of cropping, or the hem of the cape is cut off. */
.spot__media--flat { display: grid; place-items: center; background: var(--white); }
.spot__media--flat img { object-fit: contain; padding: clamp(16px, 3vw, 40px); }
.spot__flag { position: absolute; left: 14px; top: 14px;
  background: var(--ink); color: #fff; font-size: .66rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; padding: 6px 10px;
  border-radius: var(--radius); }
.spot__flag--offer { background: var(--accent); color: var(--on-accent); }
.spot__body { padding: clamp(24px, 3.2vw, 42px); display: flex; flex-direction: column; }
.spot__body .eyebrow { margin-bottom: 10px; }
.spot__title { margin: 0 0 14px; font-size: clamp(1.45rem, 2.3vw, 1.95rem); line-height: 1.18; }
.spot__copy { margin: 0 0 20px; color: var(--ink-soft); font-size: .96rem; line-height: 1.62; }
.spot__list { list-style: none; margin: 0 0 22px; padding: 0; display: grid; gap: 8px;
  font-size: .9rem; color: var(--ink-soft); }
.spot__list li { position: relative; padding-left: 18px; }
.spot__list li::before { content: ""; position: absolute; left: 0; top: .58em;
  width: 7px; height: 7px; background: var(--gold); }
.spot__meta { margin-bottom: 18px; }
.spot__foot { margin-top: auto; display: flex; align-items: center; flex-wrap: wrap; gap: 14px;
  padding-top: 18px; border-top: 1px solid var(--line); }
.spot__price { font-size: 1.32rem; font-weight: 800; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; }
.spot__price small { display: block; font-size: .72rem; font-weight: 500;
  letter-spacing: 0; color: var(--gray); }
.spot__ctas { display: flex; flex-wrap: wrap; gap: 10px; margin-left: auto; }
@media (max-width: 900px) {
  .spot { grid-template-columns: 1fr; }
  .spot__media img { aspect-ratio: 2 / 1; height: auto; }
  .spot__ctas { margin-left: 0; }
}
@media (max-width: 620px) { .card--feature { grid-column: span 1; } }

/* ---------- product detail ---------- */
.pdp { display: grid; grid-template-columns: 1.08fr .92fr; gap: 54px; padding-top: 44px; padding-bottom: 70px; }
/* The right column is the long one: the Amazon bullets run to roughly 1,800px
   against a 595px square gallery, so on 44 of the 50 listings the left half was
   a blank white column for most of the scroll. Pinning the gallery keeps it
   beside whatever part of the copy is on screen.

   `align-self: start` is what makes it possible — grid stretches its items to
   the row by default, and a stretched item has nowhere to stick. Two columns
   only: stacked, the gallery would pin itself over the copy underneath. */
@media (min-width: 901px) { .pdp__media { position: sticky; top: 88px; align-self: start; } }
@media (max-width: 900px) { .pdp { grid-template-columns: 1fr; gap: 32px; } }

.gallery__main { border-radius: var(--radius); overflow: hidden; background: #fff; aspect-ratio: 1 / 1; }
/* contain, not cover: the listing's gallery mixes squares with tall and wide
   infographics whose copy is part of the pixels, and cover would crop it. On a
   white card the letterboxing is invisible. */
.gallery__main img { width: 100%; height: 100%; object-fit: contain; }
.gallery__thumbs { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.gallery__thumbs button {
  width: 76px; height: 76px; padding: 0; border: 1px solid var(--line);
  border-radius: var(--radius-sm); overflow: hidden; cursor: pointer; background: #fff;
}
.gallery__thumbs button[aria-selected="true"] { border-color: var(--ink); border-width: 2px; }
.gallery__thumbs img { width: 100%; height: 100%; object-fit: cover; }

.pdp__title { font-family: var(--font-display); font-size: clamp(1.7rem, 2.8vw, 2.35rem); font-weight: 800; margin-bottom: 10px; }
.pdp__price { display: flex; align-items: baseline; gap: 12px; margin: 18px 0 6px; }
.pdp__price .price { font-size: 1.9rem; }
.pdp__unit { font-size: .9rem; color: var(--green); font-weight: 700; }

.pdp__bullets { list-style: none; padding: 0; margin: 22px 0; }
.pdp__bullets li { position: relative; padding-left: 26px; margin-bottom: 11px; font-size: .96rem; color: var(--ink-soft); }
.pdp__bullets li::before {
  content: ""; position: absolute; left: 4px; top: .55em;
  width: 8px; height: 8px;
  background: var(--accent);
}

.warn {
  background: #fff6f4;
  border: 1px solid #f2d5d0;
  border-left: 4px solid var(--warn);
  border-radius: var(--radius-sm);
  padding: 12px 15px;
  font-size: .84rem;
  color: #9c2a1c;
  margin-bottom: 14px;
}
.warn + .warn { margin-top: -6px; }

.buybox { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 22px; box-shadow: var(--shadow); }
.buybox__actions { display: grid; gap: 10px; margin: 6px 0 4px; }
.buybox__ship { font-size: .84rem; color: var(--gray); text-align: center; margin: 12px 0 0; }

.trust { list-style: none; padding: 0; margin: 18px 0 0; display: grid; gap: 9px; }
.trust li { display: flex; gap: 9px; align-items: flex-start; font-size: .85rem; color: var(--ink-soft); }
.trust svg { flex: none; margin-top: 3px; }
.trust a { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }

/* ---------- scene pages: pack table, tier, group header ---------- */
.packtable { width: 100%; border-collapse: collapse; background: var(--white); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
.packtable th, .packtable td { padding: 15px 18px; text-align: left; border-bottom: 1px solid var(--line); font-size: .95rem; }
.packtable th { background: var(--ink); color: #fff; font-size: .7rem; text-transform: uppercase; letter-spacing: .09em; font-weight: 700; }
.packtable tr:last-child td { border-bottom: 0; }
.packtable td:last-child b { font-size: 1.12rem; font-variant-numeric: tabular-nums; color: var(--ink); }
.packtable a:hover { color: var(--accent-text); }
.packtable td:nth-child(2), .packtable td:nth-child(3), .packtable td:nth-child(4) { white-space: nowrap; }
/* Four columns of 36px cell padding alone overflow a phone, so the gutters and
   type shrink before the table is allowed to push the page sideways. */
@media (max-width: 640px) {
  .packtable th, .packtable td { padding: 12px 9px; font-size: .84rem; }
  .packtable th { font-size: .62rem; letter-spacing: .04em; }
  .packtable td:last-child b { font-size: 1rem; }
}
/* A 320px screen (original iPhone SE) still had the table 7px over, so the
   gutters come in again rather than the page going sideways. */
@media (max-width: 420px) {
  .packtable th, .packtable td { padding: 11px 6px; font-size: .78rem; }
  .packtable th { font-size: .58rem; letter-spacing: .02em; }
  .packtable td:last-child b { font-size: .92rem; }
}

.tier + .tier { margin-top: 46px; }
.tier__hd { display: flex; align-items: baseline; gap: 14px; margin-bottom: 20px; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.tier__hd h3 { margin: 0; }
.tier__hd span { font-size: .86rem; }

.grouphd { display: grid; grid-template-columns: 1fr 1fr; gap: 20px 40px; align-items: end; margin-bottom: 26px; padding-bottom: 16px; border-bottom: 2px solid var(--ink); }
.grouphd__title { margin: 0; }
.grouphd__note { margin: 0; font-size: .92rem; color: var(--ink-soft); }
@media (max-width: 720px) { .grouphd { grid-template-columns: 1fr; gap: 8px; align-items: start; } }

/* ---------- stat row ---------- */
.statrow { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-bottom: 30px; }
.statrow div { border-top: 2px solid var(--ink); padding-top: 14px; }
.statrow b { display: block; font-family: var(--font-display); font-size: clamp(1.8rem, 3.2vw, 2.4rem); font-weight: 800; line-height: 1; letter-spacing: -.03em; color: var(--ink); }
.statrow span { font-size: .84rem; color: var(--gray); }
.statrow__star { font-family: var(--font); font-size: .7em; color: var(--gold); vertical-align: .12em; }
@media (max-width: 620px) { .statrow { grid-template-columns: repeat(2, 1fr); } }

/* ---------- rating chart ---------- */
.rchart-wrap { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 28px 26px 20px; box-shadow: var(--shadow); }
.rchart__legend { display: flex; gap: 20px; flex-wrap: wrap; font-size: .82rem; color: var(--gray); margin-bottom: 22px; }
.rchart__legend span { display: inline-flex; align-items: center; gap: 7px; }
.rchart__dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.rchart__dot--superhero { background: var(--series-1); }
.rchart__dot--wings { background: var(--series-2); }
.rchart__dot--dinosaur { background: var(--series-3); }
.rchart__dot--sea { background: var(--series-4); }

.rchart { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.rchart__row { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(60px, 2.3fr) 168px; gap: 16px; align-items: center; }
.rchart__name { font-size: .88rem; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rchart__name:hover { color: var(--accent-text); }
.rchart__track { height: 9px; background: #f0ebdf; overflow: hidden; }
.rchart__bar { display: block; height: 100%; }
.rchart__bar--superhero { background: var(--series-1); }
.rchart__bar--wings { background: var(--series-2); }
.rchart__bar--dinosaur { background: var(--series-3); }
.rchart__bar--sea { background: var(--series-4); }
.rchart__num { display: inline-flex; align-items: center; gap: 8px; font-size: .82rem; color: var(--ink-soft); justify-content: flex-end; font-variant-numeric: tabular-nums; }
.rchart__num b { font-weight: 700; color: var(--ink); }
.rchart__more { margin: 24px 0 0; text-align: center; }
.rchart__more a {
  display: inline-flex; align-items: center; gap: 6px;
  padding-bottom: 3px; border-bottom: 1px solid var(--ink);
  font-size: .92rem; font-weight: 700; color: var(--ink);
}
.rchart__more a:hover { color: var(--accent-text); border-color: var(--accent-text); }

@media (max-width: 760px) {
  .rchart__row { grid-template-columns: 1fr auto; gap: 8px 12px; }
  .rchart__track { grid-column: 1 / -1; order: 3; }
  .rchart__num .stars__svg { display: none; }
}

/* ---------- scroll reveal ----------
   .js is set inline in <head>, so with JavaScript off nothing is ever hidden.
   The entrance is a transition rather than a keyframe: an element sitting just
   below the fold is the common case, and it should slide up, not pop. */
.js [data-reveal] { opacity: 0; transform: translateY(20px); }
.js [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity .7s cubic-bezier(.2, .7, .3, 1), transform .7s cubic-bezier(.2, .7, .3, 1);
  transition-delay: var(--d, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; }
  html { scroll-behavior: auto; }
}

/* ---------- tables / size guide ---------- */
.sizes { width: 100%; border-collapse: collapse; background: var(--white); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
.sizes th, .sizes td { padding: 13px 16px; text-align: left; font-size: .92rem; border-bottom: 1px solid var(--line); }
.sizes th { background: var(--ink); color: #fff; font-weight: 700; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; }
.sizes tr:last-child td { border-bottom: 0; }
.sizes td:first-child { font-weight: 700; color: var(--ink); }

/* ---------- listing detail: specs table + A+ modules ---------- */
/* Two-column label/value rather than the size guide's header row: these are
   scraped key-value pairs of varying count, and a dark header would imply a
   column structure the data does not have. */
.specs { width: 100%; border-collapse: collapse; background: var(--white); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
.specs th, .specs td { padding: 13px 16px; text-align: left; font-size: .92rem; border-bottom: 1px solid var(--line); vertical-align: top; }
.specs th { width: 40%; font-weight: 700; color: var(--ink); }
.specs td { color: var(--ink-soft); }
.specs tr:last-child th, .specs tr:last-child td { border-bottom: 0; }
@media (max-width: 520px) { .specs th { width: 46%; } .specs th, .specs td { padding: 11px 13px; font-size: .87rem; } }

.aplus { display: grid; gap: 16px; }
.aplus img { width: 100%; height: auto; display: block; border-radius: var(--radius-sm); }

/* ---------- line cards ---------- */
/* A flat opacity over the photo left white copy sitting on bright satin with
   almost no contrast. The scrim does the work instead, and the image keeps its
   colour everywhere the text is not. */
.linecard { position: relative; border-radius: var(--radius); overflow: hidden; background: var(--ink); color: #fff; aspect-ratio: 5 / 6; display: flex; align-items: flex-end; }
/* 50% 42% keeps heads and masks in frame — the sources are square, so a
   centre crop clips exactly the part of a costume people look at first. */
.linecard img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 42%; transition: transform .5s ease; }
.linecard::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(33, 59, 137, .95) 4%, rgba(33, 59, 137, .78) 30%,
    rgba(33, 59, 137, .28) 58%, rgba(33, 59, 137, 0) 78%);
}
.linecard:hover img { transform: scale(1.05); }
.linecard__body { position: relative; z-index: 1; padding: 30px 28px; }
.linecard__body h3 { font-size: 1.45rem; margin-bottom: 6px; color: #fff; }
.linecard__body p { font-size: .9rem; opacity: .88; margin: 0; }

/* ---------- faq ---------- */
.faq { max-width: 800px; margin: 0 auto; }
.faq details { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-sm); margin-bottom: 10px; padding: 4px 20px; }
.faq summary { cursor: pointer; font-weight: 700; color: var(--ink); padding: 15px 0; list-style: none; display: flex; justify-content: space-between; gap: 16px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent-text); font-size: 1.3rem; line-height: 1; }
.faq details[open] summary::after { content: "–"; }
.faq details p { font-size: .93rem; color: var(--ink-soft); margin: 0 0 16px; }

/* ---------- signup (footer only) ---------- */
/* This used to be a navy panel in the middle of the homepage. The reference
   site puts its newsletter in the footer, and so do we now: one form, on every
   page, instead of a second copy competing with it. Nothing here paints its own
   background — it sits directly on the footer's navy. */
.signup--footer { margin: 0 0 30px; padding: 0; }
.signup h2 { color: #fff; font-size: 1.32rem; margin-bottom: 10px; }
.signup p { color: rgba(255,255,255,.72); font-size: .9rem; margin: 0 0 16px; max-width: 44ch; }
.signup form { display: flex; gap: 8px; max-width: 420px; }
.signup input {
  flex: 1; padding: 13px 16px; border-radius: var(--radius); border: 0;
  font: inherit; font-size: .92rem; min-width: 0; color: var(--gray);
}
.signup input:focus { outline: 3px solid var(--gold); }
.signup .btn--primary { color: var(--on-accent); }
.signup__thanks { font-weight: 700; color: var(--gold); margin: 0; }
@media (max-width: 560px) { .signup form { flex-direction: column; } }

/* ---------- collection header ---------- */
.collhead { background: var(--bg-alt); padding: 54px 0 44px; }

/* ---------- footer ---------- */
.footer { background: var(--ink); color: rgba(255,255,255,.74); padding: 58px 0 26px; margin-top: 40px; font-size: .9rem; }
/* Three columns, mirroring the reference: a wide lead column carrying the
   newsletter and the brand copy, then two link columns. */
.footer__grid { display: grid; grid-template-columns: 2.1fr 1fr 1fr; gap: 44px; }
.footer__lead { max-width: 460px; }
.footer__logo { margin-bottom: 10px; }
/* The tagline runs under the name in the footer rather than beside it: the
   header hides it below 1180px, and a single line repeated in two places at two
   sizes reads as a mistake. */
.footer__tagline { color: var(--lime); font-size: .74rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; margin-bottom: 14px; }
@media (max-width: 860px) { .footer__grid { grid-template-columns: 1fr 1fr; gap: 30px; } .footer__lead { grid-column: 1 / -1; } }
@media (max-width: 520px) { .footer__grid { grid-template-columns: 1fr; } }
.footer h4 { color: #fff; font-size: .74rem; text-transform: uppercase; letter-spacing: .12em; margin-bottom: 14px; font-weight: 700; }
.footer a { display: block; padding: 5px 0; }
.footer a:hover { color: var(--gold); }
.footer .logo { color: #fff; margin-bottom: 12px; }
.footer__bottom { border-top: 1px solid rgba(255,255,255,.16); margin-top: 36px; padding-top: 20px; display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; font-size: .82rem; }
.footer__note { color: rgba(255,255,255,.5); font-size: .8rem; max-width: 60ch; margin-top: 10px; }

/* ---------- misc ---------- */
.pillrow { display: flex; flex-wrap: wrap; gap: 9px; margin-bottom: 26px; }
.pill {
  padding: 9px 16px; border-radius: var(--radius); border: 1px solid var(--line);
  background: var(--white); font-size: .78rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; cursor: pointer; color: var(--ink-soft);
}
.pill:hover { border-color: var(--ink); color: var(--ink); }
.pill[aria-pressed="true"] { background: var(--ink); color: #fff; border-color: var(--ink); }

.crumbs { font-size: .84rem; color: var(--gray); padding: 18px 0 0; }
.crumbs a:hover { color: var(--ink); }
.crumbs span { margin: 0 7px; }

.toast {
  position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 120%);
  background: var(--ink); color: #fff; padding: 13px 22px; border-radius: var(--radius);
  font-size: .9rem; font-weight: 600; box-shadow: var(--shadow-lg); z-index: 100;
  transition: transform .28s cubic-bezier(.2,.9,.3,1.2);
}
.toast.is-on { transform: translate(-50%, 0); }

.prose { max-width: 68ch; }
.prose h2 { margin-top: 1.6em; }
.prose ul { padding-left: 20px; color: var(--ink-soft); }
.prose li { margin-bottom: .5em; }
/* Inline links inherit the body colour site-wide, which left the few links in
   policy and contact copy looking like plain text. Underline them. */
.prose a { text-decoration: underline; text-underline-offset: 3px; }
.prose a:hover { text-decoration-thickness: 2px; }

.note-box { background: var(--bg-alt); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 18px 20px; font-size: .92rem; }

/* --- brand story (About) --------------------------------------------------
   The one page that gets read rather than scanned, so it runs at a different
   rhythm from the product pages: a wide lede, the belief line pulled out as a
   quote, then the three role lines — courage, freedom, a new world — listed in
   the same order as the three shapes we sell. */
.story { max-width: 72ch; margin-bottom: 54px; }
.story__lede { font-size: 1.16rem; color: var(--ink-soft); }
.story__belief {
  margin: 30px 0; padding: 2px 0 2px 26px; border-left: 3px solid var(--accent);
  font-size: 1.5rem; line-height: 1.35; font-weight: 700; color: var(--ink);
}
.story__roles, .signoff__chances { list-style: none; padding: 0; margin: 0; }
.story__roles { display: grid; gap: 10px; }
.story__roles li { position: relative; padding-left: 26px; color: var(--ink-soft); }

/* The signoff sits on navy rather than in the footer, because the tagline is the
   last thing the reader should leave with and a footer line reads as boilerplate. */
.signoff {
  margin-top: 56px; padding: 40px 36px; border-radius: var(--radius);
  background: var(--ink); color: #fff;
}
.signoff__line { font-size: 1.36rem; line-height: 1.35; font-weight: 700; margin: 0 0 22px; }
.signoff__chances { display: grid; gap: 8px; margin-bottom: 28px; }
.signoff__chances li { position: relative; padding-left: 26px; color: rgba(255, 255, 255, .88); }
.signoff__note { color: rgba(255, 255, 255, .88); margin: 0 0 28px; }
.signoff__name { font-weight: 800; letter-spacing: .06em; margin: 0; }
.signoff__tagline {
  margin: 6px 0 0; font-size: .8rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--lime);
}
.story__roles li::before, .signoff__chances li::before {
  content: ""; position: absolute; left: 0; top: .68em; width: 11px; height: 2px;
}
.story__roles li::before { background: var(--accent); }
/* Lime on navy is 8.66:1; --accent there would be 3.1:1, fine for a rule but not
   for the only marker on a line of body copy. */
.signoff__chances li::before { background: var(--lime); }

@media (max-width: 640px) {
  .story__belief { font-size: 1.24rem; padding-left: 18px; }
  .signoff { padding: 30px 22px; }
  .signoff__line { font-size: 1.16rem; }
}

/* The same belief line again on the homepage, this time as a full-width navy
   interruption between the stats and the spec sheet. It is deliberately the
   only place on the homepage that stops selling and states a position — the
   stats above prove the scale, this says why we bother. */
.storyband { background: var(--ink); color: #fff; }
.storyband__grid {
  display: grid; grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
  gap: clamp(28px, 4.5vw, 64px); align-items: center;
}
.storyband__media img {
  display: block; width: 100%; height: auto; border-radius: 18px;
  box-shadow: 0 18px 42px rgba(0, 0, 0, .3);
}
.storyband__body { text-align: left; }
.storyband .eyebrow { color: var(--lime); }
.storyband__quote {
  font-size: clamp(1.45rem, 3.1vw, 2.1rem); line-height: 1.3;
  font-weight: 800; margin: 0 0 20px;
}
/* The lede runs above the quote, not below it: it ends on a colon that the
   quote answers, so the 16px gap here is deliberately tighter than the 28px
   below — the two lines read as one thought. */
.storyband__lead { color: rgba(255, 255, 255, .88); margin: 0 0 16px; max-width: 56ch; }
.storyband__roles {
  list-style: none; padding: 0; margin: 0 0 32px;
  display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 10px 30px;
}
.storyband__roles li { position: relative; padding-left: 20px; font-size: .95rem; color: rgba(255, 255, 255, .88); }
.storyband__roles li::before {
  content: ""; position: absolute; left: 0; top: .7em; width: 9px; height: 2px; background: var(--lime);
}

@media (max-width: 880px) {
  .storyband__grid { grid-template-columns: 1fr; }
  .storyband__media { max-width: 560px; margin: 0 auto; }
}
