/* ===========================================================================
   Pocket Crates — shared stylesheet (single source of truth)
   ===========================================================================

   Loaded once from templates/base.html's <head>, which every one of the 52
   templates inherits from. It is linked BEFORE `{% block head %}`, so any
   page-scoped <style> block still overrides what's here — that's deliberate:
   it lets templates migrate onto these shared components one at a time
   without a big-bang rewrite, instead of every page having to move together.

   Structure
     1. Design tokens
     2. Canonical components (the deduplicated ones)

   Rules for adding to this file
     - Use the tokens. Never re-hardcode a token's literal value (writing
       `.85rem` instead of `var(--text-sm)`, or `#7CB5FF` instead of
       `var(--accent-2)`) — that's what caused the drift this file exists to
       fix.
     - One component, one name. Before adding a class, check it isn't a
       renamed copy of something already here.
   =========================================================================== */


/* ===========================================================================
   1. DESIGN TOKENS
   ---------------------------------------------------------------------------
   Mirrors of these currently also live in base.html's own :root block. Both
   define identical values, so they agree; base.html's copy is scheduled for
   removal once every page-scoped block is migrated (see the migration notes
   in the handoff). Until then, keep the two in sync if a token changes.
   =========================================================================== */

:root {
  /* Surfaces */
  --bg: #0F1216;
  --panel: #161A21;
  --panel-2: #1D232C;
  --border: #2A313C;
  --border-light: #3B4450;

  /* Text */
  --text: #E9EDF2;
  --muted: #9AA5B4;

  /* Accents — blue is primary, teal is secondary/community/success */
  --accent: #3D8BFD;
  --accent-2: #7CB5FF;
  --accent-dim: #2563EB;
  --teal: #23B8A2;
  --teal-2: #5BE0CB;

  /* Status */
  --success: #23B8A2;
  --error: #E2554A;
  --error-2: #FF8A7E;
  --warning: #E8B23A;

  /* Translucent accent washes — these exist because the same colour was
     previously written 15 different ways (`rgba(61,139,253,.12)` vs
     `rgba(61, 139, 253, 0.12)` vs `.1` vs `.10`...). Use these, not literals. */
  --accent-wash: rgba(61, 139, 253, .12);
  --accent-wash-strong: rgba(61, 139, 253, .18);
  --accent-edge: rgba(61, 139, 253, .32);
  --teal-wash: rgba(35, 184, 162, .12);
  --teal-edge: rgba(35, 184, 162, .32);
  --warning-wash: rgba(232, 178, 58, .12);
  --warning-edge: rgba(232, 178, 58, .32);
  --error-wash: rgba(226, 85, 74, .12);
  --error-edge: rgba(226, 85, 74, .32);

  /* Type families */
  --label: 'Fraunces', Georgia, 'Times New Roman', serif;
  --sans: 'Source Sans 3', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Craft */
  --radius: 8px;
  --radius-sm: 4px;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, .4), 0 6px 18px rgba(0, 0, 0, .28);
  --shadow-card-hover: 0 2px 4px rgba(0, 0, 0, .45), 0 12px 28px rgba(0, 0, 0, .38);
  --shadow-pop: 0 6px 24px rgba(0, 0, 0, .5);
  --ease: cubic-bezier(.22, .61, .36, 1);

  /* Spacing — 7 steps. Use these instead of ad-hoc rem values. */
  --section-gap: 4rem;
  --space-xs: .25rem;
  --space-sm: .5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;
  --space-3xl: 4rem;

  /* Body text sizes — three steps, deliberately. */
  --text-sm: .85rem;
  --text-xs: .75rem;
  --text-micro: .65rem;

  /* Display / heading sizes */
  --display-lg: 2.2rem;
  --display-md: 1.7rem;
  --display-sm: 1.1rem;
}


/* ===========================================================================
   2. CANONICAL COMPONENTS
   =========================================================================== */

/* ---------------------------------------------------------------------------
   2.1 .action-btn — pill action control
   ---------------------------------------------------------------------------
   PHASE A FIX. This was previously defined only inside kit_detail.html's
   page-scoped <style> block, but collection_detail.html also uses it (its
   "Copy shareable link" button) while extending public_base.html — which
   never loaded that CSS, so the button rendered unstyled in production.
   Living here, it works on both pages and anywhere else.
   --------------------------------------------------------------------------- */
.action-btn {
  padding: .55rem var(--space-md);
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  font-family: inherit;
  font-size: .9rem;
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  text-decoration: none;
}
.action-btn:hover { border-color: var(--muted); }
.action-btn[data-on="1"][data-kind="heart"] { color: var(--error-2); border-color: var(--error-2); }
.action-btn[data-on="1"][data-kind="favorite"] { color: var(--accent); border-color: var(--accent); }

/* Compact variant — for action buttons sitting inside a line of body text,
   e.g. collection_detail's "Copy shareable link" next to the kit count. */
.action-btn.action-btn-sm { padding: .3rem .6rem; font-size: var(--text-xs); }


/* ---------------------------------------------------------------------------
   2.2 Danger button
   ---------------------------------------------------------------------------
   Canonical source: admin_base.html's .admin-danger-btn (transparent fill,
   --error border, --error-2 label). `.admin-danger-btn` is kept as an alias
   so the ~8 admin templates already using it keep working unchanged.

   NOT merged in here, deliberately (see report): .del-btn is a borderless
   ghost ICON button that only turns red on hover, and .ml-replace-btn is a
   neutral compact toolbar button that isn't destructive at all. Folding
   either into this would visibly change them.
   --------------------------------------------------------------------------- */
.btn-danger,
.admin-danger-btn {
  background: transparent;
  border: 1px solid var(--error);
  color: var(--error-2);
}
.btn-danger:hover,
.admin-danger-btn:hover { background: var(--error-wash); }


/* ---------------------------------------------------------------------------
   2.3 .stat-tile — canonical stat/metric tile
   ---------------------------------------------------------------------------
   Replaces FOUR parallel implementations of the same idea:
     - home.html          .stat-block + .stat-number/.stat-label (3rem italic)
     - contributor.html   .stat-block (same class name, different rules!)
     - creator_dashboard  .cd-stat .label/.value
     - dashboard.html     unclassed inline styles

   Canonical sizing chosen from creator_dashboard's .cd-stat, because it was
   the only one already using a shared class + panel and sits between the
   other two in scale. home.html's oversized editorial 3rem treatment is
   intentionally NOT folded in — it's a marketing display number, a different
   job from a dashboard metric; it keeps its own .stat-number under a
   distinct name (.hero-stat) rather than being flattened to match.
   --------------------------------------------------------------------------- */
.stat-tile {
  padding: .9rem 1.1rem;
  /* Always sits inside a row/grid that owns the gap — .panel's own
     margin-bottom would double it up. */
  margin: 0;
}
/* display:block so the parts stack whether the template uses <div> or
   <span> for them (both spellings exist across the migrated pages). */
.stat-tile .stat-tile-label {
  display: block;
  font-size: var(--text-micro);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .08em;
}
.stat-tile .stat-tile-value {
  display: block;
  font-size: 1.6rem;
  font-weight: 600;
  margin-top: .2rem;
  line-height: 1.2;
  color: var(--text);
}
/* Compact variant — the contributor-profile stat strip (5 small metrics in
   an inline row). Same component, smaller step; without this it would have
   to stay a separate implementation, which is what we're removing. */
.stat-tile.stat-tile-sm {
  padding: .6rem var(--space-md);
  min-width: 90px;
  text-align: center;
}
.stat-tile.stat-tile-sm .stat-tile-value {
  font-size: 1.35rem;
  font-weight: 700;
  font-family: var(--label);
  margin-top: 0;
}
.stat-tile.stat-tile-sm .stat-tile-label {
  font-size: var(--text-xs);
  letter-spacing: .04em;
  margin-top: .1rem;
}

/* Row of tiles — auto-fit so 3 and 5 tiles both look deliberate. */
.stat-tile-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: .8rem;
  margin: var(--space-md) 0 var(--space-lg);
}
.stat-tile-row.stat-tile-row-compact {
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
/* Inline (non-grid) row, for the profile strip. */
.stat-tile-strip {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin: var(--space-md) 0;
}


/* ---------------------------------------------------------------------------
   2.4 .star-rating — canonical star display
   ---------------------------------------------------------------------------
   Replaces four implementations of the identical `★×n ☆×(5-n)` string that
   rendered at four different sizes (.78rem card, .82rem review row, .85rem
   admin, unset on the detail summary). Canonical size is --text-sm; the
   card grid keeps a smaller variant since it sits in a dense card footer.
   --------------------------------------------------------------------------- */
.star-rating {
  color: var(--accent-2);
  font-size: var(--text-sm);
  letter-spacing: .05em;
}
.star-rating.star-rating-sm { font-size: var(--text-xs); }
.star-rating .rating-count {
  color: var(--muted);
  font-family: var(--mono);
}


/* ---------------------------------------------------------------------------
   2.5 .empty-state — canonical empty/zero state
   ---------------------------------------------------------------------------
   Canonical source: public_base.html's version (panel fill + dashed border),
   chosen over admin_moderation.html's bare text-only copy because it's the
   one used on 11 of the 12 pages that have an empty state, so standardising
   on it changes the fewest surfaces. Admin moderation's empty state gains a
   panel + dashed border as a result — a deliberate, documented change.
   --------------------------------------------------------------------------- */
.empty-state {
  text-align: center;
  padding: var(--space-2xl) var(--space-lg);
  color: var(--muted);
  background: var(--panel);
  border: 1px dashed var(--border-light);
  border-radius: var(--radius);
}
.empty-state .empty-title {
  color: var(--text);
  font-family: var(--label);
  font-size: var(--display-sm);
  margin-bottom: var(--space-sm);
}
.empty-state .empty-cta { margin-top: .75rem; }


/* ---------------------------------------------------------------------------
   2.6 .auth-wrap — login / register / forgot / reset shell
   ---------------------------------------------------------------------------
   These four templates each carried a byte-identical copy of this block.
   --------------------------------------------------------------------------- */
.auth-wrap {
  max-width: 420px;
  margin: var(--space-2xl) auto 0;
}
.auth-wrap h1,
.auth-wrap p.sub { text-align: center; }


/* ---------------------------------------------------------------------------
   2.7 .save-bar — sticky save/publish bar
   ---------------------------------------------------------------------------
   Was duplicated across admin_copy / admin_featured_kits / admin_tags with
   the same visual and three different margin-tops (1.2rem / none / 1.5rem).
   Canonical: --space-lg (1.5rem), matching admin_tags, the largest of the
   three — so no bar ends up more cramped than it was.
   --------------------------------------------------------------------------- */
.save-bar {
  position: sticky;
  bottom: var(--space-md);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  padding: .8rem 1.2rem;
  margin-top: var(--space-lg);
  box-shadow: var(--shadow-pop);
}


/* ---------------------------------------------------------------------------
   2.8 Product picker (admin_bundles + bundle_propose)
   ---------------------------------------------------------------------------
   Identical in both templates.
   --------------------------------------------------------------------------- */
.product-picker { display: none; }
.product-picker.active { display: block; }
.picker-search { margin-bottom: .4rem; }

/* Product-type radio selector — was byte-identical (6 rules) in both
   admin_bundles.html and bundle_propose.html. The checked-state wash was
   `rgba(61,139,253,.1)`; it now uses --accent-wash (.12), folding one more
   of the hand-written accent opacities onto the token. */
.type-select { display: flex; gap: .6rem; margin: .3rem 0 var(--space-md); }
.type-option {
  flex: 1;
  cursor: pointer;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: .7rem .8rem;
  background: var(--panel-2);
  transition: border-color .15s, background .15s;
}
.type-option input { display: none; }
.type-option .to-title {
  font-family: var(--label);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text);
}
.type-option .to-sub {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: .15rem;
}
.type-option:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-wash);
}


/* ---------------------------------------------------------------------------
   2.9 Mixed / Raw — community mixer-preset contributions
   ---------------------------------------------------------------------------
   These classes were applied in kit_detail.html's markup with ZERO CSS behind
   them; all their layout was inline `style=` attributes. Real styles now,
   matching the section rhythm used by .pieces-section / .comments-section.
   --------------------------------------------------------------------------- */
.mixed-section {
  margin-top: var(--space-xl);
  padding-top: var(--space-lg);
  border-top: 1px solid var(--border);
}
.mixed-section h2 {
  font-size: var(--display-sm);
  margin-bottom: var(--space-sm);
}
.mixed-section > .sub { margin-top: calc(var(--space-xs) * -1); }

.mixed-submit summary {
  cursor: pointer;
  font-size: var(--text-sm);
  color: var(--accent-2);
}
.mixed-submit form { margin-top: .9rem; }

.mixed-list { margin-top: var(--space-md); }
.mixed-entry { margin-top: .9rem; }
.mixed-entry-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  flex-wrap: wrap;
}
.mixed-entry-meta { font-size: var(--text-xs); color: var(--muted); }
.mixed-entry-desc { margin: .6rem 0 0; }
.mixed-howto {
  font-size: var(--text-xs);
  color: var(--muted);
  margin-top: .9rem;
}
.mixed-empty { margin-top: var(--space-md); }

/* The Raw badge previously rendered at two different sizes for the same
   label — .6rem on cards, .65rem on the detail page, both inline. One size
   now, on the token scale. */
.badge-raw {
  vertical-align: middle;
  margin-left: var(--space-xs);
  font-size: var(--text-micro);
}
