/* Design Studio: the studio's own pages, on the Hybridge design system.

   Calm and quiet: ink on white surfaces over a porcelain canvas, the kit's face, titles in
   the kit's heading blue, glass for the navigation layer only, colour only for outcomes.
   Light by default, dark by choice: a dark set derived from the kit, chosen with the bar's
   toggle or by the system setting. The posts the studio makes are styled by the renderer,
   never by this file.

   Sections: tokens, base, shell, components, pages, then the editor's functional rules. */

/* ------------------------------------------------------------------------ tokens */

/* The chrome's colours and face, as the Hybridge kit gives them. base.html writes the
   active kit's values on :root, which outranks html, so another kit tints the tool.
   --kit-heading keeps the kit's heading colour for the dark set to lighten. */
html {
  --heading: #0f4b7b;
  --kit-heading: #0f4b7b;
  --ink: #18181b;
  --ink-soft: #52525b;
  --ink-faint: #a1a1aa;
  --ink-line: #e4e4e7;
  --ink-wash: #f4f4f5;
  --canvas: #f3f4f7;
  --white: #ffffff;
  --font-kit: "Inter";
}

:root {
  /* Outcomes only, and never from a kit: done, warning, danger, live. Text on a tint is
     darker, so it passes contrast. */
  --status-made: #16a34a;
  --status-noshow: #f2b200;
  --status-cancelled: #e5484d;
  --status-live: #22c55e;
  --text-success: #15803d;
  --text-warning: #8a5a00;
  --text-danger: #c22e33;

  /* Tints of the kit's colours, for hovers, rings, hairlines and insets. */
  --ink-85: color-mix(in srgb, var(--ink) 85%, transparent);
  --ink-40: color-mix(in srgb, var(--ink) 40%, transparent);
  --ink-25: color-mix(in srgb, var(--ink) 25%, transparent);
  --ink-15: color-mix(in srgb, var(--ink) 15%, transparent);
  --ink-10: color-mix(in srgb, var(--ink) 10%, transparent);
  --ink-5: color-mix(in srgb, var(--ink) 5%, transparent);
  --line-80: color-mix(in srgb, var(--ink-line) 80%, transparent);
  --line-70: color-mix(in srgb, var(--ink-line) 70%, transparent);
  --wash-60: color-mix(in srgb, var(--ink-wash) 60%, transparent);
  --wash-40: color-mix(in srgb, var(--ink-wash) 40%, transparent);

  /* Words on an ink fill: a primary button, a pressed choice, the chosen filter. */
  --on-ink: var(--white);

  --font-sans: var(--font-kit), ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --ease-glass: cubic-bezier(0.32, 0.72, 0, 1);
  --shadow-soft: 0 1px 2px rgba(24, 24, 27, 0.04);
  --shadow-hover: 0 1px 2px rgba(24, 24, 27, 0.04), 0 8px 20px -12px rgba(24, 24, 27, 0.22);
  --shadow-lift: 0 0 0 1px rgba(24, 24, 27, 0.05), 0 2px 4px rgba(24, 24, 27, 0.04),
    0 16px 36px -16px rgba(24, 24, 27, 0.3);
  --shadow-pill: 0 0 0 0.5px rgba(24, 24, 27, 0.06), 0 1px 2px rgba(24, 24, 27, 0.06),
    0 6px 16px -8px rgba(24, 24, 27, 0.22), inset 0 1px 0 rgba(255, 255, 255, 1);

  /* The canvas's three washes of light, and the glass: its layer, the same layer where blur
     is missing, its border, its ring, its bright inner top edge, a hover on it, and the pill
     that lifts the current item (on the glass and on a segmented track). */
  --canvas-wash-1: rgba(205, 220, 255, 0.55);
  --canvas-wash-2: rgba(230, 222, 255, 0.5);
  --canvas-wash-3: rgba(208, 238, 243, 0.5);
  --glass-fill: rgba(255, 255, 255, 0.6);
  --glass-fill-solid: rgba(255, 255, 255, 0.94);
  --glass-edge: rgba(255, 255, 255, 0.7);
  --glass-ring: rgba(24, 24, 27, 0.07);
  --glass-sheen: rgba(255, 255, 255, 0.9);
  --glass-hover: rgba(255, 255, 255, 0.45);
  --pill-fill: rgba(255, 255, 255, 0.92);

  /* A select's chevron, in ink-soft. */
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2352525b' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 8 4 4 4-4'/%3E%3C/svg%3E");

  /* The frame: the page is this wide at most, and the bar lines up with its content. */
  --page-max: 75rem;
}

/* The dark set: chosen with the toggle (data-theme), or the system setting when nothing is
   chosen. Both selectors outrank the kit's :root block, which keeps writing the light
   values; the heading is the kit's own colour lightened, so another kit keeps its hue. The
   status colours stay; the text tints lighten so they read on a dark surface. The two blocks
   must stay the same. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --canvas: #121316;
  --white: #1b1d21;
  --ink: #f4f4f5;
  --ink-soft: #b4b4bb;
  --ink-faint: #7a7a83;
  --ink-line: #2a2d33;
  --ink-wash: #24272c;
  --heading: color-mix(in srgb, var(--kit-heading) 50%, white);
  --text-success: #5bd38a;
  --text-warning: #e6c25a;
  --text-danger: #f0787c;
  --text-info: #8fb4f5;
  --on-ink: var(--canvas);
  --shadow-pill: 0 0 0 0.5px rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.3),
    0 6px 16px -8px rgba(0, 0, 0, 0.5);
  --canvas-wash-1: color-mix(in srgb, var(--heading) 9%, transparent);
  --canvas-wash-2: color-mix(in srgb, var(--heading) 6%, transparent);
  --canvas-wash-3: color-mix(in srgb, var(--heading) 6%, transparent);
  --glass-fill: rgba(24, 24, 27, 0.62);
  --glass-fill-solid: rgba(24, 24, 27, 0.94);
  --glass-edge: rgba(255, 255, 255, 0.08);
  --glass-ring: rgba(255, 255, 255, 0.06);
  --glass-sheen: transparent;
  --glass-hover: rgba(255, 255, 255, 0.06);
  --pill-fill: rgba(52, 55, 62, 0.92);
  --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23b4b4bb' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 8 4 4 4-4'/%3E%3C/svg%3E");
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --canvas: #121316;
    --white: #1b1d21;
    --ink: #f4f4f5;
    --ink-soft: #b4b4bb;
    --ink-faint: #7a7a83;
    --ink-line: #2a2d33;
    --ink-wash: #24272c;
    --heading: color-mix(in srgb, var(--kit-heading) 50%, white);
    --text-success: #5bd38a;
    --text-warning: #e6c25a;
    --text-danger: #f0787c;
    --text-info: #8fb4f5;
    --on-ink: var(--canvas);
    --shadow-pill: 0 0 0 0.5px rgba(255, 255, 255, 0.06), 0 1px 2px rgba(0, 0, 0, 0.3),
      0 6px 16px -8px rgba(0, 0, 0, 0.5);
    --canvas-wash-1: color-mix(in srgb, var(--heading) 9%, transparent);
    --canvas-wash-2: color-mix(in srgb, var(--heading) 6%, transparent);
    --canvas-wash-3: color-mix(in srgb, var(--heading) 6%, transparent);
    --glass-fill: rgba(24, 24, 27, 0.62);
    --glass-fill-solid: rgba(24, 24, 27, 0.94);
    --glass-edge: rgba(255, 255, 255, 0.08);
    --glass-ring: rgba(255, 255, 255, 0.06);
    --glass-sheen: transparent;
    --glass-hover: rgba(255, 255, 255, 0.06);
    --pill-fill: rgba(52, 55, 62, 0.92);
    --chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23b4b4bb' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 8 4 4 4-4'/%3E%3C/svg%3E");
  }
}

/* -------------------------------------------------------------------------- base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The face's optical size follows the font size on its own; a font-variation-settings
   would turn that off, so none is ever set. An in-page jump lands clear of the sticky bar. */
html {
  font-optical-sizing: auto;
  scroll-padding-top: 84px;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--canvas);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1,
h2,
h3,
p,
figure,
dl,
dd {
  margin: 0;
}

/* The scripts show and hide parts with the hidden attribute; no class may undo it. */
[hidden] {
  display: none !important;
}

/* Links are ink with an underline, never blue. */
a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--ink-25);
  text-underline-offset: 2px;
  transition: text-decoration-color 150ms var(--ease-glass);
}

a:hover {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 2px solid var(--ink-40);
  outline-offset: 2px;
}

img {
  max-width: 100%;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* One face for everything: a path or a code is the face with tabular figures. */
code {
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--ink-wash);
  font-family: inherit;
  font-size: 0.92em;
  font-variant-numeric: tabular-nums slashed-zero;
}

.tabular,
time {
  font-variant-numeric: tabular-nums;
}

.icon {
  display: block;
  flex: none;
}

/* ------------------------------------------------------------------------- shell */

/* The canvas the glass floats over: the porcelain with three faint washes of light (of the
   heading's tint in dark), on its own fixed layer so scrolling never repaints it. */
.app-canvas {
  background-color: var(--canvas);
  isolation: isolate;
}

.app-canvas::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(64rem 38rem at 6% -12%, var(--canvas-wash-1), transparent 62%),
    radial-gradient(52rem 34rem at 102% -4%, var(--canvas-wash-2), transparent 64%),
    radial-gradient(60rem 40rem at 42% 112%, var(--canvas-wash-3), transparent 62%);
}

/* Glass, for the navigation layer only: the bar and the tab bar. */
.glass {
  background: var(--glass-fill);
  -webkit-backdrop-filter: blur(22px) saturate(1.8);
  backdrop-filter: blur(22px) saturate(1.8);
  border: 1px solid var(--glass-edge);
  box-shadow:
    0 0 0 0.5px var(--glass-ring),
    0 14px 34px -18px rgba(24, 24, 27, 0.28),
    inset 0 1px 0 var(--glass-sheen);
}

/* The lens on the current item: brighter than the glass, and lifted off it. */
.glass-pill {
  background: var(--pill-fill);
  box-shadow: var(--shadow-pill);
}

/* No blur available: a denser layer, so text over it still reads. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass {
    background: var(--glass-fill-solid);
  }
}

/* The system's "reduce transparency" makes the glass solid. */
@media (prefers-reduced-transparency: reduce) {
  .glass {
    background: var(--white);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* The bar floats 12px from the top in a fixed 72px slot, so the page never jumps when it
   condenses; its glass is a layer behind its contents. */
.bar-slot {
  position: sticky;
  top: 0;
  z-index: 40;
  height: 72px;
  padding: 12px max(12px, env(safe-area-inset-right)) 0 max(12px, env(safe-area-inset-left));
  pointer-events: none;
}

.bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: calc(var(--page-max) - 24px);
  height: 60px;
  margin: 0 auto;
  padding: 0 8px 0 12px;
  border-radius: 22px;
  pointer-events: auto;
  transition: height 300ms var(--ease-glass);
}

.bar.is-condensed {
  height: 52px;
}

.bar-glass {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

.bar > :not(.bar-glass) {
  position: relative;
}

.bar-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  color: var(--ink);
  text-decoration: none;
  transform-origin: left center;
  transition: transform 300ms var(--ease-glass);
}

.bar.is-condensed .bar-brand {
  transform: scale(0.9);
}

.bar-logo {
  display: block;
  width: auto;
  height: 32px;
}

/* One lockup per theme: the kit's own on light, its dark-background version on dark. */
.bar-logo-dark {
  display: none;
}

:root[data-theme="dark"] .bar-logo-light {
  display: none;
}

:root[data-theme="dark"] .bar-logo-dark {
  display: block;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .bar-logo-light {
    display: none;
  }

  :root:not([data-theme="light"]) .bar-logo-dark {
    display: block;
  }
}

.bar-rule {
  flex: none;
  width: 1px;
  height: 24px;
  background: var(--ink-10);
}

.bar-name,
.bar-page {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  white-space: nowrap;
}

/* The phone's bar names the page instead; the h1 says it for a screen reader. */
.bar-page {
  display: none;
}

.bar-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}

.bar-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 40px;
  padding: 0 14px;
  border-radius: 9999px;
  color: var(--ink-soft);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.006em;
  text-decoration: none;
  transition:
    color 150ms var(--ease-glass),
    background-color 150ms var(--ease-glass),
    height 300ms var(--ease-glass);
}

.bar-item:not([aria-current]):hover {
  background: var(--glass-hover);
  color: var(--ink);
}

.bar-item[aria-current="page"] {
  color: var(--ink);
}

.bar.is-condensed .bar-item {
  height: 36px;
}

/* Between the phone and a wide screen, the bar's items keep their words only. */
@media (min-width: 768px) and (max-width: 1023px) {
  .bar-item .icon {
    display: none;
  }

  .bar-item {
    padding: 0 12px;
  }

  /* v6: six items leave no room for the name beside the lockup, so here it is kept for a
     screen reader only, as on a phone; it comes back from 1024px. */
  .bar-rule {
    display: none;
  }

  .bar-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

/* The theme toggle: a round ghost button at the bar's right end, after the items. v7: Sign
   out, while the passcode gate is on, is drawn the same way, after it. */
.theme-toggle,
.bar-icon-button {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 9999px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: color 150ms var(--ease-glass), background-color 150ms var(--ease-glass);
}

.theme-toggle:hover,
.bar-icon-button:hover {
  background: var(--glass-hover);
  color: var(--ink);
}

.bar-signout {
  display: flex;
  flex: none;
  margin: 0;
}

/* The phone's tab bar: glass floating 12px above the bottom, clear of the safe area. */
.tab-bar {
  display: none;
  position: fixed;
  right: max(12px, env(safe-area-inset-right));
  bottom: 12px;
  left: max(12px, env(safe-area-inset-left));
  z-index: 40;
  padding: 6px 6px max(6px, env(safe-area-inset-bottom));
  border-radius: 26px;
}

.tab-bar ul {
  display: flex;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tab-bar li {
  flex: 1;
  min-width: 0;
}

.tab-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  height: 52px;
  padding: 0 4px;
  border-radius: 20px;
  color: var(--ink-soft);
  font-size: 10.5px;
  font-weight: 500;
  line-height: 1.25;
  text-decoration: none;
  transition: color 150ms var(--ease-glass), background-color 150ms var(--ease-glass);
}

.tab-item[aria-current="page"] {
  color: var(--ink);
}

.tab-item span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 767px) {
  .bar-nav {
    display: none;
  }

  .bar-page {
    display: inline;
  }

  /* The toggle stays in the bar, at its right end beside the page's name. */
  .theme-toggle {
    margin-left: auto;
  }

  .bar-name {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .tab-bar {
    display: block;
  }
}

/* The page: 84px down (the bar's slot and 12px), 16px from the sides on a phone and 24px
   from 640px, clear of the tab bar below 768px. */
.page {
  display: flex;
  flex-direction: column;
  gap: 20px;
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 12px max(16px, env(safe-area-inset-right)) calc(100px + env(safe-area-inset-bottom))
    max(16px, env(safe-area-inset-left));
}

@media (min-width: 640px) {
  .page {
    padding-right: max(24px, env(safe-area-inset-right));
    padding-left: max(24px, env(safe-area-inset-left));
  }
}

@media (min-width: 768px) {
  .page {
    padding-bottom: 64px;
  }
}

/* The editor's canvas, preview and settings need more room; the bar widens with them. */
.is-wide {
  --page-max: 99rem;
}

/* Demo mode and a missing photo source: a neutral line under the bar, never yellow. */
.banner-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.banner {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 14px;
  border: 1px solid var(--line-80);
  border-radius: 14px;
  background: color-mix(in srgb, var(--white) 60%, transparent);
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1.45;
}

.banner::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--ink-faint);
  transform: translateY(-1px);
}

/* The page title: two tones, the title in heading blue and its tail in faint ink. */
.page-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  max-width: 48rem;
  margin: 4px 0 12px;
}

.page-title {
  font-size: 30px;
  font-weight: 500;
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--heading);
  text-wrap: balance;
}

@media (min-width: 640px) {
  .page-title {
    font-size: 36px;
  }
}

.page-title-tail {
  display: block;
  color: var(--ink-faint);
}

/* A tail drawn from typed text (a brief) keeps to two lines; the text is in full below. */
.page-title-tail.is-clamped {
  display: -webkit-box;
  overflow: hidden;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.page-lede {
  max-width: 42rem;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.page-meta {
  font-size: 13px;
  color: var(--ink-soft);
}

/* -------------------------------------------------------------------- components */

/* Surface: a section of a page, a soft white card on the canvas. */
.panel {
  min-width: 0;
  padding: 20px 24px 24px;
  border: 1px solid var(--line-80);
  border-radius: 20px;
  background: var(--white);
  box-shadow: var(--shadow-soft);
}

.panel.is-flush {
  padding: 0;
  overflow: hidden;
}

/* Section titles: ordinary words at 15px in heading blue, never tracked capitals. */
.panel > h2,
.section-title,
.group-title {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--heading);
}

.panel > h2 {
  margin-bottom: 16px;
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 24px;
  margin-bottom: 16px;
}

.section-desc {
  margin-top: 4px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* Inset: a quieter group inside a surface. */
.inset {
  padding: 16px;
  border-radius: 16px;
  background: var(--wash-60);
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.meta {
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.meta-faint {
  color: var(--ink-faint);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
}

.inline-form {
  display: inline-flex;
  margin: 0;
}

/* Buttons: round, 36px, secondary by default; one primary, in ink, per view. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 36px;
  padding: 6px 16px;
  border: 1px solid var(--ink-line);
  border-radius: 9999px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.006em;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    color 150ms var(--ease-glass),
    background-color 150ms var(--ease-glass),
    border-color 150ms var(--ease-glass),
    box-shadow 150ms var(--ease-glass);
}

.btn:hover {
  border-color: var(--ink-25);
  background: var(--wash-60);
}

.btn:focus-visible,
.btn-link:focus-visible,
.choice-btn:focus-visible,
.filter-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px var(--ink-10);
}

.btn:disabled,
.btn[aria-disabled="true"],
.btn-link:disabled {
  opacity: 0.45;
  pointer-events: none;
}

.btn-primary {
  border-color: transparent;
  background: var(--ink);
  color: var(--on-ink);
}

.btn-primary:hover {
  border-color: transparent;
  background: var(--ink-85);
}

.btn-small {
  min-height: 32px;
  padding: 5px 14px;
  font-size: 13px;
}

/* A destructive action that stays quiet until pointed at; its words in the darker danger
   text, so they pass contrast. */
.btn-danger-soft {
  border-color: transparent;
  background: transparent;
  color: var(--text-danger);
}

.btn-danger-soft:hover {
  border-color: transparent;
  background: rgba(229, 72, 77, 0.1);
}

/* An action drawn as an ink link with an underline. */
.btn-link {
  display: inline;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  text-align: left;
  text-decoration: underline;
  text-decoration-color: var(--ink-25);
  text-underline-offset: 2px;
  cursor: pointer;
  transition: text-decoration-color 150ms var(--ease-glass);
}

.btn-link:hover {
  text-decoration-color: currentColor;
}

/* Ghost icon buttons: like and dislike. Pressed is the active state, in ink. */
.choice-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 9999px;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition:
    color 150ms var(--ease-glass),
    background-color 150ms var(--ease-glass),
    box-shadow 150ms var(--ease-glass);
}

.choice-btn:hover {
  background: var(--ink-5);
  color: var(--ink);
}

.choice-btn[aria-pressed="true"] {
  background: var(--ink);
  color: var(--on-ink);
}

@media (pointer: coarse) {
  .choice-btn {
    width: 40px;
    height: 40px;
  }
}

/* Fields: labels above in sentence case, 40px fields, hints and errors 12px under. */
label {
  display: block;
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}

.field {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.field label {
  margin-bottom: 6px;
}

input[type="text"],
input[type="password"],
input[type="number"],
select,
textarea {
  width: 100%;
  min-height: 40px;
  margin: 0;
  padding: 0 14px;
  border: 1px solid var(--ink-line);
  border-radius: 12px;
  background-color: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  transition:
    border-color 150ms var(--ease-glass),
    box-shadow 150ms var(--ease-glass);
}

textarea {
  display: block;
  min-height: 88px;
  padding: 10px 14px;
  line-height: 1.5;
  resize: vertical;
}

select {
  padding-right: 36px;
  appearance: none;
  background-image: var(--chevron);
  background-position: right 12px center;
  background-repeat: no-repeat;
  background-size: 16px;
}

input[type="number"] {
  width: 6.5rem;
  font-variant-numeric: tabular-nums;
}

input::placeholder,
textarea::placeholder {
  color: var(--ink-faint);
}

input[type="text"]:hover,
input[type="password"]:hover,
input[type="number"]:hover,
select:hover,
textarea:hover {
  border-color: var(--ink-25);
}

input[type="text"]:focus,
input[type="password"]:focus,
input[type="number"]:focus,
select:focus,
textarea:focus {
  border-color: var(--ink-40);
  outline: none;
  box-shadow: 0 0 0 4px var(--ink-5);
}

input[type="text"]:disabled,
input[type="password"]:disabled,
input[type="number"]:disabled,
select:disabled,
textarea:disabled {
  cursor: not-allowed;
  border-color: var(--ink-line);
  background-color: var(--ink-wash);
  color: var(--ink-faint);
}

input[type="file"]:disabled {
  opacity: 0.45;
}

input[type="checkbox"],
input[type="radio"],
input[type="range"] {
  accent-color: var(--ink);
}

/* The browser's own file button, drawn as a small secondary button. */
input[type="file"] {
  max-width: 100%;
  color: var(--ink-soft);
  font: inherit;
  font-size: 13px;
}

input[type="file"]::file-selector-button {
  min-height: 32px;
  margin-right: 12px;
  padding: 0 14px;
  border: 1px solid var(--ink-line);
  border-radius: 9999px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 150ms var(--ease-glass), background-color 150ms var(--ease-glass);
}

input[type="file"]::file-selector-button:hover {
  border-color: var(--ink-25);
  background: var(--wash-60);
}

.field-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(12rem, 100%), 1fr));
  gap: 16px;
}

/* A small field (a number) with its label above it. */
.field-small {
  display: flex;
  flex-direction: column;
}

.hint {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.field-error {
  margin: 0;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.5;
  color: var(--text-danger);
}

/* A checkbox beside its words. */
.check-option {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 14px;
  font-weight: 400;
  color: var(--ink);
  cursor: pointer;
}

.check-option input {
  width: 16px;
  height: 16px;
  margin: 0;
}

/* Segmented control: a solid wash track, glass being the bars' alone, with the chosen
   option lifted as a pill. */
.pill-group {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.pill-group legend {
  margin: 0 0 6px;
  padding: 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}

.segmented {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  gap: 4px;
  padding: 4px;
  border-radius: 9999px;
  background: var(--ink-wash);
}

.pill-option {
  position: relative;
  display: inline-flex;
  margin: 0;
  font-weight: 500;
  cursor: pointer;
}

.pill-option input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.pill-option span {
  padding: 6px 16px;
  border-radius: 9999px;
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1.4;
  white-space: nowrap;
  transition:
    color 150ms var(--ease-glass),
    background-color 150ms var(--ease-glass),
    box-shadow 150ms var(--ease-glass);
}

.pill-option:hover span {
  color: var(--ink);
}

.pill-option input:checked + span {
  background: var(--pill-fill);
  box-shadow: var(--shadow-pill);
  color: var(--ink);
}

.pill-option input:focus-visible + span {
  box-shadow: 0 0 0 4px var(--ink-10);
}

.pill-option input:disabled + span {
  opacity: 0.45;
  cursor: not-allowed;
}

@media (max-width: 639px) {
  .segmented {
    border-radius: 20px;
  }
}

/* Filters: small pills that size to their words. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.filter-btn {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 12px;
  border: 1px solid var(--ink-line);
  border-radius: 9999px;
  background: var(--white);
  color: var(--ink-soft);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition:
    color 150ms var(--ease-glass),
    background-color 150ms var(--ease-glass),
    border-color 150ms var(--ease-glass);
}

.filter-btn:hover {
  border-color: var(--ink-25);
  color: var(--ink);
}

.filter-btn.is-active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--on-ink);
}

/* Badges: small soft pills. Neutral by default; warning where it is an outcome. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: fit-content;
  max-width: 100%;
  padding: 3px 8px;
  border-radius: 9999px;
  background: var(--ink-wash);
  color: var(--ink-soft);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1.2;
  text-decoration: none;
}

a.badge:hover {
  color: var(--ink);
}

.flag-chip,
.warning {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  max-width: 100%;
  margin: 0;
  padding: 3px 9px;
  border-radius: 9999px;
  background: rgba(242, 178, 0, 0.15);
  color: var(--text-warning);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
}

.flag-chip {
  padding: 3px 8px;
  font-size: 11.5px;
}

/* The live dot: the one thing on the page that moves on its own. */
.live-dot {
  display: inline-block;
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--status-live);
  animation: live-pulse 1.8s var(--ease-glass) infinite;
}

@keyframes live-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.45);
  }
  70%,
  100% {
    box-shadow: 0 0 0 6px rgba(34, 197, 94, 0);
  }
}

/* A run's or a step's status: meta text, coloured only for an outcome. Running gets the
   live dot, succeeded, failed and interrupted their colour. */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 500;
  text-transform: capitalize;
}

.status-pill.status-running::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--status-live);
  animation: live-pulse 1.8s var(--ease-glass) infinite;
}

.status-pill.status-succeeded {
  color: var(--text-success);
}

.status-pill.status-failed {
  color: var(--text-danger);
}

.status-pill.status-interrupted {
  color: var(--text-warning);
}

/* Soft cards: one rounded white card per item, 10px apart. Lifted is the next or the
   recommended one; faded is finished or turned down. */
.card-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.session-card,
.contact-card,
.sample-card,
.ref-card,
.direction-card,
.upload-card,
.reference-card {
  position: relative;
  min-width: 0;
  border: 1px solid var(--ink-line);
  border-radius: 16px;
  background: var(--white);
  box-shadow: var(--shadow-soft);
  transition:
    background-color 200ms var(--ease-glass),
    border-color 200ms var(--ease-glass),
    box-shadow 200ms var(--ease-glass),
    opacity 200ms var(--ease-glass);
}

.session-card:hover,
.contact-card:hover,
.contact-card:focus-visible {
  border-color: var(--ink-15);
  box-shadow: var(--shadow-hover);
}

.is-lifted {
  border-color: var(--ink-15);
  box-shadow: var(--shadow-lift);
}

.is-faded {
  border-color: var(--line-70);
  background: color-mix(in srgb, var(--white) 55%, transparent);
  box-shadow: none;
  color: var(--ink-faint);
}

/* Something to say on a card, such as "Recommended": meta words, after an ink dot. */
.card-flag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink);
  font-size: 12px;
  font-weight: 500;
}

.card-flag::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--ink);
}

/* Cards with a picture, in a grid. */
.contact-sheet,
.sample-grid,
.ref-grid {
  display: grid;
  gap: 10px;
}

.contact-sheet {
  grid-template-columns: repeat(auto-fill, minmax(min(11rem, 100%), 1fr));
}

.sample-grid {
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
}

.ref-grid {
  grid-template-columns: repeat(auto-fill, minmax(min(12.5rem, 100%), 1fr));
}

/* References and the picker's thumbnails are small pictures to pick from, so a phone
   shows two a row; samples and layouts keep one, to be judged. */
@media (max-width: 639px) {
  .ref-grid,
  .contact-sheet {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* A picture sits in its card with a little room around it. */
.contact-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 8px 8px 12px;
  color: inherit;
  text-decoration: none;
}

.contact-thumb {
  display: block;
  overflow: hidden;
  aspect-ratio: 1080 / 1350;
  border-radius: 10px;
  background: var(--ink-wash);
}

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

.contact-caption {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 4px;
}

.contact-brief {
  display: -webkit-box;
  overflow: hidden;
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.45;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.contact-meta {
  color: var(--ink-soft);
  font-size: 12px;
}

/* Empty state: what the empty space means, and the next step. */
.empty {
  padding: 32px 24px;
  border: 1px dashed var(--ink-line);
  border-radius: 20px;
  text-align: center;
}

.empty-title {
  color: var(--ink);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.012em;
}

.empty-detail {
  max-width: 26rem;
  margin: 6px auto 0;
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.6;
}

/* Facts: a quiet label over its value, in a grid. */
.facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(10rem, 100%), 1fr));
  gap: 16px 20px;
}

.facts dt {
  color: var(--ink-faint);
  font-size: 12px;
}

.facts dd {
  margin-top: 2px;
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

/* A dense log: one compact line per entry; the newest is lifted in an inset. */
.log {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.log > li {
  padding: 8px 12px;
  border-top: 1px solid var(--line-70);
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1.5;
}

.log > li:first-child {
  border-top: 0;
}

.log > li:last-child {
  border-top-color: transparent;
  border-radius: 12px;
  background: var(--wash-60);
  color: var(--ink);
}

/* Data tables: inside a surface, sentence case labels on a faint wash, hairlines between
   rows, numbers tabular and right aligned. */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  text-align: left;
}

.data-table thead {
  border-bottom: 1px solid var(--ink-line);
  background: var(--wash-40);
}

.data-table th {
  padding: 10px 16px;
  color: var(--ink-soft);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}

.data-table tbody tr {
  border-bottom: 1px solid var(--line-70);
  transition: background-color 150ms var(--ease-glass);
}

.data-table tbody tr:last-child {
  border-bottom: 0;
}

.data-table tbody tr:hover {
  background: var(--wash-40);
}

.data-table td {
  padding: 12px 16px;
  color: var(--ink);
  vertical-align: middle;
}

.data-table .num {
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* A missing value is a faint middot, never a dash. */
.missing {
  color: var(--ink-faint);
}

/* A disclosure: its summary with a small chevron that turns as it opens. */
details > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  list-style: none;
  cursor: pointer;
}

details > summary::-webkit-details-marker {
  display: none;
}

details > summary::after {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  margin-left: 2px;
  border-right: 1.6px solid var(--ink-faint);
  border-bottom: 1.6px solid var(--ink-faint);
  transform: translateY(-2px) rotate(45deg);
  transition: transform 200ms var(--ease-glass);
}

details:not([open]) > summary::after {
  transform: rotate(-45deg);
}

/* A short line after an action, such as "Deleted 2 photos.": neutral, under the title. */
.result-message {
  padding: 9px 14px;
  border: 1px solid var(--line-80);
  border-radius: 14px;
  background: var(--white);
  color: var(--ink-soft);
  font-size: 13px;
}

/* --------------------------------------------------------------------- pages */

/* Studio: the brief, the mode and the settings on one surface, then recent work. */
.studio-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.studio-counts {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
}

/* Reference images (v5): a label over the file button, a hint under. The brief form's rule
   takes a label's gap away, so this one gives it back. */
.studio-form .reference-images-field label {
  margin-bottom: 6px;
}

.mode-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
}

/* The limits join the settings row while Auto is chosen; their hint ends the row. */
.studio-settings {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 16px;
}

.auto-limits {
  display: contents;
}

.auto-limits-hint {
  flex-basis: 100%;
  order: 1;
  margin: 0;
}

.studio-settings .field-small input {
  width: 6.5rem;
}

.studio-settings > .btn {
  min-height: 40px;
  padding: 0 20px;
}

.session-card {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 24px;
  padding: 14px 16px;
  color: inherit;
  text-decoration: none;
}

.session-card-brief {
  flex: 1 1 20rem;
  min-width: 0;
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.session-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  color: var(--ink-soft);
  font-size: 13px;
}

.session-card.is-faded .session-card-brief,
.session-card.is-faded .session-card-meta {
  color: var(--ink-faint);
}

.session-card.is-faded:hover {
  background: var(--white);
  box-shadow: none;
}

/* Session: the live pill above the title, Stop beside it, "See the run" as a link. */
.live-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}

.live-pill {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  max-width: 100%;
  padding: 5px 12px;
  border: 1px solid var(--ink-line);
  border-radius: 9999px;
  background: var(--white);
  color: var(--ink-soft);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.4;
}

.live-pill .live-dot {
  transform: translateY(-1px);
}

.session-panel > .stack > .decision-list {
  margin-bottom: 4px;
}

.question {
  color: var(--ink);
  font-size: 14px;
}

.failed-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.failed-error {
  color: var(--text-danger);
  font-size: 14px;
  font-weight: 500;
}

.source-photo-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

/* The brief, with the quality bar as a labelled inset beside it. */
.brief-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  align-items: start;
}

.brief-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.brief-form label {
  margin: 0;
}

@media (min-width: 640px) {
  .brief-row:has(> .quality-bar-inset) {
    grid-template-columns: minmax(0, 1fr) 8rem;
  }

  /* The references (v5) sit under the brief, so the quality bar spans both rows beside them. */
  .brief-row > .quality-bar-inset {
    grid-column: 2;
    grid-row: 1 / span 2;
  }
}

.quality-bar-inset {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 8rem;
  padding: 10px;
  border-radius: 16px;
  background: var(--wash-60);
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  transition: background-color 150ms var(--ease-glass);
}

.quality-bar-inset:hover {
  background: var(--ink-wash);
}

.quality-bar-inset img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 8px;
}

/* The designer's references (v5): a labelled inset holding a row of small soft cards, 96px
   wide, each with its picture whole on a quiet square, its note and Save, and Remove; Add
   under the row. The row wraps, two a row on a phone. */
.references-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.references-title {
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
}

.reference-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.reference-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 96px;
  padding: 6px 6px 8px;
}

.reference-thumb {
  display: block;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  border-radius: 10px;
  background: var(--ink-wash);
}

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

.reference-note {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
}

/* A one-line note in a card this narrow: the system's field at the 32px size of its Save. */
.reference-note input[type="text"] {
  min-height: 32px;
  padding: 0 10px;
  font-size: 13px;
}

.reference-card .btn-link {
  font-size: 13px;
}

.concept-facts dd {
  font-weight: 400;
}

/* Research: the status line, the report as it came, the searches, the sources. */
details.panel > summary {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--heading);
}

details.panel[open] > summary {
  margin-bottom: 16px;
}

.research-status {
  display: flex;
  align-items: baseline;
  gap: 8px;
  color: var(--ink-soft);
  font-size: 13px;
}

/* Made up, or not grounded: the designer should know before trusting it. */
.research-status-demo,
.research-status-ungrounded {
  color: var(--text-warning);
}

.research-status-demo::before,
.research-status-ungrounded::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--status-noshow);
  transform: translateY(-1px);
}

/* The report as returned: its own line breaks, and long words or addresses wrap. */
.research-text {
  max-width: 46rem;
  font-size: 15px;
  line-height: 1.6;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.query-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 6px 0 0;
  padding: 0;
  list-style: none;
}

.query-list .badge {
  font-size: 12px;
  line-height: 1.35;
}

.research-sources {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line-70);
}

.research-sources li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--line-70);
  border-radius: 8px;
  font-size: 13px;
  scroll-margin-top: 12px;
}

/* The source a chip jumped to. */
.research-sources li:target {
  background: var(--ink-wash);
}

.research-source-number {
  flex: none;
  min-width: 2.25em;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.research-source-body {
  min-width: 0;
  overflow-wrap: anywhere;
}

.research-source-domain {
  margin-left: 8px;
  color: var(--ink-faint);
  font-size: 12px;
}

/* Directions: three soft cards, the recommended one lifted. */
.direction-chosen-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
}

.direction-chosen {
  font-size: 14px;
  font-weight: 500;
}

.direction-chosen-row + .direction-choices {
  margin-top: 16px;
}

.direction-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: 10px;
}

.direction-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
}

.direction-reason {
  color: var(--ink-soft);
  font-size: 13px;
}

/* A card shows its fields or, after "Edit and use", its form; the buttons sit at the
   card's foot, so the three line up. */
.direction-view,
.direction-edit-form {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 8px;
  overflow-wrap: anywhere;
}

.direction-edit-form {
  gap: 12px;
}

.direction-title {
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.direction-kind {
  color: var(--ink-faint);
  font-size: 12px;
}

.direction-look {
  color: var(--ink-soft);
  font-size: 13px;
}

.direction-fields {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.direction-fields dt {
  color: var(--ink-faint);
  font-size: 12px;
}

.direction-fields dd {
  font-size: 14px;
}

.direction-headline {
  font-weight: 600;
}

.direction-facts {
  margin: 0;
  padding-left: 1.1em;
}

.direction-sources {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.source-chip {
  padding: 1px 7px;
  border: 1px solid var(--ink-line);
  border-radius: 9999px;
  color: var(--ink-soft);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: border-color 150ms var(--ease-glass), color 150ms var(--ease-glass);
}

.source-chip:hover {
  border-color: var(--ink-25);
  color: var(--ink);
}

.direction-buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin-top: auto;
  padding-top: 8px;
}

.direction-choices > .direction-actions {
  margin-top: 4px;
}

/* Prompt and words: fields per the system, the choices in one row. */
.prompt-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.choice-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px 24px;
}

.sample-count-field .hint {
  white-space: nowrap;
}

.version-notes {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}

.version-reason {
  color: var(--ink-soft);
  font-size: 13px;
}

.version-label {
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
}

.prompt-diff {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line-70);
}

.prompt-diff summary {
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
}

.change-list {
  margin: 12px 0;
  padding-left: 1.1em;
  color: var(--ink-soft);
  font-size: 13px;
}

.change-list li + li {
  margin-top: 4px;
}

.diff-text {
  margin-top: 12px;
  line-height: 1.7;
}

/* Words added and words dropped, in ink and faint ink. */
.diff-text ins {
  padding: 1px 3px;
  border-radius: 4px;
  background: var(--ink-wash);
  color: var(--ink);
  font-weight: 500;
  text-decoration: none;
}

.diff-text del {
  color: var(--ink-faint);
  text-decoration: line-through;
}

/* Uploads: a label, the file button and Upload, a hint under. */
.upload-form {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.upload-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}

/* Rounds of samples, each on its own surface, the newest first. */
.rounds-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.rounds-section > .group-title {
  padding: 4px 4px 0;
}

.round-panel > .section-title {
  margin-bottom: 4px;
}

.round-note {
  margin-bottom: 16px;
  color: var(--ink-soft);
  font-size: 13px;
}

.round-panel > .sample-grid {
  margin-top: 12px;
}

.round-note + .sample-grid {
  margin-top: 0;
}

/* v6: under a round's title, a compare round's models and cost, or the model that stood in
   for one no longer available. Meta words, figures lined up. */
.round-meta {
  margin-bottom: 12px;
  color: var(--ink-soft);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.round-meta + .sample-grid {
  margin-top: 0;
}

/* A sample: the photo, then what the critic said, the reactions and the next steps. */
.sample-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 8px 8px 14px;
}

.sample-card.is-rejected {
  opacity: 0.55;
}

.sample-photo {
  position: relative;
  overflow: hidden;
  aspect-ratio: 1080 / 1350;
  border-radius: 10px;
  background: var(--ink-wash);
}

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

.sample-photo-missing {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
}

.sample-error {
  color: var(--text-danger);
  font-size: 12px;
  text-align: center;
}

.sample-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 8px;
  padding: 0 6px;
}

.sample-verdict {
  color: var(--ink);
  font-size: 14px;
}

.sample-scores,
.sample-unscored,
.sample-rank-reason {
  color: var(--ink-soft);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.sample-unscored {
  color: var(--ink-faint);
}

/* v6: the model and the cost on a sample card, a neutral badge whose figures line up. */
.sample-model {
  font-variant-numeric: tabular-nums;
}

.sample-rank {
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.flag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.sample-reactions {
  display: flex;
  gap: 4px;
  margin-left: -4px;
}

.sample-comment {
  min-height: 60px;
  font-size: 13px;
}

.sample-comment-hint {
  display: none;
  color: var(--ink-faint);
  font-size: 12px;
}

.sample-card[data-reaction="liked"] .sample-comment-hint {
  display: block;
}

.sample-actions,
.candidate-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin-top: auto;
  padding-top: 4px;
}

.sample-actions .btn-link,
.candidate-actions .btn-link {
  font-size: 13px;
}

/* Feedback on the newest round. */
.round-feedback-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line-70);
}

.round-feedback-existing {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line-70);
  color: var(--ink-soft);
  font-size: 13px;
}

/* Layouts: cards like the samples, with Adjust's settings folding out. */
.candidate-caption {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
}

.adjust-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line-70);
}

.adjust-form .field-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(9rem, 100%), 1fr));
  gap: 12px;
}

.adjust-form .btn {
  align-self: flex-start;
}

.layout-more {
  margin-top: 16px;
}

/* The finished post, and what the final check made of it. */
.finished-post-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 24px;
}

.finished-post-thumb {
  display: block;
  width: 6rem;
  aspect-ratio: 1080 / 1350;
  border-radius: 10px;
  object-fit: cover;
  background: var(--ink-wash);
}

.final-check {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 16px;
}

.final-check-picked {
  color: var(--ink-soft);
  font-size: 13px;
}

.final-check-line {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
}

.final-check-hint {
  color: var(--ink-soft);
  font-size: 13px;
}

/* Post: two columns from 900px, the post on the left. */
.post-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

@media (min-width: 900px) {
  .post-layout {
    grid-template-columns: minmax(0, 23rem) minmax(0, 1fr);
  }
}

.post-figure {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.post-inset {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
}

.post-image {
  display: block;
  width: 100%;
  aspect-ratio: 1080 / 1350;
  border-radius: 10px;
  object-fit: cover;
}

.post-sample-scores {
  color: var(--ink-soft);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.post-details {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.post-direction {
  font-size: 14px;
}

.caption-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

.caption-text {
  font-size: 14px;
  line-height: 1.6;
  white-space: pre-wrap;
}

.hashtags {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.post-warnings {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.auto-summary {
  color: var(--ink-soft);
  font-size: 13px;
}

.why-panel summary {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
}

.why-panel[open] summary {
  margin-bottom: 8px;
}

.why-subhead {
  margin: 12px 0 4px;
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 500;
}

.reasons {
  margin: 0;
  padding-left: 1.1em;
  font-size: 14px;
  line-height: 1.6;
}

.reasons li + li {
  margin-top: 4px;
}

.reference-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.reference-thumbs img {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 8px;
  object-fit: cover;
  background: var(--ink-wash);
}

.revise-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding-top: 16px;
  border-top: 1px solid var(--line-70);
}

.revise-form textarea {
  margin-bottom: 0;
}

.revise-form .btn {
  margin-top: 12px;
}

.versions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.versions .why-subhead {
  margin: 0;
}

.version-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.version-pill {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 0 11px;
  border: 1px solid var(--ink-line);
  border-radius: 9999px;
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
}

.version-pill.is-current {
  border-color: var(--ink);
  color: var(--ink);
}

.post-links {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
}

/* Library: the quality bar, the imports, the taste and the references. */
.quality-bar-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 20px 24px;
}

.quality-bar-figure {
  flex: none;
  width: 11rem;
  padding: 10px;
}

.quality-bar-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 8px;
}

.quality-bar-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  min-width: min(16rem, 100%);
}

.quality-bar-explain {
  font-size: 14px;
}

/* Your uploads (v5): the brand's shelf as a row of small soft cards that wraps, each with
   its picture whole, its name, its size and Remove. A phone shows two a row. */
.upload-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(9.5rem, 100%), 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (max-width: 639px) {
  .upload-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.upload-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 8px 8px 12px;
}

.upload-caption {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 4px;
}

.upload-card .upload-name {
  font-size: 13px;
  font-weight: 500;
}

.upload-meta {
  color: var(--ink-soft);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.upload-card .inline-form {
  margin-top: auto;
  padding: 0 4px;
}

.import-actions {
  margin-bottom: 0;
}

.imports-panel .hint {
  margin-top: 8px;
}

.library-add {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--line-70);
}

@media (min-width: 900px) {
  .library-add {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
  }
}

.links-form {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}

.links-form textarea {
  min-height: 72px;
}

.links-form .btn {
  margin-top: 12px;
}

.library-note {
  margin-top: 16px;
}

.import-summary {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
  font-size: 13px;
}

.import-summary summary {
  font-weight: 500;
}

.import-summary ul {
  margin: 8px 0 0;
  padding-left: 1.1em;
  color: var(--ink-soft);
}

.taste-panel .facts {
  grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
}

.taste-summary {
  margin-top: 16px;
  font-size: 14px;
}

.references-panel .section-head {
  align-items: center;
}

/* A reference: its picture, its name and kind, and like and dislike. A liked card gets an
   ink hairline, a disliked one fades. */
.ref-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.ref-card[data-choice="liked"] {
  border-color: var(--ink);
}

.ref-card[data-choice="disliked"] {
  opacity: 0.55;
}

.ref-card.is-hidden {
  display: none;
}

.ref-image {
  flex: none;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--ink-wash);
}

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

.ref-image-missing {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--ink-faint);
  font-size: 12px;
}

.ref-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px 0;
}

.ref-label {
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.ref-category,
.ref-status {
  color: var(--ink-soft);
  font-size: 12px;
}

.ref-status {
  color: var(--ink-faint);
}

.ref-status::first-letter {
  text-transform: uppercase;
}

.ref-actions {
  display: flex;
  gap: 4px;
  margin-top: auto;
  padding: 8px 10px 10px;
}

@media (prefers-reduced-motion: no-preference) {
  .ref-card.just-updated {
    animation: ref-confirm 150ms var(--ease-glass);
  }
}

@keyframes ref-confirm {
  from {
    transform: scale(0.98);
  }
  to {
    transform: scale(1);
  }
}

/* Archive: filters and the two delete actions over a grid of photo cards. */
.archive-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  margin-bottom: 16px;
}

.archive-select {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 1;
  display: inline-flex;
  margin: 0;
  padding: 6px;
  border-radius: 9px;
  background: color-mix(in srgb, var(--white) 92%, transparent);
  box-shadow: var(--shadow-soft);
  cursor: pointer;
}

.archive-select input {
  width: 16px;
  height: 16px;
  margin: 0;
}

.archive-meta,
.archive-score,
.archive-reaction {
  color: var(--ink-soft);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.archive-prompt {
  color: var(--ink);
  font-size: 13px;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.prompt-more {
  display: inline;
}

.prompt-more summary {
  display: inline;
  color: var(--ink);
  font-weight: 500;
  text-decoration: underline;
  text-decoration-color: var(--ink-25);
  text-underline-offset: 2px;
}

.prompt-more summary::after {
  content: none;
}

.archive-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  margin-top: auto;
  padding-top: 6px;
}

.archive-actions .btn-link {
  font-size: 13px;
}

/* v6: the Model filter sits under the archive's filters, named by a faint label. */
.archive-filters {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.filter-label {
  align-self: center;
  margin-right: 4px;
  color: var(--ink-faint);
  font-size: 12px;
  font-weight: 500;
}

/* Runs: a table of every run, its stages indented under it. */
.runs-table .cell-kind {
  color: var(--ink-soft);
  font-size: 13px;
  white-space: nowrap;
}

.runs-table .cell-brief {
  width: 100%;
  min-width: 14rem;
}

.run-link {
  color: var(--ink);
  font-weight: 500;
  overflow-wrap: anywhere;
}

.runs-table .cell-started,
.runs-table .cell-took {
  color: var(--ink-soft);
  font-size: 13px;
}

.runs-table .cell-session {
  font-size: 13px;
  white-space: nowrap;
}

.runs-table tr.is-child .cell-kind {
  padding-left: 32px;
}

.runs-table tr.is-child .run-link {
  color: var(--ink-soft);
  font-weight: 400;
}

/* Below 900px the six columns no longer fit, so each run stacks into a small block. */
@media (max-width: 899px) {
  .runs-table thead {
    display: none;
  }

  .runs-table,
  .runs-table tbody,
  .runs-table td {
    display: block;
  }

  .runs-table tr {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 4px 12px;
    padding: 12px 16px;
  }

  .runs-table td {
    padding: 0;
  }

  .runs-table .cell-brief {
    grid-column: 1 / -1;
    order: -1;
    min-width: 0;
  }

  .runs-table .cell-status,
  .runs-table .cell-took {
    text-align: right;
  }

  .runs-table .cell-started {
    text-align: left;
  }

  .runs-table .cell-session:empty {
    display: none;
  }

  .runs-table tr.is-child {
    padding-left: 32px;
  }

  .runs-table tr.is-child .cell-kind {
    padding-left: 0;
  }
}

/* Run: the status, the steps as a dense log, the child runs as links. */
.run-status {
  display: flex;
  align-items: center;
  gap: 6px;
}

.run-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
}

.run-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.run-panel > h2 {
  margin-bottom: 4px;
}

.run-working {
  display: flex;
  align-items: center;
  gap: 8px;
}

.run-done {
  font-size: 14px;
  font-weight: 500;
}

.run-done-note {
  color: var(--ink-soft);
  font-weight: 400;
}

.run-failed {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.run-error {
  color: var(--text-danger);
  font-size: 14px;
  font-weight: 500;
}

.step-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
}

.step-status-dot {
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: 9999px;
  background: var(--ink-faint);
  transform: translateY(-2px);
}

.step-status-dot.status-succeeded {
  background: var(--status-made);
}

.step-status-dot.status-failed {
  background: var(--status-cancelled);
}

.step-status-dot.status-running {
  background: var(--status-live);
  animation: live-pulse 1.8s var(--ease-glass) infinite;
}

.step-body {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 12px;
  min-width: 0;
}

.step-name {
  display: flex;
  align-items: baseline;
  gap: 8px;
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
}

/* Inside the log, a step's status is a word: the dot carries its colour. */
.step-name .status-pill {
  color: var(--ink-faint);
  font-size: 12.5px;
  font-weight: 400;
}

.step-name .status-pill::before {
  content: none;
}

.step-meta {
  order: 1;
  color: var(--ink-faint);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.step-note {
  flex-basis: 100%;
  order: 2;
  color: var(--ink-soft);
  font-size: 13px;
  overflow-wrap: anywhere;
}

.step-error {
  flex-basis: 100%;
  order: 3;
  color: var(--text-danger);
  font-size: 13px;
  font-weight: 500;
}

/* From 900px, one line per step in three aligned columns: the step and its status, its
   time and provider, then its note. The order keeps the columns right whichever line the
   script adds first. */
@media (min-width: 900px) {
  .step-body {
    display: grid;
    grid-template-columns: minmax(0, 17rem) minmax(0, 10rem) minmax(0, 1fr);
    column-gap: 16px;
  }

  .step-name {
    grid-column: 1;
  }

  .step-meta {
    grid-column: 2;
  }

  .step-note,
  .step-error {
    grid-column: 3;
  }
}

.child-runs {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 8px;
  padding-top: 16px;
  border-top: 1px solid var(--line-70);
}

.run-list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

.run-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 16px;
  padding: 8px 0;
  border-top: 1px solid var(--line-70);
  font-size: 14px;
}

.run-row:first-child {
  border-top: 0;
}

/* Editor and its picker: the canvas in a surface, the settings in another. */
.editor {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 21rem;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "stage panel"
    "actions panel";
  gap: 20px;
  align-items: start;
}

.editor-stage {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
  grid-area: stage;
}

/* The settings column: the Ask surface over the settings surface (v5). */
.editor-side {
  display: flex;
  flex-direction: column;
  gap: 20px;
  min-width: 0;
  grid-area: panel;
}

.editor-panel {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* Ask (v5): what to change in words, a file when the change needs one, Apply and Undo, and
   one line on what the editor did, or the question it asks. */
.editor-ask-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* A long word in the line wraps rather than widening the column. */
.editor-ask-line,
.editor-ask-form .field-error {
  overflow-wrap: anywhere;
}

.editor-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  grid-area: actions;
}

.editor-actions .hint,
.editor-actions .field-error {
  margin: 0;
}

.editor-words {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.editor-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 16px;
  border-top: 1px solid var(--line-70);
}

.editor-group .hint {
  margin: 0;
}

.editor-group > .btn,
.editor-part > .btn {
  align-self: flex-start;
}

.editor-part {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.editor-number {
  display: flex;
  align-items: center;
  gap: 8px;
}

.editor-number .hint {
  margin: 0;
  font-size: 13px;
}

.editor-italic {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.editor-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-weight: 400;
  font-size: 14px;
  cursor: pointer;
}

.editor-toggle input {
  width: 16px;
  height: 16px;
  margin: 0;
}

.editor-toggle:has(input:disabled) {
  cursor: default;
}

.swatch-group legend {
  margin: 0 0 8px;
  padding: 0;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}

.picker-form {
  margin: 0;
}

/* Each card of the picker is a form's button, drawn as a soft card. */
.picker-card {
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* Add image's picker: an inset under the Add buttons, never a dialog. The upload field on
   top, the brand's uploads under it as small cards to press. */
.editor-uploads {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.editor-uploads .hint {
  margin: 6px 0 0;
}

.editor-shelf-title {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}

.editor-shelf-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(5rem, 1fr));
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* An upload to press: its picture whole on a quiet square, its name under it. */
.upload-pick {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
  height: 100%;
  padding: 6px 6px 8px;
  border: 1px solid var(--ink-line);
  border-radius: 12px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition:
    border-color 150ms var(--ease-glass),
    box-shadow 150ms var(--ease-glass);
}

.upload-pick:hover {
  border-color: var(--ink-15);
  box-shadow: var(--shadow-hover);
}

.upload-pick:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px var(--ink-10);
}

.upload-thumb {
  display: block;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  border-radius: 8px;
  background: var(--ink-wash);
}

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

/* A name wraps rather than being cut short. */
.upload-name {
  color: var(--ink);
  font-size: 12px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

@media (max-width: 60rem) {
  .editor {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas:
      "stage"
      "panel"
      "actions";
  }
}

/* ------------------------------------------------- editor: functional rules */

/* The post at half size: 540 by 675 on a wide screen, scaled down whole on a phone.
   Sizes inside are shares of the canvas width, so the words wrap the same at any scale;
   at full width a 64px headline draws at 32px. The editor's script declares the faces
   the canvas sets the words in, from the page's data, so no typeface is named here. */
.editor-canvas {
  --post-width: 1080;
  position: relative;
  flex: none;
  width: 540px;
  max-width: 100%;
  aspect-ratio: 1080 / 1350;
  container-type: inline-size;
  overflow: hidden;
  outline: 1px solid var(--ink-line);
  user-select: none;
  -webkit-user-select: none;
}

/* The photo's box: the bottom layer, chosen, moved and resized like a block. The canvas
   colour shows around it. It covers the canvas until the script places it. */
.editor-photo-box {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  cursor: move;
  touch-action: none;
}

.editor-photo {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  max-width: none;
  height: 100%;
}

.editor-block {
  position: absolute;
  margin: 0;
  cursor: move;
  touch-action: none;
}

/* The words as the renderer sets them (base.css and custom.html). The designer's own text
   is set like the headline. */
.editor-headline,
.editor-subline,
.editor-text {
  font-size: calc(var(--px) * 100cqw / var(--post-width));
  text-wrap: balance;
}

.editor-headline,
.editor-text {
  letter-spacing: var(--headline-tracking);
  line-height: 1.08;
}

.editor-subline {
  line-height: 1.35;
  opacity: 0.78;
}

/* Words left empty are not drawn; their place stays visible here so it can be found. */
.editor-block.is-empty {
  min-height: 1em;
  outline: 1px dashed var(--ink-faint);
}

.editor-logo {
  display: block;
  max-width: none;
  height: auto;
}

/* An uploaded image fills its box as its fit says; the script sets the box and the fit. */
.editor-image {
  display: block;
  max-width: none;
}

/* Only the chosen item has an outline, drawn over everything with its handles, and
   dashed for the photo. The line sits just inside the item, so it shows at the canvas's
   edge too; a faint halo outside it keeps it visible over a photo of any tone. --handle
   is the handles' size, which the script reads as well. The blocks are layered by their
   place in the list, at most twelve of them, so the outline goes above the twelfth. */
.editor-selection {
  --handle: 14px;
  position: absolute;
  z-index: 13;
  pointer-events: none;
  outline: 1px solid var(--ink);
  outline-offset: -1px;
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--white) 60%, transparent);
}

.editor-selection.is-photo {
  outline-style: dashed;
}

/* A handle on each corner and on the middle of each side, centred on its point. */
.editor-handle {
  position: absolute;
  width: var(--handle);
  height: var(--handle);
  margin: calc(var(--handle) / -2) 0 0 calc(var(--handle) / -2);
  border: 2px solid var(--white);
  border-radius: 3px;
  background: var(--ink);
  pointer-events: auto;
  touch-action: none;
}

.editor-handle[data-editor-handle="nw"] {
  top: 0;
  left: 0;
  cursor: nwse-resize;
}

.editor-handle[data-editor-handle="n"] {
  top: 0;
  left: 50%;
  cursor: ns-resize;
}

.editor-handle[data-editor-handle="ne"] {
  top: 0;
  left: 100%;
  cursor: nesw-resize;
}

.editor-handle[data-editor-handle="e"] {
  top: 50%;
  left: 100%;
  cursor: ew-resize;
}

.editor-handle[data-editor-handle="se"] {
  top: 100%;
  left: 100%;
  cursor: nwse-resize;
}

.editor-handle[data-editor-handle="s"] {
  top: 100%;
  left: 50%;
  cursor: ns-resize;
}

.editor-handle[data-editor-handle="sw"] {
  top: 100%;
  left: 0;
  cursor: nesw-resize;
}

.editor-handle[data-editor-handle="w"] {
  top: 50%;
  left: 0;
  cursor: ew-resize;
}

/* The words take their height from their width, so every handle they show resizes
   across. */
.editor-selection.is-width-only .editor-handle {
  cursor: ew-resize;
}

/* On an edge that touches the canvas's edge, the handles sit inside the item, where the
   canvas does not clip them. */
.editor-selection.at-left [data-editor-handle$="w"] {
  margin-left: 0;
}

.editor-selection.at-right [data-editor-handle$="e"] {
  margin-left: calc(var(--handle) * -1);
}

.editor-selection.at-top [data-editor-handle^="n"] {
  margin-top: 0;
}

.editor-selection.at-bottom [data-editor-handle^="s"] {
  margin-top: calc(var(--handle) * -1);
}

@media (pointer: coarse) {
  .editor-selection {
    --handle: 24px;
  }
}

.editor-preview {
  display: flex;
  flex: 1 1 16rem;
  flex-direction: column;
  gap: 12px;
  max-width: 540px;
  margin: 0;
}

.editor-preview img {
  display: block;
  width: 100%;
  height: auto;
  outline: 1px solid var(--ink-line);
}

/* What the renderer changed in the arrangement. */
.editor-adjustments {
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ink-soft);
  font-size: 13px;
}

.editor-adjustments li {
  padding: 4px 0 4px 12px;
  border-left: 2px solid var(--status-noshow);
}

/* The pan arrows, laid out as a cross. */
.pan-pad {
  display: grid;
  grid-template-columns: repeat(3, 2.5rem);
  grid-template-areas:
    ". up ."
    "left . right"
    ". down .";
  gap: 4px;
}

.pan-pad .btn {
  min-height: 2.5rem;
  padding: 0;
}

.pan-pad [data-pan="up"] {
  grid-area: up;
}

.pan-pad [data-pan="left"] {
  grid-area: left;
}

.pan-pad [data-pan="right"] {
  grid-area: right;
}

.pan-pad [data-pan="down"] {
  grid-area: down;
}

/* Colour choices: a row of circles with the colour inside and its name as the title. */
.swatch-group {
  margin: 0;
  padding: 0;
  border: none;
}

.swatch-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.swatch {
  position: relative;
  display: inline-flex;
  margin: 0;
  cursor: pointer;
}

.swatch input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.swatch-dot {
  width: 1.75rem;
  height: 1.75rem;
  border: 1px solid var(--ink-line);
  border-radius: 50%;
  background: var(--swatch, transparent);
}

/* The brand's own colour for the role, which follows the chosen block and the mode. */
.swatch-brand .swatch-dot {
  border: 2px dashed var(--ink-faint);
}

.swatch input:checked + .swatch-dot,
.swatch input:focus-visible + .swatch-dot {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.swatch-group .swatch-name {
  margin: 8px 0 0;
}

/* -------------------------------------------------------- image models (v6) */

/* The Model picker beside "Samples a round", and auto mode's Photo model: wide enough for a
   model's name and price, and its own line on a phone. */
.model-field {
  flex: 1 1 16rem;
  min-width: 0;
  max-width: 26rem;
}

.studio-settings .model-field {
  flex: 1 1 18rem;
}

/* The session page keeps "Samples a round" and the Model picker side by side: they wrap as
   one group when the row is full. */
.round-settings {
  display: flex;
  flex: 1 1 28rem;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px 24px;
  min-width: 0;
}

/* Compare models: a disclosure under the picker, its choices one a line, its button under. */
.compare-models > summary {
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
}

.compare-models[open] > summary {
  margin-bottom: 12px;
}

.compare-fieldset {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.compare-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.compare-list .check-option,
.model-controls .check-option {
  font-size: 13px;
}

.compare-fieldset .hint {
  margin: 0;
}

.sample-error a {
  color: var(--ink);
  font-weight: 500;
}

/* Settings: a soft card per provider inside the Image models surface, its models as a dense
   list with hairlines between them. */
.settings-alert {
  margin-bottom: 12px;
}

.provider-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.provider-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  padding: 16px;
  border: 1px solid var(--ink-line);
  border-radius: 16px;
  background: var(--white);
  box-shadow: var(--shadow-soft);
  scroll-margin-top: 96px;
}

.provider-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}

/* The status pill: neutral for "Not set up", success for "Ready" and "Free", danger for a
   refused key; the tint is the status colour, the words its darker text colour. */
.provider-status.is-success {
  background: color-mix(in srgb, var(--status-made) 14%, transparent);
  color: var(--text-success);
}

.provider-status.is-danger {
  background: color-mix(in srgb, var(--status-cancelled) 14%, transparent);
  color: var(--text-danger);
}

.provider-key-line {
  font-variant-numeric: tabular-nums;
}

.provider-key-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.provider-check,
.settings-result {
  color: var(--ink-soft);
  font-size: 13px;
  line-height: 1.5;
}

.provider-check {
  color: var(--ink);
}

.provider-check.is-failed {
  color: var(--text-danger);
}

.provider-note {
  margin: 0;
}

.model-list {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--line-70);
  list-style: none;
}

.model-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line-70);
}

.model-row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.model-name {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.model-label {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
}

.model-price {
  color: var(--ink-soft);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}

.model-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
}

.model-controls .select-small {
  width: auto;
  min-height: 32px;
  padding-left: 12px;
  font-size: 13px;
}

.settings-save {
  margin-top: 16px;
}

.settings-save .settings-result,
.limits-form .settings-result {
  margin: 0;
}

/* Limits: three small fields in a row, the checkbox and Save under them. */
.limits-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.limits-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 16px;
}

.money-field {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.money-field > span {
  position: absolute;
  left: 12px;
  color: var(--ink-soft);
  font-size: 14px;
  pointer-events: none;
}

.money-field input[type="number"] {
  padding-left: 24px;
}

/* Usage: the table on a flush surface, the title and the note padded as a surface pads. */
.usage-title {
  padding: 20px 24px 12px;
}

.usage-scroll {
  overflow-x: auto;
}

.usage-table th.usage-group {
  padding-bottom: 0;
  text-align: center;
}

.usage-table .usage-provider {
  color: var(--ink);
  font-size: 14px;
  font-weight: 500;
}

.usage-note {
  margin: 0;
  padding: 12px 24px 20px;
}

.settings-about {
  max-width: 42rem;
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.6;
}

@media (max-width: 639px) {
  .model-field,
  .studio-settings .model-field {
    flex-basis: 100%;
    max-width: none;
  }

  .usage-table th,
  .usage-table td {
    padding: 10px 8px;
  }

  .usage-title {
    padding: 16px 16px 8px;
  }

  .usage-note {
    padding: 10px 16px 16px;
  }
}

/* ------------------------------------------------- product photos (v6 Part B) */

/* A reference card is wide enough for its small Style · Product toggle; while it asks for the
   rights line it widens, so the line reads in a few lines rather than a word a line. */
.reference-card {
  width: 128px;
}

.reference-card.is-confirming {
  width: 232px;
}

.reference-thumb {
  position: relative;
}

/* "Product" on the thumbnail of a product photo: the neutral badge, lifted off the picture. */
.reference-badge {
  position: absolute;
  top: 6px;
  left: 6px;
  background: var(--white);
  box-shadow: var(--shadow-pill);
  color: var(--ink);
}

.reference-role {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
}

/* The segmented control at a card's size. */
.segmented-small {
  gap: 2px;
  padding: 3px;
}

.segmented-small .pill-option span {
  padding: 3px 7px;
  font-size: 12px;
}

.reference-rights {
  align-items: flex-start;
  font-size: 12px;
  line-height: 1.4;
}

.reference-rights input {
  flex: none;
  margin-top: 1px;
}

/* The line on where product photos go, and the fidelity choice under it, above the cards. */
.product-line {
  color: var(--ink-soft);
  font-size: 13px;
}

.fidelity-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}

/* "From your uploads": the editor's picker of the brand's uploads, as a disclosure under Add. */
.references-uploads > summary {
  color: var(--ink);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}

.references-uploads[open] > summary {
  margin-bottom: 10px;
}

.references-uploads .inline-form,
.references-uploads .upload-pick {
  height: 100%;
}

/* A sample's badges side by side: its model and cost, and the product photos it was sent. */
.sample-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.sample-products {
  font-variant-numeric: tabular-nums;
}

.sample-product-note {
  color: var(--ink-soft);
  font-size: 12.5px;
}

/* The Studio page's "These are product photos": the box, its words and the rights line. */
.studio-form .reference-images-field .products-option {
  align-items: flex-start;
  margin: 10px 0 0;
}

.products-option input {
  flex: none;
  margin-top: 2px;
}

.products-option-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.products-option-rights {
  color: var(--ink-soft);
  font-size: 12.5px;
}

/* ------------------------------------------------------------------ sign in (v7) */

/* The passcode page: one narrow panel, a little below the bar. */
.signin-panel {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
  max-width: 440px;
  margin: 6vh auto 0;
}

.signin-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* --------------------------------------------------------------------- motion */

/* Motion answers a click or a scroll on the glass curve; with reduced motion, nothing
   moves, the live pulse included. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
  }
}
