/* Hookshift. Hammersmith One sets anything that names something (the mark,
   page and card headings); Poppins does the reading. Both are self-hosted
   latin subsets - a webfont CDN is a third party on every page of a paid
   product for no benefit, and the marketing site's CSP is font-src 'self'. */

@font-face {
  font-family: "Hammersmith One";
  src: url("/static/fonts/HammersmithOne-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/static/fonts/Poppins-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/static/fonts/Poppins-500.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/static/fonts/Poppins-600.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: "Poppins";
  src: url("/static/fonts/Poppins-700.woff2") format("woff2");
  font-weight: 700;
  font-display: swap;
}

:root {
  color-scheme: light;
  --ink: #16181d;
  --ink-soft: #3d424b;
  --muted: #6e747f;
  --line: #e7e5e1;
  --line-strong: #d6d2cc;
  --bg: #faf8f5;
  --card: #ffffff;

  /* Straight off the logo: amber at one corner running into orange at the
     other. Type on brand is always ink, never white - the logo sets black on
     orange for the same reason, it is the only pairing that passes contrast
     at these values. */
  --brand: #f5842f;
  --brand-soft: #ffc46b;
  --brand-wash: #fff4e6;
  --brand-line: #f6d3a5;
  --brand-gradient: linear-gradient(135deg, #ffc46b 0%, #f5842f 100%);
  /* Orange is unreadable as link text on white; this is the same hue taken
     dark enough to pass AA on the page background. */
  --brand-ink: #a8540c;

  --accent: var(--brand);
  --accent-fg: var(--ink);
  --error: #b42318;
  --error-wash: #fdf3f2;
  --ok: #1c7a4d;
  --ok-wash: #f1f9f4;
  --ok-line: #a8d6bd;

  --radius: 12px;
  --radius-sm: 9px;
  --shadow: 0 1px 2px rgba(22, 24, 29, 0.04), 0 8px 24px -12px rgba(22, 24, 29, 0.14);
  --display: "Hammersmith One", "Trebuchet MS", sans-serif;
  --sans: "Poppins", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }
/* A jump link glides to its section rather than cutting to it, as the
   marketing site does. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 15px/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: 0.005em;
  line-height: 1.2;
}
h1 { font-size: 1.9rem; }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.05rem; }
h4 { font-size: 0.95rem; }

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

/* ------------------------------------------------------------------ chrome */

.skip-link {
  position: absolute; left: -9999px; top: 8px; z-index: 80;
  padding: 8px 12px; background: var(--card); border-radius: var(--radius-sm);
}
.skip-link:focus { left: 12px; }

/* The work down the left, the account at the bottom of it. */
.shell { display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: 100vh; }
.sidebar {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 18px 16px;
  border-right: 1px solid var(--line);
  background: var(--card);
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}
.brand {
  font-family: var(--display);
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  flex: none;
}
.brand::before {
  content: "";
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: var(--brand-gradient);
  flex: none;
}

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink-soft);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
}
.nav-glyph { font-size: 11px; color: var(--muted); width: 12px; text-align: center; }
.nav a:hover { color: var(--ink); background: var(--bg); }
.nav a[aria-current="page"] {
  color: var(--ink);
  background: var(--brand-wash);
  box-shadow: inset 0 0 0 1px var(--brand-line);
}
.nav a[aria-current="page"] .nav-glyph { color: var(--brand-ink); }

.side-links { margin-top: auto; }
.side-links .nav-glyph { display: inline-flex; }
.account-menu { position: relative; }
.account-drop .ico { margin-right: 8px; vertical-align: -2px; color: var(--muted); }
.account-pill {
  width: 100%;
  justify-content: flex-start;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 12px;
  white-space: nowrap;
  box-shadow: none;
  gap: 6px;
}
.account-pill:hover { background: var(--card); border-color: var(--line-strong); color: var(--ink); }
.account-pill .caret { font-size: 10px; color: var(--muted); margin-left: auto; }
.account-name { overflow: hidden; text-overflow: ellipsis; }
.account-drop {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 6px);
  min-width: 180px;
  padding: 6px;
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 28px rgba(22, 24, 29, 0.13);
  display: flex;
  flex-direction: column;
}
.account-drop a, .account-drop button {
  display: block;
  width: 100%;
  text-align: left;
  justify-content: flex-start;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  background: none;
  box-shadow: none;
}
.account-drop a:hover, .account-drop button:hover { background: var(--bg); color: var(--ink); }
.account-drop a[aria-current="page"] { background: var(--brand-wash); color: var(--ink); }
.account-drop form { margin: 6px 0 0; padding-top: 6px; border-top: 1px solid var(--line); }
.logout-form { margin: 0; }
.logout-form button {
  background: none;
  color: var(--muted);
  padding: 5px 8px;
  font-size: 13px;
  font-weight: 500;
  box-shadow: none;
}
.logout-form button:hover { color: var(--ink); background: var(--bg); }

.page { max-width: 940px; margin: 0 auto; padding: 32px 24px 96px; width: 100%; }

.page-head { margin-bottom: 22px; }
.page-head h1, .page-head h2 { margin: 0 0 4px; }
.page-head .sub { margin: 0; max-width: 62ch; }

/* ------------------------------------------------------------------ blocks */

.center-card {
  max-width: 440px;
  margin: 72px auto;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 34px 32px;
  text-align: center;
}
.center-card h1 { margin: 0 0 8px; }
.lede { color: var(--muted); margin: 0 0 20px; }
.stack { display: flex; flex-direction: column; gap: 10px; text-align: left; }
.settings .stack button[type="submit"] { align-self: flex-start; }

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
}
.card h2, .card h3 { margin-top: 0; }
.two-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }

/* ------------------------------------------------------------------ controls */

input[type="email"], input[type="text"], input[type="time"],
input[type="number"], input[type="password"], select, textarea {
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
  font-size: 15px;
  font-family: inherit;
  line-height: 1.5;
  width: 100%;
}
textarea { resize: vertical; }
/* Selects draw their own chevron, so they look like the rest of the form
   rather than like the browser (Ale, 2026-09-13). */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%236b6f76' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--brand);
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-wash);
}
:where(a, button, .button, input, select, textarea, summary):focus-visible {
  outline: 2px solid var(--brand-ink);
  outline-offset: 2px;
}

button, .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  background: var(--brand-gradient);
  color: var(--ink);
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 18px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  box-shadow: 0 1px 2px rgba(22, 24, 29, 0.12);
}
button:hover:not(:disabled), .button:hover { filter: brightness(1.05); color: var(--ink); }
button:active:not(:disabled) { transform: translateY(1px); }
button:disabled { opacity: 0.45; cursor: default; box-shadow: none; }
.button.small, button.small { padding: 7px 13px; font-size: 13px; }

/* Second-rank action: same shape, no fill. Most buttons on a page should be
   one of these, or the page has no primary action at all. */
.button.quiet, button.quiet, .thumb {
  background: var(--card);
  color: var(--ink-soft);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  font-weight: 500;
}
.button.quiet:hover, button.quiet:hover:not(:disabled), .thumb:hover {
  filter: none;
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink);
}
.thumb {
  font-size: 12.5px; padding: 6px 11px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 5px; line-height: 1.25;
}
/* A .thumb that is a link (download) is the same control as a .thumb that is
   a button, so it must not wear a link's underline beside one. */
a.thumb, a.thumb:hover { text-decoration: none; }
button.danger, .button.danger {
  background: none;
  color: var(--error);
  box-shadow: inset 0 0 0 1px var(--error);
}
button.danger:hover:not(:disabled) { filter: none; background: var(--error-wash); color: var(--error); }

.error { color: var(--error); font-size: 13.5px; }
.error-box {
  border: 1px solid var(--error);
  background: var(--error-wash);
  border-radius: var(--radius-sm);
  padding: 10px 13px;
  margin: 0 0 12px;
}
.muted, .note, .sub { color: var(--muted); font-size: 13.5px; }
.saved-note { font-size: 12.5px; color: var(--ok); font-weight: 500; }
[x-cloak] { display: none !important; }

.empty-state {
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  padding: 34px 24px;
  text-align: center;
  color: var(--muted);
  background: var(--card);
}

/* ------------------------------------------------------------------ /videos */

.add-video { margin-bottom: 26px; }
.add-panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.add-panel > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 15px 20px;
  cursor: pointer;
  font-weight: 600;
  list-style: none;
}
.add-panel > summary::-webkit-details-marker { display: none; }
.add-panel > summary::after {
  content: "";
  margin-left: auto;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
  transition: transform 0.15s;
}
.add-panel[open] > summary::after { transform: rotate(-135deg); }
.add-panel > summary .sub { font-weight: 400; }
.add-body { padding: 18px 20px 20px; border-top: 1px solid var(--line); }

.dropzone {
  display: block;
  border: 1.5px dashed var(--brand-line);
  background: var(--brand-wash);
  border-radius: var(--radius);
  padding: 26px 20px;
  text-align: center;
  cursor: pointer;
}
.dropzone:hover, .dropzone.over { border-color: var(--brand); background: #ffe9cd; }
.dropzone strong { display: block; font-size: 15px; }
.dropzone .sub { margin: 4px 0 0; }
.dropzone input[type="file"] {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.dropzone:focus-within { outline: 2px solid var(--brand-ink); outline-offset: 2px; }

.upload-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  color: var(--ink-soft);
  padding: 9px 12px;
  margin-top: 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.upload-row .name {
  font-weight: 500; flex: none; max-width: 45%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.upload-row progress {
  flex: 1;
  height: 6px;
  appearance: none;
  border: none;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}
.upload-row progress::-webkit-progress-bar { background: var(--line); border-radius: 999px; }
.upload-row progress::-webkit-progress-value { background: var(--brand); border-radius: 999px; }
.upload-row progress::-moz-progress-bar { background: var(--brand); border-radius: 999px; }
.upload-row.error { border-color: var(--error); background: var(--error-wash); color: var(--error); }
.upload-row.error progress { display: none; }

.reels-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(108px, 1fr)); gap: 12px; }
/* The "we could not reach Instagram" line is a sibling of the reel cards, so
   without this it is laid out as one, squeezed into a 108px column. */
.reels-grid > p { grid-column: 1 / -1; margin: 0; }
.reel-card { text-align: center; }
.reel-card img, .reel-thumb-placeholder {
  width: 100%;
  border-radius: var(--radius-sm);
  aspect-ratio: 9/16;
  object-fit: cover;
  display: block;
  background: var(--line);
  margin-bottom: 6px;
}
.reel-card .button { width: 100%; }
.reel-card .note { font-size: 11.5px; line-height: 1.35; }

.sources-list { display: flex; flex-direction: column; gap: 12px; }

.source-panel {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  /* No overflow: hidden. It was here to keep the summary's own background
     inside the rounded corners, and it clipped every tooltip that tried to
     leave the card - the same clipping that hid the hook's tip one level
     down (Ale, 2026-09-12, who read it as a z-index problem; it was not).
     The summary carries the radius itself instead. */
}
.source-panel > summary:first-child { border-radius: calc(var(--radius) - 1px); }
.source-panel[open] > summary:first-child {
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
/* A hovered card paints over the ones after it, so its tooltip is not left
   behind the next panel down. */
.source-panel:hover { position: relative; z-index: 2; }
.source-panel > summary {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 18px;
  cursor: pointer;
  list-style: none;
}
.source-panel > summary::-webkit-details-marker { display: none; }
.source-panel > summary:hover { background: var(--bg); }
.source-body { padding: 18px; border-top: 1px solid var(--line); }

.source-thumb {
  width: 48px;
  height: 84px;
  flex: none;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.source-thumb img { width: 100%; height: 100%; object-fit: cover; }

.source-title { flex: 1; min-width: 0; }
.source-title h3 {
  margin: 0;
  font-size: 15px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.source-title .sub, .source-title .error { margin: 2px 0 0; font-size: 12.5px; display: block; }

.pill {
  flex: none;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 3px 11px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.pill.warn { background: var(--brand-wash); border-color: var(--brand-line); }
.pill.bad { background: var(--error-wash); border-color: var(--error); color: var(--error); }

/* A spinner beats the word "Preparing" on its own: it says something is
   happening rather than something is stuck. */
.spinner {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  border: 2px solid var(--brand-line);
  border-top-color: var(--brand);
  animation: spin 0.8s linear infinite;
  flex: none;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }

.source-actions { display: flex; gap: 8px; flex: none; align-items: center; }
.source-actions form { margin: 0; }

.field-group { margin-bottom: 24px; }
.field-group:last-child { margin-bottom: 0; }
.field-group > h4 {
  margin: 0 0 3px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.field-group > .sub { margin: 0 0 10px; }

.questions-row { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 12px; }
.question {
  flex: 1 1 250px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}
.question > span { display: block; font-weight: 600; font-size: 14px; margin-bottom: 7px; }
.question .choices { display: flex; gap: 8px; margin-bottom: 7px; }
.question .choices label {
  flex: 1;
  text-align: center;
  font-size: 13px;
  font-weight: 500;
  padding: 6px 0;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.question .choices label:has(input:checked) {
  background: var(--brand-wash);
  border-color: var(--brand);
}
.question .choices input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.question .choices label:focus-within { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.question .sub { margin: 0; font-size: 12.5px; }

.hook-rows { display: flex; flex-direction: column; gap: 10px; }
.hook-row { display: grid; grid-template-columns: 20px 1fr auto; gap: 10px; align-items: start; }
.hook-n { padding-top: 13px; font-size: 12.5px; color: var(--muted); text-align: right; }
.hook-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; align-items: start; }
/* Both boxes grow with what is in them: hooks and captions both run to
   several lines, and a fixed two-row box turns each one into its own little
   scroll area. */
.hook-fields textarea { font-size: 14px; field-sizing: content; min-height: 44px; max-height: 12em; }
.hook-row .hidden-action { visibility: hidden; }
@media (max-width: 700px) { .hook-fields { grid-template-columns: 1fr; } }
.hooks-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.hooks-toolbar select { width: auto; min-width: 180px; padding: 7px 10px; font-size: 13px; }
.spacer { flex: 1; }
.hook-count { font-size: 12.5px; color: var(--muted); }

/* ------------------------------------------------------------------ preview */

.preview-head { margin-bottom: 20px; }
.preview-head .count { font-size: 15px; margin: 4px 0; }
/* Something like footage behind a style: soft green leaves, drawn with
   gradients and a blur, so white text with no box is as visible as black on
   white. Ale, 2026-09-13: "white text on transparent background (a common
   setting) and it's not visible". */
.leafy { position: relative; overflow: hidden; isolation: isolate; }
.leafy::before {
  content: ""; position: absolute; inset: -30%; z-index: -1;
  background:
    radial-gradient(circle at 18% 30%, #a5d66f 0, #a5d66f 14%, transparent 34%),
    radial-gradient(circle at 74% 22%, #2f7d32 0, #2f7d32 16%, transparent 38%),
    radial-gradient(circle at 62% 78%, #7cb342 0, #7cb342 15%, transparent 36%),
    radial-gradient(circle at 22% 82%, #1b5e20 0, #1b5e20 18%, transparent 40%),
    radial-gradient(circle at 90% 70%, #c5e1a5 0, #c5e1a5 10%, transparent 30%),
    #4e9a4a;
  filter: blur(6px);
}
.swatch-text {
  display: inline-block; padding: 1px 5px; border-radius: 3px; font-weight: 700;
  font-family: var(--sans); line-height: 1.2; white-space: nowrap;
}
.swatch-text.big { font-size: 22px; padding: 4px 10px; border-radius: 6px; }


/* ------------------------------------------------------------------- home */

.stat-row {
  display: grid; gap: 12px; margin-bottom: 18px;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
.stat {
  display: flex; flex-direction: column; gap: 4px;
  padding: 16px 18px; text-decoration: none;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.stat:hover { border-color: var(--brand-line); background: var(--brand-wash); }
.stat-n { font-family: var(--display); font-size: 1.9rem; color: var(--ink); line-height: 1.1; }
.stat-label { font-size: 12.5px; color: var(--muted); }
/* The estimated tile: same shape as the measured ones, marked on its face so
   it is never read as one of them. */
.stat.est { cursor: help; }
.est-tag {
  margin-left: 5px; padding: 1px 5px; border-radius: var(--radius-sm);
  background: var(--brand-wash); color: var(--brand-ink);
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em;
}
.home-cols { display: grid; gap: 16px; grid-template-columns: 1fr 1fr; margin-bottom: 16px; }
.home-cols .card h3 { margin: 0 0 6px; }
.hook-quote {
  margin: 8px 0 14px; padding-left: 12px; border-left: 3px solid var(--brand-line);
  font-size: 15px; white-space: pre-wrap;
}
.home-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.notice { border-color: var(--brand-line); background: var(--brand-wash); margin-bottom: 16px; }
.notice.bad { border-color: var(--error); background: var(--error-wash); }
.notice p { margin: 0; }
@media (max-width: 760px) { .home-cols { grid-template-columns: 1fr; } }

/* Home before the first reel is out: a numbered path, ticked from real state. */
.setup { margin-bottom: 16px; }
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.steps li { display: flex; gap: 14px; align-items: flex-start; color: var(--muted); }
.steps li.done, .steps li.now { color: var(--ink); }
.steps li strong { display: block; margin-bottom: 2px; }
.steps li .sub { display: block; max-width: 56ch; }
.steps li .button { margin-top: 10px; }
.step-mark {
  flex: 0 0 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  font-size: 13px; font-weight: 600; border: 1px solid var(--line-strong); color: var(--muted);
}
.steps li.done .step-mark { background: var(--ok); border-color: var(--ok); color: #fff; }
.steps li.now .step-mark { background: var(--brand-gradient); border-color: transparent; color: var(--ink); }
.row-title { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }

/* ------------------------------------------------------- dialogs, toasts */

/* No padding on the dialog itself: the backdrop click that closes it is a
   click on the <dialog> element, so the content sits in one padded child. */
.modal {
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 0;
  position: relative;
  max-width: 460px;
  width: calc(100% - 32px);
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 24px 60px rgba(22, 24, 29, 0.22);
}
.modal > form, .modal > .modal-inner { padding: 20px; }
.modal::backdrop { background: rgba(22, 24, 29, 0.35); }
/* The X in the corner, the same on every dialog. */
.modal-close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  display: grid; place-items: center; width: 30px; height: 30px; padding: 0;
  border-radius: 50%; background: var(--card); color: var(--muted);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.modal-close:hover { filter: none; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.modal h3 { margin: 0 0 8px; }
.modal-body p { margin: 0; color: var(--ink-soft); }
.modal-field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--muted); }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

#toasts {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  display: flex; flex-direction: column; gap: 8px; max-width: min(380px, calc(100% - 36px));
}
.toast {
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  background: var(--card);
  border: 1px solid var(--line-strong);
  box-shadow: 0 10px 30px rgba(22, 24, 29, 0.16);
  font-size: 13.5px;
}
.toast.bad { border-color: var(--error); background: var(--error-wash); }

.error-page { max-width: 560px; }
.error-page code { background: var(--bg); padding: 2px 6px; border-radius: 4px; }
.danger-zone { border-color: var(--error-wash); }
.account-actions .danger-zone { border-color: var(--error); }

/* The account's own picture, so the product says "you". */
.avatar { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; flex: none; }
.avatar-fallback {
  display: grid; place-items: center; width: 22px; height: 22px; flex: none;
  border-radius: 50%; background: var(--brand-gradient); color: var(--ink);
  font-size: 11px; font-weight: 700;
}
.avatar + .avatar-fallback { display: none; }

/* A video's variants, inside the video's own panel. The controls sit in
   their own column beside the grid: full-width sliders and a full-width row
   of alignment buttons is what a control strip looks like when it loses the
   column it was written for. */
/* overflow-anchor: every control here swaps the whole block it sits in.
   Chrome's scroll anchoring then picked something in the new block to hold
   still and threw the page to the bottom of the panel on a slider release
   (Ale, 2026-09-13, reproduced in her Chrome). */
.variants { margin-top: 0; overflow-anchor: none; }
.variants-body { display: grid; grid-template-columns: 248px 1fr; gap: 24px; align-items: start; }
@media (max-width: 760px) { .variants-body { grid-template-columns: 1fr; } }
.variants-head h4 { margin: 0 0 4px; }
.variants-head .sub { margin: 0 0 10px; max-width: 70ch; }

.hooks-head { display: flex; align-items: center; gap: 10px; cursor: pointer; list-style: none; }
.hooks-head::-webkit-details-marker { display: none; }
.hooks-head h4 { margin: 0; }
/* The marker is drawn rather than left to the browser, so it sits where the
   heading is and turns with the fold. */
.hooks-head h4::before {
  content: "";
  display: inline-block;
  width: 0; height: 0;
  margin-right: 8px;
  border: 5px solid transparent;
  border-left-color: var(--muted);
  vertical-align: middle;
  transition: transform 0.12s ease;
}
details.hooks[open] > .hooks-head h4::before,
.tested-fold[open] > .hooks-head h4::before,
.variants-fold[open] > .hooks-head h4::before { transform: rotate(90deg); }
details.hooks[open] > .hooks-head { margin-bottom: 10px; }

/* Hooks, read rather than edited: what most visits to a video are for. */
.hook-read-list { margin: 0 0 12px; padding-left: 22px; display: flex;
                  flex-direction: column; gap: 8px; }
.hook-read-list li { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: start; }
.hook-read-list li .hook-read-caption { grid-column: 1 / -1; }
.hook-read-text { margin: 0; font-size: 14.5px; white-space: pre-wrap; }
/* Quiet until wanted, but still in the tab order and under a finger. */
.hook-skip { opacity: 0; }
.hook-read-list li:hover .hook-skip, .hook-skip:focus, .hook-read-list li.skipped .hook-skip { opacity: 1; }
@media (hover: none) { .hook-skip { opacity: 1; } }
/* Dimmed and labelled "Off", never struck through. Ale, 2026-09-12: "i'm
   seeing this like it's used up, but we never published any reels with it so
   it is NOT used up." A line through a hook reads as spent, and a hook is
   never spent: skipping is a switch she can flip back, and even a hook whose
   combinations really have all been made is only finished until another
   variant axis exists - which is exactly what adding zoom and grade just
   did. Nothing about a hook is terminal, so nothing should be drawn as if it
   were. */
.hook-read-list li.skipped .hook-read-text { color: var(--muted); }
.hook-read-list li.skipped .hook-read-text::after {
  content: "Off";
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-soft);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  vertical-align: 2px;
  white-space: nowrap;
}
.hook-read-caption { margin-top: 2px; }
.hook-read-caption summary { font-size: 12.5px; color: var(--muted); cursor: pointer; }
.hook-read-caption p { margin: 4px 0 0; font-size: 13px; color: var(--ink-soft);
                       white-space: pre-wrap; }

/* Alignment: three buttons that look like what they do. */
.align-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; max-width: 260px; }
.align-btn {
  display: grid;
  place-items: center;
  padding: 8px 6px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.align-btn:hover { background: var(--bg); }
.align-btn.on { background: var(--brand-wash); border-color: var(--brand); }
.align-btn { position: relative; }
.align-btn input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.align-btn:focus-within { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.align-btn svg { width: 30px; height: 20px; fill: var(--ink-soft); }
.align-btn svg .frame { fill: none; stroke: var(--line-strong); stroke-width: 1.2; }
.align-btn.on svg { fill: var(--ink); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.rate { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.rate label { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.rate input[type="number"] { width: 72px; }
.acknowledgement {
  flex-basis: 100%; max-width: 640px; padding: 14px 16px; margin-top: 8px;
  border: 1px solid var(--error); border-radius: var(--radius); background: var(--error-wash);
}
.acknowledgement p { margin: 0 0 8px; font-size: 13px; line-height: 1.5; }
.acknowledgement label { display: block; font-size: 13px; margin-bottom: 8px; }

.preview-panel {
  display: grid; grid-template-columns: 248px 1fr; gap: 24px;
  padding: 18px; margin-bottom: 16px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.preview-controls h3 { margin: 0 0 14px; font-size: 15px; }
.preview-controls .control { display: block; margin-bottom: 18px; }
.preview-controls .control > span { display: block; font-weight: 600; font-size: 13px; margin-bottom: 6px; }
.preview-controls form.control { margin-bottom: 18px; }
.segmented { display: flex; gap: 6px; }
.segmented label {
  flex: 1; text-align: center; font-size: 12.5px; font-weight: 500; padding: 6px 0;
  cursor: pointer; text-transform: capitalize;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
}
.segmented label.on { background: var(--brand-wash); border-color: var(--brand); color: var(--ink); }
/* Visually hidden, NOT display:none - that took the radios out of the tab
   order and out of the accessibility tree, leaving the justification control
   keyboard-unreachable and unannounced. */
.segmented input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.segmented label:focus-within { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.slider { display: block; font-size: 12.5px; color: var(--muted); margin-bottom: 8px; }
.slider input { width: 100%; accent-color: var(--brand); }

.make-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 12px 0 0; }
.make-row .sub { margin: 0; }
.htmx-indicator { opacity: 0; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; }

/* The fonts and styles, as chips that ARE the picker: a font chip is the
   font's own name in its own face and nothing else; a style chip is its
   colours. Click one to see only it, again for everything. */
.chip-bar {
  margin: 16px 0 18px; padding: 12px 14px;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.chip-row + .chip-row { margin-top: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 7px; height: 34px;
  padding: 0 13px; border-radius: 999px; text-decoration: none;
  background: var(--card); color: var(--ink-soft);
  border: 1px solid var(--line-strong); box-shadow: none;
  font-size: 12.5px; font-weight: 500; line-height: 1;
}
.chip:hover { border-color: var(--brand); background: var(--brand-wash); color: var(--ink); }
/* on: a switch that is on, which is the ordinary state, so it looks ordinary:
   white, dark text, a firm border. Off is the marked one: dashed and faded.
   Orange is kept for the one real highlight on a page (Ale, 2026-09-13:
   "a little bit too much orange everywhere"). */
.chip.on { background: var(--card); border-color: var(--ink-soft); color: var(--ink); }
.chip.selected { background: var(--card); border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); color: var(--ink); }
.chip img { height: 17px; width: auto; max-width: 190px; object-fit: contain; display: block; }
.chip-swatch {
  display: grid; place-items: center; width: 22px; height: 18px; border-radius: 4px;
  font-size: 11px; font-weight: 700; box-shadow: inset 0 0 0 1px var(--line-strong);
}
/* Not used on this video: still here, still clickable, plainly dimmed. */
.chip.off { opacity: 0.4; background: var(--bg); border-style: dashed; }
.chip.off.selected { opacity: 0.7; }
.chip-link { margin-left: auto; font-size: 12.5px; white-space: nowrap; }
.cell-filter { color: inherit; text-decoration: none; border-bottom: 1px dotted var(--line-strong); }
.cell-filter:hover { color: var(--brand-ink); border-bottom-color: var(--brand-ink); }
.chip-group .chip-row { flex: 1; }
.controls-col { display: flex; flex-direction: column; gap: 14px; }
.on-this-video { padding: 10px 12px; border: 1px dashed var(--line-strong); border-radius: var(--radius-sm); }
.on-this-video form { margin: 0; }
.on-this-video form + form { margin-top: 8px; }
.on-this-video .sub { margin: 0 0 6px; }
.grid-note { margin: 0 0 10px; }

/* One reel, rendered on request, under the cell that asked for it. */
.preview-video {
  margin-top: 14px; padding: 12px 14px; max-width: 420px;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.preview-video p { margin: 0 0 8px; }
.preview-video p:last-child { margin-bottom: 0; }
.preview-video form { display: flex; align-items: center; gap: 10px; margin: 0 0 8px; }
.preview-actions { display: flex; gap: 8px; }
.rendering-note { display: flex; align-items: center; gap: 8px; }
.cell-watch {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 26px; height: 26px; padding: 0 0 0 2px; border-radius: 50%;
  background: rgba(22, 24, 29, 0.6); color: #fff; font-size: 10px; box-shadow: none;
}
.cell-watch:hover { background: var(--brand); color: var(--ink); filter: none; }

/* One reel per cell, and clicking it works on that one alone. */
.cell-open { position: absolute; inset: 0; }
.cell-open:hover { box-shadow: inset 0 0 0 3px var(--brand); border-radius: var(--radius-sm); }
/* Two lines at most: "Plus Jakarta Sans SemiBold · Black on white" is the
   whole name of a variant, and an ellipsis after the font hid the style. */
.cell-style {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  font-size: 11.5px; line-height: 1.3; color: var(--muted); margin-bottom: 4px;
  overflow: hidden;
}
.focus-bar { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; flex-wrap: wrap; }
/* "Show [every font] in [every style]": the way to narrow the grid. */
.grid-filter label { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.grid-filter select { width: auto; padding: 6px 30px 6px 10px; font-size: 13px; color: var(--ink); }
/* The hook is moved by dragging it on the preview. While it moves, the safe
   area shows: everything outside it darkens (the 4:5 crop, the margins, and
   Instagram's button rail), so where the hook may go is a picture, not a
   rule (Ale, 2026-09-13: "people are grown ups"). */
.frame[data-hook-y] { cursor: grab; }
.safe-guide, .rail-guide {
  position: absolute; pointer-events: none; opacity: 0; transition: opacity 0.15s ease; z-index: 1;
}
.safe-guide {
  border: 1px dashed rgba(255, 255, 255, 0.85); border-radius: 3px;
  box-shadow: 0 0 0 2000px rgba(10, 12, 16, 0.5);
}
.rail-guide { right: 0; bottom: 0; background: rgba(10, 12, 16, 0.35); border-left: 1px dashed rgba(255, 255, 255, 0.5); }
.frame.dragging .safe-guide, .frame.dragging .rail-guide,
.preview-grid.focused .frame[data-hook-y]:hover .safe-guide, .preview-grid.focused .frame[data-hook-y]:hover .rail-guide,
.frame[data-hook-y]:focus-visible .safe-guide, .frame[data-hook-y]:focus-visible .rail-guide { opacity: 1; }
.frame.dragging .layer { z-index: 2; }
/* Approve and Skip on a cell, as one yes/no pair like the Queue's. */
.cell figcaption .decide { width: 100%; }
.cell figcaption .decide .inline { flex: 1; }
.cell figcaption .decide .thumb { width: 100%; }
.approve-all { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }
.approve-all .sub { margin: 0; }
.frame[data-hook-y].dragging { cursor: grabbing; }
.frame[data-hook-y].dragging .layer { transition: none; }
.frame img, .cell-open { -webkit-user-drag: none; user-select: none; }
.preview-grid.focused .frame[data-hook-y] { touch-action: none; }
.frame[data-hook-y]:focus-visible { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.tested-fold, .variants-fold { margin-top: 14px; }
.tested-fold > .sub { margin: 0 0 8px; }
.tested-fold .chip-bar { margin: 0; }
.tested-fold[open] > .hooks-head, .variants-fold[open] > .hooks-head { margin-bottom: 10px; }
.focus-bar .sub { margin: 0; }
.preview-grid.focused { grid-template-columns: minmax(0, 260px); }
.pager { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.pager .sub { margin: 0; }

.preview-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.cell { margin: 0; }
.cell.skipped .frame { opacity: 0.32; }
/* The frame keeps the reel's own 1080x1920, so the text layer lands exactly
   where it will land in the video - the whole point of previewing at all. */
.frame {
  position: relative; aspect-ratio: 1080 / 1920; overflow: hidden;
  border-radius: var(--radius-sm); background: var(--line);
}
.frame img { position: absolute; inset: 0; width: 100%; height: 100%; }
.frame .poster { object-fit: cover; }
.frame .layer { object-fit: fill; }
.band-guide {
  position: absolute; left: 0; right: 0; pointer-events: none;
  border-top: 1px dashed rgba(255, 255, 255, 0.55);
  border-bottom: 1px dashed rgba(255, 255, 255, 0.55);
}
.preparing {
  display: none; position: absolute; inset: 0; align-items: center; justify-content: center;
  font-size: 12px; color: var(--muted); text-align: center; padding: 0 10px;
}
.frame.nopost .preparing { display: flex; }
.frame.nopost .poster, .frame.nopost .layer, .frame.nopost .band-guide { display: none; }
.cell figcaption { margin-top: 6px; }
.cell figcaption .thumb { width: 100%; }

/* ------------------------------------------------------------------ settings */

.settings { max-width: 780px; margin-bottom: 40px; scroll-margin-top: 64px; }
.settings > h2 { margin: 0 0 6px; }
.settings > h3 { margin: 18px 0 8px; font-size: 0.95rem; color: var(--ink-soft); scroll-margin-top: 64px; }
.count-line { margin: 14px 0 0; padding: 10px 14px; font-size: 13.5px; color: var(--ink-soft);
              background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm); max-width: 62ch; }
.count-line strong { color: var(--ink); }
.rate-note { margin: 0; }
/* A switch drawn as a chip, the way every other on/off thing on this page
   is: a hidden checkbox, the chip tinted while it is on. */
.settings-chips .chip.switch, .chip.switch { cursor: pointer; padding: 0 15px; }
.chip.switch:has(input:disabled) { cursor: default; }
.check-line .sub { font-size: 12.5px; }
.chip.switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.chip.switch:has(input:focus-visible) { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.chip.switch:not(.on) { color: var(--muted); border-style: dashed; }
.settings .sub { max-width: 62ch; margin-bottom: 14px; }
/* Jump links, pinned under the top edge while the page scrolls past six
   sections. */
.settings-nav {
  position: sticky; top: 0; z-index: 5; display: flex; gap: 4px; flex-wrap: wrap;
  margin: 0 0 24px; padding: 8px 0;
  background: var(--bg); border-bottom: 1px solid var(--line);
}
.settings-nav a {
  padding: 6px 12px; border-radius: 999px; font-size: 13px; font-weight: 500;
  color: var(--ink-soft); text-decoration: none;
}
.settings-nav a:hover { background: var(--card); color: var(--ink); box-shadow: inset 0 0 0 1px var(--line-strong); }
/* The posting window and the rate read as one sentence: "Between 15:00 and
   23:00, up to 5 a day". Small boxes, because they hold five characters. */
.when-row { display: flex; align-items: flex-start; gap: 6px 18px; flex-wrap: wrap; margin-bottom: 12px; }
/* The two forms dissolve into the row, so a warning or an error inside one
   takes a full line of its own instead of pushing "up to N a day" down. */
.when-row > form { display: contents; }
.when-row label { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; }
.when-row input[type="time"], .when-row input[type="number"] {
  width: auto; padding: 6px 8px; font-size: 14px; line-height: 1.3;
}
.when-row input[type="number"] { width: 58px; }
.when-row input.bad { border-color: var(--error); box-shadow: 0 0 0 3px var(--error-wash); }
.when-row .rate { margin-top: 0; }
.timezone-row select { width: auto; max-width: 100%; padding: 6px 30px 6px 10px; font-size: 14px; }
.timezone-row .sub { margin: 0; }
/* Fonts as cards in two columns: the name in its own face on top, a real
   hook in it underneath. A list of full-width rows was one very long column
   of the same thing. */
/* Fonts and styles as chips, like the video page draws them. */
.chip-form { margin: 0; }
.settings-chips { gap: 8px; }
.settings-chips .chip { height: 38px; padding: 0 6px 0 13px; }
.settings-chips .chip.on { background: var(--card); border-color: var(--ink-soft); color: var(--ink); }
.settings-chips .chip.locked { padding-right: 13px; }
.settings-chips .chip img { height: 18px; }
.chip-body {
  display: inline-flex; align-items: center; gap: 7px; background: none; border: none;
  box-shadow: none; padding: 0; color: inherit; font: inherit; cursor: pointer;
}
.chip-body:hover { filter: none; }
.chip-x {
  width: 22px; height: 22px; padding: 0; margin-left: 2px; border-radius: 999px;
  background: none; box-shadow: none; color: var(--muted); font-size: 16px; line-height: 1;
}
.chip-x:hover { background: var(--card); color: var(--error); filter: none; }
.settings-chips .chip-add, .chip-add { border-style: dashed; color: var(--brand-ink); padding: 0 15px; }
.chip-add:hover { border-style: solid; }
.chip-swatch.leafy { width: 30px; height: 24px; border-radius: 5px; font-size: 11px; box-shadow: none; }
.chip-swatch.timing { width: 26px; font-size: 10.5px; background: var(--bg); color: var(--ink-soft); }
.chip-swatch.leafy .swatch-text { padding: 0 3px; font-size: 10.5px; }

/* The catalogue: one family a row, its name in its own face, a weight. */
.modal-fonts { width: min(720px, 94vw); max-width: none; }
.modal-head { padding-right: 38px; margin-bottom: 4px; }
.modal-head h3 { margin: 0; }
.modal-head + .sub { margin: 0 0 12px; }
/* The catalogue: a card per family, its name set in itself at the weight
   picked underneath, and one button. */
.catalogue {
  list-style: none; margin: 0; padding: 2px; max-height: 62vh; overflow-y: auto;
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
}
.catalogue li { border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--bg); }
.catalogue li.on { border-color: var(--line-strong); background: var(--card); }
.catalogue form { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; margin: 0; }
.catalogue img { height: 26px; width: auto; max-width: 100%; object-fit: contain; object-position: left; display: block; }
.catalogue-name { font-size: 12.5px; color: var(--muted); }
.catalogue-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.catalogue-row .spacer { flex: 1; }
.wpill { display: inline-flex; align-items: center; cursor: pointer; }
.wpill input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.wpill span {
  padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 500;
  color: var(--ink-soft); background: var(--card); box-shadow: inset 0 0 0 1px var(--line-strong);
}
.wpill:has(input:checked) span { background: var(--ink); color: var(--card); box-shadow: none; }
.wpill:has(input:focus-visible) span { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.catalogue button { min-width: 64px; }
@media (max-width: 640px) { .catalogue { grid-template-columns: 1fr; } }

/* Adding or changing a style: presets, then a preview over leaves and the
   fields under it. */
/* overflow visible so a colour pop-over can hang below the last field. */
.modal-look { width: min(620px, 92vw); max-width: none; overflow: visible; }
.preset-block { margin-bottom: 14px; }
.preset-block .sub { margin: 0 0 8px; }
.preset-block .chip { height: 36px; cursor: pointer; }
.preset-block .chip.on { background: var(--card); border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.preset-block .chip.on:hover { background: var(--error-wash); border-color: var(--error); box-shadow: inset 0 0 0 1px var(--error); }
.preset-block .chip.on:hover .chip-tick::before { content: "\00d7"; }
.preset-block .chip.on:hover .chip-tick { font-size: 0; color: var(--error); }
.preset-block .chip.on:hover .chip-tick::before { font-size: 14px; }
.chip-tick { color: var(--ok); font-weight: 700; }
.modal-look .modal-actions { align-items: center; }
.modal-look .modal-actions .saved-note { margin-right: auto; }
.or-line { margin: 14px 0 0 !important; font-weight: 500; color: var(--ink-soft); }
.look-editor { display: grid; grid-template-columns: 1fr; gap: 14px; }
.look-preview { display: grid; place-items: center; min-height: 140px; padding: 16px; border-radius: var(--radius-sm); }
.preview-block { display: inline-block; text-align: center; border-radius: 6px; }
.preview-block.boxed { padding: 6px 12px; }
.preview-line { display: block; }
.preview-line span { display: inline-block; padding: 2px 10px; border-radius: 5px; font-weight: 700; font-size: 22px; line-height: 1.25; white-space: nowrap; }
.preview-block.boxed .preview-line span { padding: 0 2px; border-radius: 0; }
.preview-line + .preview-line { margin-top: 3px; }
.look-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 16px; }
.look-fields .modal-field { display: flex; flex-direction: column; gap: 5px; font-size: 13px; color: var(--muted); }
.look-fields .modal-field input[type="text"], .look-fields select { font-size: 14px; padding: 7px 10px; }
.look-fields .check-line { grid-column: 1 / -1; margin: 2px 0 0; }
.modal-look .modal-actions { margin-top: 16px; }

/* One colour field: a swatch, its hex, and a pop-over with the grid. */
.color-field-host { position: relative; }
.color-field { display: flex; align-items: center; gap: 8px; position: relative; }
.color-swatch {
  position: relative; width: 38px; height: 30px; padding: 0; border-radius: 7px; overflow: hidden;
  background: none; box-shadow: inset 0 0 0 1px var(--line-strong);
}
.color-swatch .checker, .color-swatch .tint { position: absolute; inset: 0; }
.checker {
  background-color: #e8e8e8;
  background-image: linear-gradient(45deg, #c8c8c8 25%, transparent 25%, transparent 75%, #c8c8c8 75%),
                    linear-gradient(45deg, #c8c8c8 25%, transparent 25%, transparent 75%, #c8c8c8 75%);
  background-size: 10px 10px; background-position: 0 0, 5px 5px;
}
.color-hex { font-size: 13px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.color-pop {
  position: absolute; z-index: 20; top: calc(100% + 6px); left: 0; width: 236px;
  padding: 10px; background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); box-shadow: 0 12px 28px rgba(22, 24, 29, 0.16);
}
.color-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; margin-bottom: 10px; }
.color-cell {
  aspect-ratio: 1; padding: 0; border-radius: 6px; box-shadow: inset 0 0 0 1px rgba(22, 24, 29, 0.14);
  min-height: 0;
}
.color-cell.on { box-shadow: inset 0 0 0 2px var(--ink); }
.color-custom { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
.color-custom + .color-custom { margin-top: 8px; }
.color-custom input[type="text"] { width: 96px; padding: 5px 8px; font-size: 13px; font-family: ui-monospace, monospace; }
.color-custom input[type="range"] { flex: 1; accent-color: var(--brand); }
.account-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.account-actions > div { padding: 16px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }
.account-actions h3 { margin: 0 0 6px; }
.account-actions .sub { margin-bottom: 12px; }
.account-actions form { margin: 0; }

.mode-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.mode-option {
  display: flex; align-items: flex-start; gap: 10px; position: relative;
  padding: 14px 16px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); cursor: pointer; background: var(--card);
}
.mode-option:has(input:checked) { border-color: var(--brand); background: var(--brand-wash); }
.mode-option.recommended { border-color: var(--brand-line); box-shadow: inset 0 0 0 1px var(--brand-line); }
.mode-option input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.mode-option:has(input:focus-visible) { outline: 2px solid var(--brand-ink); outline-offset: 2px; }
.mode-option:hover { border-color: var(--brand-line); }
.mode-option strong { display: block; }
.mode-option .sub { display: block; margin: 4px 0 0; font-size: 13px; }
.badge {
  display: inline-block; margin-bottom: 6px; padding: 2px 9px; border-radius: 999px;
  background: var(--brand-gradient); color: var(--ink); font-size: 11px; font-weight: 600;
  letter-spacing: 0.02em;
}
@media (max-width: 760px) { .mode-grid { grid-template-columns: 1fr; } }

.field-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.field-row label { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.field-row input[type="time"] { width: auto; }

/* ------------------------------------------------------------------ tomorrow */

.tomorrow-head { margin-bottom: 16px; }
.tomorrow-list {
  list-style: none; padding: 0; margin: 0;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
}
/* One day's worth of the approval list. Quiet on purpose: it marks where a
   day would break, it is not a heading anyone needs to read first. */
.day-divider {
  display: flex; align-items: baseline; gap: 8px;
  margin: 18px 0 8px; font-size: 13px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted);
}
.day-divider .sub { text-transform: none; letter-spacing: 0; font-weight: 400; }
.tomorrow-item { display: flex; align-items: center; gap: 14px; padding: 12px 16px; }
.tomorrow-item + .tomorrow-item { border-top: 1px solid var(--line); }
.tomorrow-item.empty { opacity: 0.55; }
.thumb-wrap {
  width: 48px; height: 84px; border-radius: var(--radius-sm); overflow: hidden;
  background: var(--line); flex-shrink: 0;
}
.thumb-wrap img { width: 100%; height: 100%; object-fit: cover; }
.tomorrow-meta { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fire-time { font-weight: 600; font-size: 13px; }
.hook-text { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.transform-note { font-size: 12px; color: var(--muted); }
.tomorrow-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; flex-wrap: wrap; }
/* `display: contents` so the BUTTON is the flex item, not the form wrapped
   round it. Download is a bare <a> with no wrapper, so while the forms were
   `display: inline` it sat on a different line box from the other two and
   read as misaligned - which it was. */
.tomorrow-actions .inline { display: contents; }
.thumb.on { background: var(--brand-wash); box-shadow: inset 0 0 0 1px var(--brand); color: var(--ink); }

/* Approve and Skip are one yes/no control: joined, and only ever one of them
   pressed. Skip removes the reel, so its pressed state never persists - the
   pairing is what says they are alternatives. */
.decide { display: flex; }
.decide .thumb { border-radius: 0; }
.decide > .inline:first-child .thumb { border-top-left-radius: 999px; border-bottom-left-radius: 999px; }
.decide > .inline:last-child .thumb { border-top-right-radius: 999px; border-bottom-right-radius: 999px; }
.decide > .inline + .inline .thumb { margin-left: -1px; }
/* That -1px is what joins the pair, and it also means the SECOND button's
   left border sits on top of the first's right one. So Skip's red reached the
   dividing line and Approve's green did not - it was being painted
   underneath (Ale, 2026-09-12). Whichever button is being hovered or held
   comes forward and its own colour draws the divider. Hover outranks the
   pressed state, so hovering Skip on an approved reel still shows red. */
.decide .thumb { position: relative; }
.decide .thumb[aria-pressed="true"] { z-index: 1; }
.decide .thumb:hover:not(:disabled) { z-index: 2; }
/* Yes is green, no is red - the pair reads at a glance without anyone having
   to read either word (Ale, 2026-09-12: "skip is red. make approve / approved
   green"). Approved is the filled one, because it is a state that persists;
   skip removes the reel, so red is only ever a hover. */
.thumb.yes:hover:not(:disabled) { color: var(--ok); box-shadow: inset 0 0 0 1px var(--ok); }
.thumb.yes[aria-pressed="true"] {
  background: var(--ok-wash); box-shadow: inset 0 0 0 1px var(--ok); color: var(--ok);
}
.thumb.yes[aria-pressed="true"]:hover:not(:disabled) {
  background: var(--ok-wash); color: var(--ok); box-shadow: inset 0 0 0 1px var(--ok);
}
.thumb.no:hover { color: var(--error); box-shadow: inset 0 0 0 1px var(--error); }
.thumb .ico { flex: none; }
.day-divider .day-approve { margin-left: auto; }
.queue-section { margin-bottom: 30px; }
.section-head { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.section-head h2 { margin: 0; }
.section-head .button, .section-head .sub { margin-left: auto; }
/* The thumbnail is the play button: a reel you can watch before you decide. */
.thumb-wrap .watch {
  width: 100%; height: 100%; padding: 0; border-radius: 0; box-shadow: none;
  background: var(--line) center / cover no-repeat; color: #fff;
}
.thumb-wrap .watch .play {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  background: rgba(22, 24, 29, 0.55); font-size: 10px; padding-left: 2px;
}
.thumb-wrap .watch:hover { filter: none; }
.thumb-wrap .watch:hover .play { background: var(--brand); color: var(--ink); }
/* ------------------------------------------------- the reel preview

   Not a player in a box: the screen a reel is approved or skipped on. Its own
   heading (the hook, and which video it came from), the player between two
   arrows that walk the same list the page below is showing, and one row of
   decisions under it. The dialog itself carries no padding so the close cross
   can sit in its true corner; the form inside holds the padding. */
.modal-watch {
  max-width: min(560px, 94vw);
  width: min(560px, 94vw);
  padding: 0;
  overflow: visible;
}
.modal-watch > form { padding: 20px 22px 18px; }

/* Room for the cross, and for the fact that a hook is often four lines. */
.watch-head { padding-right: 38px; margin-bottom: 16px; }
.watch-hook { margin: 0; font-size: 17px; line-height: 1.35; }
.watch-hook.no-hook { color: var(--muted); font-style: italic; font-weight: 500; }
/* .modal-body p sets margin 0 and its own colour on every paragraph in a
   dialog, which is right for a one-line confirm and wrong for a body that
   draws its own layout - hence the extra class here and on .watch-note. */
.modal-body .watch-from { margin: 6px 0 0; font-size: 13px; color: var(--muted); }
.watch-from strong { color: var(--ink-soft); font-weight: 600; }

/* Flex, not a three-column grid: the player is sized by its height, so its
   width is whatever 9:16 works out to - and in a grid the arrows sat out at
   the dialog's edges instead of beside the thing they page through. */
.watch-stage { display: flex; align-items: center; justify-content: center; gap: 12px; }
/* Sized by HEIGHT, not width: a 9:16 reel filling a 420px-wide dialog is
   750px tall, which is taller than the laptop it is being reviewed on. */
.watch-video {
  display: block; aspect-ratio: 9 / 16; background: #000;
  /* Both caps, no fixed size: tall screens are limited by height, narrow ones
     by the width left over beside the arrows, and 9:16 survives either way.
     min-width lets the flex line actually do the second one. */
  max-height: min(56vh, 460px); max-width: 100%; min-width: 0;
  border-radius: var(--radius-sm); box-shadow: 0 6px 20px rgba(22, 24, 29, 0.18);
}
.watch-arrow {
  display: grid; place-items: center; width: 38px; height: 38px; flex: none; padding: 0;
  border-radius: 50%; background: var(--card); color: var(--ink-soft);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.watch-arrow:hover:not(:disabled) { filter: none; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }

.watch-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line);
}
.watch-bar .thumb { font-size: 13px; padding: 7px 13px; }
.watch-count { margin-left: auto; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  .watch-stage { gap: 6px; }
  .watch-arrow { width: 32px; height: 32px; flex: none; }
}

/* ------------------------------------------------------------------ results */

.followers-note { max-width: 70ch; margin: -6px 0 22px; }
.breakdown-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px; margin: 8px 0 28px; }
.breakdown-block.wide { grid-column: 1 / -1; }
.breakdown-block.wide .bars li { grid-template-columns: minmax(0, 1fr) 220px 60px 56px; }
.breakdown-block h3 { margin: 0 0 8px; }
.breakdown-block .sub { margin: 0 0 8px; }
.bars { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.bars li { display: grid; grid-template-columns: minmax(0, 1fr) 90px 52px 56px; align-items: center; gap: 8px; font-size: 13px; }
/* What the numbers in this block are, on the block itself: an average is only
   safe to read if nobody has to be told twice that it is one. */
.bar-unit { font-weight: 400; font-size: 11.5px; color: var(--muted); }
/* How many reels are behind the average. Absent at one, because "1 reel" on
   every second row is noise, and the average of one reel is the reel. */
.bar-reels {
  justify-self: start; padding: 1px 6px; border-radius: 999px;
  background: var(--line); color: var(--muted);
  font-size: 10.5px; white-space: nowrap;
}
.bar-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 8px; border-radius: 999px; background: var(--line); overflow: hidden; }
.bar-fill { display: block; height: 100%; background: var(--brand-gradient); border-radius: 999px; }
.bar-n { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink-soft); }
.reels-table th.num, .reels-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.table-scroll { overflow-x: auto; }
.reels-table .reel-hook { min-width: 240px; }
.reels-table td.sub { white-space: nowrap; }
.reels-table th.num { white-space: nowrap; }
.reels-table .reel-hook a { color: var(--ink); text-decoration: none; }
.reels-table .reel-hook a:hover { color: var(--brand-ink); text-decoration: underline; }
.breakdown {
  width: 100%; border-collapse: collapse; font-size: 13px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
.breakdown td, .breakdown th { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; }
.breakdown tr:last-child td { border-bottom: none; }
.breakdown th { font-weight: 600; color: var(--muted); font-size: 12px; }
/* A sortable head is a button the whole way across, so the target is the
   column heading itself rather than a caret beside it. */
.th-sort {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 0; border: 0; background: none; cursor: pointer;
  font: inherit; color: inherit; text-align: inherit;
  /* The base button rule is a filled pill with a shadow. Everything it sets
     has to be undone here or a column heading comes out looking like a
     button someone forgot to style. */
  border-radius: 0; box-shadow: none;
}
.th-sort:hover:not(:disabled) { filter: none; }
.th-sort:active:not(:disabled) { transform: none; }
.th-sort:hover { color: var(--ink); }
.breakdown th.num .th-sort { flex-direction: row-reverse; }
.th-sort::after { content: ""; font-size: 9px; color: var(--brand-ink); }
/* A hint that the column sorts at all, faint and only under the pointer. */
.th-sort:hover::after { content: "\25BC"; color: var(--line-strong); }
.breakdown th[aria-sort="descending"] .th-sort::after { content: "\25BC"; }
.breakdown th[aria-sort="ascending"] .th-sort::after { content: "\25B2"; }

/* Debug */
.page-head h1 .ico { vertical-align: -3px; margin-right: 4px; color: var(--brand-ink); }
.report-card { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 30px; }
.report-card h3 { margin: 0 0 4px; }
.report-card .sub { margin: 0; max-width: 60ch; }
.report-card .button { flex: none; }
.facts { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 0; align-items: start; }
.facts > div { padding: 12px 14px; background: var(--card); border: 1px solid var(--line); border-radius: var(--radius-sm); }
.facts > div.wide { grid-column: 1 / -1; }
.facts dt { font-size: 12px; color: var(--muted); margin: 0 0 6px; }
.facts dd { margin: 0; font-size: 14px; }
.facts dd .sub { display: block; margin: 6px 0 0; }
.job-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 5px 16px; font-size: 13px; }
.job-list li { display: flex; align-items: center; gap: 8px; }
.job-list .pill { min-width: 96px; justify-content: center; white-space: nowrap; }
.pill.ok { background: var(--ok-wash); border-color: var(--ok-line); color: var(--ok); }
.breakdown.log td { vertical-align: top; }
.breakdown.log .when { white-space: nowrap; color: var(--muted); }
.breakdown.log .muted { display: block; font-size: 12.5px; }
code.err { font-size: 12px; white-space: pre-wrap; word-break: break-word; color: var(--error); }
.modal-report .modal-field { display: flex; flex-direction: column; gap: 6px; font-size: 13.5px; }
.modal-report textarea { font-size: 14px; }
.check-line { display: flex; gap: 9px; align-items: flex-start; font-size: 13.5px; margin: 12px 0 8px; }
.check-line input { width: auto; margin-top: 4px; accent-color: var(--brand); }
.modal-report .sub { margin: 0; font-size: 12.5px; }

.plan-list .card form + form { margin-top: 8px; }
.plan-list .card .button, .plan-list .card button { width: 100%; }
.tos-check { display: flex; gap: 9px; align-items: flex-start; font-size: 13px; color: var(--muted); text-align: left; }
.tos-check input { margin-top: 3px; width: auto; accent-color: var(--brand); }

.legal-footer {
  max-width: 940px; margin: 0 auto; padding: 24px; display: flex; gap: 16px;
  font-size: 12.5px; color: var(--muted); border-top: 1px solid var(--line);
}
.legal-footer a { color: var(--muted); }

/* ------------------------------------------------------------------ narrow */

@media (max-width: 760px) {
  .preview-panel { grid-template-columns: 1fr; }
  .totals-grid { grid-template-columns: repeat(2, 1fr); }
  .breakdown-cols { grid-template-columns: 1fr; }
  .two-cards { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar {
    position: static; height: auto; flex-direction: row; align-items: center;
    flex-wrap: wrap; gap: 10px; border-right: 0; border-bottom: 1px solid var(--line);
  }
  .nav { flex-direction: row; order: 3; flex-basis: 100%; overflow-x: auto; }
  .nav a { white-space: nowrap; padding: 7px 10px; }
  .account-menu { margin-top: 0; margin-left: auto; width: auto; }
  .account-pill { width: auto; }
  .account-drop { bottom: auto; top: calc(100% + 6px); left: auto; }
  .page { padding: 22px 16px 72px; }
  .account-menu { margin-left: auto; }
  /* "Add a video / Upload a file, or ..." wraps the title itself into two
     lines at this width. The explainer is the half that can go. */
  .add-panel > summary { white-space: nowrap; }
  .add-panel > summary .sub { display: none; }
  .source-panel > summary { flex-wrap: wrap; }
  .source-actions { flex-basis: 100%; margin-left: 62px; }
  .tomorrow-item { flex-wrap: wrap; }
  .tomorrow-meta { flex-basis: calc(100% - 62px); }
  .tomorrow-actions { flex-basis: 100%; margin-left: 62px; }
  .hook-text { white-space: normal; }
  .legal-footer { flex-wrap: wrap; gap: 12px; padding: 20px 16px; }
}

/* A reel that has already gone out. Dimmed like a skipped cell, because it
   genuinely cannot be made again - but labelled, never struck through, and
   the label says whether Hookshift posted it or she did. Downloading does NOT
   put a cell here (Ale, 2026-09-12: taking the file says nothing about where
   it went), so a downloaded cell keeps every control it had. */
.cell.done .frame { opacity: 0.45; }
.sub.done { color: var(--ink-soft); font-weight: 600; }
.downloaded-note { white-space: nowrap; }

/* Subtitles sit with the variant axes, on one line - it is an axis, not a
   section (Ale, 2026-09-12: "this does NOT have to take so much screen real
   estate"). */
.subtitle-row { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin: 0 0 14px; }
.subtitle-q { font-weight: 600; font-size: 14px; }
.subtitle-row .choices { display: flex; gap: 12px; }
.subtitle-row .choices label { display: inline-flex; align-items: center; gap: 5px; font-size: 13.5px; }
.subtitle-row .sub { margin: 0; }

/* Rename in place: the pencil only earns its space next to the name. */
.source-title h3 { display: inline-flex; align-items: center; gap: 8px; }
.thumb.rename { padding: 3px 6px; opacity: 0; }
.source-panel:hover .thumb.rename, .thumb.rename:focus { opacity: 1; }
.rename-form { display: flex; align-items: center; gap: 6px; }
.rename-form input { padding: 5px 9px; font-size: 15px; min-width: 260px; }

/* Why the slider above appears to do nothing. */
.pinned-note { color: var(--ink-soft); }

/* Posted reels to reuse: best first, numbers on the still, and the whole list
   boxed so it cannot eat the page it is one option on. */
.reels-scroll {
  max-height: 340px; overflow-y: auto; padding-right: 4px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg);
}
.reels-scroll .reels-grid { padding: 10px; }
.reel-thumb { position: relative; }
.reel-thumb img, .reel-thumb-placeholder {
  display: block; width: 100%; aspect-ratio: 9 / 16; object-fit: cover;
  border-radius: var(--radius-sm); background: var(--line);
}
/* Flush to the thumbnail on every side, so it reads as part of the still
   rather than a second rounded rectangle floating on top of it (Ale,
   2026-09-12: "i don't like that smaller rounded dark gray rectangle ... make
   it be the same size as the thumbnail so i don't see a weird video border").
   Same radius as the image, and only the bottom corners are rounded. */
.reel-stats {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column; gap: 1px;
  font-size: 11.5px; font-weight: 600; line-height: 1.3; color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.72));
  padding: 20px 8px 7px;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
}
.reel-views { font-size: 12.5px; }
.reel-comments { font-weight: 500; opacity: 0.92; }
/* The one that cleared the comment bar says so louder than the rest. */
.reel-stats .strong { color: var(--brand-soft); }

/* The chip bar is three separate decisions, so it reads as three. Ale,
   2026-09-12: "visually separate the three things: fonts, styles, and
   subtitles. and give that block a small title". */
.chip-bar-title {
  margin: 0 0 10px; font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft);
  display: flex; align-items: baseline; gap: 10px;
}
.chip-bar-title .sub { text-transform: none; letter-spacing: 0; font-weight: 400; }
.chip-group { display: flex; align-items: flex-start; gap: 12px; padding: 9px 0; }
.chip-group + .chip-group { border-top: 1px dashed var(--line); }
.chip-group-label {
  flex: none; width: 62px; padding-top: 5px;
  font-size: 11.5px; font-weight: 600; color: var(--muted);
}
/* The subtitles chip is a button, not a link like the filter chips, so it
   needs the chip look spelled out rather than inherited from <a>. */
.sub-chip {
  background: var(--card); cursor: pointer;
  font-family: inherit; font-size: 12.5px; font-weight: 500; line-height: 1;
}
.chip-swatch.subs {
  font-size: 10px; font-weight: 700; letter-spacing: 0.04em;
  color: var(--ink); background: var(--line);
}
.sub-chip.on .chip-swatch.subs { color: var(--card); background: var(--ink); }

/* Variants fold, same shape as the hooks fold above it. */
/* The rule belongs to the fold, above its heading - it used to sit on the
   .variants section inside it, which drew the line UNDER "Variants" and made
   it look like the separator for whatever came next (Ale, 2026-09-12). */
.variants-fold {
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line);
}
.variants-fold > summary { cursor: pointer; }
.variants-fold[open] > summary { margin-bottom: 10px; }

/* A reel with no hook: the footage and its subtitles, nothing written over
   it. Named rather than left blank, and dimmed so it does not read as a hook
   that failed to load. */
.hook-text.no-hook { color: var(--muted); font-style: italic; }

/* Under the player, where a mis-heard word is being looked at right now -
   with room to breathe, rather than tucked against the video (Ale,
   2026-09-13: "the subtitles text is too close to the video preview"). */
.modal-body .watch-note { margin: 20px 0 0; text-align: center; font-size: 13px; color: var(--muted); }

/* ------------------------------------------------------------------ tooltips */

/* Tooltips are ONE element on <body>, positioned by ui.js - not a ::after on
   the thing they belong to. A pseudo-element lives inside its host, so any
   ancestor with overflow: hidden cuts it off, and three separate times one
   did: .hook-text (clipping for its ellipsis), .source-panel (clipping for
   its rounded corners), and the reels grid. Ale, 2026-09-12: "3 times the
   same bug is a stroooong signal it should be fixed for good." Nothing can
   clip a child of <body>. */
.tip {
  position: fixed; z-index: 200; pointer-events: none;
  max-width: min(380px, 60vw); width: max-content;
  padding: 8px 11px; border-radius: var(--radius-sm);
  background: var(--card); color: var(--ink);
  border: 1px solid var(--line-strong);
  box-shadow: 0 10px 28px rgba(22, 24, 29, 0.16);
  font: 400 12.5px/1.45 var(--sans); text-align: left;
  white-space: pre-wrap; text-transform: none; letter-spacing: 0;
  opacity: 0; transform: translateY(3px);
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.tip.on { opacity: 1; transform: translateY(0); }

/* A hook is one line in the row and all of it in the tip. */
.hook-text[data-tip] { cursor: help; }

/* Post it now: the one button here that puts something on Instagram. */
.thumb.go { color: var(--brand-ink); box-shadow: inset 0 0 0 1px var(--brand-line); }
.thumb.go:hover { background: var(--brand-wash); box-shadow: inset 0 0 0 1px var(--brand); }

/* The hook's row: the wrapper carries the tooltip (it clips nothing), the
   inner span does the truncating. Both needed - putting them on one element
   means the ellipsis clips the tooltip too. */
.hook-line { display: block; min-width: 0; max-width: 100%; }
.hook-line[data-tip] { cursor: help; }
.hook-line .hook-text { display: block; }

/* Nothing on these screens has a Save button any more - changing something
   saves it - so the note that says whether that has happened does the work a
   button used to. */
.saved-note.unsaved { color: var(--brand-ink); }

/* A field that cannot be accepted says so where it is, not on another page.
   Generic on purpose - any form can use both. */
.field-error { margin: 6px 0 0; font-size: 13px; color: var(--error); flex-basis: 100%; }
input.bad, textarea.bad, select.bad {
  border-color: var(--error);
  box-shadow: 0 0 0 3px var(--error-wash);
}

/* Said beside the form that saved itself, not as a toast - a toast per field
   would be a running commentary on typing. */
.autosave-note { margin-left: 10px; }

/* The native time control drew its own clock button and spinners in the OS's
   style, which matched nothing else here. Ale, 2026-09-12: "the time picker
   in the settings is ugly ... i'd imagine people actually type in these
   fields, they don't select." So the picker chrome goes and the field is the
   same box as every other input - still a real time field, so typing 1800
   still works and a phone still offers its own keypad. */
input[type="time"] {
  font-variant-numeric: tabular-nums;
  width: auto; min-width: 0;
  padding: 6px 9px;
  text-align: center;
}
input[type="time"]::-webkit-calendar-picker-indicator { display: none; }
input[type="time"]::-webkit-inner-spin-button,
input[type="time"]::-webkit-outer-spin-button { display: none; }

/* A video whose file came back from Instagram rather than off her own disk.
   Red so it is noticed, and a warning icon so it invites the hover that
   explains it. */
.low-quality {
  color: var(--error); font-weight: 600; cursor: help;
  white-space: nowrap;
}
.low-quality .ico { vertical-align: -2px; margin-right: 2px; }

/* Delete: red enough to be read as delete, quiet enough not to shout from a
   row of videos. */
.thumb.danger-quiet { color: var(--error); }
.thumb.danger-quiet:hover:not(:disabled) {
  color: var(--error); background: var(--error-wash);
  box-shadow: inset 0 0 0 1px var(--error);
}
.source-actions { display: flex; align-items: center; gap: 6px; }
.source-actions .thumb.on {
  background: var(--ok-wash); box-shadow: inset 0 0 0 1px var(--ok); color: var(--ok);
}
.source-actions form { margin: 0; display: contents; }
.pill.warn .ico { vertical-align: -1px; }
