/* ============================================================
   SELECTED WORK — case-study grid + detail dialog.

   Deliberately a *content* surface, not a HUD surface: the bento
   tiles use backdrop-blur and tight density because they are
   instrument panels. These are things to read, so they get solid
   surfaces, more air, and longer measures. Same tokens, same
   accent, same easing — different job.
   ============================================================ */

:root {
  /* status colours — tuned per scheme further down */
  --ok: #3ddc97;
  --ok-ink: #3ddc97;
  --warn: #f5c542;
  --warn-ink: #f5c542;
  --idle: #8b94a3;

  /* long-form reading colour: softer than --text, still >7:1 */
  --prose: #c3cad6;

  /* the plate the SVG schematics sit on */
  --shot-bg: linear-gradient(150deg, #171b25, #10131a 70%);
}

@media (prefers-color-scheme: light) {
  :root {
    --ok: #0f9d63;
    --ok-ink: #0a6f47;
    --warn: #b4740a;
    --warn-ink: #8a5a08;
    --idle: #5b6478;
    --prose: #2f374a;
    --shot-bg: linear-gradient(150deg, #f7f9fc, #eaeef5 70%);
  }

}

/* ------------------------------------------------------------
   SECTION FRAME
   ------------------------------------------------------------ */

.work {
  padding: clamp(56px, 9vw, 128px) 0 clamp(32px, 5vw, 64px);
  scroll-margin-top: 24px;
}

.work-head {
  max-width: 68ch;
  margin-bottom: clamp(28px, 4vw, 44px);
}

.work-head .label {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin: 0 0 var(--s4);
}
.work-head .label svg { width: 13px; height: 13px; stroke: var(--accent); }

#work-title {
  margin: 0 0 var(--s4);
  font-size: clamp(34px, 5.4vw, 60px);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
}
/* one small piece of punctuation carries the accent — not the whole heading */
#work-title em { font-style: normal; color: var(--accent); }

.work-intro {
  margin: 0;
  max-width: 58ch;
  font-size: clamp(15px, 1.3vw, 17.5px);
  color: var(--muted);
  line-height: 1.6;
}

/* ------------------------------------------------------------
   FILTER BAR
   Real links (#work/<category>) so the state is shareable and the
   control still means something with JavaScript switched off.
   ------------------------------------------------------------ */

.work-filters { margin-bottom: clamp(20px, 3vw, 32px); }

.filter-row {
  display: flex;
  gap: var(--s2);
  margin: 0;
  padding: 0 2px 4px;
  list-style: none;
  overflow-x: auto;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
}
.filter-row::-webkit-scrollbar { display: none; }
.filter-row li { flex: none; scroll-snap-align: start; }

.fbtn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;                 /* touch target, not a decorative pill */
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color .2s var(--ease-out), border-color .2s var(--ease-out),
              background-color .2s var(--ease-out);
}
.fbtn:hover { color: var(--text); border-color: var(--line-strong); }

.fbtn .fcount {
  display: inline-grid;
  place-items: center;
  min-width: 19px;
  height: 19px;
  padding: 0 5px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--text) 10%, transparent);
  font-size: 10px;
  letter-spacing: 0;
  color: inherit;
}

.fbtn.is-on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.fbtn.is-on .fcount { background: color-mix(in srgb, var(--on-accent) 18%, transparent); }

.nojs-note {
  display: none;
  margin: var(--s3) 0 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  letter-spacing: .06em;
  color: var(--muted);
}
.no-js .nojs-note { display: block; }

/* ------------------------------------------------------------
   GRID + CARDS
   ------------------------------------------------------------ */

.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: clamp(14px, 1.6vw, 22px);
  align-items: start;
}

.case {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  overflow: hidden;
  /* transform/opacity only — the FLIP pass drives these directly */
  transition: border-color .25s var(--ease-out), box-shadow .25s var(--ease-out);
}

/* .case sets display:flex, which outranks the [hidden] attribute's UA
   display:none — so filtered-out cards stayed on screen while JavaScript
   believed they were hidden. Specificity (0,2,0) beats .case (0,1,0). */
.case[hidden] { display: none; }

.case-card { display: contents; }

/* the whole card is clickable, but the <a> in the heading is the real
   control — one tab stop, and it still works with JS off */
.case-title a::after { content: ''; position: absolute; inset: 0; }

.case:hover { border-color: var(--line-strong); box-shadow: 0 0 44px -18px var(--glow); }
.case:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}
.case-title a:focus-visible { outline: none; }   /* the card carries the ring */

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .case { transition: border-color .25s var(--ease-out), box-shadow .25s var(--ease-out), transform .25s var(--ease-out); }
  .case:hover { transform: translateY(-3px); }
  .case:hover .case-shot img { transform: scale(1.035); }
  .case:hover .case-cta svg { transform: translateX(3px); }
}

/* ---- thumbnail ---- */
.case-shot {
  position: relative;
  aspect-ratio: 16 / 9;          /* space reserved before the SVG loads */
  background: var(--shot-bg);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.case-shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .4s var(--ease-out);
}

/* ---- meta ---- */
.case-meta {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  padding: var(--s5) var(--s5) var(--s4);
  flex: 1;
}

.case-kicker {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
  margin: 0;
}

.case-cat {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px 3px 7px;
  border-radius: 99px;
  border: 1px solid currentColor;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.badge::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}
/* status is never colour alone — the label spells it out */
.badge-live { color: var(--ok-ink); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.badge-wip  { color: var(--warn-ink); background: color-mix(in srgb, var(--warn) 14%, transparent); }
.badge-archived { color: var(--idle); background: color-mix(in srgb, var(--idle) 12%, transparent); }

.case-title {
  margin: 0;
  font-size: clamp(19px, 1.7vw, 22px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.case-title a { text-decoration: none; color: var(--text); }

.case-hook {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 46ch;
}

/* ---- stack chips ---- */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.chips li {
  padding: 3px 9px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: color-mix(in srgb, var(--text) 4%, transparent);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .04em;
  color: var(--muted);
  white-space: nowrap;
}

.case-cta {
  display: flex;
  align-items: center;
  gap: var(--s2);
  margin: auto 0 0;
  padding-top: var(--s2);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
}
.case-cta svg { width: 15px; height: 15px; transition: transform .25s var(--ease-out); }
.no-js .case-cta { display: none; }

.work-empty {
  margin: var(--s6) 0 0;
  font-size: 15px;
  color: var(--muted);
}
.work-empty a { color: var(--accent); }

/* ------------------------------------------------------------
   CASE DETAIL — prose shared by the JS-off list and the dialog
   ------------------------------------------------------------ */

.case-detail {
  padding: var(--s5) var(--s5) var(--s6);
  border-top: 1px dashed var(--line);
}
/* with JS on, details live in #case-store until a dialog needs one */
.js .case-detail { display: none; }
.js .cm-body .case-detail { display: block; border-top: none; padding: 0; }

.cd-block { margin: 0 0 var(--s6); }
.cd-block:last-child { margin-bottom: 0; }

.cd-block h4 {
  margin: 0 0 var(--s3);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
}

.cd-block p {
  margin: 0;
  max-width: 66ch;
  font-size: 16px;
  line-height: 1.72;
  color: var(--prose);
}
.cd-block em { font-style: italic; color: var(--text); }
.cd-block code {
  font-family: var(--font-mono);
  font-size: .88em;
  padding: 1px 5px;
  border-radius: 5px;
  border: 1px solid var(--line);
  background: color-mix(in srgb, var(--text) 6%, transparent);
  color: var(--text);
}

.linkrow { display: flex; flex-wrap: wrap; gap: var(--s3); }

/* "no public link, and here is why" — a real answer, so it keeps prose size
   and only shifts tone. Needs p.cd-note: plain .cd-note loses to .cd-block p,
   which is one element-selector more specific. */
.cd-block p.cd-note {
  max-width: 62ch;
  color: var(--muted);
}

.ext {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-btn);
  background: color-mix(in srgb, var(--text) 4%, transparent);
  color: var(--text);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: border-color .2s var(--ease-out), background-color .2s var(--ease-out);
}
.ext:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.ext svg { width: 14px; height: 14px; stroke: var(--accent); }

/* ------------------------------------------------------------
   DIALOG
   ------------------------------------------------------------ */

.case-modal {
  width: min(760px, calc(100vw - 32px));
  max-height: min(88dvh, 900px);
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 18px;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-win);
  overflow: hidden;
}
.case-modal::backdrop {
  background: rgba(4, 6, 10, .62);
  backdrop-filter: blur(6px);
}
@media (prefers-color-scheme: light) {
  .case-modal::backdrop { background: rgba(20, 26, 38, .48); }
}

.cm-shell {
  display: flex;
  flex-direction: column;
  max-height: inherit;
  max-height: min(88dvh, 900px);
}

.cm-head {
  display: flex;
  align-items: flex-start;
  gap: var(--s4);
  padding: var(--s5) var(--s5) var(--s4);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.cm-headings { flex: 1; min-width: 0; }

.cm-kicker {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
  margin: 0 0 var(--s2);
}
.cm-cat {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

.cm-title {
  margin: 0;
  font-size: clamp(22px, 3vw, 30px);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.12;
}
.cm-hook {
  margin: var(--s2) 0 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--muted);
  max-width: 56ch;
}

.cm-close {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--muted);
  background: transparent;
  transition: color .2s var(--ease-out), border-color .2s var(--ease-out), background-color .2s var(--ease-out);
}
.cm-close:hover { color: var(--text); border-color: var(--line-strong); background: color-mix(in srgb, var(--text) 7%, transparent); }
.cm-close svg { width: 17px; height: 17px; }

.cm-body {
  padding: var(--s6) var(--s5);
  overflow-y: auto;
  overscroll-behavior: contain;
  flex: 1;
}

.cm-foot {
  display: flex;
  gap: var(--s2);
  padding: var(--s3) var(--s4);
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--text) 3%, transparent);
}
.cm-nav {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r-btn);
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  max-width: 50%;
  transition: color .2s var(--ease-out), background-color .2s var(--ease-out);
}
.cm-nav span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-nav:hover { color: var(--text); background: color-mix(in srgb, var(--text) 7%, transparent); }
.cm-nav svg { width: 15px; height: 15px; flex: none; }
.cm-next { margin-left: auto; }
.cm-nav[hidden] { display: none; }

/* entrance: transform + opacity only, exit quicker than enter */
@media (prefers-reduced-motion: no-preference) {
  .case-modal[open] { animation: cm-in .24s var(--ease-out); }
  .case-modal[open]::backdrop { animation: cm-fade .24s var(--ease-out); }
  .case-modal.is-closing { animation: cm-out .15s var(--ease-in) forwards; }
  .case-modal.is-closing::backdrop { animation: cm-fade .15s var(--ease-in) reverse forwards; }
}
@keyframes cm-in   { from { opacity: 0; transform: translateY(14px) scale(.985); } }
@keyframes cm-out  { to   { opacity: 0; transform: translateY(8px) scale(.99); } }
@keyframes cm-fade { from { opacity: 0; } }

/* body scroll lock while the dialog owns the screen */
body.cm-open { overflow: hidden; }

/* ------------------------------------------------------------
   RESPONSIVE
   ------------------------------------------------------------ */

@media (max-width: 900px) {
  .work-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
}

@media (max-width: 640px) {
  .work-grid { grid-template-columns: 1fr; }
  .case-meta { padding: var(--s4); }
  .cm-head { padding: var(--s4); }
  .cm-body { padding: var(--s5) var(--s4); }
  .case-detail { padding: var(--s4); }
  .cd-block { margin-bottom: var(--s5); }
}

/* 320px: nothing may overflow the viewport */
@media (max-width: 380px) {
  .work { padding-top: 48px; }
  .case-hook { font-size: 14px; }
  .chips li { font-size: 10.5px; }
  .cm-nav span { display: none; }
  .cm-nav { padding: 0 12px; }
}

/* the blur/backdrop budget on phones is already spent by the bento */
@media (max-width: 760px) {
  .case-modal::backdrop { backdrop-filter: none; background: rgba(4, 6, 10, .78); }
}

@media (prefers-reduced-motion: reduce) {
  .case, .case-shot img, .case-cta svg { transition: none; }
}

/* ------------------------------------------------------------
   LIGHT-SCHEME OVERRIDES

   Last in the file on purpose. A vivid accent is paint, not ink:
   #4cc3ff on paper is about 2:1. Anywhere the accent carries
   meaning as text or as an icon it swaps to the darkened form.
   These have the same specificity as the rules they correct, so
   they only win by coming after them.
   ------------------------------------------------------------ */

@media (prefers-color-scheme: light) {
  #work-title em,
  .case-cta,
  .cd-block h4,
  .work-empty a { color: var(--accent-ink); }

  .work-head .label svg,
  .ext svg { stroke: var(--accent-ink); }

  .ext:hover { border-color: var(--accent-ink); background: color-mix(in srgb, var(--accent-ink) 10%, transparent); }

  .fbtn.is-on {
    background: var(--accent-ink);
    border-color: var(--accent-ink);
    color: #fff;
  }
  .fbtn.is-on .fcount { background: rgba(255, 255, 255, .24); }

  .case:focus-within {
    border-color: var(--accent-ink);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-ink) 28%, transparent);
  }
}

/* ============================================================
   POLISH PASS — fluid layout, entrance motion, quieter status
   ============================================================ */

/* ---- Truly fluid columns ------------------------------------
   min(100%, 340px) is the whole trick: the track can never demand
   more width than the container has, so the grid degrades to one
   column on its own and cannot force a horizontal scrollbar at any
   viewport. That replaces the 900px and 640px breakpoints that used
   to do this job in steps.
   ------------------------------------------------------------ */
.work-grid {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr));
  gap: clamp(14px, 1.4vw, 24px);
}

/* Ultrawide: stop the page stretching to 2560px of unreadable line
   length. The bento and the section share the cap so their left
   edges stay aligned. */
.bento,
.work,
.land-top,
.land-foot {
  max-width: 1800px;
  margin-inline: auto;
  width: 100%;
}

/* ---- Entrance motion ---------------------------------------
   Armed by JavaScript, never by CSS alone: if the script fails or
   IntersectionObserver is missing, nothing is ever hidden. Uses
   animation rather than transition so no transform lingers on the
   element to fight the FLIP pass when a filter is applied.
   ------------------------------------------------------------ */
.reveal-armed .case:not(.is-in),
.reveal-armed .work-head:not(.is-in),
.reveal-armed .work-filters:not(.is-in) { opacity: 0; }

.reveal-armed .case.is-in,
.reveal-armed .work-head.is-in,
.reveal-armed .work-filters.is-in { opacity: 1; }
/* the rise itself is played from js/work.js with the Web Animations API, so
   an element that never gets animated is simply visible rather than blank */

/* ---- Status: eleven cards all read "Live", so the badge is a
        quiet confirmation, not an alert ------------------------ */
.badge {
  border-color: color-mix(in srgb, currentColor 38%, transparent);
  font-weight: 500;
}
.badge-live { background: color-mix(in srgb, var(--ok) 9%, transparent); }
.badge-wip  { background: color-mix(in srgb, var(--warn) 10%, transparent); }

/* ---- Card polish -------------------------------------------
   The thumbnail plate gets a hairline of accent on hover: enough
   to confirm the card is live under the cursor without moving
   anything or repainting the whole surface.
   ------------------------------------------------------------ */
.case-shot::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), transparent);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform .4s var(--ease-out);
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .case:hover .case-shot::after,
  .case:focus-within .case-shot::after { transform: scaleX(1); }
}

/* the CTA slides its label as well as its arrow */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .case-cta span { transition: transform .25s var(--ease-out); }
  .case:hover .case-cta span { transform: translateX(2px); }
}

/* ---- Dialog: give the body a little more room at large sizes -- */
@media (min-width: 1100px) {
  .case-modal { width: min(820px, calc(100vw - 48px)); }
  .cm-body { padding: var(--s6) var(--s6); }
}

/* ---- Very wide phones / small tablets in landscape ----------
   88dvh of dialog on a 400px-tall landscape phone leaves no room
   for the header, so let the body take what it needs and scroll.
   ------------------------------------------------------------ */
@media (max-height: 520px) {
  .case-modal, .cm-shell { max-height: 94dvh; }
  .cm-head { padding: var(--s3) var(--s4); }
  .cm-title { font-size: clamp(18px, 3vw, 22px); }
  .cm-hook { display: none; }
  .cm-body { padding: var(--s4); }
}

/* ---- 320px floor -------------------------------------------- */
@media (max-width: 360px) {
  .case-meta { padding: var(--s4) var(--s3) var(--s3); }
  .chips li { padding: 3px 7px; }
  .fbtn { padding: 0 12px; }
}

/* ============================================================
   REEL — the Jitter "Orbit" format, rebuilt on real cards

   The reference (4-3.json) is a horizontal conveyor: seven cards on
   a 680px pitch stepping left one slot at a time, with the strip
   scaling to 125% for the beat where a card sits in the middle.

   This reproduces that motion on the actual project cards rather
   than embedding the Lottie, so the content stays real: clickable,
   selectable, screen-reader readable, and correct when a project
   changes. Built on native scroll-snap, so touch, trackpad, keyboard
   and the scrollbar all work without any of it being reimplemented.
   ============================================================ */

.work-grid.is-reel {
  display: flex;
  grid-template-columns: none;
  gap: clamp(14px, 1.6vw, 24px);
  overflow-x: auto;
  overflow-y: visible;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  /* one card width, shared by the track and the gutters below */
  --reel-card: clamp(260px, 78vw, 420px);
  /* room for the focused card to scale up without being clipped */
  padding-block: 10px 22px;
  /* No gutters. The rail keeps real cards on both sides of the focused one by
     rotating them round, so half a screen of empty padding is never needed —
     and that padding was what left the left half of the reel blank. */
  padding-inline: 0;
}
.work-grid.is-reel::-webkit-scrollbar { display: none; }

.work-grid.is-reel .case {
  flex: 0 0 var(--reel-card);
  scroll-snap-align: center;
  transform-origin: 50% 50%;
}

/* the centre beat: the card in the middle of the rail is the subject,
   everything else steps back. Transform and opacity only. */
/* Cards are full strength by default and only step back once JS has actually
   identified a focused card (.has-focus is set from the first observer
   callback). If IntersectionObserver never fires, every card stays legible
   instead of the whole reel sitting dimmed at 58%. */
@media (prefers-reduced-motion: no-preference) {
  .work-grid.is-reel .case {
    transition: transform .45s var(--ease-out), opacity .45s var(--ease-out);
  }
  .work-grid.is-reel.has-focus .case:not(.is-focus) {
    opacity: .58;
    transform: scale(.94);
  }
}
/* With reduced motion the rail is just a scrollable strip — every card
   stays at full size and full opacity. */
@media (prefers-reduced-motion: reduce) {
  .work-grid.is-reel { scroll-behavior: auto; }
}

/* ---- rail controls ---- */
.reel-bar {
  display: none;
  align-items: center;
  gap: var(--s2);
  margin-top: var(--s3);
}
.is-reel-mode .reel-bar { display: flex; }

.reel-btn {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--muted);
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  transition: color .2s var(--ease-out), border-color .2s var(--ease-out), background-color .2s var(--ease-out);
}
.reel-btn:hover { color: var(--text); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.reel-btn svg { width: 16px; height: 16px; }

.reel-dots {
  display: flex;
  gap: 6px;
  margin-inline: var(--s2) auto;
  padding: 0;
  list-style: none;
}
.reel-dots button {
  width: 22px; height: 22px;
  display: grid;
  place-items: center;
}
.reel-dots button::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--line-strong);
  transition: background-color .25s var(--ease-out), width .25s var(--ease-out);
}
.reel-dots button[aria-current="true"]::before { background: var(--accent); width: 18px; border-radius: 99px; }

.reel-play {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 99px;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: color .2s var(--ease-out), border-color .2s var(--ease-out);
}
.reel-play:hover { color: var(--text); border-color: var(--line-strong); }
.reel-play svg { width: 13px; height: 13px; }

/* ---- Reel / Grid switch, sitting with the filters ---- */
.view-switch {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  flex: none;
}
.view-switch button {
  min-height: 38px;
  padding: 0 14px;
  border-radius: 99px;
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: color .2s var(--ease-out), background-color .2s var(--ease-out);
}
.view-switch button:hover { color: var(--text); }
.view-switch button[aria-pressed="true"] { background: var(--accent); color: var(--on-accent); }

.filter-line {
  display: flex;
  align-items: center;
  gap: var(--s3);
  flex-wrap: wrap;
}
.filter-line .filter-row { flex: 1; min-width: 0; }

@media (prefers-color-scheme: light) {
  .view-switch button[aria-pressed="true"] { background: var(--accent-ink); color: #fff; }
  .reel-dots button[aria-current="true"]::before { background: var(--accent-ink); }
}

/* a reel of one has nothing to advance through */
/* Too few cards to fill the rail, so there is nothing to rotate — centre them
   instead of leaving them jammed against the left edge. */
.work-grid.is-reel.is-single,
.work-grid.is-reel.is-short { justify-content: center; }

@media (max-width: 640px) {
  .view-switch { width: 100%; justify-content: center; }
  .view-switch button { flex: 1; }
}
