/* Tier List Maker — tool-specific styles (uses tokens from assets/brand.css) */

.tl-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  margin-bottom: 18px;
}

.tl-toolbar-group {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.tl-tier-count {
  font-size: 12px;
  color: var(--f9y-text-dim);
  letter-spacing: 0.04em;
}

/* --- team browser panel --- */

.tl-team-browser {
  padding: 14px 16px;
  margin-bottom: 18px;
}

.tl-team-browser-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

.tl-team-search,
.tl-team-select {
  font-family: var(--f9y-font-body);
  font-size: 13px;
  padding: 8px 10px;
  border-radius: var(--f9y-radius-sm);
  border: 1px solid var(--f9y-border);
  background: var(--f9y-surface);
  color: var(--f9y-text);
}

.tl-team-search {
  flex: 1 1 180px;
  min-width: 140px;
}

.tl-league-toggle {
  display: inline-flex;
  border-radius: var(--f9y-radius-sm);
  border: 1px solid var(--f9y-border);
  overflow: hidden;
}

.tl-league-btn {
  font-family: var(--f9y-font-body);
  font-size: 13px;
  font-weight: 500;
  padding: 8px 14px;
  border: none;
  background: var(--f9y-surface);
  color: var(--f9y-text-dim);
  cursor: pointer;
}

.tl-league-btn + .tl-league-btn {
  border-left: 1px solid var(--f9y-border);
}

.tl-league-btn.is-active {
  background: var(--f9y-green);
  color: var(--f9y-white);
}

.tl-ap25-controls {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

/* an authored `display` on this class otherwise wins over the browser's
   default `[hidden] { display: none }` UA rule (author styles always
   beat user-agent ones, regardless of specificity), so the `hidden`
   attribute app.js sets in NFL mode would silently do nothing without
   this override. */
.tl-ap25-controls[hidden] {
  display: none;
}

.tl-ap25-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--f9y-font-body);
  font-size: 13px;
  font-weight: 500;
  padding: 8px 10px;
  border-radius: var(--f9y-radius-sm);
  border: 1px solid var(--f9y-border);
  background: var(--f9y-surface);
  color: var(--f9y-text);
  cursor: pointer;
  user-select: none;
}

.tl-ap25-toggle input:disabled {
  cursor: not-allowed;
}

.tl-ap25-toggle:has(input:disabled) {
  color: var(--f9y-text-faint);
  cursor: not-allowed;
}

.tl-ap25-rank {
  position: absolute;
  top: -6px;
  left: -6px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--f9y-green);
  color: var(--f9y-white);
  font-family: var(--f9y-font-body);
  font-weight: 500;
  font-size: 10px;
  line-height: 18px;
  text-align: center;
}

.tl-team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 8px;
  max-height: 340px;
  overflow-y: auto;
  padding: 4px 2px;
}

.tl-team-chip {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 8px 4px;
  border: 1px solid var(--f9y-border);
  border-radius: var(--f9y-radius-sm);
  background: var(--f9y-surface);
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.1s ease;
}

.tl-team-chip:hover {
  border-color: var(--f9y-green);
  transform: translateY(-1px);
}

.tl-team-chip-logo {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--f9y-font-display);
  font-weight: 400;
  font-size: 13px;
  letter-spacing: 0.01em;
  color: var(--f9y-white);
  overflow: hidden;
}

.tl-team-chip-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--f9y-white);
}

.tl-team-chip-name {
  font-size: 10px;
  text-align: center;
  color: var(--f9y-text-dim);
  line-height: 1.2;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%;
}

.tl-team-browser-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 10px;
}

.tl-team-empty {
  grid-column: 1 / -1;
  color: var(--f9y-text-faint);
  font-size: 13px;
  padding: 12px 4px;
}

/* --- import logos modal --- */

.tl-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(16, 19, 17, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}

.tl-modal-overlay[hidden] {
  display: none;
}

.tl-modal {
  width: 100%;
  max-width: 520px;
  padding: 24px;
}

.tl-modal-title {
  font-family: var(--f9y-font-display);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 20px;
  margin: 0 0 10px;
}

.tl-modal-help {
  font-size: 13px;
  color: var(--f9y-text-dim);
  line-height: 1.5;
  margin: 0 0 12px;
}

.tl-modal-help code {
  background: var(--f9y-surface-2);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 12px;
}

.tl-modal-textarea {
  width: 100%;
  min-height: 160px;
  font-family: var(--f9y-font-body);
  font-size: 12px;
  padding: 10px;
  border-radius: var(--f9y-radius-sm);
  border: 1px solid var(--f9y-border);
  background: var(--f9y-surface);
  color: var(--f9y-text);
  resize: vertical;
}

.tl-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 14px;
}

/*
  --- the exportable card ---
  Mirrors graphics/branding.py's render_branded_card frame exactly:
  green left stripe, black header (eyebrow/headline), cream body (the
  tiers), black footer (tagline). Fixed to Instagram's optimal post
  ratio (4:5, 1080x1350) via JS (see layoutBoard() in app.js) rather
  than growing with content — header/footer/each tier row get an
  explicit pixel height computed from the card's current width, so the
  export is always exactly on-ratio no matter how many tiers or items
  are on the board. Advanced CSS sizing (aspect-ratio, etc.) is
  deliberately avoided here since html2canvas's rendering engine doesn't
  reliably support it — plain computed pixel heights render identically
  on-screen and in the export.
*/

.tl-capture {
  display: flex;
  align-items: stretch;
  border-radius: 0; /* square corners — cleaner for a social post than rounded */
  overflow: hidden;
  border: 1px solid var(--f9y-border);
  box-shadow: 0 1px 3px rgba(16, 19, 17, 0.08);
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
}

.tl-capture-stripe {
  flex: 0 0 10px;
  background: var(--f9y-green);
}

.tl-capture-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  /* pulled 1px left, on top of the stripe (later in DOM order so it
     paints over it) — html2canvas can leave a single antialiased,
     partially-transparent pixel right at the seam between the two flex
     siblings, which reads as a faint light line once the export is
     flattened onto a non-transparent background. The 1px overlap makes
     sure a solid color always covers that seam instead of a gap. */
  margin-left: -1px;
  position: relative;
}

.tl-capture-header {
  background: var(--f9y-black);
  /* horizontal padding is set inline by layoutBoard() (padX) so it lines
     up exactly with the body's padding and the tiers below; this is
     just a pre-JS fallback. Vertical padding is also set inline. */
  padding: 5% 7%;
  box-sizing: border-box;
  overflow: hidden;
  /* title/subtitle are position:absolute within this (see .tl-capture-
     headline / .tl-capture-subtitle below) rather than flex children —
     when the header's fixed height is tight enough to exactly fit their
     content (which it always is, by construction, since layoutBoard()
     sizes the header FROM their content), Chromium's flexbox silently
     clamps any top-margin increase on a flex child once the column's
     content would overflow the container's definite height: margin-top
     values above a certain point all rendered pixel-identical to that
     threshold in testing. Absolute positioning has no such clamp — each
     element's `top` always places it exactly where set. */
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  /* header/body/footer's heights are computed precisely in layoutBoard()
     to sum to exactly the card's total height — flex's default
     flex-shrink:1 can still silently compress them by a fraction of a
     px if that sum doesn't land exactly on the card's own separately-
     rounded total, which was throwing off the header's air-cropping
     math enough to visibly skew the title/subtitle gaps. Locking all
     three to flex-shrink:0 makes each one take its set height exactly. */
  flex-shrink: 0;
}

.tl-capture-headline {
  /* absolute within .tl-capture-header — top/left/width are set inline
     by layoutBoard(). left+width (not right:0) because html2canvas's own
     layout engine was observed to mis-measure left:0;right:0's resolved
     width on the capture, even though real browsers render it correctly
     live — see .tl-capture-header's comment on why this isn't a flex
     child. */
  position: absolute;
  top: 0;
  font-family: var(--f9y-font-display);
  font-weight: 400;
  text-transform: uppercase;
  line-height: 1.05;
  color: var(--f9y-white);
  margin: 0;
  white-space: nowrap;
  /* Explicit tracking, not just "normal" — html2canvas's per-character
     canvas text measurement has been observed to land tighter than the
     live DOM for this condensed font depending on the browser/OS doing
     the export, closing the gap between letters almost entirely. A real
     letter-spacing value is honored by html2canvas's text renderer too,
     so it holds a visible gap open no matter how canvas measures glyphs.
     Kept deliberately generous (not a token 0.01–0.02em nudge) since a
     smaller value here was still reported as touching in a real export. */
  letter-spacing: 0.0075em;
}

#board-title[data-placeholder]:empty::before {
  content: attr(data-placeholder);
  color: var(--f9y-gray);
}

#board-title {
  outline: none;
  border-radius: 6px;
  /* no vertical padding — it'd be a fixed px amount on top of the
     font's own (proportional-to-size) built-in air, breaking
     layoutBoard()'s per-font-size air-ratio math in fitHeadlineFontSize
     neighbors below */
  padding: 0 6px;
  margin-left: -6px;
}

#board-title:hover,
#board-title:focus {
  background: rgba(255, 255, 255, 0.1);
}

/* matches the real chart pipeline's "subtitle: DM Mono Regular" —
   font-size and margin-top are set inline by layoutBoard() (the latter
   so the gap above the subtitle always matches the gap above the title) */
.tl-capture-subtitle {
  /* absolute within .tl-capture-header, same reasoning as
     .tl-capture-headline above — top/left/width are set inline by
     layoutBoard() */
  position: absolute;
  top: 0;
  font-family: var(--f9y-font-body);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--f9y-gray);
  margin: 0;
  line-height: 1.1; /* explicit rather than the browser default, so the
    air-ratio constants in layoutBoard() stay accurate regardless of
    browser/font fallback quirks */
  white-space: nowrap;
  overflow: hidden;
}

#board-subtitle[data-placeholder]:empty::before {
  content: attr(data-placeholder);
}

#board-subtitle {
  outline: none;
  border-radius: 6px;
  padding: 0 6px; /* see #board-title's comment on vertical padding */
  margin-left: -6px;
}

#board-subtitle:hover,
#board-subtitle:focus {
  background: rgba(255, 255, 255, 0.1);
}

/* An empty subtitle still shows its dim placeholder live (so it's
   discoverable as an editable field), but that placeholder — and the
   line's own space — should never bake into the exported PNG if the
   user never actually typed one. That's handled in exportPng() by
   toggling an inline `display: none` directly rather than a CSS rule
   keyed off :empty — html2canvas doesn't reliably honor structural
   pseudo-classes like :empty when resolving styles for the capture, so
   a `.exporting #board-subtitle:empty { display: none }` rule here
   applies correctly on the live page but silently does nothing in the
   actual export. */

.tl-capture-body {
  background: var(--f9y-cream);
  /* horizontal padding set inline by layoutBoard() (padX); vertical
     padding stays fixed here and is accounted for in the tier-row math */
  padding: 14px 16px;
  box-sizing: border-box;
  overflow: hidden;
  flex-shrink: 0; /* see .tl-capture-header's comment */
}

.tl-capture-footer {
  background: var(--f9y-black);
  display: flex;
  align-items: center;
  padding: 0 7%;
  box-sizing: border-box;
  flex-shrink: 0; /* see .tl-capture-header's comment */
}

/* matches the real chart pipeline's footer: brand name in the
   "eyebrow" green/mono treatment, paired with a dim "meta" mono tag —
   font-size set inline by layoutBoard(), proportional to footer height */
.tl-capture-footer-left {
  font-family: var(--f9y-font-body);
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
}

.tl-capture-footer-brand {
  font-weight: 500;
  letter-spacing: 0.14em;
  color: var(--f9y-green);
}

.tl-capture-footer-sep {
  color: var(--f9y-gray);
}

.tl-capture-footer-tag {
  font-weight: 400;
  letter-spacing: 0.1em;
  color: var(--f9y-gray);
}

/* --- tiers --- */

.tl-tiers {
  display: flex;
  flex-direction: column;
  gap: 4px;
  height: 100%;
}

/* square corners + a thick black border, like the bordered stat cells in
   the chart pipeline's table-style graphics — tier color stays on the
   label chip, this is just the container treatment */
.tl-tier {
  display: flex;
  align-items: stretch;
  border-radius: 0;
  overflow: hidden;
  border: 2px solid var(--f9y-black);
  background: var(--f9y-surface);
  flex-shrink: 0;
}

.tl-tier-label {
  flex: 0 0 110px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 4px 8px;
  box-sizing: border-box;
  text-align: center;
  color: var(--f9y-black);
  overflow: hidden;
  border-right: 2px solid var(--f9y-black);
}

.tl-tier-name {
  font-family: var(--f9y-font-display);
  font-weight: 400;
  font-size: 17px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  outline: none;
  min-width: 20px;
  max-width: 100%;
  line-height: 1.15;
  overflow: hidden;
  /* white-space/word-break/display/line-clamp are set inline by
     fitTierLabelFontSize() in app.js — it first tries to shrink to fit
     on one line, and only wraps (at word boundaries, never mid-word) as
     a fallback for multi-word labels that still don't fit */
}

.tl-tier-name:focus,
.tl-tier-name:hover {
  text-decoration: underline dotted;
}

.tl-tier-color {
  width: 22px;
  height: 18px;
  padding: 0;
  border: none;
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  flex-shrink: 0;
}

/* Items in a tier lay out on a single line and shrink (sized by JS in
   layoutBoard()) to fit as more are added, rather than wrapping —
   that's what keeps a tier row's height fixed regardless of count. */
.tl-items-row {
  flex: 1;
  display: flex;
  /* wraps onto additional lines past MAX_ITEMS_PER_ROW (app.js), each
     line's item size computed to fit the tier's fixed row height —
     more items means more/smaller lines, not one ever-shrinking line */
  flex-wrap: wrap;
  align-content: center;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  box-sizing: border-box;
  overflow: hidden;
  min-width: 0;
}

.tl-tier-controls {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 6px;
  border-left: 1px solid var(--f9y-border);
  background: var(--f9y-surface-2);
}

.tl-icon-btn {
  width: 24px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
  border: 1px solid var(--f9y-border);
  border-radius: 5px;
  background: var(--f9y-surface-2);
  color: var(--f9y-text-dim);
  cursor: pointer;
}

.tl-icon-btn:hover {
  color: var(--f9y-text);
  border-color: var(--f9y-accent);
}

.tl-icon-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* --- items (images / text cards) --- */

.tl-item {
  position: relative;
  width: 76px;
  height: 76px;
  overflow: hidden;
  color: var(--f9y-black);
  cursor: grab;
  flex-shrink: 0;
}

/* only text cards get a visible chip — an image item (almost always a
   team logo) has no background/border/radius of its own, just the logo
   floating free, per "no background or rounded square container, just
   the logos being pulled in" */
.tl-item[data-type="text"] {
  border-radius: 8px;
  background: var(--f9y-surface-2);
  border: 1px solid var(--f9y-border);
}

.tl-item:active {
  cursor: grabbing;
}

.tl-item-img {
  width: 100%;
  height: 100%;
  /* contain, not cover — with no visible box behind it, cropping a logo
     to fill a square would just look wrong; show the whole mark instead */
  object-fit: contain;
  display: block;
  pointer-events: none;
}

.tl-item-text {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 6px;
  font-family: var(--f9y-font-display);
  font-weight: 400;
  font-size: 15px;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  line-height: 1.1;
  outline: none;
  overflow: hidden;
}

.tl-item-remove {
  position: absolute;
  top: 2px;
  right: 2px;
  width: 18px;
  height: 18px;
  border: none;
  border-radius: 50%;
  background: rgba(16, 19, 17, 0.75);
  color: #fff;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 2;
}

.tl-item:hover .tl-item-remove {
  display: flex;
}

.tl-item.sortable-ghost {
  opacity: 0.35;
}

.tl-item.sortable-chosen .tl-item-img {
  filter: brightness(1.08);
}

/* --- pool --- */

.tl-pool-section {
  margin-top: 24px;
}

.tl-pool-label {
  font-family: var(--f9y-font-display);
  font-weight: 400;
  text-transform: uppercase;
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--f9y-text-dim);
  margin-bottom: 8px;
}

.tl-pool-label span {
  font-family: var(--f9y-font-body);
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  color: var(--f9y-text-faint);
}

.tl-pool {
  /* unlike a tier's item row, the pool isn't height-constrained/exported —
     restore normal wrapping and fixed item size here */
  flex-wrap: wrap;
  overflow: visible;
  min-height: 96px;
  padding: 10px;
  border: 1px dashed var(--f9y-border);
  border-radius: var(--f9y-radius-sm);
  background: var(--f9y-surface);
}

.tl-pool .tl-item {
  width: 76px;
  height: 76px;
}

.tl-pool.tl-pool-empty::before {
  content: 'Drop images here, or use "+ Add Images" above';
  color: var(--f9y-text-faint);
  font-size: 13px;
  padding: 6px;
}

.tl-pool.tl-drag-over {
  border-color: var(--f9y-accent);
  background: var(--f9y-surface-2);
}

/* --- export state: hide UI chrome that shouldn't appear in the PNG --- */

.exporting .tl-tier-controls,
.exporting .tl-tier-color,
.exporting .tl-item-remove {
  display: none !important;
}

.exporting #board-title:hover,
.exporting #board-subtitle:hover {
  background: transparent;
}

/* the subtle border/shadow on .tl-capture is only there to separate the
   card from the page background while editing — html2canvas captures it
   as part of the element, so it shows up as a faint light-colored edge
   around the exported PNG unless it's stripped for the capture. */
.tl-capture.exporting {
  border-color: transparent;
  box-shadow: none;
}

/* --- toast --- */

.tl-toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  background: var(--f9y-surface-3);
  border: 1px solid var(--f9y-accent);
  color: var(--f9y-text);
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 13px;
  z-index: 50;
}

@media (max-width: 640px) {
  .tl-tier-label {
    flex-basis: 84px;
  }
  .tl-item {
    width: 64px;
    height: 64px;
  }
}
