/* User portfolios (/portfolios)
   Index, show and the four forms all run in the site's tape idiom —
   flat panels, hairline rules, mono figures — under the `shelf-` and
   `folio-` classes below. */

/* ================================================================
   Portfolio and holding forms — /portfolios/new, /portfolios/:id/edit,
   and the holding forms underneath them. The cover sheet of a book,
   read in the same idiom as the shelf and the book itself.

   The page caps at a reading column rather than spanning the shelf's
   full width: one thing is being specified, and a 1100px field of
   nothing beside a name box reads as a page that lost its content.
   Fields divide on hairlines, the sheet closes on a recessed foot
   carrying the commit, and nothing lifts.
   ================================================================ */

.folio-form-page {
  padding: 2.5rem 0 4.5rem;
}

.folio-form-shell {
  max-width: 40rem;
  margin: 0 auto;
}

/* ============ Masthead ============ */
.folio-form-head {
  margin-bottom: 1.75rem;
}

.folio-form-title {
  margin: 0.9rem 0 0;
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 4vw, 2.9rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.005em;
  color: var(--text-bright);
  overflow-wrap: anywhere;
}

/* Which book is being written into — a label, so it takes the mono
   micro-label role rather than reading as prose. */
.folio-form-sub {
  margin: 0.6rem 0 0;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  line-height: 1.5;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

/* ============ The sheet ============ */
.folio-sheet {
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}

.folio-sheet-errors {
  padding: 1.05rem 1.35rem 1.15rem;
  border-bottom: 1px solid var(--border);
  background: rgba(194, 95, 76, 0.08);
}

.folio-sheet-errors-title {
  margin: 0 0 0.55rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--danger);
}

.folio-sheet-errors ul {
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--text);
}
.folio-sheet-errors li + li { margin-top: 0.3rem; }

/* The figure the holder is working against, stated as a readout rather
   than as a notice — it is a number, and numbers here read in mono. */
.folio-sheet-readout {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.8rem 1.35rem 0.85rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-darker);
}

.folio-sheet-readout-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}

.folio-sheet-readout-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-bright);
  white-space: nowrap;
}
/* Weight still unassigned is a pending state, so it takes the caution
   color — the same reading the shelf gives a book short of 100%. */
.folio-sheet-readout-value--open { color: var(--secondary); }

/* ============ Fields ============ */
.folio-field {
  padding: 1.3rem 1.35rem;
}
.folio-field + .folio-field { border-top: 1px solid var(--border-light); }

.folio-field-label {
  display: block;
  width: 100%;
  margin: 0 0 0.6rem;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}

.folio-input {
  display: block;
  width: 100%;
  padding: 0.8rem 0.9rem;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 2px;
  color: var(--text-bright);
  font-family: inherit;
  font-size: 0.95rem;
  line-height: 1.4;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.folio-input::placeholder { color: var(--text-muted); }
.folio-input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--ring);
}

/* A figure the holder types is a figure the book will compare, so it
   is set in the same tabular mono the book reads it back in. The
   stepper is browser chrome that belongs to no part of this system;
   arrow keys still increment without it. */
.folio-input--figure {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
  appearance: textfield;
}
.folio-input--figure::-webkit-outer-spin-button,
.folio-input--figure::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Ticker search: the field accepts a symbol or a company name, so it
   takes mono without forcing case. */
.folio-input--ticker {
  font-family: var(--font-mono);
  letter-spacing: 0.03em;
}

.folio-field-hint {
  margin: 0.6rem 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text-muted);
}

.folio-field-search { position: relative; }

/* Unit well: the mark sits inside the field's box, divided from the
   figure by a rule rather than floated beside it. */
.folio-input-unit {
  display: flex;
  align-items: stretch;
  background: var(--bg-surface);
  border: 1px solid var(--border);
  border-radius: 2px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.folio-input-unit:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--ring);
}
.folio-input-unit .folio-input {
  border: 0;
  border-radius: 0;
  background: transparent;
}
.folio-input-unit .folio-input:focus { box-shadow: none; }

.folio-input-unit-mark {
  display: flex;
  align-items: center;
  padding: 0 0.9rem;
  border-left: 1px solid var(--border);
  background: var(--bg-main);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text-muted);
}

/* ============ Two-position selector ============ */
/* One bordered instrument split by a rule, not two cards with a gap.
   The selected half carries the system's inset marker on its leading
   edge — a rule drawn with a shadow, never a lift. */
.folio-switch {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--border);
  background: var(--bg-surface);
}

.folio-switch-opt {
  --folio-mark: inset 0 2px 0 var(--primary);
  position: relative;
  display: block;
  padding: 0.95rem 1.05rem 1.05rem;
  cursor: pointer;
  transition: background 0.15s ease;
}
.folio-switch-opt + .folio-switch-opt { border-left: 1px solid var(--border); }
.folio-switch-opt:hover { background: var(--bg-highlight); }

/* Visually hidden but still focusable: the retired rule used
   display:none, which took the whole group off the keyboard. */
.folio-switch-input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.folio-switch-opt:has(.folio-switch-input:focus-visible) {
  z-index: 1;
  box-shadow: 0 0 0 3px var(--ring);
}
.folio-switch-opt:has(.folio-switch-input:checked) {
  background: var(--bg-highlight);
  box-shadow: var(--folio-mark);
}
.folio-switch-opt:has(.folio-switch-input:checked):has(.folio-switch-input:focus-visible) {
  box-shadow: var(--folio-mark), 0 0 0 3px var(--ring);
}

.folio-switch-name {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text);
  transition: color 0.15s ease;
}
.folio-switch-opt:has(.folio-switch-input:checked) .folio-switch-name {
  color: var(--text-bright);
}

.folio-switch-desc {
  display: block;
  margin-top: 0.4rem;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--text-muted);
}

/* Switching the measure on a book that already holds positions leaves
   them without a figure in the new one — caution, not direction. */
.folio-switch-note {
  margin: 0.75rem 0 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--secondary);
}

/* ============ Foot ============ */
.folio-sheet-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.75rem;
  padding: 1.1rem 1.35rem;
  border-top: 1px solid var(--border);
  background: var(--bg-darker);
}

/* ============ Responsive ============ */
@media (max-width: 768px) {
  .folio-form-page { padding: 1.75rem 0 3rem; }
  .folio-form-head { margin-bottom: 1.35rem; }
  .folio-form-title { font-size: clamp(1.85rem, 8vw, 2.4rem); }

  .folio-field { padding: 1.15rem 1rem; }
  .folio-sheet-errors { padding: 1rem; }
  .folio-sheet-readout { padding: 0.75rem 1rem; }

  /* The instrument reads vertically; its divider and its marker turn
     with it. */
  .folio-switch { grid-template-columns: 1fr; }
  .folio-switch-opt {
    --folio-mark: inset 2px 0 0 var(--primary);
  }
  .folio-switch-opt + .folio-switch-opt {
    border-left: 0;
    border-top: 1px solid var(--border);
  }

  .folio-sheet-foot {
    flex-direction: column-reverse;
    align-items: stretch;
    padding: 1rem;
  }
  .folio-sheet-foot .btn { width: 100%; }
}

/* Empty State (index page; container styling comes from the shared
   .empty-state in assets.css) */
.empty-state-icon {
  margin-bottom: 1.5rem;
  color: var(--text-muted);
}

.empty-state h3 {
  margin: 0 0 0.5rem;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-bright);
}

.empty-state p {
  margin: 0 0 1.5rem;
  color: var(--text-muted);
}

/* ================================================================
   Portfolio show (/portfolios/:id) — the holder's own book, read in
   the site's tape idiom. Allocation weight is the holder's choice,
   not a market result, so every bar here stays in the neutral sage
   rather than the gain/loss vocabulary.
   ================================================================ */

/* ============ Masthead ============ */
.folio-masthead {
  padding: 1.5rem 0 2.5rem;
}

.folio-utility {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 2rem;
}

.folio-back {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
  text-decoration: none;
  padding: 0.4rem 0.1rem;
  transition: color 0.15s ease;
}
/* The one motion flourish the button system allows: a directional
   control moves its arrow, and nothing else. */
.folio-back svg {
  width: 0.85rem;
  height: 0.85rem;
  flex: none;
  transition: transform 0.15s ease;
}
.folio-back:hover { color: var(--text-bright); }
.folio-back:hover svg { transform: translateX(-3px); }
.folio-back:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
  border-radius: 2px;
}

.folio-tools {
  display: flex;
  gap: 0.6rem;
}

.folio-name {
  margin: 0 0 0.5rem;
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 4.5vw, 3.4rem);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: 0.005em;
  color: var(--text-bright);
  overflow-wrap: anywhere;
}

.folio-kind {
  margin: 0 0 1.75rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}

/* The rule is the gutter: cells divide on hairlines, never on gaps. */
.folio-board {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  margin: 0;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}

.folio-cell {
  padding: 1.1rem 1.35rem 1.2rem;
}
.folio-cell + .folio-cell { border-left: 1px solid var(--border); }

.folio-cell dt {
  margin: 0 0 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
}

.folio-cell dd {
  margin: 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: clamp(1.5rem, 2.4vw, 1.9rem);
  font-weight: 600;
  line-height: 1.1;
  color: var(--text-bright);
}

/* Weight still unassigned is a pending state, so it takes the caution
   color until the book closes at 100. */
.folio-cell dd.folio-open { color: var(--secondary); }

.folio-currency {
  font-size: 0.62em;
  color: var(--text-muted);
  margin-right: 0.08em;
}

.folio-ratio {
  display: block;
  width: 100%;
  max-width: 160px;
  height: 3px;
  margin-top: 0.55rem;
  background: var(--bg-highlight);
  overflow: hidden;
}
.folio-ratio-fill {
  display: block;
  height: 100%;
  background: var(--info);
  transform-origin: left center;
  animation: folio-bar-draw 0.55s cubic-bezier(0.16, 1, 0.3, 1) both;
}

@keyframes folio-bar-draw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ============ Page bands ============ */
.folio-section {
  background: var(--bg-main);
  border-top: 1px solid var(--border);
  padding: 2.75rem 0 3.5rem;
}

/* ============ Holdings ledger ============ */
.folio-book {
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}
/* Percentage book: asset / last close / bar / allocation / tools. */
.folio-book--weight {
  --folio-cols: minmax(8rem, 1.9fr) 7.5rem minmax(4rem, 1fr) 6.5rem 8rem;
}
/* Shares book: asset / shares / last close / value / bar / weight / tools. */
.folio-book--shares {
  --folio-cols: minmax(7rem, 1.5fr) 5rem 7rem 7.5rem minmax(3rem, 0.7fr) 5rem 8rem;
}

.folio-head,
.folio-row,
.folio-foot {
  display: grid;
  grid-template-columns: var(--folio-cols);
  align-items: center;
  gap: 0 1rem;
  padding: 0.62rem 1.1rem;
}

.folio-head {
  border-bottom: 1px solid var(--border);
  background: var(--bg-darker);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text);
}
.folio-col--right { text-align: right; }

.folio-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}
.folio-item { display: block; }
.folio-item + .folio-item { border-top: 1px solid var(--border-light); }

.folio-row { transition: background 0.15s ease; }
.folio-row:hover { background: var(--bg-highlight); }

.folio-asset {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  min-width: 0;
}

.folio-ticker {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-bright);
  text-decoration: none;
  transition: color 0.15s ease;
}
.folio-ticker:hover { color: var(--primary); }
.folio-ticker:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
  border-radius: 2px;
}

.folio-exchange {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Recognition, not data — the name takes the row's remaining room and
   stops at one line so the figure columns keep their height. */
.folio-asset-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.72rem;
  color: var(--text-muted);
}

.folio-qty,
.folio-close,
.folio-value {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  color: var(--text);
  text-align: right;
  white-space: nowrap;
}
/* The row's money figure carries the reading weight. */
.folio-value { color: var(--text-bright); }

.folio-bar {
  display: block;
  width: 100%;
  height: 3px;
  background: var(--bg-highlight);
  overflow: hidden;
}
.folio-bar-fill {
  display: block;
  height: 100%;
  background: var(--info);
  transform-origin: left center;
  animation: folio-bar-draw 0.55s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.folio-weight {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-bright);
  text-align: right;
  white-space: nowrap;
}

.folio-void { color: var(--text-dim); }

.folio-rowtools {
  display: flex;
  justify-content: flex-end;
  gap: 1rem;
}

.folio-tool {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-muted);
  text-decoration: none;
  padding: 0.3rem 0.1rem;
  transition: color 0.15s ease;
}
.folio-tool:hover { color: var(--text-bright); }
.folio-tool--danger:hover { color: var(--danger); }
.folio-tool:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
  border-radius: 2px;
}

.folio-foot {
  border-top: 1px solid var(--border);
  background: var(--bg-darker);
}

.folio-foot-label {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text);
}

.folio-foot-value,
.folio-foot-weight {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-bright);
  text-align: right;
  white-space: nowrap;
}

.folio-empty {
  padding: 3rem 2rem;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  text-align: center;
}

.folio-empty-title {
  margin: 0 0 0.5rem;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--text-bright);
}

.folio-empty-hint {
  margin: 0 0 1.5rem;
  color: var(--text-muted);
}

/* ============ Channels calling the holdings ============ */
.folio-voices {
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}

.folio-voices-head,
.folio-voice {
  display: grid;
  grid-template-columns: 2.6rem minmax(11rem, 1.2fr) minmax(0, 2fr) 7rem;
  align-items: center;
  gap: 0 1rem;
  padding: 0.62rem 1.1rem;
}

.folio-voices-head {
  border-bottom: 1px solid var(--border);
  background: var(--bg-darker);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text);
}

.folio-voices-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}
.folio-voice + .folio-voice { border-top: 1px solid var(--border-light); }
.folio-voice { transition: background 0.15s ease; }
.folio-voice:hover { background: var(--bg-highlight); }

.folio-voice-rank {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
  color: var(--text-dim);
}

.folio-voice-channel {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}

.folio-voice-avatar {
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid var(--border);
}
.folio-voice-avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.folio-voice-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-bright);
  text-decoration: none;
  transition: color 0.15s ease;
}
a.folio-voice-name:hover { color: var(--primary); }
a.folio-voice-name:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
  border-radius: 2px;
}

.folio-voice-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  min-width: 0;
}

.folio-tag {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 2px;
  padding: 0.18rem 0.4rem;
  text-decoration: none;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.folio-tag:hover {
  border-color: var(--text-muted);
  color: var(--text-bright);
}
.folio-tag:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

.folio-voice-count {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  color: var(--text);
  text-align: right;
  white-space: nowrap;
}

.folio-cell-label { display: none; }

@media (prefers-reduced-motion: reduce) {
  .folio-ratio-fill,
  .folio-bar-fill { animation: none; }
}

/* ============ Responsive ============ */
/* Between the full row and the stacked one the legal name has no room
   beside the figure columns; ticker and exchange still identify the
   asset, and the name returns once the row stacks. */
@media (max-width: 1024px) and (min-width: 769px) {
  .folio-book--weight {
    --folio-cols: minmax(6rem, 1.2fr) 7rem minmax(3rem, 0.8fr) 6.5rem 7.5rem;
  }
  .folio-book--shares {
    --folio-cols: minmax(5rem, 1fr) 4.5rem 6.5rem 7rem minmax(2.5rem, 0.6fr) 4.75rem 7.5rem;
  }
  .folio-head,
  .folio-row,
  .folio-foot {
    gap: 0 0.75rem;
    padding: 0.62rem 0.9rem;
  }
  .folio-asset-name { display: none; }
}

@media (max-width: 768px) {
  .folio-masthead { padding: 1.25rem 0 2rem; }

  /* The strip reads vertically; the divider turns with it. */
  .folio-board { grid-template-columns: 1fr; }
  .folio-cell + .folio-cell {
    border-left: 0;
    border-top: 1px solid var(--border);
  }

  .folio-section { padding: 2rem 0 2.75rem; }

  .folio-head { display: none; }

  /* One holding reflows to three or four lines: the asset, then the
     allocation against its bar, then the prices, then the tools.
     Column headers give way to inline labels so no bare figure loses
     its name. */
  .folio-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      "asset  asset"
      "weight bar"
      "close  tools";
    align-items: end;
    gap: 0.7rem 1rem;
    padding: 0.95rem 1rem;
  }
  .folio-book--shares .folio-row {
    grid-template-areas:
      "asset  asset"
      "weight bar"
      "qty    close"
      "value  tools";
  }

  .folio-asset  { grid-area: asset; flex-wrap: wrap; }
  .folio-asset-name { flex-basis: 100%; }
  .folio-weight { grid-area: weight; text-align: left; font-size: 1.15rem; }
  .folio-bar    { grid-area: bar; align-self: center; }
  .folio-qty    { grid-area: qty; text-align: left; }
  .folio-close  { grid-area: close; text-align: left; }
  .folio-book--shares .folio-close { text-align: right; }
  .folio-value  { grid-area: value; text-align: left; }
  .folio-rowtools { grid-area: tools; align-self: end; }

  .folio-cell-label {
    display: block;
    margin-bottom: 0.25rem;
    font-family: var(--font-mono);
    font-size: 0.62rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--text-muted);
  }
  .folio-weight .folio-cell-label { display: none; }
  .folio-book--shares .folio-close .folio-cell-label { text-align: right; }

  .folio-foot {
    grid-template-columns: 1fr auto auto;
    gap: 0 1.25rem;
  }
  .folio-foot > span:empty { display: none; }

  .folio-voices-head { display: none; }

  .folio-voice {
    grid-template-columns: 2.6rem minmax(0, 1fr) auto;
    grid-template-areas:
      "rank channel count"
      "tags tags    tags";
    gap: 0.6rem 0.75rem;
    padding: 0.85rem 1rem;
  }
  .folio-voice-rank    { grid-area: rank; }
  .folio-voice-channel { grid-area: channel; }
  .folio-voice-count   { grid-area: count; }
  .folio-voice-tags    { grid-area: tags; }
  .folio-voice-tags:empty { display: none; }
  .folio-voice-count .folio-cell-label { display: none; }
}

@media (max-width: 480px) {
  .folio-utility {
    flex-wrap: wrap;
    gap: 0.75rem;
  }
  .folio-row { padding: 0.9rem 0.8rem; }
  .folio-voice { padding: 0.8rem 0.8rem; }
}

/* ================================================================
   Portfolio index (/portfolios) — the shelf: one record per book
   the holder keeps. Same tape idiom as the show page; the generic
   `folio-` helpers (tools, voids, labels, empty state) are shared.
   ================================================================ */

.shelf-masthead { padding: 2.5rem 0; }

.shelf-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.25rem 2rem;
  flex-wrap: wrap;
}

.shelf-sub {
  margin: 0;
  max-width: 58ch;
  color: var(--text-muted);
}

/* The rule is the gutter: columns divide on hairlines and tracked
   grid lines, never on card gaps. */
.shelf-book {
  --shelf-cols: minmax(11rem, 2fr) 6rem 8rem 9rem 8rem 5.5rem;
  border: 1px solid var(--border);
  background: var(--bg-elevated);
}

.shelf-colhead,
.shelf-row {
  display: grid;
  grid-template-columns: var(--shelf-cols);
  align-items: center;
  gap: 0 1rem;
}

.shelf-colhead {
  padding: 0.62rem 1.1rem;
  border-bottom: 1px solid var(--border);
  background: var(--bg-darker);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text);
}

.shelf-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}
.shelf-item { display: block; }
.shelf-item + .shelf-item { border-top: 1px solid var(--border-light); }

/* These rows are the page's primary records, so they sit a step
   roomier than the holding rows inside a single book. */
.shelf-row {
  padding: 0.85rem 1.1rem;
  transition: background 0.15s ease;
}
.shelf-row:hover { background: var(--bg-highlight); }

.shelf-id {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  min-width: 0;
}

.shelf-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-bright);
  text-decoration: none;
  transition: color 0.15s ease;
}
.shelf-name:hover { color: var(--primary); }
.shelf-name:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
  border-radius: 2px;
}

.shelf-kind {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.11em;
  color: var(--text-muted);
  white-space: nowrap;
}

.shelf-count,
.shelf-alloc,
.shelf-value,
.shelf-opened {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  color: var(--text);
  text-align: right;
  white-space: nowrap;
}

/* The book's headline figure carries the reading weight. */
.shelf-alloc,
.shelf-value {
  font-weight: 600;
  color: var(--text-bright);
}

/* A book still short of 100% is pending, so it takes the caution
   color until the allocation closes — same reading as the show page. */
.shelf-alloc.shelf-open { color: var(--secondary); }

.shelf-opened { color: var(--text-muted); }

/* Void cells mark the reading the other allocation kind doesn't have. */
.shelf-row .folio-void {
  font-weight: 400;
  color: var(--text-dim);
}

/* Own tools cell — the shared .folio-rowtools carries a grid-area that
   belongs to the show page's stacked holding rows. */
.shelf-tools {
  display: flex;
  justify-content: flex-end;
  gap: 1rem;
}

@media (max-width: 1024px) and (min-width: 769px) {
  .shelf-book { --shelf-cols: minmax(8rem, 1.6fr) 5rem 7rem 8rem 7.5rem 4.5rem; }
  .shelf-colhead,
  .shelf-row { gap: 0 0.75rem; }
  .shelf-colhead { padding: 0.62rem 0.9rem; }
  .shelf-row { padding: 0.85rem 0.9rem; }
}

@media (max-width: 768px) {
  .shelf-masthead { padding: 1.75rem 0 2rem; }

  .shelf-head {
    flex-direction: column;
    align-items: flex-start;
  }

  .shelf-colhead { display: none; }

  /* One book reflows to labelled figure pairs; the void cells drop
     out since the inline label already names what remains. */
  .shelf-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: end;
    gap: 0.7rem 1rem;
    padding: 0.95rem 1rem;
  }

  .shelf-id {
    grid-column: 1 / -1;
    flex-wrap: wrap;
  }

  .shelf-count,
  .shelf-alloc,
  .shelf-value,
  .shelf-opened { text-align: left; }

  .shelf-row .folio-void { display: none; }
}

@media (max-width: 480px) {
  .shelf-row { padding: 0.9rem 0.8rem; }
}
