/* Scripts page (category.html). Uses styles.css for the top bar, category tiles, sale strip, footer and float UI. */

/* ---------- Head: blurred backdrop and title ---------- */

.cat-head {
    position: relative;
    isolation: isolate;
    padding-bottom: clamp(32px, 3vw, 56px);
}

/* The home hero picture: sharp on the right, blurred behind, fading into the page colour at the bottom. */
/* It reaches well below the head and melts away on long eased steps (a mask, not a colour), so there is no line
   where the picture ends: it thins out behind the top of the cards. */
.cat-head__bg {
    position: absolute;
    inset: 0 0 clamp(-360px, -22vw, -180px);
    z-index: -1;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 30%, rgba(0,0,0,0.94) 40%, rgba(0,0,0,0.82) 49%, rgba(0,0,0,0.66) 58%, rgba(0,0,0,0.48) 66%, rgba(0,0,0,0.31) 74%, rgba(0,0,0,0.17) 82%, rgba(0,0,0,0.07) 89%, rgba(0,0,0,0.02) 95%, transparent 100%);
    mask-image: linear-gradient(180deg, #000 0%, #000 30%, rgba(0,0,0,0.94) 40%, rgba(0,0,0,0.82) 49%, rgba(0,0,0,0.66) 58%, rgba(0,0,0,0.48) 66%, rgba(0,0,0,0.31) 74%, rgba(0,0,0,0.17) 82%, rgba(0,0,0,0.07) 89%, rgba(0,0,0,0.02) 95%, transparent 100%);
    pointer-events: none;
}
.cat-head__bg::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 2;
    background: linear-gradient(180deg, transparent 0%, rgba(11, 12, 18, 0.12) 35%, rgba(11, 12, 18, 0.3) 70%, rgba(11, 12, 18, 0.4) 100%);
}

.cat-head__row {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: clamp(24px, 4vw, 80px);
    padding: clamp(36px, 4vw, 72px) var(--gutter) 0;
}

/* Sale block on the right: the home hero's sale, a size smaller. */
.cat-sale { flex: none; } /* animates once, as a whole (catIn below) */
.cat-sale[hidden] { display: none; }
.cat-sale .sale-a__big { font-size: clamp(80px, 7vw, 140px); }
.cat-sale .sale-a__name { margin: 0; font-size: 13px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold); }
.cat-sale .cd { margin-top: 10px; }

@media (max-width: 960px) {
    .cat-head__row { flex-direction: column; align-items: flex-start; }
}

.cat-head__eyebrow {
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: #c4a6ff;
}

.cat-head__title h1 {
    margin: 8px 0 0;
    font-family: 'Gilroy', 'Inter', sans-serif; /* was 'Big Shoulders Display' (trial: Gilroy) */
    letter-spacing: -0.03em;
    font-size: clamp(56px, 6vw, 112px);
    font-weight: 800;
    line-height: 0.95;
}

.cat-head__title p { max-width: 620px; margin: 14px 0 0; font-size: clamp(15px, 1.05vw, 18px); line-height: 1.5; color: var(--muted); }

/* ---------- Layout: sticky filter column on the left, results on the right ---------- */

.cat-main {
    position: relative; /* paints over the head background, which reaches down behind it */
    display: grid;
    grid-template-columns: clamp(220px, 15vw, 280px) minmax(0, 1fr);
    align-items: start;
    gap: clamp(24px, 2.6vw, 48px);
    padding: clamp(24px, 2.4vw, 40px) var(--gutter) clamp(64px, 6vw, 120px);
}

/* Filter panel: a glass column of small blocks. Version and sort are segmented switches,
   series and frameworks are pills. */
.side {
    position: sticky;
    top: 24px;
    display: grid;
    gap: 20px;
    padding: 20px;
    border-radius: 22px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.02); /* plain, no extra light */
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
}

.side__head { display: flex; align-items: center; justify-content: space-between; }
.side__head h2 { margin: 0; font-size: 18px; font-weight: 800; letter-spacing: -0.02em; }
.side__reset { padding: 4px 10px; border-radius: 999px; background: rgba(167, 123, 255, 0.16); font-size: 12px; font-weight: 800; color: #d4bfff; }
.side__reset:hover { background: rgba(167, 123, 255, 0.28); color: #fff; }
.side__reset[hidden] { display: none; }

.side__group h3 { margin: 0 0 10px; font-size: 11px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); }

/* Segmented switch: options side by side in one rounded track. */
.seg {
    position: relative;
    isolation: isolate;
    display: grid;
    gap: 4px;
    padding: 4px;
    border-radius: 14px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.08);
}

.seg--3 { grid-template-columns: repeat(3, auto); }
.seg--2 { grid-template-columns: repeat(2, auto); }

/* The white thumb slides to the picked option instead of jumping. Its place and width come from the picked
   button itself (category.js sets --x and --w), so it fits even when the options are not the same width. */
.seg::before {
    content: '';
    position: absolute;
    top: 4px;
    bottom: 4px;
    left: 0;
    z-index: -1;
    width: var(--w, 0px);
    border-radius: 10px;
    background: #fff;
    transform: translateX(var(--x, 4px));
}

.seg.is-ready::before { transition: transform 0.4s var(--ease), width 0.4s var(--ease); }

.seg__opt {
    padding: 8px 6px;
    border-radius: 10px;
    font-size: 12px;
    font-weight: 700;
    color: var(--muted);
    white-space: nowrap;
    transition: background 0.25s var(--ease), color 0.25s var(--ease);
}

.seg__opt:hover { color: var(--text); }
.seg__opt.is-active { color: #0b0c12; } /* the white behind it is the sliding thumb (.seg::before) */

/* Pills: wrap onto as many lines as they need. */
.pills { display: flex; flex-wrap: wrap; gap: 6px; }

.pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    padding: 0 12px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.04);
    font-size: 13px;
    font-weight: 700;
    color: var(--muted);
    transition: background 0.25s var(--ease), color 0.25s var(--ease), border-color 0.25s var(--ease);
}

.pill small { font-size: 11px; font-weight: 800; color: var(--faint); }
.pill:hover { color: var(--text); border-color: rgba(255, 255, 255, 0.22); }
.pill.is-active { background: rgba(167, 123, 255, 0.2); border-color: rgba(196, 166, 255, 0.6); color: #fff; }
.pill.is-active small { color: #d4bfff; }

/* Series: one under another. Each row has a small letter badge in the series' colour (--tone), the name
   and the count; the chosen row lights up in its colour with a soft glow from the left. */
.series { display: grid; gap: 4px; }

.series__row {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 6px 10px 6px 6px;
    border-radius: 12px;
    border: 1px solid transparent;
    text-align: left;
    color: var(--muted);
    transition: background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease);
}

.series__row:hover { background: rgba(255, 255, 255, 0.05); color: var(--text); }

.series__badge {
    display: grid;
    place-items: center;
    flex: none;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: color-mix(in srgb, var(--tone) 18%, transparent);
    color: var(--tone);
    font-size: 13px;
    font-weight: 800;
    transition: background 0.25s var(--ease), color 0.25s var(--ease);
}

.series__badge svg { width: 16px; height: 16px; }
.series__name { flex: 1; font-size: 14px; font-weight: 700; }
.series__count { font-size: 12px; font-weight: 800; color: var(--faint); }

.series__row.is-active {
    border-color: transparent;
    background: var(--tone); /* the picked row is filled with its own colour, dark text on it */
    color: #0b0c12;
}

.series__row.is-active .series__badge { background: rgba(11, 12, 18, 0.16); color: #0b0c12; }
.series__row.is-active .series__count { color: rgba(11, 12, 18, 0.7); }

/* Framework pills show a tick when on. */
.pill--check.is-active::before { content: '✓'; font-size: 12px; color: #c4a6ff; }

.results__bar { display: flex; }

.results__search {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: 1;
    height: 50px;
    padding: 0 18px;
    border-radius: 16px;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.02); /* same plain glass as the filter panel */
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    color: var(--muted);
    transition: border-color 0.3s var(--ease);
}

.results__search:focus-within { border-color: rgba(196, 166, 255, 0.5); }
.results__search svg { width: 18px; height: 18px; flex: none; }
.results__search input { flex: 1; min-width: 0; border: 0; outline: 0; background: none; color: var(--text); font: inherit; font-size: 15px; }
.results__count { flex: none; font-size: 13px; color: var(--faint); }
.results__count b { color: var(--text); }

/* ---------- Store cards: picture on top, details and the two buttons below ---------- */

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(clamp(240px, 17vw, 320px), 1fr));
    gap: clamp(14px, 1.2vw, 22px);
    margin-top: 18px;
}

.tile {
    position: relative;
    isolation: isolate;
    container-type: inline-size; /* the price and buttons scale with the card's own width (cqi) */
    overflow: hidden;
    /* Cards off screen are not drawn at all until they come near the view. */
    content-visibility: auto;
    contain-intrinsic-size: auto 440px;
    display: flex;
    flex-direction: column;
    padding: 8px;
    border-radius: 22px;
    border: 1px solid rgba(255, 255, 255, 0.07);
    background:
        radial-gradient(120% 60% at 50% 120%, rgba(167, 123, 255, 0.12), transparent 70%),
        rgba(20, 19, 32, 0.85);
    /* Cards arrive blur to sharp, a little after one another. */
    --in-blur: 8px;
    --in-y: 0px;
    animation: catIn 0.6s var(--ease) backwards;
    animation-delay: calc(0.3s + var(--i) * 0.04s);
    transition: transform 0.4s var(--ease), border-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}

/* Card background: the script's own picture, heavily blurred and darkened (--art is set per card). */
.tile::before {
    content: '';
    position: absolute;
    inset: -30px;
    z-index: -1;
    background: var(--art) center / cover no-repeat;
    filter: blur(36px) saturate(1.3) brightness(0.38);
    transform: scale(1.15);
}

.tile:hover { transform: translateY(-4px); border-color: transparent; box-shadow: 0 24px 54px rgba(0, 0, 0, 0.5); }

/* Hover frame in the card's own colours: a thin ring along the card edge (masked to 1.5px) showing the card's
   picture, blurred and brightened, turning slowly while the card is hovered. The picture turns with a transform
   on its own layer (<span class="tile__ring"><i>), which the browser moves without redrawing; animating the
   background position of a blurred, masked layer made it flicker in some browsers. */
.tile__ring {
    position: absolute;
    inset: 0;
    z-index: 1;
    overflow: hidden;
    padding: 1.5px;
    border-radius: inherit;
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.4s var(--ease);
}

.tile__ring i {
    position: absolute;
    inset: -60%;
    background: var(--art) center / cover no-repeat;
    filter: blur(14px) saturate(2) brightness(1.6);
    animation: ringTurn 14s linear infinite paused;
    will-change: transform;
}

.tile:hover .tile__ring { opacity: 1; }
.tile:hover .tile__ring i { animation-play-state: running; }

@keyframes ringTurn { to { transform: rotate(360deg); } }

/* Picture inset in the card, with its own rounded corners. */
.tile__art { position: relative; display: block; aspect-ratio: 16 / 11.5; overflow: hidden; border-radius: 15px; background: #1b1d25; }
.tile__img { width: 100%; height: 100%; object-fit: cover; }
.tile:hover .tile__img { transform: scale(1.05); }


.tile__body { display: flex; flex-direction: column; gap: 10px; flex: 1; padding: 16px 16px 16px; }
.tile__top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 8px; }
.tile__series { font-size: 11px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: #c4a6ff; }
.tile__fw { display: flex; gap: 3px; }
.tile__fw i { padding: 3px 8px; border-radius: 7px; background: rgba(255, 255, 255, 0.09); font-style: normal; font-size: 11px; font-weight: 700; color: rgba(255, 255, 255, 0.78); }
.tile__name { font-size: 23px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.2; }
.tile__name:hover { color: #d4bfff; }

/* Price on the left (old price and discount above it), then Add to Basket and a round Details arrow. */
.tile__foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: auto; padding-top: 34px; }
.tile__price { display: grid; line-height: 1.1; }
.tile__was { display: flex; align-items: center; gap: 6px; }
.tile__price s { font-size: clamp(12px, 4.2cqi, 15px); color: var(--faint); white-space: nowrap; }
.tile__was em { padding: 2px 8px; border-radius: 7px; background: var(--gold); color: #1a1406; font-style: normal; font-size: clamp(11px, 3.6cqi, 13px); font-weight: 800; white-space: nowrap; }
.tile__free { justify-self: start; padding: 4px 12px; border-radius: 8px; background: #a77bff; color: #fff; font-style: normal; font-size: 18px; font-weight: 800; letter-spacing: 0.02em; }
.tile__price b { font-size: clamp(22px, 8cqi, 32px); font-weight: 800; letter-spacing: -0.02em; white-space: nowrap; }
.tile__actions { display: flex; align-items: center; gap: 6px; }

.tile__details {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.14);
    background: rgba(255, 255, 255, 0.05);
    transition: background 0.3s var(--ease), border-color 0.3s var(--ease);
}

.tile__details svg { width: 16px; height: 16px; }
.tile__details:hover { background: rgba(255, 255, 255, 0.12); border-color: rgba(255, 255, 255, 0.3); }

/* Narrow cards: the Details arrow steps aside so the price and Add to Basket fit (the picture and name open the
   script page too). */
@container (max-width: 300px) {
    .tile__details { display: none; }
    .tile__foot { gap: 6px; }
    .tile__add { padding: 0 10px; }
    .tile__was { gap: 4px; }
    .tile__was em { padding: 2px 5px; }
}

.tile__add {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 40px;
    padding: 0 clamp(12px, 4.4cqi, 16px);
    border-radius: 999px;
    background: #fff;
    color: #0b0c12;
    font-size: clamp(12px, 3.8cqi, 13px);
    font-weight: 800;
    white-space: nowrap;
    transition: box-shadow 0.3s var(--ease), background 0.3s var(--ease), color 0.3s var(--ease);
}

.tile__add:hover { box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.16); }

.grid-empty { margin: 40px 0; text-align: center; color: var(--muted); }
/* Before the store data arrives the grid keeps a screen of room, so the footer is not shown and then pushed down. */
.grid:empty:has(~ .grid-empty[hidden]) { min-height: 100vh; }
.grid-empty[hidden] { display: none; }

@media (max-width: 860px) {
    .cat-main { grid-template-columns: 1fr; }
    .side { position: static; }
    /* Two cards to a row on phones, three on tablets. */
    .grid { grid-template-columns: repeat(auto-fill, minmax(clamp(150px, 26vw, 220px), 1fr)); gap: 12px; }
    .tile { padding: 6px; border-radius: 18px; contain-intrinsic-size: auto 300px; }
    .tile__art { border-radius: 13px; }
}

/* Small cards: no framework tags, the price over a full-width Add to Basket. */
@container (max-width: 240px) {
    .tile__fw { display: none; }
    .tile__body { gap: 4px; padding: 10px 6px 6px; }
    .tile__series { font-size: 10px; }
    .tile__name { font-size: 16px; }
    .tile__foot { flex-direction: column; align-items: stretch; gap: 8px; padding-top: 10px; }
    .tile__price b { font-size: 20px; }
    .tile__actions { width: 100%; }
    .tile__add { flex: 1; justify-content: center; height: 38px; }
}

/* Touch screens: a tap leaves :hover stuck on the card, so the hover lift and ring stay off. The filter panel and
   search box drop their backdrop blur (costly while scrolling on phones), and the search text is 16px so iOS
   does not zoom the page in when it is tapped. */
@media (hover: none) {
    .side, .results__search { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(20, 19, 32, 0.7); }
    .results__search input { font-size: 16px; }
    .tile:hover { transform: none; border-color: rgba(255, 255, 255, 0.07); box-shadow: none; }
    .tile:hover .tile__ring { opacity: 0; }
    .tile:hover .tile__img { transform: none; }
}

/* Phones and tablets: the filter panel folds away behind its header. */
.side__toggle { display: none; }

@media (max-width: 860px) {
    .cat-main .side__toggle { display: inline-flex; }
    .cat-main .side:not(.is-open) > .side__group { display: none; }
}

.side__toggle {
    align-items: center;
    gap: 6px;
    height: 36px;
    margin-left: 8px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.12);
    background: rgba(255, 255, 255, 0.05);
    font-size: 13px;
    font-weight: 800;
    color: var(--text);
}
.side__toggle svg { width: 14px; height: 14px; transition: transform 0.3s var(--ease); }
.side__toggle[data-count]:not([data-count="0"])::before {
    content: attr(data-count);
    display: grid;
    place-items: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 999px;
    background: #a77bff;
    color: #0b0c12;
    font-size: 11px;
    font-weight: 800;
}
.side.is-open .side__toggle svg { transform: rotate(180deg); }
.side__head:has(.side__toggle) .side__reset { margin-left: auto; }
.side__head:has(.side__reset[hidden]) .side__toggle { margin-left: auto; }

/* ---------- Entrance: the content comes in piece by piece (the top bar and category tiles stay put) ---------- */
.cat-head__title > *, .cat-sale, .side, .results__bar {
    animation: catIn 0.7s var(--ease) backwards;
}

.cat-head__title > :nth-child(2) { animation-delay: 0.06s; }
.cat-head__title > :nth-child(3) { animation-delay: 0.12s; }
.cat-sale { animation-delay: 0.18s; }
.side { animation-delay: 0.24s; }
.results__bar { animation-delay: 0.28s; }

/* Entrances only describe where they start and use "backwards": once over they leave nothing behind
   (a held blur(0) filter would keep every element on its own layer and make scrolling heavy). */
@keyframes catIn { from { opacity: 0; filter: blur(var(--in-blur, 10px)); transform: translateY(var(--in-y, 14px)); } }

/* The picture sits near the middle of the head (soft on both sides and at the bottom). */
.cat-head__bg .hero-layer .hero-layer__main {
    right: auto;
    left: 40%; /* a little left of centre, clear of the sale block on the right */
    transform: translateX(-50%);
    -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 22%, #000 78%, transparent 100%), linear-gradient(180deg, #000 55%, transparent 100%);
    -webkit-mask-composite: source-in;
    mask-image: linear-gradient(90deg, transparent 0%, #000 22%, #000 78%, transparent 100%), linear-gradient(180deg, #000 55%, transparent 100%);
    mask-composite: intersect;
}

/* Small "what's inside" cards (bundle pages, subscription tiers): their picture box centres the placeholder logo,
   so the picture itself is laid over the whole box to fill it edge to edge. */
.tile--inc .tile__art > .tile__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
