/* ==========================================================================
   Shared controls
   --------------------------------------------------------------------------
   Everything here is static glass (no backdrop-filter) or etched: real blur
   belongs to floating chrome only. Materials come from the --mat-* bundles
   and rims in tokens.css; labels on accent surfaces read --on-accent or
   --on-select, whose per palette values are measured there.
   ========================================================================== */

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 20px;
  border: 0;
  border-radius: var(--r-control);
  font: 700 var(--step-0s)/1.2 var(--font);
  letter-spacing: 0;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  background: var(--mat-etched);
  box-shadow: var(--rim-etched);
  transition: background var(--dur-chip) linear, box-shadow var(--dur-chip) linear, color var(--dur-chip) linear,
              transform var(--dur-release) var(--ease-out-back);
}
.btn svg { flex: none; width: 18px; height: 18px; }
.btn:hover { background: var(--mat-etched-hover); box-shadow: inset 0 0 0 1px var(--etch-line-hover); }

/* Accent glass, one per view. */
.btn-primary { color: var(--on-accent); text-shadow: var(--on-accent-shadow); background: var(--mat-accent); box-shadow: var(--glass-rim); }
.btn-primary:hover { background: var(--mat-accent-hover); box-shadow: var(--glass-rim), var(--shadow-select); }

/* Etched, same as the base; kept so a variant class always wins a tie. */
.btn-secondary { background: var(--mat-etched); box-shadow: var(--rim-etched); color: var(--text); }

.btn-ghost { background: transparent; box-shadow: none; color: var(--text-soft); }
.btn-ghost:hover { background: var(--mat-etched); box-shadow: none; color: var(--text); }

/* A fixed fill: a white label measures 5.9:1 on it in every palette. */
.btn-danger { background: linear-gradient(var(--danger-fill), var(--danger-fill)); box-shadow: inset 0 1px 0 rgb(255 255 255 / .18); color: #fff; }
/* Restates the edge, or .btn:hover's etched ring would replace it. */
.btn-danger:hover {
  background: linear-gradient(rgb(0 0 0 / .10), rgb(0 0 0 / .10)), linear-gradient(var(--danger-fill), var(--danger-fill));
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .18);
}

.btn-sm { min-height: 36px; padding: 0 14px; font-size: var(--step--1); gap: 6px; }
.btn-sm svg { width: 16px; height: 16px; }
.btn-lg { min-height: 52px; padding: 0 24px; font-size: 1rem; }
.btn-block { display: flex; width: 100%; }
/* The creator panel's compact size (admin.css sets its padding and type). */
.btn-xs { min-height: 28px; }

@media (prefers-reduced-motion: no-preference) {
  .btn:active { transform: scale(.98); transition-duration: var(--dur-press); transition-timing-function: var(--ease-decel); }
}

/* After every variant and its hover, so a disabled button never lights up. */
.btn:disabled,
.btn[aria-disabled='true'] {
  cursor: default;
  color: rgb(var(--ink) / .45);
  text-shadow: none;
  background: var(--mat-etched);
  box-shadow: var(--rim-etched);
  transform: none;
}
.btn-primary:disabled,
.btn-primary[aria-disabled='true'] { background: var(--mat-neutral); color: rgb(var(--ink) / .55); text-shadow: none; box-shadow: var(--glass-rim); }

/* Submitting (site.js adds .is-busy): the label goes transparent so the
   button keeps its size, and a ring turns where it was. */
.btn.is-busy { position: relative; color: transparent; text-shadow: none; pointer-events: none; }
.btn.is-busy::after {
  content: '';
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid rgb(255 255 255 / .35);
  border-top-color: #fff;
}
/* White would vanish on an etched button in light; the ring takes the label ink. */
.btn:not(.btn-primary, .btn-danger).is-busy::after {
  border-color: color-mix(in srgb, var(--text) 30%, transparent);
  border-top-color: var(--text);
}
:root[data-theme='light'] .btn-primary.is-busy::after {
  border-color: color-mix(in srgb, var(--on-accent) 35%, transparent);
  border-top-color: var(--on-accent);
}
@media (prefers-reduced-motion: no-preference) {
  .btn.is-busy::after { animation: spin 800ms linear infinite; }
}
@keyframes spin { to { transform: rotate(360deg); } }

/* The copied state of a [data-copy] button (site.js): label and colour only. */
.btn.is-copied,
.btn.is-copied:hover { color: var(--status-safe-ink); }
.copy-tick { flex: none; width: 12px; height: 12px; }
/* Drawn from the offset, so without motion the tick simply shows. */
.copy-tick path { stroke-dasharray: 20; }
@media (prefers-reduced-motion: no-preference) {
  .copy-tick path { animation: copy-tick-draw var(--dur-marker) var(--ease-decel) both; }
}
@keyframes copy-tick-draw { from { stroke-dashoffset: 20; } }

/* ==========================================================================
   Link actions
   ========================================================================== */

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 600 var(--step-0s)/1.3 var(--font);
  color: var(--text);
  text-decoration: none;
  transition: color var(--dur-chip) linear;
}
.text-link svg { flex: none; width: 16px; height: 16px; }
.text-link:hover { color: var(--link); }

.card-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 600 var(--step--1)/1.3 var(--font);
  color: var(--link);
  text-decoration: none;
}
.card-link svg { flex: none; width: 14px; height: 14px; }
.card-link:hover { text-decoration: underline; text-underline-offset: 3px; }

@media (prefers-reduced-motion: no-preference) {
  .text-link svg,
  .card-link svg { transition: transform var(--dur-chip) var(--ease-decel); }
  .text-link:hover svg,
  .card-link:hover svg { transform: translateX(3px); }
}

.hero-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 12px 24px; margin-top: 32px; }
.hero-actions .btn-lg { min-width: 200px; }

/* ==========================================================================
   Chips and pills
   ========================================================================== */

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  padding: 8px 14px;
  border: 0;
  border-radius: var(--r-chip);
  font: 600 var(--step-chip)/1.2 var(--font);
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  background: var(--mat-neutral);
  box-shadow: var(--glass-rim);
  transition: background var(--dur-chip) linear, color var(--dur-chip) linear, box-shadow var(--dur-chip) linear;
}
button.tag { cursor: pointer; }
a.tag:hover,
button.tag:hover { background: var(--mat-neutral-hover); color: var(--text); }
.tag.is-active,
.tag[aria-current='page'],
.tag[aria-pressed='true'] { background: var(--mat-accent); color: var(--on-accent); text-shadow: var(--on-accent-shadow); font-weight: 700; }
/* Colour restated: a:hover above outranks the active label otherwise. */
.tag:is(.is-active, [aria-current='page'], [aria-pressed='true']):hover { background: var(--mat-accent-hover); color: var(--on-accent); }
.tag:disabled,
.tag[aria-disabled='true'] { opacity: .4; pointer-events: none; }
.tag svg { flex: none; width: 14px; height: 14px; }
.tag-row { display: flex; flex-wrap: wrap; gap: 8px; }
.tag-row.is-scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  margin-inline: calc(-1 * var(--gutter-page));
  padding-inline: var(--gutter-page);
}
.tag-row.is-scroll::-webkit-scrollbar { display: none; }

/* On glass a chip is etched (no glass in glass), and its selected state is
   the quiet thumb: the accent moment belongs to the page, not the card.
   --ink-2 on an etched fill over glass measured 4.09:1 (mint, dark), so
   etched labels take --text-soft (the app's 86% etched ink). */
:is(.post-card, .source-card, .group, .card, .appearance-panel) .tag,
.post-meta-tags .tag,
.tag-sm {
  min-height: 26px;
  padding: 4px 10px;
  font-size: var(--step--1);
  background: var(--mat-etched);
  box-shadow: var(--rim-etched);
  color: var(--text-soft);
}
:is(.post-card, .source-card, .group, .card, .appearance-panel) :is(a, button).tag:hover,
.post-meta-tags :is(a, button).tag:hover,
:is(a, button).tag-sm:hover { background: var(--mat-etched-hover); box-shadow: inset 0 0 0 1px var(--etch-line-hover); color: var(--text); }
:is(.post-card, .source-card, .group, .card, .appearance-panel) .tag:is(.is-active, [aria-current='page'], [aria-pressed='true']),
:is(.post-card, .source-card, .group, .card, .appearance-panel) .tag:is(.is-active, [aria-current='page'], [aria-pressed='true']):hover,
.tag-sm:is(.is-active, [aria-current='page'], [aria-pressed='true']),
.tag-sm:is(.is-active, [aria-current='page'], [aria-pressed='true']):hover {
  background: var(--mat-quiet);
  box-shadow: var(--rim-quiet);
  color: var(--text);
  text-shadow: none;
  font-weight: 700;
}

/* Information, never interactive. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  font: 600 var(--step--2)/1.5 var(--font);
  color: var(--ink-2);
  white-space: nowrap;
  background: var(--mat-etched);
  box-shadow: var(--rim-etched);
}
.pill-version { font-family: var(--mono); font-weight: 500; letter-spacing: 0; }
/* The same etched ink rule as chips: --ink-2 fell to 3.70:1 inside glass. */
:is(.card, .group, .panel, .post-card, .source-card, .auth-card, .appearance-panel) .pill:not(.pill-pending, .pill-verified) { color: var(--text-soft); }
/* The raw status inks on an etched fill measured 4.04:1 (safe, light, void)
   and 3.92:1 (safe, dark, mint, inside a group); a quarter of --text clears
   both. */
.pill-pending { color: color-mix(in srgb, var(--status-caution-ink) 75%, var(--text)); }
.pill-verified { color: color-mix(in srgb, var(--status-safe-ink) 75%, var(--text)); }
.pill-pending::before,
.pill-verified::before {
  content: '';
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--dot);
  box-shadow: 0 0 6px var(--dot);
}
.pill-pending { --dot: var(--status-caution); }
.pill-verified { --dot: var(--status-safe); }
/* On a featured card's 26% wash the status inks fall under 3:1 (mint), so
   the label goes plain and the dot alone carries the status. */
:is(.card.is-featured, .post-card.post-featured) .pill { color: var(--text); }

/* ==========================================================================
   Segmented control
   ========================================================================== */

.period-tabs {
  display: inline-flex;
  gap: 0;
  padding: 3px;
  border-radius: var(--r-control);
  background: var(--mat-neutral);
  box-shadow: var(--glass-rim);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}
.period-tabs::-webkit-scrollbar { display: none; }
.period-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 32px;
  padding: 6px 14px;
  border: 0;
  border-radius: var(--r-chip);
  background: transparent;
  font: 600 var(--step-chip)/1.2 var(--font);
  letter-spacing: .1px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-chip) linear;
}
/* Idle labels on an etched track take the etched ink (--ink-2 there
   measured 4.03:1, mint, dark); :where() keeps this under hover and
   selection. */
:where(.auth-card, .appearance-panel, .panel, .identifier-mode-tabs, .theme-segmented) .period-tab { color: var(--text-soft); }
button.period-tab { cursor: pointer; }
.period-tab:hover { color: var(--text); }
.period-tab.is-active,
.period-tab[aria-current='page'],
.period-tab[aria-checked='true'],
.period-tab[aria-pressed='true'] {
  background: var(--mat-select);
  color: var(--on-select);
  text-shadow: var(--on-select-shadow);
  font-weight: 700;
  box-shadow: inset 0 0 0 .5px rgb(255 255 255 / .22), var(--shadow-select);
}
/* Secondary filters on a view that already has its accent moment. */
.period-tabs.is-quiet .period-tab:is(.is-active, [aria-current='page'], [aria-checked='true'], [aria-pressed='true']) {
  background: var(--mat-quiet);
  color: var(--text);
  text-shadow: none;
  box-shadow: var(--rim-quiet);
}
/* Inside glass the track is etched. */
:is(.auth-card, .appearance-panel, .panel) .period-tabs,
.identifier-mode-tabs,
.theme-segmented { background: var(--mat-etched); box-shadow: var(--rim-etched); }
/* The track scrolls sideways on phones, so the ring goes inside. */
.period-tab:focus-visible { outline-offset: -2px; }
.period-tab:disabled,
.period-tab[aria-disabled='true'] { opacity: .4; pointer-events: none; }
/* A travelling ::before thumb paints these, so the segment only changes its
   label colour and weight. */
.identifier-mode-tabs .period-tab.is-active,
.identifier-mode-tabs .period-tab[aria-pressed='true'],
.theme-segmented [aria-checked='true'] { background: transparent; box-shadow: none; text-shadow: none; color: var(--text); font-weight: 700; }

/* Link-driven segments: the thumb travels as a named view-transition group
   (each owner names its active segment). */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-group(segment-category),
  ::view-transition-group(segment-period),
  ::view-transition-group(active-filter) {
    animation-duration: var(--dur-segment);
    animation-timing-function: var(--ease-out-cubic);
  }
}

/* ==========================================================================
   Cards
   ========================================================================== */

/* Paragraph rules skip labels through :where(), so a p.card-label or
   p.eyebrow keeps its own type without the paragraph rule gaining weight. */

.card {
  position: relative;
  display: block;
  border-radius: var(--r-card);
  padding: 20px;
  background: var(--mat-neutral);
  box-shadow: var(--glass-rim);
  color: var(--text);
  text-decoration: none;
}
@media (min-width: 760px) {
  .card { padding: 24px; }
}
.card h3 { margin: 0 0 6px; font: 700 1.0625rem/1.3 var(--font); letter-spacing: -0.01em; color: var(--text); }
.card p:where(:not(.card-label, .eyebrow)) { margin: 0; font: 400 var(--step-0s)/1.55 var(--font); color: var(--ink-2); }
a.card { transition: background var(--dur-chip) linear, transform var(--dur-release) var(--ease-out-back); }
a.card:hover { background: var(--mat-neutral-hover); }
/* --ink-2 on the 16% hover wash measured 4.28:1 (mint, dark). */
a.card:hover p:where(:not(.card-label, .eyebrow)) { color: var(--ink-2-strong); }
@media (prefers-reduced-motion: no-preference) {
  a.card:active { transform: scale(.99); transition-duration: var(--dur-press); }
}
/* Featured: one per view. Secondary text on the 26% wash needs the
   stronger ink. */
.card.is-featured,
.post-card.post-featured { background: var(--mat-card); }
.card.is-featured p:where(:not(.card-label, .eyebrow)),
.post-card.post-featured p:where(:not(.card-label, .eyebrow)),
.post-card.post-featured .post-meta,
:is(.card.is-featured, .post-card.post-featured) :is(.card-label, .eyebrow) { color: var(--ink-2-strong); }
.post-list { display: flex; flex-direction: column; gap: 10px; }

/* ==========================================================================
   Frosted groups with rows
   ========================================================================== */

.group { border-radius: var(--r-group); background: var(--mat-neutral); box-shadow: var(--glass-rim); overflow: clip; }
.group-row {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
  min-height: 52px;
  padding: 13px 16px;
  color: var(--text);
  text-decoration: none;
}
.group-row + .group-row::before { content: ''; position: absolute; top: 0; right: 0; left: 16px; height: 1px; background: var(--hairline); }
/* Under the text, past the 30px mark: 16 + 30 + 13. */
.group-row:has(> .icon-mark) + .group-row::before,
.group.has-marks .group-row + .group-row::before { left: 59px; }
.group-row-body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.group-row-title { margin: 0; font: 500 var(--step-0s)/1.3 var(--font); letter-spacing: -0.01em; color: var(--text); }
.group-row-sub { margin: 0; font: 400 var(--step--1)/1.45 var(--font); color: var(--ink-2); }
.group-row-trail { flex: none; display: inline-flex; align-items: center; gap: 8px; font: 600 var(--step--1)/1.3 var(--font); color: var(--ink-2); }
.group-row-trail .chev { width: 18px; height: 18px; color: rgb(var(--ink) / .5); }
a.group-row { transition: background var(--dur-chip) linear; }
a.group-row:hover { background: var(--row-hover); }
/* --ink-2 under the hover overlay measured 4.30:1 (mint, dark). */
a.group-row:hover .group-row-sub { color: var(--ink-2-strong); }
a.group-row:active { background: var(--row-press); }
/* The group clips its overflow, so the ring goes inside. */
a.group-row:focus-visible { outline-offset: -2px; }
.group-row.is-active,
.group-row[aria-current='page'] { background: var(--mat-row-selected); }
/* The 30% wash stacks on the group's own 10%: --ink-2-strong measured
   4.17:1 there (mint, dark), so the whole selected row reads in --text. */
.group-row:is(.is-active, [aria-current='page']) :is(.group-row-sub, .group-row-trail) { color: var(--text); }
a.group-row:is(.is-active, [aria-current='page']):hover { background: linear-gradient(var(--row-hover), var(--row-hover)), var(--mat-row-selected); }
.group-label { margin: 0 0 10px 4px; }
.group + .group-label,
.group + .group { margin-top: 22px; }

/* Label and value rows inside a panel: hairlines only, the panel is the glass. */
.definition-list { display: grid; margin: 0; }
.definition-list > div {
  display: grid;
  grid-template-columns: minmax(110px, 34%) 1fr;
  gap: 4px 16px;
  align-items: baseline;
  padding: 12px 0;
}
.definition-list > div + div { box-shadow: inset 0 1px 0 var(--hairline); }
.definition-list dt { margin: 0; font: 700 .6875rem/1.4 var(--font); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-2); }
.definition-list dd { margin: 0; min-width: 0; overflow-wrap: anywhere; font: 500 var(--step-0s)/1.4 var(--font); color: var(--text); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Eyebrows and section heads
   ========================================================================== */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font: 700 var(--step--2)/1.4 var(--font);
  letter-spacing: var(--track-caps);
  text-transform: uppercase;
  color: var(--eyebrow-ink);
}
.eyebrow-index { display: none; }
.card-label {
  display: block;
  margin: 0 0 14px;
  font: 700 .6875rem/1.4 var(--font);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-2);
}
/* --eyebrow-ink is measured on the ground; on glass an eyebrow becomes the
   card label. */
:is(.card, .group, .panel, .post-card, .source-card, .auth-card, .appearance-panel) .eyebrow { color: var(--ink-2); font-size: .6875rem; letter-spacing: var(--track-label); }

.section-head { max-width: 640px; margin: 0 0 clamp(28px, 4vw, 40px); }
.section-head.center { margin-inline: auto; text-align: center; }
.section-head .eyebrow { display: flex; margin-bottom: 12px; }
.section-head.center .eyebrow { justify-content: center; }
.section-head h1 { margin: 0; font: 700 var(--step-3)/1.08 var(--font); letter-spacing: var(--track-h1); color: var(--text); }
.section-head h2 { margin: 0; font: 700 var(--step-2)/1.15 var(--font); letter-spacing: var(--track-h2); color: var(--text); }
.section-head p:where(:not(.eyebrow)) { margin: 14px 0 0; font: 400 var(--step-0l)/1.55 var(--font); color: var(--text-soft); max-width: 58ch; }
.section-head.center p:where(:not(.eyebrow)) { margin-inline: auto; }
.section-head-compact { margin-bottom: 18px; }
.section-head-compact h2 { font-size: var(--step-1); letter-spacing: var(--track-title); }
/* Privacy and terms put the docs meta row under a left-aligned head. */
.section-head .doc-meta { justify-content: flex-start; margin: 16px 0 0; }
.subhead h3 { margin: 0; font: 700 var(--step-1)/1.25 var(--font); }
.subhead p:where(:not(.eyebrow)) { margin: 8px 0 0; color: var(--ink-2); }
.glass-highlight { display: inline; padding: 0; border: 0; background: none; box-shadow: none; font-weight: 600; color: var(--text); }

/* ==========================================================================
   Icon mark: the app's 30px keycap
   ========================================================================== */

.icon-mark,
.card-icon,
.post-icon {
  --mark-c: var(--tint);
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 1px solid transparent;
  border-radius: var(--r-icon);
  background:
    radial-gradient(95% 95% at 50% 62.5%, color-mix(in srgb, var(--mark-c) 26%, transparent), rgb(0 0 0 / .32)) padding-box,
    linear-gradient(rgb(0 0 0 / .55), rgb(255 255 255 / .16)) border-box;
  color: color-mix(in srgb, var(--mark-c) 58%, white);
}
.icon-mark svg,
.card-icon svg,
.post-icon svg { width: 16px; height: 16px; stroke-width: 2; filter: drop-shadow(0 0 4px rgb(255 255 255 / .30)); }
.icon-mark--lg,
.card-icon,
.post-header .post-icon,
.doc-mark { width: 44px; height: 44px; border-radius: var(--r-icon-lg); }
.icon-mark--lg svg,
.card-icon svg,
.post-header .post-icon svg,
.doc-mark svg { width: 22px; height: 22px; }
/* The 30px ladder step scaled to 24px. */
.icon-mark--sm { width: 24px; height: 24px; border-radius: 8px; }
.icon-mark--sm svg { width: 14px; height: 14px; }
:root[data-theme='light'] :is(.icon-mark, .card-icon, .post-icon) {
  background:
    radial-gradient(95% 95% at 50% 62.5%, color-mix(in srgb, var(--mark-c) 16%, transparent), color-mix(in srgb, var(--mark-c) 4%, transparent)) padding-box,
    linear-gradient(rgb(0 0 0 / .16), rgb(255 255 255 / .9)) border-box;
  /* The rim gradient shows through the translucent fill, darkest at the top:
     a 78% glyph measured 2.90:1 there (mono); 64% measures 4.0:1 or better
     in all ten. */
  color: color-mix(in srgb, var(--mark-c) 64%, black);
}
:root[data-theme='light'] :is(.icon-mark, .card-icon, .post-icon) svg { filter: none; }

/* ==========================================================================
   Swatches
   ========================================================================== */

.swatch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgb(var(--ink) / .18);
  cursor: pointer;
  outline: 1.5px solid transparent;
  outline-offset: 4px;
  transition: outline-color var(--dur-chip) linear, transform var(--dur-release) var(--ease-out-back);
}
/* The name stays for assistive tech. */
.swatch > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* The account picker's radio stays the real control, invisible over the
   swatch. */
.swatch > input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
@media (prefers-reduced-motion: no-preference) {
  .swatch:hover { transform: scale(1.06); }
  .swatch:active { transform: scale(.94); }
}
.swatch[aria-pressed='true'],
.accent-swatch:has(input:checked) { outline-color: var(--text); }
/* The halo keeps the check at 3:1 over the light end of mono, reverse and
   mint. */
.swatch[aria-pressed='true']::after,
.accent-swatch:has(input:checked)::after {
  content: '';
  position: absolute;
  inset: 0;
  margin: auto;
  width: 17px;
  height: 17px;
  background: #fff;
  pointer-events: none;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
  filter: drop-shadow(0 0 2px rgb(0 0 0 / .55));
}
.swatch:focus-visible,
.accent-swatch:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 4px; }
/* The base display must not unhide the locked void swatch. */
.swatch[hidden] { display: none; }
.swatches { display: grid; grid-template-columns: repeat(5, 40px); gap: 14px 16px; }
/* The fill is the choice itself, so forced colours must not blank it. */
@media (forced-colors: active) {
  .swatch { forced-color-adjust: none; }
}

/* ==========================================================================
   Empty state
   ========================================================================== */

.empty-state { display: grid; justify-items: center; gap: 10px; padding: 48px 24px; text-align: center; }
/* A circle, not the app's square tile. */
.empty-state .icon-mark { width: 52px; height: 52px; border-radius: 50%; }
.empty-state .icon-mark svg { width: 24px; height: 24px; }
.empty-state h2,
.empty-state h3 { margin: 6px 0 0; font: 700 1.125rem/1.3 var(--font); color: var(--text); }
.empty-state p:where(:not(.empty-state-links, .eyebrow)) { margin: 0; max-width: 44ch; font: 400 var(--step-0s)/1.55 var(--font); color: var(--ink-2); }
.empty-state-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 20px; margin: 8px 0 0; }

/* ==========================================================================
   Utilities
   ========================================================================== */

.pagination { display: flex; align-items: center; gap: 14px; margin-top: 24px; }
.text-muted { color: var(--ink-2); }

@media (max-width: 559.98px) {
  .hero-actions .btn { width: 100%; max-width: 320px; }
}
