/* =========================================================
 Octavemerch - shared stylesheet
 Aesthetic: bold, dark, band-poster inspired
 ========================================================= */

/* ---------- Page reveal gate ----------
 * Pages that fetch data (Firestore, etc.) opt in by adding
 * data-loading="1" to <body>. While present, <main> is invisible
 * (opacity:0). JS removes the attribute when data has settled,
 * triggering a smooth fade-in. Without this gate, pages render
 * their HTML defaults (placeholder names, "0", "€0.00"), then flash
 * to the localStorage cache, then to cloud values - up to 3 paints
 * per refresh that the user sees as flicker.
 *
 * Static pages (terms, privacy, etc.) don't set data-loading and
 * render normally. The transition stays declared globally so even
 * pages that toggle the attribute mid-life (rare) get the smooth
 * fade for free.
 *
 * Duration: 350ms cubic-bezier easing. Long enough to feel intentional
 * and polished, short enough that customers don't notice they waited. */
main { transition: opacity 0.25s cubic-bezier(0.22, 0.61, 0.36, 1); }
body[data-loading="1"] main { opacity: 0; pointer-events: none; }

/* ---------- Card fade-in ----------
 * OPT-IN behaviour. Pages that want the whole-card fade put
 * data-cards-fade on their <body>. Pages without the attribute keep
 * the original behaviour (cards visible immediately), which prevents
 * the fade-in from breaking older pages that don't load the updated
 * app.js / _enhanceCardFadeIn handler.
 *
 * On opt-in pages: each .card starts at opacity:0. JS in js/app.js
 * walks .card:not(.ready), waits for the inner <img>s to load (or
 * 1.5s safety timeout per card), then adds `.ready` so the whole
 * card (image + title + meta + price) fades to opacity:1 over 1.2s.
 *
 * The inner .card-img / .dm-mockup-imgwrap / .dm-mockup-multi
 * wrappers stay fully visible - they fade as part of the parent
 * card. Older pages that didn't get app.js refreshed continue to
 * use the previous image-group fade, kept here as a fallback for
 * compatibility. */
body[data-cards-fade] .card {
 opacity: 0;
 transition: opacity 1.2s ease-out;
}
body[data-cards-fade] .card.ready {
 opacity: 1;
}
/* Fallback for non-opt-in pages: keep the original image-group fade
 * so the older app.js (which targets .card-img / .dm-mockup-imgwrap
 * / .dm-mockup-multi) still works. */
body:not([data-cards-fade]) .card-img,
body:not([data-cards-fade]) .dm-mockup-imgwrap,
body:not([data-cards-fade]) .dm-mockup-multi {
 opacity: 0;
 transition: opacity 0.3s ease-out;
}
body:not([data-cards-fade]) .card-img.ready,
body:not([data-cards-fade]) .dm-mockup-imgwrap.ready,
body:not([data-cards-fade]) .dm-mockup-multi.ready {
 opacity: 1;
}

:root {
 --bg: #0b0b0f;
 --bg-2: #14141b;
 --bg-3: #1c1c26;
 --fg: #f4f4f6;
 --muted: #8a8a99;
 --accent: #ff2d55; /* hot pink/red */
 --accent-2: #ffb703; /* amber */
 --accent-3: #00e5a8; /* mint */
 --border: #2a2a36;
 --radius: 10px;
 --radius-lg: 18px;
 --shadow: 0 10px 30px rgba(0,0,0,0.35);
 --font-display: "Bebas Neue", "Oswald", Impact, sans-serif;
 --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

html, body {
 margin: 0;
 padding: 0;
 background: var(--bg);
 color: var(--fg);
 font-family: var(--font-body);
 line-height: 1.55;
 -webkit-font-smoothing: antialiased;
}

a { color: var(--accent-3); text-decoration: none; }
a:hover { color: var(--fg); }

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

h1, h2, h3, h4 {
 font-family: var(--font-display);
 letter-spacing: 0.02em;
 line-height: 1.05;
 margin: 0 0 0.5em;
 text-transform: uppercase;
}

h1 { font-size: clamp(2.2rem, 5vw, 4rem); }
h2 { font-size: clamp(1.6rem, 3vw, 2.6rem); }
h3 { font-size: 1.3rem; }

p { margin: 0 0 1em; }

.container {
 max-width: 1200px;
 margin: 0 auto;
 padding: 0 1.25rem;
}

/* ---------- Header / Nav ---------- */
.site-header {
 position: sticky;
 top: 0;
 z-index: 50;
 background: rgba(11,11,15,0.85);
 backdrop-filter: blur(10px);
 border-bottom: 1px solid var(--border);
}

.nav {
 display: flex;
 align-items: center;
 justify-content: space-between;
 padding: 0.9rem 0;
}

.logo {
 font-family: var(--font-display);
 font-size: 1.6rem;
 color: var(--fg);
 letter-spacing: 0.05em;
 text-transform: uppercase;
}
.logo span { color: var(--accent); }

.nav-links {
 display: flex;
 gap: 1.25rem;
 align-items: center;
 list-style: none;
 margin: 0;
 padding: 0;
}
.nav-links a {
 color: var(--fg);
 font-weight: 500;
 font-size: 0.95rem;
}
.nav-links a:hover { color: var(--accent); }

.nav-cta {
 padding: 0.5rem 1rem;
 border: 1px solid var(--accent);
 border-radius: var(--radius);
 color: var(--accent) !important;
 font-weight: 600;
}
.nav-cta:hover { background: var(--accent); color: #fff !important; }

/* ---------- Profile dropdown ---------- */
.profile-dropdown { position: relative; }
.profile-trigger {
 display: inline-flex; align-items: center; gap: 0.35rem;
 padding: 0;
 background: none; border: none; cursor: pointer;
 color: var(--fg); font-weight: 500; font-size: 0.95rem;
 font-family: inherit;
}
.profile-trigger:hover { color: var(--accent); }
.profile-caret { font-size: 0.7rem; transition: transform 0.15s; opacity: 0.7; }
.profile-trigger[aria-expanded="true"] .profile-caret { transform: rotate(180deg); }
.profile-menu {
 display: none;
 position: absolute; top: calc(100% + 0.6rem); right: 0;
 min-width: 220px;
 background: var(--bg-2); border: 1px solid var(--border); border-radius: var(--radius);
 padding: 0.4rem; z-index: 1000;
 box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
}
.profile-menu.open { display: block; }
.profile-menu-item {
 display: block;
 padding: 0.6rem 0.85rem;
 color: var(--fg) !important;
 font-size: 0.9rem; font-weight: 500;
 border-radius: 6px;
 text-decoration: none;
 transition: background 0.12s, color 0.12s;
}
.profile-menu-item:hover { background: rgba(255, 107, 53, 0.1); color: var(--accent) !important; }
.profile-menu-divider { height: 1px; background: var(--border); margin: 0.35rem 0.4rem; }
.profile-menu-signout { color: var(--muted) !important; }
.profile-menu-signout:hover { background: rgba(255, 45, 85, 0.12); color: #ff3b3b !important; }
/* Hide Subscription menu item for non-band users */
body.role-customer .profile-menu-item.is-hidden-customer { display: none; }

.cart-badge {
 display: inline-block;
 min-width: 18px;
 padding: 0 6px;
 margin-left: 4px;
 background: var(--accent);
 color: #fff;
 border-radius: 999px;
 font-size: 0.75rem;
 text-align: center;
}

/* Admin nav badge - same shape as the cart badge but a different colour
 * (mint accent) so it visually reads as "things waiting for review" rather
 * than "cart count". Hides itself when empty (zero items needing action). */
.admin-nav-link { position: relative; }
.admin-nav-badge {
 display: inline-block;
 min-width: 18px;
 padding: 0 6px;
 margin-left: 6px;
 background: var(--accent-3, #00e5a8);
 color: #0c0c10;
 border-radius: 999px;
 font-size: 0.72rem;
 font-weight: 700;
 line-height: 18px;
 text-align: center;
 vertical-align: middle;
}
.admin-nav-badge:empty { display: none; }

/* ---------- Buttons ---------- */
.btn {
 display: inline-block;
 padding: 0.8rem 1.4rem;
 border-radius: var(--radius);
 font-weight: 600;
 font-size: 0.95rem;
 border: none;
 cursor: pointer;
 text-transform: uppercase;
 letter-spacing: 0.04em;
 transition: transform 0.15s, background 0.15s;
}
.btn:hover { transform: translateY(-1px); }
.btn-primary { background: var(--accent); color: #fff; }
.btn-primary:hover { background: #ff4c6e; color: #fff; }

/* Band hero CTA - accent button with a strong outline + shadow so it stays
 readable against any band hero image (light, dark, or busy). */
.band-hero-cta {
 background: var(--accent);
 color: #fff;
 font-weight: 700;
 padding: 0.75rem 1.5rem;
 border-radius: 999px;
 box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45), 0 0 0 2px rgba(255, 255, 255, 0.18);
 text-decoration: none;
 display: inline-block;
}
.band-hero-cta:hover { background: #ff4c6e; color: #fff; transform: translateY(-1px); }
.btn-secondary {
 background: transparent;
 color: var(--fg);
 border: 1px solid var(--border);
}
.btn-secondary:hover { border-color: var(--fg); }
.btn-ghost {
 background: transparent;
 color: var(--fg);
 padding: 0.4rem 0.6rem;
 transition: color 0.15s ease;
}
.btn-ghost:hover { color: var(--accent-3); }

/* Generic loading state for any button. Add the class .btn-loading to a
 * button to replace its text with a centred spinner (text colour goes
 * transparent so the original label still occupies the space - no width
 * jump). pointer-events disabled so users can't click while busy. Use the
 * setBtnLoading() helper in js/app.js to apply consistently. */
.btn-loading {
 color: transparent !important;
 pointer-events: none;
 position: relative;
}
.btn-loading::after {
 content: '';
 position: absolute;
 left: 50%;
 top: 50%;
 width: 18px;
 height: 18px;
 margin: -9px 0 0 -9px;
 border: 2px solid rgba(255, 255, 255, 0.3);
 border-top-color: #fff;
 border-radius: 50%;
 animation: btn-spin 0.7s linear infinite;
}
/* Ghost / secondary buttons are darker text on a light/dark bg - use the
 * fg colour for the spinner so it stays visible against any background. */
.btn-ghost.btn-loading::after,
.btn-secondary.btn-loading::after {
 border-color: rgba(244, 244, 246, 0.25);
 border-top-color: var(--fg);
}
@keyframes btn-spin { to { transform: rotate(360deg); } }

/* Card carousel: prev/next arrows + "1/2 · Front" counter sit inside an
 <a class="card"> so without these overrides they'd inherit the mint
 anchor colour. White by default; mint only on hover. */
.dm-nav, .dm-counter { color: var(--fg) !important; transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease; }
.dm-nav { background: rgba(255, 255, 255, 0.08) !important; border: 1px solid rgba(255, 255, 255, 0.18) !important; }
.dm-nav:hover { color: var(--accent-3) !important; background: rgba(0, 229, 168, 0.18) !important; border-color: rgba(0, 229, 168, 0.45) !important; }

/* Variant-picker modal (band page → click product) renders the same dm-nav
 carousel inside a WHITE modal panel, where white-on-white was unreadable.
 Force dark text + a visible darker chip background for the modal context. */
#variant-modal .dm-nav,
#variant-modal .dm-counter { color: #1a1a1f !important; }
#variant-modal .dm-nav { background: rgba(0, 0, 0, 0.06) !important; border: 1px solid rgba(0, 0, 0, 0.18) !important; }
#variant-modal .dm-nav:hover { color: var(--accent); background: rgba(255, 107, 53, 0.12) !important; border-color: rgba(255, 107, 53, 0.45) !important; }

/* Modal close (×) sits on a white card; the global .btn-ghost is white-on-
 * dark, which made the × nearly invisible. Force it dark, give it a subtle
 * hover hit-area, and bump the font size so it reads as an actual close
 * button rather than a stray glyph in the corner. */
#variant-modal .btn-ghost {
 color: #1a1a1f !important;
 font-size: 1.6rem;
 line-height: 1;
 padding: 0.25rem 0.6rem;
 border-radius: 6px;
 transition: background 0.15s ease, color 0.15s ease;
}
#variant-modal .btn-ghost:hover {
 background: rgba(0, 0, 0, 0.08);
 color: var(--accent) !important;
}

/* ---------- Hero ---------- */
.hero {
 position: relative;
 padding: 6rem 0 5rem;
 overflow: hidden;
 background:
 radial-gradient(circle at 20% 20%, rgba(255,45,85,0.18), transparent 60%),
 radial-gradient(circle at 80% 60%, rgba(0,229,168,0.15), transparent 60%),
 var(--bg);
}
.hero h1 { font-size: clamp(2.8rem, 7vw, 6rem); }
.hero .lede { font-size: 1.15rem; color: var(--muted); max-width: 620px; }
.hero .cta-row { display: flex; gap: 0.75rem; margin-top: 1.5rem; flex-wrap: wrap; }

/* ---------- Section ---------- */
section.block {
 padding: 4rem 0;
 border-top: 1px solid var(--border);
}
.block .eyebrow {
 color: var(--accent);
 text-transform: uppercase;
 letter-spacing: 0.15em;
 font-size: 0.8rem;
 font-weight: 700;
 margin-bottom: 0.75rem;
}

/* ---------- Grids ---------- */
.grid {
 display: grid;
 gap: 1.25rem;
}
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 900px) {
 .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
 /* grid-3 still collapses to 1 column on phone (3 -> 1 keeps cards
  * comfortably readable). grid-4 stays at 2 columns so the band
  * catalog and shop grid show 2 designs per row on mobile - twice
  * the catalog visible per scroll without sacrificing legibility. */
 .grid-3 { grid-template-columns: 1fr; }
 .grid-4 { grid-template-columns: repeat(2, 1fr); gap: 0.75rem; }
 /* At half-phone-width (~165px per card) the card padding and font
  * sizes need to scale down so the title doesn't dominate. */
 .grid-4 .card { border-radius: 8px; }
 .grid-4 .card-body { padding: 0.7rem; }
 .grid-4 .card-title { font-size: 0.9rem; }
 .grid-4 .card-meta { font-size: 0.72rem; }
 .grid-4 .card-price { font-size: 0.95rem; }
 /* Multi-side carousel arrows + counter - shrink so they don't crowd
  * out the tiny card width. */
 .grid-4 .dm-counter { font-size: 0.62rem; }
 .grid-4 .dm-nav { width: 24px !important; height: 24px !important; font-size: 0.95rem !important; }
}

/* ---------- Cards ---------- */
.card {
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius-lg);
 overflow: hidden;
 transition: transform 0.2s, border-color 0.2s;
 display: flex;
 flex-direction: column;
}
.card:hover { transform: translateY(-3px); border-color: var(--accent); }
.card .card-img {
 /* 1:1 image area matches the inner mockup's aspect-ratio so every product
 (tee, hoodie, tank, women's tank) gets the same visual footprint and
 cards don't end up unequal in the grid. */
 aspect-ratio: 1 / 1;
 width: 100%;
 background: linear-gradient(135deg, #222, #111);
 display: flex;
 align-items: center;
 justify-content: center;
 position: relative;
 overflow: hidden;
}
/* Ensure the inner mockup never overflows the card-img and doesn't push it
 taller. (Some products previously rendered slightly off, leaving one card
 visibly bigger than its neighbours.) */
.card .card-img > * { max-width: 100%; max-height: 100%; }
.card .card-img .dm-mockup { width: 100%; height: 100%; }
/* Multi-view mockups (front/back/sleeves) stack a square image area + a
 nav row, so they're naturally taller than 1:1. Let the card-img grow
 to fit that - without this override, max-height:100% squishes the image
 area and distorts the design's position on the photo. */
.card .card-img:has(.dm-mockup-multi) {
 aspect-ratio: auto;
 align-items: stretch;
}
.card .card-img > .dm-mockup-multi { max-height: none; }
.card .card-img > .dm-mockup-multi .dm-mockup-imgwrap { width: 100%; }
.card .card-img .poster {
 font-family: var(--font-display);
 font-size: 2.4rem;
 color: #fff;
 text-align: center;
 padding: 1rem;
 text-transform: uppercase;
 text-shadow: 3px 3px 0 var(--accent);
}
.card .card-body {
 padding: 1rem 1.1rem 1.2rem;
 display: flex;
 flex-direction: column;
 gap: 0.3rem;
 flex: 1;
}
.card .card-title {
 font-weight: 600; font-size: 1.05rem; color: var(--fg);
 /* Clamp to one line so a long title doesn't make the card taller than
 its grid neighbours. Ellipsis instead of wrap. */
 white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.card .card-meta {
 color: var(--muted); font-size: 0.85rem;
 /* Reserve 2 lines for the product/meta text so single-line cards have
 the same body height as cards whose product name wraps. Clamps over
 2 lines if longer. */
 display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
 line-clamp: 2;
 overflow: hidden;
 min-height: 2.4em;
}
.card .card-price { margin-top: auto; color: var(--accent-2); font-weight: 700; }

/* ---------- Band index (alpha letter dropdowns) ----------
 * Each letter A-Z is a button. Clicking a letter expands a single
 * dropdown panel below the alphabet showing only the bands whose
 * names start with that letter. Single-select: opening another letter
 * closes the previous one. Letters with no matching bands appear
 * dimmed and disabled. Works identically on mobile and desktop. */
.alpha-index {
 display: flex;
 flex-wrap: wrap;
 gap: 0.4rem;
 margin-bottom: 1rem;
}
.alpha-btn {
 display: inline-flex;
 align-items: center;
 gap: 0.3rem;
 padding: 0.45rem 0.7rem;
 border: 1px solid var(--border);
 border-radius: 6px;
 background: transparent;
 color: var(--muted);
 font-weight: 600;
 font-size: 0.85rem;
 font-family: inherit;
 cursor: pointer;
 transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.alpha-btn:hover:not(.disabled):not(:disabled) {
 color: #fff;
 background: var(--bg-3);
 border-color: var(--muted);
}
.alpha-btn.active {
 color: #fff;
 background: var(--accent);
 border-color: var(--accent);
}
.alpha-btn.disabled,
.alpha-btn:disabled {
 opacity: 0.35;
 cursor: not-allowed;
}
.alpha-count {
 font-size: 0.7rem;
 font-weight: 500;
 padding: 0 0.35rem;
 border-radius: 999px;
 background: rgba(255, 255, 255, 0.08);
 color: inherit;
 min-width: 1.1rem;
 text-align: center;
}
.alpha-btn.active .alpha-count {
 background: rgba(0, 0, 0, 0.25);
}

/* The dropdown panel that appears below the alphabet for the active
 * letter. Single panel - we re-render it whenever the active letter
 * changes. A subtle border + slight inset background makes it read
 * as "expanded content" rather than just another section. */
.band-dropdown {
 background: var(--bg-3);
 border: 1px solid var(--border);
 border-radius: 10px;
 padding: 1rem 1.1rem 0.6rem;
 margin-top: 0.25rem;
 animation: alphaDropdownIn 0.18s ease-out;
}
@keyframes alphaDropdownIn {
 from { opacity: 0; transform: translateY(-4px); }
 to { opacity: 1; transform: translateY(0); }
}
.band-dropdown-header {
 color: var(--accent);
 font-weight: 700;
 font-size: 1.05rem;
 margin-bottom: 0.45rem;
}
.band-list {
 list-style: none;
 padding: 0;
 margin: 0;
 columns: 2;
 column-gap: 1.5rem;
}
.band-list li {
 padding: 0.4rem 0;
 break-inside: avoid;
}
.band-list a {
 color: var(--fg);
 font-weight: 500;
}
.band-list a:hover { color: var(--accent); }
.band-list-letter {
 display: inline-block;
 min-width: 1.1rem;
 color: var(--muted);
 font-weight: 700;
 margin-right: 0.3rem;
}

/* Phone: single column so band names don't get crammed at half width. */
@media (max-width: 560px) {
 .band-list { columns: 1; }
 .alpha-btn { padding: 0.4rem 0.55rem; font-size: 0.8rem; }
 .band-dropdown { padding: 0.85rem 0.9rem 0.5rem; }
}

/* ---------- Forms ---------- */
.form-grid {
 display: grid;
 gap: 1rem;
 max-width: 600px;
}
label { display: block; font-weight: 600; margin-bottom: 0.35rem; font-size: 0.9rem; }
input[type=text], input[type=email], input[type=password], input[type=url],
input[type=number], select, textarea {
 width: 100%;
 padding: 0.75rem 0.9rem;
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius);
 color: var(--fg);
 font: inherit;
}
textarea { min-height: 120px; resize: vertical; }
input:focus, select:focus, textarea:focus {
 outline: none;
 border-color: var(--accent);
}

/* ---------- Hero banner (band page) ---------- */
.band-hero {
 position: relative;
 padding: 4rem 0 2rem;
 background: linear-gradient(180deg, #1a0620 0%, var(--bg) 100%);
 text-align: center;
 overflow: hidden;
}
.band-hero.has-cover {
 padding: 7rem 0 3rem;
 min-height: 360px;
}
.band-hero .cover-bg {
 position: absolute; inset: 0; z-index: 0;
 background-size: cover;
 background-position: center;
 background-repeat: no-repeat;
}
.band-hero .cover-overlay {
 position: absolute; inset: 0; z-index: 1;
 background: linear-gradient(180deg, rgba(11,11,15,0.45) 0%, rgba(11,11,15,0.65) 60%, var(--bg) 100%);
}
.band-hero > .container { position: relative; z-index: 2; }
.band-hero .hero-owner-controls {
 position: absolute; top: 1rem; right: 1rem; z-index: 3;
 display: flex; gap: 0.5rem;
}
.band-hero .hero-edit-btn {
 display: inline-flex; align-items: center; gap: 0.4rem;
 padding: 0.45rem 0.85rem; font-size: 0.8rem; font-weight: 600;
 background: rgba(11,11,15,0.75); color: #fff;
 border: 1px solid rgba(255,255,255,0.25); border-radius: 999px;
 cursor: pointer; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
 transition: background 0.15s, border-color 0.15s;
}
.band-hero .hero-edit-btn:hover { background: var(--accent); border-color: var(--accent); }
.band-hero .hero-edit-btn-ghost { background: rgba(11,11,15,0.5); }
.band-hero .hero-edit-btn-ghost:hover { background: rgba(255,45,85,0.85); border-color: rgba(255,45,85,0.85); }
.band-hero h1 {
 font-size: clamp(3rem, 8vw, 7rem);
 color: var(--fg);
 text-shadow: 4px 4px 0 var(--accent);
}
.band-hero .band-bio { max-width: 640px; margin: 0 auto; color: var(--muted); }
.band-hero.has-cover .band-bio { color: rgba(255,255,255,0.85); }

/* Owner-only inline edit affordance for the band bio. */
.band-bio[data-band-bio-editable] { cursor: pointer; transition: color 0.12s ease; }
.band-bio[data-band-bio-editable]:hover { color: var(--accent); }
.band-bio-edit-hint { font-size: 0.75rem; opacity: 0.55; margin-left: 0.4rem; }
.band-bio-edit-wrap { max-width: 640px; margin: 0 auto; display: flex; flex-direction: column; gap: 0.5rem; align-items: center; }
.band-bio-input {
 width: 100%; max-width: 640px;
 padding: 0.6rem 0.75rem;
 border-radius: 8px;
 border: 1px solid var(--border);
 background: rgba(0, 0, 0, 0.6);
 color: #fff;
 font: inherit;
 resize: vertical;
}
.band-bio-edit-actions { display: flex; gap: 0.5rem; }
.band-bio-edit-actions .btn { padding: 0.45rem 1rem; font-size: 0.85rem; }
.band-bio.is-editing { cursor: default; }
.band-hero .band-meta { color: var(--accent-2); margin-top: 0.5rem; letter-spacing: 0.15em; text-transform: uppercase; font-size: 0.8rem; }

/* ---------- Design studio ---------- */
.studio {
 display: grid;
 grid-template-columns: 1fr 340px;
 gap: 1.5rem;
 align-items: start;
}
@media (max-width: 900px) { .studio { grid-template-columns: 1fr; } }

.studio-canvas {
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius-lg);
 padding: 1.5rem;
 min-height: 520px;
 display: flex;
 align-items: center;
 justify-content: center;
 flex-direction: column;
 gap: 1rem;
}
.studio-preview {
 position: relative;
 width: 100%;
 max-width: 420px;
 aspect-ratio: 3 / 4;
 background: #eee;
 border-radius: 12px;
 overflow: hidden;
 display: flex;
 align-items: center;
 justify-content: center;
}
.studio-preview.tshirt-white { background: #f5f5f5; }
.studio-preview.tshirt-black { background: #111; }
.studio-preview.hat-black { background: #111; aspect-ratio: 1/1; }
.studio-preview.beanie { background: #222; aspect-ratio: 1/1; }
.studio-preview.underwear { background: #ddd; aspect-ratio: 4/3; }
.studio-preview .placed-art {
 position: absolute;
 top: 25%;
 left: 25%;
 width: 50%;
 height: 50%;
 display: flex;
 align-items: center;
 justify-content: center;
 font-family: var(--font-display);
 font-size: 2rem;
 text-align: center;
 color: #000;
 padding: 8px;
}
.studio-preview .placed-art img {
 max-width: 100%;
 max-height: 100%;
 object-fit: contain;
}

.studio-controls {
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius-lg);
 padding: 1.5rem;
 display: flex;
 flex-direction: column;
 gap: 1rem;
}
.product-pills {
 display: flex;
 flex-wrap: wrap;
 gap: 0.5rem;
}
.product-pills button {
 padding: 0.5rem 0.8rem;
 background: var(--bg-3);
 border: 1px solid var(--border);
 border-radius: 999px;
 color: var(--fg);
 font-size: 0.85rem;
 cursor: pointer;
}
.product-pills button.active {
 background: var(--accent);
 border-color: var(--accent);
 color: #fff;
}

/* ---------- Table / list ---------- */
table.admin-table {
 width: 100%;
 border-collapse: collapse;
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius);
 overflow: hidden;
}
.admin-table th, .admin-table td {
 padding: 0.85rem 1rem;
 text-align: left;
 border-bottom: 1px solid var(--border);
}
.admin-table th {
 background: var(--bg-3);
 text-transform: uppercase;
 letter-spacing: 0.08em;
 font-size: 0.8rem;
 color: var(--muted);
}
.admin-table tr:last-child td { border-bottom: none; }
.status-pill {
 display: inline-block;
 padding: 3px 10px;
 border-radius: 999px;
 font-size: 0.75rem;
 font-weight: 700;
 text-transform: uppercase;
}
.status-pending { background: rgba(255,183,3,0.15); color: var(--accent-2); }
.status-approved { background: rgba(0,229,168,0.15); color: var(--accent-3); }
.status-rejected { background: rgba(255,45,85,0.15); color: var(--accent); }

/* ---------- Cart ---------- */
.cart-item {
 display: grid;
 grid-template-columns: 100px 1fr auto;
 gap: 1rem;
 padding: 1rem 0;
 border-bottom: 1px solid var(--border);
 align-items: center;
}
.cart-thumb {
 width: 100px;
 height: 120px;
 border-radius: 8px;
 background: var(--bg-3);
 display: flex;
 align-items: center;
 justify-content: center;
 font-family: var(--font-display);
 font-size: 1.2rem;
 overflow: hidden;
}
.cart-summary {
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius-lg);
 padding: 1.5rem;
 margin-top: 2rem;
}
.cart-summary .row {
 display: flex;
 justify-content: space-between;
 padding: 0.4rem 0;
}
.cart-summary .row.total {
 border-top: 1px solid var(--border);
 margin-top: 0.5rem;
 padding-top: 0.75rem;
 font-weight: 700;
 font-size: 1.2rem;
}

/* ---------- Footer ---------- */
.site-footer {
 margin-top: 4rem;
 padding: 3rem 0 2rem;
 border-top: 1px solid var(--border);
 background: var(--bg-2);
 color: var(--muted);
 font-size: 0.9rem;
}
.site-footer .grid-4 { gap: 2rem; }
.site-footer h4 {
 color: var(--fg);
 font-family: var(--font-display);
 font-size: 1rem;
 margin-bottom: 0.6rem;
}
.site-footer ul { list-style: none; padding: 0; margin: 0; }
.site-footer li { padding: 0.2rem 0; }
.site-footer a { color: var(--muted); }
.site-footer a:hover { color: var(--fg); }

.toast {
 position: fixed;
 bottom: 20px;
 right: 20px;
 background: var(--accent-3);
 color: #000;
 padding: 0.9rem 1.2rem;
 border-radius: var(--radius);
 font-weight: 600;
 box-shadow: var(--shadow);
 z-index: 1000;
 opacity: 0;
 transform: translateY(20px);
 transition: opacity 0.25s, transform 0.25s;
 pointer-events: none;
}
.toast.show { opacity: 1; transform: translateY(0); }

/* ---------- Utilities ---------- */
.row { display: flex; gap: 1rem; align-items: center; }
.between { justify-content: space-between; }
.muted { color: var(--muted); }
.center { text-align: center; }
.mt-1 { margin-top: 0.5rem; } .mt-2 { margin-top: 1rem; } .mt-3 { margin-top: 1.5rem; } .mt-4 { margin-top: 2rem; }
.mb-1 { margin-bottom: 0.5rem; } .mb-2 { margin-bottom: 1rem; } .mb-3 { margin-bottom: 1.5rem; } .mb-4 { margin-bottom: 2rem; }
.hidden { display: none !important; }

/* mobile nav */
.nav-toggle { display: none; background: transparent; border: none; color: var(--fg); font-size: 1.4rem; cursor: pointer; }
@media (max-width: 720px) {
 .nav-links { display: none; flex-direction: column; position: absolute; top: 100%; left: 0; right: 0; background: var(--bg-2); border-top: 1px solid var(--border); padding: 1rem; }
 .nav-links.open { display: flex; }
 .nav-toggle { display: inline-block; }
}

/* Hide band-targeted CTAs from signed-in customers */
body.role-customer .band-cta { display: none !important; }

/* ---------- Clickable category cards (homepage) ---------- */
.category-card {
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: space-between;
 gap: 0.75rem;
 transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
 cursor: pointer;
}
.category-card:hover {
 transform: translateY(-3px);
 border-color: var(--accent);
 box-shadow: 0 10px 24px rgba(0,0,0,0.35);
}
.category-card .category-cta {
 display: inline-block;
 margin-top: 0.5rem;
 font-size: 0.8rem;
 font-weight: 700;
 color: var(--accent);
 letter-spacing: 0.05em;
 text-transform: uppercase;
}

/* ---------- Shop category chips ---------- */
.chip {
 display: inline-block;
 padding: 0.45rem 0.9rem;
 border: 1px solid var(--border);
 border-radius: 999px;
 font-size: 0.85rem;
 font-weight: 600;
 color: var(--muted);
 text-decoration: none;
 background: var(--bg-2);
 transition: all 0.15s ease;
}
.chip:hover { color: #fff; border-color: var(--accent); }
.chip.chip-active {
 background: var(--accent);
 color: #0b0b0f;
 border-color: var(--accent);
}

/* ---------- Support page ---------- */
.support-layout {
 display: grid;
 grid-template-columns: 220px 1fr;
 gap: 2.5rem;
 margin-top: 2rem;
 align-items: start;
}
.support-nav {
 position: sticky;
 top: 1rem;
 display: flex;
 flex-direction: column;
 gap: 0.25rem;
 padding: 1rem;
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius);
}
.support-nav a {
 display: block;
 padding: 0.55rem 0.75rem;
 border-radius: 8px;
 color: var(--muted);
 font-weight: 600;
 font-size: 0.95rem;
 text-decoration: none;
 transition: background 0.12s, color 0.12s;
}
.support-nav a:hover { color: #fff; background: rgba(255,255,255,0.04); }
.support-nav a.active {
 background: var(--accent);
 color: #0b0b0f;
}
.support-body { display: flex; flex-direction: column; gap: 3rem; }
.support-topic {
 scroll-margin-top: 2rem;
 padding: 2rem;
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius-lg);
}
.support-topic h2 { margin-top: 0.5rem; }
.support-topic h3 { margin-top: 1.5rem; font-size: 1.1rem; }
.support-topic p, .support-topic li { line-height: 1.6; color: rgba(255,255,255,0.85); }
.support-topic ul { padding-left: 1.25rem; }
.support-topic a { color: var(--accent); }

@media (max-width: 760px) {
 .support-layout { grid-template-columns: 1fr; }
 .support-nav {
 position: static;
 flex-direction: row;
 flex-wrap: wrap;
 gap: 0.5rem;
 }
 .support-nav a { padding: 0.4rem 0.7rem; font-size: 0.85rem; }
}

/* ---------- Subscription / billing UI ---------- */
.sub-card {
 padding: 1.5rem 1.75rem;
 background: var(--bg-2);
 border: 1px solid var(--border);
 border-radius: var(--radius);
}
.sub-card .sub-status {
 display: inline-block;
 padding: 0.25rem 0.7rem;
 border-radius: 999px;
 font-size: 0.78rem;
 font-weight: 700;
 letter-spacing: 0.05em;
 text-transform: uppercase;
}
.sub-status.trialing { background: rgba(59,130,246,0.18); color: #93c5fd; border: 1px solid rgba(59,130,246,0.35); }
.sub-status.active { background: rgba(0,229,168,0.15); color: #00e5a8; border: 1px solid rgba(0,229,168,0.35); }
.sub-status.past_due { background: rgba(245,158,11,0.18); color: #fbbf24; border: 1px solid rgba(245,158,11,0.35); }
.sub-status.canceled { background: rgba(148,163,184,0.18);color: #cbd5e1; border: 1px solid rgba(148,163,184,0.35); }
.sub-status.expired { background: rgba(239,68,68,0.18); color: #fca5a5; border: 1px solid rgba(239,68,68,0.35); }
.sub-status.none { background: rgba(255,255,255,0.08);color: var(--muted); border: 1px solid rgba(255,255,255,0.10); }

/* Primary CTA row - full-weight buttons, generous spacing. */
.sub-cta {
 display: flex;
 gap: 0.75rem;
 flex-wrap: wrap;
 margin-top: 1.25rem;
 align-items: center;
}
.sub-cta--primary .btn {
 font-size: 0.95rem;
}
/* Inside the subscription card, give .btn-ghost a visible outlined-button
 * treatment. The base .btn-ghost rule has no border/background so the
 * buttons look like floating text. Scoping to .sub-cta keeps the rest of
 * the site (where ghost buttons are inline icon-style) untouched. */
.sub-cta .btn-ghost {
 background: rgba(255,255,255,0.04);
 border: 1px solid var(--border);
 padding: 0.65rem 1.1rem;
 border-radius: var(--radius);
 transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.sub-cta .btn-ghost:hover {
 background: rgba(0,229,168,0.10);
 border-color: rgba(0,229,168,0.40);
 color: var(--accent-3);
}
/* Secondary cluster - visually muted under the primary action. Smaller
 * type, tighter padding, separated from the primary CTA by a thin rule
 * so it reads as "manage" rather than another call-to-action. */
.sub-cta--secondary {
 margin-top: 0.85rem;
 padding-top: 0.85rem;
 border-top: 1px solid var(--border);
 gap: 0.5rem;
}
.sub-cta--secondary .btn {
 font-size: 0.78rem;
 padding: 0.5rem 0.95rem;
 letter-spacing: 0.05em;
 opacity: 0.78;
}
.sub-cta--secondary .btn:hover {
 opacity: 1;
}
.plan-pick {
 display: grid;
 grid-template-columns: 1fr;
 gap: 1rem;
 margin-top: 1rem;
}
.plan-pick label {
 display: block;
 padding: 1.25rem;
 border: 2px solid var(--border);
 border-radius: var(--radius);
 cursor: pointer;
 transition: border-color 0.15s, background 0.15s;
}
.plan-pick label:hover { border-color: var(--accent); }
.plan-pick input[type=radio]:checked + .plan-body {
 /* checked styling handled via wrapper class */
}
.plan-pick label.selected {
 border-color: var(--accent);
 background: rgba(255,107,53,0.06);
}
.plan-price {
 font-family: 'Bebas Neue', sans-serif;
 font-size: 2rem;
 color: var(--accent);
 line-height: 1;
 margin: 0.25rem 0;
}

/* ----------------------------------------------------------------------
 * Self-hosted typefaces (not on Google Fonts).
 *
 * Noituma = Dieter Steffmann's "Cloister Black" Textura blackletter.
 *   Served as TTF (~71 KB). The visual typeface is in the public domain
 *   (Morris Fuller Benton, 1904); Steffmann's digital font is freeware
 *   for personal and commercial use. We expose it under the family name
 *   "Noituma" so it appears that way in the wizard font picker. No
 *   changes to the font file itself - this is a CSS alias only
 *   (license-clean).
 *
 *   The .woff2 line was dropped because the file was never built /
 *   uploaded - browsers fell through to the .ttf correctly, but every
 *   page logged a "Failed to decode font / OTS parsing error" pair
 *   because hosting returned an HTML 404 (with a UTF-8 BOM) that the
 *   OpenType sanitizer choked on. If we want the bandwidth saving back,
 *   generate /fonts/CloisterBlack.woff2 from the TTF and re-add the
 *   line above the TTF src. As-is the site loads the TTF cleanly.
 * -------------------------------------------------------------------- */
@font-face {
 font-family: 'Noituma';
 font-style: normal;
 font-weight: 400;
 font-display: swap;
 src: url('/fonts/CloisterBlack.ttf') format('truetype');
}
@font-face {
 font-family: 'Cloister Black';
 font-style: normal;
 font-weight: 400;
 font-display: swap;
 src: url('/fonts/CloisterBlack.ttf') format('truetype');
}
