/* Scrolling Stories components. Classes use the `ss-` prefix and read only tokens.css.
   Spec and usage rules: docs/design-system/components.md */

/* ---- Base ---- */
.ss-root {
  background: var(--ss-paper);
  color: var(--ss-ink);
  font: var(--ss-weight-regular) var(--ss-text-md) / var(--ss-leading-ui) var(--ss-font-ui);
  -webkit-font-smoothing: antialiased;
}
.ss-root *, .ss-root *::before, .ss-root *::after { box-sizing: border-box; }
.ss-root :focus-visible { outline: 2px solid var(--ss-focus); outline-offset: 2px; }
/* A control may be smaller to look at than it is to hit. These grow the box that answers a
   press to --ss-touch without moving anything, and only up and down: controls in a row sit side
   by side, so a wider one would steal its neighbour's press. Each of them keeps room above and
   below for the overshoot; a chip row widens its own row gap to make it. */
@media (pointer: coarse) {
  .ss-root .ss-chip,
  .ss-root .ss-segmented > *,
  .ss-root button.ss-tag,
  .ss-root .ss-switch,
  .ss-root .ss-setting__help,
  .ss-root .ss-setting__reset { position: relative; }
  .ss-root .ss-chip::before,
  .ss-root .ss-segmented > *::before,
  .ss-root button.ss-tag::before,
  .ss-root .ss-switch::before,
  .ss-root .ss-setting__help::before,
  .ss-root .ss-setting__reset::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: var(--ss-touch);
    transform: translateY(-50%);
  }
  /* The switch is the one that is also too narrow; nothing sits within 4px of it. */
  .ss-root .ss-switch::before { left: -4px; right: -4px; }
}
.ss-root a { color: var(--ss-forest); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--ss-forest) 35%, transparent); text-underline-offset: 3px; }
.ss-root a:hover { color: var(--ss-forest-hover); text-decoration-color: currentColor; }
.ss-vh { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* A component class that sets `display` outranks the user agent's rule for [hidden], so an
   `.ss-inline-error[hidden]` still takes up space. Restore what the attribute promises. */
.ss-root [hidden] { display: none !important; }
/* The reader's skip link, on every shell: off-screen until focused, then a real control. */
.ss-skip { position: absolute; left: var(--ss-space-2); top: -100px; z-index: var(--ss-z-toast); padding: var(--ss-space-2) var(--ss-space-4);
  border-radius: var(--ss-radius-md); background: var(--ss-print); color: var(--ss-ink); box-shadow: var(--ss-shadow-menu); }
.ss-skip:focus { top: var(--ss-space-2); }

/* ---- Type ---- */
.ss-title-xl, .ss-title-l, .ss-title-m, .ss-title-s, .ss-title-xs {
  font-family: var(--ss-font-display); font-weight: var(--ss-weight-medium);
  color: var(--ss-ink-heading); line-height: var(--ss-leading-tight); margin: 0;
}
.ss-title-xl { font-size: var(--ss-display-xl); letter-spacing: -0.01em; }
.ss-title-l  { font-size: var(--ss-display-l); letter-spacing: -0.01em; }
.ss-title-m  { font-size: var(--ss-display-m); }
.ss-title-s  { font-size: var(--ss-display-s); line-height: 1.2; }
.ss-title-xs { font-size: var(--ss-display-xs); line-height: 1.25; }
.ss-chapter  { font-family: var(--ss-font-display); font-style: italic; color: var(--ss-ink-heading); }
.ss-label    { font-size: var(--ss-text-xs); font-weight: var(--ss-weight-semibold); color: var(--ss-ink-2); }
.ss-hint     { font-size: var(--ss-text-xs); color: var(--ss-ink-3); }
.ss-meta     { font-size: var(--ss-text-xs); color: var(--ss-ink-3); }
.ss-eyebrow  { font-size: var(--ss-text-xs); font-weight: var(--ss-weight-semibold); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ss-forest); }
.ss-code     { font-family: var(--ss-font-mono); font-size: var(--ss-text-sm); }

/* ---- Buttons ---- */
.ss-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--ss-space-2);
  height: var(--ss-control-md); padding: 0 var(--ss-space-4);
  border: 1px solid var(--ss-line-control); border-radius: var(--ss-radius-md);
  background: var(--ss-print); color: var(--ss-ink);
  font: var(--ss-weight-medium) var(--ss-text-sm) / 1 var(--ss-font-ui);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background var(--ss-duration-fast) var(--ss-ease), border-color var(--ss-duration-fast) var(--ss-ease);
}
.ss-root a.ss-btn { text-decoration: none; color: var(--ss-ink); }
.ss-btn:hover { background: var(--ss-fill); }
.ss-btn svg { width: var(--ss-icon-sm); height: var(--ss-icon-sm); flex-shrink: 0; }
.ss-btn--primary, .ss-root a.ss-btn--primary { background: var(--ss-forest); border-color: var(--ss-forest); color: var(--ss-white); font-weight: var(--ss-weight-semibold); }
.ss-btn--primary:hover { background: var(--ss-forest-hover); border-color: var(--ss-forest-hover); }
.ss-btn--primary:active { background: var(--ss-forest-active); }
.ss-btn--ghost, .ss-root a.ss-btn--ghost { background: transparent; border-color: transparent; color: var(--ss-ink-2); }
.ss-btn--ghost:hover { background: var(--ss-fill); color: var(--ss-ink); }
.ss-btn--danger, .ss-root a.ss-btn--danger { background: transparent; border-color: transparent; color: var(--ss-terracotta-text); }
.ss-btn--danger:hover { background: var(--ss-terracotta-tint); }
.ss-btn--danger-fill { background: var(--ss-terracotta-text); border-color: var(--ss-terracotta-text); color: var(--ss-white); font-weight: var(--ss-weight-semibold); }
/* Sign-in providers (#229): the fill is the provider's own colour, from tokens.css — Google's
   white button with the coloured G and a grey border, Apple's black and Facebook's blue with
   the mark inverted to white. Hover darkens the brand colour a step instead of swapping to
   --ss-fill. The label keeps 4.5:1 on each (tests/unit/test_design_tokens.py). */
.ss-btn--google, .ss-root a.ss-btn--google { background: var(--ss-brand-google); border-color: var(--ss-line-control); color: var(--ss-ink); }
.ss-btn--google:hover { background: color-mix(in srgb, var(--ss-brand-google) 94%, var(--ss-ink)); }
.ss-btn--apple, .ss-root a.ss-btn--apple { background: var(--ss-brand-apple); border-color: var(--ss-brand-apple); color: var(--ss-white); }
.ss-btn--apple:hover { background: color-mix(in srgb, var(--ss-brand-apple) 86%, var(--ss-white)); }
.ss-btn--facebook, .ss-root a.ss-btn--facebook { background: var(--ss-brand-facebook); border-color: var(--ss-brand-facebook); color: var(--ss-white); }
.ss-btn--facebook:hover { background: color-mix(in srgb, var(--ss-brand-facebook) 88%, var(--ss-ink)); }
.ss-btn--apple .ss-provider__mark, .ss-btn--facebook .ss-provider__mark { filter: brightness(0) invert(1); }
.ss-btn--sm { height: var(--ss-control-sm); padding: 0 var(--ss-space-3); }
.ss-btn--lg { height: var(--ss-control-lg); padding: 0 var(--ss-space-6); font-size: var(--ss-text-md); }
.ss-btn--icon { width: var(--ss-control-md); padding: 0; border-color: transparent; background: transparent; color: var(--ss-ink-2); }
.ss-btn--icon.ss-btn--sm { width: var(--ss-control-sm); }
.ss-btn[disabled], .ss-btn[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
@media (pointer: coarse) { .ss-btn, .ss-btn--icon { min-height: var(--ss-touch); min-width: var(--ss-touch); } }

/* ---- Fields ---- */
.ss-field { display: flex; flex-direction: column; gap: var(--ss-space-1); }
.ss-input, .ss-select, .ss-textarea {
  width: 100%; min-height: var(--ss-control-md); padding: 0 var(--ss-space-3);
  border: 1px solid var(--ss-line-control); border-radius: var(--ss-radius-md);
  background: var(--ss-print); color: var(--ss-ink);
  font: var(--ss-text-field) / var(--ss-leading-ui) var(--ss-font-ui);
}
.ss-textarea { padding: var(--ss-space-2) var(--ss-space-3); min-height: 5rem; resize: vertical; }
.ss-input::placeholder, .ss-textarea::placeholder { color: var(--ss-ink-3); }
.ss-select { appearance: none; padding-right: var(--ss-space-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235a5448' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; }
.ss-field--error .ss-input, .ss-field--error .ss-textarea { border-color: var(--ss-terracotta-text); }
.ss-field__error { font-size: var(--ss-text-xs); color: var(--ss-terracotta-text); }
/* Catches a field a surface styles itself, or one a script writes before it is given
   `.ss-input`. Checkboxes and the rest are left alone: nothing is typed into them. */
@media (pointer: coarse) {
  .ss-root input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"]),
  .ss-root select,
  .ss-root textarea { font-size: var(--ss-text-field); }
  /* A 34px box has to be hit before it can be typed in, and a slider's 16px track more so —
     hence no `[type="range"]` here, unlike the font size above. */
  .ss-input, .ss-select,
  .ss-root input:not([type="checkbox"], [type="radio"], [type="file"], [type="color"]),
  .ss-root select { min-height: var(--ss-touch); }
}

/* Switch: every on/off setting. Markup: <button role="switch" aria-checked="true" class="ss-switch"> */
.ss-switch { position: relative; width: 38px; height: 22px; border-radius: var(--ss-radius-round); border: 1px solid var(--ss-line-control); background: var(--ss-fill); cursor: pointer; padding: 0; flex-shrink: 0; }
.ss-switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: var(--ss-white); box-shadow: var(--ss-shadow-raised); transition: transform var(--ss-duration-fast) var(--ss-ease); }
.ss-switch[aria-checked="true"] { background: var(--ss-forest); border-color: var(--ss-forest); }
.ss-switch[aria-checked="true"]::after { transform: translateX(16px); }

/* ---- Choice ---- */
/* Chips: pick one named preset from a set (motion, text style). role="radiogroup" + role="radio". */
.ss-chips { display: flex; flex-wrap: wrap; gap: var(--ss-space-2); }
/* 7px of hit area above and below each chip, so two rows of them need 14px between. */
@media (pointer: coarse) { .ss-chips { row-gap: 14px; align-items: center; min-height: var(--ss-touch); } }
.ss-chip { display: inline-flex; align-items: center; gap: var(--ss-space-1); height: 30px; padding: 0 var(--ss-space-3);
  border: 1px solid var(--ss-line-control); border-radius: var(--ss-radius-md); background: var(--ss-print);
  font-size: var(--ss-text-sm); color: var(--ss-ink); cursor: pointer; }
/* A chip is on whichever way it says so: one of a set (`aria-checked`) or a toggle on its own. */
.ss-chip[aria-checked="true"], .ss-chip[aria-pressed="true"] {
  background: var(--ss-ink); border-color: var(--ss-ink); color: var(--ss-white); }
.ss-chip__default { color: var(--ss-ink-3); }
.ss-chip[aria-checked="true"] .ss-chip__default { color: color-mix(in srgb, var(--ss-white) 70%, transparent); }
/* Segmented: switch between 2–4 views or modes. role="tablist" or radiogroup. */
.ss-segmented { display: inline-flex; gap: 2px; padding: 3px; border-radius: 9px; background: var(--ss-fill); }
.ss-segmented > * { padding: 5px var(--ss-space-4); border-radius: 7px; border: 0; background: transparent; font: var(--ss-weight-medium) var(--ss-text-sm) / 1.4 var(--ss-font-ui); color: var(--ss-ink-2); cursor: pointer; }
.ss-segmented > [aria-selected="true"], .ss-segmented > [aria-checked="true"] { background: var(--ss-print); color: var(--ss-ink); box-shadow: var(--ss-shadow-raised); }

/* ---- Status tags ---- */
.ss-tag { display: inline-flex; align-items: center; gap: 6px; height: 24px; padding: 0 9px; border-radius: var(--ss-radius-sm);
  font-size: var(--ss-text-xs); font-weight: var(--ss-weight-medium); white-space: nowrap; background: var(--ss-fill); color: var(--ss-ink-2); }
.ss-tag--dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.ss-tag--published { background: var(--ss-moss-tint); color: var(--ss-moss); }
.ss-tag--scheduled, .ss-tag--attention { background: var(--ss-ochre-tint); color: var(--ss-ochre-text); }
.ss-tag--private, .ss-tag--members { background: var(--ss-heather-tint); color: var(--ss-heather); }
.ss-tag--featured { background: var(--ss-forest-tint); color: var(--ss-forest); }
.ss-tag--error { background: var(--ss-terracotta-tint); color: var(--ss-terracotta-text); }

/* A small unread count beside a navigation item (PCB-23). The number is text, not a dot:
   the bell has to say how many without a screen reader having to read a label that repeats it. */
.ss-count { display: inline-flex; align-items: center; justify-content: center; min-width: 20px; height: 20px;
  padding: 0 6px; border-radius: 10px; background: var(--ss-forest); color: var(--ss-print);
  font-size: var(--ss-text-xs); font-weight: var(--ss-weight-medium); line-height: 1; }

/* ---- Surfaces ---- */
.ss-card { background: var(--ss-print); border: 1px solid var(--ss-line); border-radius: var(--ss-radius-lg); }
.ss-card--pad { padding: var(--ss-space-6); }
.ss-divider { height: 1px; background: var(--ss-line); border: 0; margin: 0; }
/* A photo shown on a light surface. Never on the stage or in the reader. */
.ss-print { display: inline-block; background: var(--ss-white); padding: 3px; box-shadow: var(--ss-shadow-print); }
.ss-print > img { display: block; object-fit: cover; }
.ss-placeholder { display: flex; align-items: center; justify-content: center; gap: var(--ss-space-2); background: var(--ss-fill); color: var(--ss-ink-2); font-size: var(--ss-text-xs); }

/* ---- Menus, dialogs, sheets ---- */
.ss-menu { background: var(--ss-print); border: 1px solid var(--ss-line); border-radius: var(--ss-radius-lg); box-shadow: var(--ss-shadow-menu); padding: var(--ss-space-1); min-width: 200px; z-index: var(--ss-z-menu); }
.ss-menu__item { display: flex; align-items: center; gap: var(--ss-space-3); width: 100%; min-height: 36px; padding: 0 var(--ss-space-3); border: 0; border-radius: 6px; background: transparent; font: var(--ss-text-md) var(--ss-font-ui); color: var(--ss-ink); text-align: left; cursor: pointer; }
.ss-menu__item:hover, .ss-menu__item:focus-visible { background: var(--ss-fill); }
@media (pointer: coarse) { .ss-menu__item { min-height: var(--ss-touch); } }
.ss-root a.ss-menu__item { color: var(--ss-ink); text-decoration: none; }
.ss-menu__item--danger { color: var(--ss-terracotta-text); }
.ss-menu__desc { display: block; font-size: var(--ss-text-xs); color: var(--ss-ink-3); }
.ss-scrim { position: fixed; inset: 0; background: var(--ss-scrim); z-index: var(--ss-z-dialog); display: flex; align-items: center; justify-content: center; padding: var(--ss-space-4); }
.ss-dialog { width: min(440px, 100%); background: var(--ss-print); border-radius: var(--ss-radius-lg); box-shadow: var(--ss-shadow-dialog); padding: var(--ss-space-6); }
.ss-dialog__title { font: var(--ss-weight-semibold) var(--ss-text-lg) / 1.3 var(--ss-font-ui); margin: 0 0 var(--ss-space-2); }
.ss-dialog__body { color: var(--ss-ink-2); margin: 0 0 var(--ss-space-6); }
.ss-dialog__actions { display: flex; justify-content: flex-end; gap: var(--ss-space-2); }
.ss-sheet { position: fixed; left: 0; right: 0; bottom: 0; max-height: 85dvh; overflow: auto; background: var(--ss-print); border-radius: var(--ss-radius-xl) var(--ss-radius-xl) 0 0; box-shadow: var(--ss-shadow-dialog); z-index: var(--ss-z-sheet); }
.ss-sheet__grip { width: 36px; height: 4px; border-radius: 2px; background: var(--ss-line-control); margin: var(--ss-space-2) auto; }

/* ---- Panel (a dialog a page fills itself) and popover menus ---- */
/* A dialog whose body scrolls, so a long list is never cut off at the bottom of the window
   with nothing on screen to say more follows. */
.ss-panel {
  display: flex;
  flex-direction: column;
  width: min(760px, 100%);
  max-height: min(86dvh, 900px);
  background: var(--ss-print);
  border-radius: var(--ss-radius-lg);
  box-shadow: var(--ss-shadow-dialog);
}
.ss-panel__head {
  display: flex;
  align-items: center;
  gap: var(--ss-space-3);
  padding: var(--ss-space-4) var(--ss-space-5);
  border-bottom: 1px solid var(--ss-line);
}
.ss-panel__body {
  flex: 1 1 auto;
  overflow: auto;
  padding: var(--ss-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--ss-space-6);
}
.ss-panel__foot {
  display: flex;
  align-items: center;
  gap: var(--ss-space-3);
  padding: var(--ss-space-4) var(--ss-space-5);
  border-top: 1px solid var(--ss-line);
}
.ss-panel > .ss-inline-error { padding: 0 var(--ss-space-5) var(--ss-space-4); }

/* A "More" menu. `ssMenu` puts it on the body and sets left/top, so it is never clipped by a
   card that hides its own overflow. It is opened from a control, so it has to outrank whatever
   that control is on: at --ss-z-menu it was drawn behind the beats editor's panel, which is a
   sheet, and the beat's ⋯ menu could not be seen or pressed on a phone at all. */
.ss-menu--pop { position: absolute; z-index: var(--ss-z-dialog); }
/* On a phone a panel is a bottom sheet, as the inspector and the library are
   (components.md § Menus, dialogs, and sheets). `:has` keeps this off the confirm dialogs,
   which share the scrim but stay centred. */
@media (max-width: 599px) {
  .ss-scrim:has(.ss-panel) { align-items: flex-end; padding: 0; }
  .ss-panel {
    width: 100%;
    max-height: 92dvh;
    border-radius: var(--ss-radius-xl) var(--ss-radius-xl) 0 0;
    padding-bottom: env(safe-area-inset-bottom);
  }
}
/* #446: a phone's picker, as its own sheet over the panel (`ssPickerSheet`); each entry a full target. */
.ss-panel--picker > .ss-sheet__grip { flex-shrink: 0; }
.ss-panel__title { margin: 0; font: var(--ss-weight-semibold) var(--ss-text-lg) / 1.3 var(--ss-font-ui); color: var(--ss-ink); }
.ss-panel--picker .ss-panel__body { padding: var(--ss-space-2); gap: 2px; }
.ss-panel--picker .ss-menu__item { min-height: var(--ss-touch); border-radius: var(--ss-radius-md); }
.ss-panel--picker .ss-menu__name { font-weight: var(--ss-weight-medium); }
.ss-panel--picker .ss-menu__desc { color: var(--ss-ink-2); }
/* A touch screen keeps :hover on whatever the finger last touched, which opened the sheet. */
@media (hover: none) {
  .ss-panel--picker .ss-menu__item:hover:not([aria-checked="true"], :focus-visible) { background: transparent; }
}

/* ---- Feedback ---- */
.ss-toast-region { position: fixed; left: 50%; bottom: calc(var(--ss-space-6) + env(safe-area-inset-bottom)); transform: translateX(-50%); z-index: var(--ss-z-toast); display: flex; flex-direction: column; gap: var(--ss-space-2); width: min(520px, calc(100vw - 2rem)); }
@media (max-width: 959px) { .ss-toast-region { bottom: calc(var(--ss-tabbar-h) + var(--ss-space-3) + env(safe-area-inset-bottom)); } }
.ss-toast { display: flex; align-items: center; gap: var(--ss-space-3); padding: var(--ss-space-3) var(--ss-space-4); border-radius: var(--ss-radius-md); background: var(--ss-ink); color: var(--ss-ink-on-dark); box-shadow: var(--ss-shadow-menu); font-size: var(--ss-text-sm); }
.ss-toast__action { margin-left: auto; background: none; border: 0; color: var(--ss-focus-on-dark); font: var(--ss-weight-semibold) var(--ss-text-sm) var(--ss-font-ui); cursor: pointer; }
/* Undo is often the only way back, so it is a full target; the card tightens to pay for it. */
@media (pointer: coarse) {
  .ss-toast { padding-block: var(--ss-space-1); }
  .ss-toast__action { min-height: var(--ss-touch); min-width: var(--ss-touch); padding: 0 var(--ss-space-2); }
}
.ss-banner { display: flex; align-items: center; gap: var(--ss-space-3); padding: var(--ss-space-3) var(--ss-space-4); font-size: var(--ss-text-sm); border-bottom: 1px solid var(--ss-line); }
.ss-banner--info { background: var(--ss-forest-tint); }
.ss-banner--attention { background: var(--ss-ochre-tint); }
.ss-banner--blocked { background: var(--ss-terracotta-tint); }
.ss-banner__actions { margin-left: auto; display: flex; gap: var(--ss-space-2); }
.ss-inline-error { display: flex; gap: var(--ss-space-2); align-items: flex-start; font-size: var(--ss-text-sm); color: var(--ss-terracotta-text); }
.ss-empty { text-align: center; padding: var(--ss-space-12) var(--ss-space-6); }
.ss-empty__title { font-family: var(--ss-font-display); font-size: var(--ss-display-s); color: var(--ss-ink-heading); margin: 0 0 var(--ss-space-2); }
.ss-empty__body { color: var(--ss-ink-2); margin: 0 auto var(--ss-space-4); max-width: 36ch; }
/* Two buttons in a centred empty state: laid out by whitespace they touch once they wrap. */
.ss-empty__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--ss-space-2); }
/* #642: opt-in soft lines in an empty state's padding, off both sides of the screen. Never stop dots or pins. */
.ss-lines { --ss-lines-band: url("../branding/lines-band.5c55a8b7c2ed.svg"); isolation: isolate; padding-block: var(--ss-space-12); }
.ss-lines::before,
.ss-lines::after {
  content: "";
  /* Block, or the static position of the lower line is the end of the last line box, not below it. */
  display: block;
  /* With no positioned ancestor, left and right 0 meet the viewport's edges; 100vw would add a scrollbar. */
  position: absolute;
  left: 0;
  right: 0;
  height: var(--ss-space-12);
  z-index: -1;
  pointer-events: none;
  background: var(--ss-line);
  -webkit-mask: var(--ss-lines-band) center / auto 100% repeat-x;
  mask: var(--ss-lines-band) center / auto 100% repeat-x;
}
.ss-lines::before { margin-top: calc(-1 * var(--ss-space-12)); }
.ss-lines::after { transform: rotate(180deg); }
/* #677: a photograph veiled in paper around one clear window, shared by sign-in and the home masthead. The page gives
   `.ss-veil` its position (fixed or absolute) and the window's `--ss-win-w/h/x/y`; the veil is not a token, as a new one
   forces a renderer rebuild. Bottom to top: photograph, veil, dotted lines, window. */
.ss-veil { inset: 0; overflow: hidden; z-index: 0; container-type: size; }
.ss-veil__photo { position: relative; z-index: 0; width: 100%; height: 100%; object-fit: cover; }
.ss-veil::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: color-mix(in srgb, var(--ss-paper) 66%, transparent);
}
/* `--ss-veil-keep` is a second mask layer: a page sets it to clear the lines from where its words sit. */
.ss-veil::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--ss-line-control);
  -webkit-mask: url("../branding/lines-dotted.5b4f6c03ea3c.svg") center / cover no-repeat, var(--ss-veil-keep, linear-gradient(var(--ss-paper), var(--ss-paper)));
  -webkit-mask-composite: source-in;
  mask: url("../branding/lines-dotted.5b4f6c03ea3c.svg") center / cover no-repeat, var(--ss-veil-keep, linear-gradient(var(--ss-paper), var(--ss-paper)));
  mask-composite: intersect;
}
/* No hole in the veil: Chromium and WebKit size one differently, so the window holds its own copy of the photograph. */
.ss-veil__window {
  visibility: hidden; /* not display: none, or a box that appears later starts its pan out of step */
  position: absolute;
  z-index: 3;
  width: 0;
  height: 0;
  overflow: hidden;
  isolation: isolate;
  border-radius: var(--ss-radius-lg);
}
.ss-veil__window img { position: absolute; max-width: none; width: 100cqw; height: 100cqh; object-fit: cover; }
.ss-veil__window::after {
  content: "";
  position: absolute;
  inset: 0;
  border: 2.5px solid var(--ss-ink-heading);
  border-radius: inherit;
}
@media (min-width: 960px) {
  @supports (container-type: size) {
    .ss-veil__window { visibility: visible; left: var(--ss-win-x); top: var(--ss-win-y); width: var(--ss-win-w); height: var(--ss-win-h); }
    .ss-veil__window img { left: calc(-1 * var(--ss-win-x)); top: calc(-1 * var(--ss-win-y)); }
  }
}
@media (prefers-reduced-motion: no-preference) {
  /* Decoration on a photograph, so reduced motion stops both pans rather than slowing them. */
  .ss-veil img { animation: ss-veil-pan 60s var(--ss-ease) infinite alternate; transform-origin: 50% 50%; }
  @keyframes ss-veil-pan {
    from { transform: scale(1.06) translate3d(0, -1%, 0); }
    to { transform: scale(1.12) translate3d(0, 1%, 0); }
  }
}
/* No photograph: solid lines on paper, in a page that sets `position` on the element. A photograph covers this layer. */
.ss-veil-lines::before {
  content: "";
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--ss-line);
  -webkit-mask: url("../branding/lines.b19e80348293.svg") center / cover no-repeat, var(--ss-veil-keep, linear-gradient(var(--ss-paper), var(--ss-paper)));
  -webkit-mask-composite: source-in;
  mask: url("../branding/lines.b19e80348293.svg") center / cover no-repeat, var(--ss-veil-keep, linear-gradient(var(--ss-paper), var(--ss-paper)));
  mask-composite: intersect;
}
.ss-skeleton { background: linear-gradient(90deg, var(--ss-fill), var(--ss-fill-highlight), var(--ss-fill)); background-size: 200% 100%; animation: ss-shimmer 1.4s linear infinite; border-radius: var(--ss-radius-sm); }
@keyframes ss-shimmer { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .ss-skeleton { animation: none; } }

/* ---- Notice ---- */
/* A message inside a card or a panel. Not `.ss-banner`, which is a state of the whole page
   under the top bar, and not `.ss-inline-error`, which sits against one control. */
.ss-notice {
  padding: var(--ss-space-3) var(--ss-space-4);
  border-radius: var(--ss-radius-md);
  background: var(--ss-fill);
  color: var(--ss-ink);
  font-size: var(--ss-text-md);
}
.ss-notice--error { background: var(--ss-terracotta-tint); color: var(--ss-terracotta-text); }
.ss-notice--warning { background: var(--ss-ochre-tint); color: var(--ss-ochre-text); }
.ss-notice--success { background: var(--ss-moss-tint); color: var(--ss-moss); }
.ss-notice--info { background: var(--ss-forest-tint); color: var(--ss-forest); }

/* ---- Checklist (publish) ---- */
/* The button is `white-space: nowrap` and shrinkable, so on a narrow card it used to shrink
   under its own label and print it across the heading beside it. It asks for its own width and
   drops to a line of its own instead. */
.ss-check { display: flex; flex-wrap: wrap; gap: var(--ss-space-3); padding: var(--ss-space-3) 0; border-top: 1px solid var(--ss-line); }
.ss-check > .ss-btn { flex: 0 0 auto; margin-left: auto; }
.ss-check__mark { width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; flex-shrink: 0; background: var(--ss-moss-tint); color: var(--ss-moss); }
.ss-check--todo .ss-check__mark { background: var(--ss-ochre-tint); color: var(--ss-ochre-text); }
.ss-check--blocked .ss-check__mark { background: var(--ss-terracotta-tint); color: var(--ss-terracotta-text); }

/* ---- Timeline ---- */
.ss-tl { position: relative; background: var(--ss-print); }
.ss-tl__row { display: flex; align-items: center; margin-bottom: var(--ss-space-2); }
.ss-tl__label { width: 100px; flex-shrink: 0; font-size: var(--ss-text-xs); font-weight: var(--ss-weight-medium); color: var(--ss-ink-3); }
.ss-tl__track { position: relative; flex: 1; }
.ss-tl__beat { position: absolute; top: 0; height: 44px; display: flex; align-items: center; gap: 7px; padding: 0 6px; overflow: hidden;
  border-radius: var(--ss-radius-sm); border-left: 3px solid var(--ss-lane-photo); background: var(--ss-lane-photo-tint); font-size: var(--ss-text-xs); font-weight: var(--ss-weight-medium); }
.ss-tl__beat--text { border-left-color: var(--ss-lane-text); background: var(--ss-lane-text-tint); }
.ss-tl__beat img { width: 32px; height: 24px; object-fit: cover; border-radius: var(--ss-radius-xs); flex-shrink: 0; }
.ss-tl__text { position: absolute; top: 0; height: 26px; border-radius: 4px; border: 1px solid var(--ss-lane-text); background: var(--ss-white); font: italic var(--ss-text-xs) / 24px var(--ss-font-display); padding: 0 var(--ss-space-2); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.ss-tl__keyframe { position: absolute; top: 9px; width: 8px; height: 8px; background: var(--ss-lane-text); border: 1.5px solid var(--ss-white); transform: rotate(45deg); }
.ss-tl__wordchange { position: absolute; top: 3px; bottom: 3px; width: 2px; background: var(--ss-lane-text); }
.ss-tl__layer { position: absolute; top: 0; height: 24px; display: flex; align-items: center; gap: 5px; padding: 0 6px; border-radius: 4px; color: var(--ss-white); font-size: var(--ss-text-xs); overflow: hidden; white-space: nowrap; }
.ss-tl__layer--map { background: var(--ss-lane-map); }
.ss-tl__layer--overlay { background: var(--ss-lane-overlay); }
.ss-tl__layer--backdrop { background: var(--ss-lane-backdrop); }
.ss-tl__layer--advanced { background: var(--ss-lane-advanced); }
.ss-tl__chapter { position: absolute; top: 0; height: 20px; display: flex; align-items: center; gap: 5px; padding-left: 5px; border-left: 2px solid var(--ss-ochre); font: italic var(--ss-text-sm) var(--ss-font-display); color: var(--ss-ink-heading); white-space: nowrap; }
.ss-tl__playhead { position: absolute; top: 0; bottom: 0; width: 2px; background: var(--ss-terracotta); pointer-events: none; }
/* A timeline block is a button, and `aria-selected` is not valid on one: the selected beat
   marks itself with `aria-current`. */
.ss-tl [aria-current="true"] { outline: 2px solid var(--ss-forest); outline-offset: 1px; }

/* ---- Reader chrome (renderer) ---- */
.ss-chrome { background: var(--ss-chrome-bg); -webkit-backdrop-filter: blur(var(--ss-chrome-blur)); backdrop-filter: blur(var(--ss-chrome-blur)); color: var(--ss-ink-on-dark); border-radius: var(--ss-radius-xl); }
.ss-chrome--pill { border-radius: var(--ss-radius-round); height: 36px; display: inline-flex; align-items: center; gap: 6px; padding: 0 14px; font-size: var(--ss-text-sm); font-weight: var(--ss-weight-semibold); }
.ss-chrome :focus-visible, .ss-chrome [aria-current="true"] { outline-color: var(--ss-focus-on-dark); color: var(--ss-focus-on-dark); }
@media (prefers-reduced-transparency: reduce) { .ss-chrome { background: var(--ss-chrome-bg-strong); backdrop-filter: none; } }

/* ---- Icons ---- */
/* One symbol from static/icons/icons.svg, drawn by {% icon %}. The size comes from the
   tag's width/height; the colour is inherited, so an icon inside a primary button is white
   and one inside a danger menu item is terracotta with no extra rule. */
.ss-icon { display: inline-block; vertical-align: -0.15em; flex-shrink: 0; }

/* ---- Layout helpers ---- */
/* Two shells every v2 page is built inside. The rest of a page's layout belongs to its own
   surface stylesheet; these are only the things every surface agreed on. */
.ss-page { max-width: var(--ss-content-max); margin: 0 auto; padding: var(--ss-space-10) var(--ss-space-12); }
.ss-stack { display: flex; flex-direction: column; gap: var(--ss-space-4); }
.ss-row { display: flex; align-items: center; gap: var(--ss-space-2); }
.ss-spacer { flex: 1 1 auto; }
@media (max-width: 599px) { .ss-page { padding: var(--ss-space-6) var(--ss-space-4); } }

/* ---- Inspector controls (#440) ---- */
/* The eight row-value controls for the beat inspector, story panel and chapter panel.
   docs/design-system/inspector/README.md is the spec; static/js/editor/inspector-controls.js
   builds these as real elements. A set of short options never wraps at 390px. */
.ss-segmented > * { white-space: nowrap; }

.ss-picker {
  display: inline-flex; align-items: center; justify-content: space-between; gap: var(--ss-space-2);
  height: var(--ss-control-md); min-width: 156px; padding: 0 var(--ss-space-2) 0 var(--ss-space-3);
  border: 1px solid var(--ss-line-control); border-radius: var(--ss-radius-md);
  background: var(--ss-print); color: var(--ss-ink);
  font-size: var(--ss-text-md); font-family: var(--ss-font-ui); text-align: left; cursor: pointer;
}
.ss-picker__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ss-picker svg { flex-shrink: 0; color: var(--ss-ink-2); }
.ss-picker.is-inherited .ss-picker__value { color: var(--ss-ink-2); }
/* Inherited (#440): the chosen segment keeps its shape but drops the dark "own value" fill. */
.ss-segmented.is-inherited > [aria-checked="true"] { background: var(--ss-fill); color: var(--ss-ink-2); box-shadow: none; }
/* #482: one option that can't be chosen, its row's reason saying why; the rest stay live. */
.ss-segmented > [data-unavailable] { color: var(--ss-ink-3); cursor: default; text-decoration: line-through; }

/* A menu item carrying a description and/or a badge (the picker's popover, ssMenu's 3rd arg). */
.ss-menu__item--desc { align-items: flex-start; min-height: 0; padding: var(--ss-space-2) var(--ss-space-3); }
.ss-menu__text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ss-menu__name { display: flex; align-items: center; gap: var(--ss-space-2); color: var(--ss-ink); }
.ss-menu__item[aria-checked="true"] { background: var(--ss-forest-tint); }
/* #444: a disabled entry stays in the list so its line can say why; it looks and acts inert. */
.ss-menu__item[aria-disabled="true"] { cursor: default; }
.ss-menu__item[aria-disabled="true"]:hover { background: transparent; }
.ss-menu__item[aria-disabled="true"] .ss-menu__name { color: var(--ss-ink-3); }
.ss-menu__check { margin-left: auto; flex-shrink: 0; align-self: center; color: var(--ss-forest); }
/* #494: a colour's dot before its name, on a picker and in its entries. */
.ss-swatch { flex-shrink: 0; width: 14px; height: 14px; border-radius: var(--ss-radius-round);
  box-shadow: inset 0 0 0 1px var(--ss-line-control); }
/* #513: None is a slash through the dot, not an empty ring a white dot could pass for. */
.ss-swatch--none { background-image: linear-gradient(to top right,
  transparent calc(50% - 1.5px), var(--ss-ink-2) calc(50% - 1.5px),
  var(--ss-ink-2) calc(50% + 1.5px), transparent calc(50% + 1.5px)); }
.ss-picker .ss-swatch + .ss-picker__value { flex: 1 1 auto; }
.ss-menu__item--desc > .ss-swatch { margin-top: 3px; }
.ss-menu__title { padding: var(--ss-space-2) var(--ss-space-3) var(--ss-space-1); font-size: var(--ss-text-xs);
  font-weight: var(--ss-weight-semibold); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ss-ink-2); }
.ss-menu--picker { width: 344px; }
/* #442: a long list (26 looks) scrolls inside the popover rather than off the screen. */
.ss-menu--picker { max-height: min(26rem, calc(50vh - 3rem)); overflow-y: auto; }

.ss-slider { display: flex; align-items: center; gap: var(--ss-space-2); width: 100%; }
.ss-slider__end { flex: 0 0 44px; font-size: var(--ss-text-xs); color: var(--ss-ink-2); }
.ss-slider__end--high { text-align: right; }
.ss-slider input[type="range"] { flex: 1 1 auto; min-width: 0; height: 28px; margin: 0; accent-color: var(--ss-forest); }

/* A bigger switch for a row's value column; the settings page keeps the default 38x22 size. */
.ss-switch--lg { width: 44px; height: 26px; }
.ss-switch--lg::after { top: 3px; left: 3px; width: 20px; height: 20px; }
.ss-switch--lg[aria-checked="true"]::after { transform: translateX(18px); }

.ss-pad { display: inline-grid; grid-template-columns: repeat(3, 26px); grid-template-rows: repeat(3, 26px); gap: 2px; }
.ss-pad button { display: flex; align-items: center; justify-content: center; padding: 0; border: 0;
  border-radius: var(--ss-radius-sm); background: var(--ss-fill); color: var(--ss-ink-2); cursor: pointer; }
.ss-pad button[aria-checked="true"] { background: var(--ss-ink); color: var(--ss-white); }
@media (pointer: coarse) {
  /* #440: unlike the rest of this section, the cells really do grow to the 44px floor rather
     than gain an invisible press box — a 3x3 grid of chips would otherwise be the one control
     left under it on a phone. */
  .ss-pad { grid-template-columns: repeat(3, var(--ss-touch)); grid-template-rows: repeat(3, var(--ss-touch)); }
  .ss-pad button { width: var(--ss-touch); height: var(--ss-touch); }
}

.ss-well { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ss-well__thumb { width: 52px; height: 38px; padding: 0; border: 0; border-radius: var(--ss-radius-sm);
  background-color: var(--ss-fill); background-size: cover; background-position: center; color: var(--ss-ink-2);
  cursor: grab; flex-shrink: 0; }
.ss-well__thumb--icon { width: auto; min-width: 52px; padding: 0 var(--ss-space-2); display: inline-flex;
  align-items: center; gap: 6px; font-size: var(--ss-text-xs); }
.ss-well__thumb[aria-grabbed="true"] { cursor: grabbing; opacity: 0.6; }
.ss-well__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 96px; }
.ss-well__add { width: 52px; height: 38px; padding: 0; flex-shrink: 0; display: inline-flex; align-items: center;
  justify-content: center; border: 1px dashed var(--ss-line-control); border-radius: var(--ss-radius-sm);
  background: transparent; color: var(--ss-ink-2); cursor: pointer; }
.ss-well__empty { font-size: var(--ss-text-sm); color: var(--ss-ink-2); }
.ss-well__tail { display: inline-flex; align-items: center; gap: 6px; }
/* #443: a thumb that can't be reordered (a bundle's) is only a way into the library. */
.ss-well__thumb:not([draggable="true"]) { cursor: pointer; }
/* #443: the "+N" after `limit` thumbs, the size of one. */
.ss-well__more { width: 52px; height: 38px; padding: 0; flex-shrink: 0; border: 0; border-radius: var(--ss-radius-sm);
  background: var(--ss-fill); color: var(--ss-ink-2); font: var(--ss-weight-medium) var(--ss-text-sm) / 1 var(--ss-font-ui);
  font-variant-numeric: tabular-nums; cursor: pointer; }
.ss-well__more:hover { color: var(--ss-ink); }

.ss-unitfield { position: relative; display: flex; }
.ss-unitfield .ss-input { padding-right: var(--ss-space-8); width: 100%; }
.ss-unitfield__unit { position: absolute; right: var(--ss-space-3); top: 50%; transform: translateY(-50%);
  font-size: var(--ss-text-xs); color: var(--ss-ink-2); pointer-events: none; }
.ss-unitfield .ss-btn--ghost { position: absolute; right: 2px; top: 50%; transform: translateY(-50%); }
/* The button's measured width replaces this once it is laid out (#443). */
.ss-unitfield--action .ss-input { padding-right: 6rem; }
/* #444: the trailing action can be a toggle (the map's Named only). */
.ss-unitfield .ss-btn--ghost[aria-pressed="true"] { background: var(--ss-forest-tint); color: var(--ss-forest); }
/* The unit sits where a number field's spinner would; the arrow keys still step it (#442). */
.ss-unitfield input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
.ss-unitfield input[type="number"]::-webkit-inner-spin-button,
.ss-unitfield input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

.ss-disclosure > summary { display: flex; align-items: center; gap: var(--ss-space-2); min-height: 44px;
  font: var(--ss-weight-medium) var(--ss-text-md) / 1.3 var(--ss-font-ui); color: var(--ss-ink); cursor: pointer;
  list-style: none; }
.ss-disclosure > summary::-webkit-details-marker { display: none; }
.ss-disclosure > summary svg { flex-shrink: 0; transition: transform var(--ss-duration-fast) var(--ss-ease); }
.ss-disclosure[open] > summary svg { transform: rotate(180deg); }
.ss-disclosure__sum { margin-left: auto; font-size: var(--ss-text-sm); color: var(--ss-ink-2); font-weight: var(--ss-weight-regular); }
.ss-disclosure[open] .ss-disclosure__sum { display: none; }

.ss-badge { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 var(--ss-space-2) 0 6px;
  border: 1px solid var(--ss-line); border-radius: var(--ss-radius-round); background: var(--ss-print);
  color: var(--ss-ink-2); font-size: var(--ss-text-xs); font-weight: var(--ss-weight-medium); white-space: nowrap; }
.ss-badge svg { width: 12px; height: 12px; }

/* The picker and a media well's tiles look smaller than they are to hit; an invisible
   press box grows the target without growing the row (the rule beside .ss-chip does the same). */
@media (pointer: coarse) {
  .ss-root .ss-picker,
  .ss-root .ss-well__thumb,
  .ss-root .ss-well__more,
  .ss-root .ss-well__add { position: relative; }
  .ss-root .ss-picker::before,
  .ss-root .ss-well__thumb::before,
  .ss-root .ss-well__more::before,
  .ss-root .ss-well__add::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: var(--ss-touch);
    transform: translateY(-50%);
  }
}

/* ---- Inspector: the row and the section header (#441) ---- */
/* One row per setting, and the section header above a group of them. `inspector-controls.js`
   builds these as settingRow() and sectionHead(); docs/design-system/inspector/README.md
   § The row, § Inherit states, § Help is the spec. */
.ss-setting {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto var(--ss-control-sm);
  grid-template-areas: "label value reset" "reason reason reason";
  align-items: center;
  column-gap: var(--ss-space-2);
  min-height: var(--ss-touch);
}
.ss-setting__label {
  grid-area: label;
  display: flex; align-items: center; gap: var(--ss-space-2); min-width: 0;
  font: var(--ss-weight-medium) var(--ss-text-md) / 1.3 var(--ss-font-ui);
}
.ss-setting__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The badge itself is ssInspectorControls.badge() — .ss-badge, styled above. */
.ss-setting__help, .ss-setting__reset {
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  padding: 0; border: 0; border-radius: var(--ss-radius-sm); background: transparent; color: var(--ss-ink-2); cursor: pointer;
}
.ss-setting__help:hover, .ss-setting__reset:hover { background: var(--ss-fill); color: var(--ss-ink); }
.ss-setting__help { width: 24px; height: 24px; }
.ss-setting__reset { grid-area: reset; width: var(--ss-control-sm); height: var(--ss-control-sm); }
.ss-setting__value { grid-area: value; justify-self: end; min-width: 0; }
/* The controls draw their value in currentColor, so muting the value column mutes them. */
.ss-setting--inherited .ss-setting__value { color: var(--ss-ink-2); }
.ss-setting__reason { grid-area: reason; margin: 0 0 var(--ss-space-1); font-size: var(--ss-text-sm); color: var(--ss-ink-2); }
/* A refusal the author has to act on (#443, the embed's link), in the field-error colour. */
.ss-setting__reason--error { color: var(--ss-terracotta-text); }
/* The reason stays at full strength, and so does a reset passed as onReset: there it is the
   way out (#442, Position's "Put it back where its style puts it"). */
.ss-setting--unavailable > :not(.ss-setting__reason, .ss-setting__reset) { opacity: 0.5; }
/* A control that needs the row's width (the slider) takes a line of its own under the label. */
.ss-setting--stack { grid-template-areas: "label label reset" "value value ." "reason reason reason"; }
/* #466: with no reset to show, the label's line runs the full width; the control's keeps the column. */
.ss-setting--stack:not(:has(> .ss-setting__reset)) { grid-template-areas: "label label label" "value value ." "reason reason reason"; }
.ss-setting--stack .ss-setting__value { justify-self: stretch; }

.ss-section {
  display: flex; align-items: center; gap: var(--ss-space-2);
  padding: var(--ss-space-4) 0 var(--ss-space-1);
  border-bottom: 1px solid var(--ss-line);
}
.ss-section__title {
  margin: 0; font: var(--ss-weight-semibold) var(--ss-text-xs) / 1.3 var(--ss-font-ui);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ss-ink-2);
}
.ss-section__sum { margin-left: auto; font-size: var(--ss-text-xs); color: var(--ss-ink-2); }
/* Only the first of summary/action needs to claim the row's free space; sectionHead() adds
   this to the action button when there is no summary before it. */
.ss-section__act--push { margin-left: auto; }

/* Shares ssMenu's popover surface and body-level positioning — the inspector clips overflow. */
.ss-tip {
  position: absolute;
  z-index: var(--ss-z-dialog);
  max-width: min(320px, 100vw - 32px);
  padding: var(--ss-space-2) var(--ss-space-3);
  border: 1px solid var(--ss-line);
  border-radius: var(--ss-radius-lg);
  background: var(--ss-print);
  color: var(--ss-ink);
  font-size: var(--ss-text-sm);
  line-height: 1.4;
  box-shadow: var(--ss-shadow-menu);
}
/* #574: the bubble's last line, a link to the help page that says more. 44px to hit on touch. */
.ss-tip__more { display: flex; width: fit-content; align-items: center; margin-top: var(--ss-space-2); font-weight: var(--ss-weight-medium); }
@media (pointer: coarse) { .ss-tip__more { min-height: var(--ss-touch); margin-top: 0; } }
