/* ==========================================================================
   Lake Mead Admin — Components
   Everything reusable. Consumes tokens.css; no literal colors.
   ========================================================================== */

/* ==========================================================================
   LAYOUT PRIMITIVES
   ========================================================================== */

/* A 12-column grid with a gap that matches the card rhythm. Children opt
   into spans with .col-N and stack below the mobile breakpoint. */
.row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--sp-5);
}
.row + .row { margin-top: var(--sp-5); }

.col-1  { grid-column: span 1; }
.col-2  { grid-column: span 2; }
.col-3  { grid-column: span 3; }
.col-4  { grid-column: span 4; }
.col-5  { grid-column: span 5; }
.col-6  { grid-column: span 6; }
/* Span every track of an auto-fit grid, whatever it resolved to this
   viewport. `span 6` would guess; `1 / -1` asks. */
.col-full { grid-column: 1 / -1; }
.col-7  { grid-column: span 7; }
.col-8  { grid-column: span 8; }
.col-9  { grid-column: span 9; }
.col-10 { grid-column: span 10; }
.col-11 { grid-column: span 11; }
.col-12 { grid-column: span 12; }

@media (max-width: 1200px) {
  .col-1, .col-2, .col-3 { grid-column: span 6; }
  .col-4, .col-5 { grid-column: span 6; }
  .col-7, .col-8, .col-9, .col-10, .col-11 { grid-column: span 12; }
}
@media (max-width: 760px) {
  .row > [class^="col-"] { grid-column: span 12; }
}

/* Auto-fitting grid for card decks that shouldn't be pinned to 12 columns. */
.grid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.grid--wide { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grid--tight { gap: var(--sp-3); grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

.stack   { display: flex; flex-direction: column; gap: var(--sp-4); }
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-3); }
.between { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }

/* ==========================================================================
   CARD
   ========================================================================== */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-sm);
  transition: background var(--t-base) var(--ease),
              border-color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease),
              transform var(--t-base) var(--ease);
}
/* Only interactive cards lift; static widgets stay put. */
.card--hover:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); }
.card--flat { box-shadow: none; }
.card--bare { background: none; border: 0; box-shadow: none; }

.card__head {
  display: flex;
  align-items: center;
  /* Wrap rather than overflow. A card header can accumulate a title plus
     several actions, and on a narrow viewport an unwrapped row pushes the
     whole page into a horizontal scroll — the one layout failure this theme
     treats as a defect. */
  flex-wrap: wrap;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
}
.card__head--bordered { border-bottom: 1px solid var(--line-soft); padding-bottom: var(--sp-4); }
.card__title {
  font-size: var(--fs-md);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--track-snug);
}
.card__sub { font-size: var(--fs-sm); color: var(--muted); font-weight: var(--fw-body); }
.card__actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  flex-wrap: wrap;          /* same reason as .card__head above */
  gap: var(--sp-2);
}

.card__body { flex: 1 1 auto; padding: var(--sp-5); }
.card__head + .card__body { padding-top: var(--sp-2); }
.card__foot {
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line-soft);
  background: var(--surface-alt);
  border-radius: 0 0 var(--radius-card) var(--radius-card);
}
/* Tables and lists run edge to edge inside a card. */
.card__flush { padding: 0; }

/* ==========================================================================
   BUTTONS
   Pill-shaped and heavy-weight, straight from the earlier portfolio project.
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  height: 38px;
  padding: 0 var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--surface-alt);
  color: var(--ink);
  font-size: var(--fs-sm);
  font-weight: var(--fw-heavy);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: transform var(--t-base) var(--ease),
              background var(--t-base) var(--ease),
              color var(--t-base) var(--ease),
              border-color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:disabled, .btn.is-disabled {
  opacity: .5;
  pointer-events: none;
}

/* Primary is aqua with ink text — aqua is too light for white type. */
.btn--primary { background: var(--aqua); color: var(--on-accent); }
.btn--primary:hover { background: var(--aqua-deep); color: var(--on-accent); }

.btn--blue { background: var(--blue); color: var(--white); }
.btn--blue:hover { background: var(--blue-deep); color: var(--white); }

.btn--danger { background: var(--rose); color: var(--white); }
.btn--danger:hover { background: var(--rose); color: var(--white); filter: brightness(.93); }

/* Ghost is the portfolio's secondary: hairline border, transparent fill. */
.btn--ghost {
  background: transparent;
  border-color: var(--line);
  color: var(--ink);
}
.btn--ghost:hover { background: var(--sidebar-hover); border-color: var(--muted); }

.btn--soft { background: var(--aqua-soft); color: var(--ink); }
.btn--soft:hover { background: var(--aqua); color: var(--on-accent); }

.btn--quiet { background: transparent; color: var(--muted); }
.btn--quiet:hover { background: var(--sidebar-hover); color: var(--ink); }

.btn--sm { height: 30px; padding: 0 var(--sp-4); font-size: var(--fs-xs); }
.btn--lg { height: 46px; padding: 0 var(--sp-7); font-size: var(--fs-base); }
.btn--block { width: 100%; }
.btn--icon { width: 38px; padding: 0; }
.btn--icon.btn--sm { width: 30px; }

/* Buttons joined into a segmented control. */
.btn-group { display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--radius-pill); background: var(--surface-alt); }
.btn-group .btn { height: 30px; background: transparent; color: var(--muted); font-size: var(--fs-xs); }
.btn-group .btn.is-active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
.btn-group .btn:hover { transform: none; color: var(--ink); }

/* ==========================================================================
   BADGES, CHIPS, DOTS
   ========================================================================== */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 3px var(--sp-3);
  border-radius: var(--radius-pill);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
  letter-spacing: .02em;
  white-space: nowrap;
}
.badge--aqua   { background: var(--aqua-soft);   color: var(--ink); }
.badge--blue   { background: var(--blue-soft);   color: var(--blue-ink); }
.badge--sun    { background: var(--sun-soft);    color: var(--sun-ink); }
.badge--rose   { background: var(--rose-soft);   color: var(--rose-ink); }
.badge--violet { background: var(--violet-soft); color: var(--violet-ink); }
.badge--muted  { background: var(--surface-alt); color: var(--muted); }
.badge--solid  { background: var(--aqua); color: var(--on-accent); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  height: 28px;
  padding: 0 var(--sp-3);
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
}
.chip button { color: var(--muted); font-size: var(--fs-2xs); }
.chip button:hover { color: var(--rose); }

/* Status dot — a legend marker that inherits the current color. */
.dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 8px;
}
.dot--aqua { color: var(--aqua-deep); }
.dot--blue { color: var(--blue); }
.dot--sun  { color: var(--sun); }
.dot--rose { color: var(--rose); }
.dot--violet { color: var(--violet); }
.dot--muted { color: var(--muted); }

/* ==========================================================================
   AVATARS
   ========================================================================== */
.avatar {
  position: relative;
  flex: 0 0 auto;
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--blue-soft);
  color: var(--blue-ink);
  font-size: var(--fs-sm);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--track-snug);
  overflow: hidden;
  user-select: none;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--xs { width: 24px; height: 24px; font-size: var(--fs-2xs); }
.avatar--sm { width: 30px; height: 30px; font-size: var(--fs-xs); }
.avatar--lg { width: 52px; height: 52px; font-size: var(--fs-lg); }
.avatar--xl { width: 84px; height: 84px; font-size: var(--fs-2xl); }
.avatar--square { border-radius: var(--radius-sm); }

.avatar--aqua   { background: var(--aqua-soft);   color: var(--ink); }
.avatar--sun    { background: var(--sun-soft);    color: var(--sun-ink); }
.avatar--rose   { background: var(--rose-soft);   color: var(--rose-ink); }
.avatar--violet { background: var(--violet-soft); color: var(--violet-ink); }

/* Presence indicator, clipped out of the avatar edge. */
.avatar__status {
  position: absolute;
  right: 0; bottom: 0;
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 2px solid var(--surface);
  background: var(--muted);
}
.avatar__status--online { background: var(--aqua-deep); }
.avatar__status--busy   { background: var(--rose); }
.avatar__status--away   { background: var(--sun); }

/* Overlapping stack for "who's on this" rows.
   The overlap is proportional to the avatar size — a flat -10px leaves a
   24px avatar with only 14px showing, which clips the initials. */
.avatar-stack { display: flex; }
.avatar-stack .avatar { border: 2px solid var(--surface); margin-left: -10px; }
.avatar-stack .avatar--xs { margin-left: -7px; }
.avatar-stack .avatar--sm { margin-left: -9px; }
.avatar-stack .avatar--lg { margin-left: -14px; }
.avatar-stack .avatar:first-child { margin-left: 0; }
.avatar-stack .avatar--more { background: var(--surface-alt); color: var(--muted); }

/* ==========================================================================
   TABLES
   Always wrap in .table-wrap so a wide table scrolls itself instead of
   forcing the page to scroll.
   ========================================================================== */
.table-wrap { width: 100%; overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; }

.table th, .table td {
  padding: var(--sp-3) var(--sp-5);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}
.table thead th {
  position: sticky;
  top: 0;
  background: var(--surface-alt);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.table tbody td {
  border-bottom: 1px solid var(--line-soft);
  font-size: var(--fs-base);
}
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background var(--t-fast) var(--ease); }
.table tbody tr:hover { background: var(--surface-alt); }
.table .num { text-align: right; }
.table--compact th, .table--compact td { padding: var(--sp-2) var(--sp-4); }
.table--striped tbody tr:nth-child(even) { background: var(--surface-alt); }

/* Sortable header affordance, driven by datatable.js. */
.table th[data-sort] { cursor: pointer; user-select: none; }
.table th[data-sort]:hover { color: var(--ink); }
.table th[data-sort]::after {
  content: "\f0dc";           /* fa-sort */
  font-family: "Font Awesome 7 Free";
  font-weight: 900;
  margin-left: var(--sp-2);
  opacity: .3;
  font-size: .9em;
}
.table th[data-sort][aria-sort="ascending"]::after  { content: "\f0de"; opacity: 1; }
.table th[data-sort][aria-sort="descending"]::after { content: "\f0dd"; opacity: 1; }

/* The identity cell: avatar + name over secondary line. */
.cell-user { display: flex; align-items: center; gap: var(--sp-3); }
.cell-user__name { font-weight: var(--fw-semi); color: var(--ink); line-height: 1.3; }
.cell-user__meta { font-size: var(--fs-xs); color: var(--muted); line-height: 1.3; }

/* ==========================================================================
   FORMS
   ========================================================================== */
.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field + .field { margin-top: var(--sp-5); }

.label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  color: var(--ink-soft);
}
.label .req { color: var(--rose); }
.hint { font-size: var(--fs-xs); color: var(--muted); }
.error-text { font-size: var(--fs-xs); color: var(--rose); font-weight: var(--fw-medium); }

.input, .select, .textarea {
  width: 100%;
  padding: 0 var(--sp-4);
  height: 42px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--fs-base);
  transition: border-color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease),
              background var(--t-base) var(--ease);
}
.textarea { height: auto; min-height: 110px; padding: var(--sp-3) var(--sp-4); resize: vertical; line-height: 1.6; }
.input::placeholder, .textarea::placeholder { color: var(--muted); }

.input:hover, .select:hover, .textarea:hover { border-color: var(--muted); }
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px var(--blue-soft);
}
.input:disabled, .select:disabled, .textarea:disabled {
  background: var(--surface-alt);
  color: var(--muted);
  cursor: not-allowed;
}
.input.is-invalid, .select.is-invalid, .textarea.is-invalid { border-color: var(--rose); }
.input.is-invalid:focus { box-shadow: 0 0 0 3px var(--rose-soft); }
.input.is-valid { border-color: var(--aqua-deep); }

/* Native select needs its own arrow once appearance is stripped. */
.select {
  appearance: none;
  padding-right: var(--sp-8);
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23617180' d='M8 11L3 6h10z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--sp-4) center;
  background-size: 14px;
  cursor: pointer;
}

/* Input with a leading or trailing adornment. */
.input-group { position: relative; display: flex; align-items: center; }
.input-group .input { padding-left: var(--sp-8); }
.input-group__icon {
  position: absolute;
  left: var(--sp-4);
  color: var(--muted);
  font-size: var(--fs-sm);
  pointer-events: none;
}
.input-group__action {
  position: absolute;
  right: var(--sp-3);
  color: var(--muted);
  font-size: var(--fs-sm);
}
.input-group__action:hover { color: var(--ink); }
.input-group--trail .input { padding-left: var(--sp-4); padding-right: var(--sp-8); }

/* --- Checkbox / radio ----------------------------------------------------
   The native control is hidden but still focusable; .check__box is painted. */
.check {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--sp-3);
  cursor: pointer;
  font-size: var(--fs-base);
  line-height: 1.4;
}
.check input { position: absolute; opacity: 0; width: 0; height: 0; }
.check__box {
  flex: 0 0 18px;
  width: 18px; height: 18px;
  margin-top: 2px;
  display: grid;
  place-items: center;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-xs);
  background: var(--surface);
  color: transparent;
  font-size: 10px;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.check--radio .check__box { border-radius: 50%; }
.check input:checked + .check__box {
  background: var(--aqua);
  border-color: var(--aqua);
  color: var(--on-accent);
}
.check input:focus-visible + .check__box { box-shadow: 0 0 0 3px var(--blue-soft); }
.check input:disabled + .check__box { opacity: .45; }
.check input:disabled ~ * { opacity: .6; }

/* --- Switch --------------------------------------------------------------- */
.switch { display: inline-flex; align-items: center; gap: var(--sp-3); cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch__track {
  position: relative;
  flex: 0 0 42px;
  width: 42px; height: 24px;
  border-radius: var(--radius-pill);
  background: var(--line);
  transition: background var(--t-base) var(--ease);
}
.switch__track::after {
  content: "";
  position: absolute;
  top: 3px; left: 3px;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: transform var(--t-base) var(--ease);
}
.switch input:checked + .switch__track { background: var(--aqua); }
.switch input:checked + .switch__track::after { transform: translateX(18px); }
.switch input:focus-visible + .switch__track { box-shadow: 0 0 0 3px var(--blue-soft); }

/* --- File drop ------------------------------------------------------------ */
.dropzone {
  display: grid;
  place-items: center;
  gap: var(--sp-3);
  padding: var(--sp-8) var(--sp-5);
  border: 1.5px dashed var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-alt);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--t-base) var(--ease), background var(--t-base) var(--ease);
}
.dropzone:hover, .dropzone.is-dragging { border-color: var(--aqua-deep); background: var(--aqua-soft); }
.dropzone i { font-size: var(--fs-2xl); color: var(--muted); }

/* ==========================================================================
   ALERTS
   ========================================================================== */
.alert {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--radius-card);
  border: 1px solid transparent;
  font-size: var(--fs-sm);
}
.alert i { margin-top: 2px; font-size: var(--fs-md); }
.alert__title { font-weight: var(--fw-heavy); margin-bottom: 2px; }
.alert__close { margin-left: auto; color: inherit; opacity: .6; }
.alert__close:hover { opacity: 1; }

.alert--aqua { background: var(--aqua-soft); color: var(--ink); border-color: var(--aqua); }
.alert--blue { background: var(--blue-soft); color: var(--blue-ink); border-color: transparent; }
.alert--sun  { background: var(--sun-soft);  color: var(--sun-ink);  border-color: transparent; }
.alert--rose { background: var(--rose-soft); color: var(--rose-ink); border-color: transparent; }

/* ==========================================================================
   DROPDOWN
   ========================================================================== */
[data-dropdown] { position: relative; }

.dropdown-menu {
  position: absolute;
  right: 0;
  top: calc(100% + var(--sp-2));
  z-index: var(--z-dropdown);
  min-width: 200px;
  padding: var(--sp-2);
  border-radius: var(--radius-card);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity var(--t-base) var(--ease),
              transform var(--t-base) var(--ease),
              visibility var(--t-base);
}
[data-dropdown].is-open > .dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: none;
}
.dropdown-menu--left { right: auto; left: 0; }
.dropdown-menu--wide { min-width: 320px; padding: 0; }

.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius-xs);
  color: var(--ink-soft);
  font-size: var(--fs-sm);
  text-align: left;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.dropdown-item:hover { background: var(--surface-alt); color: var(--ink); }
.dropdown-item i { width: 16px; text-align: center; color: var(--muted); }
.dropdown-item:hover i { color: var(--ink); }
.dropdown-item--danger { color: var(--rose); }
.dropdown-item--danger i { color: var(--rose); }
.dropdown-item--danger:hover { background: var(--rose-soft); color: var(--rose-ink); }

.dropdown-divider { height: 1px; margin: var(--sp-2) 0; background: var(--line-soft); }
.dropdown-head {
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border-bottom: 1px solid var(--line-soft);
  font-weight: var(--fw-heavy);
  font-size: var(--fs-sm);
}
.dropdown-foot {
  padding: var(--sp-3);
  border-top: 1px solid var(--line-soft);
  text-align: center;
}

/* ==========================================================================
   MODAL
   ========================================================================== */
.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  background: rgba(7, 19, 30, .55);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-base) var(--ease), visibility var(--t-base);
}
.modal.is-open { opacity: 1; visibility: visible; }

.modal__panel {
  width: 100%;
  max-width: 520px;
  max-height: 88vh;
  overflow-y: auto;
  border-radius: var(--radius-shell);
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  transform: translateY(16px) scale(.98);
  transition: transform var(--t-base) var(--ease);
}
.modal.is-open .modal__panel { transform: none; }
.modal__panel--lg { max-width: 760px; }

.modal__head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-6) var(--sp-6) var(--sp-3);
}
.modal__title { font-size: var(--fs-xl); font-weight: var(--fw-heavy); letter-spacing: var(--track-snug); }
.modal__close { margin-left: auto; color: var(--muted); font-size: var(--fs-lg); }
.modal__close:hover { color: var(--ink); }
.modal__body { padding: var(--sp-3) var(--sp-6) var(--sp-6); }
.modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-6) var(--sp-6);
}

/* ==========================================================================
   TABS
   ========================================================================== */
.tabs {
  display: flex;
  gap: var(--sp-1);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  /* The active tab's underline is positioned at bottom:-1px so it covers the
     border above, and `overflow-x: auto` makes overflow-y compute to `auto`
     as well — so that 1px overhang was real vertical overflow and every tab
     strip in the theme carried a phantom 1px scrollbar. This is the room it
     needs. `min-height` covers the other half of it: the buttons come out at
     a fractional 44.8px, which rounds scrollHeight above clientHeight on its
     own. */
  padding-bottom: 1px;
  min-height: 48px;
}
.tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  color: var(--muted);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  white-space: nowrap;
  transition: color var(--t-base) var(--ease);
}
.tab:hover { color: var(--ink); }
.tab.is-active { color: var(--ink); }
/* The active underline is aqua and sits on the border line. */
.tab.is-active::after {
  content: "";
  position: absolute;
  left: var(--sp-3); right: var(--sp-3);
  bottom: -1px;
  height: 2px;
  border-radius: var(--radius-pill);
  background: var(--aqua-deep);
}
.tab-panel { display: none; padding-top: var(--sp-5); }
.tab-panel.is-active { display: block; }

/* Wrapping variant for long strips: the tabs flow onto a second row
   instead of scrolling sideways. Each row keeps its own hairline so the
   active underline still has a line to sit on. */
.tabs--wrap {
  flex-wrap: wrap;
  overflow: visible;
  row-gap: 0;
  padding-bottom: 0;
  min-height: 0;
}
.tabs--wrap .tab { border-bottom: 1px solid var(--line); margin-bottom: -1px; }
.tabs--wrap::after { content: ''; flex: 1 1 auto; border-bottom: 1px solid var(--line); margin-bottom: -1px; }

/* Pill variant for filter rows. */
/* Pills carry no underline, so they have nothing to overflow and none of the
   room above applies — without this reset the min-height leaves 12px of dead
   space under every pill strip. */
.tabs--pills { border: 0; gap: var(--sp-2); min-height: 0; padding-bottom: 0; }
.tabs--pills .tab { border-radius: var(--radius-pill); padding: var(--sp-2) var(--sp-4); }
.tabs--pills .tab.is-active { background: var(--aqua); color: var(--on-accent); }
.tabs--pills .tab.is-active::after { display: none; }

/* ==========================================================================
   ACCORDION
   ========================================================================== */
.accordion { border: 1px solid var(--line-soft); border-radius: var(--radius-card); overflow: hidden; }
.accordion__item + .accordion__item { border-top: 1px solid var(--line-soft); }
.accordion__head {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  background: var(--surface);
  font-weight: var(--fw-semi);
  text-align: left;
  transition: background var(--t-base) var(--ease);
}
.accordion__head:hover { background: var(--surface-alt); }
.accordion__icon { margin-left: auto; color: var(--muted); transition: transform var(--t-base) var(--ease); }
.accordion__item.is-open .accordion__icon { transform: rotate(180deg); }
.accordion__body {
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--t-base) var(--ease);
}
.accordion__item.is-open .accordion__body { max-height: 800px; }
.accordion__inner { padding: 0 var(--sp-5) var(--sp-5); color: var(--ink-soft); font-size: var(--fs-sm); }

/* ==========================================================================
   TOOLTIP
   ========================================================================== */
[data-tip] { position: relative; }
[data-tip]:hover::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + var(--sp-2));
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-dropdown);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-xs);
  background: var(--ink);
  color: var(--paper);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  white-space: nowrap;
  box-shadow: var(--shadow-md);
  pointer-events: none;
}

/* ==========================================================================
   PROGRESS
   ========================================================================== */
.progress {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--surface-alt);
  overflow: hidden;
}
.progress__bar {
  height: 100%;
  width: var(--v, 0%);
  border-radius: var(--radius-pill);
  background: var(--aqua-deep);
  transition: width var(--t-slow) var(--ease);
}
.progress__bar--blue   { background: var(--blue); }
.progress__bar--sun    { background: var(--sun); }
.progress__bar--rose   { background: var(--rose); }
.progress__bar--violet { background: var(--violet); }
.progress--lg { height: 10px; }

/* ==========================================================================
   PAGINATION
   ========================================================================== */
.pagination { display: flex; align-items: center; gap: var(--sp-1); }
.page-btn {
  min-width: 34px; height: 34px;
  display: grid;
  place-items: center;
  padding: 0 var(--sp-2);
  border-radius: var(--radius-pill);
  color: var(--ink-soft);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  transition: background var(--t-base) var(--ease), color var(--t-base) var(--ease);
}
.page-btn:hover { background: var(--surface-alt); color: var(--ink); }
.page-btn.is-active { background: var(--aqua); color: var(--on-accent); }
.page-btn:disabled { opacity: .4; pointer-events: none; }

/* ==========================================================================
   TIMELINE
   The vertical rule is drawn on the list; each dot punches through it.
   ========================================================================== */
.timeline { position: relative; padding-left: var(--sp-6); }
.timeline::before {
  content: "";
  position: absolute;
  left: 5px; top: 6px; bottom: 6px;
  width: 2px;
  background: var(--line);
}
.timeline__item { position: relative; padding-bottom: var(--sp-5); }
.timeline__item:last-child { padding-bottom: 0; }
.timeline__dot {
  position: absolute;
  left: calc(-1 * var(--sp-6) + 1px);
  top: 5px;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--aqua-deep);
  box-shadow: 0 0 0 3px var(--surface);
}
.timeline__dot--blue   { background: var(--blue); }
.timeline__dot--sun    { background: var(--sun); }
.timeline__dot--rose   { background: var(--rose); }
.timeline__dot--violet { background: var(--violet); }
.timeline__title { font-size: var(--fs-sm); font-weight: var(--fw-bold); }
.timeline__meta { font-size: var(--fs-xs); color: var(--muted); }
.timeline__body { margin-top: var(--sp-1); font-size: var(--fs-sm); color: var(--ink-soft); }

/* ==========================================================================
   STAT TILE
   ========================================================================== */
.stat { display: flex; align-items: flex-start; gap: var(--sp-4); padding: var(--sp-5); }
.stat__icon {
  flex: 0 0 44px;
  width: 44px; height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-card);
  background: var(--aqua-soft);
  color: var(--ink);
  font-size: var(--fs-md);
}
.stat__icon--blue   { background: var(--blue-soft);   color: var(--blue-ink); }
.stat__icon--sun    { background: var(--sun-soft);    color: var(--sun-ink); }
.stat__icon--rose   { background: var(--rose-soft);   color: var(--rose-ink); }
.stat__icon--violet { background: var(--violet-soft); color: var(--violet-ink); }

.stat__label { font-size: var(--fs-sm); color: var(--muted); font-weight: var(--fw-medium); }
.stat__value {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--track-tight);
  line-height: 1.2;
  margin-top: 2px;
}
.stat__meta { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--muted); }
.trend { display: inline-flex; align-items: center; gap: 3px; font-weight: var(--fw-heavy); }
.trend--up   { color: var(--aqua-deep); }
.trend--down { color: var(--rose); }

/* ==========================================================================
   BANNER
   The dashboard welcome panel. Uses the shell radius and the signature
   aqua-to-blue wash from the portfolio hero.
   ========================================================================== */
.banner {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-7);
  border-radius: var(--radius-shell);
  background:
    radial-gradient(120% 160% at 100% 0%, var(--blue-soft) 0%, transparent 60%),
    linear-gradient(135deg, var(--aqua-soft), var(--surface) 62%);
  border: 1px solid var(--line-soft);
  overflow: hidden;
}
.banner__body { flex: 1 1 auto; min-width: 0; }
.banner__title {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--track-tight);
}
.banner__text { margin: var(--sp-2) 0 var(--sp-5); color: var(--ink-soft); font-size: var(--fs-md); max-width: 46ch; }
.banner__art { flex: 0 0 auto; width: 190px; opacity: .95; }
@media (max-width: 860px) {
  .banner { padding: var(--sp-6); }
  .banner__art { display: none; }
}

/* ==========================================================================
   EMPTY STATE
   ========================================================================== */
.empty {
  display: grid;
  place-items: center;
  gap: var(--sp-3);
  padding: var(--sp-9) var(--sp-5);
  text-align: center;
}
.empty__icon {
  width: 64px; height: 64px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--surface-alt);
  color: var(--muted);
  font-size: var(--fs-xl);
}
.empty__title { font-size: var(--fs-lg); font-weight: var(--fw-heavy); }
.empty__text { color: var(--muted); font-size: var(--fs-sm); max-width: 42ch; }

/* ==========================================================================
   LIST — a card-flush list of rows (referrals, activity, files)
   ========================================================================== */
.list__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  transition: background var(--t-fast) var(--ease);
}
.list__item + .list__item { border-top: 1px solid var(--line-soft); }
.list--hover .list__item:hover { background: var(--surface-alt); }
/* A group label inside a flush list — lets one card hold two related sets
   (for example, a property's own pages, then its external links) without splitting
   them into separate cards. */
.list__subhead {
  padding: var(--sp-3) var(--sp-5) var(--sp-2);
  background: var(--surface-alt);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
}
.list__subhead + .list__item { border-top: 0; }

/* Both are block so the title always sits above its meta line. As inline
   spans they only appeared stacked when the source happened to put a newline
   between them — markup written on one line ran the two together
   ("Repositorytylerdevops/360DNA-COM"). */
.list__title { display: block; font-size: var(--fs-sm); font-weight: var(--fw-semi); line-height: 1.35; }
.list__meta  { display: block; font-size: var(--fs-xs); color: var(--muted); line-height: 1.35; }
.list__end { margin-left: auto; text-align: right; white-space: nowrap; }

/* A whole row that is a link. The <a> fills the row so the entire strip is the
   target, not just the title text. */
.list__link {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex: 1 1 auto;
  min-width: 0;
  color: inherit;
}
.list__link:hover { color: inherit; }
.list__link:hover .list__title { color: var(--blue); }
.list__link:focus-visible { outline-offset: -2px; }

/* A row that only looks static because it genuinely is — no hover lift, no
   pointer. Pairs with the badge explaining why there is no link. */
.list__item.is-static { cursor: default; }
.list--hover .list__item.is-static:hover { background: transparent; }

/* ==========================================================================
   TOAST
   ========================================================================== */
.toast-stack {
  position: fixed;
  /* Cleared above the back-to-top button, which owns this same corner (see
     .to-top in shell.css). Stated here rather than there because this file
     loads later and would otherwise win the override back. */
  right: var(--sp-5); bottom: calc(var(--sp-5) + 48px + var(--sp-3));
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
@media (max-width: 480px) {
  .toast-stack { bottom: calc(var(--sp-4) + 44px + var(--sp-3)); }
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 280px;
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--radius-card);
  background: var(--surface);
  border: 1px solid var(--line-soft);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-sm);
  animation: toast-in var(--t-base) var(--ease);
}
@keyframes toast-in {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   PORTFOLIO PATTERNS — ported into the master library 2026-08-26
   --------------------------------------------------------------------------
   Four components lifted from an earlier portfolio project's own component page,
   generalised onto this theme's tokens so they work in an admin context.
   The originals are photo-driven; these use the theme's gradient art so the
   library stays image-free and rethemes with the picker.
   ========================================================================== */

/* --- Multi-destination link list -----------------------------------------
   For a card that genuinely points at more than one place. The card becomes
   an <article> rather than a wrapping <a>, so each row stays independently
   clickable — a single card-wide link would swallow them. */

.link-list { list-style: none; margin: 0; padding: 0; }
.link-list li + li { border-top: 1px solid var(--line-soft); }
.link-list a {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-2);
  color: var(--ink-soft);
  font-size: var(--fs-sm); font-weight: var(--fw-semi);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.link-list a:hover { background: var(--surface-alt); color: var(--ink); }
.link-list a i { margin-left: auto; font-size: var(--fs-xs); color: var(--muted); }
.link-list a:hover i { color: var(--aqua); }

/* --- Roster list ----------------------------------------------------------
   A long run of short, unordered entries — venues, sites, credits — set in
   two columns so it reads as a body of work rather than as a thin ribbon of
   text down the page.

   `columns` rather than a grid on purpose: a grid would need a row count, and
   the count changes every time an entry is added. Columns take the list as it
   is and balance it. `break-inside: avoid` is the price of admission — without
   it a row splits across the column break and its icon ends up in one column
   with its label in the other. */

.roster {
  columns: 2;
  column-gap: var(--sp-6);
  list-style: none;
  margin: 0;
  padding: 0;
}
.roster li {
  break-inside: avoid;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  /* The row's own padding is pulled back out, so the text still starts on the
     container's left edge and only the hover panel reaches past it. Without
     this the whole list looks indented against everything above it. */
  margin: 0 calc(var(--sp-3) * -1);
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line-soft);
  border-radius: var(--radius-sm);
  transition: background var(--t-base) var(--ease), color var(--t-base) var(--ease);
}
.roster li:hover {
  background: color-mix(in srgb, var(--aqua) 12%, transparent);
  color: var(--ink);
}
.roster__ico {
  flex: 0 0 auto;
  width: 1rem;
  text-align: center;
  color: var(--muted);
  transition: color var(--t-base) var(--ease), transform var(--t-base) var(--ease);
}
.roster li:hover .roster__ico {
  color: var(--aqua-deep);
  transform: scale(1.12);
}
@media (max-width: 640px) {
  .roster { columns: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .roster li, .roster__ico { transition: none; }
  .roster li:hover .roster__ico { transform: none; }
}

/* --- Capability row -------------------------------------------------------
   Icon, discipline heading, and an unordered chip group — for items that
   have no meaningful order, where a numbered list would imply one. */

.capability-row {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  gap: var(--sp-2) var(--sp-4);
  padding: var(--sp-4) 0;
}
.capability-row + .capability-row { border-top: 1px solid var(--line-soft); }
.capability-row__mark {
  grid-row: span 2;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--aqua) 16%, transparent);
  color: var(--aqua);
}
.capability-row__title {
  margin: 0;
  font-size: var(--fs-base); font-weight: var(--fw-bold);
  letter-spacing: var(--track-snug);
  color: var(--ink);
}
.capability-row ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px;
}
.capability-row li {
  padding: 3px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--surface-alt);
  font-size: var(--fs-xs); color: var(--ink-soft);
}

/* --- Media card + video trigger ------------------------------------------
   Shared frame. .media-card opens a lightbox; .media-trigger swaps itself
   for a real player. Both are <button>s, so keyboard access is free. */

.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--sp-3);
}
.media-frame {
  position: relative;
  display: block; width: 100%;
  aspect-ratio: 16 / 10;
  border: 0; padding: 0;
  border-radius: var(--radius-card);
  overflow: hidden;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform var(--t-base) var(--ease), box-shadow var(--t-base) var(--ease);
}
.media-frame:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
.media-frame:focus-visible { outline: 2px solid var(--aqua); outline-offset: 2px; }
.media-frame__art { position: absolute; inset: 0; }
/* The overlay is what keeps a caption legible over any artwork. */
.media-frame__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(transparent 42%, color-mix(in srgb, #0a1420 74%, transparent));
}
.media-frame__meta {
  position: absolute; inset-inline: 0; bottom: 0;
  padding: var(--sp-4);
  text-align: left; color: #fff;
}
.media-frame__meta span { display: block; font-size: var(--fs-xs); opacity: .82; }
.media-frame__meta strong { display: block; font-size: var(--fs-sm); font-weight: var(--fw-bold); }
.media-frame__open {
  position: absolute; top: var(--sp-3); right: var(--sp-3);
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: color-mix(in srgb, #0a1420 62%, transparent);
  color: #fff; font-size: var(--fs-xs);
  backdrop-filter: blur(4px);
  transition: transform var(--t-fast) var(--ease);
}
.media-frame:hover .media-frame__open { transform: scale(1.12); }

/* Local gradient art, so this section needs no image files and no gallery.css. */
.media-art--ridge { background: linear-gradient(180deg, #8fb4c9 0%, #cfd9d4 46%, #6d8f74 100%); }
.media-art--dusk  { background: linear-gradient(180deg, #33456b 0%, #7a5f86 55%, #d0906d 100%); }
.media-art--reef  { background: linear-gradient(180deg, #1d5a70 0%, #2f8598 58%, #7fc0cc 100%); }

/* The swapped-in player. Sized like the frame it replaced so nothing jumps. */
.media-player {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: #0a1420;
  display: grid; place-items: center;
}
.media-player video { width: 100%; height: 100%; object-fit: cover; }
.media-player__note {
  color: #cfd8e0; font-size: var(--fs-sm); text-align: center;
  padding: var(--sp-4);
}
.media-player__close {
  position: absolute; top: var(--sp-3); right: var(--sp-3);
  padding: 5px 12px;
  border: 0; border-radius: var(--radius-pill);
  background: color-mix(in srgb, #ffffff 88%, transparent);
  color: #0a1420; font-size: var(--fs-xs); font-weight: var(--fw-bold);
  cursor: pointer;
}

/* --- Library search ------------------------------------------------------
   Turns a long component page into something you can actually pick from. */

.lib-search { display: flex; align-items: center; gap: var(--sp-3); }
.lib-search__count { font-size: var(--fs-sm); color: var(--muted); white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .media-frame, .media-frame__open { transition: none; }
  .media-frame:hover { transform: none; }
}

/* ==========================================================================
   CODE BLOCK — copy-to-clipboard snippet
   The code lives exactly once, in the <pre>. The button copies that element's
   own textContent rather than carrying a duplicate in a data- attribute:
   multi-line HTML inside an attribute means escaping quotes and newlines by
   hand, and the two copies drift apart the first time one is edited.
   ========================================================================== */
.code-block {
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--surface-alt);
}
.code-block + .code-block { margin-top: var(--sp-4); }
.code-block__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-4);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.code-block__lang {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--muted);
}
.code-block__file {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  color: var(--muted);
}
.code-block__copy { margin-left: auto; flex: 0 0 auto; }
.code-block pre {
  margin: 0;
  border: 0;
  border-radius: 0;
  background: none;
  max-height: 420px;
  overflow: auto;
}
.code-block pre code { font-size: var(--fs-2xs); line-height: 1.65; }

/* ==========================================================================
   HOW-TO GUIDE
   A build note that sits under the component it documents. Deliberately a
   <details>: on a page carrying dozens of components, every guide open at once
   is unreadable, and the summary alone tells you the guide is there.
   ========================================================================== */
.howto {
  margin-top: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--paper-warm);
}
.howto__summary {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: var(--fw-heavy);
  letter-spacing: var(--track-snug);
  list-style: none;
}
.howto__summary::-webkit-details-marker { display: none; }
.howto__summary i.howto__chev {
  margin-left: auto;
  color: var(--muted);
  transition: transform var(--t-base) var(--ease);
}
.howto[open] .howto__summary i.howto__chev { transform: rotate(180deg); }
.howto__summary:hover { color: var(--aqua-deep); }
.howto__badge {
  display: inline-grid;
  place-items: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--aqua-soft);
  color: var(--ink);
  font-size: var(--fs-2xs);
}
.howto__body {
  padding: 0 var(--sp-5) var(--sp-5);
  border-top: 1px solid var(--line-soft);
  padding-top: var(--sp-5);
}
.howto__lede {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  max-width: 72ch;
}
/* Numbered build steps. The counter is drawn rather than using <ol>'s own
   marker so it can sit in a circle and align with the text block. */
.howto__steps { list-style: none; margin: 0 0 var(--sp-5); padding: 0; counter-reset: howto; }
.howto__step {
  position: relative;
  counter-increment: howto;
  padding: 0 0 var(--sp-4) calc(var(--sp-6) + var(--sp-2));
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  max-width: 76ch;
}
.howto__step::before {
  content: counter(howto);
  position: absolute;
  left: 0; top: -1px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--aqua);
  color: var(--on-accent);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-heavy);
}
.howto__step strong { color: var(--ink); }
.howto__step p { margin: var(--sp-2) 0 0; }
.howto__note {
  margin: var(--sp-4) 0 0;
  padding: var(--sp-3) var(--sp-4);
  border-left: 3px solid var(--aqua);
  border-radius: 0 var(--radius-xs) var(--radius-xs) 0;
  background: var(--aqua-soft);
  font-size: var(--fs-xs);
  color: var(--ink);
}
.howto__files {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}

/* A neutral pad for showing a piece of fixed chrome inline, out of the corner
   it normally lives in. The demo copy is position:relative rather than fixed,
   so it sits in this box instead of on the viewport. */
.comp-stage {
  display: grid;
  place-items: center;
  width: 132px; height: 132px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-card);
  background: var(--surface-alt);
}

/* Tabs inside a build guide. The strip sits flush under the summary rule, and
   the first panel supplies its own top padding, so no double gap. */
.howto .tabs { margin-top: calc(var(--sp-2) * -1); }
.howto .tab-panel { padding-top: var(--sp-5); }

/* --- SVG gallery spec card -------------------------------------------------
   The "What These Are" panel above the design groups on ui/svg-animation.html.
   Every number in it is a build token, so the copy cannot drift from the
   library it describes.
   -------------------------------------------------------------------------- */
/* The card collapses, so the design grid is never more than a scroll away.
   It reuses the shared accordion behavior in ui.js (a .accordion__head
   button toggling .is-open on its .accordion__item) but not the shared
   accordion's max-height, which caps an open body at 800px — this one's spec
   grid and rules alert run well past that and would be clipped. Animating
   grid-template-rows from 0fr to 1fr resolves to the content's real height
   instead of a guessed maximum, so the card can grow without anyone
   remembering to raise a number here. */
.tg-spec .accordion__head {
  width: 100%;
  text-align: left;
  background: none;
  cursor: pointer;
}
.tg-spec .accordion__head:hover { background: var(--surface-alt); }
.tg-spec .accordion__head > div { flex: 1 1 auto; }
.tg-spec .accordion__icon { margin-left: auto; flex: 0 0 auto; }
/* .accordion__item.is-open .accordion__body is (0,3,0) — a plain
   .tg-spec .accordion__body ties on nothing and loses, which pinned this card
   open at the shared 800px cap. Both rules carry the .accordion__item so they
   outrank it and the body can size to its real content.

   The height itself is NOT transitioned. Interpolating grid-template-rows
   from 0fr to 1fr against an indefinite container resolved to 0 here and left
   the card open but empty; the content fades in instead, which reads the same
   and cannot clip or collapse. */
.tg-spec.accordion__item .accordion__body {
  display: grid;
  grid-template-rows: 0fr;
  max-height: none;
}
.tg-spec.accordion__item.is-open .accordion__body { grid-template-rows: 1fr; }
.tg-spec .accordion__body > .card__body {
  opacity: 0;
  transition: opacity var(--t-base) var(--ease);
}
.tg-spec.is-open .accordion__body > .card__body { opacity: 1; }
.tg-spec .accordion__body > * { min-height: 0; overflow: hidden; }
/* A 0fr track crushes the child's content box, not its padding — .card__body's
   own var(--sp-5) survived and left a 40px sliver open under the closed head.
   The padding has to come down with the row. */
.tg-spec .accordion__body > .card__body { padding-block: 0; }
.tg-spec.is-open .accordion__body > .card__body { padding-block: var(--sp-5); }
/* No rule under a head with nothing beneath it. */
.tg-spec:not(.is-open) .card__head--bordered { border-bottom-color: transparent; }
@media (prefers-reduced-motion: reduce) {
  .tg-spec .accordion__body > .card__body { transition: none; }
}

.tg-spec__item {
  padding: var(--sp-4);
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-soft);
  background: var(--surface-alt);
}
.tg-spec__label {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}
.tg-spec__value {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-lg);
  font-weight: var(--fw-heavy);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.tg-spec__note {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-xs);
  line-height: 1.55;
  color: var(--ink-soft);
}
