/*
 * Styles for the /dashboard namespace only — the signed-in "my events" area
 * (see phase-3-window-roles-links.md). Plain CSS, no build step — Propshaft
 * bundles this alongside application.css automatically (stylesheet_link_tag
 * :app bundles every *.css under app/assets). Deliberately self-contained
 * rule-wise, matching join.css's precedent; brand colors/radii/shadows come
 * from the custom properties in theme.css so web and Android stay in sync.
 */

body.dashboard {
  font-family: var(--font);
  margin: 0;
  color: var(--ink);
  background: var(--bg);
}

.dashboard h1,
.dashboard h2 {
  font-weight: 800;
  letter-spacing: -0.02em;
}

.dashboard-nav {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: 0.85rem 1.5rem;
  background: var(--grad-nav);
  color: #fff;
  /* Sticky so the way back out of an album is always one click away — the
     media grid and timeline are long pages. */
  position: sticky;
  top: 0;
  z-index: 5;
  box-shadow: var(--shadow-1);
}

.dashboard-nav .brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
  text-decoration: none;
}

.dashboard-nav .brand .brand-mark {
  width: 1.6em;
  height: 1.6em;
}

.dashboard-nav nav {
  display: flex;
  gap: 1rem;
  flex: 1;
}

.dashboard-nav nav a {
  color: var(--teal-container);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
}

.dashboard-nav nav a:hover {
  color: #fff;
}

.link-button {
  background: none;
  border: none;
  color: var(--teal-container);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

.link-button:hover {
  color: #fff;
}

.dashboard-main {
  max-width: 48rem;
  margin: 0 auto;
  padding: 1.5rem;
}

/* The media grid needs more horizontal room than the settings/table pages —
   `content_for :body_class, "wide"` (see the media_items views) widens just
   those pages instead of the 48rem default everywhere else. */
.dashboard.wide .dashboard-main {
  max-width: 72rem;
}

.flash {
  max-width: 48rem;
  margin: 1rem auto 0;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-m);
}

.flash-notice { background: var(--success-container); color: var(--on-success-container); }
.flash-alert { background: var(--error-container); color: var(--on-error-container); }

table.dashboard-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border-radius: var(--radius-m);
  overflow: hidden;
  box-shadow: var(--shadow-1);
}

table.dashboard-table th,
table.dashboard-table td {
  text-align: left;
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--outline);
  font-size: 0.9rem;
  vertical-align: middle;
}

table.dashboard-table th {
  background: var(--bg);
  font-weight: 700;
  color: var(--ink-soft);
}

table.dashboard-table tr:last-child td {
  border-bottom: none;
}

table.dashboard-table a {
  color: var(--teal);
  font-weight: 600;
  text-decoration: none;
}

table.dashboard-table a:hover {
  color: var(--coral);
}

.badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: var(--radius-pill);
  font-size: 0.75rem;
  font-weight: 700;
}

.badge-owner { background: var(--coral-container); color: var(--on-coral-container); }
.badge-member { background: var(--teal-container); color: var(--on-teal-container); }
.badge-viewer { background: var(--outline); color: var(--ink-soft); }
.badge-active { background: var(--success-container); color: var(--on-success-container); }
.badge-pending_undo { background: var(--amber-container); color: var(--on-amber-container); }
.badge-soft_deleted { background: var(--error-container); color: var(--on-error-container); }
.badge-purged { background: var(--outline); color: var(--ink-soft); }

/* EventExport statuses (phase-6-differentiators.md §Bulk download/export). */
.badge-pending { background: var(--outline); color: var(--ink-soft); }
.badge-processing { background: var(--amber-container); color: var(--on-amber-container); }
.badge-ready { background: var(--success-container); color: var(--on-success-container); }
.badge-failed { background: var(--error-container); color: var(--on-error-container); }

.btn {
  display: inline-block;
  padding: 0.45rem 0.95rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--outline-strong);
  background: var(--surface);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  text-decoration: none;
  color: var(--ink);
  transition: background 0.15s ease, box-shadow 0.15s ease;
}

.btn:hover { background: var(--coral-container); border-color: var(--coral-container); }

.btn-primary {
  background: var(--coral);
  border-color: var(--coral);
  color: #fff;
  box-shadow: var(--shadow-1);
}

.btn-primary:hover { background: var(--coral-dark); border-color: var(--coral-dark); }

.btn-danger { border-color: var(--coral-dark); color: var(--coral-dark); }
.btn-danger:hover { background: var(--error-container); }

.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}

.muted { color: var(--ink-faint); font-size: 0.85rem; }

.card {
  background: var(--surface);
  border-radius: var(--radius-l);
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
  box-shadow: var(--shadow-1);
}

.stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.stat-card {
  background: var(--surface);
  border-radius: var(--radius-l);
  padding: 1rem 1.25rem;
  min-width: 9rem;
  box-shadow: var(--shadow-1);
  border-top: 3px solid var(--amber);
}

.stat-card .value {
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--teal);
}

.stat-card .label {
  font-size: 0.8rem;
  color: var(--ink-faint);
}

/* A plain CSS bar chart for the analytics page (plan-9.md §4) — no JS
   charting dependency, consistent with the no-bundler stance elsewhere. */
.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 6rem;
  margin-bottom: 1.5rem;
  background: var(--surface);
  border-radius: var(--radius-l);
  padding: 0.75rem;
  box-shadow: var(--shadow-1);
}

.bar-chart .bar-col {
  flex: 1;
  height: 100%;
  display: flex;
  align-items: flex-end;
}

.bar-chart .bar {
  width: 100%;
  min-height: 2px;
  background: linear-gradient(180deg, var(--coral), var(--coral-dark));
  border-radius: 3px 3px 0 0;
}

/* Click-to-filter chips (plan-18.md) — one removable chip per active
   filter, since filters compose ("what did Grace shoot in Paris?") and
   backing out of one shouldn't discard the other. */
.filter-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow-1);
  font-size: 0.85rem;
  text-decoration: none;
}

.filter-chip:hover {
  background: var(--teal);
  color: #fff;
}

.filter-chip-x {
  font-weight: 700;
  opacity: 0.6;
}

/* Caption links on a tile read as text until hovered — the tile's own image
   is the primary target, and underlining every name and place would turn a
   photo grid into a wall of links. */
.tile-meta-link {
  text-decoration: none;
  color: inherit;
}

.tile-meta-link:hover {
  text-decoration: underline;
}

/* Visually hidden but read aloud — the chips' "×" is decorative, so the
   actual action needs a text label for screen readers. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Inline share-of-album bar in the contributors table (plan-17.md) — the
   row's own width carries the comparison, so the table doubles as the "top
   contributors" chart instead of needing a second section for it. */
.share-bar {
  display: inline-block;
  width: 5rem;
  height: 0.5rem;
  margin-right: 0.5rem;
  vertical-align: middle;
  background: var(--surface-2, rgba(0, 0, 0, 0.08));
  border-radius: 999px;
  overflow: hidden;
}

.share-bar-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--coral), var(--coral-dark));
  border-radius: 999px;
}

.field {
  margin-bottom: 1rem;
}

.field label {
  display: block;
  font-weight: 600;
  font-size: 0.85rem;
  margin-bottom: 0.3rem;
}

.field input[type="text"],
.field input[type="datetime-local"],
.field select {
  width: 100%;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--outline-strong);
  border-radius: var(--radius-s);
  box-sizing: border-box;
  font-size: 0.95rem;
  font-family: inherit;
  background: var(--surface);
  color: var(--ink);
}

.field input[type="text"]:focus,
.field input[type="datetime-local"]:focus,
.field select:focus {
  outline: 2px solid var(--coral);
  outline-offset: 1px;
  border-color: var(--coral);
}

.field-hint {
  font-size: 0.8rem;
  color: var(--ink-faint);
  margin-top: 0.25rem;
}

.radio-option {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.radio-option input { margin-top: 0.2rem; accent-color: var(--coral); }

.window-fields {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin: 0.75rem 0 1rem 1.6rem;
}

.window-fields .field-wide {
  grid-column: 1 / -1;
}

.error-messages {
  background: var(--error-container);
  color: var(--on-error-container);
  padding: 0.75rem 1rem;
  border-radius: var(--radius-m);
  margin-bottom: 1rem;
  font-size: 0.9rem;
}

.invite-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.invite-row code {
  background: var(--teal-container);
  color: var(--on-teal-container);
  padding: 0.3rem 0.7rem;
  border-radius: var(--radius-s);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.08em;
}

/* Big enough to judge the crop by — this is the picture that ends up
   representing the whole album, and a 5rem chip was too small to choose from. */
.cover-preview {
  width: 8rem;
  height: 8rem;
  object-fit: cover;
  border-radius: var(--radius-m);
  display: block;
  margin-bottom: 0.5rem;
  box-shadow: var(--shadow-1);
}

.cover-preview-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--grad-wash);
  border: 1px dashed var(--outline-strong);
  box-shadow: none;
}

.cover-preview-empty .brand-mark {
  width: 2.75rem;
  height: 2.75rem;
  opacity: 0.75;
}

.cover-picker {
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

.cover-option .muted {
  margin: 0 0 0.5rem;
  font-weight: 600;
}

.filters {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  margin-bottom: 1rem;
  flex-wrap: wrap;
}

.filters select {
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--outline-strong);
  border-radius: var(--radius-s);
  font-family: inherit;
  background: var(--surface);
  color: var(--ink);
}

.timeline-day {
  margin: 1.75rem 0 0.75rem;
  font-size: 1.1rem;
  padding-bottom: 0.35rem;
  border-bottom: 2px solid var(--amber-container);
}
.timeline-day:first-child { margin-top: 0.5rem; }

/* Friendly empty state (events list and anywhere else a list comes up empty) —
   the brand mark plus a line of copy beats a bare grey sentence. */
.empty-state {
  background: var(--surface);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-1);
  padding: 2.5rem 1.5rem;
  text-align: center;
}

.empty-state .brand-mark {
  width: 4rem;
  height: 4rem;
}

.empty-state h2 {
  margin: 0.75rem 0 0.35rem;
  font-size: 1.15rem;
}

.empty-state p {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.92rem;
}

.dashboard-nav-public {
  justify-content: space-between;
}

.store-links {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

/* Signed-out landing hero — first impression is where "take it seriously"
   is won or lost, same reasoning as the Android sign-in screen. */
.login-card {
  max-width: 26rem;
  margin: 3.5rem auto 0;
  padding: 2.5rem 2rem 2rem;
  background: var(--surface);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-2);
  text-align: center;
}

.login-card .brand-mark {
  width: 4.5rem;
  height: 4.5rem;
}

.login-wordmark {
  margin: 0.75rem 0 0.25rem;
  font-size: 2rem;
  font-weight: 800;
  letter-spacing: -0.03em;
}

.login-tagline {
  color: var(--ink-soft);
  margin: 0;
  font-size: 1.02rem;
  line-height: 1.45;
}

.login-tagline strong {
  color: var(--coral);
}

.login-value-prop {
  color: var(--ink-faint);
  font-size: 0.88rem;
  margin: 0.5rem 0 0;
  line-height: 1.45;
}

.google-signin {
  display: block;
  margin-top: 1.5rem;
  padding: 0.85rem 1.4rem;
  background: var(--coral);
  color: #fff;
  font-weight: 700;
  border-radius: var(--radius-pill);
  text-decoration: none;
  box-shadow: var(--shadow-1);
  transition: background 0.15s ease;
}

.google-signin:hover {
  background: var(--coral-dark);
}

.login-store-badges {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.75rem;
  margin: 1rem 0 0;
}

/* Both badges get the same bounding box so Google Play and the App Store
   read as the same size next to each other, despite the official artwork
   having different native aspect ratios (object-fit: contain keeps each
   undistorted inside it rather than stretching one to match the other). */
.store-badge {
  display: block;
  height: 40px;
  width: 120px;
  object-fit: contain;
}

.dashboard-nav .store-badge {
  height: 28px;
  width: 84px;
}

.dashboard-footer {
  max-width: 56rem;
  margin: 1rem auto 2rem;
  padding: 1.5rem 1.5rem 0;
  text-align: center;
  border-top: 1px solid var(--outline);
}

.dashboard-footer-legal {
  font-size: 0.8rem;
  color: var(--ink-faint);
}

.dashboard-footer-legal a {
  color: var(--ink-faint);
}

.dashboard-footer-copy {
  font-size: 0.75rem;
  color: var(--outline-strong);
  margin: 0.5rem 0 0;
}

.landing-features {
  max-width: 56rem;
  margin: 2.5rem auto 0;
  padding: 0 1.5rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}

@media (max-width: 48rem) {
  .landing-features {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 30rem) {
  .landing-features {
    grid-template-columns: 1fr;
    padding: 0 1rem;
  }

  .login-card {
    margin-top: 2rem;
    padding: 1.75rem 1.5rem;
  }

  .dashboard-nav-public {
    padding: 0.85rem 1rem;
  }
}

.landing-feature {
  background: var(--surface);
  border-radius: var(--radius-l);
  padding: 1.5rem;
  box-shadow: var(--shadow-1);
  text-align: center;
}

.landing-feature-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  font-size: 1.5rem;
  background: var(--amber-container);
  border-radius: var(--radius-pill);
}

.landing-feature h2 {
  font-size: 1rem;
  margin: 0.65rem 0 0.4rem;
}

.landing-feature p {
  margin: 0;
  font-size: 0.88rem;
  color: var(--ink-soft);
  line-height: 1.4;
}

.landing-stats {
  max-width: 40rem;
  margin: 2rem auto 3rem;
  padding: 1.5rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  text-align: center;
}

.landing-stat {
  display: flex;
  flex-direction: column;
}

.landing-stat-value {
  font-size: 1.9rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--coral);
}

.landing-stat-label {
  font-size: 0.8rem;
  color: var(--ink-faint);
  margin-top: 0.2rem;
}

@media (max-width: 30rem) {
  .landing-stats {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
}

.pagination {
  display: flex;
  gap: 1rem;
  align-items: center;
  margin-top: 1rem;
  font-size: 0.9rem;
}

.pagination-current {
  font-weight: 700;
}

.pagination-total {
  opacity: 0.7;
}

.pagination a {
  color: var(--teal);
  font-weight: 600;
}

.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.75rem;
}

.media-tile {
  position: relative;
  background: var(--surface);
  border-radius: var(--radius-m);
  overflow: hidden;
  box-shadow: var(--shadow-1);
  cursor: pointer;
  border: none;
  padding: 0;
  display: block;
  width: 100%;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.media-tile:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
}

.media-tile img {
  width: 100%;
  height: 140px;
  object-fit: cover;
  display: block;
  background: var(--outline);
}

.media-tile .placeholder {
  width: 100%;
  height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  font-size: 0.8rem;
  background: var(--outline);
}

.media-tile .tile-badge {
  position: absolute;
  top: 0.35rem;
  left: 0.35rem;
}

/* Near-duplicate cluster count (phase-6-differentiators.md §Near-duplicate
   clustering) — sits opposite the status badge so both are readable at once. */
.media-tile .tile-badge-count {
  left: auto;
  right: 0.35rem;
  background: rgba(5, 48, 61, 0.72);
  color: #fff;
}

.media-tile .tile-favorite {
  position: absolute;
  bottom: 0.35rem;
  right: 0.35rem;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  font-size: 1.1rem;
}

/* Wraps a tile + its optional caption (timeline's show_meta) so the pair
   occupies one .media-grid cell — without this, a caption rendered as a grid
   sibling would consume its own cell and desync the grid. */
.media-tile-wrap {
  display: flex;
  flex-direction: column;
}

.tile-meta {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-faint);
  line-height: 1.3;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.tile-meta .tile-author {
  font-weight: 600;
  color: var(--ink-soft);
}

.btn-favorite.active {
  border-color: var(--coral);
  color: var(--coral);
  background: var(--coral-container);
}

.cluster-strip {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  padding: 0.5rem 0.75rem;
  background: var(--bg);
  border-top: 1px solid var(--outline);
}

.cluster-strip .muted { flex-basis: 100%; }

.cluster-thumb {
  border: 2px solid transparent;
  border-radius: var(--radius-s);
  padding: 0;
  cursor: pointer;
  background: none;
  width: 3rem;
  height: 3rem;
  overflow: hidden;
}

.cluster-thumb.current { border-color: var(--coral); }

.cluster-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}


/* ── Media viewer (plan-19.md) ──────────────────────────────────────────
   One dialog per page, full-bleed rather than a shrink-wrapped box: the
   photo is the point, and on a phone a 90vw/90vh box left the controls
   crowded against the image with nowhere to put next/previous. */
.media-viewer {
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  color: #fff;
  /* The stage takes whatever is left after the chrome, strip and action bar,
     so the bar can never be pushed off-screen the way the old fixed
     max-height on the image allowed. */
  overflow: hidden;
}

/* The grid display lives on [open] only: an author `display` on the bare
   selector beats the UA's `dialog:not([open]) { display: none }`, which left
   the closed 100vw x 100dvh dialog in the page flow, covering (and eating
   clicks on) whatever sat below the grid, e.g. the pagination links. */
.media-viewer[open] {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-rows: auto 1fr auto auto;
  grid-template-areas:
    "chrome chrome chrome"
    "prev   stage  next"
    "strip  strip  strip"
    "bar    bar    bar";
}

.media-viewer::backdrop {
  background: rgba(12, 6, 4, 0.92);
}

.media-viewer-chrome {
  grid-area: chrome;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0.75rem;
}

.media-viewer-counter {
  font-size: 0.85rem;
  opacity: 0.75;
}

.media-viewer-close {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: none;
  border-radius: 999px;
  width: 2.25rem;
  height: 2.25rem;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.media-viewer-close:hover {
  background: rgba(255, 255, 255, 0.25);
}

.media-viewer-stage {
  grid-area: stage;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 0; /* lets the image shrink inside the grid row instead of overflowing */
  padding: 0 0.25rem;
}

.media-viewer-stage img,
.media-viewer-stage video {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.media-viewer-stage .placeholder {
  opacity: 0.7;
}

.media-viewer-arrow {
  align-self: center;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: none;
  border-radius: 999px;
  width: 2.75rem;
  height: 2.75rem;
  font-size: 1.75rem;
  line-height: 1;
  cursor: pointer;
  margin: 0 0.5rem;
}

.media-viewer-arrow.prev { grid-area: prev; }
.media-viewer-arrow.next { grid-area: next; }

.media-viewer-arrow:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.28);
}

.media-viewer-arrow:disabled {
  opacity: 0.25;
  cursor: default;
}

.media-viewer-strip {
  grid-area: strip;
}

.media-viewer-strip[hidden] {
  display: none;
}

.media-viewer-bar {
  grid-area: bar;
  display: flex;
  flex-wrap: wrap; /* the old bar was a nowrap flex row and overflowed on phones */
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem;
  background: rgba(0, 0, 0, 0.55);
}

.media-viewer-meta {
  margin: 0;
  margin-right: auto;
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.85rem;
}

.media-viewer-meta a {
  color: inherit;
}

.media-viewer-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.media-viewer-action-form {
  display: none;
}

/* On a narrow screen the arrows would eat the photo's width, so they overlay
   its edges instead — touch users have swipe anyway. */
@media (max-width: 40rem) {
  .media-viewer {
    grid-template-columns: 1fr;
    grid-template-areas:
      "chrome"
      "stage"
      "strip"
      "bar";
  }

  .media-viewer-arrow {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
  }

  .media-viewer-arrow.prev { left: 0.25rem; }
  .media-viewer-arrow.next { right: 0.25rem; }
}

/* ── Page header ───────────────────────────────────────────────────────
   Title plus a line of orientation, with the page's actions pushed to the
   opposite end — replaces .section-title on pages that lead with an <h1>. */
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.5rem;
}

.page-header h1 {
  margin: 0;
  font-size: 1.6rem;
}

.page-subtitle {
  margin: 0.35rem 0 0;
  color: var(--ink-faint);
  font-size: 0.9rem;
}

.page-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.breadcrumb {
  margin: 0 0 0.75rem;
  font-size: 0.85rem;
}

.breadcrumb a {
  color: var(--ink-faint);
  text-decoration: none;
  font-weight: 600;
}

.breadcrumb a:hover { color: var(--coral); }

.empty-state-cta {
  margin-top: 1.25rem !important;
}

/* ── Event cards ───────────────────────────────────────────────────────
   The events list as a photo wall: an album's own cover identifies it at a
   glance in a way a table row of names never did. */
.event-card-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1.25rem;
}

.event-card-link {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--surface);
  border-radius: var(--radius-l);
  overflow: hidden;
  box-shadow: var(--shadow-1);
  text-decoration: none;
  color: inherit;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.event-card-link:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-2);
}

.event-card-cover {
  position: relative;
  display: block;
  aspect-ratio: 3 / 2;
  background: var(--outline);
}

.event-card-cover img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* An album with nothing to show yet still gets a face — the brand gradient,
   not a grey rectangle that reads as a failed image. */
.event-card-cover-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  background: var(--grad-sunset);
}

.event-card-cover-empty .brand-mark {
  width: 3.25rem;
  height: 3.25rem;
}

.event-card-tags {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  display: flex;
  gap: 0.3rem;
  flex-wrap: wrap;
}

.event-card-body {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.85rem 1rem 1rem;
}

.event-card-name {
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
}

.event-card-meta {
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.event-card-joined {
  font-size: 0.78rem;
  color: var(--ink-faint);
}

/* ── Event hero ────────────────────────────────────────────────────────
   The cover photo as the event page's header, with the title and actions
   reading over a bottom scrim rather than sitting on plain background. */
.event-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 14rem;
  margin-bottom: 1.5rem;
  border-radius: var(--radius-xl);
  overflow: hidden;
  background: var(--grad-nav);
  box-shadow: var(--shadow-2);
}

.event-hero-plain {
  background: var(--grad-sunset);
}

.event-hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.event-hero-content {
  position: relative;
  width: 100%;
  padding: 4rem 1.5rem 1.25rem;
  color: #fff;
  background: linear-gradient(180deg, rgba(12, 6, 4, 0) 0%, rgba(12, 6, 4, 0.8) 72%);
}

.dashboard .event-hero h1 {
  margin: 0;
  font-size: 1.8rem;
  color: #fff;
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.45);
}

.event-hero-stats {
  margin: 0.3rem 0 0;
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.88);
}

.event-hero-badges {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
  margin: 0.6rem 0 0;
}

.event-hero-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

/* These buttons sit on a photograph — translucent glass instead of the page's
   white pills, which would read as a toolbar pasted over the image. */
.event-hero-actions .btn {
  background: rgba(255, 255, 255, 0.18);
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
}

.event-hero-actions .btn:hover {
  background: rgba(255, 255, 255, 0.32);
  border-color: rgba(255, 255, 255, 0.5);
}

.event-hero-actions .btn-primary {
  background: var(--coral);
  border-color: var(--coral);
}

.event-hero-actions .btn-primary:hover {
  background: var(--coral-dark);
  border-color: var(--coral-dark);
}

/* Keyboard focus was invisible on the pill buttons and the new cards — the
   default ring is lost against a photo, so it's drawn explicitly. */
.btn:focus-visible,
.event-card-link:focus-visible,
.link-button:focus-visible,
.filter-chip:focus-visible {
  outline: 2px solid var(--coral);
  outline-offset: 2px;
}

.event-hero-actions .btn:focus-visible {
  outline-color: #fff;
}

@media (max-width: 40rem) {
  .event-hero {
    min-height: 11rem;
    border-radius: var(--radius-l);
  }

  .event-hero-content {
    padding: 3rem 1rem 1rem;
  }

  .dashboard .event-hero h1 {
    font-size: 1.4rem;
  }

  .page-header h1 {
    font-size: 1.35rem;
  }

  .event-card-grid {
    grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
    gap: 1rem;
  }
}
