/* ─── Component surfaces ───────────
 * Ruby components emit semantic hooks (event-card, board-card, form-field,
 * card-block, section-header) that this file paints per theme. Same ERB
 * markup reads as editorial print OR 90s window chrome. */

/* ─── SectionComponent header ───────────*/
.section-header {
  max-width: 42rem;
  margin-bottom: 2.5rem;
}
@media (min-width: 768px) {
  .section-header { margin-bottom: 3.5rem; }
}
.section-header__title {
  font-size: var(--font-size-3xl);
  color: var(--color-text);
}
@media (min-width: 768px) {
  .section-header__title { font-size: var(--font-size-4xl); }
}
.section-header__eyebrow {
  color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}
.section-header__subtitle {
  margin-top: 0.75rem;
  max-width: 36rem;
  color: var(--color-text-muted);
  line-height: var(--line-height-relaxed);
}
[data-theme="classic"] .section-header {
  margin-bottom: 1rem;
}
[data-theme="classic"] .section-header__title {
  border-bottom: 1px solid var(--color-primary);
  padding-bottom: 0.25rem;
  display: inline-block;
  font-size: var(--font-size-lg);
}
@media (min-width: 768px) {
  [data-theme="classic"] .section-header__title { font-size: var(--font-size-xl); }
}

/* ─── CardComponent ───────────*/
.card-block {
  padding: 1.25rem 0;
}
.card-title {
  font-size: var(--font-size-lg);
  color: var(--color-text);
  margin-bottom: 0.5rem;
}
.card-description {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-relaxed);
}
[data-theme="modern"] .card-block {
  border-left: 1px solid var(--color-border-strong);
  padding-left: 1.25rem;
  transition: border-color var(--transition-base), padding-left var(--transition-base);
}
[data-theme="modern"] .card-block:hover {
  border-color: var(--color-primary);
  padding-left: 1.5rem;
}
[data-theme="modern"] .card-title {
  font-size: var(--font-size-xl);
}
[data-theme="classic"] .card-block {
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  padding: 0.75rem 1rem;
}

/* ─── EventImageComponent ───────────*
 * The shared frame for event featured images. The frame owns the aspect
 * ratio and the crop; the img only fills it, so portrait, landscape and
 * square uploads all land in the same slot without distortion. */
.event-image {
  position: relative;
  overflow: hidden;
  margin: 0;
  aspect-ratio: 16 / 9;
  background: var(--color-surface-raised);
}
.event-image--card   { aspect-ratio: 16 / 9; }
.event-image--detail { aspect-ratio: 16 / 9; }
/* An event with no image still gets a frame so the card grid keeps its
   rhythm, but the full-bleed detail banner sits lower — a 16/9 void the
   width of the viewport would read as a loading failure, not a design. */
.event-image--detail.event-image--empty { aspect-ratio: 16 / 5; }
/* Explicit overrides — declared last so an `aspect:` argument wins over
   whatever ratio the variant defaults to. */
.event-image--16x9 { aspect-ratio: 16 / 9; }
.event-image--3x2  { aspect-ratio: 3 / 2; }
.event-image--1x1  { aspect-ratio: 1 / 1; }
.event-image--4x5  { aspect-ratio: 4 / 5; }

.event-image__pane {
  position: absolute;
  inset: 0;
}
.event-image__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.event-image__placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-surface);
  color: var(--color-text-muted);
  font-family: var(--font-serif-display);
  font-size: var(--font-size-3xl);
  line-height: var(--line-height-none);
}
[data-theme="classic"] .event-image__placeholder {
  font-family: var(--font-sans);
  font-weight: var(--font-weight-bold);
}

/* ─── EventCardComponent ───────────*/
.event-card {
  display: block;
  position: relative;
  color: inherit;
}
.event-card__media {
  background: var(--color-surface-raised);
  position: relative;
  overflow: hidden;
}
.event-card__image {
  transition: transform 1.2s cubic-bezier(0.16, 1, 0.3, 1),
              filter var(--transition-base);
  filter: saturate(0.9);
}
.event-card__body {
  padding: 1.25rem 0 0;
}
.event-card__date-line {
  color: var(--color-primary);
}
.event-card__title {
  margin-top: 0.5rem;
  font-size: var(--font-size-xl);
  color: var(--color-text);
}
.event-card__location {
  margin-top: 0.35rem;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}
.event-card__excerpt {
  margin-top: 0.75rem;
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
  line-height: var(--line-height-relaxed);
}
.event-card__cta {
  margin-top: 1rem;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary);
}
.event-card__cta-arrow {
  transition: transform var(--transition-base) cubic-bezier(0.16, 1, 0.3, 1);
}

.event-flag {
  position: absolute;
  top: 0.5rem;
  z-index: 10;
  padding: 0.2rem 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: var(--color-background);
}
.event-flag--active { left: 0.5rem; border: 1px solid var(--color-success); color: var(--color-success); }
.event-flag--past   { left: 0.5rem; border: 1px solid var(--color-border-strong);  color: var(--color-text-muted); }
.event-flag--rsvp   { right: 0.5rem; left: auto; border: 1px solid var(--color-primary); color: var(--color-primary); }

[data-theme="modern"] .event-card {
  border-top: 1px solid var(--color-border);
  padding-top: 1.75rem;
  padding-bottom: 1.75rem;
  transition: border-color var(--transition-base);
}
[data-theme="modern"] .event-card:hover,
[data-theme="modern"] .event-card:focus-visible { border-color: var(--color-primary); }
[data-theme="modern"] .event-card:hover .event-card__image,
[data-theme="modern"] .event-card:focus-visible .event-card__image { transform: scale(1.06); filter: saturate(1); }
[data-theme="modern"] .event-card:hover .event-card__cta-arrow,
[data-theme="modern"] .event-card:focus-visible .event-card__cta-arrow { transform: translateX(6px); }

[data-theme="classic"] .event-card {
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  padding: 0.5rem;
}
[data-theme="classic"] .event-card__body {
  padding: 0.75rem 0.25rem 0;
}
[data-theme="classic"] .event-card__title {
  font-size: var(--font-size-lg);
  font-weight: 700;
}
[data-theme="classic"] .event-card:hover { background: var(--color-surface-raised); }
[data-theme="classic"] .event-card__image { filter: none; }

/* ─── BoardMemberCardComponent ───────────*/
.board-card {
  display: block;
}
.board-card__portrait {
  background: var(--color-surface-raised);
  position: relative;
  overflow: hidden;
}
.board-card__image {
  transition: transform 1.2s cubic-bezier(0.16, 1, 0.3, 1),
              filter var(--transition-base);
  filter: grayscale(0.4) contrast(1.05);
}
.board-card__initial {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  font-family: var(--font-serif-display);
  font-size: 3rem;
  color: var(--color-text-muted);
}
.board-card__body {
  padding: 1rem 0 0;
}
.board-card__name {
  font-size: var(--font-size-xl);
  color: var(--color-text);
}
.board-card__role {
  color: var(--color-primary);
  margin-top: 0.35rem;
}
.board-card__bio {
  margin-top: 0.75rem;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-relaxed);
}
[data-theme="modern"] .board-card { border-top: 1px solid var(--color-border); padding-top: 1.25rem; }
[data-theme="modern"] .board-card:hover .board-card__image { transform: scale(1.05); filter: grayscale(0) contrast(1); }
[data-theme="classic"] .board-card {
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  padding: 0.5rem;
}
[data-theme="classic"] .board-card__body { padding: 0.75rem 0.25rem 0; }
[data-theme="classic"] .board-card__name { font-size: var(--font-size-lg); font-weight: 700; }
[data-theme="classic"] .board-card__image { filter: none; }

/* ─── PartnerCardComponent ───────────*/
.partner-card {
  display: block;
}
.partner-card__mark {
  background: var(--color-surface-raised);
  position: relative;
  overflow: hidden;
}
.partner-card__image {
  transition: transform 1.2s cubic-bezier(0.16, 1, 0.3, 1),
              filter var(--transition-base);
  filter: grayscale(0.4) contrast(1.05);
  padding: 1.5rem;
}
.partner-card__initial {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  font-family: var(--font-serif-display);
  font-size: 3rem;
  color: var(--color-text-muted);
}
.partner-card__body {
  padding: 1rem 0 0;
}
.partner-card__name {
  font-size: var(--font-size-xl);
  color: var(--color-text);
}
.partner-card__description {
  margin-top: 0.75rem;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-relaxed);
}
.partner-card__link {
  margin-top: 0.75rem;
  display: inline-flex;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-primary);
}
[data-theme="modern"] .partner-card { border-top: 1px solid var(--color-border); padding-top: 1.25rem; }
[data-theme="modern"] .partner-card:hover .partner-card__image { transform: scale(1.05); filter: grayscale(0) contrast(1); }
[data-theme="classic"] .partner-card {
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  padding: 0.5rem;
}
[data-theme="classic"] .partner-card__body { padding: 0.75rem 0.25rem 0; }
[data-theme="classic"] .partner-card__name { font-size: var(--font-size-lg); font-weight: 700; }
[data-theme="classic"] .partner-card__image { filter: none; }

/* ─── Public media archive ───────*/
/* A collapsible category list, each category holding an irregular gallery of its
   own photos. The two themes share the tile rhythm and nothing else: Modern is a
   hairline editorial index, Classic a stack of framed album panels. */
.media-group__summary {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 0.2rem 1rem;
  /* Keeps the whole row a comfortable touch target, matching .hmd-course__summary. */
  min-height: 2.75rem;
  cursor: pointer;
  list-style: none;
  color: var(--color-text);
}
.media-group__summary::-webkit-details-marker { display: none; }
.media-group__summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.media-group__title {
  grid-column: 1;
  grid-row: 1;
  margin: 0;
  /* Long titles wrap rather than pushing the count off the row. */
  overflow-wrap: anywhere;
}
.media-group__date,
.media-group__count {
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.media-group__date { grid-column: 1; grid-row: 2; }
.media-group__count { grid-column: 2; grid-row: 1; justify-self: end; white-space: nowrap; }
.media-group__toggle { grid-column: 2; grid-row: 2; justify-self: end; }
/* Open/closed is carried by a glyph as well as by the photos themselves, so it
   never depends on color or position alone. */
.media-group__toggle::before {
  content: "+";
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}
.media-group[open] > .media-group__summary .media-group__toggle::before { content: "\2013"; }
.media-group__empty {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}
.media-group__permalink {
  display: inline-block;
  margin-top: 1.5rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.media-group__permalink:hover,
.media-group__permalink:focus-visible { color: var(--color-text); }

/* ── The gallery itself ── */
/* One twelve-column grid, walked in a six-tile cycle: a portrait lead next to a
   wider frame, one photo the full width, then three compact tiles. Every tile
   keeps a fixed frame ratio, so the page never reflows as photos load. */
.media-gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem;
  align-items: start;
}
.media-tile { display: block; }
.media-tile__frame {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--color-surface-raised);
  aspect-ratio: var(--tile-ratio, 1 / 1);
}
.media-tile__image {
  display: block;
  width: 100%;
  height: 100%;
  /* Frames crop; the image is never stretched off its own aspect ratio. */
  object-fit: cover;
}
.media-tile:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 3px;
}
.media-tile--lead { --tile-ratio: 4 / 5; }
.media-tile--wide { --tile-ratio: 4 / 5; }
.media-tile--feature { grid-column: span 2; --tile-ratio: 3 / 2; }
.media-tile--small { --tile-ratio: 1 / 1; }

@media (min-width: 768px) {
  .media-gallery { grid-template-columns: repeat(12, 1fr); }
  .media-tile--lead { grid-column: span 4; --tile-ratio: 4 / 5; }
  .media-tile--wide { grid-column: span 8; --tile-ratio: 3 / 2; }
  .media-tile--feature { grid-column: span 12; --tile-ratio: 21 / 9; }
  .media-tile--small { grid-column: span 4; --tile-ratio: 1 / 1; }
}

/* ── Modern: editorial index, image-first, asymmetric ── */
[data-theme="modern"] .media-archive { border-top: 1px solid var(--color-border); }
[data-theme="modern"] .media-group { border-bottom: 1px solid var(--color-border); }
[data-theme="modern"] .media-group__summary {
  padding: 1.5rem 0;
  transition: padding-left var(--transition-base) cubic-bezier(0.16, 1, 0.3, 1);
}
[data-theme="modern"] .media-group__summary:hover,
[data-theme="modern"] .media-group__summary:focus-visible { padding-left: 0.5rem; }
[data-theme="modern"] .media-group__title {
  font-family: var(--font-serif-display);
  font-size: var(--font-size-2xl);
  font-weight: var(--font-weight-normal);
  letter-spacing: var(--letter-spacing-tight);
  line-height: var(--line-height-tight);
}
[data-theme="modern"] .media-group__body { padding: 0.75rem 0 3.5rem; }
[data-theme="modern"] .media-gallery { gap: 1rem; }
[data-theme="modern"] .media-tile__image {
  transition: transform 1.2s cubic-bezier(0.16, 1, 0.3, 1),
              filter var(--transition-base);
  filter: grayscale(0.35) contrast(1.05);
}
[data-theme="modern"] .media-tile:hover .media-tile__image,
[data-theme="modern"] .media-tile:focus-visible .media-tile__image {
  transform: scale(1.05);
  filter: grayscale(0) contrast(1);
}

@media (min-width: 768px) {
  [data-theme="modern"] .media-gallery { gap: 2.5rem 1.25rem; }
  /* The middle tile of each compact run drops out of line, so the grid reads as a
     composition rather than as rows. */
  [data-theme="modern"] .media-gallery > .media-tile:nth-child(6n+5) { margin-top: 2.5rem; }
}

/* ── Classic: a contact sheet of mounted prints, aligned and dense ── */
[data-theme="classic"] .media-group + .media-group { margin-top: 0.75rem; }
[data-theme="classic"] .media-group__summary {
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  padding: 0.5rem 0.75rem;
}
[data-theme="classic"] .media-group__summary:hover { background: var(--color-surface-raised); }
[data-theme="classic"] .media-group__title {
  font-size: var(--font-size-lg);
  font-weight: var(--font-weight-bold);
}
[data-theme="classic"] .media-group__body {
  padding: 0.75rem;
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
}
[data-theme="classic"] .media-gallery { gap: 0.5rem; }
/* Every print is mounted on a mat of the same size and sits inside it whole:
   nothing is cropped, nothing is enlarged out of line. The photos keep their own
   shapes against the mats, and the sheet — not any single photo — is the
   composition. Modern's mosaic is the other half of that argument. */
[data-theme="classic"] .media-tile {
  background: var(--color-background);
  box-shadow: var(--shadow-inset);
  padding: 0.3rem;
  grid-column: span 1;
  --tile-ratio: 4 / 3;
}
[data-theme="classic"] .media-tile:hover { background: var(--color-surface-raised); }
[data-theme="classic"] .media-tile__frame { background: transparent; }
[data-theme="classic"] .media-tile__image { filter: none; object-fit: contain; }

@media (min-width: 640px) {
  [data-theme="classic"] .media-gallery { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1024px) {
  [data-theme="classic"] .media-gallery { grid-template-columns: repeat(4, 1fr); }
}

/* ─── Full-size photo viewer (native <dialog>) ───────*/
.photo-viewer {
  --viewer-fg: #f2efe8;
  --viewer-line: rgba(242, 239, 232, 0.45);
  color: var(--viewer-fg);
  border: 0;
  padding: 1rem;
  margin: 0;
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  background: transparent;
}
.photo-viewer[open] { display: flex; flex-direction: column; gap: 0.75rem; }
.photo-viewer::backdrop { background: rgba(10, 10, 9, 0.97); }
.photo-viewer__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}
.photo-viewer__position {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
}
.photo-viewer__actions { display: flex; align-items: center; gap: 0.5rem; }
.photo-viewer__action,
.photo-viewer__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 2.75rem;
  padding: 0 0.75rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: inherit;
  background: transparent;
  border: 1px solid var(--viewer-line);
  cursor: pointer;
}
.photo-viewer__action:hover,
.photo-viewer__nav:hover { background: rgba(242, 239, 232, 0.14); }
.photo-viewer__action:focus-visible,
.photo-viewer__nav:focus-visible { outline: 2px solid var(--viewer-fg); outline-offset: 2px; }
.photo-viewer__glyph { font-size: var(--font-size-base); line-height: 1; }
.photo-viewer__stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  /* Lets the image shrink inside the flex column instead of overflowing it. */
  min-height: 0;
}
.photo-viewer__nav { flex: none; min-width: 2.75rem; padding: 0; font-size: var(--font-size-lg); }
.photo-viewer__nav[hidden] { display: none; }
.photo-viewer__image {
  /* Lets the photo give way to the navigation buttons instead of pushing them
     off the stage. */
  min-width: 0;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* Classic opens the photo as a framed window rather than as a full-bleed
   overlay, keeping the theme's document metaphor. */
[data-theme="classic"] .photo-viewer {
  --viewer-fg: var(--color-text);
  --viewer-line: var(--color-border);
  margin: auto;
  /* fit-content, not auto: a modal dialog is absolutely positioned against both
     edges, where an auto height would stretch to fill the viewport. */
  width: fit-content;
  height: fit-content;
  max-width: 94vw;
  max-height: 92vh;
  padding: 0.5rem;
  background: var(--color-surface);
  box-shadow: var(--shadow-lg);
}
[data-theme="classic"] .photo-viewer::backdrop { background: rgba(0, 0, 0, 0.55); }
[data-theme="classic"] .photo-viewer__bar {
  background: var(--color-primary);
  color: var(--color-primary-foreground);
  padding: 0.2rem 0.2rem 0.2rem 0.5rem;
}
[data-theme="classic"] .photo-viewer__action,
[data-theme="classic"] .photo-viewer__nav {
  background: var(--color-surface);
  color: var(--color-text);
  border: 0;
  box-shadow: var(--shadow-sm);
  text-transform: none;
  letter-spacing: 0;
  font-family: var(--font-sans);
}
[data-theme="classic"] .photo-viewer__action:hover,
[data-theme="classic"] .photo-viewer__nav:hover { background: var(--color-surface-raised); }
[data-theme="classic"] .photo-viewer__stage { padding: 0.5rem 0 0; }
[data-theme="classic"] .photo-viewer__image { max-height: 70vh; box-shadow: var(--shadow-inset); }

@media (prefers-reduced-motion: reduce) {
  .media-group__summary,
  .media-tile__image { transition: none; }
  [data-theme="modern"] .media-tile:hover .media-tile__image,
  [data-theme="modern"] .media-tile:focus-visible .media-tile__image { transform: none; }
}

/* ─── FormFieldComponent ───────────*/
[data-theme="modern"] .form-field__input {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--color-border-strong);
  padding: 0.5rem 0.25rem;
  border-radius: 0;
  color: var(--color-text);
  transition: border-color var(--transition-fast);
}
[data-theme="modern"] .form-field__input:focus,
[data-theme="modern"] .form-field__input:focus-visible {
  border-bottom-color: var(--color-primary);
  box-shadow: 0 1px 0 0 var(--color-primary);
  outline: none;
}
[data-theme="modern"] .form-field__input.is-invalid { border-bottom-color: var(--color-destructive); }
[data-theme="modern"] .form-field__label {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}

[data-theme="classic"] .form-field__input {
  border: 0;
  box-shadow: var(--shadow-inset);
  background: #ffffff;
  padding: 0.25rem 0.4rem;
  font-family: var(--font-sans);
  font-size: var(--font-size-sm);
  color: var(--color-text);
}
[data-theme="classic"] .form-field__input:focus,
[data-theme="classic"] .form-field__input:focus-visible {
  outline: 1px dotted var(--color-primary);
  outline-offset: 1px;
}
[data-theme="classic"] .form-field__label {
  font-weight: 700;
  color: var(--color-text);
}

.form-field__checkbox {
  width: 1rem;
  height: 1rem;
  accent-color: var(--color-primary);
}

/* ─── AlertComponent ───────────*/
[data-theme="classic"] .alert {
  box-shadow: var(--shadow-sm);
  font-family: var(--font-sans);
  font-size: var(--font-size-sm);
  background: var(--color-surface);
}
[data-theme="modern"] .alert--notice { border-left-width: 2px; }
[data-theme="modern"] .alert { padding: 0.75rem 1rem; background: var(--color-surface); }

/* ─── Flash popup region ───────────
   The container spans the viewport top so stacked items stay centred, but
   it must not swallow clicks aimed at the page behind it — only the alerts
   themselves are interactive. */
.flash-container { pointer-events: none; }
.flash-item { pointer-events: auto; }

/* Exit transition played by flash.js. The duration must stay in step with
   EXIT_MS in app/assets/javascripts/flash.js. */
.flash-item {
  transition: opacity 300ms ease-out, transform 300ms ease-out;
}
.flash-item.flash-exit {
  opacity: 0;
  transform: translateY(-0.5rem);
}
@media (prefers-reduced-motion: reduce) {
  .flash-item { transition: none; }
}

.alert__dismiss {
  font-size: 1.25rem;
  line-height: 1;
  color: currentColor;
  opacity: 0.6;
  background: none;
  border: 0;
  cursor: pointer;
}
.alert__dismiss:hover { opacity: 1; }

[data-theme="modern"] .alert--warning { border-left-width: 2px; }

/* ─── Account page ───────────
   The shared .btn is sized for dense inline use. On the account page it
   sits in a stacked column of the only actions a member has, where it falls
   short of the 44px touch-target minimum, and the Classic bevel makes it
   shorter still. Raised here rather than globally so other pages keep
   their density. */
.account-card .btn {
  min-height: 2.75rem;
}

/* ─── Hand-Me-Downs archive ───────────
   A members-only index: a stack of disclosure rows, one per course, over two
   contribution forms. Modern reads it as an editorial index (hairline rules,
   serif course names, mono counters, a marker that slides). Classic reads it
   as a file drawer (bevelled panels, flush rows, a folder marker), so the two
   themes differ in geometry and density, not just in color. */
.hmd { max-width: 60rem; }

.hmd-lede { margin-bottom: 3rem; }
.hmd-lede__title {
  font-size: var(--font-size-3xl);
  color: var(--color-text);
}
.hmd-lede__intro {
  margin-top: 0.75rem;
  max-width: 34rem;
  color: var(--color-text-muted);
  line-height: var(--line-height-relaxed);
}
.hmd-heading {
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--color-border);
}
.hmd-contribute { margin-top: 4rem; }
.hmd-contribute__intro {
  margin: 0.75rem 0 1.25rem;
  max-width: 34rem;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-relaxed);
}

/* ── Course disclosure ── */
.hmd-course { border-bottom: 1px solid var(--color-border); }
.hmd-course__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  /* Keeps the whole row a comfortable touch target, matching .account-card .btn. */
  min-height: 2.75rem;
  padding: 0.9rem 0;
  cursor: pointer;
  list-style: none;
  color: var(--color-text);
}
.hmd-course__summary::-webkit-details-marker { display: none; }
.hmd-course__summary:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.hmd-course__name { display: inline-flex; align-items: center; gap: 0.75rem; }
/* The open/closed state is carried by a glyph as well as by position, so it never
   depends on color alone. */
.hmd-course__name::before {
  content: "+";
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}
.hmd-course[open] > .hmd-course__summary .hmd-course__name::before { content: "-"; }
.hmd-course__count {
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.hmd-course__body { padding: 0.5rem 0 1.5rem; }

.hmd-group + .hmd-group { margin-top: 1.75rem; }
.hmd-group__title {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-bold);
  color: var(--color-text);
  margin-bottom: 0.75rem;
}
.hmd-empty {
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
}

/* ── One submission ── */
.hmd-list { display: flex; flex-direction: column; }
.hmd-item {
  padding: 0.9rem 0;
  border-top: 1px solid var(--color-border);
}
.hmd-item__title {
  color: var(--color-text);
  font-weight: var(--font-weight-medium);
}
.hmd-item__meta {
  margin-top: 0.25rem;
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
}
.hmd-item__body,
.hmd-item__note {
  margin-top: 0.4rem;
  max-width: 42rem;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  line-height: var(--line-height-relaxed);
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.hmd-item__note { font-style: italic; }
.hmd-item__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-top: 0.75rem;
}
.hmd-item__votes {
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
}
.hmd-download {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--color-primary);
  font-size: var(--font-size-sm);
  text-decoration: underline;
  text-underline-offset: 0.25em;
  overflow-wrap: anywhere;
}
.hmd-download:hover { color: var(--color-primary-hover); }

/* ── Upvote control ──
   The voted state changes the word, the border and the cursor, not just the
   color, so it is still unmistakable in greyscale or at low contrast. */
.hmd-vote {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 1rem;
  border: 1px solid var(--color-border-strong);
  background: transparent;
  color: var(--color-text);
  font-family: var(--font-mono);
  font-size: var(--font-size-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}
.hmd-vote:hover { border-color: var(--color-primary); color: var(--color-primary); }
.hmd-vote:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.hmd-vote--voted,
.hmd-vote[disabled] {
  border-style: dashed;
  border-color: var(--color-border);
  color: var(--color-text-muted);
  opacity: 0.65;
  cursor: not-allowed;
}
.hmd-vote--voted::before {
  content: "x";
  font-family: var(--font-mono);
  margin-right: 0.5rem;
}
.hmd-vote--voted:hover {
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

/* ── Contribution forms ── */
.hmd-form {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 34rem;
}
.hmd-form__field { display: flex; flex-direction: column; gap: 0.35rem; }
.hmd-form__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text);
}
.hmd-form__help {
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}
.hmd-form__control {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.5rem 0.75rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-inset);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--font-size-sm);
}
.hmd-form__control:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -1px;
  border-color: var(--color-primary);
}
textarea.hmd-form__control { min-height: 6rem; resize: vertical; }
.hmd-form__control--file { padding: 0.6rem 0.75rem; }
/* Deliberately not .btn: the shared button carries a Classic override marked
   !important, which would fight the bevel this form needs. */
.hmd-form__submit {
  align-self: flex-start;
  min-height: 2.75rem;
  padding: 0 1.25rem;
  background: var(--color-accent);
  color: var(--color-accent-foreground);
  border: 1px solid var(--color-accent);
  font-family: inherit;
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}
.hmd-form__submit:hover {
  background: var(--color-accent-hover);
  border-color: var(--color-accent-hover);
}
.hmd-form__submit:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ── Modern: editorial index, generous rules, serif course names ── */
[data-theme="modern"] .hmd-course__name {
  font-family: var(--font-serif-display);
  font-size: var(--font-size-lg);
  letter-spacing: var(--letter-spacing-tight);
}
[data-theme="modern"] .hmd-course__summary {
  transition: padding-left var(--transition-base) cubic-bezier(0.16, 1, 0.3, 1),
              color var(--transition-fast);
}
[data-theme="modern"] .hmd-course__summary:hover,
[data-theme="modern"] .hmd-course__summary:focus-visible {
  padding-left: 0.75rem;
  color: var(--color-primary);
}
[data-theme="modern"] .hmd-index { border-top: 1px solid var(--color-border); }
[data-theme="modern"] .hmd-course__body { padding-left: 0.75rem; }
@media (prefers-reduced-motion: reduce) {
  [data-theme="modern"] .hmd-course__summary { transition: none; }
}

/* ── Classic: a file drawer. Framed panels, flush rows, folder markers,
      no sliding chrome. ── */
[data-theme="classic"] .hmd-lede__title { font-size: var(--font-size-xl); }
[data-theme="classic"] .hmd-lede { margin-bottom: 1.25rem; }
[data-theme="classic"] .hmd-contribute { margin-top: 1.75rem; }
[data-theme="classic"] .hmd-heading {
  background: var(--color-primary);
  color: var(--color-primary-foreground);
  padding: 0.25rem 0.5rem;
  border-bottom: 0;
}
[data-theme="classic"] .hmd-index { margin-top: 0.5rem; }
[data-theme="classic"] .hmd-course {
  background: var(--color-surface);
  box-shadow: var(--shadow-sm);
  border-bottom: 0;
  margin-bottom: 0.35rem;
}
[data-theme="classic"] .hmd-course__summary {
  padding: 0.4rem 0.6rem;
  font-weight: var(--font-weight-bold);
}
[data-theme="classic"] .hmd-course__name::before { content: "[+]"; }
[data-theme="classic"] .hmd-course[open] > .hmd-course__summary .hmd-course__name::before { content: "[-]"; }
[data-theme="classic"] .hmd-course__body {
  padding: 0.6rem;
  border-top: 1px solid var(--color-border);
}
[data-theme="classic"] .hmd-item { padding: 0.5rem 0; }
[data-theme="classic"] .hmd-group + .hmd-group { margin-top: 1rem; }
[data-theme="classic"] .hmd-vote {
  border: 0;
  box-shadow: var(--shadow-sm);
  background: var(--color-background);
  padding: 0 0.75rem;
}
[data-theme="classic"] .hmd-vote:active { box-shadow: var(--shadow-inset); }
[data-theme="classic"] .hmd-vote--voted,
[data-theme="classic"] .hmd-vote[disabled] {
  box-shadow: var(--shadow-inset);
  border: 0;
}
[data-theme="classic"] .hmd-form__submit {
  background: var(--color-background);
  color: var(--color-text);
  border: 0;
  box-shadow: var(--shadow-sm);
  padding: 0 1rem;
}
[data-theme="classic"] .hmd-form__submit:hover { background: var(--color-surface-raised); }
[data-theme="classic"] .hmd-form__submit:active {
  box-shadow: var(--shadow-inset);
  transform: translate(1px, 1px);
}

/* ─── Admin media: the photos already on a category ───────────
 * A plain grid of thumbnails, each its own label, so the whole tile is the hit
 * target for the remove checkbox. Removal is state on the form, not an action of
 * its own: nothing leaves until the category is saved. */
.media-photos {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  border: 0;
}
.media-photos__legend {
  padding: 0;
}
.media-photos__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.media-photos__label {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  cursor: pointer;
}
.media-photos__thumb {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}
.media-photos__remove {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: var(--font-size-xs);
  color: var(--color-text-muted);
}
.media-photos__label:hover .media-photos__remove,
.media-photos__checkbox:focus-visible ~ .media-photos__remove {
  color: var(--color-text);
}
/* Ticked reads as "on its way out" before the page says so in words. */
.media-photos__label:has(.media-photos__checkbox:checked) .media-photos__thumb {
  opacity: 0.4;
  border-color: var(--color-destructive);
}
.media-photos__label:has(.media-photos__checkbox:checked) .media-photos__remove {
  color: var(--color-destructive);
  font-weight: var(--font-weight-bold);
}

/* Modern: hairline frames, the label set as a small-caps cue. */
[data-theme="modern"] .media-photos__remove {
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* Classic: mounted thumbnails in a bevelled well, like the rest of its chrome. */
[data-theme="classic"] .media-photos__grid {
  box-shadow: var(--shadow-inset);
  background: var(--color-background);
  padding: 0.5rem;
}
[data-theme="classic"] .media-photos__thumb {
  border: 0;
  box-shadow: var(--shadow-inset);
  padding: 2px;
}
[data-theme="classic"] .media-photos__remove {
  font-family: var(--font-mono);
}

/* ─── Admin media batch upload ───────────
 * Status is carried by the row's text and a glyph, never by colour alone; the
 * colours only reinforce it. Modern reads the queue as a hairline manifest,
 * Classic as a framed transfer dialog. */
.media-upload {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.media-upload__drop {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.75rem;
  border: 1px dashed var(--color-border);
  background: var(--color-surface);
}
.media-upload__drop.is-dragover {
  border-color: var(--color-primary);
  background: var(--color-surface-raised);
}
.media-upload__input { max-width: 100%; }
.media-upload__summary:empty { display: none; }
.media-upload__list {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  max-height: 18rem;
  overflow-y: auto;
  margin: 0;
  padding: 0;
  list-style: none;
}
.media-upload__list:empty { display: none; }
.media-upload__file {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.15rem 0.75rem;
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--color-border);
  font-size: var(--font-size-xs);
}
.media-upload__name {
  color: var(--color-text);
  overflow-wrap: anywhere;
}
.media-upload__state {
  color: var(--color-text-muted);
  text-align: right;
  overflow-wrap: anywhere;
}
.media-upload__file[data-state="uploading"] .media-upload__state::before { content: "↑ "; }
.media-upload__file[data-state="done"] .media-upload__state::before { content: "✓ "; }
.media-upload__file[data-state="rejected"] .media-upload__state::before,
.media-upload__file[data-state="failed"] .media-upload__state::before { content: "✕ "; }
.media-upload__file[data-state="done"] .media-upload__state { color: var(--color-success); }
.media-upload__file[data-state="rejected"] .media-upload__state,
.media-upload__file[data-state="failed"] .media-upload__state { color: var(--color-destructive); }
.media-upload__bar {
  grid-column: 1 / -1;
  display: block;
  height: 2px;
  background: var(--color-border);
}
.media-upload__bar > span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--color-primary);
  transition: width var(--transition-fast);
}
.media-upload__file[data-state="ready"] .media-upload__bar,
.media-upload__file[data-state="rejected"] .media-upload__bar { visibility: hidden; }
@media (max-width: 30rem) {
  .media-upload__file { grid-template-columns: minmax(0, 1fr); }
  .media-upload__state { text-align: left; }
}
@media (prefers-reduced-motion: reduce) {
  .media-upload__bar > span { transition: none; }
}

/* Modern: a manifest. Hairlines, small caps state column, no frame. */
[data-theme="modern"] .media-upload__drop {
  border: 1px solid var(--color-border);
  border-left-width: 2px;
  background: transparent;
}
[data-theme="modern"] .media-upload__state {
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* Classic: a transfer dialog. Bevelled frame, flush rows, blocky progress. */
[data-theme="classic"] .media-upload__drop {
  border: 0;
  box-shadow: var(--shadow-inset);
  background: var(--color-background);
  padding: 0.5rem;
}
[data-theme="classic"] .media-upload__list {
  box-shadow: var(--shadow-inset);
  background: var(--color-background);
  padding: 0.25rem 0.5rem;
  gap: 0;
}
[data-theme="classic"] .media-upload__file {
  font-family: var(--font-mono);
  border-bottom: 0;
  padding: 0.2rem 0;
}
[data-theme="classic"] .media-upload__bar {
  height: 0.5rem;
  box-shadow: var(--shadow-inset);
  background: var(--color-surface);
}
[data-theme="classic"] .media-upload__summary { font-weight: var(--font-weight-bold); }
