/* Gallery — modernised skin over the shared warm/blueprint palette.
   Same colours as the rest of the app (cream / emerald / amber / charcoal),
   with square corners, gentle elevation, and roomier spacing for a cleaner,
   more contemporary feel. */

body {
  font-family: var(--sans);
  color: var(--charcoal);
  background-color: var(--cream);
  background-image:
    linear-gradient(var(--grid-minor) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-minor) 1px, transparent 1px),
    linear-gradient(var(--grid-major) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-major) 1px, transparent 1px);
  background-size: 22px 22px, 22px 22px, 110px 110px, 110px 110px;
}



/* ─── Sidebar ─── */
/* Nearly opaque: at 0.6 the page's blueprint grid read straight through the
   filter list and fought the labels. A hairline edge replaces the grid as the
   separator from the card area.

   The sidebar collapses to a thin rail (`.library-sidebar--collapsed`, driven
   by `bindLibrarySidebar` in libraryCards.js): at 176–208px it is half a
   phone's screen, and the cards it squeezed were narrower than the sidebar
   itself. Below 900px an *open* sidebar floats over the cards rather than
   pushing them, so opening the filters never re-creates that squeeze — see the
   narrow-screen media queries at the end of this file. Padding lives on
   `.library-sidebar-content` so the collapsed rail keeps none of it. */
.library-body { position: relative; }

.library-sidebar {
  --library-sidebar-rail-w: 26px;

  position: relative;
  background: rgba(253,248,240,0.94) !important;
  border-color: var(--border-warm) !important;
}

.library-sidebar-content {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 8px 16px 14px;
}

/* Expanded: a small chevron in the sidebar's top-right corner. */
.library-sidebar-toggle {
  position: absolute;
  top: 6px;
  right: 5px;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  color: rgba(127, 85, 28, .76);
  background: transparent;
  border: 1px solid rgba(154, 106, 36, .52);
  cursor: pointer;
  transition: color .12s, background-color .12s, border-color .12s;
}
.library-sidebar-toggle:hover {
  color: #7f551c;
  background: rgba(154, 106, 36, .07);
  border-color: rgba(127, 85, 28, .78);
}
.library-sidebar-toggle:focus-visible {
  outline: 1px solid var(--emerald);
  outline-offset: 1px;
}
.library-sidebar-chevron { transition: transform .16s ease; }
.library-sidebar-toggle-label { display: none; }

/* Collapsed: the toggle *is* the rail — full height, with a vertical label. */
.library-sidebar--collapsed {
  width: var(--library-sidebar-rail-w) !important;
}
.library-sidebar--collapsed .library-sidebar-content { display: none; }
.library-sidebar--collapsed .library-sidebar-toggle {
  inset: 0;
  width: 100%;
  height: 100%;
  flex-direction: column;
  justify-content: flex-start;
  gap: 8px;
  padding-top: 8px;
  border: 0;
}
.library-sidebar--collapsed .library-sidebar-chevron { transform: rotate(180deg); }
.library-sidebar--collapsed .library-sidebar-toggle-label {
  display: block;
  writing-mode: vertical-rl;
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Only ever visible under the narrow-screen rules at the end of this file. */
.library-sidebar-backdrop { display: none; }

.sidebar-label {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amber-ink);
  padding: 0 10px 0 6px;
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.sidebar-label::before {
  content: '';
  width: 14px;
  height: 1px;
  background: var(--amber);
  flex-shrink: 0;
}
.filter-section + .filter-section {
  margin-top: 6px;
  padding-top: 14px;
  border-top: 1px solid rgba(120,80,30,0.14);
}
.clear-filters-btn {
  border: 1px solid var(--border-warm);
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: var(--fs-sm) !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase !important;
  color: var(--charcoal) !important;
  background: rgba(120,80,30,0.03) !important;
  transition: border-color 0.15s, color 0.15s, background 0.15s !important;
}
.clear-filters-btn:hover {
  border-color: rgba(43,106,100,0.3);
  color: var(--emerald) !important;
  background: rgba(43,106,100,0.08) !important;
}

.tag-btn {
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: var(--fs-sm) !important;
  letter-spacing: 0.07em !important;
  text-transform: uppercase !important;
  color: var(--charcoal) !important;
  transition: background 0.15s, color 0.15s !important;
}
.tag-btn:not(.tag-btn-active):hover {
  background: rgba(120,80,30,0.06) !important;
  color: var(--charcoal) !important;
}
.tag-btn-active {
  background: rgba(43,106,100,0.12) !important;
  color: var(--emerald) !important;
  font-weight: 600 !important;
}
/* The markup tags inactive badges `bg-gray-100 text-gray-500`; both are cool
   grays that read as a foreign element on cream. Repaint them warm. */
.count-badge {
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: var(--fs-2xs) !important;
  padding: 1px 6px !important;
  background: rgba(120,80,30,0.08) !important;
  color: var(--warm-gray) !important;
}
.tag-btn-active .count-badge {
  background: var(--emerald) !important;
  color: var(--white) !important;
}

/* ─── Card area ─── */
/* The three library pages own their padding here rather than through Tailwind's
   `p-6`, so the narrow-screen tier below can buy the cards back ~20px of width. */
.library-main { padding: 24px; }

/* The grids used to be inline `style=` on the wrapper each page's JS emits;
   they live here so they can respond to the viewport. Sketch/Moodboard cards
   keep a fixed 310px so a half-empty library doesn't stretch two cards across a
   desktop row; Pattern cards have always filled the row. */
.library-grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 310px), 310px));
  justify-content: start;
}
.library-grid--products {
  gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  justify-content: stretch;
}

/* ─── Pattern cards ─── */
.library-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}

.library-heading p {
  margin: 0 0 4px;
  color: var(--amber-ink);
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.library-heading h1 {
  margin: 0;
  color: var(--charcoal);
  font-family: var(--serif);
  font-size: clamp(24px, 3vw, 34px);
  line-height: 1;
}

#library-count {
  color: var(--warm-gray);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.library-error {
  display: flex;
  max-width: 520px;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin-top: 32px;
  padding: 18px;
  border-left: 3px solid #b3261e;
  background: var(--cream-surf);
  color: var(--charcoal);
}

.library-error span { color: var(--warm-gray); }

.library-error button {
  margin-top: 4px;
  padding: 7px 12px;
  border: 0;
  background: var(--charcoal);
  color: var(--white);
  cursor: pointer;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.library-error button:hover { background: var(--emerald); }

.card-preview svg { width: 100%; height: 100%; display: block; }

article[data-id] {
  background: var(--cream-surf) !important;
  border: 1px solid var(--border-warm) !important;
  border-radius: 0 !important;
  box-shadow: 0 1px 3px rgba(28,26,23,0.06) !important;
  transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease !important;
}
article[data-id]:hover {
  transform: translateY(-3px) !important;
  border-color: rgba(43,106,100,0.45) !important;
  box-shadow: 0 12px 28px rgba(28,26,23,0.12) !important;
}

/* Thumbnails are thin single-stroke sketches, so the dot grid behind them is
   kept lighter than the page grid — otherwise it competes with the drawing. */
.card-preview {
  background-color: var(--cream) !important;
  background-image:
    radial-gradient(rgba(120,80,30,0.07) 1px, transparent 1px) !important;
  background-size: 14px 14px !important;
  border-bottom: 1px solid rgba(120,80,30,0.14) !important;
}

article[data-id] h3 {
  font-family: var(--serif) !important;
  font-size: 18px !important;
  font-weight: 700 !important;
  letter-spacing: 0.005em;
}
article[data-id] h3.card-name:hover {
  color: var(--emerald) !important;
}

article[data-id] .bg-emerald-50 {
  background: rgba(43,106,100,0.1) !important;
  color: var(--emerald) !important;
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: var(--fs-2xs) !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase;
  padding: 2px 9px !important;
}

article[data-id] .text-gray-400 {
  font-family: var(--mono) !important;
  font-size: var(--fs-sm) !important;
  color: var(--warm-gray) !important;
}

.card-menu-btn {
  border-radius: 0 !important;
}
.card-menu-btn:hover {
  background: rgba(120,80,30,0.07) !important;
}

/* ─── Card brand/type dropdowns ─── */
/* The native arrow sits inside the padding box, so a long value ("Maison
   carrillo") ran straight under it. `appearance: none` drops the OS arrow for
   the same two-gradient chevron the account modal uses, and padding-right
   reserves a lane for it that the text is then clipped at.
   Use `background-color` — never the `background` shorthand — in this rule and
   its states, or the chevron gets wiped along with the fill. */
.card-select {
  /* Fixed 60/40 split — brand names run longer than type names, so the row is
     divided by field rather than evenly, and a width that tracked the selected
     value made the boxes ragged and different on every card. The share is set
     per field just below. A value longer than its share ellipsises; `title`
     (set in gallery.js) carries the full text. */
  min-width: 0;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  text-transform: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--charcoal);
  background-color: rgba(120,80,30,0.04);
  border: 1px solid var(--border-warm);
  border-radius: 0;
  /* Since the width is fixed, the chevron lane is kept as narrow as it can be
     without the text touching it: the chevron occupies 3–11px from the right
     edge, padding-right stops the text at 18px. */
  padding: 7px 18px 7px 8px;
  cursor: pointer;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--warm-gray) 50%),
                    linear-gradient(135deg, var(--warm-gray) 50%, transparent 50%);
  background-position: calc(100% - 11px) center, calc(100% - 7px) center;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
  transition: border-color 0.15s, background-color 0.15s;
}
/* 3:2 on a zero basis = 60/40 of the row once the gap is taken out. */
.card-select[data-field="brand"] { flex: 3 1 0; }
.card-select[data-field="type"]  { flex: 2 1 0; }

.card-select:hover { border-color: rgba(120, 80, 30, 0.42); background-color: rgba(120,80,30,0.07); }
.card-select:focus { outline: none; border-color: var(--emerald); }

#empty-new-btn {
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: var(--fs-sm) !important;
  letter-spacing: 0.1em !important;
  text-transform: uppercase !important;
  background: var(--charcoal) !important;
  padding: 9px 20px !important;
  transition: background 0.15s, transform 0.15s !important;
}
#empty-new-btn:hover { background: var(--emerald) !important; transform: translateY(-1px); }

#user-menu span   { font-family: var(--mono) !important; font-size: var(--fs-sm) !important; letter-spacing: 0.05em !important; }
#user-menu button {
  border-radius: 0 !important;
  font-family: var(--mono) !important;
  font-size: var(--fs-sm) !important;
  letter-spacing: 0.08em !important;
  text-transform: uppercase !important;
}

/* ─── Library controls bar (search + sort) ─── */
.library-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
.library-search-wrap {
  position: relative;
  flex: 1 1 240px;
  max-width: 420px;
  min-width: 180px;
}
.library-search-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--amber-ink);
  pointer-events: none;
}
.library-search {
  width: 100%;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  color: var(--charcoal);
  background: var(--cream-surf);
  border: 1px solid var(--border-warm);
  border-radius: 0;
  padding: 9px 14px 9px 36px;
  outline: none;
  box-shadow: 0 1px 2px rgba(28,26,23,0.03);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.library-search::placeholder { color: var(--warm-gray); }
.library-search:hover { border-color: rgba(120, 80, 30, 0.42); }
.library-search:focus {
  border-color: var(--emerald);
  box-shadow: 0 0 0 3px rgba(43,106,100,0.12);
}
.library-search::-webkit-search-cancel-button { cursor: pointer; }

.library-sort-wrap {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;   /* far end of the bar; inert once it wraps to full rows */
}
.library-sort-label {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--amber-ink);
}
.library-sort {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
  color: var(--charcoal);
  background: var(--cream-surf);
  border: 1px solid var(--border-warm);
  border-radius: 0;
  padding: 8px 14px;
  cursor: pointer;
  outline: none;
  box-shadow: 0 1px 2px rgba(28,26,23,0.03);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.library-sort:hover { border-color: rgba(120, 80, 30, 0.42); }
.library-sort:focus {
  border-color: var(--emerald);
  box-shadow: 0 0 0 3px rgba(43,106,100,0.12);
}

/* The "Nouveau …" action moved out of the header into this bar (see the
   `new_button` macro), so it reads the same on a phone as on a desktop instead
   of collapsing to a bare "+". `order` puts it first no matter where the macro
   is called from, so the bar reads action → search → sort, with sort pushed to
   the far end (`.library-sort-wrap`'s auto margin). Same charcoal→emerald
   treatment as the empty-state `#empty-new-btn`. */
.library-new-btn {
  order: -1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 16px;
  border: 0;
  border-radius: 0;
  background: var(--charcoal);
  color: var(--white);
  cursor: pointer;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background 0.15s ease, transform 0.15s ease;
}
.library-new-btn:hover { background: var(--emerald); transform: translateY(-1px); }
.library-new-btn:focus-visible { outline: 2px solid var(--emerald); outline-offset: 2px; }
.library-new-btn svg { flex: 0 0 auto; }

/* ─── Per-card actions menu (kebab dropdown) ─── */
.card-menu-pop {
  position: fixed;
  z-index: 60;
  min-width: 150px;
  background: var(--cream-surf);
  border: 1px solid var(--border-warm);
  border-radius: 0;
  box-shadow: 0 12px 32px rgba(28, 26, 23, 0.16);
  padding: 6px;
  display: flex;
  flex-direction: column;
}
.card-menu-item {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: left;
  color: var(--charcoal);
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 8px 11px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.card-menu-item:hover {
  background: rgba(43, 106, 100, 0.1);
  color: var(--emerald);
}
.card-menu-item--danger:hover {
  background: rgba(190, 50, 40, 0.1);
  color: #b91c1c;
}

/* ─── Narrow screens (phones, split-screen windows) ────────────────────────
   900px is where the sidebar stops sharing the row and starts floating over the
   cards — it matches the breakpoint `bindLibrarySidebar` collapses at, so an
   open sidebar is only ever floating below it. 700px is where the card area
   itself is too tight for the desktop spacing. The two tiers are separate on
   purpose: a tablet in portrait wants the floating sidebar but not the phone
   spacing. Keep the 900 here in step with SIDEBAR_NARROW in libraryCards.js. */

@media (max-width: 900px) {
  /* Open + narrow: float over the cards instead of squeezing them. The rail is
     out of the flex row here, so the cards keep the full width either way. */
  .library-sidebar:not(.library-sidebar--collapsed) {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    z-index: 45;
    box-shadow: 6px 0 24px rgba(28, 26, 23, 0.16);
    /* Fully opaque here: the resting 0.94 is tuned for the page's flat
       blueprint grid, and over card thumbnails it left the filter labels
       unreadable. */
    background: var(--cream) !important;
  }
  .library-sidebar:not(.library-sidebar--collapsed) + .library-sidebar-backdrop {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 44;
    background: rgba(28, 26, 23, 0.28);
  }
}

@media (max-width: 700px) {
  .library-main { padding: 16px 14px 28px; }

  /* The count drops under the title, which frees the right half of this block
     for the "Nouveau …" button sitting just below it. */
  .library-heading {
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    margin-bottom: 10px;
  }

  .library-controls { gap: 10px; margin-bottom: 18px; }
  /* Search and sort each take a full row: at ~340px a side-by-side pair left
     the search box too short to read a pattern name back. */
  .library-search-wrap { flex: 1 1 100%; max-width: none; min-width: 0; }
  .library-sort-wrap { flex: 1 1 100%; }
  .library-sort { flex: 1 1 auto; min-width: 0; }
  /* "Nouveau …" becomes a square tile at the top-right of the card area: the
     glyph over the label, and the label itself wrapped onto two lines by the
     tile's width rather than by any markup, so every wording ("Nouveau patron",
     "New board", …) breaks at its own space. `order` floats it above the
     full-width search, `margin-left` pins it right. */
  .library-new-btn {
    order: -1;
    flex: 0 0 auto;
    flex-direction: column;
    gap: 3px;
    width: 88px;
    height: 76px;
    margin-left: auto;
    padding: 8px 6px;
    white-space: normal;
    text-align: center;
    line-height: 1.3;
    letter-spacing: 0.06em;
  }

  /* Where the page has a heading, the tile lines up with the title instead of
     costing a row of its own. It stays in the controls bar in the DOM — that is
     where it belongs on a wide screen — so lifting it means positioning it
     against `.library-main`, whose padding the offsets mirror. The heading
     reserves the lane on its right so a long title can never run underneath,
     and its bottom margin keeps the taller tile clear of the search box.
     Pattern/Moodboard have no heading and keep the in-flow placement above. */
  .library-main { position: relative; }
  .library-heading { padding-right: 116px; margin-bottom: 18px; }
  .library-heading + .library-controls .library-new-btn {
    position: absolute;
    top: 16px;   /* = .library-main's padding-top */
    right: 14px; /* = .library-main's padding-right */
  }

  /* Cards share out the row rather than holding their desktop 310px: at a
     phone's ~344px that width left a dead margin, and in the 560–700px band it
     left room for a second column the fixed track could not use. Pattern cards
     already stretch, so only the gap changes for them. */
  .library-grid {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
    gap: 16px;
  }
  .library-grid--products { gap: 16px; }

  /* Finger-sized rows in the filter list (they are ~30px on desktop). */
  .library-sidebar-content .tag-btn,
  .library-sidebar-content .clear-filters-btn {
    padding-top: 9px !important;
    padding-bottom: 9px !important;
  }
}
