/* =====================================================================
   /shop/ : the KEEP CALM shop.

   Self contained on purpose. The layout studies at /shop-directions-v2/ are a
   review artifact and will be deleted; the production shop must not depend on
   a directory that is going away, so the primitives it needs are here rather
   than imported from kc-shop-studies.css. The comments that travelled with
   those primitives came too, because each one records a bug that a fresh pair
   of eyes would otherwise reintroduce.

   EVERY COLOR IS A --wt-* TOKEN. No hex literals anywhere in this file. That
   is what makes the nav's own light/dark button drive the whole shop with no
   extra code, and it is only true while the shop body sits inside .wt-shell,
   where the dark values are defined.
   ===================================================================== */

.kcshop { font-family: var(--wt-font-body); color: var(--wt-ink); }
.kcshop *, .kcshop *::before, .kcshop *::after { box-sizing: border-box; }

/* THE BROWSER'S OWN figure MARGIN IS THE TRAP, and it is worth naming because
   it cost a whole verification pass on the studies. A <figure> carries
   margin-inline: 40px from the user agent stylesheet, so every tile built as a
   figure rendered 80px narrower than its grid cell: 67px of picture inside a
   147px column, at a perfectly correct 2:3. A ratio check cannot catch that,
   because the ratio is right and only the SIZE is wrong. */
.kcshop figure, .kcshop dl, .kcshop dd, .kcshop blockquote { margin: 0; }
.kcshop h1, .kcshop h2, .kcshop h3 { font-family: var(--wt-font-display); color: var(--wt-ink); margin: 0; text-wrap: balance; }
.kcshop ul { list-style: none; margin: 0; padding: 0; }

/* Anything the runtime draws must be styled here, not in a page. Studies once
   styled their own link color, which covered the server-rendered rows and
   missed every row drawn after the data loaded: those fell back to the browser
   default #0000ee, a 1.96 contrast ratio on dark, failing WCAG outright. */
.kcshop a { color: var(--kcshop-link, var(--wt-link)); }

.kcshop-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.kcshop :focus-visible { outline: 3px solid var(--wt-focus); outline-offset: 2px; border-radius: 4px; }

/* ---------------------------------------------------------------------
   IMAGES: the ratio travels with the image, never with the container.
   Every lifestyle frame is exactly 2:3 (1024x1536 or 1600x2400 at source,
   served at 900x1350 and 450x675). Garment and poster product shots from the
   print partner are 1:1.
   --------------------------------------------------------------------- */
.kcshop-img { display: block; width: 100%; height: 100%; background: var(--wt-chip-bg); }
/* display:block IS LOAD-BEARING. The frame is often a <span> inside a link,
   where a <div> would be invalid HTML, and aspect-ratio does not apply to a
   non-replaced INLINE box: without this the frame collapses to its content
   width and the tile renders 67px wide at a perfectly correct ratio. */
.kcshop-frame {
  display: block; overflow: hidden; background: var(--wt-chip-bg);
  border-radius: 14px; aspect-ratio: 2 / 3;
}
.kcshop-frame > .kcshop-img { object-fit: cover; object-position: center top; }
/* A poster's product shot is a SQUARE photograph of a print hanging on white,
   and the print itself only occupies the middle of it. Letterboxing that square
   into a 3:4 tile with object-fit:contain left a third of every poster tile as
   empty panel under a small white square, which in dark mode read as a bright
   block floating above a hole.

   Cover instead. A 1:1 source in a 3:4 box scales to the box's HEIGHT exactly,
   so nothing is cropped vertically and the clips at the top survive; the only
   thing trimmed is 12.5% of white margin off each side, which the print never
   reaches. The tile fills, the poster gets bigger, and the ratio is still
   declared on the image rather than left to the container. */
.kcshop-frame--poster { aspect-ratio: 3 / 4; background: var(--wt-paper); }
.kcshop-frame--poster > .kcshop-img { object-fit: cover; object-position: center; }

/* ---------------------------------------------------------------------
   FULL WIDTH. The shell carries .wt-shell--musicwide, exactly as /music/,
   /games/ and /posters/ do, so the page runs edge to edge and the masthead
   re-constrains itself. The old break-out (negative inline margins plus the
   page background repainted underneath) is gone: it was a second way of doing
   something the site already had one way of doing, and it was the reason the
   rail had to paint its own background to hide a seam.
   --------------------------------------------------------------------- */
.kcshop .am-layout { align-items: flex-start; }

/* ---------------------------------------------------------------------
   THE LEFT RAIL IS .am-side, THE SITE'S RAIL.

   Kaʻo, 2026-08-20: "I asked that the Shop have the same left nav as /music/,
   /games/, /posters/ - what you did does not look or act like that... search
   exposed as opposed to going to dedicated page. Not in same background color
   - as a container - as a collapsable module."

   All three of those are one cause: the shop had its OWN rail, .kcshop-side,
   which was a column of rows with no panel around it. Everything that made the
   others read as a module (the surface, the hairline closing all four sides,
   the sticky offset, the section headings, the collapse toggle) lived in
   v17.css and kc-rail-toggle.css and was never loaded here.

   So the shop loads those two files and writes .am-side markup, and every rule
   the old rail carried is deleted rather than reimplemented. What is left
   below is only what the shop has and the other rails do not: a count on a
   row, price bands, and 52 color swatches.
   --------------------------------------------------------------------- */
.kcshop .am-side { }
/* The count sits at the end of a row and disappears with the words when the
   rail collapses to an icon strip. Without this it stayed, and a 72px strip
   showed a bare "293" beside an icon. */
/* v17 gives .am-side__nav `flex: 1 1 auto` so a music rail's playlist list
   fills the panel. The shop hangs its color swatches BELOW the nav, so that
   grow pushed them to the bottom of the drawer with a hole under the COLOR
   heading. The shop's nav is its natural height and the swatches sit under
   their own label. */
.kcshop .am-side__nav { flex: 0 0 auto; }

.kcshop-n {
  margin-inline-start: auto; font-weight: 400; color: var(--mus-ink-quiet);
  font-variant-numeric: tabular-nums; font-size: 13px;
  transition: opacity 110ms ease;
}
html.kc-rail-collapsed .kcshop-n { opacity: 0; }
/* A FACET THAT WOULD RETURN NOTHING IS NOT A LINK, IT IS A DEAD END.
   Disabled rather than hidden, so the panel does not reflow every time a
   filter changes and the shopper can see what is not available. */
.kcshop .am-side [aria-disabled="true"] { opacity: .42; cursor: not-allowed; }
.kcshop .am-side [aria-disabled="true"]:hover { background: none; }
/* A pressed filter reads like the page you are on, because that is what it is:
   the rail's own statement of what is narrowing the grid. v17.css styles
   [aria-current="page"] for links; a filter is a button and says it with
   aria-pressed, so it needs the same treatment written out. */
.kcshop .am-side__nav [aria-pressed="true"] {
  background: var(--am-active, var(--mus-surface-2)); color: var(--mus-accent); font-weight: 600;
}
.kcshop .am-side__nav [aria-pressed="true"] .kcshop-n { color: var(--mus-accent); }

/* ---------------------------------------------------------------------
   COLOR SWATCHES. There are 52 real garment colors, every one sampled from the
   print partner's own mockup, so a stacked list of 52 rows would be longer than
   the rest of the rail put together. A grid says the same thing in nine rows
   and lets the eye run the hue ramp, which is the Nike treatment and is simply
   better at this count.
   --------------------------------------------------------------------- */
.kcshop-swatches {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(38px, 1fr));
  gap: 6px; padding: 6px 10px 4px;
}
.kcshop-swatch {
  position: relative; width: 100%; aspect-ratio: 1; min-height: 34px;
  border-radius: 50%; border: 0; padding: 0; cursor: pointer;
  /* The ring rides on every dot, not only the pale ones, so no swatch reads as
     a different shape from its neighbours. */
  box-shadow: inset 0 0 0 1px var(--wt-rule-strong);
  background: var(--kcshop-swatch);
}
.kcshop-swatch:hover { box-shadow: inset 0 0 0 1px var(--wt-rule-strong), 0 0 0 2px var(--wt-chip-bg); }
.kcshop-swatch[aria-pressed="true"] { box-shadow: inset 0 0 0 1px var(--wt-rule-strong), 0 0 0 3px var(--wt-accent); }
.kcshop-swatch[aria-pressed="true"]::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 9px; height: 5px;
  border-inline-start: 2px solid var(--wt-surface); border-block-end: 2px solid var(--wt-surface);
  transform: rotate(-45deg) translate(1px, -2px); mix-blend-mode: difference;
}

/* ---------------------------------------------------------------------
   THE MAIN COLUMN
   --------------------------------------------------------------------- */
.kcshop-main { flex: 1 1 auto; min-width: 0; padding: 0 clamp(18px, 2.4vw, 36px) 60px; }

/* THE BANDS COME IN FROM BOTH EDGES (Kaʻo, 2026-08-19): "have the right and
   left edges come in. They should not be at the edge." A full-bleed layout put
   the membership band and the ID.me band hard against the viewport on the
   right, so their rounded corners were clipping the window. They now carry
   their own inset on top of the column's padding, which reads as a contained
   panel rather than as a strip that ran out of page. */
.kcshop-band, .kcshop-heroes { margin-inline: clamp(0px, 2.2vw, 40px); }

.kcshop-sec { padding-block-end: 56px; }
.kcshop-sec__h {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 18px;
}
.kcshop-sec__h h2 { font-size: clamp(20px, 2.4vw, 27px); letter-spacing: -.01em; }
.kcshop-sec__h p { margin: 4px 0 0; color: var(--wt-ink-soft); font-size: 14.5px; }
.kcshop-eyebrow {
  font: 700 11px var(--wt-font-ui); letter-spacing: .1em; text-transform: uppercase;
  color: var(--wt-eyebrow); margin: 0 0 6px;
}

/* ---------------------------------------------------------------------
   THE HERO. The lockup, not a sentence: KEEP CALM, a small AND on the same
   baseline, then the line. The ratio is .552em at weight 700 with .05em
   tracking, which is exactly what .kc-footer__and uses, so the shop's lockup
   and the footer's are the same lockup rather than two that nearly agree.
   --------------------------------------------------------------------- */
/* THE PICTURE WAS HARD AGAINST THE TOP OF THE PAGE. Kaʻo, 2026-08-20: "Image
   on right too tight to the top... looks unprofessional. Move down to have
   same alignment of left menu top alignment. Don't lose the fact that we have
   space below the big image for padding - keep that."

   Measured before: the figure's top was y=61, the same pixel as the rail's
   border box and the main column's, with nothing else on that line, so it read
   as an image that had run out of page. The page header now opens the column
   and the hero starts under it, which puts the picture on the same line the
   rail's first module starts on. The 54px under it is untouched, because that
   is the part he asked to keep. */
.kcshop-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .84fr); gap: 46px; align-items: stretch; padding: 0 0 54px; }
.kcshop-hero__c { display: flex; flex-direction: column; justify-content: center; padding-block: 8px 40px; min-width: 0; }
.kcshop-hero__h {
  font-weight: 800; letter-spacing: -.03em; line-height: .96; margin: 10px 0 20px;
  font-size: clamp(34px, 5.4vw, 78px); text-transform: uppercase;
}
/* THE LOCKUP CANNOT BREAK. "KEEP CALM" and its small "and" are one unit; left
   to wrap, the headline arrived as three lines with AND stranded alone on the
   second. The nowrap is on the pair, not on the whole headline, so the phrase
   after it still wraps freely. */
.kcshop-lock { white-space: nowrap; }
.kcshop-and { font-size: .552em; font-weight: 700; letter-spacing: .05em; margin-inline-start: .16em; }
.kcshop-hero__p { font-size: 17px; color: var(--wt-ink-soft); line-height: 1.6; max-width: 46ch; margin: 0 0 26px; }
.kcshop-hero__btns { display: flex; gap: 12px; flex-wrap: wrap; }
/* A 2:3 portrait in a wide slot has to lose something. Centring it cropped the
   face, so the crop keeps the top and loses the floor, which is the call the
   home page hero already makes. */
.kcshop-hero__fig .kcshop-frame { aspect-ratio: auto; height: 100%; min-height: 500px; border-radius: 18px; }

/* Both buttons are primary: Shop women and Shop men are the same offer, and
   making one of them quiet implies a default that is not there. Raised to
   a.kcshop-btn so a container's own `a { color }` cannot repaint them. */
a.kcshop-btn, button.kcshop-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: 700 15px var(--wt-font-ui); text-decoration: none; padding: 15px 30px;
  border-radius: 999px; border: 0; cursor: pointer; min-height: 48px;
  background: var(--wt-btn-bg); color: var(--wt-btn-ink); transition: background 150ms ease;
}
a.kcshop-btn:hover, button.kcshop-btn:hover { background: var(--wt-btn-bg-hover); color: var(--wt-btn-ink); }
a.kcshop-btn--ghost, button.kcshop-btn--ghost {
  background: none; color: var(--wt-link); border: 1px solid var(--wt-rule-strong);
  padding: 11px 20px; min-height: 44px; font-size: 14px;
}
a.kcshop-btn--ghost:hover, button.kcshop-btn--ghost:hover { background: var(--wt-chip-bg); color: var(--wt-link-hover); }

/* ---------------------------------------------------------------------
   TILES. No container, no panel, no fill: the picture is the card, its corners
   are rounded, the words sit under it flush left, and the whole tile lifts on
   hover so the caption travels with it, exactly as the song and poster cards
   behave on /music/ and /posters/.
   --------------------------------------------------------------------- */
.kcshop-grid { display: grid; gap: 28px 18px; grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); }
.kcshop-rail {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(212px, 1fr); gap: 18px;
  overflow-x: auto; scroll-snap-type: x mandatory; padding-block: 10px 6px; margin-block: -10px 0;
  scrollbar-width: thin;
}
.kcshop-rail > * { scroll-snap-align: start; }

.kcshop-card { display: flex; flex-direction: column; gap: 9px; transition: transform 170ms ease; }
.kcshop-card:hover, .kcshop-card:focus-within { transform: translateY(-6px); }
.kcshop-card__link { display: block; border-radius: 14px; text-decoration: none; color: inherit; position: relative; }
/* The alternate frame is the same phrase on a different model or in a
   different place, revealed on hover. It is preloaded only on hover, so a
   phone that never hovers never downloads it. */
.kcshop-card__alt {
  position: absolute; inset: 0; opacity: 0; transition: opacity 220ms ease;
  border-radius: 14px; overflow: hidden;
}
.kcshop-card__link:hover .kcshop-card__alt, .kcshop-card__link:focus-visible .kcshop-card__alt { opacity: 1; }
.kcshop-card__link { display: flex; flex-direction: column; gap: 9px; }
.kcshop-card__body { display: flex; flex-direction: column; gap: 2px; }
/* ONE LINK PER CARD. The picture and the title used to be two separate links
   to the same product, so a screen reader announced every tile twice and a
   keyboard user pressed Tab twice to get past it. They are now one link that
   contains both, which also gives that link a real accessible name (the
   photograph's alt text plus the phrase) instead of relying on the image alt
   alone. The eye, heart and share row sits OUTSIDE it, because a link inside a
   link is invalid HTML. */
.kcshop .kcshop-card__title {
  font: 700 14px var(--wt-font-ui); color: var(--wt-ink); letter-spacing: .01em;
}
.kcshop-card__link:hover .kcshop-card__title { color: var(--wt-link-hover); text-decoration: underline; }
.kcshop-card__meta { font: 400 13px var(--wt-font-ui); color: var(--wt-ink-soft); }
.kcshop-card__also { font: 400 12.5px var(--wt-font-ui); color: var(--wt-ink-quiet); }
.kcshop-card__price { font-weight: 600; color: var(--wt-ink); font-variant-numeric: tabular-nums; }

/* A small solid badge is the ONLY thing allowed on top of a picture. Captions
   never sit over an image. */
.kcshop-badge {
  position: absolute; inset-block-start: 10px; inset-inline-start: 10px; z-index: 1;
  font: 700 10.5px var(--wt-font-ui); letter-spacing: .06em; text-transform: uppercase;
  background: var(--wt-btn-bg); color: var(--wt-btn-ink); padding: 5px 9px; border-radius: 6px;
}

.kcshop-actbar { display: flex; align-items: center; gap: 9px; margin-top: 3px; }
.kcshop-act {
  width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center;
  background: none; border: 1px solid var(--wt-rule); color: var(--wt-ink-soft);
  cursor: pointer; padding: 0; text-decoration: none;
  transition: border-color 140ms ease, color 140ms ease, background 140ms ease;
}
.kcshop-act svg { width: 17px; height: 17px; }
.kcshop-act:hover { border-color: var(--wt-accent); color: var(--wt-accent); background: var(--wt-chip-bg); }
.kcshop-act[aria-pressed="true"] { color: var(--wt-accent); border-color: var(--wt-accent); }
.kcshop-act[aria-pressed="true"] svg { fill: currentColor; }

@media (prefers-reduced-motion: reduce) {
  .kcshop-card, .kcshop-card__alt, a.kcshop-btn, .kcshop-act { transition: none; }
  .kcshop-card:hover, .kcshop-card:focus-within { transform: none; }
  .kcshop-rail { scroll-behavior: auto; }
}

/* ---------------------------------------------------------------------
   THE TOOLBAR above the results.
   --------------------------------------------------------------------- */
.kcshop-tools { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 22px; }
.kcshop-count { font: 500 14px var(--wt-font-ui); color: var(--wt-ink-soft); margin: 0; }
/* THE SORT CHEVRON CANNOT BE MOVED WITH PADDING. Without appearance:none the
   browser draws its OWN arrow at its own fixed offset and padding only moves
   the text. This is the product page's treatment copied deliberately rather
   than approximated, so the shop's sort control and the product page's Size
   and Color controls are visibly the same control. */
.kcshop-field {
  -webkit-appearance: none; appearance: none;
  padding: 11px 40px 11px 14px; border-radius: 9px; min-height: 44px;
  border: 1px solid var(--wt-rule-strong); background-color: var(--wt-surface);
  color: var(--wt-ink); font: 500 15px var(--wt-font-ui); cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235f6a60' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center;
}
html[data-mode="batman"] .wt-shell .kcshop-field {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23c2cabb' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
[dir="rtl"] .kcshop-field { padding: 11px 14px 11px 40px; background-position: left 14px center; }

/* Applied filters, so a shopper can always see and undo what is narrowing the
   grid. A filter you cannot see is a filter you cannot remove. */
.kcshop-applied { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 18px; }
.kcshop-applied:empty { display: none; }
.kcshop-pill {
  display: inline-flex; align-items: center; gap: 7px; min-height: 36px;
  font: 600 13px var(--wt-font-ui); color: var(--wt-chip-ink);
  background: var(--wt-chip-bg); border: 1px solid var(--wt-chip-border);
  border-radius: 999px; padding: 6px 8px 6px 14px; cursor: pointer;
}
.kcshop-pill:hover { border-color: var(--wt-accent); color: var(--wt-accent); }
.kcshop-pill svg { width: 14px; height: 14px; }
.kcshop-pill__dot { width: 14px; height: 14px; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--wt-rule-strong); }

.kcshop-empty { padding: 40px 0 20px; max-width: 46ch; }
.kcshop-empty h2 { font-size: 20px; margin-bottom: 8px; }
.kcshop-empty p { color: var(--wt-ink-soft); line-height: 1.6; margin: 0 0 16px; }

.kcshop-more { display: flex; justify-content: center; padding-block-start: 34px; }

/* ---------------------------------------------------------------------
   THE MEMBERSHIP BAND. It promotes the member discount with the three real
   tiers and a CTA that goes somewhere a shopper can act on, rather than back
   to the shop they are already standing in.
   --------------------------------------------------------------------- */
.kcshop-band {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .92fr);
  gap: 34px; align-items: center; border: 1px solid var(--wt-rule); border-radius: 18px;
  padding: 28px 32px; margin-bottom: 54px;
}
.kcshop-band h2 { font-size: clamp(20px, 2.4vw, 27px); letter-spacing: -.01em; }
.kcshop-band p { color: var(--wt-ink-soft); margin: 8px 0 18px; max-width: 52ch; line-height: 1.6; }
.kcshop-tier {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 11px 0; border-block-end: 1px solid var(--wt-rule);
}
.kcshop-tier:last-child { border-block-end: 0; }
.kcshop-tier__n { font: 600 14.5px var(--wt-font-ui); color: var(--wt-ink); }
.kcshop-tier__g { font: 400 13px var(--wt-font-ui); color: var(--wt-ink-quiet); }
.kcshop-tier__p { font: 800 19px var(--wt-font-ui); color: var(--wt-accent); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------
   THE ID.me OFFER. Same message and same faces as the home page, at a weight
   that does not compete with the merchandise. There is no CTA because there is
   nothing to click: eligibility is verified at checkout.
   --------------------------------------------------------------------- */
.kcshop-heroes {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 34px; align-items: center; border: 1px solid var(--wt-rule);
  border-radius: 18px; padding: 24px 28px; margin-block-end: 56px;
}
.kcshop-heroes__strip { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 6px; }
/* Full-body studio portraits at 2:3. Cropping them square cut their heads off,
   which is the one thing a portrait cannot lose, so the tile keeps the source
   ratio and nothing is cropped or squashed at all. */
.kcshop-heroes__ph { display: block; aspect-ratio: 2 / 3; overflow: hidden; border-radius: 10px; background: var(--wt-chip-bg); }
.kcshop-heroes__ph img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.kcshop-heroes h2 { font-size: clamp(20px, 2.4vw, 27px); letter-spacing: -.01em; margin: 0 0 8px; }
.kcshop-heroes p { color: var(--wt-ink-soft); font-size: 14.5px; line-height: 1.6; margin: 0 0 12px; max-width: 52ch; }
.kcshop-heroes__groups { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
.kcshop-heroes__groups li {
  font: 600 12px var(--wt-font-ui); color: var(--wt-ink-soft);
  border: 1px solid var(--wt-rule); border-radius: 7px; padding: 5px 10px;
}
.kcshop-heroes__verify { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.kcshop-heroes__verify img { height: 26px; width: auto; }
.kcshop-heroes__verify p { margin: 0; font-size: 13px; max-width: 44ch; }
html[data-mode="batman"] .wt-shell .kcshop-heroes__verify img { filter: invert(1) brightness(1.7); }

/* ---------------------------------------------------------------------
   CATEGORY PAGES. Nike's interior move is an editorial band that states the
   category at display size over one photograph, then gets out of the way and
   lets the grid do the selling. Ours keeps the KEEP CALM lockup rather than
   borrowing the type treatment.
   --------------------------------------------------------------------- */
.kcshop-cathero {
  position: relative; border-radius: 18px; overflow: hidden; margin-block-end: 34px;
  /* TALL ENOUGH TO KEEP A HEAD. The source is a 2:3 portrait and the band is
     roughly 2.6:1, so a short band shows a 25% slice of the picture and the
     first thing that slice loses is the face. Raising the band to about 2:1
     and starting the crop near the top keeps the face, the shoulders and the
     phrase on the chest, which is the whole reason the photograph is here. */
  min-height: clamp(320px, 40vw, 560px); display: grid; align-items: end;
  background: var(--wt-chip-bg);
}
.kcshop-cathero__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center 10%; }
/* THE SCRIM IS SIZED BY THE WORST CASE, not by how it looks over one picture.
   The copy is fixed white and the photograph underneath is whatever that
   category's best frame happens to be, so the only safe assumption is that the
   pixels behind the text are pure white. At .62 alpha a white photograph
   composites to rgb(97,97,97), which is 6.2:1 against white: AA for body text
   with room to spare, and every stop below the text block is darker still.
   The measured floor is published as data-kcshop-scrim so
   scripts/verify-shop.mjs checks the same number this comment claims. */
.kcshop-cathero__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(0, 0, 0, .90) 0%, rgba(0, 0, 0, .80) 32%, rgba(0, 0, 0, .62) 58%,
    rgba(0, 0, 0, .18) 84%, rgba(0, 0, 0, 0) 100%);
}
.kcshop-cathero__c { position: relative; padding: clamp(22px, 3vw, 40px); max-width: 42ch; }
/* Fixed white rather than a token: this copy sits on a photograph under a dark
   scrim in BOTH themes, so it must not follow the theme's ink color. Measured
   against the scrim's darkest stop, white is 14.6:1 here. */
.kcshop-cathero__c, .kcshop-cathero__c h2 { color: #ffffff; }
.kcshop-cathero__eyebrow { font: 700 11px var(--wt-font-ui); letter-spacing: .12em; text-transform: uppercase; color: #ffffff; opacity: .88; margin: 0 0 8px; }
.kcshop-cathero__c h2 { font-size: clamp(30px, 4.6vw, 62px); font-weight: 800; letter-spacing: -.025em; line-height: .98; text-transform: uppercase; }
.kcshop-cathero__c p { color: #ffffff; opacity: .9; font-size: 15.5px; line-height: 1.55; margin: 12px 0 0; }

/* NO PHOTOGRAPH, NO SCRIM, SO NO WHITE TYPE. When a category has no frame that
   honestly shows its garment the band carries type alone, and the fixed white
   above would then be white on cream: the Posters page shipped exactly that for
   one build and the heading was unreadable. Here the band goes back to theme
   tokens, which are contrast-checked in both themes. */
.kcshop-cathero--plain { min-height: 0; background: var(--wt-panel-bg); border: 1px solid var(--wt-panel-border); }
.kcshop-cathero--plain .kcshop-cathero__c { max-width: 56ch; padding-block: clamp(28px, 4vw, 52px); }
.kcshop-cathero--plain .kcshop-cathero__c,
.kcshop-cathero--plain .kcshop-cathero__c h2 { color: var(--wt-ink); }
.kcshop-cathero--plain .kcshop-cathero__eyebrow { color: var(--wt-eyebrow); opacity: 1; }
.kcshop-cathero--plain .kcshop-cathero__c p { color: var(--wt-ink-soft); opacity: 1; }

.kcshop-crumbs { font: 500 13px var(--wt-font-ui); margin: -10px 0 16px; color: var(--wt-ink-quiet); }
/* Padded to a real target height rather than left at the 16px a bare inline
   link measures. It is exempt from WCAG 2.2 target size as inline text, but a
   breadcrumb is the one link people hit on a phone to go back up. */
.kcshop-crumbs a { color: var(--wt-link); text-decoration: none; display: inline-block; padding: 6px 2px; min-height: 24px; }
.kcshop-crumbs a:hover { text-decoration: underline; }
.kcshop-crumbs span { padding: 0 6px; }

/* ---------------------------------------------------------------------
   MOBILE. Below 900px .am-side is already an off-canvas drawer with its own
   transform and its own scrim, because that is what it is on /music/ and
   /posters/. The shop supplies the button that opens it and the bar it sits
   in, and nothing else: the second drawer this file used to carry is gone.
   --------------------------------------------------------------------- */
.kcshop-filterbar { display: none; }

@media (max-width: 900px) {
  .kcshop-main { padding-inline: 16px; }
  .kcshop-band, .kcshop-heroes { margin-inline: 0; }
  .kcshop-pagehd { padding-block: 14px 6px; }

  .kcshop-filterbar {
    display: flex; align-items: center; gap: 10px; padding: 10px 16px;
    position: sticky; inset-block-start: 0; z-index: 6;
    background: var(--wt-page-bg); border-block-end: 1px solid var(--wt-rule);
  }
  .kcshop-filterbar .kcshop-count { margin-inline-start: auto; }
  /* The drawer needs room for the swatch grid and a way out at the bottom. */
  .kcshop .am-side { padding-bottom: 96px; }
  .kcshop-side__done {
    position: fixed; inset-block-end: 0; inset-inline-start: 0; width: min(300px, 86vw);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom));
    background: var(--mus-surface); border-block-start: 1px solid var(--mus-rule); z-index: 1311;
    display: none;
  }
  .kcshop .am-side.is-open ~ .kcshop-side__done,
  .kcshop .am-side.is-open .kcshop-side__done { display: block; }
  .kcshop-side__done .kcshop-btn { width: 100%; }

  .kcshop-hero { grid-template-columns: 1fr; gap: 24px; padding-block: 0 40px; }
  .kcshop-hero__c { padding-block: 6px 0; }
  .kcshop-hero__fig .kcshop-frame { min-height: 0; aspect-ratio: 4 / 5; }
  .kcshop-scrollcue { display: none; }
  .kcshop-band { grid-template-columns: 1fr; gap: 22px; padding: 22px 20px; }
  .kcshop-heroes { grid-template-columns: 1fr; padding: 20px; }
  .kcshop-heroes__strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kcshop-grid { gap: 22px 14px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .kcshop-rail { grid-auto-columns: minmax(160px, 1fr); }
  .kcshop-sec { padding-block-end: 44px; }
}

/* Two across is the floor. One giant tile per row turns a browse into a
   scroll, and the phrase is legible at 150px. */
@media (max-width: 420px) {
  .kcshop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 12px; }
  .kcshop-card__title { font-size: 13px; }
}

@media (min-width: 901px) {
  .kcshop-side__done { display: none; }
}

/* =====================================================================
   WHAT THE SHOP ADDS ON TOP OF THE SHARED LAYOUT
   ===================================================================== */

/* ---- the page header: crown, word, one action ----
   The same lockup /music/, /games/ and /posters/ put at the top of their main
   column, so the rail's first module has a word to line up with. */
.kcshop-pagehd {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 18px; flex-wrap: wrap;
  /* 14px is measured, not chosen. The rail's first module now starts 22px
     below the panel's own top (16px band + 6px heading margin) and .am-lockup
     carries margin-top:-10px, so without this the word sat at y=70 against a
     rail row at y=84. With it they are both at 84, which is the alignment
     Kaʻo asked for: the top of the word, not the top of the crown. */
  padding: 14px 0 18px;
}
/* The same crown treatment /posters/ gives its lockup, so the two headers are
   one lockup rather than two that nearly agree. */
.kcshop-pagehd .am-lockup { gap: 7px; }
.kcshop-pagehd .am-lockup__crown { height: 1.24em; transform: translateY(-0.05em); }
.kcshop-pagehd .am-lockup__word { text-transform: none; }
a.kcshop-btn--sm, button.kcshop-btn--sm {
  padding: 10px 18px; min-height: 42px; font-size: 14px; gap: 7px;
}
a.kcshop-btn--sm svg { width: 17px; height: 17px; }

/* ---- the scroll cue ----
   Kaʻo, 2026-08-20: "Nobody on this page would know to scroll down... include
   a down arrow - subtle like on [the home page]." Same size, same weight and
   same quiet border as the home page's, and it moves the page when pressed. */
.kcshop-scrollcue { display: flex; justify-content: center; padding: 0 0 44px; margin-top: -14px; }
.kcshop-cue {
  width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--wt-rule-strong); background: var(--wt-surface);
  color: var(--wt-ink-soft); cursor: pointer; padding: 0;
  transition: transform 220ms ease, background 160ms ease, color 160ms ease;
}
.kcshop-cue svg { width: 22px; height: 22px; }
.kcshop-cue:hover { background: var(--wt-chip-bg); color: var(--wt-ink); transform: translateY(3px); }
@media (prefers-reduced-motion: no-preference) {
  .kcshop-cue { animation: kcshop-nudge 2.6s ease-in-out infinite; }
  @keyframes kcshop-nudge {
    0%, 72%, 100% { transform: translateY(0); }
    82% { transform: translateY(5px); }
  }
}

/* ---- the search page's one field ---- */
.kcshop-bigsearch {
  display: flex; align-items: center; gap: 10px; max-width: 620px;
  background: var(--wt-surface); border: 1px solid var(--wt-field-border);
  border-radius: 12px; padding: 0 14px; min-height: 56px; margin: 4px 0 8px;
}
.kcshop-bigsearch:focus-within { outline: 3px solid var(--wt-focus); outline-offset: 1px; }
.kcshop-bigsearch svg { width: 20px; height: 20px; color: var(--wt-ink-quiet); flex: 0 0 auto; }
.kcshop-bigsearch input {
  font: 400 17px var(--wt-font-ui); color: var(--wt-ink); background: none; border: 0;
  outline: none; flex: 1 1 auto; min-width: 0; height: 54px;
}
.kcshop-bigsearch input::placeholder { color: var(--wt-ink-quiet); }
.kcshop-search__clear {
  border: 0; background: none; cursor: pointer; color: var(--wt-ink-quiet);
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; padding: 0;
}
.kcshop-search__clear:hover { color: var(--wt-ink); background: var(--wt-chip-bg); }
.kcshop-search__clear svg { width: 16px; height: 16px; }
.kcshop-bigsearch__hint { color: var(--wt-ink-quiet); font: 400 14px var(--wt-font-ui); margin: 0 0 26px; }

/* ---- a print partner product shot, used where no photograph of that garment
   exists. It is square, on white, so it keeps its own ratio and sits on a
   neutral panel rather than being cropped into a 2:3 portrait box. ---- */
.kcshop-frame--shot { aspect-ratio: 1 / 1; background: var(--wt-paper); }
.kcshop-frame--shot > .kcshop-img { object-fit: contain; object-position: center; }

/* THE hidden ATTRIBUTE LOSES TO A CLASS. [hidden] is a user agent rule at
   specificity (0,0,1); .kcshop-more is (0,1,0). So "Show more" was on screen
   under a complete grid AND under "Nothing matches that yet" with zero
   results, which is what Kaʻo screenshotted. */
/* ---- which language you are seeing ----
   Quiet by design: it is orientation, not a promotion. It only appears when
   the visitor's language has designs AND other languages do too, so an English
   visitor on an English-heavy shop never sees a notice about nothing. */
.kcshop-langband {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  border: 1px solid var(--wt-rule); border-radius: 12px;
  padding: 12px 16px; margin-bottom: 18px; background: var(--wt-surface);
}
.kcshop-langband[hidden] { display: none; }
.kcshop-langband__t { margin: 0; font: 500 14px var(--wt-font-ui); color: var(--wt-ink-soft); }
.kcshop-langband__b {
  margin-inline-start: auto; background: none; border: 1px solid var(--wt-rule-strong);
  border-radius: 999px; padding: 8px 16px; min-height: 40px; cursor: pointer;
  font: 600 13px var(--wt-font-ui); color: var(--wt-link);
}
.kcshop-langband__b:hover { background: var(--wt-chip-bg); color: var(--wt-link-hover); border-color: var(--wt-accent); }

.kcshop-more[hidden] { display: none; }
/* THE SAME TRAP, AND IT ALMOST SHIPPED A SECOND TIME. .kcshop-band is
   `display: grid`, specificity (0,1,0), which beats the user agent's
   `[hidden] { display: none }` at (0,0,1). The member band is rendered hidden
   on purpose and revealed only when the store can really honor the discount;
   without this line it was hidden in the DOM and visible on the page, which is
   the worst of both, a promise nobody could see was meant to be off. Measured
   in a browser: hidden=true, display=grid. */
.kcshop-band[hidden] { display: none; }
.kcshop-more__n { opacity: .72; font-weight: 500; }
