:root {
  /* Covely's colours, taken from the brand and its application: the near-black
     midnight blue of the wordmark, and the magenta of the dot above the 'c'.

     The magenta is an accent, not an interface colour: in the Covely product it
     appears on the logo's dot and on a few details, while the actions are
     midnight blue. Using it for every button would turn it into something else —
     so here it plays the bookmark (what is active, what is selected) and the blue
     does the work.

     The two greys are not the same grey by accident: --panel is the card,
     --panel-2 is what sits inside a card, and they have to stay distinct or the
     fields disappear into the panel that holds them. */
  --bg: #f7f7fa;
  --panel: #ffffff;
  --panel-2: #f3f4f8;
  --border: #e5e6ee;
  --text: #12123a;
  --muted: #5c6178;           /* darkened one step: 4.44:1 inside a card was not enough */
  --accent: #ec1e79;          /* the logo's dot: borders, dots, fills */
  /* The same magenta does not hold up as TEXT: it sits at 4.18:1 on white and
     3.58:1 on its own light tint, below the WCAG threshold of 4.5. The brand's
     colour does not change — a dark variant is added, to be used when the accent
     plays ink. 6.38:1 on white, 5.47:1 on --accent-soft. */
  --accent-ink: #b8135e;
  --accent-soft: rgba(236, 30, 121, .1);
  /* The red of destructive actions. It used to be #f87171, a dark-theme colour
     left behind here on a white background: 2.52:1, that is, the least legible
     text on the page sitting on the action that deletes a project. */
  --danger: #b91c1c;
  /* The red as a **fill**, which is a different job from the red as ink, and it
     travels with its own colour on top for the reason `--on-solid` exists: the
     dark theme's `--danger` is a light pink, so the ink that reads on it there is
     the dark one, not white. One pair, decided once, legible in both. */
  --on-danger: #ffffff;
  --ink: #12123a;             /* the actions, the strong text, the brand */
  --ink-2: #24245c;
  --ok: #0b6b49;
  --warn: #855309;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* ---------- the conversation ----------
     Two knobs, because the chat is read for an hour at a time and every value in it
     was written inline.

     `--field` is the box you type in, and it is a *lighter* grey than the panel it
     sits on rather than a darker one. A field darker than its card reads as a hole;
     one step lighter reads as paper, and the border can then be a hairline instead
     of a frame holding it in.

     `--chat-fs` was a fallback inside `var()` in two places and defined nowhere, so
     changing the size of the conversation meant finding both. It was 12.8px while the
     director's answers were bubbles in a narrow rail; the owner's second drawing sets
     them as a page in a wider column, at the size of the rest of the screen's text, and
     the owner then asked for a step smaller and tighter lines, so more of a long
     conversation reads at once. */
  --field: #fafbfe;
  --chat-fs: 13px;

  /* ---------- the filled action ----------
     `--ink` was doing two jobs at once: the colour of strong text, and the fill of
     the primary button and the user's chat bubble — always with white on top. On a
     light ground the two happen to be the same colour, so nothing said they were
     different things. On a dark one they pull apart: strong text has to go light,
     and a light fill with white text is an invisible button.

     So the fill is its own pair, and it always travels with the colour that goes
     on top of it. Whoever writes `background: var(--solid)` writes
     `color: var(--on-solid)` on the next line, and the button is legible in both
     themes without either one knowing which theme it is. */
  --solid: #12123a;
  --solid-2: #24245c;         /* the same, one step darker: hover */
  --on-solid: #ffffff;

  /* The red as ink. `--danger` is the word «Delete»; this is the border and the
     text of the same thing once it is hovered or alarmed. It was written out
     fifteen times as #a41d1d. */
  --danger-ink: #a41d1d;
  --danger-soft: rgba(190, 30, 30, .07);
  --danger-line: rgba(190, 30, 30, .35);
  --ok-soft: rgba(15, 138, 95, .08);
  --ok-line: rgba(15, 138, 95, .32);
  --warn-soft: rgba(251, 191, 36, .1);
  --warn-line: rgba(251, 191, 36, .38);
  /* The violet of the chips and the preset cards, which was three different
     rgba() of the same colour written from memory. */
  --violet-soft: rgba(124, 108, 245, .14);
  --violet-line: rgba(124, 108, 245, .45);
  --violet-ink: #4b3fb8;
  /* The accent one step brighter, for the one place it is a fill being hovered. */
  --accent-hi: #ff2f8a;
  --accent-line: rgba(236, 30, 121, .3);
  /* The same accent again, faint enough to be a halo rather than a second border.
     One place uses it: the button that spends, which has to be the one your eye
     lands on among two cards of the same size. */
  --accent-halo: rgba(236, 30, 121, .16);

  /* A veil laid over one of our own surfaces — the drop target lighting up, the
     bin appearing on a tile. Unlike `--scrim` this one is not on an image, so it
     has to follow the theme or it is a white sheet over a dark card. */
  --veil: rgba(255, 255, 255, .86);
  --veil-strong: rgba(255, 255, 255, .92);
  /* The prompt is code, and code reads as code: a dark block on a light page. On a
     dark page it stops being the darkest thing there and lifts instead. */
  --code-block: #0b0d13;
  /* The block is dark in both themes, so its ink is light in both. Without this
     line `.prompt` inherited --text: near-black on near-black, 1.09:1 — the
     generated prompt, which is the technical result the whole Studio exists to
     produce, was invisible unless you selected it with the mouse. */
  --on-code-block: #d7dae8;

  /* ---------- what sits on top of an image ----------
     These two do not change with the theme, and that is the point: they sit on a
     frame the model generated, not on our background. A download button over a
     photograph needs the same dark disc and the same white glyph whichever theme
     the menus are in — the photograph did not change. */
  --scrim: rgba(15, 17, 26, .74);
  --scrim-strong: rgba(8, 9, 14, .93);
  --on-scrim: #ffffff;

  /* What goes on top of `--accent` when the accent is a fill.
     Fifteen rules in the studio's sheet write `background: var(--accent)`, and what
     they put on it was white — through `--on-scrim`, through `--on-solid`, and once
     as a literal `#fff`. Three spellings of one decision, which held because there
     was one accent and somebody had looked at it.
     An agency's skin replaces the accent with a colour nobody has looked at, and
     white on a pastel is nothing at all — so the pairing needs a name before it can
     be computed. `app/js/skin.js` sets this by measurement when a skin is worn.
     It stays white here, unchanged, and that is deliberate: the same measurement
     says white on this magenta is 4.06:1, under AA. That is a fact about a brand
     rather than a bug in a feature, and changing it is somebody's decision and not
     this commit's.
     Not overridden in the dark block below, because `--accent` is not either: the
     magenta is the one colour that does not move between the themes. */
  --on-accent: #ffffff;

  /* The veil behind a dialog, and the three elevations. Shadows are the part of a
     light interface that simply does not transfer: on a dark ground a black shadow
     is invisible, so dark trades them for a rim of light. */
  --overlay: rgba(18, 20, 28, .72);
  --shadow-1: 0 1px 3px rgba(27, 30, 40, .12);
  --shadow-2: 0 8px 24px rgba(18, 20, 28, .1);
  --shadow-3: 0 26px 70px rgba(10, 12, 20, .45);

  --code-bg: rgba(18, 18, 58, .09);
  /* A third surface, between the card and what sits inside it: the rails, the
     tracks, the empty slots. It was #eceef4 in seven places. */
  --panel-3: #eceef4;

  /* ---------- the marks on a chart ----------
     The operator's dashboard draws data, and a mark is not a word: a bar is held to
     the 3:1 a graphical object needs against the surface behind it, not to the 4.5:1
     a sentence needs. Three of them for the credits — what was spent, what came
     back, what was granted — and two more, because the Analytics screen plots three
     units on one x-axis: credits, a count of generations, and the director's cost in
     dollars. Each unit gets a band of its own, and a mark alone in its band still has
     to be told apart from the others in the legend beside it.

     Every value here was measured rather than matched by eye, against `--panel`,
     which is the card a chart is drawn on:

       light, on #ffffff   --chart-1 4.18:1   --chart-bad 6.48:1   --chart-2 7.77:1
                           --chart-3 4.77:1   --chart-4   4.92:1
       dark,  on #15162a   --chart-1 4.26:1   --chart-bad 5.66:1   --chart-2 4.14:1
                           --chart-3 9.85:1   --chart-4  10.36:1

     and pairwise, under simulated protanopia and deuteranopia, the worst of the
     three original pairs is dE 13.8 light and dE 11.2 dark in OKLab x100, against a
     floor of 8; the worst pair involving one of the two additions is dE 9.1 light —
     `--chart-3` against `--chart-4` — and dE 13.5 dark. So somebody who cannot
     separate red from green still separates these. Five categorical hues that hold
     up under both simulations on both grounds is close to all the room there is: a
     sixth would not fit, and the answer to a sixth series is a sixth band. The
     legend is drawn anyway: colour is never the only channel for identity.

     They repeat colours the interface already has — the brand magenta, the violet of
     `--violet-ink`, the amber of `--warn` — and are named again because a fill and
     an ink are different jobs. The dark theme lightens ink so it can be read on a
     dark ground, which is the opposite of what a fill on a dark card wants: taking
     `--violet-ink`'s #b3a9ff as a bar gives a mark that blows out. These are the
     same hues re-stepped for the job. Declared in this sheet as well as the panel's
     because the two token blocks are one copy compared byte for byte; the studio
     draws no charts today. */
  --chart-1: #ec1e79;
  --chart-2: #4b3fb8;
  --chart-bad: #855309;
  /* A count of things, and money measured in another currency. The green is the
     dollar line and not a verdict on the figure it draws: the band's caption carries
     the sign, the colour only says which line it is. */
  --chart-3: #0a7d99;
  --chart-4: #068060;

  /* Form controls, scrollbars and the like are drawn by the browser, and it needs
     telling which way round we are or they come out light on a dark page. */
  color-scheme: light;
}

/* ---------- dark ----------
   Not an inversion: an inversion of a considered light palette gives a grey soup.
   The ground keeps the wordmark's midnight blue rather than going neutral black,
   so the product still looks like itself with the lights off, and the magenta is
   untouched — it is the brand's, and it is the one thing that should read the same
   in both.

   What changes role rather than value: `--ink` goes light because it is text,
   `--solid` goes light because a filled button has to stand off a dark ground, and
   the shadows become a rim of light because a black shadow on black is nothing.

   Every pair here was measured. Body text is 14.87:1 on a card, the muted text
   7.51:1, and the accent stays off text duty in both themes — which is what
   `--accent-ink` is for. */
:root[data-theme="dark"] {
  --bg: #0c0d18;
  --panel: #15162a;
  --panel-2: #1d1f37;
  --panel-3: #262943;
  --border: #2c2f4d;
  --text: #e9eaf5;
  --muted: #a2a7c4;
  --accent: #ec1e79;
  --accent-ink: #ff74ae;
  --accent-soft: rgba(236, 30, 121, .2);
  --danger: #ff8f8f;
  --on-danger: #14152c;
  --danger-ink: #ff8f8f;
  --danger-soft: rgba(255, 143, 143, .12);
  --danger-line: rgba(255, 143, 143, .4);
  --ink: #f0f1fa;
  --ink-2: #c9cce4;
  --ok: #4ade80;
  --ok-soft: rgba(74, 222, 128, .13);
  --ok-line: rgba(74, 222, 128, .38);
  --warn: #fbbf24;
  --warn-soft: rgba(251, 191, 36, .13);
  --warn-line: rgba(251, 191, 36, .38);
  /* Lighter than the panel here too, which on a dark ground means a step *up*
     towards the light: the relationship is what carries, not the value. */
  --field: #23253f;
  --violet-soft: rgba(150, 137, 255, .18);
  --violet-line: rgba(150, 137, 255, .5);
  --violet-ink: #b3a9ff;
  --accent-hi: #ff5c9c;
  --accent-line: rgba(255, 116, 174, .4);
  /* Wider open here: a wash this faint disappears on a dark ground, and the halo
     is the whole point of the rule that uses it. */
  --accent-halo: rgba(255, 116, 174, .26);

  --veil: rgba(15, 16, 32, .88);
  --veil-strong: rgba(15, 16, 32, .94);
  --code-block: #080910;
  --on-code-block: #d7dae8;

  --solid: #e9eaf5;
  --solid-2: #ffffff;
  --on-solid: #14152c;

  --overlay: rgba(4, 5, 12, .78);
  /* A rim of light instead of a shadow, plus a real shadow underneath for the
     things that float highest: on this ground the rim is what says «above». */
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .5);
  --shadow-2: 0 8px 24px rgba(0, 0, 0, .55), 0 0 0 1px rgba(255, 255, 255, .05);
  --shadow-3: 0 26px 70px rgba(0, 0, 0, .7), 0 0 0 1px rgba(255, 255, 255, .07);

  --code-bg: rgba(255, 255, 255, .09);

  /* The five marks re-stepped for a dark card, not flipped. Ratios and the worst
     CVD pairs are in the comment on the light ones. */
  --chart-1: #ec1e79;
  --chart-2: #7468e8;
  --chart-bad: #c58413;
  --chart-3: #22d3ee;
  --chart-4: #5bdd95;

  color-scheme: dark;
}

/* ---------- the type ----------
   Two faces and one scale, for every screen of the studio. Each page used to set its own
   title — Figtree on the Home alone, the system face everywhere else, seven sizes and four
   trackings for the same «title of a page» — and the pages read as if from different sites.

   Inter is the text, Figtree the titles: one variable file per range of characters each,
   ours to serve under the SIL Open Font License (`app/fonts/OFL-inter.txt`,
   `app/fonts/OFL.txt`), so the page still asks nobody else for anything. Where a file
   cannot be reached — the single file opened off a stick — the stacks fall back to the
   system face named after them.

   Outside the colour block every sheet shares byte for byte, because the panel does not
   take part in it. */
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("fonts/inter-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Figtree"; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url("fonts/figtree-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree"; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url("fonts/figtree-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
:root {
  --font-body: "Inter", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-display: "Figtree", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  /* The scale: a page's title, the line under it, a section's title. */
  --fs-page-title: clamp(30px, 2.9vw, 42px);
  --fs-page-sub: 16px;
  --fs-section: clamp(21px, 1.9vw, 26px);
  /* How wide a page's content runs before it is centred. */
  --page-max: 1400px;
}
@media (max-width: 560px) {
  :root { --fs-page-title: 28px; --fs-section: 21px; }
}

* { box-sizing: border-box; }

/* `hidden` means hidden. Always.

   The browser achieves it with a `display: none` in its own stylesheet, which is
   the weakest rule there is: any `display` we write overrides it, and the
   attribute stops doing anything with nothing to signal it. The symptom is an
   element the code believes hidden and that is nonetheless visible — an empty
   text field inside a confirmation that asks for nothing, a menu entry appearing
   to somebody who should not have it, a "Login active" checkbox in a creation
   form.

   All three happened, one at a time, and each time the remedy was a
   `.something[hidden] { display: none }` line at the bottom of the sheet:
   twenty-six of them, and the twenty-seventh new class started it over. This one
   covers them all — `!important` because it has to beat the rules written after
   it too, which is exactly when the defect shows up. */
[hidden] { display: none !important; }
/* The app holds the screen and does not scroll: what scrolls is the two columns,
   each on its own. Without this the left menu would slide away as soon as the
   conversation lengthened, and the navigation would disappear exactly while
   somebody is working. */
html, body { height: 100%; }
body {
  margin: 0; overflow: hidden; background: var(--bg); color: var(--text);
  font: 15px/1.5 var(--font-body);
  /* A column, so that a band above the shell takes its height *from* the shell
     rather than *after* it.

     The page cannot scroll — `overflow: hidden` two lines up — and `.shell` was
     `height: 100%`, which is 100% of the body whatever else is in it. So the seat
     bar, added as a sibling in front of it, pushed 47px of the studio off the
     bottom of a page with no way to reach it: the column's own footer, the brand-kit
     dropdown and the account menu, all below the fold and unreachable. Measured,
     not reasoned about — the smoke reads `.shell`'s bottom against the viewport.

     Everything else that lands in `body` is `position: fixed` (the gate, the
     dialogs) or `position: absolute` (the skip link), so none of them becomes a row
     here; the one unpositioned child, the download anchor in `storage.js`, is
     appended and removed inside one frame. */
  display: flex; flex-direction: column;
}
/* Every title is set in the display face — the headings, and the names on the cards that
   are buttons and so cannot hold one. A card's title keeps its own size, because cards are
   not one size; a page's title and a section's take theirs from the scale below. */
h1, h2, h3, h4,
.sh-door-t, .sh-tool-t, .sh-road-t, .start-name { font-family: var(--font-display); }

/* ---------- a page's head ----------
   The same three lines on every screen, wherever it was drawn: the eyebrow in the accent,
   the title, the line under it. A page's own class lays the head out — the search beside
   it, a count after the title — and never sets its type. */
.page-eyebrow {
  margin: 0 0 10px; font-size: 12px; font-weight: 700; line-height: 1.4; letter-spacing: .12em;
  text-transform: uppercase; color: var(--accent-ink);
}
.page-title {
  margin: 0; font-family: var(--font-display); font-size: var(--fs-page-title); font-weight: 800;
  line-height: 1.08; letter-spacing: -.035em; color: var(--ink); text-wrap: balance;
}
.page-sub { margin: 8px 0 0; font-size: var(--fs-page-sub); line-height: 1.5; color: var(--muted); }
/* `.card .section-title` out-ranks `.card h2`, the small capitals a card's heading wears. */
.section-title, .card .section-title {
  margin: 0; font-family: var(--font-display); font-size: var(--fs-section); font-weight: 800;
  line-height: 1.15; letter-spacing: -.025em; color: var(--ink); text-transform: none; text-wrap: balance;
}
.section-sub { margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: var(--muted); }
.section-sub { margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: var(--muted); }

/* ---------- The brand, at the top of the column ----------
   The full-width header is gone: it said a name and three models, and to say it
   took a 76px band on every screen. The brand now opens the left column, which is
   already the place you navigate from. */
.side-brand {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 6px 0;
}
/* The logo is Explore's door (the owner's word of 2026-10-24): the mark and the agency's
   word inside a button, laid out as they were beside each other. The wide-logo rule below
   gives the mark the header's width; the button is the header's item now, so it takes it. */
.side-home {
  display: flex; align-items: center; gap: 10px; min-width: 0; padding: 0; cursor: pointer;
  font: inherit; text-align: left; color: inherit; background: none; border: 0; border-radius: 10px;
}
.side-home:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
@media (min-width: 621px) {
  body:not(.nav-collapsed) .side-home:has(.brand-logo) { flex: 1 1 auto; }
}
/* The logo, and nothing behind it.

   It had a tile — first a magenta-to-purple gradient this product invented, then
   the artwork's own near-black — and a tile is a rounded black square that the
   brand does not have. On this column it is also unnecessary: `--side-bg` is
   `#0a0c14` in both themes, so the ground is always dark enough for white ink,
   which is what the artwork is.

   The other surfaces are not so lucky and keep theirs — the panel's column and the
   console's are painted from `--panel`, which is white on the light theme, and the
   three sign-in cards are `--panel` itself. A white logo on white is nothing at
   all, so where the ground can turn pale the logo brings its own. Here it cannot,
   so it does not.

   **The width is deliberately not set.** Three different things sit in this box —
   our lockup, three and a half times as wide as it is tall; an agency's wordmark;
   an agency's monogram — and a fixed 34px square, which is what was here while ours
   was the mark alone, crops two of the three. The height is the constant and the
   column's own `--side-w` is what bounds the width. */
.brand-mark { display: flex; align-items: center; flex: none; height: 34px; }
/* Ours: the whole lockup, with the mark beside it for the fold.

   Both are in the page and the rules show one — see `brandLogoNode`, which is also
   where the argument for two elements rather than one rewritten `src` is written
   down. The mark is not a second logo, it is this artwork cropped: 60px of folded
   column cannot hold a lockup, and a lockup squeezed into one is a logo nobody
   recognises. */
.brand-ours { display: flex; align-items: center; line-height: 0; }
.brand-ours-full { display: block; width: auto; height: 34px; }
.brand-ours-icon { display: none; }
/* An agency's mark, where ours would be. Bounded rather than sized: a wordmark is
   wide and a monogram is square, and the one thing that must not happen is a logo
   pushing the column's own width around.

   The bound used to be 30px both ways, from when ours was a mark on its own and a
   square was the whole of what this box could be. Ours is a lockup, so a wordmark
   they upload gets what ours gets — otherwise the white label shows the agency
   smaller than the company it replaced. Folded, it is a 60px strip and the only
   thing that fits is a monogram, so there the square bound comes back.

   **It lives here rather than at the end of the file, and that is not tidying.**
   The 620px block overrides it with the same specificity, and an override with the
   same specificity only wins from further down — with this rule last, a phone got a
   150px logo in a 56px column and the cascade was right about it. */
.brand-logo { max-width: 150px; max-height: 34px; object-fit: contain; display: block; }
body.nav-collapsed .brand-logo { max-width: 40px; max-height: 30px; }
/* An agency's own logo is **their** artwork and is shown as it is: no ground from
   us anywhere, and no padding either, because a plate under somebody else's mark is
   us framing it. */
.brand-mark:has(.brand-logo),
.gate-logo:has(.brand-logo) { background: none; padding: 0; }
/* And it takes the whole header: the width the column has, beside the button that
   folds it, up to 64px tall. Not folded and not on a phone only — those keep the
   strip's square bound above, and a media query rather than a later override so the
   620px block does not have to out-rank it. */
@media (min-width: 621px) {
  body:not(.nav-collapsed) .brand-mark:has(.brand-logo) { flex: 1 1 auto; min-width: 0; height: auto; }
  body:not(.nav-collapsed) .brand-mark:has(.brand-logo) .brand-logo { max-width: 100%; max-height: 64px; }
}
/* The agency's word beside the mark, in the titles' face. */
/* Empty is the ordinary state: ours is the mark alone, and this carries an agency's
   name only where they have given one. An empty span still takes its gap in a flex
   row, which is a hole beside the logo that nobody can explain. */
.brand-word:empty { display: none; }
.brand-word {
  font-family: var(--font-display);
  font-size: 24px; font-weight: 700; letter-spacing: -.03em; line-height: 1;
  color: var(--side-ink); white-space: nowrap; overflow: hidden;
}
.side-toggle {
  margin-left: auto; flex: none; width: 28px; height: 28px; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  color: var(--side-muted); background: transparent; border: 1px solid transparent; border-radius: 8px;
  transition: color .14s, border-color .14s, background .14s;
}
.side-toggle:hover { color: var(--side-ink); background: var(--side-bg-2); border-color: var(--side-line); }

/* The service rows — `.status`, `.mdl-*` — went to `admin/styles.css` with the two
   elements they dressed. `#status` and `#engine-notes` were markup on the panel's
   Engines card, painted from `initHealth()` in `app/js/app.js`: two halves in two
   files, which is exactly why they had to travel together. */

.view[hidden] { display: none; }

/* ---------- AI direction ----------
   Two columns filling the screen's height, and the wide one is the *stage*.
   It used to be the other way round: the conversation took the elastic fraction
   and the result lived in a 430px rail. That was right when the result was a
   thumbnail to glance at, and wrong from the moment it became a thing to work on
   — a 9:16 video 430px wide is a preview, not a video, and an image you have to
   lean into is an image nobody judges properly. The talking is narrow and fixed;
   the making gets the room.

   The two tracks are swapped in place rather than reordered: `.chat-col` is still
   the first child in the markup, so the tab order still matches what the eye sees
   and the single-column fallback below 1020px still stacks the conversation
   first, with nothing to re-teach it. `order:` and `grid-column:` would both have
   done it visually and broken both of those quietly. */
.chat-view {
  position: relative;
  display: grid; grid-template-columns: clamp(360px, 29vw, 470px) minmax(0, 1fr);
  gap: 18px; align-items: stretch; height: 100%; min-height: 0; overflow: hidden;
}

/* `min-width: 0` on a grid child is not decoration: without it the track floors at
   the widest unbreakable thing inside — one long word in a message, one prompt
   line without spaces — and the column silently exceeds the 430px it was given. */
.chat-col { position: relative; display: flex; flex-direction: column; height: 100%; min-width: 0; min-height: 0; margin: 0; }

/* ---------- the director's ground: an aurora, glass and a canvas ----------
   The owner's redesign asked for a column with impact and a tone that holds together.
   The column's own drifting fields — magenta, violet, blue — come out of the sidebar
   and lie, much softer, under the whole work area while the director is open; the
   conversation is glass over them, so they show through it; the stage is paper, the
   one solid surface, because what is on it is the work. Its tokens live on `.main` and
   not in `:root`, whose block is copied byte for byte into the other two pages' sheets
   (`test/build.test.js`) and has no business carrying one screen's ground.

   With a skin worn the fields are three tints of the agency's accent — our violet and
   blue showing through somebody else's brand is what the white label exists to stop
   (`sidebarTokens` in skin.js makes the same argument for the column). */
.main {
  --dir-aurora-1: rgba(236, 30, 121, .22);
  --dir-aurora-2: rgba(124, 77, 255, .2);
  --dir-aurora-3: rgba(56, 110, 255, .15);
  --dir-violet: #7c4dff;
  --dir-glass: rgba(255, 255, 255, .66);
  --dir-glass-line: rgba(255, 255, 255, .9);
  --dir-card-line: rgba(18, 18, 58, .07);
  --dir-card-shadow: 0 1px 2px rgba(24, 16, 64, .05), 0 34px 64px -42px rgba(24, 16, 64, .38);
  --dir-canvas-hi: #f8f8fb;
  --dir-canvas-lo: #eaebf1;
  --dir-canvas-line: rgba(18, 18, 58, .05);
  --dir-canvas-dot: rgba(18, 18, 58, .075);
  --dir-canvas-shade: rgba(24, 16, 64, .09);
  --dir-piece-shadow: rgba(24, 16, 64, .36);
  --dir-msg-shadow: 0 1px 2px rgba(24, 16, 64, .04), 0 12px 26px -20px rgba(24, 16, 64, .28);
}
:root[data-theme="dark"] .main {
  --dir-aurora-1: rgba(236, 30, 121, .24);
  --dir-aurora-2: rgba(124, 77, 255, .26);
  --dir-aurora-3: rgba(56, 110, 255, .2);
  --dir-violet: #9a7cff;
  --dir-glass: rgba(21, 22, 42, .74);
  --dir-glass-line: rgba(255, 255, 255, .08);
  --dir-card-line: rgba(255, 255, 255, .07);
  --dir-card-shadow: 0 0 0 1px rgba(255, 255, 255, .03), 0 34px 64px -34px rgba(0, 0, 0, .75);
  --dir-canvas-hi: #1d1f3a;
  --dir-canvas-lo: #101125;
  --dir-canvas-line: rgba(255, 255, 255, .05);
  --dir-canvas-dot: rgba(255, 255, 255, .06);
  --dir-canvas-shade: rgba(0, 0, 0, .4);
  --dir-piece-shadow: rgba(0, 0, 0, .7);
  --dir-msg-shadow: 0 0 0 1px rgba(255, 255, 255, .04), 0 12px 26px -18px rgba(0, 0, 0, .7);
}
:root[data-skin="on"] .main {
  --dir-aurora-1: color-mix(in srgb, var(--accent) 18%, transparent);
  --dir-aurora-2: color-mix(in srgb, var(--accent) 11%, transparent);
  --dir-aurora-3: color-mix(in srgb, var(--accent) 7%, transparent);
  --dir-violet: var(--accent);
}
/* The fields, while the director is the screen: three still ones painted once, and a
   fourth that drifts on a long cycle — only `transform` moves, so it costs a composite. */
.main:has(> #view-chat:not([hidden])) { position: relative; isolation: isolate; }
.main:has(> #view-chat:not([hidden]))::before,
.main:has(> #view-chat:not([hidden]))::after {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
}
.main:has(> #view-chat:not([hidden]))::before {
  inset: 0;
  background:
    radial-gradient(40% 55% at 6% 10%, var(--dir-aurora-1), transparent 72%),
    radial-gradient(36% 48% at 30% 100%, var(--dir-aurora-2), transparent 74%),
    radial-gradient(44% 50% at 100% 0%, var(--dir-aurora-3), transparent 72%),
    radial-gradient(30% 40% at 78% 96%, var(--dir-aurora-1), transparent 74%);
}
.main:has(> #view-chat:not([hidden]))::after {
  left: -6%; top: 22%; width: 44%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, var(--dir-aurora-2), transparent 66%);
  filter: blur(36px); opacity: .9;
}
@media (prefers-reduced-motion: no-preference) {
  .main:has(> #view-chat:not([hidden]))::after { animation: dir-drift 24s ease-in-out infinite alternate; will-change: transform; }
}
@keyframes dir-drift { to { transform: translate3d(38%, -18%, 0) scale(1.18); } }

/* The conversation on glass: the fields through it, an edge of light round it, and the
   faintest wash of the accent where it begins. */
.chat-view > .chat-col.card {
  padding: 14px 14px 12px; border-radius: 24px;
  background:
    radial-gradient(120% 34% at 0% 0%, color-mix(in srgb, var(--accent) 8%, transparent), transparent 72%),
    radial-gradient(90% 30% at 100% 100%, color-mix(in srgb, var(--dir-violet) 7%, transparent), transparent 70%),
    var(--dir-glass);
  -webkit-backdrop-filter: blur(22px) saturate(1.5); backdrop-filter: blur(22px) saturate(1.5);
  border: 1px solid var(--dir-glass-line);
  box-shadow: 0 34px 64px -46px rgba(24, 16, 64, .45), inset 0 1px 0 color-mix(in srgb, var(--dir-glass-line) 70%, transparent);
}
/* And its edge catches the light: a hairline that runs from the accent at the top corner
   into nothing and comes back as the violet at the foot, where the box is. Drawn on its own
   layer and masked to the border, so the glass under it stays glass. */
.chat-view > .chat-col.card::before {
  content: ""; position: absolute; inset: -1px; z-index: 0; border-radius: inherit; padding: 1px; pointer-events: none;
  background: linear-gradient(165deg, color-mix(in srgb, var(--accent) 60%, transparent), transparent 34%, transparent 66%, color-mix(in srgb, var(--dir-violet) 50%, transparent));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
}

/* An image dragged in: the whole view catches it — a file dropped on the video would
   otherwise fall through to the window handler and be swallowed — and the
   conversation says so, because that is where the file goes. The veil used to cover
   the whole view, the picture on the stage included, which read as the file being
   opened full screen rather than attached to the chat. */
.chat-view.dropping .chat-col { border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent-soft); }
.chat-view.dropping .chat-col::after {
  content: attr(data-drop-label);
  position: absolute; inset: 0; z-index: 6; display: grid; place-items: center;
  padding: 20px; text-align: center; pointer-events: none;
  font-size: 15px; font-weight: 600; color: var(--accent-ink);
  background: var(--veil); border-radius: 24px;
}
@media (prefers-reduced-motion: no-preference) {
  .chat-view.dropping .chat-col::after { animation: drop-in .14s ease-out; }
}
@keyframes drop-in { from { opacity: 0; } }

/* ---------- the starting page: the director before anything is said ----------
   The owner's «Create» (2026-10-24): one column in the middle of the aurora — the title,
   the box, a line about what can be attached and one about the mode, then the goals to
   start from. It is this screen in a state, `#view-chat[data-fresh]`, written by
   `paintKind` (`freshConversation`), and not a screen of its own: the box, its bar, the
   files dropped on it and the lines the studio says are the director's, so the first
   Send turns the page into the two columns with nothing moved from anywhere.

   Nothing here sets the box's colour or its shadow: the box keeps its one `:focus-within`
   treatment (`.composer`), which a rule of this specificity would otherwise outrank. */
.main > .chat-view[data-fresh] { display: block; overflow-y: auto; overscroll-behavior: contain; }
.chat-view[data-fresh] > .chat-side { display: none; }
.chat-view[data-fresh] > .chat-col.card {
  height: auto; min-height: 0; max-width: 1040px; margin: 0 auto; padding: clamp(12px, 3.5vh, 44px) 20px 40px;
  background: none; border-color: transparent; box-shadow: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.chat-view[data-fresh] > .chat-col.card::before { display: none; }
.chat-view[data-fresh] .chat-log { flex: none; min-height: 0; overflow: visible; padding: 0; align-items: center; }
/* What the box already shows — the pictures put in it — is not said twice above it; the
   studio's own lines (a file refused, a reference dropped) stay. */
.chat-view[data-fresh] .chat-log > .msg.upload-only,
.chat-view[data-fresh] .chat-jump { display: none; }
#chat-intro.fresh-hero {
  align-self: center; max-width: 820px; margin: 0; padding: 0; text-align: center;
  color: var(--text); background: none; border: 0; box-shadow: none;
}
/* The page's head (`.page-eyebrow`, `.page-title`, `.page-sub`), centred over the box: the
   one screen whose head is not on the left, because the box under it is in the middle. */
.fresh-eyebrow { display: inline-block; }
.fresh-title { display: grid; }
/* The studio's half of the sentence in the accent running into the director's violet —
   which under a skin is the agency's accent again (`--dir-violet`, `[data-skin="on"]`). */
.fresh-brand {
  background: linear-gradient(90deg, var(--accent), color-mix(in oklab, var(--accent) 55%, var(--dir-violet)));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.fresh-sub { margin-inline: auto; max-width: 54ch; }
.chat-view[data-fresh] .composer { width: min(100%, 780px); margin: clamp(16px, 3vh, 28px) auto 0; padding: 14px 14px 12px 16px; gap: 8px; border-radius: 22px; }
.composer-title { display: none; }
.chat-view[data-fresh] .composer-title { display: block; margin: 0 2px; font-size: 15px; font-weight: 700; color: var(--text); }
.chat-view[data-fresh] .composer textarea { min-height: 64px; font-size: 15px; }
/* The question's example line is cut where the box is narrow, rather than scrolled. */
.chat-view[data-fresh] .composer textarea:placeholder-shown { overflow-y: hidden; }
/* The two round buttons carry a word here, as the mockup draws them. */
.attach-word, .send-word { display: none; }
.chat-view[data-fresh] .btn.icon.composer-attach { width: auto; height: 36px; padding: 0 14px 0 10px; gap: 7px; border-radius: 999px; }
.chat-view[data-fresh] .attach-word { display: inline; font-size: 13.5px; font-weight: 600; }
.chat-view[data-fresh] .composer-bar #chat-send { width: auto; height: 44px; padding: 0 18px 0 20px; gap: 8px; border-radius: 999px; }
.chat-view[data-fresh] .send-word { display: inline; font-size: 14.5px; font-weight: 600; }
.chat-view[data-fresh] #chat-send .send-arrow { transform: rotate(90deg); }
@media (prefers-reduced-motion: no-preference) {
  .chat-view[data-fresh] #chat-send:not(.stop):not(:disabled):hover .send-arrow { transform: rotate(90deg) translateY(-2px); }
}

/* Under the box: what can be attached, how the lit mode works, and the goals. */
.chat-start { display: none; }
.chat-view[data-fresh] .chat-start { display: block; width: min(100%, 1000px); margin: 14px auto 0; }
.start-hint, .start-mode {
  display: flex; align-items: center; justify-content: center; gap: 7px; margin: 0 auto;
  max-width: 780px; font-size: 13px; line-height: 1.45; color: var(--muted); text-align: center;
}
.start-mode { margin-top: 6px; }
.start-hint .sd-ic { flex: none; }
.start-rule { margin: clamp(16px, 3vh, 28px) 0 16px; border: 0; border-top: 1px solid var(--border); }
.start-sub { margin-bottom: 14px; }
.start-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.start-card {
  display: flex; flex-direction: column; min-width: 0; padding: 0; overflow: hidden; cursor: pointer;
  font: inherit; text-align: left; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 1px 2px rgba(24, 16, 64, .04), 0 18px 34px -30px rgba(24, 16, 64, .5);
  transition: transform .16s, box-shadow .16s, border-color .16s;
}
.start-card:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
  box-shadow: 0 1px 2px rgba(24, 16, 64, .05), 0 22px 40px -28px color-mix(in srgb, var(--accent) 60%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .start-card:hover:not(:disabled) { transform: translateY(-2px); }
}
.start-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.start-card:disabled { cursor: progress; opacity: .6; }
.start-art {
  position: relative; display: block; aspect-ratio: 16 / 9;
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 55%, var(--panel)), color-mix(in srgb, var(--dir-violet) 45%, var(--panel)));
}
.start-art img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.start-badge {
  position: absolute; left: 12px; bottom: -16px; display: grid; place-items: center; width: 36px; height: 36px;
  color: var(--accent-ink); background: var(--panel); border: 1px solid var(--border); border-radius: 11px;
  box-shadow: 0 8px 16px -10px rgba(24, 16, 64, .45);
}
.start-words { display: grid; gap: 4px; padding: 26px 14px 15px; }
.start-name { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 14.5px; font-weight: 700; }
.start-name .sd-ic { flex: none; color: var(--muted); }
.start-line { font-size: 13px; line-height: 1.4; color: var(--muted); }
@media (max-width: 900px) {
  .start-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
}

/* ---- the two technical answers, folded at the foot of the result ----
   Closed, because they answer a question asked *after* looking at the picture:
   which engine drew this, and what was actually sent. A prompt open by default is
   four hundred characters of machine text between somebody and their own work. */
.res-folds { margin-top: 12px; border-top: 1px solid var(--border); }
.res-fold { border-bottom: 1px solid var(--border); }
.res-fold:last-child { border-bottom: 0; }
.res-fold > summary {
  display: flex; align-items: center; gap: 10px; padding: 10px 2px;
  cursor: pointer; list-style: none; font-size: 13px;
}
.res-fold > summary::-webkit-details-marker { display: none; }
.res-fold > summary::after {
  content: "\203a"; margin-left: auto; color: var(--muted); font-size: 16px; line-height: 1;
  transform: rotate(90deg); transition: transform .15s;
}
.res-fold[open] > summary::after { transform: rotate(270deg); }
.res-fold-what { font-weight: 600; color: var(--ink); }
.res-fold > summary .hint { margin: 0; }
.res-fold > .hint { margin: 0 2px 10px; }
.res-fold .btn-row { padding-bottom: 10px; }
/* A generation's id: small, copyable, and in the face that says it is a code. */
.res-trace { margin: 0 2px 10px; }
.res-trace-line, .msg-trace { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.res-trace-line code, .msg-trace code { font-family: var(--mono); font-size: 11.5px; user-select: all; overflow-wrap: anywhere; }
.msg-trace { margin-top: 6px; font-size: 12px; opacity: .85; }

/* What the job is, next to the goal's badge, once the picking is over. */
.chat-flow { font-size: 12px; font-weight: 600; color: var(--muted); letter-spacing: -.005em; }

/* The project at the head of the chat: you read it, and hovering over it you read
   the specifics the director is following. */
.chat-folder {
  max-width: 100%; overflow-wrap: anywhere; text-align: start;
  padding: 3px 10px; cursor: help; font: inherit; font-size: 12px; font-weight: 600;
  color: var(--ink-2); background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 999px;
}
.chat-folder[hidden] { display: none; }

/* Finished: the conversation closes, but the door stays. */
.chat-done {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 10px; padding: 10px 14px;
  background: var(--ok-soft); border: 1px solid var(--ok-line); border-radius: 11px;
}
.chat-done[hidden] { display: none; }
.chat-done strong { color: var(--ok); font-size: 13.5px; }
.chat-done .hint { margin: 0; flex: 1; min-width: 0; }
.composer.locked { opacity: .55; }
.composer.locked textarea { cursor: not-allowed; }

/* ---------- The goal's icon ----------
   The same mark in the chat, in the column and in the listing: that is how, among
   thirty jobs, you tell at a glance which was which. The colour belongs to the
   type, not to the theme — five tints that stay recognisable even at 14px. */
.kind-ic {
  display: grid; place-items: center; flex: none;
  width: 2.1em; height: 2.1em; border-radius: 9px;
  color: var(--k, var(--ink)); background: color-mix(in srgb, var(--k, var(--ink)) 12%, transparent);
}
/* 12% of a hue over white is a soft tint; over a dark card it is nothing at all —
   the badge loses the wash that told you, across the room, what kind of job this
   was. The mix goes up rather than the hue changing, so the two themes read as the
   same badge. */
:root[data-theme="dark"] .kind-ic { background: color-mix(in srgb, var(--k, var(--ink)) 22%, transparent); }
.kind-badge { --k: var(--ink); }
[data-kind="image"] { --k: #6d4fd6; }
[data-kind="video"] { --k: #ec1e79; }
[data-kind="ads"] { --k: #c2700c; }
[data-kind="ugc"] { --k: #2563a8; }
[data-kind="music"] { --k: #0f8a5f; }
[data-kind="voice"] { --k: #0e8c8c; }
/* The same six, lifted for a dark card. Measured: the light hues came in at
   3.17:1 (image), 2.91:1 (the blue, now UGC's) and 4.09:1 (music) against --panel,
   and that colour is the label naming what a generation is. */
:root[data-theme="dark"] [data-kind="image"] { --k: #a894ff; }
:root[data-theme="dark"] [data-kind="video"] { --k: #ff74ae; }
:root[data-theme="dark"] [data-kind="ads"] { --k: #e0a53c; }
:root[data-theme="dark"] [data-kind="ugc"] { --k: #7bb4ee; }
:root[data-theme="dark"] [data-kind="music"] { --k: #4ade80; }
:root[data-theme="dark"] [data-kind="voice"] { --k: #5fd4cf; }
.kind-badge { display: inline-flex; align-items: center; gap: 7px; vertical-align: middle; }
.kind-lb { font-size: 12.5px; font-weight: 600; color: var(--k); }

.chat-kind { display: inline-flex; align-items: center; }
.chat-log { flex: 1; min-height: 160px; overflow-y: auto; padding-right: 6px; display: flex; flex-direction: column; gap: 5px; }
/* A change of speaker gets air; a second paragraph from the same one does not. Two
   consecutive turns from the director are one thought continuing, and spacing them
   like a reply makes a long answer read as an argument with itself. */
.chat-log > .msg.user + .msg.assistant,
.chat-log > .msg.assistant + .msg.user { margin-top: 6px; }

/* `anywhere` and not `break-word`: a URL or a model id with no spaces in it is
   exactly what a 330px column meets, and the softer value leaves it sticking out. */
.msg {
  position: relative; max-width: 90%; padding: 8px 12px; border-radius: 14px;
  font-size: var(--chat-fs); line-height: 1.42; letter-spacing: -.004em;
  overflow-wrap: anywhere;
}
.msg p { margin: 0 0 4px; }
.msg p:last-child { margin-bottom: 0; }
/* The person's own words, as the owner's drawing has them: the accent's wash rather
   than the midnight fill, read in the same ink as everything else in the column. */
.msg.user {
  align-self: flex-end; max-width: 88%; padding: 9px 14px; background: var(--accent-soft); color: var(--text);
  border-radius: 14px; border-bottom-right-radius: 5px;
}
/* No border and no mark beside it, as the owner's drawing has it: the director's
   words are a card one step off white, wide enough to read as a page of the plan
   rather than a bubble in a thread. `:not(.shots)` keeps a strip of pictures, which is
   also a `.msg.assistant`, out of it. */
.msg.assistant {
  align-self: flex-start; background: var(--panel-2); border-bottom-left-radius: 5px;
}
.chat-log > .msg.assistant:not(.shots):not(.intro) {
  align-self: stretch; max-width: 100%; padding: 12px 16px; border-radius: 16px;
}
.msg.assistant.intro { color: var(--muted); }
/* On the director's glass the words are paper: the director's a white card with a lift,
   the person's the accent's wash running into the violet, edged in its own line — two
   voices told apart from across the room, in the tokens a skin and the dark theme reach. */
.chat-col .chat-log > .msg.assistant:not(.shots) {
  background: var(--panel); border: 1px solid var(--dir-card-line); box-shadow: var(--dir-msg-shadow);
}
.chat-col .chat-log > .msg.user {
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 13%, var(--panel)), color-mix(in srgb, var(--dir-violet) 11%, var(--panel)));
  border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
  box-shadow: 0 10px 22px -18px color-mix(in srgb, var(--accent) 70%, transparent);
}

/* The studio talking about itself — a file archived, a version saved — is neither
   side of the conversation, and a bubble gave it the weight of one. A centred line
   in the margin is read when it matters and ignored when it does not. */
.msg.system:not(.prompt-trace):not(.ask) {
  align-self: center; max-width: 96%; padding: 2px 4px; text-align: center;
  background: transparent; font-size: 11.8px; color: var(--muted);
}

/* Markdown. The director's text is structured: small headings, lists, bolds. The
   measures are tight on purpose — inside a chat bubble an h3 with a web page's
   margins breaks the reading instead of guiding it. */
.md-h { margin: 8px 0 3px; font-size: 13px; font-weight: 600; line-height: 1.35; letter-spacing: -.012em; }
.md-h:first-child { margin-top: 0; }
.md-list { margin: 3px 0 4px; padding-left: 18px; }
.md-list li { margin: 1px 0; }
.md-list li::marker { color: var(--ink-2); font-weight: 600; }
.msg.user .md-list li::marker { color: var(--accent-ink); }
.md-quote {
  margin: 5px 0; padding: 2px 0 2px 11px; color: var(--muted);
  border-left: 3px solid var(--border);
}
.md-code {
  margin: 8px 0; padding: 9px 11px; overflow-x: auto;
  background: var(--panel); border: 1px solid var(--border); border-radius: 9px;
  font-family: var(--mono); font-size: 11.4px; line-height: 1.5;
}
.md-inline-code {
  padding: 1px 5px; border-radius: 5px; background: var(--code-bg);
  font-family: var(--mono); font-size: 11.6px; color: var(--ink-2);
}
.msg.user .md-inline-code { background: var(--panel); color: var(--ink-2); }
.msg hr { margin: 7px 0; border: 0; border-top: 1px solid var(--border); }
.msg a { color: var(--ink-2); }
.msg.user a { color: var(--accent-ink); }

/* ---------- A reference, shown ----------
   `@Image2` is the name the prompt will use, and it is the only name the director
   can use — it never sees a URL for a file the user uploaded. Correct and
   unreadable: three references in and nobody remembers which one was the bag. So
   where the file is still in the brief, the token is the file: a thumbnail the
   height of the line it sits on, the name it arrived under, and a click for full
   size. Inline-flex with a baseline-ish alignment so a reference mid-sentence does
   not push the line apart. */
.aref {
  display: inline-flex; align-items: center; gap: 4px; vertical-align: -2px;
  /* Margin on the left only. With one on both sides a reference followed by a comma
     read as «[pill] , tenuta in mano» — a gap before the punctuation, which is the
     kind of thing that makes a careful layout look careless. */
  margin-left: 1px; padding: 0 6px 0 2px; max-width: 13em;
  font: inherit; font-size: .9em; font-weight: 600; line-height: 1.5; color: var(--ink-2);
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  cursor: pointer; text-align: left; overflow: hidden;
  transition: border-color .14s, background .14s;
}
.aref > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Kept under the line's own height, so a paragraph with three references in it has
   the same rhythm as one with none. */
.aref > img {
  flex: none; width: 1.3em; height: 1.3em; border-radius: 50%;
  object-fit: cover; background: var(--panel-2);
}
/* Nothing to show — an audio file, or an image whose data URI the save had to
   throw away — so the pill closes up rather than leaving a hole where a picture
   would be. */
.aref:not(:has(> img)) { padding-left: 7px; cursor: default; }
.aref:hover { border-color: var(--accent); background: var(--accent-soft); }
.aref:not(:has(> img)):hover { background: var(--panel); border-color: var(--border); }
.aref:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* On the user's tinted bubble the pill sits on paper, edged in the tint's own line. */
.msg.user .aref { color: var(--ink-2); background: var(--panel); border-color: var(--accent-line); }
.msg.user .aref:hover { background: var(--panel-2); }

/* Copying a message: it appears on hover, so it does not take up space forever.
   But it appears *over* the first line, and «Tengo la borsa di …» with two words
   hidden under a button is exactly the kind of detail that makes a careful layout
   look careless. So the first block of the message keeps its right edge clear —
   only the first, so no bubble grows and nothing shifts when the button fades in. */
.msg.assistant .msg-body > *:first-child { padding-right: 26px; }
.msg-copy {
  position: absolute; top: 5px; right: 5px; opacity: 0;
  width: 26px; height: 26px; padding: 0; cursor: pointer;
  background: var(--panel); border: 1px solid var(--border); border-radius: 7px;
  color: var(--muted); font-size: 13px; line-height: 1; transition: opacity .15s;
}
.msg:hover .msg-copy, .msg-copy:focus-visible { opacity: 1; }
.msg-copy:hover { border-color: var(--accent); color: var(--accent-ink); }

/* The pieces a delivery names, under it: the same chip, and a click shows the picture. */
.msg-pieces { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.opt-chip {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  padding: 7px 16px 7px 8px; font: inherit; font-size: 13.5px; text-align: left;
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  color: var(--text); transition: border-color .15s, transform .15s;
}
.opt-chip:hover { border-color: var(--accent); transform: translateY(-1px); }
.opt-n {
  display: grid; place-items: center; width: 22px; height: 22px; flex: none;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent-ink);
  font-size: 12px; font-weight: 700;
}

/* ---- the question as a choice card ---- */
/* A container, so the answers lay themselves out by the card's own width rather than the
   window's: the same card is 400px wide docked in the director's column and twice that
   in the stacked layout, and «two columns from 720px of window» put two columns of 150px
   into the first. */
.ask {
  container: ask / inline-size;
  align-self: stretch; max-width: 100%; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--accent);
  border-radius: 14px; box-shadow: var(--shadow-2);
  animation: ask-in .22s ease-out;
}
@keyframes ask-in { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: reduce) { .ask { animation: none; } }
/* **An answered card is a record, and a record is one line.**
   The markup beside the dock has said so since the dock was written — «the moment it
   is answered it is sealed and moved into the log, where it becomes the record it
   always was» — and nothing ever made it look like one: four options at full height
   stayed there, and three questions into a job the conversation was a wall of
   buttons nobody could press. So what is kept is what a record needs — which question
   was asked, and what was answered — and the options go with the moment they were
   live in. Hidden rather than removed, because the node is the answer's own proof:
   `.on` is what `↳` is echoing. */
.ask.answered {
  border-color: var(--border); box-shadow: none; opacity: .82;
  padding: 9px 12px 8px;
}
.ask.answered .ask-options,
.ask.answered .ask-multi { display: none; }
.ask.answered .ask-q { margin-bottom: 0; font-size: 13px; }
.ask.answered .ask-head { margin-bottom: 4px; }
.ask.answered .ask-answer { margin-top: 6px; padding-top: 6px; }
.ask-head { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.ask-tag {
  padding: 2px 8px; border-radius: 999px; background: var(--accent-soft);
  color: var(--accent-ink); font-size: 10.5px; font-weight: 700; line-height: 1.5;
  letter-spacing: .05em; text-transform: uppercase;
}
.ask-multi { font-size: 11.5px; color: var(--muted); }
.ask-q { margin: 0 0 7px; font-size: 13.5px; font-weight: 600; line-height: 1.34; }
.ask-q p { margin: 0; }
/* The text a question is about — a script, a voice-over — whole: what is approved is read
   before it is approved. It was a quote inside the card; it is a page of the conversation
   now, above the card that approves it (`askScript`), a page of the director's with the
   accent's rule at its edge saying it is the text being approved. Never clamped and never
   scrolled inside itself: the conversation scrolls. */
.chat-log > .msg.ask-script {
  align-self: stretch; max-width: 100%; padding: 14px 18px 14px 16px; border-radius: 16px;
  background: var(--panel); border: 1px solid var(--dir-card-line); border-left: 3px solid var(--accent);
  box-shadow: var(--dir-msg-shadow);
}
.msg.ask-script .msg-body { display: block; white-space: pre-wrap; }
/* **Compact, because the card is the column's.** It docks over the box, in a column 360
   to 470px wide, and four answers of four lines each — number, name on two lines, detail
   on two — made a card taller than half the conversation it belongs to. An answer is now
   one line: its number, or the photograph it is about; its name, whole; and what it
   entails beside it, for as long as the line lasts. The whole of both is the button's
   title, and its name for a screen reader. Where the card is too narrow for a name and a
   detail side by side the detail goes under the name, a line each; where it is twice as
   wide the answers go two to a row. */
.ask-options { display: grid; gap: 5px; }
@container ask (min-width: 560px) { .ask-options { grid-template-columns: 1fr 1fr; } }
.ask-opt {
  /* The tile's ground, named once: the number sits on the corner of a photograph with a
     ring of it, and the ring has to change with the ground on hover and on the gate. */
  --opt-bg: var(--panel-2);
  display: flex; align-items: center; gap: 9px; min-width: 0; min-height: 38px; cursor: pointer; text-align: left;
  padding: 4px 10px 4px 6px; font: inherit; color: var(--text);
  background: var(--opt-bg); border: 1px solid var(--border); border-radius: 10px;
  transition: border-color .14s, background .14s, transform .14s;
}
.ask-opt:hover { --opt-bg: var(--panel); border-color: var(--accent); transform: translateY(-1px); }
/* The card opens with the first option focused — that is what makes it answerable
   from the keyboard, and it is `askCard`'s last act. Without a rule of its own that
   focus was drawn by the browser: a black ring, at rest, on the very option the
   accent below is trying to single out. The house outline instead, as on the
   version rails. */
.ask-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ask-opt:disabled { cursor: default; opacity: .55; transform: none; }
.ask-opt.on { --opt-bg: var(--panel); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* The one that spends.
   Every other option on a card answers a question; this one starts a paid
   generation, and until it was drawn differently the two were the same button —
   the click that picks a 9:16 and the click that costs forty-two credits, same
   border, same weight. So it carries the accent at rest, where the others only
   take it on hover: among two options it reads as the one that acts, which is what
   it is. It deliberately carries no figure — the amount is in the line above the
   card, written by the director, while what is actually charged is the server's
   own number, and a button is the worst place for those two to differ.
   `:disabled` is left to win afterwards, so an answered card goes quiet whole. */
.ask-opt.spends {
  --opt-bg: var(--accent-soft);
  border-color: var(--accent);
  /* Three layers, each doing one thing: the inner line thickens the border to two
     pixels without moving the text, the glow spreads that colour outwards, and the
     one below lifts the card off the other. The glow is blurred and not a second
     flat ring — a ring is a border drawn twice, and the card already carries the
     focus outline at rest, which would make three concentric lines of the same
     colour. A single harder border was not enough at a glance, which is the
     distance this choice is actually made at. */
  box-shadow:
    inset 0 0 0 1px var(--accent),
    0 0 14px 2px var(--accent-halo),
    0 4px 14px -6px var(--accent-line);
}
/* The hover of `.ask-opt` sets the plain panel behind it, which would wash the
   tint off exactly when the pointer is on it. */
.ask-opt.spends:hover { --opt-bg: var(--accent-soft); }
.ask-opt.spends .ask-opt-label { color: var(--accent-ink); }
.ask-opt.spends:disabled { --opt-bg: var(--panel-2); border-color: var(--border); box-shadow: none; }
/* The mark: the number, or the photograph with the number on its corner. The number
   stays on both, because it is how an answer is named out loud and in the director's
   text; the photograph is how a product is recognised before its name is read. */
.ask-opt-mark { position: relative; flex: none; display: grid; place-items: center; }
.ask-opt .opt-n { width: 20px; height: 20px; font-size: 11px; }
/* The size on the picture itself: a percentage of a grid cell sized by its content is a
   picture at its own height, and a portrait photograph ran down past its row. */
.ask-opt-pic {
  display: block; width: 30px; height: 30px; object-fit: cover; border-radius: 7px;
  background: var(--panel); outline: 1px solid var(--border); outline-offset: -1px;
}
.ask-opt-mark.pic .opt-n {
  position: absolute; top: -4px; left: -5px; width: 15px; height: 15px; font-size: 9.5px;
  /* Solid: the accent's tint is a wash, and over a photograph a wash is mud. */
  background: linear-gradient(var(--accent-soft), var(--accent-soft)), var(--panel);
  box-shadow: 0 0 0 2px var(--opt-bg);
}
.ask-opt-text { display: flex; align-items: baseline; gap: 8px; flex: 1 1 auto; min-width: 0; }
/* The name whole, and the detail in what is left of the line: a name is 1–5 words and is
   what the answer is chosen by, so it is the detail that gives way. */
.ask-opt-label {
  flex: 0 1 auto; min-width: 0; font-weight: 600; font-size: 13.5px; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ask-opt-detail {
  flex: 1 1 0; min-width: 0; font-size: 12px; color: var(--muted); line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* On the gate the detail is where the figure sits, and an ellipsis could take the figure:
   there it wraps, whole, under the name. */
.ask-opt.spends .ask-opt-text { flex-wrap: wrap; row-gap: 1px; }
.ask-opt.spends .ask-opt-detail { flex-basis: 100%; white-space: normal; }
@container ask (max-width: 339.98px) {
  .ask-opt-text { flex-direction: column; align-items: stretch; gap: 1px; }
  .ask-opt-detail { flex: none; }
}
/* What it costs, inside a line that describes what is being made.
   The rest of the detail is the description — a ratio, a duration, how many
   stills — and it is grey because it is context. This is the number the decision
   is taken on, and it was drawn as though it were context too. Full ink and bold,
   in place, so it is read without leaving the sentence it belongs to.
   Full ink in both cards, the accented one included: there the label is already
   accent, and giving the figure the same colour would merge the two into one pink
   block. The strongest ink on the page is what separates it. */
.ask-opt-cost { color: var(--text); font-weight: 700; }
/* Under a card that spends, the figure and nothing else: the coins and the number the
   click approves, on a hairline, in the ink the decision is taken in. Under a choice of
   several answers, «Confirm» alone. No card has a box of its own: the composer an inch
   below is where another answer is typed, and its placeholder says so. */
.ask-foot {
  display: flex; align-items: center; justify-content: flex-end; margin-top: 8px; padding-top: 8px;
  border-top: 1px solid var(--border);
}
.ask-cost { display: inline-flex; align-items: center; gap: 7px; color: var(--text); }
.ask-cost .sd-ic { flex: none; color: var(--accent-ink); }
.ask-cost-n { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
/* Two options that spend, each with its own figure: on the option, under its detail. */
.ask-opt-price {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 2px;
  font-size: 12.5px; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums;
}
.ask-opt-price .sd-ic { color: var(--accent-ink); }
.ask.answered .ask-foot { display: none; }
.ask-answer {
  display: flex; align-items: center; gap: 6px;
  margin: 10px 0 0; padding-top: 9px; border-top: 1px dashed var(--border);
  font-size: 13.5px; color: var(--accent-ink); font-weight: 600;
}
/* The photograph the answer was chosen by, kept in the record beside it. */
.ask-answer-pic {
  flex: none; width: 22px; height: 22px; object-fit: cover; border-radius: 5px;
  outline: 1px solid var(--border); outline-offset: -1px;
}

/* And the line on a question that spends, put back with a reopened conversation.
   Same rule above it, deliberately — it sits where an answer would — but in the
   muted ink and not the accent's: it is not an answer, and reading as one is the
   one thing it must not do. */
.ask-stale {
  margin: 10px 0 0; padding-top: 9px; border-top: 1px dashed var(--border);
  font-size: 13px; color: var(--muted);
}

/* Back to the bottom. It sits above the flow, not inside it: it must move nothing.
   The offset is everything under the log — the composer, and a question docked on
   it — which `watchComposerHeight` in chat-ui.js measures and writes here. Measuring
   the composer alone put the pill on the docked card. */
.chat-jump {
  position: absolute; left: 50%; bottom: calc(var(--below-log, 120px) + 10px); transform: translate(-50%, 8px);
  z-index: 4; padding: 6px 14px; cursor: pointer; opacity: 0; pointer-events: none;
  font: inherit; font-size: 12.5px; color: var(--ink-2);
  background: var(--panel); border: 1px solid var(--accent); border-radius: 999px;
  box-shadow: var(--shadow-1); transition: opacity .16s, transform .16s;
}
.chat-jump.on { opacity: 1; pointer-events: auto; transform: translate(-50%, 0); }
.msg.error { align-self: stretch; max-width: 100%; background: var(--danger-soft); border: 1px solid var(--danger-line); color: var(--danger-ink); font-size: 13.5px; }
.msg.error.msg-retry { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; }

.msg.thinking { padding: 14px; }
.dots { display: inline-flex; gap: 5px; }
.dots i { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); animation: blink 1.3s infinite; }
.dots i:nth-child(2) { animation-delay: .18s; }
.dots i:nth-child(3) { animation-delay: .36s; }
@keyframes blink { 0%, 60%, 100% { opacity: .25; } 30% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .dots i { animation: none; opacity: .6; } }

.tool {
  align-self: flex-start; display: flex; align-items: center; gap: 9px;
  font-size: 12.5px; color: var(--muted); padding: 5px 12px;
  border: 1px dashed var(--border); border-radius: 999px;
}
.tool.done { color: var(--ok); border-style: solid; border-color: var(--ok-line); }
/* A call that did not work, drawn as information and not as an alarm: the owner's word,
   «non può mostrare un errore così in chat». The director explains it in its next words,
   or a grey line of facts does (`settleFailures`), so the row only has to say that this one
   did not come out — the muted ink of a held line, a solid border to set it apart from a
   call still running. The class stays `error`: the checks count failures by it. */
.tool.error { color: var(--muted); border-style: solid; border-color: var(--border); }
.tool.error .tool-dot { background: var(--muted); }
.tool-spin { width: 10px; height: 10px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent); animation: spin .8s linear infinite; }
.tool-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
/* How many calls a folded line stands for (`foldToolRow`): the batch's ten lines as one. */
.tool-n { padding: 0 7px; border-radius: 999px; font-weight: 600; font-variant-numeric: tabular-nums; background: color-mix(in srgb, currentColor 12%, transparent); }
.tool-why {
  align-self: flex-start; max-width: 90%; margin: -2px 0 2px 12px;
  font-size: 12px; line-height: 1.45; color: var(--muted);
}
/* The line of facts under a failure the director did not explain: grey like the held
   refusal, in the reader's language, and the generation's id under it where there is one. */
.tool-why.told .msg-trace { margin-top: 2px; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .tool-spin { animation: none; } }

.msg.system {
  align-self: stretch; max-width: 100%; font-size: 12.5px; color: var(--muted);
  background: transparent; border: 1px dashed var(--border);
}

/* The uploaded image, inside the conversation and with no comment: the frame hugs
   it instead of stretching across the whole column, because there is no text to
   contain. As wide as it takes to judge it at a glance, and no wider. */
.msg.system.upload-only {
  align-self: flex-start; max-width: 240px; padding: 8px; border-style: solid;
}
.msg.system.upload-only .msg-upload { margin: 0; }
.msg-upload { margin: 10px 0 2px; max-width: 240px; }
.msg-upload { position: relative; }
.msg-upload img {
  width: 100%; display: block; border-radius: 10px; cursor: zoom-in;
  border: 1px solid var(--accent); background: var(--panel-2);
}
/* Removing an image uploaded by mistake: on the preview, where the thing to
   remove is. Always visible and not on hover — a control that only appears if you
   pass over it is a control that does not exist for anybody who does not know. */
.upload-drop {
  position: absolute; top: 6px; right: 6px; width: 24px; height: 24px; padding: 0;
  display: grid; place-items: center; cursor: pointer; line-height: 1; font-size: 15px;
  color: var(--on-scrim); background: var(--scrim); border: 0; border-radius: 50%;
}
.upload-drop:hover { background: var(--danger-ink); }
.msg-upload figcaption { font-family: var(--mono); font-size: 11px; color: var(--ink-2); margin-top: 4px; }

/* ---------- The stack: one item with several shots ----------

   A catalogue product comes in as three or four references — they are different
   angles on the same object, and the generator wants them all — but to whoever is
   looking it is one thing, chosen once. Three identical previews of the same
   helmet filled the conversation saying as much as the first.

   The effect is a shadow and not two extra elements: two offset borders behind the
   image, visible at the corners. No node added, no change of layout, and the
   margin exists only so the neighbours do not clip them. The count ("+2") stays
   written, because a stack says "there is more than one" but not how many — and
   how many is the number you come looking for. */
.stacked img {
  box-shadow:
    4px 4px 0 -1px var(--panel), 4px 4px 0 0 var(--border),
    8px 8px 0 -1px var(--panel), 8px 8px 0 0 var(--border);
}
.msg-upload.stacked { margin-bottom: 12px; padding-right: 9px; }
/* In the compact row the preview is 26px: there a stack of shadows would be a
   smudge. The space is enough, and the text line next to it states the count. */
.asset-row.stacked img { box-shadow: 2px 2px 0 -.5px var(--panel), 2px 2px 0 0 var(--border); margin-right: 3px; }

/* An uploaded audio file: the player in place of the preview. Wider than an image
   because a player's controls become unusable below 260px — the progress bar
   disappears before everything else. */
.msg.system.upload-only:has(.msg-audio) { max-width: 320px; }
/* A declared width, not a percentage: the message bubble fits its content, so a
   `width: 100%` on the player would depend on a width that depends on the player —
   and the browser falls back to the intrinsic size, which for an <audio> with no
   room is the player reduced to two buttons. */
.msg-audio { width: 300px; max-width: 100%; }
.msg-audio audio { width: 100%; display: block; }
/* Under a clip the conversation made: «Use this» puts it back on the job, «In use» says
   it is the one there. Small and quiet — the player is the thing, this is its state. */
.heard-use { display: flex; justify-content: flex-end; margin-top: 4px; }
.heard-use-btn {
  font: inherit; font-size: 12px; font-weight: 600; color: var(--accent);
  background: transparent; border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 10px; cursor: pointer;
}
.heard-use-btn:hover { border-color: var(--accent); }
.heard-use-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.heard-in-use { font-size: 12px; color: var(--ink-2); padding: 3px 0; }
.heard-in-use::before { content: '✓ '; color: var(--ok); }

.btn.icon { padding: 8px 11px; font-size: 15px; line-height: 1; }

/* The box above, the controls below.
   It used to be one row: the box grew as you typed, but it started 44px tall —
   that is, it invited you to write one line. A brief is longer than a line, and
   seeing it whole before sending it is the difference between correcting it and
   noticing afterwards. Autopilot/PRO live here because this is where they matter:
   at the moment Send is pressed, not at the top of the screen. */
/* ---- the question, against the box it is answered in ----

   A live question docks here instead of being appended to the log. The log is the
   *record* of a conversation and the composer is where you act in it, and a question
   put a scroll away from the box that answers it is how somebody comes to type a
   reply to a card they can no longer see.

   The two read as one object: the dock loses its bottom corners and its bottom
   border, the composer loses its top ones, and the join is a single hairline. Not a
   card floating above a field — a field with the question printed on top of it. */
.ask-dock { margin-top: 12px; }
.ask-dock[hidden] { display: none; }
.ask-dock .ask {
  margin: 0; border-radius: 18px 18px 0 0; border-bottom: 0;
  box-shadow: none; background: var(--panel);
}
/* The composer joins on when there is something docked, and keeps its own shape
   when there is not. `:has()` rather than a class toggled from the script: the state
   is «is the dock showing», which the DOM already knows, and a second copy of it in
   a class is a copy that can disagree.

   It sets no colour of its own. The dock drops its bottom border and the composer
   keeps its top one, so exactly one hairline sits between them — and the composer
   goes on having a single `:focus-within` treatment, which is a rule this repository
   already paid for: there were two once, an ink border and a magenta ring, and
   typing lit the box in both at the same time. */
.chat-col:has(.ask-dock:not([hidden])) .composer {
  margin-top: 0; border-radius: 0 0 18px 18px;
}
/* One line under a question rather than two: it is the question's other answer, and the
   question is what is being read (`paintPlaceholder` sets the rows). */
.chat-col:has(.ask-dock:not([hidden])) .composer textarea { min-height: 0; }

/* A floating card on the glass: 20px corners, the accent's hairline in both modes, and a
   long low shadow that lifts it off the column. Since the redesign it is shorter — two
   lines of text to start, growing as it is written — and its controls are one line.

   Its hairline is the accent's, with the faintest halo of it, in Autopilot as in PRO:
   the lit half of the switch in the bar answers «am I in PRO?», an inch below, and the
   box is the same box in both. */
.composer {
  display: flex; flex-direction: column; gap: 6px; margin-top: 12px; padding: 10px 10px 9px 12px;
  background: var(--field); border: 1px solid color-mix(in srgb, var(--accent) 52%, var(--border)); border-radius: 20px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 5%, transparent), 0 18px 36px -24px color-mix(in srgb, var(--ink) 55%, transparent);
  transition: border-color .16s, box-shadow .16s, background .16s;
}
.composer textarea {
  margin: 0; padding: 3px 2px 0; resize: none; min-height: 44px; max-height: 240px;
  overflow-y: auto; background: transparent; border: 0;
  font-size: var(--chat-fs); line-height: 1.55; letter-spacing: -.004em;
}
.composer textarea:focus { outline: none; }
/* One focus treatment, not two.
   There were two `:focus-within` rules — one turning the border to ink, a later one
   adding a solid 2px magenta ring — so typing lit the box up twice, in two colours,
   and it was the loudest thing on the screen. The resting hairline a step deeper, with
   the accent's soft halo behind it, says the same thing at a tenth of the volume. */
.composer:focus-within {
  background: var(--panel);
  border-color: color-mix(in srgb, var(--accent) 75%, var(--border));
  box-shadow: 0 0 0 4px var(--accent-soft), 0 18px 36px -24px color-mix(in srgb, var(--accent) 60%, transparent);
}
/* **One line**, as the owner's redesign asks: the reference, the two modes, the levers —
   in PRO the models and the sliders, in both modes the shape and the steps as icon chips —
   and Send at the far end. The tools are one group and Send another: the strip is
   `display: contents`, so its controls are the group's own flex items, and where the box
   is too narrow for all of them (PRO, on a narrow column) the last tools wrap to a second
   line inside their group rather than shrink past reading, while Send keeps the bottom
   right corner. No figure: the cost is said on the card of the click that spends. */
/* The references, over the text (the owner's word of 2026-10-24): small pictures that wrap,
   each with its × — on the corner, shown on hover and focus, always on a touch screen — and
   a sound or a file that is missing as a line of its own under them, with its player. */
.composer-refs { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; padding: 2px 2px 0; }
.composer-refs[hidden] { display: none; }
.ref-thumb { position: relative; flex: none; width: 46px; height: 46px; margin: 0; }
.ref-thumb img {
  display: block; width: 100%; height: 100%; object-fit: cover; cursor: zoom-in;
  border-radius: 10px; background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--border);
}
.ref-thumb.stacked img { box-shadow: 3px 3px 0 -1px var(--field), 3px 3px 0 0 var(--border); }
.ref-empty {
  display: grid; place-items: center; width: 100%; height: 100%; padding: 2px; overflow: hidden;
  border: 1px dashed var(--warn); border-radius: 10px; font-size: 9px; line-height: 1.1; text-align: center; color: var(--warn);
}
.ref-thumb .ref-x {
  position: absolute; top: -6px; right: -6px; display: grid; place-items: center; width: 20px; height: 20px; padding: 0;
  font: inherit; font-size: 13px; line-height: 1; cursor: pointer; color: var(--on-scrim); background: var(--scrim);
  border: 2px solid var(--field); border-radius: 50%; opacity: 0; transition: opacity .12s;
}
.ref-thumb:hover .ref-x, .ref-thumb:focus-within .ref-x { opacity: 1; }
.ref-thumb .ref-count, .ref-thumb .ref-id {
  position: absolute; bottom: 3px; padding: 0 4px; border-radius: 6px; font-size: 9.5px; font-weight: 700; line-height: 14px;
}
.ref-thumb .ref-count { right: 3px; color: var(--on-scrim); background: var(--scrim); }
.ref-thumb .ref-id { left: 3px; }
.composer-refs > .asset-row { flex: 1 0 100%; min-width: 0; }

.composer-bar { display: flex; align-items: flex-end; gap: 6px; min-width: 0; }
.composer-tools { flex: 1 1 auto; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; min-width: 0; }
.composer-tools > :not(.pro-strip) { flex: none; }
.composer-tools > .pro-strip:not([hidden]) { display: contents; }
.composer-bar #chat-send { flex: none; margin-left: auto; }
.composer .btn { white-space: nowrap; }

/* The reference button: a picture with a plus, in a ring the size of Send, so the two
   ends of the bar are one pair of round controls. Quiet at rest — it is the one on the
   bar that is not the action — and it takes the paper's lift on hover. */
.btn.icon.composer-attach {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; padding: 0; border-radius: 50%;
  background: transparent; border-color: var(--border); color: var(--ink-2);
  transition: background .14s, color .14s, border-color .14s;
}
.btn.icon.composer-attach:hover {
  background: var(--panel-2); color: var(--ink);
  border-color: color-mix(in srgb, var(--ink) 25%, var(--border));
}
.btn.icon.composer-attach:disabled:hover { background: transparent; border-color: var(--border); }
.composer-attach svg { display: block; }

/* The two modes as one pill beside it: the chosen one tinted, the other a word — the
   height of the chips beside it, so the line reads as one row of pills. */
.composer-bar .mode-switch { gap: 2px; padding: 2px; border-radius: 999px; height: 32px; align-items: center; }
.composer-bar .mode { padding: 0 11px; height: 26px; border-radius: 999px; font-weight: 600; font-size: 12.5px; }

/* ==========================================================================
   The AI Director
   ==========================================================================
   Two columns on the view's aurora: the conversation on glass, and the stage — the
   goal and the job at its head with the facts that decide the result as chips, what
   was made on a canvas, one piece at a time, and the strip of every generation. The
   rest of the brief — its words, the references, the timeline, the engine — is
   «Details», a drawer over the stage. The conversation has no head of its own: the
   job's name is the stage's. Everything is drawn in the tokens, so the dark theme and
   an agency's skin follow. */

/* A line the director remembered, or one the end-of-job pass proposes: a margin line
   like the studio's other notes, with its buttons inline, and wrapping as a whole on a
   narrow column rather than pushing the column wide. */
.chat-log > .msg.system.mem-chip {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center; gap: 4px 8px;
  border: 0; text-align: left;
}
.mem-chip-label { font-weight: 600; color: var(--ink-2); }
.mem-chip-kind {
  padding: 0 7px; font-size: 11px; font-weight: 600; color: var(--muted);
  border: 1px solid var(--border); border-radius: 999px;
}
.mem-chip-replaces { color: var(--muted); font-style: italic; overflow-wrap: anywhere; }
.mem-chip-text { min-width: 0; overflow-wrap: anywhere; color: var(--text); }
.mem-chip-text::before { content: "«"; }
.mem-chip-text::after { content: "»"; }
.mem-chip-acts { display: inline-flex; gap: 6px; }
.mem-chip-acts:empty { display: none; }
.mem-chip-btn {
  padding: 2px 9px; font: inherit; font-weight: 600; color: var(--accent-ink); cursor: pointer;
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
}
.mem-chip-btn:hover:not(:disabled) { border-color: var(--accent); }
.mem-chip-btn:disabled { opacity: .5; cursor: default; }

/* «Conversation resumed», centred between two hairlines. */
.chat-log > .msg.system.resumed {
  align-self: stretch; max-width: 100%; display: flex; align-items: center; gap: 10px; border: 0;
}
.msg.system.resumed::before, .msg.system.resumed::after {
  content: ""; flex: 1; height: 1px; background: var(--border);
}
.msg.system.resumed .msg-body { flex: 0 1 auto; }

/* ---- the stage: one card, the width the third column used to take ----
   The facts' card that stood beside the picture's went with the redesign: «take the
   right-hand column away … put the information in the centre». The card is the stage
   now — the job's name and its principal facts at its head, what was made on a canvas
   under them, the strip of every generation, and under all of it the brief as it fills
   in (`.gp-details`). It fills the column's height at least, so a canvas with little under
   it has the room. */
.chat-side > .gp-card.card {
  position: relative; flex: 1 0 auto; display: flex; flex-direction: column;
  min-height: 100%; margin: 0; padding: 0;
  background: var(--panel); border: 1px solid var(--dir-card-line); border-radius: 24px;
  box-shadow: var(--dir-card-shadow);
}
.gp-body { position: relative; flex: 1 0 auto; display: flex; flex-direction: column; min-width: 0; }
.gp-main {
  flex: 1 0 auto; display: flex; flex-direction: column; gap: 12px; min-width: 0;
  padding: 16px 18px 14px; container: gpmain / inline-size;
}
.gp-main > .project-foot { margin-top: 0; }

/* ---- the head: what this job is, and what can be done with all of it ----
   The goal's mark on its own tint, the goal small over the job's name, and at the right
   «Download all». Where the card is narrow it keeps its mark and gives up its words,
   which stay its name. */
.gp-head-acts { display: flex; align-items: center; gap: 8px; min-width: 0; }
.gp-id { flex: 1 1 auto; display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; min-width: 0; }
.gp-card .chat-kind { display: flex; align-items: center; flex-wrap: nowrap; gap: 12px; min-width: 0; }
.gp-card .kind-badge { gap: 10px; }
.gp-card .kind-badge .kind-ic {
  width: 42px; height: 42px; border-radius: 13px;
  background: linear-gradient(140deg, color-mix(in srgb, var(--k) 20%, var(--panel)), color-mix(in srgb, var(--k) 8%, var(--panel)));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--k) 22%, transparent), 0 8px 18px -10px color-mix(in srgb, var(--k) 55%, transparent);
}
.gp-name { display: grid; gap: 1px; min-width: 0; }
/* The goal as an eyebrow over the job, in its own colour. */
.gp-name .kind-lb {
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; line-height: 1.2; color: var(--k);
}
.gp-sub { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 8px; min-width: 0; color: var(--muted); }
.gp-title:empty { display: none; }
.gp-title {
  min-width: 0; overflow-wrap: anywhere; font-size: 17px; font-weight: 700; letter-spacing: -.015em; line-height: 1.25;
  color: var(--text); text-wrap: balance;
}
.gp-card .gp-sub .chat-flow { padding: 0; border: 0; background: none; font-size: 13px; font-weight: 500; color: var(--muted); }
/* No title yet: the job from the catalogue is the name. */
.gp-card .gp-sub .gp-title:empty + .chat-flow { font-size: 16px; font-weight: 700; letter-spacing: -.01em; color: var(--text); }
.gp-open { font-size: 15px; font-weight: 600; color: var(--muted); }

.gp-head-acts > .btn.small {
  flex: none; display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 14px;
  border-radius: 999px; font-size: 13px; font-weight: 600; color: var(--text);
  background: var(--panel); border-color: var(--border);
  transition: border-color .14s, background .14s, color .14s, box-shadow .14s;
}
.gp-head-acts > .btn.small:hover:not(:disabled) { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--accent-ink); }
.gp-head-acts > .btn.small .sd-ic { flex: none; }
@container gpmain (max-width: 520px) {
  .gp-head-acts > .btn.small { width: 34px; padding: 0; justify-content: center; }
  .gp-head-acts > .btn.small > span {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
}

/* **One fact decides the empty column**: `#result-card[hidden]`, which `paintResult`
   writes and nothing else keeps a copy of. The drawing and «Download all» read it here,
   so they cannot disagree about whether the column holds anything. Hidden while empty:
   the download — back, disabled, at the first generation. */
.gp-main:has(> .gp-stage[hidden]) .gp-dl,
.gp-main:has(> .gp-stage:not([hidden])) > .gp-empty { display: none; }
/* The foot carries a save that failed and nothing else (`footLabel` in app.js), so it is
   drawn only while it carries one — on the empty column as under a stage. */
.gp-main > .project-foot:not(:has(.err-hint)) { display: none; }

/* ---- the canvas ----
   What was made sits on a ground of its own, the Studio's: a soft light from above on a
   grey that is neither the card nor the picture — so a white product shot still has its
   edges — with the accent's halo behind the piece, faint enough to be light rather than
   colour. The empty column and the piece being made stand on the same ground, so nothing
   changes under the eye when the first picture lands.
   The owner found the grey flat, so the ground has depth without a picture of its own:
   a fine grid of dots, the director's aurora caught faintly in two corners (the accent
   above, the cool one below — a skin turns both into its accent), and a soft shade at
   the edges. All of it gradients on tokens, so the dark theme and a skin repaint it. */
.gp-empty,
.gp-card .ws-stage {
  position: relative; isolation: isolate; border-radius: 18px;
  background:
    radial-gradient(circle at 1px 1px, var(--dir-canvas-dot) 1px, transparent 1.4px) 0 0 / 18px 18px,
    radial-gradient(70% 55% at 12% 0%, color-mix(in srgb, var(--dir-aurora-1) 55%, transparent), transparent 72%),
    radial-gradient(65% 60% at 100% 100%, color-mix(in srgb, var(--dir-aurora-3) 70%, transparent), transparent 70%),
    radial-gradient(120% 95% at 50% 0%, var(--dir-canvas-hi) 0%, var(--dir-canvas-lo) 72%);
  box-shadow: inset 0 0 0 1px var(--dir-canvas-line), inset 0 0 70px -12px var(--dir-canvas-shade);
}
.gp-empty::after,
.gp-card .ws-stage::after {
  content: ""; position: absolute; z-index: -1; inset: 8% 14%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, var(--accent-halo), transparent);
  opacity: .55;
}
.gp-card .ws-stage { min-width: 0; padding: 16px 16px 14px; }

/* The empty column: a picture of pictures, the title, and two lines (`paintGenEmpty`).
   Not a placeholder for what is coming — that is the card `#result-wait` draws, in the
   shape of the request — but the answer to «what is this column for». */
.gp-empty {
  flex: 1 1 auto; display: grid; align-content: center; justify-items: center; gap: 6px;
  margin: 0; padding: 30px 20px 40px; text-align: center;
}
.gp-empty::after { inset: 18% 22%; }
.gp-empty-art { position: relative; width: min(300px, 82%); margin-bottom: 18px; }
.gp-empty-art::before {
  content: ""; position: absolute; inset: -14% -8%; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, var(--accent-halo), transparent);
}
.gp-empty-art svg { position: relative; display: block; width: 100%; height: auto; overflow: visible; }
@media (prefers-reduced-motion: no-preference) {
  .gp-empty-art svg { animation: gp-float 6s ease-in-out infinite alternate; }
}
@keyframes gp-float { to { transform: translateY(-8px); } }
.ge-back { fill: var(--panel-2); stroke: var(--border); stroke-width: 1.5; }
.ge-front { fill: var(--panel); stroke: var(--accent-line); stroke-width: 1.5; filter: drop-shadow(0 14px 22px var(--accent-halo)); }
.ge-glyph, .ge-back-glyph { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.ge-glyph > *, .ge-back-glyph > * { vector-effect: non-scaling-stroke; }
.ge-glyph { stroke: var(--accent); stroke-width: 2.4; }
.ge-back-glyph { stroke: var(--border); stroke-width: 2; }
.ge-spark { fill: var(--accent); }
.gp-empty-title {
  margin: 0 0 4px; max-width: 100%; font-size: clamp(19px, 5.4cqi, 28px); font-weight: 700; line-height: 1.2;
  letter-spacing: -.02em; color: var(--text); text-wrap: balance;
}
.gp-empty-line { margin: 0; max-width: 40ch; font-size: 14.5px; line-height: 1.5; color: var(--muted); }
/* Stacked under the conversation the drawing is smaller: there it pushes the strip and
   the chips down the first screen. */
@container gp (max-width: 599.98px) {
  .gp-empty { padding: 18px 16px 24px; }
  .gp-empty-art { width: min(180px, 60%); margin-bottom: 10px; }
}

/* ---- the piece on the stage ----
   The picture lifted off the canvas by a shadow, its corners rounded, and under it one
   row: «02 / 04», its name, the arrows and what can be done with it. */
.gp-card .result-stage { padding: 0; background: none; border: 0; border-radius: 0; }
/* The stage's ⋯ (`stageMenu`, chat-ui.js): every action on the piece, in the grey's corner,
   the same place for a picture and a video. The picture's «enlarge» corner moved to the
   picture's other side for it, so the two never sit on one another. */
.gp-card .stage-more {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  display: grid; place-items: center; width: 36px; height: 36px; padding: 0; cursor: pointer;
  color: var(--text); border: 1px solid var(--dir-card-line); border-radius: 11px;
  background: color-mix(in srgb, var(--panel) 84%, transparent); backdrop-filter: blur(6px);
  box-shadow: 0 6px 16px -10px var(--dir-piece-shadow);
}
.gp-card .stage-more:hover { background: var(--panel); }
.gp-card .stage-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gp-card .stage-more[hidden] { display: none; }
.gp-card .stage-more.busy svg { animation: stage-more-busy 1s ease-in-out infinite; }
@keyframes stage-more-busy { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .gp-card .stage-more.busy svg { animation: none; } }
/* How tall the piece may stand: the column's height once the card's head and the row under
   the piece are on it — the owner's «massima» (2026-10-24), some 670px at 1440×900 where it was
   460. The strip no longer has to fit under it on the first screen: it stands in the side
   column beside the stage (`.ws-side`), and a wide piece's height is the width's. The player
   carries its bar and the line about the archive, so it stands a little shorter. Never under 300px. This is the one declaration of
   the figure: the wait card holds the same box, so nothing moves when the piece lands. */
.gp-card .result-card { --stage-h: max(300px, 100svh - 232px); }
.gp-card .result-card.on-player { --stage-h: max(300px, 100svh - 262px); }
.gp-card .result-pic { position: relative; display: block; width: fit-content; max-width: 100%; margin: 0 auto; }
.gp-card .result-shot img {
  width: auto; height: auto; max-width: 100%; min-height: min(var(--stage-h), 300px);
  border-radius: 12px; background: var(--panel);
  box-shadow: 0 26px 50px -30px var(--dir-piece-shadow), 0 2px 6px -2px var(--dir-piece-shadow);
}
/* Once decoded, the picture's own proportions: the floor above is for the wait (`paintResult`). */
.gp-card .result-shot img.is-loaded { min-height: 0; }
.gp-card .result-dl {
  top: 10px; left: 10px; right: auto; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 11px;
  background: color-mix(in srgb, var(--scrim) 80%, transparent); backdrop-filter: blur(6px);
}
.gp-card .result-shot figcaption {
  align-items: center; justify-content: flex-start; gap: 10px; margin-top: 14px;
  font-size: 13.5px; color: var(--text);
}
.gp-card .result-shot figcaption b { font-family: inherit; font-size: 13.5px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; }
.gp-card .result-shot figcaption b .result-n { color: var(--accent-ink); }
.gp-card .result-shot figcaption b .result-of { margin-left: 2px; font-weight: 500; }
.result-navs { display: inline-flex; gap: 6px; }
/* The picture's label under the stage comes from what the director wrote, and a long
   one wraps in the caption row rather than pushing the arrows out of the card. */
.gp-card .result-shot figcaption .result-what { min-width: 0; overflow-wrap: anywhere; font-weight: 600; }
.gp-card .result-navs .result-nav {
  position: static; transform: none; display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 50%; background: var(--panel); color: var(--text);
  border: 1px solid var(--border); box-shadow: 0 4px 10px -6px var(--dir-piece-shadow);
  transition: border-color .14s, color .14s, transform .14s;
}
.gp-card .result-navs .result-nav:hover { border-color: var(--accent); color: var(--accent-ink); }
.gp-card .result-navs .result-nav[hidden] { display: none; }
.result-act { display: inline-flex; align-items: center; gap: 8px; }
.gp-card .result-acts { gap: 8px; }
.result-acts .btn.small.result-act {
  min-height: 36px; padding: 0 14px; gap: 7px; border-radius: 999px; font-size: 13px; font-weight: 600; white-space: nowrap;
}
.result-acts .btn.small.result-act:not(.accent) { background: var(--panel); }
.result-acts .btn.small.result-act:not(.accent):hover:not(:disabled) { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--accent-ink); }
.result-acts .btn.small.result-act.accent {
  background: linear-gradient(135deg, var(--accent), color-mix(in oklab, var(--accent) 62%, var(--dir-violet)));
  border-color: transparent; box-shadow: 0 10px 20px -12px var(--accent);
}
.result-acts .btn.small.result-act.accent:hover:not(:disabled) { filter: brightness(1.06); }
/* A narrow stage: the outlined actions keep their marks and give up their words on screen —
   still their names, and their tooltips — while the filled one, the one the card invites,
   keeps both. On a phone the video's row was four lines: the arrows, then each button alone. */
@container gpmain (max-width: 520px) {
  .gp-card .result-acts .btn.small.result-act:not(.accent) { width: 36px; padding: 0; justify-content: center; }
  .gp-card .result-acts .result-act:not(.accent) .act-word {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  /* And two lines where there were four: the arrows and the marks on one, at its two ends,
     and the filled action across the whole width under them. */
  .gp-card .result-shot .result-acts, .gp-card .video-acts { display: contents; }
  .gp-card .result-acts > .result-act:not(.accent):first-child { margin-left: auto; }
  .gp-card .result-acts > .btn.small.result-act.accent { flex: 1 0 100%; justify-content: center; }
}

/* The player, the same way: lifted off the canvas, its actions in a row under it and the
   line about the archive under them, quieter. */
.gp-card .result-video {
  max-height: var(--stage-h); border: 0; border-radius: 14px; box-shadow: 0 26px 50px -28px var(--dir-piece-shadow);
}
.gp-card .video-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.gp-card .video-navs:empty { display: none; }
.gp-card .video-acts { justify-content: flex-end; margin: 0 0 0 auto; }
/* The version's star: the icon alone, square, filled on a favourite. */
.video-star[aria-pressed="true"] { color: var(--accent-ink); }
.video-star[aria-pressed="true"] .sd-ic { fill: currentColor; }
/* The actions that are an icon alone — «Delete» under a picture and on the video's bar, the version's star:
   square. As specific as the rule above that gives every action its padding, or that rule wins and the
   14px either side leave the icon a sliver 6px wide inside its round button; and an icon never shrinks. */
.result-acts .btn.small.result-act.result-del,
.result-acts .btn.small.result-act.video-del,
.result-acts .btn.small.result-act.video-star { width: 36px; padding: 0; justify-content: center; }
.result-acts .btn.small.result-act .sd-ic { flex: none; }
.result-del:hover, .video-del:hover { color: var(--danger-ink); background: var(--danger-soft); border-color: var(--danger-ink); }
.gp-card .video-note { margin: 10px 0 0; text-align: center; font-size: 12px; }
.gp-card .video-note[hidden] { display: none; }

/* ---- the strip: every generation of the job ----
   A title and its count, the words about what is ready and kept, and the tiles: what the
   stage walks, one per piece — a picture, the video (by the version on its player), a
   piece being made. The one on the stage is ringed in the accent, the kept ones carry
   their tick filled. */
.gp-strip { min-width: 0; margin-top: 14px; }
.gp-strip-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 4px 12px; margin: 0 2px 10px; }
.gp-strip-title {
  display: inline-flex; align-items: center; gap: 8px; margin: 0;
  font-size: 13px; font-weight: 700; letter-spacing: .01em; color: var(--text); text-transform: none;
}
.gp-strip-title .gp-count { font-variant-numeric: tabular-nums; }
#result-count { margin: 0; }
#result-count:not(:empty) { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--muted); }
#result-count:not(:empty) .sd-ic { color: var(--ok); }
.btn.gp-dl .sd-ic { flex: none; }
.gp-count:not(:empty) {
  padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 700; color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel)); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
}

/* A tile is a fixed size and never as wide as its caption: with the automatic minimum a
   flex item has, a long label held its tile wide and the next one — a tile still being
   made, «being made · 0:02 · 13%» — was pushed past the strip's edge, cut, with a
   scrollbar under the pair. The caption gives way instead: a picture's label ends in «…»,
   and the tile still being made wraps its state onto a second line. */
.gp-card .result-strip { gap: 12px; margin-top: 0; padding: 2px 2px 6px; }
.gp-card .result-strip .shot { flex: 0 0 116px; min-width: 0; max-width: 116px; transition: transform .16s; }
@media (hover: hover) {
  .gp-card .result-strip .shot:hover { transform: translateY(-2px); }
}
.gp-card .result-strip .shot img,
.gp-card .result-strip .shot-player video {
  aspect-ratio: 4 / 3; border-radius: 12px; border: 1px solid var(--border);
  transition: box-shadow .16s, border-color .16s;
}
.gp-card .result-strip .shot.on img,
.gp-card .result-strip .shot-player.on video {
  border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent), 0 10px 22px -10px var(--accent);
}
.gp-card .result-strip .shot.kept:not(.on) img { border-color: var(--k); box-shadow: 0 0 0 2px var(--k); }
.gp-card .result-strip .shot figcaption {
  display: block; margin-top: 7px; text-align: left; font-size: 12px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gp-card .result-strip .shot.on figcaption { font-weight: 600; color: var(--text); }
.gp-card .result-strip .shot-slot figcaption { white-space: normal; }
/* The video's tile: its frame with a play mark over it, so among stills it reads as the
   film it is. */
.shot-play {
  position: absolute; left: 50%; top: 50%; z-index: 1; display: grid; place-items: center;
  width: 30px; height: 30px; margin: -15px 0 0 -15px; border-radius: 50%; pointer-events: none;
  color: var(--on-scrim); background: color-mix(in srgb, var(--scrim) 85%, transparent); backdrop-filter: blur(4px);
}
.shot-play .sd-ic { margin-left: 2px; }
/* The tile still being made: framed in the accent, a small spinner, its number in the
   corner. Failed, a red frame and no spinner. */
.gp-card .result-strip .slot-box {
  height: auto; aspect-ratio: 4 / 3; min-height: 0; display: grid; place-items: center;
  border: 1.5px solid var(--accent); border-radius: 12px; background: var(--accent-soft);
}
.gp-card .result-strip .slot-box::after { content: none; }
.gp-card .result-strip .shot-slot.on .slot-box { box-shadow: 0 0 0 3px var(--accent-soft), 0 10px 22px -12px var(--accent); }
.slot-spin { width: 22px; height: 22px; border-radius: 50%; border: 2.5px solid var(--accent-line); border-top-color: var(--accent); }
@media (prefers-reduced-motion: no-preference) { .slot-spin { animation: sd-turn 1s linear infinite; } }
.slot-box > .slot-n {
  position: absolute; left: 8px; bottom: 6px; font-size: 11.5px; font-weight: 600; line-height: 1;
  color: var(--muted); font-variant-numeric: tabular-nums;
}
.gp-card .result-strip .shot-slot.failed .slot-box { border-color: var(--danger); background: var(--danger-soft); }
.shot-slot.failed .slot-spin { display: none; }
/* The ⤓'s 44px target (`.shot-dl::after`, centred on a button 5px in from the corner)
   reached 5px past the last tile, and the strip — a scroller — scrolled by those 5px,
   with a scrollbar under two tiles that fit. Here the target is anchored at the tile's
   corner instead: the same 44px, and the same button inside it. */
.result-strip .shot-dl::after { top: -5px; right: -5px; left: auto; transform: none; }
/* A star, the favourites: an outline always visible, so it is found without hovering,
   and filled in the goal's colour once the picture is one of them. */
.gp-card .shot-keep { top: 7px; left: 7px; background: rgba(255, 255, 255, .92); border-color: var(--border); color: var(--muted); }
.gp-card .shot-keep .sd-ic { stroke-width: 2; }
.gp-card .shot-keep:hover { background: #fff; color: var(--k); }
.gp-card .shot-keep[aria-pressed="true"] { background: var(--k); border-color: #fff; color: var(--on-accent); }
.gp-card .shot-keep[aria-pressed="true"] .sd-ic { fill: currentColor; }
/* «Edited»: a version made from another picture of the row, not a generation of its own.
   Bottom left, clear of the star above it and of the ⤓ in the other corner. */
.shot-edited {
  position: absolute; left: 7px; bottom: 7px; z-index: 2; pointer-events: none;
  padding: 1px 7px; border-radius: 999px;
  font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: #fff; background: rgba(15, 17, 40, .72);
}
/* A version too large to decode, drawn by the picture it was made from: its size, where «Edited» goes.
   Numbers, so neither capitals nor tracking, and small enough for «16K · 15360×15360» in a 116px tile. */
.shot-edited.shot-heavy {
  max-width: calc(100% - 14px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 9.5px; letter-spacing: 0; text-transform: none;
}
.result-heavy {
  position: absolute; left: 10px; bottom: 10px; z-index: 2; pointer-events: none;
  padding: 3px 9px; border-radius: 999px;
  font-size: 12px; font-weight: 700; color: #fff; background: rgba(15, 17, 40, .72);
}
.gp-card .shot-state { top: 9px; left: 38px; }

/* ---- the details, under the stage, closed ----
   It was «Details», a drawer over the stage opened from its corner; then the brief laid out
   under the generation, in sight, filling in as the director decides; and since the owner's
   word of 2026-10-24 a fold again, under the generations and closed until asked for — «se ci
   clicco vedo i dettagli, altrimenti rimane tutto più pulito»: the flow, the brief and what
   the director decided, the scenes, the advanced settings. Its body is the grid the section
   was (`.gp-fold-body`): a `<details>` lays its own children out as it likes. */
.gp-details { margin-top: 4px; border-top: 1px solid var(--border); }
.gp-fold-head {
  display: flex; align-items: baseline; gap: 10px; padding: 14px 2px; cursor: pointer; list-style: none;
  font-size: 14px; color: var(--text);
}
.gp-fold-head::-webkit-details-marker { display: none; }
.gp-fold-head::after {
  content: "\203a"; align-self: center; margin-left: auto; font-size: 18px; line-height: 1; color: var(--muted);
  transform: rotate(90deg); transition: transform .15s;
}
.gp-details[open] > .gp-fold-head::after { transform: rotate(270deg); }
.gp-fold-head:hover .gp-fold-title { color: var(--accent-ink); }
.gp-fold-head:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
.gp-fold-title { font-weight: 700; }
.gp-fold-sub { font-size: 12.5px; color: var(--muted); }
.gp-fold-body { display: grid; gap: 20px; padding: 2px 0 6px; }
.gp-fold-body > * { min-width: 0; }
.gp-details .gp-card-title { margin: 0; }
.gp-sec-head { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
.gp-sec-head .gp-card-title { margin: 0; }
/* On a flow, what waits for the person, under the preview and never folded away
   (`paintFlowView`'s `now`): the step with its «Done», the check, the web research. */
.gp-flow-now {
  display: grid; gap: 10px; padding: 12px 14px; border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--accent) 32%, var(--border));
  background: color-mix(in srgb, var(--accent) 4%, var(--panel));
}
.gp-flow-now[hidden] { display: none; }
/* The Autopilot view, in the details on a conversation on a flow (`app/js/autopilot.js`):
   the flow, its steps as a row of dots that wraps, and the step it is on; what waits for a
   click is drawn under the preview (`.gp-flow-now`). Hidden off a flow. */
.gp-flow { display: grid; gap: 12px; padding: 12px 14px 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel-2); }
.gp-flow[hidden] { display: none; }
/* The conversation's jobs, oldest first («Music ✓ → Video»), when it did more than one. */
.fv-jobs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.fv-jobs-k { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.fv-jobs-list { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 0; padding: 0; list-style: none; }
.fv-job { display: inline-flex; align-items: center; font-size: 12.5px; color: var(--muted); }
.fv-job + .fv-job::before { content: '→'; margin-right: 4px; color: var(--muted); }
.fv-job-name, .fv-job-open { display: inline-flex; align-items: center; min-height: 30px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel); font: inherit; color: inherit; }
.fv-job-open { cursor: pointer; }
.fv-job-open:hover { border-color: var(--accent); color: var(--accent-ink); }
.fv-job.is-done { color: var(--text); }
.fv-job.is-now .fv-job-name { border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.fv-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; }
.fv-head .gp-card-title { margin: 0; }
.fv-cat { font-size: 12.5px; color: var(--muted); }
.fv-mode { margin-left: auto; padding: 2px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 600; color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
.fv-steps { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.fv-step { display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel); font-size: 12.5px; color: var(--muted); }
.fv-dot { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid currentColor; flex: none; }
.fv-step.is-done { color: var(--text); }
.fv-step.is-done .fv-dot { background: currentColor; }
.fv-step.is-current { color: var(--accent-ink); border-color: var(--accent); font-weight: 600; }
.fv-step.is-current .fv-dot { background: var(--accent); border-color: var(--accent); }
.fv-step.is-optional:not(.is-done):not(.is-current) { border-style: dashed; }
.fv-opt { font-size: 11px; font-weight: 400; color: var(--muted); }
.fv-now { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 13.5px; }
.fv-now-k { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.fv-now-v { color: var(--text); }
.fv-done { margin-left: auto; min-height: 36px; }
/* The decisive check: what it found, and «Check again» and «Use it anyway» beside it. */
.fv-check { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 12px; border-radius: 12px; background: var(--panel-2); }
.fv-check-why { flex: 1 1 220px; margin: 0; font-size: 13px; line-height: 1.45; color: var(--text); }
.fv-check-again, .fv-check-accept { min-height: 36px; }
/* Web research: the summary with its pages under it, never apart, and the button that asks for it. */
.fv-research { display: grid; gap: 8px; padding: 10px 12px; border-radius: 12px; background: var(--panel-2); }
.fv-research-k { margin: 0; font-size: 11.5px; font-weight: 600; color: var(--muted); }
.fv-research-sum { margin: 0; font-size: 13px; line-height: 1.5; color: var(--text); white-space: pre-line; overflow-wrap: anywhere; }
.fv-research-src { display: grid; gap: 4px; margin: 0; padding-left: 18px; font-size: 13px; line-height: 1.4; }
.fv-research-src a { color: var(--accent-ink); overflow-wrap: anywhere; }
.fv-research-host { margin-left: 6px; font-size: 12px; color: var(--muted); }
.fv-research-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; }
.fv-research-when { font-size: 12px; color: var(--muted); }
.fv-research-forget { min-height: 32px; }
.fv-research-ask { display: flex; flex-wrap: wrap; gap: 8px; }
.fv-research-q { flex: 1 1 200px; min-width: 0; min-height: 36px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px; }
.fv-research-go { min-height: 36px; }
.fv-research-why { margin: 0; font-size: 13px; color: var(--danger); }
.gb-rows { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr)); gap: 8px; margin: 0; }
.gb-row { min-width: 0; padding: 9px 12px 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel-2); }
.gb-row.wide { grid-column: 1 / -1; }
.gb-row dt { font-size: 11.5px; font-weight: 600; letter-spacing: .01em; color: var(--muted); }
.gb-row dd { margin: 3px 0 0; font-size: 13.5px; line-height: 1.45; color: var(--text); overflow-wrap: anywhere; }
/* Still to be chosen: the outline of a fact, as the chips above draw theirs. */
.gb-row.pending { background: transparent; border-style: dashed; }
.gb-row.pending dd { color: var(--muted); font-style: italic; }
.gb-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.gb-chip { padding: 3px 10px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border); font-size: 13px; }
.gb-empty { display: block; margin: -4px 0 10px; font-size: 13px; }
/* What the director decided on its own, one line each, under the facts. */
.gb-assumed { margin-top: 10px; padding: 10px 12px; border-radius: 12px; background: color-mix(in srgb, var(--accent) 5%, var(--panel)); }
.gb-assumed-k { display: block; font-size: 11.5px; font-weight: 600; color: var(--accent-ink); }
.gb-assumed ul { margin: 4px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.45; color: var(--text); }
.gb-sub { margin: 0 0 8px; font-size: 13px; font-weight: 700; color: var(--text); }
/* The section's own gap spaces its parts: the lists' margins were the drawer's. */
.gp-details .timeline-strip { margin-top: 0; }
@media (prefers-reduced-motion: no-preference) {
  .gb-row.is-new, .gb-assumed.is-new { animation: gp-spec-in .45s cubic-bezier(.2, .7, .2, 1) both; }
  .gb-row.is-changed, .gb-assumed.is-changed { animation: gp-spec-flash 1.2s ease-out; }
}

/* ---- «Advanced settings», folded, at the foot of the brief ---- */
.gp-card .res-folds { margin-top: 14px; border-top: 0; }
.gp-card .res-fold { border: 1px solid var(--border); border-radius: 14px; background: var(--panel); }
.gp-card .res-fold > summary { gap: 10px; padding: 12px 14px; font-size: 13.5px; }
.gp-card .res-fold > summary::after { transform: rotate(90deg); font-size: 18px; color: var(--text); }
.gp-card .res-fold[open] > summary::after { transform: rotate(270deg); }
.res-fold-ic { flex: none; color: var(--text); }
.gp-card .res-fold-what { color: var(--text); }
.res-fold-row { display: flex; align-items: baseline; gap: 8px; margin: 0 14px 8px; font-size: 13px; }
.res-fold-row .hint { margin: 0; }
.res-fold-k { font-weight: 600; color: var(--text); }
/* What the piece on the stage was made with, one row each (`paintPieceFacts`). */
/* The piece's facts open the folds, out of any fold of their own: the engine fold describes a
   picture and is hidden while the player is on the stage, and a version's «made on Veo 3.1,
   asked on Seedance» is exactly what has to be read there. */
.res-facts { padding: 10px 0 2px; }
.res-facts .res-fold-row { margin: 0 2px 8px; }
.res-facts[hidden] { display: none; }
.gp-card .res-fold > .hint, .gp-card .res-trace { margin: 0 14px 12px; }

/* ---- the foot: a save that failed, with its mark ---- */
.gp-card .project-foot { margin-top: auto; padding-top: 10px; }
.gp-card .project-foot .hint { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; }
.gp-card .project-foot .hint:empty { display: none; }

/* The stage's column scrolls on its own: the stage stays at the top, and a long strip or
   a stacked drawer does not drag the conversation with it. One card in it, as tall as the
   column at least. */
.chat-side {
  display: flex; flex-direction: column; gap: 14px; min-width: 0; min-height: 0;
  height: 100%; overflow-y: auto; overscroll-behavior: contain; padding: 0 4px 0 0;
}
.chat-side .card { margin-bottom: 0; }

/* The goal's colour, `--k`, on the head's mark and the kept frames; with no goal yet,
   the accent. The card is a container, so what it holds is laid out by its own width
   rather than the window's: the column beside the conversation is a different width at
   every window size. */
.gp-card { container-type: inline-size; container-name: gp; }
.gp-card:not([data-kind]) { --k: var(--accent); }
.gp-stage { min-width: 0; }
.gp-stage[hidden] { display: none; }
.gp-card .gp-card-title { margin: 0 0 12px; font-size: 16px; font-weight: 700; text-transform: none; letter-spacing: -.015em; color: var(--text); }

/* The tick on a thumbnail: keep this one. A ring at rest in the top corner, filled in
   the goal's colour when pressed, and the thumbnail framed to match — so the kept ones
   read as a set across the strip without anybody counting them. 24px, the minimum
   target WCAG 2.5.8 asks for, and on a finger 30px. */
.shot-keep {
  position: absolute; top: 5px; left: 5px; z-index: 2;
  display: grid; place-items: center; width: 24px; height: 24px; padding: 0;
  border-radius: 50%; border: 1.5px solid #fff; cursor: pointer;
  background: rgba(15, 17, 40, .38); color: transparent;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .28); transition: background .14s, color .14s, transform .14s;
}
.shot-keep .sd-ic { stroke-width: 2.6; }
.shot-keep:hover { background: rgba(15, 17, 40, .55); color: rgba(255, 255, 255, .85); }
.shot-keep:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.shot-keep[aria-pressed="true"] { background: var(--k); border-color: var(--k); color: var(--panel); }
@media (prefers-reduced-motion: no-preference) {
  .shot-keep[aria-pressed="true"] { animation: shot-kept .22s ease-out; }
}
@keyframes shot-kept { 50% { transform: scale(1.18); } }
@media (pointer: coarse) { .shot-keep { width: 30px; height: 30px; } }
.result-strip .shot.kept img { border-color: var(--k); box-shadow: 0 0 0 2px var(--k); }

@keyframes gp-spec-in { from { opacity: 0; transform: translateY(4px) scale(.96); } }
@keyframes gp-spec-flash {
  0%, 25% {
    border-color: color-mix(in srgb, var(--k) 55%, var(--border));
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--k) 14%, transparent);
  }
}
.gp-card .timeline-strip[hidden] { display: none; }

.asset-list { margin-top: 12px; display: flex; flex-direction: column; gap: 5px; }
.asset-row {
  display: flex; align-items: center; gap: 8px; font-size: 12.5px;
  padding: 5px 8px; background: var(--panel-2); border-radius: 7px;
}
.asset-row img { width: 26px; height: 26px; object-fit: cover; border-radius: 5px; flex: none; }
/* The player for an audio file among the references. A 26px row cannot hold the
   controls, so the row becomes a column: you listen first, then read what it is
   for. */
.asset-row:has(.asset-audio) { flex-wrap: wrap; }
.asset-row .asset-audio { width: 100%; height: 32px; order: -1; }
.asset-row .ref { font-family: var(--mono); color: var(--ink-2); flex: none; }
.asset-row .what { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.asset-row .asset-id-badge {
  flex: none; font-family: var(--mono); font-size: 10px; letter-spacing: .04em;
  padding: 2px 5px; border-radius: 4px; background: var(--code-bg); color: var(--ink-2);
}

.asset-row .drop {
  flex: none; background: none; border: 0; color: var(--muted); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0 2px;
}
.asset-row .drop:hover { color: var(--danger-ink); }

.timeline-strip { margin-top: 12px; display: flex; flex-direction: column; gap: 5px; }
.tl-beat { display: flex; gap: 10px; font-size: 12.5px; padding: 5px 8px; background: var(--panel-2); border-radius: 7px; }
.tl-time { font-family: var(--mono); color: var(--ink-2); white-space: nowrap; }
.tl-action { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.avatar-picker {
  align-self: stretch; max-width: 100%; padding: 12px 14px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
}
.avatar-picker-title { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.avatar-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px; }
.avatar-card { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.avatar-card img {
  width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 9px;
  border: 1px solid var(--border); cursor: zoom-in; display: block; background: var(--panel);
}
.avatar-card figcaption {
  font-size: 11.5px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* «Browse the gallery», under the faces: the window that picks one more (avatar-gallery.js). */
.avatar-gallery-go { margin-top: 12px; }

/* The style test. The tiles are wider than the avatars and take the project's
   aspect ratio: a style is judged on the framing the video will really have, not on
   a cropped square. The ratio arrives from the JS as --tile-ratio. */
.style-picker .avatar-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.style-card img { aspect-ratio: var(--tile-ratio, 1); }
.style-card figcaption { white-space: normal; font-weight: 600; }
.style-picker.answered { opacity: .72; }
/* The summary of a test already decided: the choice is visible, the others remain
   as a reminder of what was rejected. */
.style-card.picked img { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.style-mark { min-height: 16px; font-size: 11.5px; font-weight: 700; color: var(--accent-ink); }

.lightbox {
  position: fixed; inset: 0; z-index: 100; display: flex; flex-direction: column;
  background: var(--scrim-strong); backdrop-filter: blur(2px);
}
.lightbox-frame {
  flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center;
  overflow: auto; padding: 20px;
}
.lightbox-frame img { max-width: 100%; max-height: 100%; object-fit: contain; cursor: zoom-in; display: block; }
/* Actual size: the image leaves the frame and the frame scrolls. */
.lightbox-frame.zoomed { align-items: flex-start; justify-content: flex-start; }
.lightbox-frame.zoomed img { max-width: none; max-height: none; width: auto; cursor: zoom-out; }
.lightbox-bar {
  display: flex; align-items: center; gap: 12px; padding: 12px 20px;
  border-top: 1px solid var(--border); background: var(--panel);
}
.lightbox-caption { flex: 1; font-size: 13px; color: var(--muted); min-width: 0; }
.lightbox-save { display: inline-flex; align-items: center; gap: 6px; }

/* The approved library, as «Approved library» on the Characters tab opens it: in the
   app's large sheet, whose body is the panel — its three buttons first, the line that
   counts, then one row per character with every photo's verdict. The sheet already
   draws the card, so the panel draws no box of its own. */
.lib-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; }
.lib-bar .hint { margin: 0; }
.library-panel { min-width: 0; }
.library-panel > .hint { margin: 0 0 8px; }
.library-panel > .hint:empty { display: none; }
.lib-group { padding: 14px 0; border-top: 1px solid var(--border); }
.lib-group:first-child { border-top: 0; padding-top: 6px; }
.lib-head { display: flex; align-items: center; justify-content: space-between; gap: 8px 10px; flex-wrap: wrap; }
.lib-head strong { flex: 1 1 200px; min-width: 0; font-size: 14.5px; color: var(--ink); overflow-wrap: anywhere; }
.lib-assets { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.lib-asset { margin: 0; width: 74px; }
.lib-asset img {
  width: 74px; height: 74px; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border); display: block; background: var(--panel);
}
.lib-asset figcaption { font-size: 10.5px; margin-top: 3px; text-align: center; color: var(--muted); }
.lib-asset.active img { border-color: var(--ok-line); }
.lib-asset.active figcaption { color: var(--ok); }
.lib-asset.failed img { border-color: var(--danger-line); }
.lib-asset.failed figcaption { color: var(--danger); }

.project-foot { flex-wrap: wrap; row-gap: 8px;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
}
.project-foot .hint { margin: 0; }

.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.card-head h2 { margin: 0; }

/* ---------- The result ----------
   What came out: the video with its editor, or the images one at a time, large. It
   is the stage half of the generation's card now (`.gp-card`), which carries the
   frame in the goal's colour that this used to. */

/* The stage: the image in the middle, the arrows at the sides. Over the chequered
   ground because a slide with a white background on a white card has no edges, and
   you cannot tell where the image ends and the page begins. */
/* What is being made, before it exists.
   The ratio arrives from the JS as --wait-ratio, the same way the style grid gets
   --tile-ratio: it is the brief's own format, so the column is already the right
   shape when the picture lands in it and nothing jumps.
   It used to borrow the stage's chequer and `.cast-empty`'s dashed border, «rather
   than inventing a third placeholder look», and to carry no bar and no percentage
   because the provider sends a status word and nothing else. Both changed on the
   owner's drawing: the card is a card now — the phase, the ring, the title, the clock
   and three steps (`buildWaitCard`) — and the number is the prediction `waits.js`
   makes and labels as one, drawn once as a figure and once as the arc round it. */
.result-wait[hidden] { display: none; }
/* The arrows under the box while it holds the stage, centred under it: the same two
   buttons the picture's caption carries, styled there by `.gp-card .result-navs`. */
.rw-navs { display: flex; justify-content: center; margin-top: 10px; }
.rw-box {
  /* The width is computed from the height cap and not left at 100%, and the two
     are not interchangeable: `width: 100%` with `max-height` clamps the height
     while the width stays put, so a 9:16 box came out landscape — the one shape it
     must never be. Deriving the width instead means the cap bounds the box without
     touching its proportions, and `min(100%, …)` hands the column back the say
     when it is the narrower of the two. `--wait-ratio` is `9 / 16`, which is a
     division inside calc() and a ratio outside it. */
  width: min(100%, calc(var(--stage-h, min(60vh, 72svh)) * var(--wait-ratio, 1)));
  aspect-ratio: var(--wait-ratio, 1); margin-inline: auto;
  display: grid; place-content: center; gap: 4px; justify-items: center;
  /* Filled, not transparent, and grey rather than white. The frame around it is
     the stage's own chequer — kept so that nothing moves when the picture lands in
     it — and a dashed outline over that chequer disappeared into it. White filled
     it in the other direction: the box read as an image that had come out blank,
     which is the one thing a placeholder must not look like. */
  background: var(--panel-2); border: 1px dashed var(--border); border-radius: 9px;
  position: relative; overflow: hidden;
}
/* The sweep. It is what separates «still working» from «finished, and empty» —
   a shape that does not move is a result, whatever is written in it. Slow and
   low-contrast on purpose: a band crossing the box says alive. It used to add that
   anything travelling once and stopping would read as a bar reaching an end, «the
   fraction we do not have»; the ring on the director's card is that fraction now, and
   it is allowed because it is the labelled prediction, never closes before the file
   exists, and is the same number as the figure inside it. The sweep stays under it. */
.rw-box::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, var(--panel) 50%, transparent 70%);
  transform: translateX(-100%);
  animation: rw-shimmer 2.1s ease-in-out infinite;
}
.rw-box > * { position: relative; z-index: 1; }
@keyframes rw-shimmer { to { transform: translateX(100%); } }
/* With motion off the words do the work: the caption says what is happening and
   the clock is visibly counting, so nothing is lost but the sweep. */
@media (prefers-reduced-motion: reduce) { .rw-box::after { animation: none; opacity: 0; } }
.result-wait.failed .rw-box::after { animation: none; opacity: 0; }
.rw-what { font-size: 13px; color: var(--ink); }
.rw-state { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
.rw-state[hidden] { display: none; }
/* The number, and it is the biggest thing in the box because it is what somebody
   looks at. Tabular, so the box does not twitch every second as the digits change
   width. The Studio's retouch panel draws the same class; the director's card sizes it
   to its ring below. */
.rw-pct { font-family: var(--mono); font-size: 30px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--ink); line-height: 1; }
.rw-time { font-family: var(--mono); font-size: 13px; font-variant-numeric: tabular-nums; color: var(--muted); }
/* What kind of number it is — a prediction — is in its label (`wait.pct.aria`), which a
   screen reader announces; on screen it is the ring and the clock under it that qualify
   it. A failed one stays where it stopped, dimmed. */
.result-wait.failed .rw-pct { opacity: .5; }
/* The slot in the strip. It was the big box's sweep at thumbnail size, «one animation
   and one look». The owner's drawing gives the tile its own: an accent frame, a small
   spinner and its number in the strip — and the big card keeps the sweep. Two looks for
   two things now: the card describes one job, the tile marks a place in the row. */
.shot-slot .shot-media { display: grid; place-items: stretch; }
.slot-box { width: 100%; height: 100%; aspect-ratio: auto; min-height: 64px; }
.shot-slot figcaption { color: var(--muted); font-style: italic; }
.result-wait.failed .rw-box { border-color: var(--danger); }
.result-wait.failed .rw-state { color: var(--danger-ink); }
.result-wait.failed .rw-time { opacity: .5; }

/* ---- the director's card for a generation in flight (`buildWaitCard`) ----
   Everything scoped to `#result-wait`: `.rw-box` and `.rw-pct` are also the Studio's
   retouch panel and the strip's tile.

   The box keeps the true shape of the request — a 9:16 is 9:16 and a square is square,
   the width derived from the stage's height cap as above — with one exception, and it is
   new: a floor of 300px (or the stage's own height, if that is less). The box used to be
   strictly the picture's shape; a 21:9 in a 340px column is 146px tall, which holds no
   ring, no title and no steps. So a shape that wide is drawn taller than itself, and the
   spec in its corner says the shape in words. Inside, what does not fit goes first — the
   line about the job, then the steps, then their labels — read off the box's own size. */
#result-wait > .rw-box {
  container: rw / size;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 8px;
  min-height: min(var(--stage-h, 300px), 300px);
  padding: 46px 18px 16px;
  border: 1px solid var(--border); border-style: solid; border-radius: 16px;
}
#result-wait .rw-top {
  position: absolute; top: 14px; left: 16px; right: 16px;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
/* The pill keeps its word whole and the spec gives way: on a narrow card the two used to
   run into each other, the pill's word over the spec or the spec under the box's edge. The
   shape comes first in the spec, so it is what survives the cut; the whole is its title. */
.rw-pill {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  font-size: 11.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.rw-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
@media (prefers-reduced-motion: no-preference) {
  #result-wait .rw-dot { animation: rw-pulse 1.6s ease-in-out infinite; }
}
@keyframes rw-pulse { 50% { opacity: .35; transform: scale(.8); } }
.rw-spec { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The ring: the figure bent round, from the top, in the accent on a hairline track. */
.rw-ring {
  position: relative; display: grid; place-items: center; flex: none; margin: auto 0 6px;
  width: clamp(72px, min(44cqi, 30cqb), 164px); aspect-ratio: 1;
}
.rw-ring svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); overflow: visible; }
.rw-ring-track { fill: none; stroke: var(--border); stroke-width: 5; }
.rw-ring-arc { fill: none; stroke: var(--accent); stroke-width: 5; stroke-linecap: round; stroke-dasharray: 100; }
#result-wait .rw-pct {
  font-family: inherit; font-size: clamp(17px, min(10cqi, 8cqb), 40px); font-weight: 800; letter-spacing: -.03em; color: var(--text);
}
#result-wait .rw-what {
  max-width: 24ch; font-size: clamp(16px, min(5.4cqi, 5cqb), 26px); font-weight: 800; line-height: 1.2;
  letter-spacing: -.02em; text-align: center; text-wrap: balance; color: var(--text);
}
.rw-sub { font-size: clamp(13px, 3.4cqi, 16px); line-height: 1.4; text-align: center; color: var(--muted); }
.rw-sub[hidden] { display: none; }
.rw-elapsed { display: inline-flex; align-items: center; gap: 7px; margin-top: 4px; font-size: 13px; color: var(--muted); }
.rw-elapsed .sd-ic { flex: none; }
#result-wait .rw-time { font-family: inherit; font-size: 13px; }
#result-wait .rw-state { max-width: 40ch; font-size: 12.5px; line-height: 1.4; text-align: center; }
/* A failure's one line, and its whole sentence with the id folded under «Details». */
.rw-more {
  padding: 2px 6px; cursor: pointer; font: inherit; font-size: 12px; color: var(--muted);
  background: none; border: 0; border-radius: 6px; text-decoration: underline; text-underline-offset: 2px;
}
.rw-more:hover { color: var(--ink); }
.rw-more[hidden], .rw-detail[hidden] { display: none; }
.rw-detail {
  box-sizing: border-box; width: 100%; max-width: 44ch; max-height: 132px; margin: 0; padding: 8px 10px; overflow: auto;
  font-size: 11.5px; line-height: 1.45; color: var(--muted); text-align: left; overflow-wrap: anywhere;
  background: var(--panel-2); border-radius: 8px; user-select: text;
}
/* The three steps, at the foot; the middle one is where the job is. */
.rw-steps {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  margin: auto 0 0; padding: 14px 0 2px; list-style: none;
}
.rw-step { display: flex; align-items: center; gap: 7px; min-width: 0; font-size: 13.5px; color: var(--muted); white-space: nowrap; }
.rw-step + .rw-step::before { content: ""; flex: none; width: clamp(10px, 8cqi, 64px); height: 1px; margin-right: 1px; background: var(--border); }
.rw-step-mark {
  display: grid; place-items: center; flex: none; width: 16px; height: 16px; border-radius: 50%;
  border: 1.5px solid var(--border); background: var(--panel); color: var(--panel);
}
.rw-step-mark .sd-ic { display: none; stroke-width: 3; }
.rw-step[data-state="done"] .rw-step-mark { border-color: transparent; background: color-mix(in srgb, var(--muted) 55%, var(--panel)); }
.rw-step[data-state="done"] .rw-step-mark .sd-ic:first-child { display: block; }
.rw-step[data-state="current"] { color: var(--accent-ink); font-weight: 600; }
.rw-step[data-state="current"] .rw-step-mark { border-color: var(--accent); background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.rw-step[data-state="failed"] { color: var(--danger-ink); font-weight: 600; }
.rw-step[data-state="failed"] .rw-step-mark { border-color: var(--danger); background: var(--danger); color: var(--on-danger); }
.rw-step[data-state="failed"] .rw-step-mark .sd-ic:last-child { display: block; }
#result-wait.failed .rw-dot { background: var(--danger); animation: none; }
/* Its frame too, as the tile's is: `#result-wait > .rw-box` above outranks the older
   `.result-wait.failed .rw-box`, which left a failed card's border grey. */
#result-wait.failed > .rw-box { border-color: var(--danger); }
#result-wait.failed .rw-ring-arc { stroke: var(--danger); }
/* On the player's slide only the arrows stay, under the player: they are the way back to
   the tile, and the card above them would stack the generation over the version on screen
   — the column shows one slide at a time (`paintResult`). */
#result-wait.navs-only > .rw-box { display: none; }
@container rw (max-height: 280px) { .rw-sub { display: none; } }
@container rw (max-height: 225px) { .rw-steps { display: none; } }
/* A narrow card keeps the three words, smaller, as the owner's drawing has them; only
   a card too narrow for them at that size keeps the word of the step it is on. */
@container rw (max-width: 340px) {
  .rw-steps { gap: 5px; }
  .rw-step { gap: 5px; font-size: 12px; }
  .rw-step + .rw-step::before { width: 8px; }
}
@container rw (max-width: 290px) {
  .rw-step:not([data-state="current"]):not([data-state="failed"]) .rw-step-label { display: none; }
}

.result-stage {
  position: relative; display: grid; place-items: center; padding: 10px;
  border-radius: 12px; background: repeating-conic-gradient(var(--panel-3) 0% 25%, var(--panel-2) 0% 50%) 50% / 16px 16px;
  border: 1px solid var(--border);
}
.result-stage[hidden] { display: none; }
.result-shot { margin: 0; width: 100%; position: relative; }
.result-shot img {
  display: block; width: 100%; max-height: var(--stage-h, min(60vh, 72svh)); object-fit: contain; cursor: zoom-in;
  border-radius: 8px; background: var(--panel);
}
.result-shot figcaption {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-top: 8px; font-size: 12.5px; color: var(--muted);
}
.result-shot figcaption b { font-family: var(--mono); font-size: 11.5px; color: var(--k); }
/* What can be done with this picture, under it rather than over it.
   `margin-left: auto` pushes the pair to the right of the caption's own text, and
   `flex-wrap` on the caption is what lets them drop onto a line of their own
   instead of squeezing: measured, the pair at its widest is 328px and the column
   on a phone is 314px. Two stacked buttons are legible; two clipped ones are not. */
.result-shot figcaption { flex-wrap: wrap; }
.result-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
/* The reason a button is off, on its own line under the pair rather than inside
   the row: beside two buttons it would be read as a third one. */
.result-nope { flex: 0 0 100%; margin: 2px 0 0; text-align: right; font-size: 11.5px; }
.result-dl {
  position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; padding: 0;
  cursor: pointer; font-size: 15px; line-height: 1; color: var(--on-scrim);
  background: var(--scrim); border: 0; border-radius: 8px;
}
.result-dl:hover { background: var(--k); }
.result-dl:disabled { opacity: .6; cursor: default; }

.result-nav {
  position: absolute; top: 50%; z-index: 2; width: 34px; height: 46px; padding: 0;
  transform: translateY(-50%); cursor: pointer; font-size: 22px; line-height: 1;
  color: var(--ink); background: var(--veil-strong);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-1);
}
.result-nav:hover { border-color: var(--k); color: var(--k); }
.result-nav[hidden] { display: none; }
.result-nav.prev { left: 6px; }
.result-nav.next { right: 6px; }

/* The thumbnails: a strip that scrolls horizontally, not a grid that grows
   vertically — they exist to jump from one slide to another, and have to sit under
   the stage without pushing it off screen. */
/* `.gallery` is a grid and comes later in the sheet: without the double selector
   the strip went back to stacking into two columns. */
.gallery.result-strip {
  display: flex; gap: 8px; margin-top: 10px; padding-bottom: 4px;
  overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin;
}
.result-strip .shot { flex: 0 0 74px; margin: 0; cursor: pointer; }
.result-strip .shot img { aspect-ratio: 1; border-radius: 7px; }
.result-strip .shot.on img { border-color: var(--k); box-shadow: 0 0 0 2px color-mix(in srgb, var(--k) 35%, transparent); }
.result-strip .shot figcaption { display: none; }
/* Except the slot's, which is the only thing on it that says what it is. A
   finished thumbnail is a picture and needs no caption; an empty dashed square
   needs the two words. */
.result-strip .shot-slot figcaption { display: block; text-align: center; }
/* The player's slide: the version on the player by its first frame, drawn like a
   thumbnail and captioned like a slot — a frame alone does not say which version it is. */
.shot-player video {
  display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 7px;
  border: 1px solid var(--border); background: #10121a;
}
.result-strip .shot-player figcaption { display: block; text-align: center; }
.result-strip .shot-player.on video { border-color: var(--k); box-shadow: 0 0 0 2px color-mix(in srgb, var(--k) 35%, transparent); }
/* The word on a tile that has just landed. Over the picture and not under it: the
   caption is the label somebody gave the shot, and a state pushed in beside it
   would read as part of the name. */
.shot-state {
  position: absolute; top: 6px; left: 6px; z-index: 2;
  padding: 1px 7px; border-radius: 999px;
  background: var(--ok-bg, rgba(32, 132, 70, 0.92)); color: #fff;
  font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
}
.shot { position: relative; }

/* At rest the bell is an icon and not an alert: present, findable, and asking for
   nothing. It comes back to full strength on hover and on focus, because a control
   that stays dim under the pointer reads as disabled. */
.side-jobs.empty .jobs-btn { opacity: 0.45; }
.side-jobs.empty .jobs-btn:hover,
.side-jobs.empty .jobs-btn:focus-visible { opacity: 1; }
/* The stand-in row, which is a div and not a button: nothing to open until the
   row exists. It keeps the running dot so it does not visibly change shape when the
   real one replaces it. */
.job-starting { cursor: default; opacity: .8; }
.job-starting:hover { background: none; }

.jobs-empty { padding: 14px 12px; text-align: center; }
.jobs-empty-said { margin: 0 0 8px; color: var(--muted); font-size: 13px; }
.jobs-empty-go {
  border: 0; background: none; padding: 0; cursor: pointer;
  color: var(--accent, #2f6fed); font-size: 13px; font-weight: 600;
}
.jobs-empty-go:hover { text-decoration: underline; }

/* A turn that ended without the card. Grey and not red: nothing broke and nothing
   was charged — what is missing is a click, and the sentence says so. */
.tool.held { color: var(--muted); }
.tool.held .tool-dot { background: var(--muted); }

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin-top: 10px; }
.shot { margin: 0; }
.shot-media { position: relative; }
.shot-dl {
  position: absolute; top: 5px; right: 5px; width: 24px; height: 24px; padding: 0;
  border: 0; border-radius: 6px; cursor: pointer; font-size: 13px; line-height: 1;
  background: var(--scrim); color: var(--on-scrim); opacity: 0; transition: opacity .12s;
}
.shot-media:hover .shot-dl, .shot-dl:focus-visible { opacity: 1; }
.shot-dl:disabled { opacity: 1; cursor: default; color: var(--muted); }
.shot img {
  width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 8px;
  border: 1px solid var(--border); cursor: pointer; display: block; background: var(--panel-2);
}
.shot figcaption { font-size: 11.5px; color: var(--muted); margin-top: 4px; line-height: 1.35; }

/* The cap is what makes the wide stage usable rather than merely large. `width:
   100%` alone was harmless in a 430px rail — a 9:16 clip came out 430×765 and the
   controls under it stayed on screen. Across a thousand pixels the same clip
   wants to be 1000×1778, and everything below it, the range panel and the button
   that spends credits included, is pushed past `.main { overflow: hidden }` where
   no amount of scrolling reaches it. So the height leads and the width follows. */
.result-video {
  display: block; width: auto; max-width: 100%; margin: 8px auto 0;
  max-height: min(58vh, 70svh);
  border-radius: 10px; border: 1px solid var(--border); background: #10121a;
}

/* ---------- Editing a range: «Edit video» ----------
   The owner's mockup, over the conversation: the preview in a card of its own and the
   range under it on the left, the two steps and the button that spends in a second card
   on the right. Navy for the titles, the studio's pink for everything acted on, and a
   wash of the same pink so faint it reads as warmth rather than colour.

   The palette lives in tokens scoped to this screen — `--ve-accent` is the studio's
   `--accent`, so a brand skin that changes the accent changes this screen with it — and
   `.edov-video` is on the overlay while the range editor holds it and on the editor's
   own pane, so the tokens reach the shared head as well as the editor. */
.edov-video {
  --ve-navy: #0b0d33;
  --ve-accent: var(--accent);
  --ve-on-accent: #ffffff;
  --ve-title: var(--ve-navy);
  --ve-text: #171a3f;
  --ve-text-2: #5f617a;
  --ve-hint: #8a8ba1;
  --ve-soft: color-mix(in srgb, var(--ve-accent) 10%, #ffffff);
  --ve-soft-line: color-mix(in srgb, var(--ve-accent) 26%, #ffffff);
  /* The accent as text on its own soft wash, a step darker so it reads there: above
     4.5:1 for the studio's pink. */
  --ve-accent-ink: color-mix(in srgb, var(--ve-accent) 84%, #000000);
  --ve-wash: color-mix(in srgb, var(--ve-accent) 3%, #ffffff);
  --ve-stage: linear-gradient(160deg, color-mix(in srgb, var(--ve-accent) 3.5%, #ffffff) 0%, #faf9fd 55%, color-mix(in srgb, var(--ve-accent) 4.5%, #ffffff) 100%);
  --ve-panel: #ffffff;
  --ve-line: #ececf3;
  --ve-card-line: color-mix(in srgb, var(--ve-accent) 8%, #ececf3);
  --ve-chip: #f8f8fc;
  --ve-field: #ffffff;
  --ve-skeleton: color-mix(in srgb, var(--ve-accent) 6%, #eeeef4);
  --ve-shadow: 0 1px 2px rgba(16, 18, 60, .05), 0 8px 22px -10px rgba(16, 18, 60, .16);
  --ve-glow: 0 12px 28px -12px color-mix(in srgb, var(--ve-accent) 75%, transparent);
}
:root[data-theme="dark"] .edov-video {
  --ve-navy: #eef0ff;
  --ve-text: #e6e7f5;
  --ve-text-2: #b9bad0;
  --ve-hint: #a3a4bd;
  --ve-soft: color-mix(in srgb, var(--ve-accent) 20%, #17182b);
  --ve-soft-line: color-mix(in srgb, var(--ve-accent) 48%, #17182b);
  --ve-accent-ink: color-mix(in srgb, var(--ve-accent) 50%, #ffffff);
  --ve-wash: color-mix(in srgb, var(--ve-accent) 4%, #15162a);
  --ve-stage: linear-gradient(160deg, color-mix(in srgb, var(--ve-accent) 7%, #121325) 0%, #121325 60%, color-mix(in srgb, var(--ve-accent) 5%, #121325) 100%);
  --ve-panel: #15162a;
  --ve-line: #2b2d48;
  --ve-card-line: color-mix(in srgb, var(--ve-accent) 16%, #2b2d48);
  --ve-chip: #1d1f36;
  --ve-field: #1b1d33;
  --ve-skeleton: #25273f;
  --ve-shadow: 0 1px 2px rgba(0, 0, 0, .5), 0 0 0 1px rgba(255, 255, 255, .05);
}

/* The overlay itself, while this editor holds it: the studio behind it, blurred, under a
   faint neutral veil — the owner's word, in place of the pink wash that hid it — closer
   to the window's edge, and a head of its own: the arrow back, the title in navy, the
   version as a pink chip, «Close» at the right. */
.edov.edov-video {
  padding: clamp(8px, 1.45vh, 16px) clamp(8px, 1.7vw, 28px);
  background: rgb(18 20 44 / .16);
  -webkit-backdrop-filter: blur(18px) saturate(1.1); backdrop-filter: blur(18px) saturate(1.1);
}
:root[data-theme="dark"] .edov.edov-video { background: rgb(6 7 16 / .42); }
.edov.edov-video .edov-panel {
  width: min(100%, 1560px); height: min(100%, 1000px); background: var(--ve-panel);
  border-color: var(--ve-card-line); border-radius: 22px;
  box-shadow: 0 30px 80px -34px color-mix(in srgb, var(--ve-accent) 34%, rgba(16, 18, 60, .4));
}
.edov-back { display: none; }
.edov.edov-video .edov-head { gap: 18px; padding: 14px 22px 10px; background: var(--ve-panel); border-bottom: 0; }
.edov.edov-video .edov-back {
  display: grid; place-items: center; flex: none; width: 46px; height: 46px; padding: 0;
  border: 1px solid var(--ve-soft-line); border-radius: 12px; background: var(--ve-panel); color: var(--ve-navy);
  cursor: pointer; transition: background .15s, border-color .15s;
}
.edov.edov-video .edov-back:hover { background: var(--ve-soft); }
.edov.edov-video .edov-head strong {
  flex: none; font-size: 27px; font-weight: 800; letter-spacing: -.02em; line-height: 1.1; color: var(--ve-title);
}
.edov.edov-video .edov-head .hint {
  padding: 6px 14px; border-radius: 999px; background: var(--ve-soft); color: var(--ve-accent-ink);
  font-size: 14px; font-weight: 600;
}
.edov.edov-video .edov-head .btn {
  padding: 11px 24px; border: 0; border-radius: 12px; background: color-mix(in srgb, var(--ve-accent) 6%, var(--ve-chip)); color: var(--ve-navy);
  font-size: 14.5px; font-weight: 700;
}
.edov.edov-video .edov-head .btn:hover { background: var(--ve-soft); }
.edov-back:focus-visible, .vedit button:focus-visible, .vedit-track:focus-visible { outline: 2px solid var(--ve-accent); outline-offset: 2px; }

/* The pane: no scroll of its own on a wide screen, where each column holds itself; on a
   narrow one it is the one thing that scrolls. */
.edov-pane.edov-video { padding: 0; overflow: hidden; background: var(--ve-panel); }
.edov-pane.edov-video > .vedit { max-width: none; margin: 0; }

.vedit {
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(384px, 31%, 448px); grid-template-rows: minmax(0, 1fr);
  gap: 20px; height: 100%; padding: 4px 20px 18px; color: var(--ve-text); background: var(--ve-panel);
}
/* Each column names its track: a child that can be hidden must not let the other
   slide into its place. */
.vedit-main { grid-column: 1; grid-row: 1; min-width: 0; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto; }
.vedit-side {
  grid-column: 2; grid-row: 1; min-width: 0; min-height: 0; overflow-y: auto; display: flex; flex-direction: column;
  padding: 22px 22px 16px; border: 1px solid var(--ve-card-line); border-radius: 18px;
  background: linear-gradient(180deg, var(--ve-panel) 0%, var(--ve-wash) 100%);
}
.vedit-h { margin: 0; font-size: 17px; font-weight: 700; color: var(--ve-title); }

/* ---- the preview, a card of its own ---- */
.vedit-preview {
  position: relative; min-height: 0; display: grid; grid-template-rows: minmax(0, 1fr) auto;
  padding: 18px 30px 14px; border: 1px solid var(--ve-card-line); border-radius: 18px; background: var(--ve-stage);
}
.vedit-preview-head {
  position: absolute; top: 20px; left: 30px; right: 30px; z-index: 1; pointer-events: none;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.vedit-format { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 500; color: var(--ve-text-2); }
.vedit-format .sd-ic { color: var(--ve-navy); }
/* The video at its own shape, as large as the room allows: the room is a container,
   so the width is the smaller of its width and its height times the video's ratio. The
   poster sits in the same cell, under it, until the video has a frame of its own. */
.vedit-frame { grid-row: 1; min-height: 0; container-type: size; display: grid; place-items: center; }
.vedit-frame > * { grid-area: 1 / 1; }
.vedit-video, .vedit-poster {
  display: block; aspect-ratio: var(--ve-ratio, .5625);
  width: min(100cqw, calc(100cqh * var(--ve-ratio, .5625))); height: auto; border-radius: 14px;
}
.vedit-poster { background: #0e0f1a; box-shadow: 0 14px 34px -14px rgba(16, 18, 60, .42); }
.vedit-video { position: relative; background: transparent; }
.vedit-player {
  grid-row: 2; justify-self: center; width: min(100%, 580px); margin-top: 8px;
  display: flex; align-items: center; gap: 8px; padding: 5px 18px;
  background: var(--ve-panel); border: 1px solid var(--ve-line); border-radius: 16px; box-shadow: var(--ve-shadow);
}
.vedit-ib {
  display: grid; place-items: center; flex: none; width: 38px; height: 38px; padding: 0;
  border: 0; border-radius: 10px; background: transparent; color: var(--ve-navy); cursor: pointer;
}
.vedit-ib:hover { background: var(--ve-soft); }
.vedit-ib.vedit-play {
  width: 48px; height: 48px; border-radius: 50%; background: var(--ve-accent); color: var(--ve-on-accent); margin: 0 6px;
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--ve-accent) 80%, transparent);
}
.vedit-ib.vedit-play:hover { background: color-mix(in srgb, var(--ve-accent) 88%, #000); }
.vedit-ib.vedit-play .sd-ic { fill: currentColor; }
.vedit-clock {
  flex: 1; min-width: 0; margin-left: 12px; white-space: nowrap; overflow: hidden;
  font-size: 15px; font-variant-numeric: tabular-nums; color: var(--ve-hint);
}
.vedit-clock b { font-weight: 700; color: var(--ve-navy); }

/* ---- the range ---- */
.vedit-select { position: relative; min-width: 0; padding: 16px 8px 0; }
.vedit-select-head { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.vedit-select .vedit-h { font-size: 20px; font-weight: 800; letter-spacing: -.015em; }
.vedit-chip {
  padding: 4px 12px; border-radius: 999px; background: var(--ve-soft); color: var(--ve-accent-ink);
  font-size: 13px; font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.vedit-hint { margin: 4px 0 0; font-size: 14px; color: var(--ve-hint); }
.vedit-stripbox { position: relative; margin-top: 14px; }

/* The track is the strip of frames, tall enough to aim at with a finger. */
.vedit-track { position: relative; height: 50px; cursor: crosshair; touch-action: none; user-select: none; border-radius: 10px; }
.vedit-frames { position: absolute; inset: 0; overflow: hidden; border-radius: 10px; background: var(--ve-skeleton); }
.vedit-film { display: flex; height: 100%; }
.vedit-film-frame { display: block; flex: 1 1 0; min-width: 0; height: 100%; }
.vedit-film-frame + .vedit-film-frame { border-left: 1px solid rgba(255, 255, 255, .35); }
/* A tile waiting for its frame shimmers; one the other road has only stood in for is
   paler until its own arrives. */
.vedit-film-frame:not(.drawn):not(.rough) {
  background: linear-gradient(100deg, var(--ve-skeleton) 30%, color-mix(in srgb, var(--ve-skeleton) 35%, #ffffff) 50%, var(--ve-skeleton) 70%);
  background-size: 300% 100%;
}
@media (prefers-reduced-motion: no-preference) {
  .vedit-film-frame:not(.drawn):not(.rough) { animation: vedit-shimmer 1.3s ease-in-out infinite; }
}
@keyframes vedit-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
.vedit-film-frame.rough { opacity: .7; }
/* Outside the window the frames step back a little: the chosen stretch is the one in focus. */
.vedit-dim { position: absolute; top: 0; bottom: 0; pointer-events: none; background: rgba(255, 255, 255, .16); }
:root[data-theme="dark"] .vedit-dim { background: rgba(10, 11, 24, .34); }
.vedit-dim.before { left: 0; }
.vedit-dim.after { right: 0; }
.vedit-sel {
  position: absolute; top: 0; bottom: 0; min-width: 2px; pointer-events: none;
  border: 3px solid var(--ve-accent); border-radius: 10px;
  background: color-mix(in srgb, var(--ve-accent) 20%, transparent);
}
/* The handles: a pink pill on each edge with its grip. The drawing is 24px; the reach is
   wider. */
.vedit-handle {
  position: absolute; top: -5px; bottom: -5px; width: 24px; pointer-events: auto; cursor: ew-resize;
  border-radius: 9px; background: var(--ve-accent);
  box-shadow: 0 3px 8px -2px color-mix(in srgb, var(--ve-accent) 60%, transparent);
}
/* Centred on the selection's outer edge, which is the moment: half the handle and the
   selection's border out from the box it is placed in. */
.vedit-handle.start { left: -15px; }
.vedit-handle.end { right: -15px; }
.vedit-handle::before {
  content: ''; position: absolute; top: 50%; left: 50%; width: 6px; height: 18px; transform: translate(-50%, -50%);
  border-inline: 2px solid var(--ve-on-accent); opacity: .95;
}
/* The playhead: a hairline of the accent at the preview's moment, running past the strip
   above and into the ruler below. */
.vedit-playhead {
  position: absolute; top: -9px; bottom: -16px; z-index: 2; width: 2px; margin-left: -1px;
  border-radius: 2px; background: var(--ve-accent); pointer-events: none;
}

/* The frame under the edge being dragged, floating over the strip with its time. */
.vedit-scrub {
  position: absolute; bottom: calc(100% + 14px); z-index: 3; pointer-events: none;
  display: flex; align-items: center; gap: 10px; padding: 6px 14px 6px 6px;
  background: var(--ve-panel); border: 1px solid var(--ve-card-line); border-radius: 12px; box-shadow: var(--ve-shadow);
}
.vedit-scrub::after {
  content: ''; position: absolute; top: 100%; left: var(--caret, 50%); width: 10px; height: 10px; margin: -5px 0 0 -5px;
  transform: rotate(45deg); background: var(--ve-panel); border: solid var(--ve-card-line); border-width: 0 1px 1px 0;
}
.vedit-scrub-pic { display: block; width: 52px; height: 52px; border-radius: 8px; background: var(--ve-chip); }
.vedit-scrub-time { font-size: 13.5px; font-variant-numeric: tabular-nums; color: var(--ve-navy); }

.vedit-ticks { position: relative; height: 24px; }
.vedit-tick {
  position: absolute; bottom: 2px; transform: translateX(-50%);
  font-size: 12.5px; color: var(--ve-hint); white-space: nowrap; font-variant-numeric: tabular-nums;
}
.vedit-tick::before {
  content: ''; position: absolute; left: 50%; bottom: calc(100% + 1px); width: 1px; height: 6px;
  background: var(--ve-line);
}
.vedit-tick.first { transform: none; }
.vedit-tick.first::before { left: 0; }
.vedit-tick.last { transform: translateX(-100%); }
.vedit-tick.last::before { left: 100%; }
.vedit-tick-minor { position: absolute; top: 5px; width: 2px; height: 4px; margin-left: -1px; border-radius: 1px; background: var(--ve-line); }

/* The scenes under the ruler: as many chips as the row holds, each as wide as its scene
   is long, and «›» at the end with all of them when they do not fit. */
.vedit-scenebar { position: relative; display: flex; gap: 10px; margin-top: 4px; }
.vedit-scenebar[hidden] { display: none; }
.vedit-scenes { display: flex; gap: 10px; flex: 1; min-width: 0; }
.vedit-scene {
  flex: 1 1 0; min-width: 0; height: 42px; padding: 0 16px;
  border: 1px solid var(--ve-line); border-radius: 12px; background: var(--ve-chip); color: var(--ve-text-2);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vedit-scene:hover { border-color: var(--ve-soft-line); }
.vedit-scene.on { background-color: var(--ve-soft); border-color: var(--ve-soft-line); color: var(--ve-accent-ink); font-weight: 500; }
.vedit-scene:disabled { cursor: default; }
.vedit-scenes-more {
  display: grid; place-items: center; flex: none; width: 42px; height: 42px; padding: 0;
  border: 1px solid var(--ve-line); border-radius: 12px; background: var(--ve-panel); color: var(--ve-accent); cursor: pointer;
}
.vedit-scenes-more[hidden] { display: none; }
.vedit-scenes-more:hover, .vedit-scenes-more[aria-expanded="true"] { background: var(--ve-soft); border-color: var(--ve-soft-line); }
.vedit-scenes-list {
  position: absolute; right: 0; bottom: calc(100% + 8px); z-index: 4; width: min(380px, 100%);
  max-height: min(340px, 50vh); overflow-y: auto; padding: 6px;
  background: var(--ve-panel); border: 1px solid var(--ve-card-line); border-radius: 14px; box-shadow: var(--ve-shadow);
}
.vedit-scenes-list[hidden] { display: none; }
.vedit-scenes-item {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; align-items: baseline; width: 100%;
  padding: 9px 10px; border: 0; border-radius: 9px; background: transparent; color: var(--ve-text);
  font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
}
.vedit-scenes-item b { font-weight: 600; color: var(--ve-hint); font-variant-numeric: tabular-nums; }
.vedit-scenes-item span { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vedit-scenes-item:hover { background: var(--ve-chip); }
.vedit-scenes-item.on { background: var(--ve-soft); color: var(--ve-accent-ink); }
.vedit-scenes-item.on b { color: var(--ve-accent-ink); }

/* ---- the panel ---- */
.vedit-side-head { margin-bottom: 18px; }
.vedit-side-title { margin: 0; font-size: 26px; font-weight: 800; letter-spacing: -.015em; line-height: 1.15; color: var(--ve-title); }
.vedit-side-sub { margin: 6px 0 0; font-size: 15.5px; color: var(--ve-hint); }
.vedit-step { display: flex; flex-direction: column; gap: 12px; }
.vedit-step-head { display: flex; align-items: center; gap: 16px; }
.vedit-step-n {
  display: grid; place-items: center; flex: none; width: 38px; height: 38px; border-radius: 50%;
  background: var(--ve-soft); color: var(--ve-accent-ink); font-size: 16px; font-weight: 700;
}
.vedit-step-title { margin: 0; font-size: 16.5px; font-weight: 700; color: var(--ve-title); }
.vedit-times { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
/* «Da» and «A» over their fields, as the mockup draws them. */
.vedit-tf { display: flex; flex-direction: column; gap: 4px; min-width: 0; cursor: text; }
.vedit-tf-cap { padding-left: 4px; font-size: 13px; line-height: 16px; color: var(--ve-hint); }
.vedit-tf-box {
  display: flex; align-items: center; gap: 12px; min-width: 0; height: 50px; padding: 0 14px;
  border: 1px solid var(--ve-line); border-radius: 12px; background: var(--ve-field);
}
.vedit-tf:focus-within .vedit-tf-box { border-color: var(--ve-accent); box-shadow: 0 0 0 3px var(--ve-soft); }
.vedit-tf-ic {
  display: grid; place-items: center; flex: none; width: 30px; height: 30px;
  border-radius: 50%; background: var(--ve-soft); color: var(--ve-accent);
}
.vedit-tf-in {
  flex: 1; min-width: 0; width: 100%; padding: 0; border: 0; outline: 0; background: transparent; box-shadow: none;
  font: inherit; font-size: 17px; font-weight: 700; letter-spacing: .02em; color: var(--ve-navy);
  font-variant-numeric: tabular-nums;
}
.vedit-tf-in:disabled { opacity: .6; }
.vedit-range-play {
  display: flex; align-items: center; justify-content: center; gap: 12px; height: 50px; padding: 0 16px;
  border: 1.5px solid color-mix(in srgb, var(--ve-accent) 62%, var(--ve-panel)); border-radius: 12px;
  background: color-mix(in srgb, var(--ve-accent) 4%, var(--ve-panel)); color: var(--ve-accent-ink);
  font: inherit; font-size: 16px; font-weight: 600; cursor: pointer;
}
.vedit-range-play .sd-ic { color: var(--ve-accent); }
.vedit-range-play:hover, .vedit-range-play[aria-pressed="true"] { background: var(--ve-soft); }

/* The range's prompt is context: closed it shows its first line. */
.vedit-prompt { border: 1px solid var(--ve-line); border-radius: 12px; background: var(--ve-chip); }
.vedit-prompt > summary {
  display: flex; align-items: baseline; gap: 10px; padding: 11px 14px;
  cursor: pointer; list-style: none;
}
.vedit-prompt > summary::-webkit-details-marker { display: none; }
.vedit-prompt > summary::before { content: '▶'; color: var(--ve-navy); font-size: 9px; transition: transform .15s; }
.vedit-prompt[open] > summary::before { transform: rotate(90deg); }
.vedit-label { flex: none; font-size: 13px; font-weight: 600; color: var(--ve-navy); }
.vedit-peek {
  flex: 1; min-width: 0; font-size: 13px; color: var(--ve-hint);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vedit-target {
  margin: 0 10px 10px; width: calc(100% - 20px);
  background: var(--ve-field); color: var(--ve-text-2); resize: vertical; font-size: 12.5px;
}
.vedit-target:focus { outline: none; border-color: var(--ve-line); }

.vedit-rule { width: 100%; margin: 16px 0; border: 0; border-top: 1px solid var(--ve-line); }

/* The change field is the one being worked in: it is the largest. */
.vedit-change {
  width: 100%; height: 96px; min-height: 64px; padding: 12px 16px; resize: vertical;
  border: 1px solid var(--ve-line); border-radius: 12px; background: color-mix(in srgb, var(--ve-accent) 1.5%, var(--ve-field)); color: var(--ve-text);
  font: inherit; font-size: 15px; line-height: 1.5;
}
.vedit-change::placeholder { color: var(--ve-hint); }
.vedit-change:focus { outline: none; border-color: var(--ve-accent); box-shadow: 0 0 0 3px var(--ve-soft); }
.vedit-count { margin: -8px 2px 0 0; text-align: right; font-size: 13px; color: var(--ve-hint); font-variant-numeric: tabular-nums; }
.vedit-count.full { color: var(--ve-accent-ink); font-weight: 600; }
.vedit-change-hint { margin-top: -6px; }
.vedit-status { margin: 0; }

/* The button that spends: a gradient of the accent, the words in the middle, what it
   spends on its right. It lights up once something is written for it to do. */
.vedit-foot { margin-top: auto; padding-top: 16px; }
.vedit-apply {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: stretch; width: 100%; min-height: 58px; margin: 0; padding: 0;
  border: 0; border-radius: 14px; color: var(--ve-on-accent);
  background: linear-gradient(90deg, var(--ve-accent) 0%, color-mix(in srgb, var(--ve-accent) 66%, #ffffff) 100%);
  font: inherit; font-size: 17px; font-weight: 600; cursor: pointer; opacity: .9;
  transition: opacity .15s, box-shadow .15s, filter .15s;
}
.vedit-apply.ready { opacity: 1; box-shadow: var(--ve-glow); }
.vedit-apply:hover:not(:disabled) { opacity: 1; filter: brightness(.95); }
.vedit-apply:disabled { cursor: default; opacity: .5; }
.vedit-apply.busy { cursor: progress; }
.vedit-apply-main { display: flex; align-items: center; justify-content: center; gap: 12px; min-width: 0; padding: 0 10px; }
.vedit-apply-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vedit-apply-meta {
  display: flex; align-items: center; gap: 7px; padding: 0 18px;
  border-left: 1px solid color-mix(in srgb, var(--ve-on-accent) 34%, transparent);
  font-size: 16px; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.vedit-apply-cost { display: inline-flex; align-items: center; gap: 5px; }
.vedit-apply-cost .sd-ic { fill: currentColor; stroke-width: 1.2; }
.vedit-apply-dot { opacity: .8; margin-right: 2px; }
.vedit-apply-note { margin: 12px 0 0; text-align: center; font-size: 13.5px; color: var(--ve-hint); }

/* The subtitles: the switch, how many there are, and their two files at the right. */
.vedit-captions { display: flex; align-items: center; gap: 14px; margin-top: 12px; }
.vedit-captions-n { flex: 1; min-width: 0; font-size: 14px; color: var(--ve-hint); }
.vedit-captions-files { display: flex; gap: 10px; }
.vedit-cc, .vedit-dl {
  display: inline-flex; align-items: center; gap: 10px; flex: none; height: 44px; padding: 0 18px;
  border: 1px solid var(--ve-line); border-radius: 12px; background: var(--ve-panel); color: var(--ve-navy);
  font: inherit; font-size: 14.5px; font-weight: 700; cursor: pointer;
}
.vedit-dl { gap: 8px; padding: 0 16px; }
.vedit-cc:hover, .vedit-dl:hover { border-color: var(--ve-soft-line); }
.vedit-cc.on { background: var(--ve-soft); border-color: var(--ve-soft-line); color: var(--ve-accent-ink); }

/* A panel at its narrowest still says the whole of its button. */
@media (min-width: 1100px) and (max-width: 1366px) {
  .vedit-side { padding-inline: 20px; }
  .vedit-apply { font-size: 16px; }
  .vedit-apply-main { gap: 10px; padding: 0 8px; }
  .vedit-apply-meta { padding: 0 16px; font-size: 15px; }
}
/* Two columns on a short window: the panel tightens before it scrolls, and its foot
   stays in sight when it does. */
@media (min-width: 1100px) {
  .vedit-foot { position: sticky; bottom: 0; z-index: 2; padding-bottom: 2px; background: var(--ve-wash); }
}
@media (min-width: 1100px) and (max-height: 860px) {
  .edov.edov-video .edov-head { padding-block: 12px 8px; }
  .vedit { padding-bottom: 14px; }
  .vedit-side { padding-top: 16px; }
  .vedit-side-head { margin-bottom: 12px; }
  .vedit-side-title { font-size: 22px; }
  .vedit-side-sub { margin-top: 4px; font-size: 14.5px; }
  .vedit-step { gap: 9px; }
  .vedit-step-n { width: 34px; height: 34px; font-size: 15px; }
  .vedit-tf-box { height: 46px; }
  .vedit-range-play { height: 44px; }
  .vedit-prompt > summary { padding-block: 9px; }
  .vedit-rule { margin: 12px 0; }
  .vedit-change { height: 72px; }
  .vedit-foot { padding-top: 12px; }
  .vedit-preview { padding-top: 16px; padding-bottom: 12px; }
  .vedit-preview-head { top: 16px; }
  .vedit-select { padding-top: 12px; }
  .vedit-captions { margin-top: 10px; }
}
/* Under the width the two columns need, the panel goes under the preview and the pane
   scrolls as one page. The preview then has a height of its own, since there is no
   column for it to fill. */
@media (max-width: 1099px) {
  .edov-pane.edov-video { overflow-y: auto; }
  .vedit { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto; height: auto; }
  .vedit-main { grid-row: 1; grid-template-rows: auto auto; }
  .vedit-preview { height: clamp(360px, 62vh, 640px); }
  .vedit-side { grid-column: 1; grid-row: 2; overflow: visible; }
}
/* A phone: the overlay is the whole screen, the gutters are 16px, and the head and the
   transport tighten until they fit 390px without a horizontal scroll. */
@media (max-width: 640px) {
  .edov.edov-video { padding: 0; }
  .edov.edov-video .edov-panel { border-radius: 0; border: 0; }
  .edov.edov-video .edov-head { gap: 10px; padding: 10px 16px; }
  .edov.edov-video .edov-back { width: 38px; height: 38px; }
  .edov.edov-video .edov-head strong { font-size: 20px; }
  .edov.edov-video .edov-head .hint { padding: 4px 10px; font-size: 12.5px; }
  .edov.edov-video .edov-head .btn { padding: 8px 14px; }
  .vedit { padding: 0 16px 16px; gap: 14px; }
  .vedit-preview { padding: 12px 12px 10px; height: clamp(340px, 64vh, 560px); grid-template-rows: auto minmax(0, 1fr) auto; }
  .vedit-preview-head { position: static; grid-row: 1; margin-bottom: 8px; }
  .vedit-frame { grid-row: 2; }
  .vedit-player { grid-row: 3; gap: 0; padding: 5px 6px; margin-top: 10px; }
  .vedit-ib { width: 32px; height: 32px; }
  .vedit-ib.vedit-play { width: 42px; height: 42px; margin: 0 2px; }
  .vedit-clock { margin-left: 4px; font-size: 13px; }
  .vedit-select { padding: 14px 0 0; }
  .vedit-select .vedit-h { font-size: 19px; }
  .vedit-side { padding: 20px 16px 22px; }
  .vedit-side-title { font-size: 23px; }
  .vedit-times { gap: 10px; }
  .vedit-tf-box { gap: 8px; padding: 0 10px; }
  .vedit-tf-in { font-size: 16px; }
  .vedit-captions { flex-wrap: wrap; gap: 10px; }
  .vedit-captions-n { order: 3; flex-basis: 100%; }
  .vedit-cc { padding: 0 14px; }
  .vedit-captions-files { margin-left: auto; }
  .vedit-dl { padding: 0 12px; }
  .vedit-apply-meta { padding: 0 14px; }
}

/* ================= THE PRODUCT'S FRAME =================
   Two vertical columns, as tall as the screen. On the left the memory: the brand,
   where you go, and the saved generations. On the right the work.

   The left column does not scroll. It used to be `sticky`, which is a different
   thing: it stayed pinned at the top but the page beneath it scrolled, and with a
   short window half the menu ended up off screen. Now the height is the screen's
   and the only part that scrolls is the generation list, inside itself.

   Collapsible: at 60px a strip of icons remains, and the conversation takes the
   200px that are freed. The state lives in localStorage — somebody working on a
   laptop closes it once, not on every launch. */
/* The band over the studio while a staff session reads a prompt set (prompt-set-band.js): a row of the body's column,
   above the shell, so the shell gives up its height. Solid, in the filled action's colours, because it has to be seen
   for as long as the test runs — the one thing worse than a test is a test somebody forgot they were running. */
.pset-band {
  flex: none; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 7px 16px; background: var(--solid); color: var(--on-solid); font-size: 13.5px;
}
.pset-band svg { width: 18px; height: 18px; flex: none; }
.pset-band-text { flex: 1; min-width: 200px; }
.pset-band-pick, .pset-band-live {
  min-height: 32px; border-radius: 8px; font: inherit; font-weight: 600;
  border: 1px solid currentColor; background: transparent; color: inherit; padding: 0 10px;
}
.pset-band-pick option { color: var(--text); background: var(--panel); }
.pset-band-live { background: var(--on-solid); color: var(--solid); border-color: var(--on-solid); cursor: pointer; }
.pset-band-error { width: 100%; font-size: 12.5px; }

.shell {
  --side-w: 264px;
  display: grid; grid-template-columns: var(--side-w) minmax(0, 1fr);
  /* Whatever is left, and `min-height: 0` is the half that does the work: a flex
     item's floor is its content, so without it a grid full of scrollable panes
     refuses to shrink and the overflow comes straight back. It was `height: 100%`,
     which is the same thing only while nothing else shares the column. */
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  transition: grid-template-columns .18s ease;
}
body.nav-collapsed .shell { --side-w: 60px; }

@media (prefers-reduced-motion: reduce) { .shell { transition: none; } }

/* ---- the column, and why it carries its own colours ----

   It is dark in both themes, on purpose. Every other surface in this studio follows
   the theme because it holds the work — a picture judged against a light ground and
   the same picture against a dark one are two different judgements, and the person
   looking has to be able to pick. The column holds no work. What it holds is where
   you are, and a fixed dark edge is what makes the workspace beside it read as the
   lit thing on the screen.

   So these tokens are declared here and not in `:root`: the column is the one place
   in the interface that does not inherit the page's palette. Two things read them —
   the column, and the account menu that opens from its foot (mockup 18 draws it in
   the column's colours) — and `--accent` still comes from the theme, because the
   brand's pink is the brand's pink on either ground.

   The menu is not inside `.side`: it lives in `document.body`, because the column
   clips. So the palette is declared once for both selectors rather than inherited,
   and the menu cannot drift from the column it opens over. A skin writes its
   column's colours on both selectors for the same reason (`skinCss` in
   app/js/skin.js): an agency's column and the menu opening from it wear one palette. */
.side, .bk-pop.acct-pop {
  /* The ground and the accents are covely.ai's own — `#0A0C14` is the site's dark
     surface and the three drifting fields below are its hero's, to the hex. The
     column is the one place in the product that has to read as the same object as
     the homepage. */
  --side-bg: #0a0c14;
  --side-bg-2: rgba(255, 255, 255, .055);
  --side-line: rgba(255, 255, 255, .09);
  --side-text: #b9bfd4;
  --side-ink: #f2f4fb;
  --side-muted: #7d849e;
}
.side {
  /* The three drifting fields, as variables rather than as literals in the rules
     below.

     They were covely.ai's magenta, purple and blue, written into the gradients —
     and on a column an agency is reselling as its own that is **our brand showing
     through theirs**, which is the one thing the white label exists to remove. It
     looked like decoration and it was the feature being unfinished.

     Ours by default, so nothing changes for anybody who is not reselling; a skin
     with a column colour overrides all three with tints of its own accent. */
  --side-glow-1: rgba(255, 46, 126, .58);
  --side-glow-2: rgba(124, 77, 255, .52);
  --side-glow-3: rgba(56, 110, 255, .5);
  /* And the far end of each, at zero alpha in its **own** colour rather than
     `transparent`. `transparent` is `rgba(0,0,0,0)`, and a gradient that fades to it
     is only free of a grey midpoint because every current engine interpolates
     premultiplied. That is true and it is an assumption about somebody else's
     software, on the one surface this product cannot afford to look wrong on. Three
     more tokens buys the question not being asked. */
  --side-glow-1-out: rgba(255, 46, 126, 0);
  --side-glow-2-out: rgba(124, 77, 255, 0);
  --side-glow-3-out: rgba(56, 110, 255, 0);

  position: relative; isolation: isolate;
  display: flex; flex-direction: column; min-height: 0; height: 100%; overflow: hidden;
  padding: 16px 14px 10px; background: var(--side-bg); border-right: 0;
  color: var(--side-text);
}

/* ---- the drifting ground, from the site's hero ----

   Three soft colour fields on long, unequal cycles, so the ground moves without
   ever arriving anywhere; `alternate`, so there is no jump at the loop. Only
   `transform` animates — the blur is applied once and the layer is composited after
   that, which is what keeps three blurred circles cheap enough to leave running
   behind every screen.

   Pseudo-elements and not three spans, because this column's markup is navigation:
   a person tabbing through it should not meet three empty decorative nodes, and
   there is nothing here for a screen reader to skip. Two of them belong to `.side`
   and the third to `.side-nav`, which is the only way to get three with no extra
   element — and it is why they are placed in per-cent of their own box.

   `isolation: isolate` on the column and `z-index: 0` here: without a stacking
   context of its own a blurred layer at `-1` paints behind the column's own
   background and disappears, which is the failure that looks like «the effect did
   not ship».

   It is decoration with no meaning, so it stops entirely under
   `prefers-reduced-motion` — the colours stay, the movement goes, which reads as a
   designed gradient rather than as something missing. */
.side::before,
.side::after,
.side-nav::before {
  content: ""; position: absolute; z-index: 0; display: block; pointer-events: none;
  border-radius: 50%; aspect-ratio: 1; filter: blur(64px);
}
.side::before {
  top: -14%; left: -46%; width: 168%; opacity: .55;
  background: radial-gradient(circle, var(--side-glow-1), var(--side-glow-1-out) 66%);
}
.side::after {
  bottom: -10%; right: -52%; width: 176%; opacity: .5;
  background: radial-gradient(circle, var(--side-glow-2), var(--side-glow-2-out) 66%);
}
.side-nav::before {
  top: 28%; right: -34%; width: 128%; opacity: .42;
  background: radial-gradient(circle, var(--side-glow-3), var(--side-glow-3-out) 64%);
}
/* Everything the column holds sits above the fields. Stated once here rather than
   per child: a `z-index` remembered on six elements is a `z-index` forgotten on the
   seventh. */
.side > *, .side-nav > * { position: relative; z-index: 1; }
/* The fields are positioned against `.side-nav`'s box for the third one, so it must
   not clip them, and it is the one element in the column that could. */
.side-nav { position: relative; overflow: visible; }

@media (prefers-reduced-motion: no-preference) {
  .side::before { animation: side-aur-1 19s ease-in-out infinite alternate; will-change: transform; }
  .side::after { animation: side-aur-2 24s ease-in-out infinite alternate; will-change: transform; }
  .side-nav::before { animation: side-aur-3 16s ease-in-out infinite alternate; will-change: transform; }
}
@keyframes side-aur-1 { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(14%, 22vh, 0) scale(1.22); } }
@keyframes side-aur-2 { from { transform: translate3d(0, 0, 0) scale(1.12); } to { transform: translate3d(-12%, -18vh, 0) scale(.86); } }
@keyframes side-aur-3 { from { transform: translate3d(0, 0, 0) scale(.92); } to { transform: translate3d(-10%, 16vh, 0) scale(1.3); } }
/* The work fills what is left, and what scrolls is the open screen — not the whole
   page, which would drag the menu along with it. */
.main {
  min-width: 0; min-height: 0; display: flex; flex-direction: column;
  padding: 16px 20px; overflow: hidden;
}
.view { flex: 1; min-height: 0; }
/* Every screen scrolls inside itself; Direction is the exception, because it
   manages its own height (a scrolling log, the composer stuck to the bottom).
   The rule is on `.main`'s child and not on a list of classes: listing them meant a
   new page was born with no scrolling — it happened, and the symptom is a page that
   stops half-way with no way of going further down.
   `align-content: start` because a grid as tall as the screen stretches its cards:
   a card holding three lines became 400px of emptiness. */
.main > .view { overflow-y: auto; overscroll-behavior: contain; }
.main > .chat-view { overflow: hidden; }

/* ---- the boot ----

   From the first paint until app.js paints its first screen (`data-booting`, set in
   the page's head): a sketch of a page over the main area, which was white for as long
   as the bundle took, and the column's places kept — the brand kit's only where the
   last visit showed one (`data-boot-kit`), the credits and the account always, their
   contents invisible until they are true. Without it the kit card arrived with the
   first screen and pushed the whole menu down. Over the views and not instead of them:
   the landing screen is laid out underneath while the boot measures it. */
.boot-mask { display: none; }
html[data-booting] .main { position: relative; }
html[data-booting] .boot-mask {
  position: absolute; inset: 0; z-index: 30; display: flex; flex-direction: column; gap: 14px;
  padding: 28px 32px; overflow: hidden; background: var(--bg);
}
.boot-mask i {
  display: block; border-radius: 10px; background: color-mix(in srgb, var(--ink) 8%, transparent);
  animation: boot-pulse 1.1s ease-in-out infinite alternate;
}
.boot-mask .bm-eyebrow { width: 120px; height: 12px; }
.boot-mask .bm-title { width: min(360px, 60%); height: 38px; }
.boot-mask .bm-line { width: min(520px, 80%); height: 14px; margin-bottom: 22px; }
.bm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 18px; }
.boot-mask .bm-grid i { aspect-ratio: 4 / 3; border-radius: 14px; }
html[data-booting][data-boot-kit] .side-kit[hidden] { display: block !important; pointer-events: none; }
html[data-booting] .side-account[hidden] { display: flex !important; pointer-events: none; }
html[data-booting] .side-kit[hidden] .kit-btn > *,
html[data-booting] .side-account[hidden] .side-me > *,
html[data-booting] .side-account[hidden] .side-jobs { visibility: hidden; }
html[data-booting] .side-kit[hidden] .kit-btn,
html[data-booting] .side-account[hidden] .side-me {
  background: var(--side-bg-2); animation: boot-pulse 1.1s ease-in-out infinite alternate;
}
@keyframes boot-pulse { from { opacity: .5; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .boot-mask i,
  html[data-booting] .side-kit[hidden] .kit-btn,
  html[data-booting] .side-account[hidden] .side-me { animation: none; }
}
.portraits { align-content: start; }

.side-nav { display: flex; flex-direction: column; gap: 3px; }
.nav-item {
  position: relative;
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px; cursor: pointer; font: inherit; font-size: 15px; line-height: 20px; text-align: left;
  color: var(--side-text); background: transparent; border: 0; border-radius: 10px;
  transition: background .13s, color .13s;
}
.nav-item:hover { background: var(--side-bg-2); color: var(--side-ink); }
.nav-item.on {
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--side-ink); font-weight: 600;
}
/* The mark on the open screen is a bar at the edge and not only a fill. A fill of
   its own is the same gesture as `:hover`, one shade apart, so on a dark ground the
   two read as the same state — and «where am I» is the one question this column
   exists to answer. The bar is a second signal; the owner's mockup tints the fill in
   the accent as well, which is what keeps it apart from a hover's grey wash. */
.nav-item.on::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: var(--accent);
}
/* Without this line `hidden` hides nothing: the `display: flex` above beats the
   browser's rule, and the "Administration" entry would appear to everybody.
   Clicking it would give no data — the endpoint answers 404 to a
   non-administrator — but a door you can see and cannot open is still one door too
   many. */
.nav-item[hidden] { display: none; }
.nav-item.on .nav-ic { color: var(--accent-hi); }
/* The icons are drawn, not emoji: emoji change face from one system to the next and
   the column stops looking like a single menu. */
.nav-ic { flex: none; display: grid; place-items: center; width: 20px; height: 20px; color: var(--side-muted); }
.nav-item:hover .nav-ic { color: var(--side-text); }
.nav-ic svg { width: 20px; height: 20px; }
.nav-lb { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* «Create», between the brand kit and the menu: the column's one filled button, in the
   accent and nothing else — a gradient through our violet would be our brand showing
   through an agency's (`skin.js`). Never lit, so `.on` has nothing to say to it. The
   kit's own bottom margin went to this one's top, so the gap is the same with no kit. */
.side > .nav-cta {
  justify-content: center; gap: 9px; margin: 18px 0 14px; padding: 11px 14px;
  font-weight: 600; color: var(--on-accent);
  background: linear-gradient(135deg, var(--accent), color-mix(in oklab, var(--accent) 80%, #000));
  border-radius: 12px; box-shadow: 0 12px 26px -14px var(--accent);
}
.side > .nav-cta .nav-ic,
.side > .nav-cta:hover .nav-ic { color: inherit; }
.side > .nav-cta:hover {
  color: var(--on-accent); filter: brightness(1.07);
  background: linear-gradient(135deg, var(--accent), color-mix(in oklab, var(--accent) 80%, #000));
}
.side > .nav-cta:focus-visible { outline: 2px solid var(--side-ink); outline-offset: 2px; }

/* ---- the brand kit, under the logo, as the owner's mockup draws it ----
   A card of its own between the logo and the menu: the kit's logo on a tile (the
   diamond in the accent when it has none), «Active brand kit» in small spaced capitals over the name of the one in
   use, and the caret, which turns up while the menu is open. It is a dropdown and not
   an open list: there are at most ten kits, but the column has to stay a navigation
   column — the active brand is always readable, the others are looked up.

   Above the menu's entries in the stacking order, which `.side > *` would otherwise
   leave equal — and an equal later sibling paints over the dropdown. */
.side > .side-kit { z-index: 3; margin: 20px 0 0; }
.side-kit[hidden] { display: none; }
/* The company the session is in, over the brand it holds (proposal C of #452): small and dim, a caption and not a
   control — the company is switched in Settings › Sub-companies. Folded, there is no room for a word, and the card's
   tile says which brand; the name stays for a screen reader. */
.kit-org {
  display: flex; align-items: center; gap: 6px; margin: 0 2px 6px; min-width: 0;
  font-size: 12px; font-weight: 600; line-height: 1.3; color: var(--side-text);
}
.kit-org::before {
  content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--side-muted);
}
.kit-org[hidden] { display: none; }
.kit-org-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kit-btn {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 58px;
  padding: 10px 12px; cursor: pointer; font: inherit; text-align: left;
  color: var(--side-ink); background: rgba(255, 255, 255, .03);
  border: 1px solid var(--side-line); border-radius: 12px;
  transition: background .13s, border-color .13s;
}
.kit-btn:hover, .kit-btn[aria-expanded="true"] { background: var(--side-bg-2); border-color: rgba(255, 255, 255, .14); }
.kit-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.kit-ic {
  flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 9px;
  color: var(--accent-hi); background: color-mix(in srgb, var(--accent) 13%, transparent);
}
/* The kit's own logo, when it has one (`paintKitMark`): on white, as the menu's tiles draw
   the others, and on a dark ground when it is drawn in white. The diamond is the kit with
   no logo. */
.kit-ic.logo, .kit-tile.on.logo { padding: 4px; background: #fff; }
.kit-ic.logo.on-dark, .kit-tile.logo.on-dark { background: #111; }
.kit-ic img { display: block; max-width: 100%; max-height: 100%; object-fit: contain; }
.kit-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; line-height: 1.25; }
.kit-label, .kit-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kit-label { font-size: 10px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--side-muted); }
.kit-name { font-size: 15px; font-weight: 700; color: var(--side-ink); }
.kit-name:empty { display: none; }
.kit-caret { flex: none; display: grid; place-items: center; color: var(--side-text); }
.kit-caret svg { display: block; transition: transform .16s ease; }
.kit-btn[aria-expanded="true"] .kit-caret svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .kit-caret svg { transition: none; } }

/* The menu: a panel in the column's own surfaces, hung under the card, as wide as it,
   and drawn over the entries below rather than pushing them down — the column is a
   navigation, and a menu that moved it would move the entry the pointer was going to.

   The ground is opaque, for the same reason as the account menu's: it lies over the
   column's own rows, and in the rail over the work, and a translucent one would show
   either through it. It is the column's ground lifted towards a warm violet, which is
   the shade the mockup's panel is drawn in, and a skin's column takes it with it
   because it is mixed from `--side-bg`.

   A column of three parts, and only the middle one scrolls: past `--kit-room` (the
   height kits.js measured under the card) the brands scroll, and the count and «New
   brand» stay where they are. */
.kit-menu {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 40;
  display: flex; flex-direction: column; max-height: var(--kit-room, 440px); padding: 7px;
  color: var(--side-text);
  background: color-mix(in srgb, var(--side-bg) 86%, #c08ab8);
  border: 1px solid rgba(255, 255, 255, .15); border-radius: 14px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .5), 0 2px 8px rgba(0, 0, 0, .28);
}
.kit-menu[hidden] { display: none; }
.kit-head {
  flex: none; display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
  padding: 5px 9px 8px; font-size: 12.5px; color: var(--side-text);
}
.kit-count { font-variant-numeric: tabular-nums; color: var(--side-text); }
.kit-list { display: flex; flex-direction: column; min-height: 0; }
.kit-rows { display: flex; flex-direction: column; gap: 2px; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.kit-rows[hidden] { display: none; }
.kit-row, .kit-act {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 6px 8px;
  cursor: pointer; font: inherit; font-size: 13.5px; text-align: left; color: var(--side-ink);
  background: transparent; border: 0; border-radius: 10px;
}
.kit-row { flex: none; min-height: 42px; padding: 4px 7px; }
.kit-row:hover, .kit-act:hover:not(:disabled) { background: rgba(255, 255, 255, .06); }
.kit-row:focus-visible, .kit-act:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; background: rgba(255, 255, 255, .06); }
/* The one in use, as drawn: a wash in the accent and a check at the end. */
.kit-row.on, .kit-row.on:hover { background: color-mix(in srgb, var(--accent) 17%, transparent); font-weight: 700; }
.kit-tile {
  flex: none; display: grid; place-items: center; width: 34px; height: 34px; overflow: hidden;
  border-radius: 9px; font-size: 12.5px; font-weight: 500; letter-spacing: .02em; line-height: 1;
  color: var(--side-text); background: rgba(255, 255, 255, .07);
}
.kit-tile.on { color: var(--accent-hi); background: color-mix(in srgb, var(--accent) 15%, var(--side-bg)); }
/* A logo is drawn for a light page far more often than for this column: on a light
   tile it reads, and on the column's ground a dark mark would be a dark square. */
.kit-tile.logo { padding: 4px; background: #fff; }
.kit-tile img { display: block; max-width: 100%; max-height: 100%; object-fit: contain; }
.kit-row-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kit-tick { flex: none; color: var(--accent-hi); stroke-width: 2.3; }
.kit-rule { flex: none; height: 1px; margin: 5px 8px; background: rgba(255, 255, 255, .1); }
.kit-act { flex: none; min-height: 36px; padding: 6px 9px; }
.kit-act > .bk-ic { flex: none; color: var(--side-text); }
.kit-act-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kit-act:disabled { color: var(--side-muted); cursor: not-allowed; }
.kit-act:disabled > .bk-ic { color: var(--side-muted); }
.kit-limit { flex: none; margin: 4px 10px 4px; font-size: 11px; line-height: 1.4; color: var(--side-text); }
.kit-limit[hidden] { display: none; }
/* A finger needs the 44px the mockup's tight rows do not give it. */
@media (pointer: coarse) { .kit-row, .kit-act { min-height: 44px; } }

/* ---- the foot of the column, as the owner's mockup 25 draws it ----
   One block, pushed to the bottom: the balance on one row, a rule, and who signed in
   with the bell. One block and not two elements with a `margin-top: auto` each — that
   would push only the first one down, and hiding one would float the other back up to
   the middle of the column. No rule over it: the menu above ends in its own space.

   It is also the box the bell's panel opens against — `.side > *` makes it a
   positioned element — so the panel sits above the whole foot and as wide as it is. */
.side-foot {
  margin-top: auto; display: flex; flex-direction: column; gap: 8px; padding-top: 14px;
}

/* The bell, on the user row, and the panel it opens above the foot. It is always on
   screen: at rest it is dim, which is an icon rather than an alert. 40px and not the
   44px the accessibility block asks of a lone target, so the name keeps its room. */
.side-jobs { flex: none; }
.side-jobs[hidden] { display: none; }
.jobs-btn {
  position: relative; display: grid; place-items: center; flex: none;
  width: 40px; height: 40px; padding: 0; cursor: pointer;
  color: var(--side-text); background: transparent; border: 0; border-radius: 10px;
}
.jobs-btn:hover, .jobs-btn[aria-expanded="true"] { color: var(--side-ink); background: var(--side-bg-2); }
.jobs-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.jobs-ic svg { width: 20px; height: 20px; display: block; }
/* The counter, drawn as the mockup's dot on the bell: the accent, ringed in the
   column's ground so it reads as sitting on the icon. The figure stays inside it and
   is not drawn — at 9px no figure reads, and the dot is the alert. `textContent` is
   what the button's label is made from, «3 generations running», and what the checks
   read; `--on-accent` travels with the fill all the same.

   It used to be a 17px pill with the figure in it, and the lesson recorded there
   still holds: `--k` is declared per kind, on the tiles and the cards — never on this
   subtree — so a `var(--k)` here resolves to nothing. The counter's background came
   out `rgba(0, 0, 0, 0)` once, which is why it is the accent. */
.jobs-n {
  position: absolute; top: 7px; right: 8px; width: 9px; height: 9px; padding: 0;
  border-radius: 50%; background: var(--accent); color: var(--on-accent);
  box-shadow: 0 0 0 2px var(--side-bg);
  font-size: 0; line-height: 0; overflow: hidden;
}
.jobs-n[hidden] { display: none; }
.jobs-panel {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); z-index: 40;
  max-height: 320px; overflow-y: auto; padding: 5px;
  border: 1px solid var(--border); border-radius: 11px;
  background: var(--panel); box-shadow: var(--shadow-2);
}
.jobs-panel[hidden] { display: none; }
/* The organisation's notices, in the one bell's panel under the generations (notifications.js). A heading, and rows that
   are the same width and hover as a generation's row. */
.side-jobs { display: flex; align-items: center; gap: 4px; }
.notify-section { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); }
.notify-section[hidden] { display: none; }
.notify-head { margin: 0 0 2px; padding: 0 8px; font-size: 12px; font-weight: 600; color: var(--muted); }
.notify-list { margin: 0; padding: 0; list-style: none; }
.notify-row { display: block; }
.cred-mine[hidden] { display: none; }
.cred-mine-body { display: flex; flex-direction: column; }
/* One row per request: a status chip, the amount in bold and the day beneath it, and a divider between rows. */
.cred-mine-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 12px 0; border-top: 1px solid var(--border); font-size: 14px; }
.cred-mine-row:first-child { border-top: 0; padding-top: 4px; }
.cred-mine-text { display: flex; flex: 1 1 180px; flex-direction: column; min-width: 0; line-height: 1.35; }
.cred-mine-chip { flex: none; padding: 2px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; background: var(--panel-2); color: var(--ink); }
.cred-mine-chip.ok { color: var(--ok); }
.cred-mine-chip.no { color: var(--danger); }
.cred-mine-chip.wait { color: var(--muted); }
.cred-mine-title, .chl-requests-title, .chl-pane-title { margin: 0 0 4px; font-size: 16px; }
.chl-requests, .chl-history { container: chl-req / inline-size; }
.chl-requests[hidden], .chl-history[hidden] { display: none; }
.chl-requests-body { min-width: 0; overflow-x: auto; }
.notify-wait { padding: 4px 8px; font-size: 13px; }
/* The requests table is its own (not .chl-table): the Sub-companies table is the first one on the page, and the rows of the two
   must not be counted as one another. */
.chl-decide { width: 100%; border-collapse: collapse; font-size: 14px; }
.chl-decide th, .chl-decide td { padding: 9px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.chl-decide th { font-size: 12px; font-weight: 600; color: var(--muted); }
/* Narrow, each request is a block: the sub-company and its figure on the first line, the note and the day under them, and
   Grant and Decline as two full-width buttons. The header stays for a screen reader. A table of five columns cannot fit a
   390px card, and it was clipped at its right edge (the Asked and Answer columns). */
@container chl-req (max-width: 600px) {
  .chl-decide thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .chl-decide, .chl-decide tbody { display: block; width: 100%; }
  .chl-decide tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 12px; align-items: baseline; padding: 12px 0; border-bottom: 1px solid var(--border); }
  .chl-decide tr:first-child { padding-top: 4px; }
  .chl-decide td { display: block; padding: 0; border: 0; }
  .chl-decide td[data-label]:not(.chl-name):not(.chl-actions)::before { content: attr(data-label); display: block; font-size: 12px; font-weight: 600; color: var(--muted); }
  .chl-decide td.chl-num { text-align: right; }
  .chl-decide td:nth-child(3), .chl-decide td:nth-child(4) { grid-column: 1 / -1; }
  .chl-decide td.chl-actions { grid-column: 1 / -1; display: flex; gap: 8px; }
  .chl-decide td.chl-actions .btn { flex: 1 1 0; }
  /* The decided list has six cells and no answers: two to a line, the outcome and who asked under the sub-company. */
  .chl-decided td:nth-child(3), .chl-decided td:nth-child(4) { grid-column: auto; }
}
.cred-request[hidden] { display: none; }
/* The company switch at the top of «Your sub-companies» (`orgSwitchBlock` in app.js): one row a company, its name and
   «Open», the one the session is in ticked instead — the check the brand menu ends its brand in use with, and
   `aria-current` with the word for a screen reader. */
.chl-switch { margin: 6px 0 16px; padding-bottom: 14px; border-bottom: 1px solid var(--border); }
.chl-switch-title { margin: 0 0 2px; font-size: 14px; }
.chl-switch-other { margin: 12px 0 4px; font-size: 13px; color: var(--muted); }
.chl-switch-hint { margin: 0 0 8px; }
.chl-switch-list { display: flex; flex-direction: column; }
.chl-switch-row {
  display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 6px 0;
  border-top: 1px solid var(--border);
}
.chl-switch-row:first-child { border-top: 0; }
.chl-switch-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.chl-switch-row[aria-current="true"] .chl-switch-name { font-weight: 600; }
.chl-switch-row .acct-tick { flex: none; color: var(--accent); stroke-width: 2.3; }
.chl-switch-go { flex: none; }
.job {
  display: flex; align-items: flex-start; gap: 8px; width: 100%;
  padding: 7px 8px; border: 0; border-radius: 8px; background: none;
  text-align: left; cursor: pointer;
}
.job:hover { background: var(--panel-2); }
.job-dot { flex: 0 0 7px; width: 7px; height: 7px; margin-top: 5px; border-radius: 50%; background: var(--muted); }
.job-running .job-dot { background: var(--k); animation: job-pulse 1.4s ease-in-out infinite; }
.job-ready .job-dot { background: var(--ok); }
.job-missing .job-dot { background: var(--danger-line); }
.job-body { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 7px; }
.job-what { font-size: 12.5px; color: var(--ink); }
.job-state { font-size: 11.5px; color: var(--muted); }
.job-back { font-size: 11px; color: var(--ok); }
@keyframes job-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .job-running .job-dot { animation: none; } }

/* Who signed in, at the foot of the column, with the bell — and the balance on the line under the name (proposal C of
   #452, as the owner took it on 2026-10-26). One row: the 34px round initials, the name, under it the coin, the figure
   in bold and «credits», and the bell beside the row. No caret and no chevron: the row opens the account menu, whose
   first entry is the credits and the plan. Where there is no credit system, the role takes the line back. Below twenty
   credits the figure turns red: the next generation might not start, and finding that out from the refusal is too late.

   The accent is the keyboard's ring and nothing else, as everywhere in the studio. */
.side-account { display: flex; align-items: center; gap: 6px; }
.side-account[hidden] { display: none; }
.side-me {
  display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; min-height: 52px;
  padding: 6px 10px; cursor: pointer; font: inherit; text-align: left; color: inherit;
  background: none; border: 0; border-radius: 10px;
  transition: background .13s;
}
.side-me:hover, .side-me[aria-expanded="true"] { background: var(--side-bg-2); }
.side-me:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The initials, round, in the brand's gradient: the same disc on the row and on the
   Profile, which is why the two share this rule. The fill is a picture and the same
   in both themes. */
.side-avatar {
  display: grid; place-items: center; width: 34px; height: 34px; flex: none;
  border-radius: 50%; color: #fff;
  background: linear-gradient(140deg, var(--accent) 0%, #7b2ff7 100%);
  font-size: 12.5px; font-weight: 700; letter-spacing: .02em;
}
.side-account-name { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; line-height: 1.3; }
.side-account-name strong { font-size: 14px; color: var(--side-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-account-name .hint { margin: 0; font-size: 12px; color: var(--side-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The balance's line: the role's place, which the role gives back when there is no balance to show. */
.side-credits {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: 12.5px; color: var(--side-text); white-space: nowrap;
}
.side-credits[hidden] { display: none; }
.side-credits:not([hidden]) ~ #account-role { display: none; }
.cr-coin { flex: none; display: block; width: 13px; height: 13px; color: var(--accent-hi); }
.cr-num { font-weight: 700; color: var(--side-ink); font-variant-numeric: tabular-nums; }
.cr-word { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.side-credits.low .cr-num, .side-me.low .cr-short { color: #ff8fa8; }
/* The folded column's figure, under the initials: shown only there. */
.cr-short {
  display: none; font-size: 11.5px; font-weight: 700; line-height: 1.1; color: var(--side-ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* The account menu, over the user row (`openAccountMenu` in app.js): a `.bk-pop` in
   `document.body`, drawn in the column's palette in both themes, as the owner's
   mockup has it — the tokens are declared for it beside `.side`'s. In the open
   column it is as wide as the row it opens over (the width comes from the row, in
   app.js); folded, the rail and the phone strip are narrower than a menu can be.

   The ground is opaque: the menu sits over the column's own rows, and a translucent
   one would show them through it. It is the column's ground lifted towards a violet,
   as drawn — `#211f37` on ours, and a skin's column takes it with it because it is
   mixed from `--side-bg`. Measured on ours: the name 15:1, the entries 9:1, the
   glyphs 4.6:1, an entry under the pointer 13:1. */
.bk-pop.acct-pop {
  width: min(248px, calc(100vw - 16px)); padding: 6px; color: var(--side-text);
  background: color-mix(in srgb, var(--side-bg) 82%, #8a7bd8);
  border-color: rgba(255, 255, 255, .11); border-radius: 12px;
}
.acct-head { padding: 10px 10px 6px; }
.acct-head strong {
  display: block; font-size: 14px; color: var(--side-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The line under a name or an entry: the role under the person's name, whose credits they are under «Credits». */
.acct-sub {
  display: block; margin-top: 1px; font-size: 12px; font-weight: 400; color: var(--side-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.acct-text { flex: 1; min-width: 0; }
/* The balance at the end of «Credits», as the row under the name prints it. */
.acct-fig { margin-left: auto; font-weight: 700; color: var(--side-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.acct-fig.low { color: #ff8fa8; }
.acct-sep { height: 1px; margin: 5px 6px; background: rgba(255, 255, 255, .1); }
.acct-item {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 38px; padding: 8px 10px;
  cursor: pointer; font: inherit; font-size: 14px; text-align: left; color: var(--side-ink);
  background: none; border: 0; border-radius: 8px; text-decoration: none;
}
.acct-item svg { flex: none; color: var(--side-text); }
.acct-item:hover, .acct-item:focus-visible { background: rgba(255, 255, 255, .07); }
.acct-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* How many support requests the team has answered and nobody has read yet (`support.js`):
   a figure at the end of the entry, and a dot on the avatar of the row that opens it. */
.acct-badge {
  margin-left: auto; min-width: 20px; padding: 1px 6px; border-radius: 999px; text-align: center;
  font-size: 11.5px; font-weight: 700; color: var(--on-accent); background: var(--accent);
}
#account-menu[data-unread] .side-avatar { position: relative; }
#account-menu[data-unread] .side-avatar::after {
  content: ''; position: absolute; top: -1px; right: -1px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 2px var(--side-bg);
}

/* ---- column collapsed: the icons remain ---- */
body.nav-collapsed .side { padding: 14px 8px; align-items: center; }
body.nav-collapsed .side-brand {
  flex-direction: column; gap: 8px; width: 100%; padding: 0 0 12px;
}
/* Folded, the lockup goes and the mark takes its place — the one swap this column
   needs and the only reason the second image is in the page at all. */
body.nav-collapsed .brand-mark { height: 30px; }
body.nav-collapsed .brand-ours-full { display: none; }
body.nav-collapsed .brand-ours-icon { display: block; width: 30px; height: 30px; }
body.nav-collapsed .brand-word,
body.nav-collapsed .nav-lb,
body.nav-collapsed .kit-text,
body.nav-collapsed .kit-caret { display: none; }
/* The name and the exact balance stay for a screen reader — the row is still «Smoke Tester, 5,067.14 credits» — and the
   eye gets the initials over the short figure, because the name is wider than the 44px there are. The company's caption
   the same way. */
body.nav-collapsed .side-account-name,
body.nav-collapsed .kit-org {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* Column collapsed: the rows stand on end. Of the brand the tile remains, of who signed
   in the initials over the short balance — which still open the account menu — and the
   bell under them. */
body.nav-collapsed .side > .side-kit { margin: 14px 0 0; }
/* «Create» stands on end with the rest: the accent's round button, its icon alone. */
body.nav-collapsed .side > .nav-cta { flex: none; width: 44px; height: 44px; margin: 12px 0 10px; padding: 0; border-radius: 50%; }
body.nav-collapsed .kit-btn {
  justify-content: center; width: 44px; min-height: 44px; padding: 4px;
  background: none; border-color: transparent;
}
body.nav-collapsed .side-foot { width: 100%; align-items: center; gap: 8px; padding-top: 12px; }
body.nav-collapsed .side-account { flex-direction: column; gap: 4px; }
body.nav-collapsed .side-me {
  flex: none; flex-direction: column; justify-content: center; gap: 3px; width: 44px; min-height: 56px; padding: 4px 0;
}
body.nav-collapsed .cr-short { display: block; }
/* Stacked under the row, as the 44px column has no room beside it (the same on the phone's strip, below). */
body.nav-collapsed .side-jobs { flex-direction: column; }
/* The two menus cannot fit inside 60px, and `.side` clips whatever tries: they leave
   the column, fixed beside it — the kit's level with the button that opened it
   (`--kit-at`, written by kits.js as it opens), the bell's on the bottom edge — which
   is the one position its clip does not reach. While one is open the column rises
   over the work beside it, or the positioned pieces of the open screen (a sticky bar,
   a card's «⋯») would paint over the menu. Under the app's overlays and dialogs,
   which start at 50. */
body.nav-collapsed .kit-menu,
body.nav-collapsed .jobs-panel {
  position: fixed; left: calc(var(--side-w) + 8px); right: auto; bottom: 12px;
  width: min(280px, calc(100vw - var(--side-w) - 16px));
}
body.nav-collapsed .kit-menu {
  top: var(--kit-at, 12px); bottom: auto; max-height: calc(100vh - var(--kit-at, 12px) - 12px);
}
body.nav-collapsed .side:has(.kit-menu:not([hidden]), .jobs-panel:not([hidden])) { z-index: 45; }
body.nav-collapsed .side-toggle { margin: 0; }
body.nav-collapsed .side-nav { width: 100%; }
body.nav-collapsed .nav-item { justify-content: center; padding: 12px 0; gap: 0; }

/* Below 1180px the director's two columns no longer fit side by side: the
   conversation keeps a height of its own and the stage goes beneath it, with the
   screen scrolling.

   It used to be 1020px, which was the width at which the *chat* stopped being
   usable. The binding constraint is now the other column: with the nav rail out,
   1024px leaves the stage 372px — narrower than the conversation beside it, which
   is the exact thing this layout exists to prevent. Stacked, it gets the whole
   width instead. Measured, not guessed: rail 230 + padding 36 + chat 330 + gap 18
   leaves a stage worth having only from about 1174px up. */
@media (max-width: 1180px) {
  .chat-view { grid-template-columns: 1fr; overflow-y: auto; overscroll-behavior: contain; }
  /* «With the screen scrolling», and for a long time it did not: `.main > .chat-view
     { overflow: hidden }` is two classes and the line above is one, so the view held
     still and whatever passed its bottom was cut — measured at 390×844, 959px of
     conversation, composer and stage inside an 822px box. The same two classes here,
     later in the sheet, win.

     And «a height of its own» is a floor, not a lid. At a fixed `min(72vh, 620px)` a
     composer taller than what was left of it — the PRO strip on a phone, a question
     card over the box — ran on over the stage below, and the stage was drawn under it.
     The conversation's row is sized to what the column holds, never less than that
     height, and the stage's to what it holds; the log is given a definite 160px to
     start from, so a long conversation scrolls inside it instead of growing the
     column — a basis of 0% is read as «its content» once the column's height is. */
  .main > .chat-view { overflow-y: auto; grid-template-rows: max-content max-content; }
  .chat-col { height: auto; min-height: min(72vh, 620px); }
  .chat-log { flex: 1 1 160px; }
  .chat-side { height: auto; overflow: visible; padding-right: 0; }
}
@media (max-width: 700px) {
  .shell { --side-w: 216px; }
  .main { padding: 12px 12px 14px; }
}

/* The prompt that was sent, collapsed: needed when a change is not visible in the
   video and the question becomes "what was actually asked for". */
.prompt-trace { padding: 8px 12px; }
.prompt-trace summary { cursor: pointer; font-weight: 600; }
.prompt-trace .prompt { margin: 8px 0 0; max-height: 260px; overflow: auto; font-size: 11.5px; }

/* ---- the workspace: a stage, and a rail beside it ----
   The rail carries what belongs to the thing being made — the video's versions,
   the image's editing panel. It is `hidden` and not empty when there is nothing to
   carry, and the stage takes the whole width: a column of nothing narrows the work
   for no one's benefit. */
/* Beside the stage only when the *workspace* is wide enough — which is not a
   question any viewport width can answer. At 1440px the answer depends on whether
   the navigation rail is collapsed, and a media query that says «beside» while the
   rail is out puts the video back at 420px, the exact width this layout was built
   to escape. A container query asks the one element that knows. */
.result-card { container-type: inline-size; container-name: ws; }
/* How tall the picture on the stage may be, and the box that holds its place while it
   is being made — one figure for both, so nothing moves when the picture lands in it.
   Six tenths of the screen, and on a short one less: the strip of what was made sits
   under the stage, and at 1280×800 a stage at 60vh left the strip's captions cut in
   half by the bottom of the column while the next picture was being made. 360px is
   what stands round the box in the column — the card's head, the arrows under the box,
   the strip and its captions, the line under them — and 240px is a floor, so a short
   window still shows a picture rather than a thumbnail. */
.ws { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; align-items: start; }
/* The side: every generation of the job, pictures and videos alike, from the first to the
   last (`.ws-side`). It stands beside the stage for every job — the owner's «sempre in
   verticale accanto» (2026-10-25), where it used to be beside a 9:16 only and under anything
   wider — in a column of its own, as tall as the stage and scrolling inside itself.
   `contain: size` keeps the column's own content from making the row taller than the stage.
   Only where the card has the room; a phone keeps the strip under the stage, lying down. */
.ws-side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
/* Its width is a quarter of the card's, between 150 and 240 pixels: at 1280 that still leaves
   a 9:16 at the stage's full height its width, and at 1920 the thumbnails read. Its own name,
   `--ws-side`: `--side-w` is the navigation's width, which a fallback here would inherit. */
@container ws (min-width: 500px) {
  .result-card .ws { --ws-side: clamp(150px, 26cqi, 240px); grid-template-columns: minmax(0, 1fr) var(--ws-side); align-items: stretch; }
  .result-card .ws-side {
    contain: size; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; padding: 2px 2px 2px 0;
  }
  .result-card .ws-side > * { flex: none; }
  .result-card .gp-strip { margin-top: 0; }
  .result-card .gp-strip-head { flex-direction: column; align-items: flex-start; gap: 2px; margin-bottom: 8px; }
  .result-card .gallery.result-strip { flex-direction: column; gap: 10px; margin-top: 0; overflow: visible; }
  .result-card .result-strip .shot { flex: none; width: 100%; max-width: none; }
  /* The stage stands at the page's full height whatever the piece's shape — the owner's word of
     2026-10-25: a 16:9 shrank the whole card to its own height, the column of generations beside
     it with it, where a 9:16 took the page. Its box is the height a tall piece gives it (the
     piece at \`--stage-h\`, the caption row under it, the padding), and a wide piece sits in its
     middle. A phone keeps the piece's own height: the strip lies under it there. */
  .gp-card .result-card .ws-stage {
    display: flex; flex-direction: column; justify-content: center;
    min-height: calc(var(--stage-h) + 78px);
  }
}
.ws-stage { min-width: 0; }
/* ---- the image editor, over everything ----
   Over, and not beside. The panel used to live in the rail, which was defensible
   while it was four sliders — and it is not four sliders: it is a creative editor
   with a canvas, a format bar, a template gallery, an animation timeline and an
   inspector. In 240px it read as a prototype, and under the container-query
   threshold it fell below the picture, which is worse. Full-bleed, it is the thing
   you came to use.

   A frame and not a component: it is a separate application with its own runtime.
   See editor/VENDORED.md. */
/* A panel over the page, not a second page.
   Full-bleed, it read as a navigation: the studio vanished and there was no
   indication you were still inside a job you could step back out of. Inset, on a
   dimmed ground, with a rounded edge and a shadow, it reads as what it is — a
   thing opened on top of the work, which is still there behind it. */
.edov {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center;
  padding: clamp(12px, 3.2vh, 34px) clamp(12px, 3.6vw, 56px);
  background: color-mix(in srgb, var(--ink) 46%, transparent);
  backdrop-filter: blur(2px);
}
.edov[hidden] { display: none; }
.edov > * { grid-column: 1; }
@media (prefers-reduced-motion: no-preference) {
  .edov { animation: edov-in .16s ease-out; }
}
@keyframes edov-in { from { opacity: 0; } }
/* The page behind must not scroll while a full-bleed frame is over it: on a
   trackpad the scroll chains through and the studio moves underneath. */
body.editor-open { overflow: hidden; }
.edov-panel {
  display: flex; flex-direction: column; overflow: hidden;
  width: min(100%, 1440px); height: min(100%, 940px);
  background: var(--bg); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: 0 24px 70px rgb(0 0 0 / .32);
}
.edov-head {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--panel);
}
.edov-head strong { font-size: 13px; }
.edov-head .hint {
  margin: 0; font-size: 11.5px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.edov-head .btn { margin-left: auto; flex: none; }
.edov-body { flex: 1; min-height: 0; position: relative; }
.edov-pane { position: absolute; inset: 0; }
.edov-pane[hidden] { display: none; }
.edov-frame { display: block; width: 100%; height: 100%; border: 0; }
/* The range editor gets the width it always needed: a track eight hundred pixels
   long says where eight seconds out of twenty are, and a hairline in a column did
   not — while the button under it spent credits on whatever the hairline said. */
.edov-stage { overflow-y: auto; padding: 18px; }
.edov-stage > * { max-width: 1100px; margin-inline: auto; }
/* The image editor over the conversation: the picture and the panel, side by side.
   Each child names its own track, so neither can slide into the other's. */
.edov-retouch { display: grid; grid-template-columns: minmax(0, 1fr) 340px; grid-template-rows: minmax(0, 1fr); }
.edrt-main { grid-column: 1; grid-row: 1; position: relative; overflow: hidden; background: var(--sd-stage); }
.edrt-side { grid-column: 2; grid-row: 1; min-width: 0; overflow-y: auto; padding: 0 20px 20px; border-left: 1px solid var(--sd-line); background: var(--panel); }
.edrt-side > .sd-sec:first-child { border-top: 0; }
.edrt-compare { position: absolute; left: 50%; bottom: 44px; z-index: 3; width: min(320px, 80%); transform: translateX(-50%); }
.edrt-compare .sd-seg { width: 100%; background: var(--panel); box-shadow: var(--sd-sh-1); }
.edrt-compare[hidden] { display: none; }
@media (max-width: 760px) {
  .edov-retouch { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) minmax(0, 48%); }
  .edrt-side { grid-column: 1; grid-row: 2; border-left: 0; border-top: 1px solid var(--sd-line); padding: 0 16px 16px; }
}
.edov-status { margin: 0; padding: 6px 14px; border-top: 1px solid var(--border); background: var(--panel); }
.edov-status[hidden] { display: none; }

/* Two versions in one box, oldest revealed from the left. */
.icmp { --at: 50%; display: grid; gap: 10px; }
.icmp-view {
  position: relative; width: 100%;
  cursor: ew-resize; touch-action: none; user-select: none;
}
.icmp-shot {
  display: block; width: 100%; max-height: 62vh; object-fit: contain;
  border-radius: 10px; border: 1px solid var(--border);
  background: repeating-conic-gradient(var(--panel-3) 0% 25%, var(--panel-2) 0% 50%) 50% / 16px 16px;
}
/* The older one covers the newer exactly and is cut at the handle. Clipped rather
   than narrowed: a box that gets shorter scales the picture inside it, and two
   pictures at two scales are not a comparison. */
.icmp-clip { position: absolute; inset: 0; clip-path: inset(0 calc(100% - var(--at)) 0 0); }
.icmp-clip .icmp-shot { height: 100%; max-height: none; }
.icmp-handle {
  position: absolute; top: 0; bottom: 0; left: var(--at);
  width: 34px; margin-left: -17px; padding: 0;
  display: grid; place-items: center;
  background: none; border: 0; cursor: ew-resize; touch-action: none;
}
.icmp-handle::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 50%;
  width: 2px; margin-left: -1px;
  background: var(--panel); box-shadow: 0 0 0 1px rgb(0 0 0 / .35);
}
.icmp-grip {
  position: relative; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  font-size: 12px; line-height: 1; letter-spacing: -1px; color: var(--ink);
  background: var(--panel); border: 1px solid var(--border); box-shadow: var(--shadow-1);
}
.icmp-handle:focus-visible { outline: none; }
.icmp-handle:focus-visible .icmp-grip { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Which side is which, without leaving the picture — and never in the way of the
   hand: a tag that swallows a pointerdown is a drag that does not start. */
.icmp-tag {
  position: absolute; top: 8px; z-index: 1; pointer-events: none;
  max-width: 42%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding: 3px 8px; border-radius: 999px;
  font-size: 11px; color: var(--ink-2);
  background: color-mix(in srgb, var(--panel) 88%, transparent);
  border: 1px solid var(--border);
}
.icmp-tag.old { left: 8px; }
.icmp-tag.new { right: 8px; }
.icmp-hint { margin: 0; font-size: 12px; color: var(--muted); text-align: center; }

/* The two commands on a result: download it, or open it in the editor. */
/* ---- the pieces of a job ----
   An inventory, and drawn as one. Lanes on a ruler would say these things are
   positioned against each other in time, and they are not: the sounds are
   references the model composes from, nothing is mixed here, and an asset has no
   field in which a start offset could even be written. */
.ws-strip { margin-top: 14px; }
.ws-strip[hidden] { display: none; }
.ws-strip-head { margin-bottom: 8px; }
.ws-strip-head h3 {
  margin: 0 0 2px; font-size: 11px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--muted);
}
.ws-strip-head .hint { margin: 0; font-size: 11.5px; }
.pieces { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 8px; }
.piece {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 8px 10px; border-radius: 10px;
  background: var(--panel-2); border: 1px solid var(--border);
}
.piece-tag {
  flex: none; padding: 2px 7px; border-radius: 6px;
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-2);
  background: var(--panel); border: 1px solid var(--border);
}
.piece-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.piece-body b { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.piece-what { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.piece .asset-audio { width: 100%; height: 30px; }
.piece-audio { border-left: 3px solid color-mix(in srgb, var(--accent) 55%, var(--border)); }

/* The generation's status sits above the previous video, not in its place. */
.vstatus {
  margin: 0 0 8px; padding: 7px 11px; border-radius: 8px;
  background: var(--panel-2); border: 1px solid var(--border); font-size: 12.5px;
}
.vstatus[hidden] { display: none; }

/* The outcome pill: visible from any screen and it withdraws by itself. */
.toast {
  position: fixed; left: 50%; bottom: 22px; z-index: 70;
  max-width: min(560px, 92vw); padding: 11px 16px;
  transform: translate(-50%, 14px); opacity: 0; pointer-events: none;
  font-size: 13.5px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 11px;
  box-shadow: var(--shadow-2);
  transition: opacity .18s, transform .18s;
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }
.toast.ok-hint { border-color: var(--ok-line); }
.toast.err-hint { border-color: var(--danger-line); color: var(--danger-ink); }
/* A notice with somewhere to send the reader takes the pointer, for its one button. */
.toast.has-act { pointer-events: auto; }
.toast-act {
  margin-left: 6px; padding: 4px 10px; font: inherit; font-size: 13px; font-weight: 600;
  color: var(--text); background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
  cursor: pointer;
}
.toast-act:hover { border-color: var(--text); }

/* The browser's captions are tiny on a 9:16 vertical: here the video is a few
   hundred px wide and the default becomes illegible. */
video::cue { font-size: 15px; background: rgba(20, 22, 30, .82); line-height: 1.35; }

.ok-hint { color: var(--ok); }
.err-hint { color: var(--danger-ink); }

.card {
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  padding: 18px; margin: 0 0 18px;
}
fieldset.card { min-width: 0; }
legend { padding: 0 8px; font-weight: 700; color: var(--ink-2); }
.card h2 { font-size: 14px; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-2); margin: 18px 0 8px; }
.card h2:first-child { margin-top: 0; }

label { display: block; margin: 10px 0; font-size: 13px; color: var(--muted); }
input, select, textarea {
  width: 100%; margin-top: 4px; padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel-2); color: var(--text);
  font: inherit;
}
textarea { resize: vertical; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

.hint { color: var(--muted); font-size: 12.5px; margin: 6px 0; }
code { font-family: var(--mono); background: var(--panel-2); padding: 1px 5px; border-radius: 5px; }

.btn {
  background: var(--panel-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 8px; padding: 7px 14px; cursor: pointer; font: inherit; font-size: 13.5px;
}
.btn:hover { border-color: var(--ink); }
.btn.primary { background: var(--solid); border-color: var(--solid); color: var(--on-solid); font-weight: 600; }
.btn.primary:hover { background: var(--solid-2); border-color: var(--solid-2); }
.btn.small { padding: 3px 10px; font-size: 12.5px; }
/* A disabled button has to look disabled. Without this, a disabled "Use this style"
   is identical to a working one: you click, nothing happens, and the app looks
   broken exactly where it is in fact saying "you have already chosen". */
.btn:disabled { opacity: .45; cursor: default; }
.btn:disabled:hover { border-color: var(--border); background: var(--panel-2); }
.btn.primary:disabled:hover { background: var(--solid); border-color: var(--solid); }
/* The director's filled action, as the owner's drawings colour it: the accent as a
   fill, with its own ink on top. Kept to the director's column and its window — the
   rest of the studio still works in midnight blue, and `--accent` stays a bookmark
   everywhere else. Disabled it goes grey rather than pale pink, so «nothing chosen
   yet» does not read as a lighter version of the same invitation. */
.btn.accent { background: var(--accent); border-color: var(--accent); color: var(--on-accent); font-weight: 600; }
.btn.accent:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.btn.accent:disabled, .btn.accent:disabled:hover { opacity: 1; background: var(--panel-3); border-color: var(--panel-3); color: var(--muted); }
/* The light red came from a dark background and on white was nearly illegible —
   right on the button that deletes something. */
.btn.danger { color: var(--danger); }
.btn.danger:hover { border-color: var(--danger-ink); background: var(--danger-soft); }
/* The composer's send button, as the owner's picture draws it: a round button on
   the right of the bar with a mark in it and no word — an up-arrow while it sends,
   a rounded square while the director works and it stops the turn.

   The same fill in both states, and nothing here paints it: `--solid` under
   `--on-solid` is `.btn.primary`'s pair, hover goes to `--solid-2` through
   `.btn.primary:hover` whichever state it is in, and `.btn:disabled` still fades
   it when `paintDone` locks the composer. The stop used to turn `--danger` red; now
   the mark alone says what a press will do. In the dark theme the pair inverts — a
   near-white circle with a dark mark — which is the decision `.btn.primary` already
   makes everywhere else. Measured: the mark is 17.9:1 on the fill and 14.2:1
   hovered in the light theme, 15.0:1 and 17.9:1 in the dark one; the circle is
   17.3:1 and 12.5:1 on the composer's `--field`.

   No width floor. `min-width: 92px` was there so the bar did not reflow when the
   word «Send» gave way to the square — a control that moves under the pointer at
   the moment somebody is watching it to press it. A circle of a fixed size is the
   same box in both states, so there is nothing left to hold still.

   34px, down from 44px, which sat heavy in the bar: between ChatGPT's 36px and
   Claude's 32px, and level with the paperclip beside it (`.btn.icon`, about 33px
   tall), so the two controls of the bar share one line. 34px is well above the
   24px minimum target of WCAG 2.5.8, so it needs no widened hit area. */
#chat-send {
  width: 36px; height: 36px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  /* The accent, as the owner's drawing fills it, running into the director's violet,
     with the accent's own ink on top — in both states, so the turn starting changes the
     mark and not the colour. */
  background: linear-gradient(135deg, var(--accent), color-mix(in oklab, var(--accent) 62%, var(--dir-violet, var(--accent))));
  border-color: transparent; color: var(--on-accent);
  box-shadow: 0 8px 18px -8px var(--accent);
  transition: filter .14s, box-shadow .14s;
}
#chat-send:hover:not(:disabled) { filter: brightness(1.07); box-shadow: 0 10px 22px -8px var(--accent); }
#chat-send:disabled, #chat-send:disabled:hover { filter: none; }
/* The arrow is markup (`.send-arrow` in index.html), stroked in `currentColor`, so
   it takes the ink the fill already chose. */
#chat-send .send-arrow { display: block; width: 18px; height: 18px; }
/* The arrow rises a pixel and a half under the pointer: the one movement on the bar,
   on the one control that acts. Not while it is a Stop, and not when it cannot act. */
@media (prefers-reduced-motion: no-preference) {
  #chat-send .send-arrow { transition: transform .16s ease-out; }
  #chat-send:not(.stop):not(:disabled):hover .send-arrow { transform: translateY(-1.5px); }
}
/* Mid-turn the arrow goes and the square arrives, in `currentColor` for the same
   reason: a hardcoded white would be a second decision about the same pair, and the
   wrong one in the dark theme.
   Scoped to `#chat-send` and not to `.btn.primary.stop`, because this is the only
   element that is ever given `.stop` (`paintSend` in chat-ui.js). */
#chat-send.stop .send-arrow { display: none; }
#chat-send.stop::before {
  content: '';
  width: 12px; height: 12px;
  border-radius: 3px;
  background: currentColor;
}
.btn-row { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0; }

.row {
  border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px; margin: 8px 0;
  background: var(--panel-2);
}

.row label { margin: 6px 0; }
.row .grid2 { gap: 8px; }

.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  border: 1px solid var(--border); border-radius: 999px; padding: 3px 11px; cursor: pointer;
  font-size: 12.5px; color: var(--muted); background: transparent; user-select: none;
}
.chip.on { background: var(--violet-soft); border-color: var(--accent); color: var(--text); }

.sticky { position: sticky; top: 16px; max-height: calc(100dvh - 32px); overflow: auto; }

/* The line under the engine's name: two words saying what imposed the choice. The
   full reason lives in the title — it only goes on screen when the choice was
   forced, which is when it is the one that will be argued with. */
.settings-why { display: block; margin-top: 1px; color: var(--muted); font-size: 12px; }

/* What the director decided on its own, under the message that decided it.
   Everything visible: no tooltip, no truncation, no count standing in for the
   lines — a tooltip does not exist on touch, and a record you have to hunt for is
   not a declaration. Set apart from the message body by a rule rather than a box,
   because it is the same voice continuing and not a warning. */
.msg-assumed {
  margin: 10px 0 2px; padding: 2px 0 2px 12px;
  border-left: 2px solid var(--accent);
}
.assumed-head { margin: 0 0 4px; font-size: inherit; font-weight: 400; color: var(--muted); }
.msg-assumed ul { margin: 0; padding-left: 16px; }
.msg-assumed li { font-size: inherit; line-height: 1.5; }
.msg-assumed li::marker { color: var(--accent-ink); }

.badge { font-size: 12px; padding: 1px 8px; border-radius: 999px; background: var(--panel-2); }
.badge.ok { color: var(--ok); } .badge.warn { color: var(--warn); }

.prompt {
  white-space: pre-wrap; word-break: break-word; font-family: var(--mono); font-size: 13px;
  background: var(--code-block); color: var(--on-code-block);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 14px; min-height: 140px; max-height: 46vh; overflow: auto;
}

/* ================= THE HOME =================
   An editorial page the owner edits from the panel, laid over the whole catalogue — the
   bar's «Explore» until the owner made it the Home, and the start page that stood here
   went with that change. `app/js/catalogue.js` is the controller, `explore-blocks.js`
   draws one section type at a time, `explore-motion.js` moves what moves, and the
   contract is `docs/explore-cms.md`. The `xp-` prefix is Explore's, and stayed.

   Built from the tokens and nothing else. The accent is `--accent` wherever it is a
   fill — with `--on-accent` on it — and `--accent-ink` wherever it is text, because an
   agency's skin replaces all three. Words that sit on a photograph are `--on-scrim`
   over a gradient of `--scrim`, the pair that does not move with the theme because the
   photograph does not. The before-and-after band is `--code-block` in both themes,
   with its own ink.

   Laid out by the screen's own width — a container query on `.cat-view` — and not the
   window's: the column beside it is 264, 216, 60 or 56 pixels depending on who folded
   what, and the page has to answer to the room it actually has. Roughly, 860px of
   screen is a 1100px window with the column open and 600px is an 820px one.

   Every picture sits on a frame that is the job's colour (`[data-kind]` gives `--k`),
   so a card still loading reads as a card being filled, and a file that never arrives —
   the single-file build cannot load `img/…` at all — leaves the category's mark in a
   designed frame rather than a grey hole. */
.cat-view { position: relative; container: xp / inline-size; scrollbar-gutter: stable; }
/* `clip` and not `hidden`: a card leaning towards the pointer pokes a few pixels past
   the page, and without this the screen grew a sideways scrollbar under the mouse. A
   clip makes no scroll container, so the chips can still stick to the screen's top. */
.xp-page { max-width: var(--page-max); margin: 0 auto; padding: 2px 0 10px; overflow-x: clip; overflow-clip-margin: 6px; }
.xp-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.xp-picker { display: none; }

/* ---------- the top: the title, its line, the search ---------- */
.xp-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 16px 32px; margin: 0 0 16px;
}
.xp-head-text { flex: 1 1 440px; min-width: 0; }
.xp-title:focus { outline: none; }
/* «New generation», under the line: the straight road into the director, and the one
   control on the page that is larger than the cards' — the owner asked for it to stand
   out, and it is the first thing the page offers. The accent fill with its own ink, as
   every primary here. */
.xp-new { margin-top: 22px; min-height: 54px; padding: 0 28px 0 24px; font-size: 16px; gap: 10px; }
.xp-new .sd-ic { flex: none; }
.xp-search { position: relative; flex: 0 1 390px; min-width: min(100%, 260px); }
.xp-search > .sd-ic { position: absolute; left: 17px; top: 50%; translate: 0 -50%; color: var(--muted); pointer-events: none; }
.xp-search-input {
  display: block; width: 100%; height: 50px; margin: 0; padding: 0 46px 0 48px;
  font: inherit; font-size: 15px; color: var(--ink);
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  box-shadow: var(--shadow-1); transition: border-color .15s, box-shadow .15s;
}
.xp-search-input::placeholder { color: var(--muted); }
.xp-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
.xp-search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.xp-search-x {
  position: absolute; right: 7px; top: 50%; translate: 0 -50%;
  display: grid; place-items: center; width: 36px; height: 36px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 0; border-radius: 50%;
}
.xp-search-x:hover { color: var(--ink); background: var(--panel-2); }
.xp-search-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- the buttons the page is made of ---------- */
.xp-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px; padding: 0 22px; cursor: pointer; white-space: nowrap;
  font: inherit; font-size: 14.5px; font-weight: 700; letter-spacing: -.005em;
  border: 1px solid transparent; border-radius: 999px;
  transition: background .18s, border-color .18s, color .18s, translate .18s, box-shadow .18s;
}
.xp-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.xp-btn-primary {
  color: var(--on-accent); background: var(--accent); border-color: var(--accent);
  box-shadow: 0 12px 28px -14px var(--accent);
}
.xp-btn-primary:hover { background: var(--accent-hi); border-color: var(--accent-hi); translate: 0 -1px; }
.xp-btn-outline { color: var(--accent-ink); background: var(--panel); border-color: var(--accent-line); }
.xp-btn-outline:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 6%, var(--panel)); }
/* Glass, on a photograph: the photograph's own pair, whatever the theme. */

.xp-dur svg { fill: currentColor; }
.xp-arrow { flex: none; transition: translate .22s cubic-bezier(.2, .7, .2, 1); }
.xp-btn:hover .xp-arrow, .xp-card:hover .xp-arrow, .xp-goal:hover .xp-arrow, .xp-more:hover .xp-arrow { translate: 3px 0; }
.xp-more {
  display: inline-flex; align-items: center; gap: 6px; flex: none; padding: 6px 2px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 700; color: var(--accent-ink); background: none; border: 0; white-space: nowrap;
}
.xp-more:focus-visible, .xp-foot-top:focus-visible, .xp-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }

/* ---------- the stage ----------
   The hero in the wider track and the column of two cards beside it. Each names its
   track, so neither slides into the other's when the other is not drawn. */
.xp-stage { display: grid; grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr); gap: 16px; margin: 0 0 20px; }
.xp-hero {
  grid-column: 1; position: relative; overflow: hidden; isolation: isolate; min-width: 0;
  display: flex; align-items: center;
  min-height: clamp(290px, 28cqi, 380px); padding: clamp(22px, 2.6cqi, 32px);
  border-radius: 24px; border: 1px solid color-mix(in srgb, var(--accent) 12%, var(--border));
  background:
    radial-gradient(90% 120% at 82% 40%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%),
    linear-gradient(100deg, color-mix(in srgb, var(--accent) 7%, var(--panel)) 0%, color-mix(in srgb, var(--accent) 15%, var(--panel)) 100%);
}
/* The words take the left of the hero and the fan the right, under them in a stack: the
   fan is laid over the hero's whole height, as the mockup has it, edge to edge. */
.xp-hero-words { position: relative; z-index: 3; width: 46%; min-width: 0; }
.xp-hero-kicker {
  margin: 0; font-size: 11.5px; font-weight: 800; letter-spacing: .12em; line-height: 1.5;
  text-transform: uppercase; color: var(--accent-ink);
}
.xp-hero-title {
  margin: 10px 0 0; font-size: clamp(28px, 3.8cqi, 54px); font-weight: 800; line-height: .98;
  letter-spacing: -.05em; color: var(--ink); text-wrap: balance;
}
.xp-hero-line { margin: 12px 0 0; max-width: 34ch; font-size: 14.5px; line-height: 1.45; color: var(--ink-2); }
/* The panel allows ninety characters of title and two hundred and forty of line, and the
   hero has a height: what does not fit is clamped rather than pushed out of the card. */
.xp-hero-sentence { display: block; }
.xp-hero-title, .xp-hero-line { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.xp-hero-title { -webkit-line-clamp: 4; }
.xp-hero-go { margin-top: 18px; }

/* The fan: three tall cards across the right of the hero, the outer two in front of the
   middle one and leaning out, as the mockup has them. A card's size is a share of the
   hero's height, and the outer ones may run a little past its edge, which cuts them. */
.xp-fan { position: absolute; top: 0; right: 0; bottom: 0; width: 52%; }
.xp-fan-card {
  --x: 0%; --y: -50%; --r: 0deg; --lift: 0px;
  position: absolute; top: 50%; z-index: 2; height: 80%; aspect-ratio: 1 / 2;
  overflow: hidden; cursor: pointer; border-radius: 16px; border: 4px solid var(--panel); background: var(--panel-2);
  box-shadow: 0 24px 46px -22px color-mix(in srgb, var(--ink) 55%, transparent);
  transform: translate(var(--x), calc(var(--y) - var(--lift))) rotate(var(--r));
  transition: transform .35s cubic-bezier(.2, .7, .2, 1), box-shadow .35s;
}
.xp-fan-card[data-at='l'] { left: 5%; --y: -47%; --r: -7deg; }
.xp-fan-card[data-at='c'] { left: 50%; z-index: 1; height: 90%; --x: -50%; --y: -51%; --r: 2deg; }
.xp-fan-card[data-at='r'] { right: 3%; --y: -48%; --r: 8deg; }
.xp-fan-card:hover { --lift: 8px; z-index: 4; box-shadow: 0 30px 54px -24px color-mix(in srgb, var(--ink) 66%, transparent); }
.xp-fan-card:has(.xp-fan-go:focus-visible) { z-index: 4; outline: 3px solid var(--accent); outline-offset: 2px; }
.xp-fan-media, .xp-fan-media > .xp-pic { position: absolute; inset: 0; }
.xp-fan-go {
  position: absolute; inset: 0; z-index: 2; margin: 0; padding: 0; cursor: pointer;
  background: none; border: 0; border-radius: inherit;
}
.xp-fan-go:focus-visible { outline: none; }
.xp-fan-chip {
  position: absolute; left: 10px; top: 10px; z-index: 3; display: inline-flex; align-items: center; gap: 6px;
  max-width: calc(100% - 20px); padding: 6px 11px 6px 9px; border-radius: 999px; pointer-events: none;
  font-size: 12px; font-weight: 700; line-height: 1.1; white-space: nowrap; overflow: hidden; color: var(--ink);
  background: color-mix(in srgb, var(--panel) 94%, transparent);
  box-shadow: 0 6px 14px -8px color-mix(in srgb, var(--ink) 50%, transparent);
}
.xp-fan-chip svg { flex: none; color: var(--ink-2); }
/* The play button over a video: white, with the play drawn as a stroke. */
.xp-fan-play {
  position: absolute; left: 50%; top: 50%; z-index: 3; translate: -50% -50%;
  display: grid; place-items: center; width: 48px; height: 48px; margin: 0; padding: 0 0 0 3px;
  color: var(--scrim-strong); background: color-mix(in srgb, var(--on-scrim) 92%, transparent);
  border: 0; border-radius: 50%; box-shadow: 0 12px 26px -12px var(--scrim-strong);
}
span.xp-fan-play { pointer-events: none; }
button.xp-fan-play { cursor: pointer; transition: scale .2s; }
button.xp-fan-play:hover { scale: 1.08; }
button.xp-fan-play:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* A fan as narrow as a phone's leaves the outer cards too little room for a word: their
   chips keep the glyph, and the middle card keeps its word. */
@container xp (max-width: 600px) {
  .xp-fan-card:not([data-at='c']) > .xp-fan-chip { gap: 0; padding: 6px; font-size: 0; }
}

/* The column beside the hero: «Have an idea?» and «Start from a reference», each its tile,
   its words and its button, and its pictures on the right — tinted pink and lilac. */
.xp-stage-side { grid-column: 2; display: grid; grid-auto-rows: minmax(0, 1fr); gap: 16px; min-width: 0; }
.xp-door {
  position: relative; overflow: hidden; isolation: isolate; min-width: 0; min-height: 0;
  display: grid; grid-template-columns: auto minmax(min-content, 1.25fr) minmax(0, 1fr); align-items: center; column-gap: 14px;
  padding: 14px 12px 14px 18px; border-radius: 20px;
}
.xp-door-idea {
  background: linear-gradient(120deg, color-mix(in srgb, var(--accent) 4%, var(--panel)), color-mix(in srgb, var(--accent) 10%, var(--panel)));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border));
}
.xp-door-ref {
  background: linear-gradient(120deg, color-mix(in srgb, var(--violet-soft) 45%, var(--panel)), color-mix(in srgb, var(--violet-soft) 90%, var(--panel)));
  border: 1px solid color-mix(in srgb, var(--violet-line) 45%, var(--border));
}
.xp-door-ic {
  align-self: start; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 13px;
  color: var(--accent); background: color-mix(in srgb, var(--accent) 11%, var(--panel));
}
.xp-door-ref .xp-door-ic { color: var(--violet-ink); background: var(--violet-soft); }
.xp-door-words { min-width: 0; }
.xp-door-title {
  margin: 2px 0 0; font-size: clamp(17px, 1.65cqi, 22px); font-weight: 800; line-height: 1.15;
  letter-spacing: -.025em; color: var(--ink); text-wrap: balance;
}
.xp-door-line { margin: 4px 0 0; font-size: 13px; line-height: 1.4; color: var(--muted); }
.xp-door-title, .xp-door-line { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/* The button never wraps: the words' column is at least as wide as it, and the pictures
   beside them take what is left. */
.xp-door-go { margin-top: 10px; min-height: 38px; padding: 0 15px; gap: 7px; font-size: 13.5px; }
.xp-door-go > svg { flex: none; }
.xp-door-ref .xp-ref-go { color: var(--violet-ink); border-color: var(--violet-line); }
.xp-door-ref .xp-ref-go:hover { border-color: var(--violet-ink); background: var(--violet-soft); }
.xp-door-pics, .xp-ref-pics { position: relative; align-self: stretch; min-height: 118px; }
.xp-door-pic, .xp-ref-pic {
  position: absolute; margin: 0; padding: 0; overflow: hidden;
  border: 3px solid var(--panel); border-radius: 12px; background: var(--panel-2);
  box-shadow: 0 16px 30px -18px color-mix(in srgb, var(--ink) 60%, transparent);
}
.xp-door-pic { cursor: pointer; transition: scale .3s cubic-bezier(.2, .7, .2, 1); }
.xp-door-pic > .xp-pic, .xp-ref-pic > .xp-pic { position: absolute; inset: 0; }
/* The perfume in front on the left, the drink behind it on the right: photographs at their
   own 4:5, sized by the column's width. */
.xp-door-pic:nth-child(1) { left: 0; top: 50%; translate: 0 -58%; z-index: 2; width: 66%; aspect-ratio: 4 / 5; rotate: -5deg; }
.xp-door-pic:nth-child(2) { right: -2%; top: 50%; translate: 0 -34%; z-index: 1; width: 60%; aspect-ratio: 4 / 5; rotate: 6deg; }
.xp-door-pics[data-n='1'] > .xp-door-pic { left: 14%; width: 72%; translate: 0 -50%; rotate: 3deg; }
.xp-door-pic:hover { z-index: 3; scale: 1.04; }
.xp-door-pic:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* The picture somebody brings, small at the top, the arrow bending down from it, and
   where it leads, larger at the bottom and in front. */
.xp-ref-pic:first-child { left: 0; top: 50%; translate: 0 -78%; z-index: 1; width: 54%; aspect-ratio: 4 / 5; rotate: -4deg; }
.xp-ref-pic:last-child { right: -2%; top: 50%; translate: 0 -22%; z-index: 2; width: 62%; aspect-ratio: 4 / 5; rotate: 3deg; }
.xp-ref-pic:only-child { left: 14%; right: auto; width: 72%; translate: 0 -50%; }
.xp-ref-arrow { position: absolute; right: 6%; top: 50%; translate: 0 -150%; z-index: 3; color: var(--ink-2); }
/* Anywhere but beside the stage, the same card as a band across the page. */
.xp-ref > .xp-door { grid-template-columns: auto minmax(0, 1fr) 220px; padding: 18px 20px; }

/* ---------- the chips ----------
   Sticky at the top of the screen's own scroll, over a frosted ground, and a strip
   that scrolls sideways with its edges fading where there is more. */
.xp-sentinel { height: 0; }
.xp-chips {
  position: sticky; top: 0; z-index: 6; margin: 0 0 26px; padding: 10px 0;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  -webkit-backdrop-filter: saturate(1.5) blur(16px); backdrop-filter: saturate(1.5) blur(16px);
  border-bottom: 1px solid transparent; transition: border-color .2s, box-shadow .2s;
}
.xp-chips.xp-stuck { border-bottom-color: var(--border); box-shadow: 0 14px 26px -22px color-mix(in srgb, var(--ink) 55%, transparent); }
.xp-chips-track { display: flex; gap: 6px; padding: 3px; overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain; }
.xp-chips-track::-webkit-scrollbar { display: none; }
.xp-chips.xp-overflows .xp-chips-track,
.xp-rail-wrap.xp-overflows .xp-rail {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, black 36px, black calc(100% - 36px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, black 36px, black calc(100% - 36px), transparent 100%);
}
.xp-chips.xp-overflows.xp-at-start .xp-chips-track,
.xp-rail-wrap.xp-overflows.xp-at-start .xp-rail {
  -webkit-mask-image: linear-gradient(90deg, black calc(100% - 36px), transparent 100%);
  mask-image: linear-gradient(90deg, black calc(100% - 36px), transparent 100%);
}
.xp-chips.xp-overflows.xp-at-end .xp-chips-track,
.xp-rail-wrap.xp-overflows.xp-at-end .xp-rail {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, black 36px);
  mask-image: linear-gradient(90deg, transparent 0, black 36px);
}
/* Sized as the mockup has them: the whole catalogue in one row on a wide screen, the
   last one just reaching the edge. */
.xp-chip {
  flex: none; display: inline-flex; align-items: center; gap: 6px; min-height: 35px; padding: 0 12px; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 700; letter-spacing: -.005em; white-space: nowrap; color: var(--ink);
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  transition: background .16s, border-color .16s, color .16s, box-shadow .16s;
}
.xp-chip > svg { flex: none; width: 14px; height: 14px; color: var(--k, var(--muted)); }
.xp-chip:hover { border-color: var(--accent-line); box-shadow: var(--shadow-1); }
.xp-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.xp-chip.on { color: var(--on-solid); background: var(--solid); border-color: var(--solid); box-shadow: var(--shadow-1); }
.xp-chip.on > svg { color: currentColor; }
.xp-chip-n {
  display: inline-grid; place-items: center; min-width: 21px; height: 21px; padding: 0 6px; border-radius: 999px;
  font-size: 11.5px; font-weight: 800; color: var(--on-accent); background: var(--accent);
}

/* ---------- a section, its title and its line ---------- */
.xp-body { min-height: 60vh; }
.xp-sec { margin: 0 0 clamp(40px, 5.2cqi, 64px); }
.xp-sec.xp-stage { margin-bottom: 18px; }
.xp-sec-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 10px 24px; margin: 0 0 18px; }
.xp-sec-words { min-width: 0; }
.xp-h3 { margin: 0; font-size: 18px; font-weight: 800; letter-spacing: -.025em; color: var(--ink); }
.xp-count { font-family: var(--mono); font-size: 11.5px; color: var(--muted); white-space: nowrap; }

/* ---------- the pictures, and the frame under each of them ---------- */
.xp-pic {
  display: grid; place-items: center; overflow: hidden;
  background:
    radial-gradient(120% 90% at calc(14% + var(--xp-v, 0) * 17%) calc(6% + var(--xp-v, 0) * 7%), color-mix(in srgb, var(--k, var(--accent)) 24%, transparent), transparent 62%),
    radial-gradient(color-mix(in srgb, var(--k, var(--accent)) 20%, transparent) 1px, transparent 1.6px) 0 0 / 15px 15px,
    color-mix(in srgb, var(--k, var(--accent)) 14%, var(--panel-2));
}
.xp-pic > img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .55s ease, scale .7s cubic-bezier(.2, .7, .2, 1);
}
.xp-pic.xp-pic-in > img { opacity: 1; }
.xp-frame-mark {
  display: grid; place-items: center; width: 40%; max-width: 116px; aspect-ratio: 1; border-radius: 50%;
  color: var(--k, var(--accent)); background: color-mix(in srgb, var(--k, var(--accent)) 14%, var(--panel));
  box-shadow:
    0 0 0 10px color-mix(in srgb, var(--k, var(--accent)) 9%, transparent),
    0 0 0 22px color-mix(in srgb, var(--k, var(--accent)) 5%, transparent);
}
.xp-frame-mark > svg { width: 42%; height: 42%; }
.xp-goal-media > .xp-pic, .xp-cat-media > .xp-pic { position: absolute; inset: 0; }
/* The panel allows ninety characters of title and two hundred and forty of line, and a
   tile has a height: what does not fit is clamped rather than pushed out of it. */
.xp-goal-title, .xp-cat-title { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.xp-goal-line { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.xp-card-title, .xp-step-title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* ---------- the cards ---------- */
.xp-card { position: relative; min-width: 0; cursor: pointer; }
.xp-idea, .xp-job {
  display: flex; flex-direction: column; padding: 8px; color: var(--ink);
  background: var(--panel); border: 1px solid var(--border); border-radius: 20px; box-shadow: var(--shadow-1);
  transform: perspective(900px) rotateX(var(--xp-rx, 0deg)) rotateY(var(--xp-ry, 0deg));
  transition: transform .55s cubic-bezier(.2, .7, .2, 1), translate .35s cubic-bezier(.2, .7, .2, 1), box-shadow .35s, border-color .25s;
}
.xp-idea:hover, .xp-job:hover { translate: 0 -4px; border-color: var(--accent-line); box-shadow: var(--shadow-2); }
.xp-card.xp-tilting { transition: transform .1s linear, translate .35s cubic-bezier(.2, .7, .2, 1), box-shadow .35s, border-color .25s; }
.xp-media {
  position: relative; overflow: hidden; isolation: isolate; aspect-ratio: 4 / 5; border-radius: 14px; background: var(--panel-2);
  /* Its own width is what decides whether a badge's words fit beside the bookmark. */
  container: xpm / inline-size;
}
.xp-media > .xp-pic { position: absolute; inset: 0; z-index: 0; }
.xp-idea:hover .xp-pic > img, .xp-job:hover .xp-pic > img, .xp-spot:hover .xp-pic > img { scale: 1.06; }
.xp-hover-video, .xp-reel-video {
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity .45s ease; pointer-events: none;
}
.xp-hover-video.xp-on, .xp-reel-video.xp-on { opacity: 1; }
.xp-glare {
  position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: 0; transition: opacity .3s;
  background: radial-gradient(circle at var(--xp-gx, 50%) var(--xp-gy, 30%), color-mix(in srgb, var(--on-scrim) 38%, transparent), transparent 58%);
  mix-blend-mode: soft-light;
}
.xp-card.xp-tilting .xp-glare { opacity: 1; }
.xp-badge {
  position: absolute; z-index: 3; top: 10px; left: 10px; display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 10px; border-radius: 999px; font-size: 11.5px; font-weight: 700; line-height: 1; white-space: nowrap;
}
.xp-badge { max-width: calc(100% - 64px); }
.xp-badge-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.xp-badge-new { color: var(--accent-ink); background: var(--panel); box-shadow: var(--shadow-1); }
.xp-badge-pick { color: var(--on-accent); background: var(--accent); }
.xp-badge-pick svg { fill: currentColor; }
/* The bookmark: glass on the picture, the accent once it is saved. 36px drawn and a
   pseudo-element taking the target past 44, so a thumb finds it. */
.xp-save {
  position: absolute; z-index: 3; top: 8px; right: 8px; display: grid; place-items: center;
  width: 36px; height: 36px; padding: 0; cursor: pointer; color: var(--on-scrim);
  background: color-mix(in srgb, var(--scrim) 40%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-scrim) 30%, transparent); border-radius: 50%;
  -webkit-backdrop-filter: blur(10px) saturate(1.4); backdrop-filter: blur(10px) saturate(1.4);
  transition: background .18s, border-color .18s, color .18s, scale .18s;
}
.xp-save::after { content: ''; position: absolute; inset: -5px; border-radius: 50%; }
.xp-save:hover { background: color-mix(in srgb, var(--scrim) 64%, transparent); scale: 1.06; }
.xp-save[aria-pressed="true"] { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.xp-save[aria-pressed="true"] .xp-bm { fill: currentColor; }
.xp-save:focus-visible { outline: 2px solid var(--on-scrim); outline-offset: 2px; box-shadow: 0 0 0 5px var(--accent); }
.xp-dur {
  position: absolute; z-index: 3; left: 10px; bottom: 10px; display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 9px; border-radius: 999px; font-size: 12px; font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--on-scrim); background: color-mix(in srgb, var(--scrim) 72%, transparent);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.xp-card-body { display: flex; flex: 1; flex-direction: column; gap: 4px; min-width: 0; padding: 12px 6px 4px; }
.xp-card-title { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.3; letter-spacing: -.02em; color: var(--ink); }
.xp-card-go {
  display: inline; margin: 0; padding: 0; cursor: pointer; text-align: left;
  font: inherit; letter-spacing: inherit; color: inherit; background: none; border: 0;
}
.xp-card-go:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
/* The whole card is what the ring is drawn round, where the browser can say so. */
@supports selector(:has(*)) {
  .xp-card-go:focus-visible { outline: none; }
  .xp-card:has(.xp-card-go:focus-visible),
  .xp-card:has(.xp-pill:focus-visible),
  .xp-goal:has(.xp-goal-go:focus-visible) { outline: 3px solid var(--accent); outline-offset: 3px; }
}
.xp-card-line {
  margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.xp-card-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 8px; margin-top: auto; padding-top: 10px; }
.cat-card-from { font-family: var(--mono); font-size: 10.5px; color: var(--muted); }
.xp-tag {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; padding: 4px 9px 4px 8px;
  border-radius: 999px; font-family: var(--mono); font-size: 11px; color: var(--ink-2); background: var(--panel-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.xp-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--k, var(--accent)); }
.xp-go-ink { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 700; color: var(--accent-ink); white-space: nowrap; }
.xp-go-dot {
  display: grid; place-items: center; flex: none; width: 30px; height: 30px; border-radius: 50%;
  color: var(--ink-2); background: var(--panel-2); transition: background .2s, color .2s;
}
.xp-job:hover .xp-go-dot { color: var(--on-accent); background: var(--accent); }

/* «Director's pick» does not fit beside a bookmark on a narrow card — a phone's grid, a
   rail on a small screen: the star stays, and the words stay for whoever hears the card
   rather than sees it. */
@container xpm (max-width: 176px) {
  .xp-badge-pick { padding: 5px 7px; }
  .xp-badge-pick .xp-badge-text {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}

/* ---------- the grids ---------- */
.xp-grid { display: grid; gap: 16px; }
.xp-grid-ideas { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.xp-grid-jobs { grid-template-columns: repeat(auto-fill, minmax(min(200px, calc(50% - 8px)), 1fr)); }
.xp-grid-spot { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.xp-grid-reels { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ---------- just arrived ---------- */
.xp-spot { display: flex; flex-direction: column; }
.xp-spot-media { aspect-ratio: 16 / 10; border-radius: 20px; box-shadow: var(--shadow-1); transition: translate .35s cubic-bezier(.2, .7, .2, 1), box-shadow .35s; }
.xp-spot:hover .xp-spot-media { translate: 0 -4px; box-shadow: var(--shadow-2); }
.xp-spot .xp-card-body { padding: 14px 2px 0; gap: 6px; }
.xp-spot-title { font-size: 17.5px; }
.xp-spot .xp-card-line { -webkit-line-clamp: 3; margin-bottom: 8px; font-size: 13.5px; }
.xp-spot .xp-pill { margin-top: auto; }
.xp-pill {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; min-height: 40px; padding: 0 17px; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 700; color: var(--accent-ink); background: var(--panel);
  border: 1.5px solid var(--accent-line); border-radius: 999px; transition: background .18s, border-color .18s;
}
.xp-spot:hover .xp-pill, .xp-pill:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--panel)); }
.xp-pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- before and after, on a band dark in both themes ---------- */
.xp-cmp {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: center; gap: clamp(22px, 4cqi, 52px);
  padding: clamp(22px, 3.6cqi, 44px); border-radius: 30px; overflow: hidden; color: var(--on-code-block);
  background:
    radial-gradient(70% 95% at 0% 0%, color-mix(in srgb, var(--accent) 28%, transparent), transparent 62%),
    radial-gradient(60% 80% at 100% 100%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 66%),
    var(--code-block);
}
.xp-cmp-title { margin: 0; font-size: clamp(28px, 3.5cqi, 46px); font-weight: 800; line-height: 1.04; letter-spacing: -.045em; color: var(--on-code-block); text-wrap: balance; }
.xp-cmp-sub { margin: 14px 0 24px; font-size: 16px; line-height: 1.5; color: color-mix(in srgb, var(--on-code-block) 80%, transparent); }
.xp-compare {
  --xp-at: 50%;
  position: relative; overflow: hidden; isolation: isolate; aspect-ratio: 16 / 10; border-radius: 22px;
  cursor: ew-resize; touch-action: pan-y; user-select: none; -webkit-user-select: none; box-shadow: var(--shadow-3);
}
.xp-compare > .xp-pic { position: absolute; inset: 0; }
.xp-cmp-before { position: absolute; inset: 0; z-index: 1; clip-path: inset(0 calc(100% - var(--xp-at)) 0 0); }
.xp-cmp-before > .xp-pic { position: absolute; inset: 0; }
.xp-cmp-tag {
  position: absolute; z-index: 3; top: 14px; padding: 6px 12px; border-radius: 999px; pointer-events: none;
  font-size: 12px; font-weight: 700; line-height: 1;
}
.xp-cmp-tag-before {
  left: 14px; color: var(--on-scrim); background: color-mix(in srgb, var(--scrim) 62%, transparent);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.xp-cmp-tag-after { right: 14px; color: var(--on-accent); background: var(--accent); }
.xp-cmp-handle {
  position: absolute; z-index: 4; top: 0; bottom: 0; left: var(--xp-at); width: 48px; margin-left: -24px;
  display: grid; place-items: center; outline: none; cursor: ew-resize;
}
.xp-cmp-handle::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 50%; width: 2px; margin-left: -1px;
  background: var(--on-scrim); box-shadow: 0 0 14px color-mix(in srgb, var(--scrim) 80%, transparent);
}
.xp-cmp-knob {
  position: relative; display: flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 50%;
  color: var(--scrim-strong); background: var(--on-scrim);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--scrim) 70%, transparent); transition: scale .2s;
}
.xp-cmp-knob > svg { margin: 0 -3px; }
.xp-compare:hover .xp-cmp-knob, .xp-compare.xp-dragging .xp-cmp-knob { scale: 1.08; }
.xp-cmp-handle:focus-visible .xp-cmp-knob { outline: 3px solid var(--accent); outline-offset: 3px; }

/* ---------- reels ---------- */
.xp-reel { display: flex; flex-direction: column; }
.xp-reel-media { aspect-ratio: 9 / 16; border-radius: 22px; box-shadow: var(--shadow-1); transition: translate .35s cubic-bezier(.2, .7, .2, 1), box-shadow .35s; }
.xp-reel:hover .xp-reel-media { translate: 0 -4px; box-shadow: var(--shadow-2); }
.xp-reel-shade {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; height: 38%; pointer-events: none;
  background: linear-gradient(to top, color-mix(in srgb, var(--scrim) 78%, transparent), transparent);
}
.xp-reel .xp-dur { left: 12px; bottom: 12px; }
.xp-reel .xp-card-body { padding: 12px 2px 0; }
.xp-reel .xp-card-line { -webkit-line-clamp: 3; }
.xp-reel .xp-go-ink { margin-top: auto; padding-top: 8px; }

/* ---------- goals: a bento of collections ---------- */
.xp-bento { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.xp-goal {
  --xp-tone: color-mix(in srgb, var(--k, var(--accent)) 38%, var(--scrim-strong));
  position: relative; overflow: hidden; isolation: isolate; min-height: 210px; cursor: pointer;
  border-radius: 24px; background: var(--code-block); box-shadow: var(--shadow-1);
  transition: translate .35s cubic-bezier(.2, .7, .2, 1), box-shadow .35s;
}
.xp-goal:hover { translate: 0 -3px; box-shadow: var(--shadow-2); }
.xp-goal-media { position: absolute; inset: 0; z-index: -2; }
.xp-goal-media .xp-pic > img { transition: opacity .55s ease, scale 1s cubic-bezier(.2, .7, .2, 1); }
.xp-goal:hover .xp-goal-media .xp-pic > img { scale: 1.07; }
/* A wash of the category's own colour from the left, dark enough under the words for
   `--on-scrim` to hold on every one of the six kinds in both themes. Measured against a
   white photograph under it, the worst case: 6.9:1 where the wash is whole (music and
   voice in the dark theme; amber light is 10.2:1, violet 12:1), and still 6.2:1 at the
   end of the longest line, where it has started to fade. */
.xp-goal-shade {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(90deg, var(--xp-tone) 0%, var(--xp-tone) 44%, color-mix(in srgb, var(--xp-tone) 72%, transparent) 64%, transparent 92%);
}
.xp-goal-body {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 6px;
  min-height: 210px; max-width: 56%; padding: 24px 26px; color: var(--on-scrim);
  text-shadow: 0 1px 14px color-mix(in srgb, var(--scrim-strong) 60%, transparent);
}
.xp-goal-title { margin: 0; font-size: clamp(20px, 2cqi, 25px); font-weight: 800; line-height: 1.12; letter-spacing: -.03em; color: var(--on-scrim); }
.xp-goal-line { margin: 0; font-size: 14px; line-height: 1.45; color: color-mix(in srgb, var(--on-scrim) 88%, transparent); }
.xp-goal-go {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; padding: 0; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 700; color: var(--on-scrim); background: none; border: 0;
}
.xp-goal-go:focus-visible { outline: 2px solid var(--on-scrim); outline-offset: 3px; border-radius: 6px; }

/* ---------- the catalogue, one rail per category ---------- */
.xp-rails, .xp-groups { display: grid; grid-template-columns: minmax(0, 1fr); gap: 30px; }
.xp-rail-block, .xp-group { min-width: 0; }
.xp-rail-head, .xp-group-head { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; }
.xp-mark {
  flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 12px;
  color: var(--k, var(--accent)); background: color-mix(in srgb, var(--k, var(--accent)) 13%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--k, var(--accent)) 22%, transparent);
}
.xp-rail-name, .xp-group-name { margin: 0; font-size: 17.5px; font-weight: 800; letter-spacing: -.025em; color: var(--ink); }
.xp-rail-head .xp-more, .xp-group-head .xp-more { margin-left: auto; }
.xp-rail-wrap { position: relative; }
.xp-rail {
  display: grid; grid-auto-flow: column; gap: 14px;
  /* As many as fit in a row up to five, each as wide as an even share of the row — and
     never narrower than a card can be read at, which is when the rail starts to scroll. */
  grid-auto-columns: clamp(156px, calc((100% - (var(--xp-n, 5) - 1) * 14px) / var(--xp-n, 5)), 244px);
  padding: 6px 4px 14px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding: 0 4px;
  scrollbar-width: none; overscroll-behavior-x: contain;
}
.xp-rail::-webkit-scrollbar { display: none; }
.xp-rail > * { scroll-snap-align: start; }
.xp-rail-arrow {
  position: absolute; z-index: 5; top: calc(42% - 22px); display: grid; place-items: center; width: 44px; height: 44px; padding: 0;
  cursor: pointer; color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 50%;
  box-shadow: var(--shadow-2); opacity: 0; transition: opacity .2s, scale .2s;
}
.xp-rail-prev { left: -4px; }
.xp-rail-next { right: -4px; }
/* On a phone the four pixels the arrows overhang by are outside the page's content box, and its
   clip cuts them off (the smoke measures it at 375px): there they sit on the rail's edge. */
@media (max-width: 480px) { .xp-rail-prev { left: 0; } .xp-rail-next { right: 0; } }
.xp-rail-wrap.xp-overflows:hover .xp-rail-arrow, .xp-rail-arrow:focus-visible { opacity: 1; }
.xp-rail-arrow:hover { scale: 1.06; }
.xp-rail-arrow:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.xp-rail-arrow:disabled { opacity: 0 !important; pointer-events: none; }

/* ---------- the steps ---------- */
.xp-steps-list { display: grid; grid-template-columns: repeat(var(--xp-n, 3), minmax(0, 1fr)); gap: 30px; margin: 0; padding: 0; list-style: none; }
.xp-step {
  position: relative; display: flex; align-items: center; gap: 16px; min-width: 0; padding: 16px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 22px; box-shadow: var(--shadow-1);
}
/* The dashed line that joins one step to the next, across the gap between them. */
.xp-step:not(:last-child)::after {
  content: ''; position: absolute; top: 50%; left: calc(100% + 4px); width: 22px; border-top: 2px dashed var(--accent-line);
}
.xp-step-pic { position: relative; flex: none; width: 88px; height: 88px; overflow: hidden; border-radius: 16px; }
.xp-step-pic > .xp-pic { position: absolute; inset: 0; }
.xp-step-text { min-width: 0; }
.xp-step-n {
  display: inline-grid; place-items: center; width: 26px; height: 26px; margin-bottom: 7px; border-radius: 50%;
  font-size: 13px; font-weight: 800; color: var(--on-accent); background: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft);
}
.xp-step-title { margin: 0 0 4px; font-size: 15.5px; font-weight: 700; letter-spacing: -.015em; color: var(--ink); }
.xp-step-line { margin: 0; font-size: 13px; line-height: 1.45; color: var(--muted); }

/* ---------- the closing invitation ---------- */
.xp-cta {
  position: relative; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); align-items: center; gap: 24px;
  min-height: 320px; padding: clamp(28px, 4.2cqi, 56px); border-radius: 32px; overflow: hidden;
  background:
    radial-gradient(90% 120% at 0% 0%, color-mix(in srgb, var(--accent) 15%, var(--panel)) 0%, transparent 62%),
    radial-gradient(80% 110% at 100% 100%, color-mix(in srgb, var(--accent) 20%, var(--panel)) 0%, transparent 66%),
    color-mix(in srgb, var(--accent) 4%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--accent) 20%, var(--border));
}
.xp-cta-title { margin: 0; font-size: clamp(28px, 3.4cqi, 46px); font-weight: 800; line-height: 1.04; letter-spacing: -.045em; color: var(--ink); text-wrap: balance; }
.xp-cta-sub { margin: 12px 0 26px; max-width: 440px; font-size: 16px; line-height: 1.5; color: var(--muted); }
.xp-cta-acts { display: flex; flex-wrap: wrap; gap: 12px; }
.xp-cta-acts .xp-btn-outline svg { color: var(--accent-ink); }
.xp-collage { position: relative; height: 290px; }
.xp-float {
  position: absolute; margin: 0; width: 44%; aspect-ratio: 4 / 5; overflow: hidden; rotate: var(--xp-rot, 0deg);
  border: 5px solid var(--panel); border-radius: 20px; box-shadow: var(--shadow-2);
}
.xp-float > .xp-pic { position: absolute; inset: 0; }
.xp-float:nth-of-type(1) { left: 2%; top: 8%; --xp-rot: -8deg; }
.xp-float:nth-of-type(2) { right: 4%; top: -2%; width: 40%; --xp-rot: 7deg; }
.xp-float:nth-of-type(3) { left: 26%; bottom: -8%; width: 36%; --xp-rot: 4deg; z-index: 2; }
.xp-float:nth-of-type(4) { right: -2%; bottom: 2%; width: 34%; --xp-rot: -6deg; }
.xp-collage-badge {
  position: absolute; z-index: 3; left: 50%; top: 48%; translate: -50% -50%; display: grid; place-items: center;
  width: 56px; height: 56px; border-radius: 50%; color: var(--ink); background: var(--panel); box-shadow: var(--shadow-2);
}
@keyframes xp-float { from { translate: 0 0; } to { translate: 0 var(--xp-fy, -9px); } }

/* ---------- the foot of the page ---------- */
.xp-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px;
  margin: 8px 0 0; padding: 22px 2px 6px; border-top: 1px solid var(--border);
}
.xp-foot-mark { display: inline-flex; align-items: center; min-height: 36px; }
/* Ours is white artwork, so on a ground that can be pale it carries its own plate, as
   on every other pale surface in the studio. Three classes deep, because the column's
   rules hide the lockup when it folds and on a phone, and those are about the column. */
.xp-foot-ours { padding: 7px 13px; border-radius: 12px; background: var(--code-block); }
.xp-foot .xp-foot-ours .brand-ours-full { display: block; width: auto; height: 22px; }
.xp-foot .xp-foot-ours .brand-ours-icon { display: none; }
.xp-foot-logo { display: block; max-width: 170px; max-height: 30px; object-fit: contain; }
.xp-foot-word { font-size: 20px; font-weight: 800; letter-spacing: -.03em; color: var(--ink); }
.xp-foot-links { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 22px; }
.xp-foot-link { font-size: 13.5px; font-weight: 600; color: var(--muted); text-decoration: none; }
.xp-foot-link:hover { color: var(--ink); text-decoration: underline; }
.xp-foot-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.xp-foot-top {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 0; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 700; color: var(--accent-ink); background: none; border: 0;
}

/* ---------- the states under the chips ---------- */
.xp-state-head { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; margin: 0 0 20px; }
.xp-state-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; }
.xp-back {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px 7px 10px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--ink-2);
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
}
.xp-back:hover { border-color: var(--accent-line); }
.xp-sub-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; margin: 34px 0 14px; }
.xp-state-head + .xp-sub-head { margin-top: 0; }
.xp-group-head { padding-bottom: 12px; border-bottom: 1px solid var(--border); }
/* One category: its photograph under a scrim, or its colour and its mark. */
.xp-cat-hero {
  position: relative; display: flex; align-items: flex-end; min-height: 230px; margin: 0 0 24px;
  overflow: hidden; isolation: isolate; border-radius: 28px; background: var(--code-block); box-shadow: var(--shadow-1);
}
.xp-cat-media { position: absolute; inset: 0; z-index: -2; }
.xp-cat-media .xp-pic { justify-items: end; padding-right: 9%; }
.xp-cat-shade {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(90deg, var(--scrim-strong) 0%, color-mix(in srgb, var(--scrim) 74%, transparent) 46%, transparent 86%),
    linear-gradient(to top, color-mix(in srgb, var(--scrim) 55%, transparent), transparent 62%);
}
.xp-cat-body { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; max-width: 760px; padding: 26px 30px 28px; color: var(--on-scrim); }
.xp-mark-lg {
  width: 56px; height: 56px; border-radius: 18px; color: var(--on-scrim);
  background: color-mix(in srgb, var(--on-scrim) 16%, transparent); border-color: color-mix(in srgb, var(--on-scrim) 26%, transparent);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.xp-cat-words { min-width: 0; }
.xp-cat-title { margin: 0; font-size: clamp(27px, 3.2cqi, 40px); font-weight: 800; line-height: 1.05; letter-spacing: -.04em; color: var(--on-scrim); }
.xp-cat-line { margin: 8px 0 12px; font-size: 15px; line-height: 1.5; color: color-mix(in srgb, var(--on-scrim) 88%, transparent); }
.xp-cat-count {
  display: inline-flex; padding: 5px 11px; border-radius: 999px; font-family: var(--mono); font-size: 11.5px;
  color: var(--on-scrim); background: color-mix(in srgb, var(--on-scrim) 16%, transparent);
}
/* An empty answer says what happened and offers the way on, across the whole row. */
.xp-empty {
  grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 46px 22px;
  text-align: center; background: var(--panel); border: 1.5px dashed var(--border); border-radius: 24px;
}
.xp-empty-ic { display: grid; place-items: center; width: 58px; height: 58px; margin-bottom: 6px; border-radius: 18px; color: var(--accent-ink); background: var(--accent-soft); }
.xp-empty-title { margin: 0; font-size: 17.5px; font-weight: 700; color: var(--ink); }
.xp-empty-line { margin: 0 0 10px; max-width: 470px; font-size: 14px; line-height: 1.5; color: var(--muted); }

/* ---------- the demo, in a window of its own ---------- */
.xp-lb {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: clamp(16px, 4vw, 56px);
  background: var(--overlay); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.xp-lb-card { display: grid; gap: 12px; width: min(1100px, 100%); }
.xp-lb-video { display: block; width: 100%; max-height: calc(100vh - 150px); border-radius: 20px; background: var(--scrim-strong); box-shadow: var(--shadow-3); }
.xp-lb-title { margin: 0; font-size: 15px; font-weight: 600; text-align: center; color: var(--on-scrim); }
.xp-lb-x {
  position: absolute; top: 16px; right: 16px; display: grid; place-items: center; width: 46px; height: 46px; padding: 0; cursor: pointer;
  color: var(--on-scrim); background: color-mix(in srgb, var(--scrim) 60%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-scrim) 30%, transparent); border-radius: 50%;
}
.xp-lb-x:focus-visible { outline: 2px solid var(--on-scrim); outline-offset: 2px; }

/* ---------- a recipe's sheet: its example beside what it makes and how ---------- */
.xp-rs-card {
  position: relative; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); width: min(980px, 100%);
  max-height: calc(100vh - 48px); overflow: hidden; border-radius: 24px; color: var(--ink); background: var(--panel);
  box-shadow: var(--shadow-3);
}
.xp-rs-media { position: relative; min-height: 300px; background: var(--panel-2); }
.xp-rs-media > .xp-pic, .xp-rs-video { position: absolute; inset: 0; width: 100%; height: 100%; }
.xp-rs-media > .xp-pic > img { width: 100%; height: 100%; object-fit: cover; }
.xp-rs-video { object-fit: cover; opacity: 0; transition: opacity .3s; }
.xp-rs-video.xp-on { opacity: 1; }
.xp-rs-words { display: flex; flex-direction: column; gap: 10px; min-width: 0; padding: 30px 30px 26px; overflow-y: auto; }
.xp-rs-cat {
  align-self: flex-start; padding: 4px 10px; border-radius: 999px;
  font-family: var(--mono); font-size: 11px; color: var(--ink-2); background: var(--panel-2);
}
.xp-rs-title { margin: 0; font-size: 26px; font-weight: 700; line-height: 1.15; letter-spacing: -.02em; }
.xp-rs-line { margin: 0; font-size: 14.5px; line-height: 1.5; color: var(--muted); }
.xp-rs-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 6px 0 0; }
.xp-rs-fact { min-width: 0; padding: 10px 12px; border-radius: 14px; background: var(--panel-2); }
.xp-rs-fact dt { font-family: var(--mono); font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.xp-rs-fact dd { margin: 3px 0 0; font-size: 13.5px; font-weight: 600; overflow-wrap: anywhere; }
.xp-rs-h3 { margin: 10px 0 0; font-size: 14px; font-weight: 700; }
.xp-rs-steps { display: grid; gap: 6px; margin: 0; padding: 0; list-style: none; counter-reset: xp-rs; }
.xp-rs-step { display: flex; align-items: center; gap: 10px; min-height: 26px; font-size: 13.5px; counter-increment: xp-rs; }
.xp-rs-step::before {
  content: counter(xp-rs); display: grid; place-items: center; flex: none; width: 24px; height: 24px; border-radius: 50%;
  font-family: var(--mono); font-size: 11px; color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}
.xp-rs-opt { font-family: var(--mono); font-size: 10.5px; color: var(--muted); }
.xp-rs-note { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.xp-rs-start { align-self: flex-start; margin-top: 8px; }
@media (max-width: 760px) {
  .xp-rs-card { grid-template-columns: minmax(0, 1fr); grid-template-rows: 200px minmax(0, 1fr); }
  .xp-rs-media { min-height: 0; }
  .xp-rs-words { padding: 22px 20px 20px; }
  .xp-rs-title { font-size: 22px; }
}

/* ---------- what moves, and only when movement is welcome ---------- */
@keyframes xp-rise { from { opacity: 0; translate: 0 22px; } }
@keyframes xp-drift { from { scale: 1.03; translate: 0 0; } to { scale: 1.12; translate: -2% -1.5%; } }
@keyframes xp-fade { from { opacity: 0; } }
@media (prefers-reduced-motion: no-preference) {
  .xp-rv:not(.xp-in) { opacity: 0; }
  .xp-rv.xp-in { animation: xp-rise .75s cubic-bezier(.2, .7, .2, 1) var(--xp-d, 0ms) backwards; }
  .xp-reel .xp-pic > img, .xp-cat-media .xp-pic > img { animation: xp-drift 18s ease-in-out infinite alternate; }
  .xp-float { animation: xp-float var(--xp-fd, 7s) ease-in-out var(--xp-fdl, 0s) infinite alternate; }
  .xp-lb { animation: xp-fade .2s ease-out; }
}
@media (prefers-reduced-motion: reduce) {
  .xp-fan-card, .xp-door-pic, button.xp-fan-play { transition: none; }
  .xp-fan-card:hover { --lift: 0px; }
  .xp-door-pic:hover { scale: none; }
  button.xp-fan-play:hover { scale: none; }
  .xp-idea, .xp-job, .xp-spot-media, .xp-reel-media, .xp-goal, .xp-pic > img { transition: none; }
  .xp-idea:hover, .xp-job:hover, .xp-spot:hover .xp-spot-media, .xp-reel:hover .xp-reel-media, .xp-goal:hover { translate: none; }
  .xp-idea:hover .xp-pic > img, .xp-job:hover .xp-pic > img, .xp-spot:hover .xp-pic > img, .xp-goal:hover .xp-goal-media .xp-pic > img { scale: none; }
}
/* A finger has no hover: the rail's arrows are for a mouse, and a thumb swipes. */
@media (hover: none) { .xp-rail-arrow { display: none; } }

/* ---------- narrower screens ---------- */
/* Under about 1150px of window with the column open the column beside the hero is too narrow
   for its words: the hero takes the width and the two cards sit side by side under it. */
@container xp (max-width: 920px) {
  .xp-stage { grid-template-columns: minmax(0, 1fr); }
  .xp-stage-side { grid-column: 1; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: auto; }
}
@container xp (max-width: 860px) {
  .xp-grid-ideas { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Four reels in three columns leave one alone on a row: they become a strip. */
  .xp-grid-reels {
    grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(200px, 36%);
    overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding: 4px 2px 10px;
  }
  .xp-grid-reels::-webkit-scrollbar { display: none; }
  .xp-grid-reels > * { scroll-snap-align: start; }
  .xp-steps-list { gap: 26px; }
  .xp-step { flex-direction: column; align-items: flex-start; }
  .xp-step:not(:last-child)::after { width: 18px; }
}
@container xp (max-width: 700px) {
  .xp-cmp { grid-template-columns: minmax(0, 1fr); }
}
@container xp (max-width: 600px) {
  .xp-head { margin-bottom: 18px; }
  .xp-search { flex: 1 1 100%; }
  /* The words over the fan, and the fan a strip of its own under them. */
  .xp-hero { flex-direction: column; align-items: stretch; min-height: 0; padding: 26px 22px 0; border-radius: 22px; }
  .xp-hero-words { width: auto; }
  .xp-hero-title { font-size: clamp(27px, 8cqi, 34px); }
  .xp-hero-line { font-size: 14.5px; }
  .xp-fan { position: relative; width: auto; height: 270px; margin: 8px -22px 0; }
  .xp-stage-side { grid-template-columns: minmax(0, 1fr); }
  /* One card a row, and in each the pictures under the tile and the words. */
  .xp-door, .xp-ref > .xp-door { grid-template-columns: auto minmax(0, 1fr); }
  .xp-door-pics, .xp-ref-pics { grid-column: 1 / -1; min-height: 150px; margin-top: 12px; }
  .xp-chips { margin-bottom: 20px; }
  .xp-grid { gap: 12px; }
  .xp-grid-ideas { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xp-grid-spot { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .xp-grid-reels { grid-auto-columns: minmax(176px, 46%); }
  .xp-bento { grid-template-columns: minmax(0, 1fr); }
  .xp-goal, .xp-goal-body { min-height: 180px; }
  .xp-goal-body { max-width: 78%; }
  /* The words take more of a narrow tile, so the wash does too. */
  .xp-goal-shade {
    background: linear-gradient(90deg, var(--xp-tone) 0%, var(--xp-tone) 64%, color-mix(in srgb, var(--xp-tone) 70%, transparent) 84%, transparent 100%);
  }
  .xp-steps-list { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .xp-step { flex-direction: row; align-items: center; }
  .xp-step:not(:last-child)::after { top: calc(100% + 3px); left: 59px; width: 0; height: 16px; border-top: 0; border-left: 2px dashed var(--accent-line); }
  .xp-cta { grid-template-columns: minmax(0, 1fr); }
  .xp-collage { height: 200px; }
  .xp-float:nth-of-type(n+3) { display: none; }
  .xp-float:nth-of-type(1) { left: 6%; }
  .xp-float:nth-of-type(2) { right: 10%; }
  .xp-cat-hero { min-height: 200px; }
  .xp-cat-body { padding: 22px; }
  .xp-compare { aspect-ratio: 4 / 3; }
  .xp-foot { flex-direction: column; align-items: flex-start; }
}
@container xp (max-width: 400px) {
  .xp-idea, .xp-job { padding: 6px; border-radius: 16px; }
  .xp-media { border-radius: 11px; }
  .xp-card-body { padding: 10px 4px 2px; }
  .xp-card-title { font-size: 14px; }
  .xp-tag { font-size: 10.5px; }
  .xp-save { top: 6px; right: 6px; width: 32px; height: 32px; }
  .xp-badge { top: 7px; left: 7px; padding: 5px 8px; font-size: 10.5px; }
  .xp-btn { min-height: 44px; padding: 0 18px; font-size: 14px; }
  .xp-chip { min-height: 40px; padding: 0 14px; }
  .xp-cmp, .xp-cta { border-radius: 24px; }
}

/* The way out of an empty catalogue, inside the picker's own empty state. It lived in
   the old catalogue's block and belongs to `picker.js`, which is why it outlived it. */
.pick-empty-go { margin-top: 12px; }

/* ================= BRAND · the shared pieces (.bk-*) =================
   The vocabulary of the owner's seven Brand mockups, written once: the page header
   with its actions, the pink button that is each page's main verb, the search, the
   chips, the card, the «⋯» and its menu, the side panel, the dot, the badge, the
   letter tile. `app/js/brand-ui.js` is the behaviour; this block is the look, and a
   tab's own block only adds what is its alone.

   The pink is `--accent` as a fill with `--on-accent` on it, and `--accent-ink`
   whenever it is text: the magenta as ink is under AA on white, which is what the
   ink variant exists for. No token is added here, because the `:root` block is
   compared byte for byte with the panel's and the partner's sheets. */

/* ---------- the page header: a title, one line, the actions ---------- */
.bk-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px 24px; flex-wrap: wrap; margin: 0 0 22px; }
.bk-head > div:first-child { min-width: 0; }
.bk-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* The brand's name is the tab's title (the owner's word, 2026-10-26), with a pencil beside it that turns it into a
   field in place: the field keeps the title's size, so renaming does not move the page. */
.bk-name-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.bk-name-row .bk-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-title-input {
  min-width: 0; width: min(520px, 100%); margin: 0; padding: 2px 8px; font: inherit; font-weight: 700;
  color: var(--ink); background: var(--panel); border: 1px solid var(--accent); border-radius: 8px;
}
.bk-title-input[hidden] { display: none; }
.bk-title-input:focus { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.bk-name-btn {
  flex: none; display: grid; place-items: center; width: 34px; height: 34px; padding: 0; cursor: pointer;
  color: var(--muted); background: transparent; border: 0; border-radius: 8px;
}
.bk-name-btn:hover { color: var(--ink); background: var(--panel-2); }
.bk-name-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.bk-name-btn[hidden] { display: none; }
/* The trash: a square beside «Save changes», as tall as it, in the danger colour on hover. */
.bk-trash { flex: none; display: grid; place-items: center; width: 42px; padding: 0; }
.bk-trash:hover:not(:disabled) { color: var(--danger); border-color: var(--danger-line); }
.bk-trash:disabled { opacity: .45; cursor: not-allowed; }
.bk-trash[hidden] { display: none; }

/* ---------- the two buttons every header carries, and the link ---------- */
.btn.bk-btn, .btn.bk-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 42px; padding: 0 18px; border-radius: 10px; font-size: 14px; font-weight: 600; white-space: nowrap;
}
.btn.bk-btn { background: var(--panel); border-color: var(--border); color: var(--text); }
.btn.bk-btn:hover { border-color: var(--ink); }
.btn.bk-btn:disabled:hover { background: var(--panel); border-color: var(--border); }
.btn.bk-cta { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.bk-cta:hover { background: var(--accent-hi); border-color: var(--accent-hi); }
.btn.bk-cta:disabled:hover { background: var(--accent); border-color: var(--accent); }
.btn.bk-btn .bk-ic, .btn.bk-cta .bk-ic { flex: none; }
/* A row's size: «✎ Modifica», «+ Salva». */
.btn.bk-btn.small, .btn.bk-cta.small { min-height: 32px; padding: 0 12px; font-size: 13px; border-radius: 8px; }
.btn.bk-wide { width: 100%; }
.bk-link {
  display: inline-flex; align-items: center; gap: 6px; padding: 0; background: none; border: 0; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600; color: var(--accent-ink); text-decoration: none;
}
.bk-link:hover { text-decoration: underline; }
.bk-link:disabled { opacity: .45; cursor: default; text-decoration: none; }
.bk-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* ---------- the card, and the head a card opens with ---------- */
.bk-card { min-width: 0; padding: 22px; background: var(--panel); border: 1px solid var(--border); border-radius: 14px; }
.bk-card + .bk-card { margin-top: 18px; }
.bk-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin: 0 0 18px; }
.bk-card-head > .bk-ic { flex: none; width: 26px; height: 26px; margin-top: 2px; color: var(--ink); }
.bk-card-head > div { flex: 1; min-width: 0; }
.bk-card-title { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.bk-card-sub { margin: 3px 0 0; font-size: 13.5px; color: var(--muted); }

/* ---------- a cell of a grid: a product, a character, a template ---------- */
.bk-item {
  min-width: 0; padding: 12px; background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  transition: border-color .13s, box-shadow .13s;
}
.bk-item:hover { border-color: var(--accent-line); }
.bk-item.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.bk-item-name { margin: 10px 0 0; font-size: 15px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-item-meta { margin: 2px 0 0; font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-media { position: relative; overflow: hidden; aspect-ratio: var(--bk-ratio, 4 / 3); background: var(--panel-2); border-radius: 10px; }
.bk-media > img, .bk-media > video { display: block; width: 100%; height: 100%; object-fit: cover; }
.bk-media > .bk-letter { position: absolute; inset: 0; width: auto; height: auto; border: 0; border-radius: 0; font-size: 34px; }
.bk-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(var(--bk-min, 240px), 100%), 1fr)); }

/* ---------- fields ----------
   Scoped to `.bk-field` and not to the page: a rule on every input of the Brand view
   would reach the checkbox, the colour well and the slider as well. */
.bk-field { display: block; margin: 0 0 16px; font-size: 13.5px; font-weight: 500; color: var(--text); }
.bk-label { display: block; margin: 0 0 7px; }
.bk-field :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"]), select, textarea) {
  margin: 0; padding: 10px 14px; font-size: 14.5px; background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.bk-field :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"]), select) { min-height: 44px; }
/* A field with a glyph in front: the site's link, the search. */
.bk-with-ic { position: relative; display: block; }
.bk-with-ic > .bk-ic { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.bk-with-ic > input { padding-left: 42px !important; }
.bk-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }
.bk-cols > .bk-span { grid-column: 1 / -1; }

/* ---------- the toolbar over a list: search, a select, a button ---------- */
.bk-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 16px; }
.bk-search { position: relative; flex: 1 1 260px; min-width: 0; margin: 0; }
.bk-search > .bk-ic { position: absolute; left: 14px; top: 50%; width: 18px; height: 18px; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.bk-search > input {
  width: 100%; min-height: 44px; margin: 0; padding: 10px 14px 10px 42px; font-size: 14.5px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.bk-select { position: relative; flex: 0 1 auto; min-width: 0; margin: 0; }
.bk-select > select {
  -webkit-appearance: none; appearance: none; width: 100%; min-height: 44px; margin: 0; padding: 10px 40px 10px 14px;
  font-size: 14px; color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 10px; cursor: pointer;
}
.bk-select > .bk-ic { position: absolute; right: 14px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }

/* ---------- chips that filter and count ----------
   Three looks and one behaviour (`bkChips`): pills, the mockup's products; `boxed`,
   squared with the one that is on tinted, the characters; `line`, tabs over a table,
   the memory. */
.bk-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0 0 16px; }
.bk-chip {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 0 14px; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 500; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  transition: border-color .13s, background .13s, color .13s;
}
.bk-chip:hover { border-color: var(--accent-line); }
.bk-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bk-chip-n {
  display: inline-grid; place-items: center; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px;
  font-size: 12px; font-weight: 700; color: var(--muted); background: var(--panel-2);
}
.bk-chip.on { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.bk-chip.on .bk-chip-n { color: var(--accent-ink); background: var(--panel); }
.bk-chips.boxed .bk-chip { min-height: 38px; border-radius: 8px; }
.bk-chips.boxed .bk-chip.on { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent); }
.bk-chips.boxed .bk-chip.on .bk-chip-n { background: var(--panel); }
.bk-chips.line { gap: 4px 24px; margin: 0; border-bottom: 1px solid var(--border); }
.bk-chips.line .bk-chip { min-height: 46px; padding: 0 4px; background: none; border: 0; border-radius: 0; box-shadow: inset 0 -2px 0 transparent; }
.bk-chips.line .bk-chip.on { color: var(--accent-ink); background: none; box-shadow: inset 0 -2px 0 var(--accent); }
.bk-chips.line .bk-chip.on .bk-chip-n { color: var(--accent-ink); background: var(--accent-soft); }

/* ---------- a segmented choice: «Da testo | Da descrizione» ---------- */
.bk-seg { display: inline-flex; gap: 2px; padding: 3px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px; }
.bk-seg.full { display: flex; }
.bk-seg.full > button { flex: 1; }
.bk-seg > button {
  min-height: 34px; padding: 0 14px; cursor: pointer; font: inherit; font-size: 13.5px; font-weight: 600;
  color: var(--muted); background: none; border: 0; border-radius: 8px;
}
.bk-seg > button[aria-pressed="true"] { color: var(--ink); background: var(--panel); box-shadow: var(--shadow-1); }
.bk-seg > button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- a main column and a side panel ----------
   Each side names its own track: `[hidden]` takes an element out of the grid, and with
   auto placement a closed side panel would hand its track to the main column. */
.bk-split { display: grid; grid-template-columns: minmax(0, 1fr) var(--bk-aside, 380px); gap: 18px; align-items: start; }
.bk-split > .bk-main { grid-column: 1; min-width: 0; }
.bk-split > .bk-aside { grid-column: 2; }
.bk-split:has(> .bk-aside[hidden]) { grid-template-columns: minmax(0, 1fr); }
.bk-aside {
  position: sticky; top: var(--bk-sticky, 16px); min-width: 0; padding: 22px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
}
.bk-aside-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 0 0 16px; }
.bk-aside-head > div { min-width: 0; }
.bk-aside-title { margin: 0; font-size: 20px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.bk-aside-sub { margin: 3px 0 0; font-size: 13.5px; color: var(--muted); }
.bk-x {
  display: grid; place-items: center; flex: none; width: 34px; height: 34px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 0; border-radius: 8px;
}
.bk-x:hover { color: var(--ink); background: var(--panel-2); }
.bk-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- the «⋯», its menu, and a popover ---------- */
.bk-more {
  display: grid; place-items: center; flex: none; width: 32px; height: 32px; padding: 0; cursor: pointer;
  color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.bk-more:hover, .bk-more[aria-expanded="true"] { border-color: var(--ink); }
.bk-more:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* On a photo: a square in its corner, as the mockups draw it. */
.bk-media > .bk-more { position: absolute; top: 10px; right: 10px; border-color: transparent; box-shadow: var(--shadow-1); }
.bk-menu, .bk-pop {
  position: fixed; z-index: 1000; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-2);
}
.bk-menu {
  display: flex; flex-direction: column; min-width: 210px; max-width: min(320px, calc(100vw - 16px));
  max-height: min(420px, calc(100vh - 16px)); overflow-y: auto; padding: 6px;
}
.bk-menu button {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px; text-align: left; cursor: pointer;
  font: inherit; font-size: 13.5px; color: var(--text); background: none; border: 0; border-radius: 8px;
}
.bk-menu button:hover:not(:disabled), .bk-menu button:focus-visible { background: var(--panel-2); outline: none; }
.bk-menu button:disabled { opacity: .45; cursor: default; }
.bk-menu button.danger { color: var(--danger); }
.bk-menu button[aria-checked="true"] { font-weight: 600; }
.bk-menu button[aria-checked="true"] > .bk-ic:last-child { color: var(--accent-ink); }
.bk-menu-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bk-menu-sep { height: 1px; margin: 5px 4px; background: var(--border); }
.bk-menu-note { margin: 0; padding: 8px 12px 4px; font-size: 11.5px; color: var(--muted); }
.bk-pop { width: min(360px, calc(100vw - 16px)); max-height: min(520px, calc(100vh - 16px)); overflow-y: auto; padding: 16px; }
.bk-pop:focus { outline: none; }

/* ---------- small marks: a status dot, a badge, a letter tile ---------- */
.bk-dot { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text); }
.bk-dot::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--muted); }
.bk-dot.ok::before { background: var(--ok); }
/* A mark and not ink: the bright amber a dot needs, not the dark `--warn` text needs. */
.bk-dot.warn::before { background: #e08a00; }
.bk-dot.bad::before { background: var(--danger); }
.bk-badge {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; white-space: nowrap;
  font-size: 12.5px; font-weight: 500; color: var(--text); background: var(--panel-2); border: 1px solid var(--border); border-radius: 7px;
}
.bk-badge.accent { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
/* Over a picture: the dark disc a photograph cannot swallow, the same in both themes. */
.bk-badge.scrim { color: var(--on-scrim); background: var(--scrim); border-color: transparent; }
.bk-letter {
  display: grid; place-items: center; flex: none; width: var(--bk-letter, 44px); height: var(--bk-letter, 44px);
  font-size: calc(var(--bk-letter, 44px) * .42); font-weight: 700; color: var(--ink);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
}
.bk-letter.round { border-radius: 50%; }

/* ---------- what fills the gaps: a note, a drop zone, a footer, an empty list ---------- */
.bk-note {
  display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; font-size: 13.5px; color: var(--text);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
}
.bk-note > .bk-ic { flex: none; margin-top: 1px; color: var(--muted); }
.bk-drop {
  display: grid; justify-items: center; gap: 6px; padding: 22px 16px; text-align: center; font-size: 13px; color: var(--muted);
  border: 1.5px dashed var(--border); border-radius: 12px;
}
.bk-drop.over { border-color: var(--accent); background: var(--accent-soft); }
.bk-drop-title { font-size: 14px; font-weight: 600; color: var(--text); }
.bk-foot { margin: 18px 0 0; font-size: 13px; color: var(--muted); }
.bk-empty {
  display: grid; place-items: center; gap: 10px; padding: 36px 20px; text-align: center; font-size: 14px; color: var(--muted);
  border: 1px dashed var(--border); border-radius: 14px;
}
/* What a card lists as facts: a glyph and a label on the left, the value beside it. */
.bk-facts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px 18px; margin: 0; }
.bk-facts dt { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--muted); }
.bk-facts dd { margin: 0; font-size: 14px; color: var(--text); }
/* A link that takes something away: «Remove this colour». The danger's ink, since it
   is text on a card. */
.bk-link.danger { color: var(--danger-ink); }
/* One line of help at the top of a popover. */
.bk-pop-hint { margin: 0 0 10px; font-size: 12.5px; color: var(--muted); }

/* ---------- a breadcrumb: where you are ----------
   Settings' «Account / Settings». Setup had one too, in a bar of its own over its tabs,
   until the owner took the bar away (2026-10-18): it only took room. */
.bk-crumbs { display: flex; align-items: center; gap: 10px; min-width: 0; font-size: 14px; }
.bk-crumb-sep { color: var(--muted); }
.bk-crumb-here { font-weight: 700; color: var(--ink); white-space: nowrap; }
.bk-help-btn {
  display: grid; place-items: center; flex: none; width: 36px; height: 36px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 0; border-radius: 50%;
}
.bk-help-btn:hover, .bk-help-btn[aria-expanded="true"] { color: var(--ink); background: var(--panel-2); }
.bk-help-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* What the «?» opens: a copy of the open panel's `.bk-help`, under a title. Wider than a
   menu, because it is paragraphs; a panel's hint lines keep their own markup, and read
   here at the size of the text around them rather than at a hint's. */
.bk-pop.bk-help-pop { width: min(440px, calc(100vw - 16px)); }
.bk-help-title { margin: 0 0 10px; font-size: 15px; font-weight: 700; color: var(--ink); }
.bk-help-body h3 { margin: 14px 0 6px; font-size: 13px; font-weight: 700; color: var(--ink); }
.bk-help-body h3:first-child { margin-top: 0; }
.bk-help-body p, .bk-help-body .hint { margin: 0 0 8px; font-size: 13.5px; line-height: 1.55; color: var(--text); }
.bk-help-body > :last-child { margin-bottom: 0; }

/* ---------- a dialog of the page's own ----------
   For what takes a moment and must not close on a stray scroll: reading a site. A veil
   over the whole window and a card in the middle; above the frame, under the app's own
   confirmations (`.dlg`), which may have to be answered over it. */
.bk-modal {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: center;
  padding: 20px; background: var(--overlay); backdrop-filter: blur(3px);
}
.bk-modal-card {
  width: min(520px, 100%); max-height: calc(100dvh - 40px); overflow-y: auto; padding: 22px 24px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-3);
}
.bk-modal-foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.bk-modal-card .bk-note { margin: 0 0 4px; }

/* «Improve quality» (app/js/enhance.js): the kind of picture, the size as a row of choices, what it makes,
   and the figure on the button that takes it. Over the image editor too, so above its overlay. */
.bk-modal.enh { z-index: 120; }
.enh-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
.enh-sub { margin: 6px 0 16px; font-size: 14px; color: var(--muted); }
.enh-field { display: block; margin: 0 0 14px; }
.enh-field .bk-label { display: block; margin-bottom: 6px; }
.enh-type { width: 100%; }
.enh-sizes { display: flex; flex-wrap: wrap; gap: 8px; }
.enh-size {
  min-width: 64px; min-height: 40px; padding: 0 14px; border-radius: 10px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--text);
  background: var(--panel); border: 1px solid var(--border);
}
.enh-size:hover:not(:disabled) { border-color: var(--ink); }
.enh-size.on { color: var(--accent-ink); border-color: var(--accent); background: var(--accent-soft); }
.enh-size:disabled { opacity: .45; cursor: not-allowed; }
.enh-size:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* A clip's «Smoother motion»: one box and its words, under the resolutions. */
.enh-smooth { display: flex; align-items: center; gap: 8px; margin: 0 0 14px; font-size: 14px; color: var(--ink); cursor: pointer; }
.enh-smooth-box { width: 16px; height: 16px; margin: 0; accent-color: var(--accent); }
.enh-smooth:has(.enh-smooth-box:disabled) { opacity: .5; cursor: not-allowed; }
.enh-dims { margin: 0 0 6px; font-size: 14px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.enh-dims:empty { display: none; }
.enh-note { margin: 0 0 6px; font-size: 13px; }
.enh-warn { margin: 6px 0 0; font-size: 13px; }
.enh-foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: 10px; margin-top: 18px; }

/* A picture's «Improve quality» is one wide window with three faces (`data-face`): the settings beside the
   original, the job being made, and the result to compare. A head, a body of two columns, a foot; every part a
   face does not use is `hidden`. On a phone the columns stack and the window scrolls. */
.bk-modal-card.enh-wide { width: min(920px, 100%); padding: 0; display: flex; flex-direction: column; }
.enh-head { display: flex; align-items: center; gap: 14px; padding: 18px 20px 16px 24px; border-bottom: 1px solid var(--border); }
.enh-mark { flex: none; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 12px; color: var(--accent-ink); background: var(--accent-soft); }
.enh-wide[data-face="done"] .enh-mark { color: var(--ok); background: var(--ok-soft); border-radius: 50%; }
.enh-words { flex: 1 1 auto; min-width: 0; }
.enh-wide .enh-title { font-size: 19px; }
.enh-wide .enh-sub { margin: 2px 0 0; font-size: 13.5px; }
.enh-by { flex: none; font-size: 12px; color: var(--muted); }
.enh-wide[data-face="done"] .enh-by { display: none; }
.enh-x {
  flex: none; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border-radius: 10px; cursor: pointer;
  color: var(--muted); background: none; border: 1px solid transparent;
}
.enh-x:hover { color: var(--ink); background: var(--panel-2); }
.enh-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.enh-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 340px); gap: 24px; padding: 20px 24px; }
/* The left column, on every face: the picture in a box of its own, drawn whole and never stretched. */
.enh-side { grid-column: 1; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.enh-pane { grid-column: 2; min-width: 0; }
.enh-file { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 14px; font-weight: 600; color: var(--ink); }
.enh-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.enh-format { flex: none; padding: 2px 7px; border-radius: 6px; font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--muted); background: var(--panel-2); }
.enh-stage {
  position: relative; height: clamp(220px, 46vh, 420px); overflow: hidden; border-radius: 14px;
  background: var(--panel-2); border: 1px solid var(--border);
}
.enh-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; user-select: none; }
.enh-tag {
  position: absolute; top: 12px; left: 12px; z-index: 3; padding: 4px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600; color: #fff; background: rgba(18, 18, 40, .62); backdrop-filter: blur(4px);
}
.enh-tag-end { left: auto; right: 12px; color: var(--on-accent, #fff); background: var(--accent); }
.enh-caption { margin: 0; font-size: 12.5px; color: var(--muted); text-align: center; }
.enh-kicker { margin: 0 0 12px; font-size: 11.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.enh-hint { display: block; margin: 6px 0 0; }
.enh-wide .enh-sizes { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }
.enh-wide .enh-size { min-width: 0; padding: 0 6px; }
/* From what to what: two figures and an arrow, in one box. */
.enh-wide .enh-dims {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px;
  margin: 0 0 14px; padding: 12px 14px; border-radius: 12px; background: var(--panel-2); font-weight: 400;
}
.enh-dim { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12px; color: var(--muted); }
.enh-dim strong { font-size: 14px; color: var(--ink); font-variant-numeric: tabular-nums; }
.enh-dim-to strong { color: var(--accent-ink); }
.enh-dims-none .enh-dim-to strong { color: var(--muted); }
.enh-arrow { display: grid; place-items: center; color: var(--accent); }
.enh-gains { display: grid; gap: 8px; margin: 0 0 12px; padding: 0; list-style: none; }
.enh-gain { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text); }
.enh-gain > svg { flex: none; color: var(--ok); }
.enh-wide .enh-heavy { margin: 0 0 6px; }
/* The foot: what is kept safe on the left, the two buttons of the face on the right. */
.enh-wide .enh-foot { margin: 0; padding: 14px 24px; border-top: 1px solid var(--border); background: var(--panel-2); border-radius: 0 0 16px 16px; }
.enh-foot-face { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; width: 100%; }
.enh-safe { display: flex; align-items: center; gap: 10px; min-width: 0; color: var(--muted); }
.enh-safe > svg { flex: none; color: var(--ok); }
.enh-safe-words { display: flex; flex-direction: column; min-width: 0; font-size: 12.5px; }
.enh-safe-words strong { font-size: 13px; color: var(--ink); }
.enh-acts { display: flex; flex-wrap: wrap; gap: 10px; margin-left: auto; }
/* The second face: the same picture twice, the right half being made; a pink seam between them. */
.enh-working { position: absolute; inset: 0; z-index: 1; clip-path: inset(0 0 0 50%); }
.enh-working .enh-img { filter: contrast(1.08) saturate(1.08); }
.enh-working::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .28) 50%, transparent 70%) no-repeat;
  background-size: 220% 100%; background-position: 120% 0;
}
@media (prefers-reduced-motion: no-preference) {
  .enh-working::after { animation: enh-sweep 2.4s ease-in-out infinite; }
}
@keyframes enh-sweep { from { background-position: 120% 0; } to { background-position: -20% 0; } }
.enh-seam { position: absolute; top: 0; bottom: 0; left: var(--enh-at, 50%); z-index: 2; width: 2px; margin-left: -1px; background: var(--accent); box-shadow: 0 0 0 1px rgba(255, 255, 255, .5); pointer-events: none; }
.enh-lead { margin: 0 0 4px; font-size: 20px; font-weight: 700; color: var(--ink); }
.enh-line { margin: 0 0 16px; font-size: 13.5px; color: var(--muted); }
.enh-meter-head { display: flex; justify-content: space-between; gap: 8px; margin: 0 0 8px; font-size: 13px; color: var(--text); }
.enh-pct { font-weight: 700; color: var(--accent-ink); font-variant-numeric: tabular-nums; }
.enh-bar { height: 8px; overflow: hidden; border-radius: 999px; background: var(--panel-3); }
.enh-fill { display: block; height: 100%; width: var(--enh-done, 0%); border-radius: inherit; background: var(--accent); transition: width .4s ease; }
.enh-steps { display: grid; gap: 12px; margin: 18px 0; padding: 0; list-style: none; }
.enh-step { display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--muted); }
.enh-dot {
  flex: none; display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%;
  color: transparent; border: 2px solid var(--border); background: var(--panel);
}
.enh-step-done { color: var(--text); }
.enh-step-done .enh-dot { color: #fff; border-color: var(--ok); background: var(--ok); }
.enh-step-now { color: var(--ink); font-weight: 600; }
.enh-step-now .enh-dot { border-color: var(--accent); box-shadow: inset 0 0 0 4px var(--panel), inset 0 0 0 9px var(--accent); }
.enh-free { display: flex; gap: 10px; margin: 0; padding: 12px 14px; border-radius: 12px; font-size: 13px; color: var(--text); background: var(--accent-soft); }
.enh-free > svg { flex: none; color: var(--accent-ink); }
.enh-stopnote { margin: 10px 0 0; }
.btn.bk-btn.enh-stop { color: var(--danger-ink); border-color: var(--danger-line); }
.btn.bk-btn.enh-stop:hover:not(:disabled) { background: var(--danger-soft); border-color: var(--danger-ink); }
/* The third face: the new version under, the original over it clipped at the handle, which is a range input
   laid over the whole picture — dragged with a finger, a mouse, or the arrow keys. */
.enh-before { position: absolute; inset: 0; z-index: 1; clip-path: inset(0 calc(100% - var(--enh-at, 50%)) 0 0); }
.enh-slider {
  position: absolute; inset: 0; z-index: 4; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: ew-resize; touch-action: pan-y;
}
.enh-compare:has(.enh-slider:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.enh-ok {
  display: inline-flex; align-items: center; gap: 6px; margin: 0 0 12px; padding: 4px 10px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; color: var(--ok); background: var(--ok-soft); border: 1px solid var(--ok-line);
}
.enh-final { display: flex; flex-direction: column; gap: 2px; margin: 14px 0; padding: 14px; border-radius: 12px; background: var(--panel-2); }
.enh-final-label { font-size: 12px; color: var(--muted); }
.enh-final-value { font-size: 20px; color: var(--ink); font-variant-numeric: tabular-nums; }
.enh-final-from { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
@media (max-width: 760px) {
  .enh-body { grid-template-columns: minmax(0, 1fr); gap: 18px; padding: 16px; }
  .enh-pane { grid-column: 1; }
  .enh-head { padding: 14px 12px 12px 16px; }
  .enh-by { display: none; }
  .enh-stage { height: clamp(200px, 38vh, 320px); }
  .enh-wide .enh-foot { padding: 12px 16px; }
  .enh-acts { width: 100%; }
  .enh-acts > .btn { flex: 1 1 auto; }
}

@media (max-width: 1100px) {
  .bk-split { grid-template-columns: minmax(0, 1fr); }
  .bk-split > .bk-aside { grid-column: 1; position: static; }
}
@media (max-width: 720px) {
  .bk-cols { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .bk-actions { width: 100%; }
  .bk-actions > .btn { flex: 1 1 auto; }
  .bk-actions > .bk-trash { flex: none; }
  .bk-card, .bk-aside { padding: 16px; }
  .bk-modal-card { padding: 18px 16px; }
}
@media (max-width: 480px) {
  /* On a phone the breadcrumb keeps where you are, and gives the width to it. */
  .bk-crumb-sep { display: none; }
}

/* ================= BRAND ================= */
/* Edge to edge, as the owner's pages draw it: the white bar and the tabs span the whole
   width of the work area, over a light-grey page. `.main` pads every screen and
   `.main > .view` is the scroller, so this view takes the padding back with a negative
   margin of the same size — at each of the three widths `.main` sets it at, below — and
   the panels pad themselves inside it.

   `--bk-sticky` is where a side panel (`.bk-aside`) sticks: under the frame, which is
   itself stuck to the top of this scroller, with the page's breathing space. The
   frame's height is the tabs' row (46px and its line). */
.brand-view {
  --brand-chrome: 47px;
  --bk-sticky: calc(var(--brand-chrome) + 16px);
  margin: -16px -20px;
  background: var(--bg);
}
@media (max-width: 700px) { .brand-view { margin: -12px -12px -14px; } }
@media (max-width: 620px) { .brand-view { margin: -10px -10px -12px; } }
/* The frame, stuck to the top while the page scrolls under it. Above the page's own
   positioned pieces — a card's «⋯», a side panel — and under every popover and dialog. */
.brand-chrome {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center;
  background: var(--panel); border-bottom: 1px solid var(--border);
}
/* The end of the tabs' row: the autosave when it has something to say, and the «?». The
   tabs scroll inside their own box, so these two stay in view on a phone. */
.brand-tabs-end { flex: none; display: flex; align-items: center; gap: 10px; padding: 0 22px 0 8px; }
/* The page under the frame: the owner's 28px of air on each side of the work. */
.brand-view > [data-panel] { padding: 26px 28px 44px; }

/* The autosave: only while a save is on its way, or when the kit is on this device only
   (`err-hint`). A save that went through is `sr-only` — said, not shown. */
.brand-saved { margin: 0; font-size: 13px; white-space: nowrap; }
.brand-saved:empty { display: none; }

/* ---------- the seven tabs, as words ----------
   The open one in the accent's ink with a line under it, drawn as an inset shadow so
   the tab is not a pixel taller than the others. The first tab's line starts where the
   page's title does, with the word inside it, as the owner's page draws it. Out of
   width they scroll sideways rather than wrap: seven words on two lines read as two
   rows of tabs. */
.brand-tabs { flex: 1 1 auto; min-width: 0; display: flex; gap: 0 26px; padding: 0 28px; overflow-x: auto; scrollbar-width: none; }
.brand-tabs::-webkit-scrollbar { display: none; }
.brand-tab {
  flex: none; display: inline-flex; align-items: center; min-height: 46px; padding: 0 15px; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 500; color: var(--text); white-space: nowrap;
  background: none; border: 0; border-radius: 0; box-shadow: inset 0 -2px 0 transparent;
  transition: color .13s, box-shadow .13s;
}
.brand-tab:hover { color: var(--ink); box-shadow: inset 0 -2px 0 var(--border); }
.brand-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; border-radius: 8px; }
.brand-tab.on { color: var(--accent-ink); font-weight: 600; box-shadow: inset 0 -2px 0 var(--accent); }

/* ---------- the kit's tab: its note, and the three cards ---------- */
/* The one line the kit keeps under its header: the kit is nearly empty. Empty, it
   takes no room at all. */
.brand-note { margin: -8px 0 18px; font-size: 13px; }
.brand-note:empty { display: none; }

/* «Import from the site», as the owner's mockup draws it (2026-10-21): a pale pink band
   under the header, with a drawing of two pages, two lines and the page's one pink
   button. The button takes its own line, full width, once the band runs out of room:
   the words grow by a thousand to its one, so on a single line it stays its own size. */
.brand-import-banner {
  display: flex; align-items: center; flex-wrap: wrap; gap: 16px 28px; margin: 0 0 18px; padding: 16px 18px 16px 30px;
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent); border-radius: 14px;
  background: linear-gradient(100deg, color-mix(in srgb, var(--accent) 9%, var(--panel)), color-mix(in srgb, var(--accent) 7%, var(--panel)));
}
.brand-import-art { flex: none; width: 87px; height: auto; overflow: visible; }
.brand-import-art .back { fill: #e2deeb; stroke: #bdbacb; stroke-width: 1.3; }
.brand-import-art .front { fill: #fbfbfd; stroke: #b9b8c8; stroke-width: 1.3; filter: drop-shadow(0 3px 5px rgba(18, 18, 58, .08)); }
.brand-import-art .dot { fill: none; stroke: #c9c6d3; stroke-width: 2.6; stroke-linecap: round; }
.brand-import-art .pic { fill: color-mix(in srgb, var(--accent) 36%, #ffffff); stroke: color-mix(in srgb, var(--accent) 55%, #6b6a7c); stroke-width: 1.3; }
.brand-import-art .txt { fill: none; stroke: #b3b4c7; stroke-width: 3; stroke-linecap: round; }
.brand-import-art .txt.soft { stroke: #d6d7e1; }
.brand-import-art .spark { fill: var(--accent); }
:root[data-theme="dark"] .brand-import-art .back { fill: #2a2d48; stroke: #4a4e72; }
:root[data-theme="dark"] .brand-import-art .front { fill: #1d1f37; stroke: #555a80; }
:root[data-theme="dark"] .brand-import-art .dot, :root[data-theme="dark"] .brand-import-art .txt.soft { stroke: #3f4366; }
:root[data-theme="dark"] .brand-import-art .txt { stroke: #6a6f96; }
.brand-import-copy { flex: 1000 1 260px; min-width: 0; }
.brand-import-title { margin: 0; font-size: 20px; font-weight: 700; line-height: 1.25; letter-spacing: -.01em; color: var(--ink); }
.brand-import-sub { margin: 4px 0 0; font-size: 15px; color: var(--muted); }
.btn.bk-cta.brand-import-go { flex: 1 0 auto; min-height: 56px; padding: 0 30px; gap: 12px; font-size: 16px; font-weight: 700; border-radius: 10px; }
@media (max-width: 560px) {
  .brand-import-banner { padding: 16px; gap: 14px 18px; }
  .brand-import-art { width: 64px; }
  .brand-import-copy { flex-basis: 180px; }
  .brand-import-title { font-size: 17px; }
  .brand-import-sub { font-size: 14px; }
}

/* The identity card: the logo in a column of its own, a line, and the facts beside it
   in two columns. Both sides name their track, although neither can disappear: the
   rule costs one declaration here and is the one that holds when somebody hides one.

   Sized by the card and not by the window (`@container brand-id`, below): how much room
   the card has depends on whether the left column is folded, which no media query can
   see. Safe here, where it would not be on the panel: containment makes this box the
   one a fixed-position child is placed against, and nothing inside the card is fixed —
   the popovers live in the body and the import dialog outside the card. */
.brand-identity { container: brand-id / inline-size; }
.brand-identity-body { display: grid; grid-template-columns: 296px minmax(0, 1fr); gap: 0 34px; }
.brand-logo-col { grid-column: 1; min-width: 0; padding-right: 46px; border-right: 1px solid var(--border); }
.brand-identity-fields { grid-column: 2; column-gap: 24px; align-content: start; }
.brand-identity .bk-field, .brand-pair .bk-field { margin-bottom: 20px; }
.brand-identity-fields textarea, .brand-pair textarea { resize: vertical; }
/* The photographic style and the light: one line, as the owner's page draws them, and
   as tall as what is written in them — `field-sizing` where the browser has it, the
   page's own measuring where it does not (`growField`). The floor is one line, whatever
   was measured, and a long placeholder is cut rather than wrapped so an empty field is
   one line as well. */
.bk-field textarea.brand-grow { min-height: 44px; overflow: hidden; resize: none; field-sizing: content; }
.bk-field textarea.brand-grow::placeholder { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* «Save changes», and its moment of «Saved ✓»: the tick after the word, where the icon
   before it was. Busy while its own save is out, and never faded. */
.brand-save .brand-save-ok { display: none; }
.brand-save.done .brand-save-ic { display: none; }
.brand-save.done .brand-save-ok { display: inline-block; }
.brand-save[aria-busy="true"] { cursor: progress; }
.brand-logo-col > .bk-label { margin-bottom: 7px; }
.brand-logo-col > .hint { margin: 8px 0 0; }
.brand-logo-col > .hint:empty { display: none; }
.brand-logo-col > .btn.bk-wide { min-height: 46px; margin-top: 10px; }
.brand-logo-col > .brand-logo-note { margin: 16px 0 0; }

/* How it speaks and how it looks, side by side and as tall as each other — and one above
   the other as soon as either would be narrower than 440px, whatever the window and the
   left column leave. Auto-placed on purpose, so that the second can wrap under the
   first: neither card can be hidden, and a child that can is the one that has to name
   its track. */
.brand-pair {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr)); gap: 18px; margin-top: 18px;
}
.brand-pair > .bk-card + .bk-card { margin-top: 0; }
.brand-pair .bk-field:last-child { margin-bottom: 0; }

/* ---------- the tone: the chosen words, and a «+» ----------
   The words as outline chips, the × on a chip's corner under the pointer or the
   keyboard — always, where there is no pointer to hover with. */
.brand-tones { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; }
.brand-tone {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  min-width: 106px; min-height: 42px; padding: 0 22px;
  font-size: 15px; font-weight: 400; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.brand-tone-x {
  position: absolute; top: -9px; right: -9px; display: grid; place-items: center; width: 22px; height: 22px;
  padding: 0; cursor: pointer; color: var(--text); background: var(--panel);
  border: 1px solid var(--border); border-radius: 50%; box-shadow: var(--shadow-1);
  opacity: 0; transition: opacity .12s;
}
.brand-tone:hover .brand-tone-x, .brand-tone:focus-within .brand-tone-x { opacity: 1; }
.brand-tone-x:hover { color: var(--danger-ink); border-color: var(--danger-line); }
.brand-tone-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.brand-tone-add {
  display: grid; place-items: center; width: 42px; height: 42px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 1px dashed var(--border); border-radius: 8px;
}
.brand-tone-add:hover, .brand-tone-add[aria-expanded="true"] { color: var(--ink); border-color: var(--ink); }
.brand-tone-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The popover under the «+»: the six traits, two by two, and a word of one's own. */
.brand-tone-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.brand-tone-opt {
  display: flex; align-items: center; justify-content: center; gap: 6px; min-width: 0; min-height: 38px; padding: 0 12px;
  cursor: pointer; font: inherit; font-size: 13.5px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.brand-tone-opt:hover:not(:disabled) { border-color: var(--accent-line); }
.brand-tone-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* Chosen already: said, and not pressable — taking it off is its chip's ×. */
.brand-tone-opt[aria-pressed="true"] { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); cursor: default; }
.brand-tone-opt[aria-pressed="true"]::before { content: '✓'; font-weight: 700; }
.brand-tone-own { display: flex; gap: 8px; margin-top: 12px; }
.brand-tone-own input {
  flex: 1; min-width: 0; margin: 0; padding: 7px 12px; font-size: 14px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}

/* ---------- the colours: swatches with their code under them ---------- */
.brand-swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 14px 28px; }
.brand-swatch { display: grid; gap: 8px; min-width: 0; }
.brand-swatch-chip {
  width: 100%; height: 48px; padding: 0; cursor: pointer;
  border: 1px solid var(--border); border-radius: 6px; transition: box-shadow .13s;
}
.brand-swatch-chip:hover, .brand-swatch-chip[aria-expanded="true"] { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--ink); }
.brand-swatch-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.brand-swatch-hex { font-family: var(--mono); font-size: 12.5px; color: var(--text); text-align: center; }
/* «+ Add colour» under the row, as a link: a tile in the row wrapped the fifth place
   onto a line of its own under four swatches. */
.brand-palette-add { margin-top: 14px; }
/* One colour's popover: the well and the code side by side, then the role and a note. */
.brand-colour-top { display: flex; align-items: flex-end; gap: 12px; }
.brand-colour-top > .bk-field { flex: 1; min-width: 0; }
.brand-colour-well {
  flex: none; width: 44px; height: 44px; margin: 0 0 16px; padding: 2px; cursor: pointer;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.brand-colour-top input:not([type="color"]) { font-family: var(--mono); text-transform: uppercase; }

/* ---------- the content language ----------
   The main one as a field, the others as chips under it. The select lies
   transparent over the field: a click anywhere opens it, and what shows is the code,
   the name and the badge. Compact, at the height of the fields around it. */
.brand-lang-field .hint { margin: 8px 0 0; font-size: 12.5px; }
.brand-lang-field .hint:empty { display: none; }
.lang-set { display: flex; flex-direction: column; gap: 10px; }
.lang-line { display: flex; align-items: center; gap: 8px 18px; flex-wrap: wrap; }
.lang-main {
  position: relative; display: flex; align-items: center; gap: 12px; flex: 1 1 240px; min-width: 0; min-height: 44px;
  margin: 0; padding: 0 14px; cursor: pointer; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.lang-main:hover { border-color: var(--accent-line); }
.lang-main:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.lang-main select { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.lang-shown { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; }
.lang-code {
  display: inline-grid; place-items: center; flex: none; min-width: 30px; height: 22px; padding: 0 6px; border-radius: 5px;
  font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--ink-2); background: var(--panel-2); border: 1px solid var(--border);
}
.lang-badge { flex: none; padding: 3px 10px; border-radius: 999px; font-size: 12.5px; color: var(--muted); background: var(--panel-2); }
.lang-chev {
  flex: none; width: 18px; height: 18px; margin-left: auto; color: var(--muted);
  fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.lang-add {
  width: auto; field-sizing: content; margin: 0; padding: 8px 4px; cursor: pointer; appearance: none; -webkit-appearance: none;
  font-size: 14.5px; font-weight: 600; color: var(--accent-ink); background: transparent; border: 0; border-radius: 6px;
}
.lang-add:focus { outline: none; }
.lang-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.lang-add[hidden] { display: none; }
.lang-others { display: flex; flex-wrap: wrap; gap: 8px; }
.lang-chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 5px 9px 5px 6px;
  font-size: 13.5px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2);
}
/* A spoken language's × on its chip. */
.word-drop { padding: 0; cursor: pointer; background: none; border: 0; color: inherit; opacity: .5; font-size: 16px; line-height: 1; }
.word-drop:hover { opacity: 1; }

/* ---------- the kit's tab, as the width runs out ---------- */
/* The identity card's own width: the logo over the facts once the facts beside it would
   be two columns too narrow to read, and the line between them turned on its side; then
   the facts in one column. */
@container brand-id (max-width: 820px) {
  .brand-identity-body { grid-template-columns: minmax(0, 1fr); }
  .brand-identity-fields { grid-column: 1; }
  /* The tile on the left of its own row and what goes with it beside it. Every piece
     names its cell: the status line under the button is there only when it has
     something to say, and an auto-placed grid would slide the note into its place. */
  .brand-logo-col {
    display: grid; grid-template-columns: minmax(0, 240px) minmax(0, 1fr); grid-template-rows: auto auto auto 1fr;
    gap: 0 24px; align-items: start;
    padding: 0 0 20px; margin: 0 0 20px; border-right: 0; border-bottom: 1px solid var(--border);
  }
  .brand-logo-col > .bk-label { grid-column: 1 / -1; grid-row: 1; }
  .brand-logo-tile { grid-column: 1; grid-row: 2 / 5; }
  .brand-logo-col > .btn.bk-wide { grid-column: 2; grid-row: 2; margin-top: 0; }
  .brand-logo-col > .hint { grid-column: 2; grid-row: 3; }
  .brand-logo-col > .brand-logo-note { grid-column: 2; grid-row: 4; }
}
@container brand-id (max-width: 520px) {
  .brand-identity-fields { grid-template-columns: minmax(0, 1fr); }
  /* One column again, in the order the markup reads. */
  .brand-logo-col { grid-template-columns: minmax(0, 1fr); }
  .brand-logo-tile { grid-column: 1; grid-row: 2; max-width: 280px; }
  .brand-logo-col > .btn.bk-wide { grid-column: 1; grid-row: 3; margin-top: 10px; }
  .brand-logo-col > .hint { grid-column: 1; grid-row: 4; }
  .brand-logo-col > .brand-logo-note { grid-column: 1; grid-row: 5; }
}
@media (max-width: 760px) {
  .brand-view > [data-panel] { padding: 20px 16px 36px; }
  /* The strip scrolls sideways here and nothing said so: the fourth tab was cut at
     «Cha…» with no sign there were three more. The fade is that sign, and the wider
     right padding lets the last tab scroll clear of it. The mask is alpha only, so
     «black» is not a colour on screen and needs no theme. */
  .brand-tabs {
    gap: 0 4px; padding: 0 40px 0 16px;
    -webkit-mask-image: linear-gradient(90deg, black calc(100% - 40px), transparent);
    mask-image: linear-gradient(90deg, black calc(100% - 40px), transparent);
  }
  .brand-tab { padding: 0 12px; }
  .brand-tabs-end { padding: 0 12px 0 4px; }
}
@media (max-width: 560px) {
  .brand-tone { min-width: 0; padding: 0 16px; }
  .brand-swatches { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); gap: 12px 16px; }
  .brand-fonts { grid-template-columns: minmax(0, 1fr); }
}
/* No pointer to hover with: the × a chip shows under it is always there. */
@media (hover: none) { .brand-tone-x { opacity: 1; } }

/* Present to a screen reader, absent from the screen. For a legend that names a
   group of controls whose purpose the heading above already gives visually. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- the kit's two typefaces, side by side under one label ---------- */
.brand-fonts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; }
.brand-fonts > label { margin: 0; }
.brand-font-label { display: block; margin: 0 0 6px; font-size: 12.5px; font-weight: 400; color: var(--muted); }

/* ---- the logo ----
   The tile is the preview and the drop zone at once: they are the same thing before
   and after the upload. The chequered ground says what no caption would — that this
   PNG really has a transparent background, or that it does not. */
.brand-logo-tile { position: relative; }
.logo-drop {
  position: relative; display: grid; place-items: center; aspect-ratio: 16 / 15; overflow: hidden;
  padding: 14px; cursor: pointer; text-align: center;
  border: 1.5px dashed var(--border); border-radius: 10px;
  background: repeating-conic-gradient(var(--panel-3) 0% 25%, var(--panel-2) 0% 50%) 50% / 16px 16px;
  transition: border-color .14s, box-shadow .14s;
}
/* With a logo in it the tile is a picture and no longer a prompt: the dashes go. */
.logo-drop:has(> img:not([hidden])) { border-style: solid; }
/* A logo drawn in a pale ink, made for a dark header: on a dark ground, or it is a blank tile. */
.logo-drop.on-dark:has(> img:not([hidden])) { background: #111; }
.logo-drop:hover, .logo-drop.over { border-color: var(--accent); }
/* Hover and keyboard focus were sharing one rule, and it removed the outline —
   so the keyboard got the hover look and nothing else. They are separated: the
   pointer gets the tint, the keyboard gets a ring it can actually see. */
.logo-drop:focus-visible { border-color: var(--accent); outline: 2px solid var(--accent); outline-offset: 2px; }
.logo-drop.over { box-shadow: inset 0 0 0 3px var(--accent-soft); }
/* Over the whole tile and contained in it, so a logo of any shape sits whole in the
   middle, and a square one fills it as the owner's page shows. */
.logo-drop img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.logo-empty { display: grid; justify-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
/* The preview and the upload prompt swap places through `hidden`, and without these
   two lines `display` would win: both would be visible at once, that is, the
   just-uploaded logo under the words "drop the logo here". */
.logo-drop img[hidden], .logo-empty[hidden] { display: none; }
.logo-empty small { color: var(--muted); opacity: .85; }
.logo-ic { color: var(--ink-2); }
/* The × on the tile's corner takes the logo away, under the pointer or the keyboard. */
.brand-logo-x {
  position: absolute; top: 8px; right: 8px; display: grid; place-items: center; width: 30px; height: 30px;
  padding: 0; cursor: pointer; color: var(--text); background: var(--panel);
  border: 1px solid var(--border); border-radius: 50%; box-shadow: var(--shadow-1);
  opacity: 0; transition: opacity .12s;
}
.brand-logo-tile:hover .brand-logo-x, .brand-logo-x:focus-visible { opacity: 1; }
.brand-logo-x:hover { color: var(--danger-ink); border-color: var(--danger-line); }
.brand-logo-x:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* And with no pointer to hover with, it is always there. After the rule it overrides. */
@media (hover: none) { .brand-logo-x { opacity: 1; } }

/* ---------- Brand · products, competitors, memory ----------
   The three tabs as the owner's mockups draw them, on the `.bk-*` pieces above: what
   is here is only what is theirs alone. One prefix per tab — `bp-` the products,
   `bc-` the competitors, `bm-` the memory — so that a rule written for one of them
   cannot reach another by accident.

   The products' grid. The minimum width is what gives four columns in the 1280px the
   view has inside the mockups' 1584px window (the left column is 264px, the page's
   padding 40px) and a fifth only past 1330px; one column on a phone. The photo is
   inset and rounded, and 16:10 is its proportion in the mockup. */
.bp-grid { --bk-min: 260px; --bk-ratio: 16 / 10; }
.bp-grid > .bk-empty { grid-column: 1 / -1; }
.bp-card { display: flex; flex-direction: column; cursor: pointer; }
.bp-card .bk-item-name { font-size: 15.5px; }
.bp-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 26px; margin-top: 4px; }
.bp-price { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15.5px; font-weight: 700; color: var(--ink); }
.bp-price.promo { color: var(--accent-ink); }
/* «Open details» shows itself on hover and on focus: eight links over eight cards are
   noise, and the whole card opens the product anyway. Opacity and not `hidden`, so the
   keyboard still reaches it — and on a screen with no hover it is always there,
   because there is nothing to hover with. */
.bp-open { flex: none; opacity: 0; transition: opacity .13s; }
.bp-card:hover .bp-open, .bp-card:focus-within .bp-open { opacity: 1; }
@media (hover: none) { .bp-open { opacity: 1; } }

/* The categories popover: a row per category, and under it the line the director
   reads about it. */
.bk-pop.bp-cats-pop { width: min(400px, calc(100vw - 16px)); padding: 10px 12px 12px; }
.bp-cats-hint { margin: 4px 4px 10px; font-size: 12.5px; color: var(--muted); }
.bp-cat { padding: 10px 4px 12px; border-top: 1px solid var(--border); }
.bp-cat-top { display: flex; align-items: center; gap: 4px; }
.bp-cat-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; color: var(--ink); }
.bp-cat-n { flex: none; margin-right: 6px; font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.bp-cat-top > .bk-x { width: 30px; height: 30px; }
.bk-x.bp-drop:hover { color: var(--danger); }
.bp-cat-note { display: block; margin: 8px 0 0; font-size: 13px; line-height: 1.45; }

/* The competitors as the owner's mockup draws them (2026-10-18): one table — the logo, who,
   what it sells, its price band, «Details» and «⋯» — and under it the positioning as one row
   that opens its three notes in place. Below 860px each row is a card of its own. */
.bc-full { margin: 0 0 16px; }
.bc-table { padding: 0; overflow: hidden; }
.bc-bar { margin: 0; padding: 18px 22px; border-bottom: 1px solid var(--border); }
.bc-count { flex: none; margin-left: auto; font-size: 15px; color: var(--muted); white-space: nowrap; }
.bc-heads, .bc-row {
  display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1.15fr) minmax(0, .85fr) auto;
  align-items: center; gap: 18px; padding: 14px 26px;
}
.bc-heads { padding-top: 16px; padding-bottom: 14px; font-size: 14px; font-weight: 600; color: var(--muted); border-bottom: 1px solid var(--border); }
.bc-list { display: flex; flex-direction: column; }
.bc-row { padding-top: 16px; padding-bottom: 16px; }
.bc-row + .bc-row { border-top: 1px solid var(--border); }
.bc-list > .bk-empty { margin: 0; padding: 28px 26px; }
.bc-cell { min-width: 0; }
.bc-cell-who { display: flex; align-items: center; gap: 22px; }
.bc-who { min-width: 0; }
.bc-name { margin: 0; font-size: 18px; font-weight: 700; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.bc-site { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; margin: 4px 0 0; font-size: 15px; font-weight: 500; }
.bc-site > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.bc-site { color: var(--accent-ink); text-decoration: none; }
a.bc-site:hover { text-decoration: underline; }
a.bc-site:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
p.bc-site { color: var(--muted); }
/* The rival's logo in a white box — a dark one when its own pixels are pale — or its initial. */
.bc-logo {
  flex: none; width: 76px; height: 76px; display: grid; place-items: center; overflow: hidden; padding: 10px;
  border-radius: 12px; font-size: 26px; font-weight: 800; color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel)); border: 1px solid var(--border);
}
.bc-logo.has { background: #fff; }
.bc-logo.has.on-dark { background: #111; }
.bc-logo img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.bc-offer-title { margin: 0; font-size: 16px; font-weight: 700; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.bc-offer-sub { margin: 3px 0 0; font-size: 14.5px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.bc-band { display: inline-block; padding: 5px 14px; border-radius: 8px; font-size: 14px; font-weight: 600; color: var(--ink); background: var(--panel-2); }
.bc-price-note { margin: 8px 0 0; font-size: 14.5px; color: var(--muted); }
.bc-band + .bc-price-note { margin-top: 8px; }
.bc-cell-price > .bc-price-note:first-child { margin-top: 0; }
.bc-acts { display: flex; align-items: center; gap: 14px; }
.bc-details { min-height: 48px; padding: 0 30px; font-size: 15.5px; font-weight: 700; }
.bc-acts .bk-more:disabled { opacity: .45; cursor: default; border-color: var(--border); }
/* A field nobody has written reads as one, rather than as a gap in the layout. */
.bc-unset { color: var(--muted); font-style: italic; }

/* The positioning: one row — its icon, whose it is, what it holds, «Edit notes» — and the three
   notes' form under it while they are written. The avoid note carries the red. */
.bc-pos { margin-top: 18px; padding: 0; }
.bc-pos-row { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; align-items: center; gap: 22px; padding: 22px 28px; }
.bc-pos-ic { color: var(--ink); }
.bc-pos-rule { width: 1px; height: 44px; background: var(--border); }
.bc-pos-name { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.bc-pos-sub { margin: 4px 0 0; font-size: 15px; color: var(--muted); }
.bc-pos-edit { border: 0; background: transparent; font-size: 15.5px; font-weight: 700; color: var(--ink); }
.bc-pos-edit:hover { text-decoration: underline; }
.bc-pos-form { display: flex; flex-direction: column; gap: 14px; padding: 4px 28px 22px; border-top: 1px solid var(--border); padding-top: 20px; }
.bc-pos-form textarea { resize: vertical; }
.bc-pos-title { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.bc-pos-title > .bk-ic { flex: none; color: var(--accent-ink); }
.bc-pos-field.avoid .bc-pos-title > .bk-ic { color: var(--danger); }
.bc-pos-field .bc-pos-title { margin: 0 0 7px; font-size: 13.5px; }
.bc-edit-foot { display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
@media (max-width: 860px) {
  .bc-heads { display: none; }
  .bc-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px 18px; padding: 18px; }
  .bc-cell-who, .bc-acts { grid-column: 1 / -1; }
  .bc-acts { justify-content: flex-end; }
  .bc-logo { width: 60px; height: 60px; }
  .bc-pos-row { grid-template-columns: auto minmax(0, 1fr); padding: 18px; }
  .bc-pos-rule { display: none; }
  .bc-pos-edit { grid-column: 1 / -1; justify-self: start; padding: 0; }
  .bc-pos-form { padding: 18px; }
}

/* A competitor's details, as the mockup draws them: who at the top, two columns, a foot. */
.ci.bk-modal[hidden] { display: none; }
.ci-card { position: relative; width: min(800px, 100%); padding: 26px 30px 22px; border-radius: 18px; }
.ci-x { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; display: grid; place-items: center; padding: 0; cursor: pointer; color: var(--ink); background: transparent; border: 0; border-radius: 10px; }
.ci-x:hover { background: var(--panel-2); }
.ci-kicker { margin: 0 0 16px; font-size: 13px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-2); }
.ci-top { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 22px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
.ci-logo {
  width: 104px; height: 80px; display: grid; place-items: center; overflow: hidden; padding: 10px;
  border-radius: 10px; font-size: 30px; font-weight: 800; color: var(--accent-ink);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel)); border: 1px solid var(--border);
}
.ci-logo.has { background: #fff; }
.ci-logo.has.on-dark { background: #111; }
.ci-logo img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.ci-name { margin: 0; font-size: 28px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); overflow-wrap: anywhere; }
.ci-site { display: inline-flex; align-items: center; gap: 6px; margin: 6px 0 0; font-size: 15px; color: var(--accent-ink); text-decoration: underline; }
p.ci-site { color: var(--muted); text-decoration: none; }
.ci-kit { margin: 0; align-self: start; padding-top: 8px; font-size: 14.5px; color: var(--ink-2); white-space: nowrap; }
.ci-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 34px; padding: 18px 0 6px; }
.ci-col + .ci-col { padding-left: 34px; border-left: 1px solid var(--border); margin-left: -34px; }
.ci-sec { padding: 14px 0; }
.ci-sec + .ci-sec { border-top: 1px solid var(--border); }
.ci-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.ci-sec-title { margin: 0; font-size: 19px; font-weight: 800; color: var(--ink); }
.ci-band { font-size: 15px; color: var(--ink-2); }
.ci-text { margin: 0; font-size: 15px; line-height: 1.55; color: var(--text); white-space: pre-line; overflow-wrap: anywhere; }
.ci-unset { margin: 0; font-size: 15px; color: var(--muted); }
.ci-points { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; font-size: 15px; line-height: 1.45; color: var(--text); }
.ci-note { margin-top: 10px; padding: 0; cursor: pointer; font: inherit; font-size: 14px; color: var(--ink-2); text-decoration: underline; background: transparent; border: 0; }
.ci-plans { margin: 0; display: flex; flex-direction: column; }
.ci-plan { display: flex; justify-content: space-between; gap: 12px; padding: 9px 0; font-size: 15px; }
.ci-plan + .ci-plan { border-top: 1px solid var(--border); }
.ci-plan dt { color: var(--text); }
.ci-plan dd { margin: 0; font-weight: 700; color: var(--ink); white-space: nowrap; }
.ci-terms { margin: 8px 0 0; font-size: 14px; color: var(--muted); }
.ci-channels { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; }
.ci-channel { display: inline-flex; align-items: center; gap: 10px; min-width: 0; font-size: 15px; color: var(--ink); text-decoration: none; }
.ci-channel:hover { text-decoration: underline; }
.ci-channel > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ci-mark { flex: none; }
.ci-foot { display: flex; justify-content: space-between; gap: 12px; padding-top: 18px; border-top: 1px solid var(--border); }
.ci-close, .ci-edit { min-height: 48px; padding: 0 28px; font-size: 15.5px; font-weight: 700; border-radius: 10px; }
.ci-close { color: var(--ink); background: var(--panel); border: 1px solid var(--border); }
.ci-edit { display: inline-flex; align-items: center; gap: 10px; color: #fff; background: var(--accent); border: 1px solid var(--accent); }
@media (max-width: 720px) {
  .ci-card { padding: 22px 16px 16px; }
  .ci-top { grid-template-columns: auto minmax(0, 1fr); }
  .ci-kit { grid-column: 1 / -1; padding-top: 0; }
  .ci-body { grid-template-columns: minmax(0, 1fr); }
  .ci-col + .ci-col { padding-left: 0; margin-left: 0; border-left: 0; border-top: 1px solid var(--border); }
}

/* ---- the competitor's window, as the owner's mockups draw it (2026-10-18) ----
   «Import a competitor» from its site or «Add a competitor» by hand: the road on the left,
   the sheet on the right, the pink panel for how the brand stands apart. */
.cd.bk-modal[hidden] { display: none; }
.cd-card {
  position: relative; width: min(1080px, 100%); padding: 30px 32px 22px; border-radius: 20px;
  display: flex; flex-direction: column; gap: 6px;
}
.cd-x {
  position: absolute; top: 22px; right: 22px; width: 36px; height: 36px; display: grid; place-items: center;
  cursor: pointer; color: var(--ink); background: transparent; border: 0; border-radius: 9px;
}
.cd-x:hover { background: var(--panel-2); }
.cd-kicker { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 12.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-2); }
.cd-kicker > .bk-ic { color: var(--accent); }
.cd-title { margin: 6px 0 0; font-size: 30px; font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
.cd-sub { margin: 0 0 14px; font-size: 16px; color: var(--muted); }
.cd-tabs { display: flex; gap: 4px; padding: 4px; width: min(480px, 100%); background: var(--panel-2); border-radius: 12px; }
.cd-tabs[hidden] { display: none; }
.cd-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 10px; padding: 10px 14px;
  cursor: pointer; font: inherit; font-size: 15px; font-weight: 600; color: var(--ink);
  background: transparent; border: 0; border-radius: 9px;
}
.cd-tab.on { color: var(--on-solid); background: var(--solid); }
/* The body is what scrolls, inside a card that keeps its head and its foot. It was `overflow:
   hidden` in a flex column with a ceiling: a scroll container's least height is zero, so the
   body took all the shrinking and cut the bottom of the sheet off, and the card — never
   overflowing — showed no scrollbar. Below 820px most of the sheet was out of reach. */
.cd-body {
  display: grid; grid-template-columns: minmax(0, 284px) minmax(0, 1fr); gap: 0; margin-top: 18px;
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--border); border-radius: 16px;
}
.cd-card.bk-modal-card { overflow: hidden; }
.cd-left { padding: 22px 20px; background: var(--panel-2); border-right: 1px solid var(--border); }
.cd-side { display: flex; flex-direction: column; gap: 14px; }
.cd-side[hidden] { display: none; }
.cd-tile { width: 64px; height: 64px; display: grid; place-items: center; border-radius: 14px; color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, var(--panel)); }
.cd-side-title { margin: 4px 0 0; font-size: 20px; font-weight: 800; line-height: 1.25; color: var(--ink); }
.cd-side-text { margin: 0; font-size: 15px; line-height: 1.5; color: var(--muted); }
.cd-field { display: flex; flex-direction: column; gap: 7px; position: relative; min-width: 0; }
.cd-lab { display: inline-flex; align-items: baseline; gap: 6px; font-size: 14px; font-weight: 600; color: var(--ink); }
.cd-req { color: var(--accent-ink); }
.cd-opt { margin-left: auto; font-size: 13px; font-weight: 400; color: var(--muted); }
.cd-with-ic { position: relative; display: block; }
.cd-with-ic > .bk-ic { position: absolute; left: 13px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.cd-with-ic > .cd-input, .cd-with-ic > .cd-url { padding-left: 42px; }
.cd-input, .cd-url {
  width: 100%; min-height: 46px; margin: 0; padding: 11px 14px; font: inherit; font-size: 15px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.cd-input:focus, .cd-url:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
textarea.cd-input { resize: vertical; line-height: 1.45; }
.cd-go {
  display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 48px; padding: 0 16px;
  cursor: pointer; font: inherit; font-size: 16px; font-weight: 700; color: #fff; background: var(--accent);
  border: 0; border-radius: 10px;
}
.cd-go:disabled { cursor: progress; opacity: .7; }
.cd-go-price[hidden] { display: none; }
.cd-paid { margin: -6px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.cd-paid[hidden], .cd-status:empty { display: none; }
.cd-status { margin: 0; font-size: 13.5px; line-height: 1.45; }
.cd-rule { width: 100%; margin: 4px 0; border: 0; border-top: 1px solid var(--border); }
.cd-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0; }
.cd-step { position: relative; display: flex; align-items: center; gap: 14px; padding: 10px 0; font-size: 15px; color: var(--ink); }
.cd-step + .cd-step::before { content: ''; position: absolute; left: 12px; top: -10px; height: 20px; border-left: 1.5px solid var(--border); }
.cd-step-dot { flex: none; width: 26px; height: 26px; border-radius: 999px; border: 1.5px solid color-mix(in srgb, var(--muted) 70%, transparent); background: var(--panel); }
.cd-step[data-state="doing"] .cd-step-dot { border-color: var(--accent); border-top-color: transparent; animation: cd-spin .9s linear infinite; }
.cd-step[data-state="done"] .cd-step-dot {
  border-color: var(--accent); background: var(--accent) center / 14px no-repeat
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E");
}
@keyframes cd-spin { to { transform: rotate(360deg); } }
.cd-tip { display: flex; align-items: flex-start; gap: 10px; margin: 0; font-size: 14px; line-height: 1.45; color: var(--muted); }
.cd-tip > .bk-ic { flex: none; margin-top: 1px; }
.cd-prompts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 16px; }
.cd-prompt { display: flex; align-items: center; gap: 14px; }
.cd-prompt-ic { flex: none; width: 48px; height: 48px; display: grid; place-items: center; border-radius: 999px; color: var(--ink); background: var(--panel); border: 1px solid var(--border); }
.cd-prompt-words { display: flex; flex-direction: column; gap: 2px; font-size: 14px; color: var(--muted); }
.cd-prompt-words b { font-size: 15px; color: var(--ink); }
.cd-sheet { padding: 22px 24px; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.cd-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cd-sheet-title { margin: 0; font-size: 20px; font-weight: 800; color: var(--ink); }
.cd-state {
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; color: var(--ink); background: var(--panel-2); border: 1px solid var(--border);
}
.cd-state[data-phase="manual"] { color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 10%, var(--panel)); border-color: transparent; }
.cd-state[data-phase="done"] > .bk-ic { color: var(--accent); }
.cd-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.cd-name { position: relative; }
/* The identity: the logo's box on the left, the name, the site and the links beside it. */
.cd-id { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 18px; align-items: start; }
.cd-id-fields { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.cd-logo-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
/* The label and the pill each stay on one line: in a 200px column they take turns, not halves. */
.cd-logo-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 8px; }
.cd-logo-head > * { white-space: nowrap; }
.cd-logo-from { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; color: var(--ink-2); background: var(--panel-2); border: 1px solid var(--border); }
.cd-logo-from[hidden] { display: none; }
.cd-logo-box {
  width: 100%; height: 112px; display: grid; place-items: center; padding: 14px; cursor: pointer; overflow: hidden;
  border: 1.5px dashed var(--border); border-radius: 12px; background: var(--panel); color: var(--muted); font: inherit;
}
.cd-logo-box.has { border-style: solid; background: #fff; }
.cd-logo-box.has.on-dark { background: #111; }
.cd-logo-box img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.cd-logo-box:disabled { cursor: default; }
.cd-logo-box:hover:not(:disabled) { border-color: var(--accent); }
.cd-logo-empty { display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; }
.cd-logo-acts { display: flex; gap: 14px; }
.cd-logo-act { display: inline-flex; align-items: center; gap: 6px; padding: 2px 0; cursor: pointer; font: inherit; font-size: 13px; color: var(--ink-2); background: transparent; border: 0; }
.cd-logo-act[hidden] { display: none; }
.cd-logo-act:hover:not(:disabled) { color: var(--ink); text-decoration: underline; }
.cd-logo-remove:hover:not(:disabled) { color: var(--danger); }
.cd-logo-act:disabled { cursor: default; opacity: .5; }
/* The plans its site lists, under the price band: a name, a price, a cross. */
.cd-plans { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.cd-plans-lab { font-size: 13px; }
.cd-plan-rows { display: flex; flex-direction: column; gap: 6px; }
.cd-plan { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 110px) 28px; gap: 6px; align-items: center; }
.cd-plan .cd-input, .cd-price-terms { min-height: 38px; padding: 7px 10px; font-size: 14px; }
.cd-plan-x { width: 28px; height: 28px; display: grid; place-items: center; padding: 0; cursor: pointer; color: var(--muted); background: transparent; border: 0; border-radius: 999px; }
.cd-plan-x:hover:not(:disabled) { color: var(--ink); background: var(--panel-2); }
.cd-plan-add { align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; padding: 2px 0; cursor: pointer; font: inherit; font-size: 13.5px; font-weight: 700; color: var(--accent-ink); background: transparent; border: 0; }
.cd-plan-add[hidden] { display: none; }
.cd-plan-add:disabled { cursor: default; opacity: .5; }
.cd-links { display: flex; flex-wrap: wrap; gap: 8px; margin-top: -4px; }
.cd-links[hidden] { display: none; }
.cd-link {
  display: inline-flex; align-items: center; gap: 2px; padding: 3px 4px 3px 10px; border-radius: 999px;
  font-size: 13px; font-weight: 600; background: var(--panel-2); border: 1px solid var(--border);
}
.cd-link a { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); text-decoration: none; }
.cd-link a:hover { text-decoration: underline; }
.cd-link-x { width: 22px; height: 22px; display: grid; place-items: center; padding: 0; cursor: pointer; color: var(--muted); background: transparent; border: 0; border-radius: 999px; }
.cd-link-x:hover:not(:disabled) { color: var(--ink); background: var(--panel); }
.cd-tiers { display: flex; gap: 4px; padding: 4px; background: var(--panel-2); border-radius: 10px; }
.cd-tier { flex: 1; padding: 7px 8px; cursor: pointer; font: inherit; font-size: 13.5px; font-weight: 600; color: var(--ink); background: transparent; border: 0; border-radius: 7px; }
.cd-tier.on { color: var(--on-solid); background: var(--solid); }
.cd-tier:disabled { cursor: default; }
.cd-price-note { min-height: 40px; padding: 8px 12px; font-size: 14px; }
.cd-differ {
  display: flex; flex-direction: column; gap: 12px; padding: 16px 18px; border-radius: 14px;
  background: color-mix(in srgb, var(--accent) 7%, var(--panel)); border: 1px solid color-mix(in srgb, var(--accent) 18%, transparent);
}
.cd-differ-head { display: flex; align-items: center; gap: 14px; }
.cd-differ-ic { flex: none; width: 42px; height: 42px; display: grid; place-items: center; border-radius: 10px; color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--panel)); }
.cd-differ-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cd-differ-title { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; font-size: 16px; color: var(--ink); }
.cd-pill { padding: 3px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 600; color: var(--accent-ink); background: color-mix(in srgb, var(--accent) 14%, var(--panel)); }
.cd-differ-sub { font-size: 14px; color: var(--muted); }
/* The sheet waiting for its read: grey bars where the fields will be. The identity — the
   name and the site — shows once the free preview gave it; the rest once the read is in. */
.cd-skel { display: none; }
.cd-sheet[data-stage="waiting"] .cd-field .cd-input,
.cd-sheet[data-stage="waiting"] .cd-tiers,
.cd-sheet[data-stage="identity"] .cd-field:not(.cd-name):not(.cd-site) .cd-input,
.cd-sheet[data-stage="identity"] .cd-tiers { visibility: hidden; }
.cd-sheet[data-stage="waiting"] .cd-with-ic > .bk-ic { visibility: hidden; }
.cd-sheet[data-stage="waiting"] .cd-plans, .cd-sheet[data-stage="identity"] .cd-plans,
.cd-sheet[data-stage="waiting"] .cd-logo-acts { visibility: hidden; }
.cd-sheet[data-stage="waiting"] .cd-skel,
.cd-sheet[data-stage="identity"] .cd-field:not(.cd-name):not(.cd-site) .cd-skel {
  display: block; position: absolute; left: 0; right: 0; bottom: 0; top: 28px; padding: 14px 16px;
  border: 1px solid var(--border); border-radius: 10px; background:
    linear-gradient(var(--border), var(--border)) 16px 16px / 52% 9px no-repeat,
    linear-gradient(var(--border), var(--border)) 16px 34px / 34% 9px no-repeat, var(--panel);
}
.cd-sheet[data-stage="waiting"] .cd-name .cd-skel, .cd-sheet[data-stage="waiting"] .cd-site .cd-skel { background:
    linear-gradient(var(--border), var(--border)) 16px 50% / 50% 9px no-repeat, var(--panel); }
.cd-differ .cd-field .cd-skel { top: 0; }
.cd-sheet[data-reading="true"] .cd-skel { animation: cd-pulse 1.2s ease-in-out infinite; }
@keyframes cd-pulse { 50% { opacity: .55; } }
.cd-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 16px; }
.cd-foot-note { display: flex; align-items: center; gap: 10px; margin: 0; font-size: 14px; color: var(--muted); }
.cd-btns { display: flex; gap: 12px; margin-left: auto; }
.cd-cancel, .cd-save { min-height: 48px; padding: 0 24px; font-size: 15.5px; font-weight: 700; border-radius: 10px; }
.cd-cancel { color: var(--ink); background: var(--panel); border: 1px solid var(--border); }
.cd-save { color: var(--on-solid); background: var(--solid); border: 1px solid var(--solid); }
.cd-save:disabled { color: var(--muted); background: var(--panel-2); border-color: var(--border); cursor: default; }
@media (prefers-reduced-motion: reduce) {
  .cd-step[data-state="doing"] .cd-step-dot, .cd-sheet[data-reading="true"] .cd-skel { animation: none; }
}
@media (max-width: 820px) {
  .cd-card { padding: 22px 16px 16px; }
  .cd-body { grid-template-columns: minmax(0, 1fr); }
  .cd-left { border-right: 0; border-bottom: 1px solid var(--border); }
  .cd-row { grid-template-columns: minmax(0, 1fr); }
  .cd-id { grid-template-columns: minmax(0, 1fr); }
}

/* The memory: one card holding the toolbar, the kind tabs, the table and its foot,
   edge to edge as the mockup draws it — so the card has no padding of its own and
   each band brings its own. */
.bm-full { margin: 0 0 16px; }
.bm-card { padding: 0; overflow: hidden; }
.bm-bar { margin: 0; padding: 18px 20px 6px; }
.bk-search.bm-search { flex: 0 1 490px; }
.bk-select.bm-origin { flex: 0 1 250px; min-width: 180px; }
.bm-kinds { padding: 0 20px; }
.bm-card .bk-empty { margin: 20px; }
.bm-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.bm-table th { padding: 16px 12px 12px; text-align: left; font-size: 13.5px; font-weight: 500; color: var(--text); border-bottom: 1px solid var(--border); }
.bm-table td { padding: 14px 12px; font-size: 14.5px; color: var(--text); border-bottom: 1px solid var(--border); vertical-align: middle; }
.bm-table tr > :first-child { padding-left: 24px; }
.bm-table tr > :last-child { padding-right: 20px; }
.bm-col-kind { width: 160px; }
.bm-col-src { width: 210px; }
.bm-col-day { width: 150px; }
.bm-col-acts { width: 104px; }
.bm-text { overflow-wrap: anywhere; }
.bm-src-in { display: inline-flex; align-items: center; gap: 10px; }
.bm-day { white-space: nowrap; }
.bm-acts { text-align: right; white-space: nowrap; }
.bm-acts .bk-x { display: inline-grid; color: var(--text); }
.bm-acts .bk-x:disabled { opacity: .35; cursor: default; background: none; }
.bk-x.bm-drop:hover:not(:disabled) { color: var(--danger); }
/* The row being edited and its editor are one thing: tinted, and held together by the
   accent's bar down their left edge. */
.bm-row.on > td { background: var(--accent-soft); border-bottom-color: transparent; }
.bm-row.on > td:first-child, .bm-edit > td { box-shadow: inset 3px 0 0 var(--accent); }
.bm-close > .bk-ic { transform: rotate(180deg); }
.bm-edit > td { padding: 18px 20px 20px 24px; }
.bm-form {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(220px, 310px);
  grid-template-areas: "text kind" "from acts" "err err"; gap: 12px 24px; align-items: end;
}
.bm-f-text { grid-area: text; margin: 0; }
.bm-f-text textarea { resize: vertical; }
.bm-f-kind { grid-area: kind; align-self: start; margin: 0; }
.bm-from { grid-area: from; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 0; font-size: 13.5px; color: var(--muted); }
.bm-from:empty { display: none; }
.bm-from > .bk-ic { flex: none; color: var(--text); }
.bm-f-acts { grid-area: acts; display: flex; justify-content: flex-end; gap: 10px; }
.bm-f-acts > .btn { min-width: 104px; }
.bm-err { grid-area: err; margin: 0; }
.bm-err:empty { display: none; }
.bk-foot.bm-foot { margin: 0; padding: 16px 24px 18px; }
/* What the end-of-job pass proposed, above the table while something waits. */
.bm-suggest {
  margin: 10px 20px 14px; padding: 14px 16px; border: 1px solid var(--accent-line);
  border-radius: 12px; background: var(--accent-soft);
}
.bm-suggest-title { margin: 0 0 4px; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.bm-suggest-hint { margin: 0 0 10px; font-size: 13px; line-height: 1.45; color: var(--muted); }
.bm-suggest-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 10px;
  padding: 8px 0; border-top: 1px solid var(--accent-line);
}
.bm-suggest-text { font-size: 14px; color: var(--text); overflow-wrap: anywhere; }
.bm-suggest-replaces { display: block; margin-top: 2px; font-size: 12.5px; font-style: italic; color: var(--muted); }
@media (max-width: 640px) {
  .bm-suggest-row { grid-template-columns: minmax(0, 1fr) auto auto; }
  .bm-suggest-row > .bk-badge { grid-column: 1 / -1; justify-self: start; }
}
.bm-cost:not(:empty)::before { content: "·"; padding: 0 8px; }

@media (max-width: 1100px) {
  .bm-col-kind { width: 130px; }
  .bm-col-src { width: 170px; }
  .bm-col-day { width: 110px; }
  .bm-form { grid-template-columns: minmax(0, 1fr) minmax(180px, 240px); }
}
/* On a phone the table becomes stacked rows: the line on top with its two actions,
   and its kind, origin and day under it. The header stays, for a screen reader. */
@media (max-width: 720px) {
  .bm-bar, .bm-kinds { padding-left: 16px; padding-right: 16px; }
  .bm-table, .bm-table tbody { display: block; }
  .bm-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* A wrapping line rather than a grid: the words and the two actions fill the first
     line exactly, so the actions sit at the same place on every row, and the kind,
     the origin and the day wrap under them however long «Conversazione» is. A grid
     with a column each overflowed a 390px row by a different amount on every row. */
  .bm-table tr.bm-row {
    display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
    padding: 12px 16px; border-bottom: 1px solid var(--border);
  }
  .bm-table tr.bm-row > td { display: block; padding: 0; border: 0; }
  .bm-table tr.bm-row.on > td { background: none; box-shadow: none; }
  .bm-table tr.bm-row.on { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); border-bottom-color: transparent; }
  .bm-table tr.bm-row > .bm-text { flex: 1 1 calc(100% - 84px); min-width: 0; }
  .bm-table tr.bm-row > .bm-acts { flex: 0 0 72px; order: 1; }
  .bm-table tr.bm-row > .bm-kind, .bm-table tr.bm-row > .bm-src, .bm-table tr.bm-row > .bm-day { order: 2; }
  .bm-table tr.bm-edit, .bm-table tr.bm-edit > td { display: block; }
  .bm-edit > td { padding: 14px 16px 16px; border-bottom: 1px solid var(--border); }
  .bm-form { grid-template-columns: minmax(0, 1fr); grid-template-areas: "text" "kind" "from" "err" "acts"; }
  .bk-foot.bm-foot { padding: 14px 16px; }
}
@media (max-width: 560px) {
  /* «Categories» and «New category» share the row under the search rather than
     taking one each: a few pixels of padding are what separated them. */
  .bp-bar > .btn { flex: 1 1 auto; padding: 0 12px; }
}

/* ---- the "Add a product" panel ----
   It covers the page because it is a form filled in with care, not a field corrected
   in passing. The same scaffolding as the annotation editor: a darkened ground, a
   centred panel, a body that scrolls on its own. */
.pm {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center;
  padding: 20px; background: var(--overlay); backdrop-filter: blur(3px);
}
/* Without this line `hidden` hides nothing — `display: grid` wins — and the result is
   the worst possible one: an invisible veil laid over the whole app, taking every
   click. */
.pm[hidden] { display: none; }
.pm-panel {
  position: relative; display: flex; flex-direction: column; gap: 4px;
  /* The height is measured against the window, not the container: the grid row
     sizes itself on its content, so against it a percentage has nothing to resolve
     against and the panel grows off screen, taking the buttons with it. The 40px is
     the veil's padding. */
  width: min(560px, 100%); max-height: calc(100dvh - 40px); padding: 22px 24px 18px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 18px;
  box-shadow: var(--shadow-3);
}
.pm-panel h2 { margin: 0; font-size: 19px; }
.pm-panel > .hint { margin: 0 0 14px; }
.pm-close {
  position: absolute; top: 14px; right: 16px; width: 30px; height: 30px; padding: 0;
  display: grid; place-items: center; font-size: 20px; line-height: 1; cursor: pointer;
  color: var(--muted); background: transparent; border: 0; border-radius: 8px;
}
.pm-close:hover { color: var(--text); background: var(--panel-2); }

/* The three ways of filling it, in a single pill: they are alternatives, and in a
   horizontal row it reads that choosing one excludes the others. */
.pm-tabs { display: flex; gap: 4px; padding: 4px; background: var(--panel-2); border-radius: 11px; }
.pm-tab {
  flex: 1; padding: 8px 10px; cursor: pointer; font: inherit; font-size: 13px;
  color: var(--muted); background: transparent; border: 0; border-radius: 8px;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.pm-tab:hover:not(:disabled) { color: var(--text); }
.pm-tab.on { color: var(--on-solid); background: var(--solid); font-weight: 600; }
.pm-tab:disabled { cursor: default; opacity: .55; }
.pm-soon { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
/* `min-height: 0` is not a detail: without it a flex item does not shrink below its
   natural height, the form pushes the panel past the screen and the "Cancel / Save"
   buttons end up outside the window — that is, the card fills in and cannot be
   saved. What has to scroll is the body, not the page. */
.pm-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 14px 2px 4px; }
.pm-tabs, .pm-foot { flex: none; }
.pm-body label { display: block; margin: 0 0 12px; font-size: 12.5px; color: var(--ink-2); font-weight: 600; }
.pm-body label input, .pm-body label textarea { margin-top: 5px; font-weight: 400; }
.pm-req { color: var(--accent-ink); }

.pm-features { display: grid; gap: 7px; margin-bottom: 12px; }
.pm-feature { margin: 0; }

/* The photos: the thumbnails and, at the end, the dashed square for adding one. The
   upload box sits in line with what has already been uploaded rather than above it:
   it is the same place, before and after. */
/* Shared by the product card and the Characters page: the same object — a small,
   editable set of photos — doing the same job. Named for the product modal it was
   born in, and not renamed, because renaming it would touch both callers to say
   nothing new. */
.pm-shots { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; padding: 2px; border-radius: 10px; }
.pm-shots.over { box-shadow: 0 0 0 2px var(--accent); }
.pm-shot { position: relative; width: 78px; height: 78px; border-radius: 10px; overflow: hidden; border: 1px solid var(--border); }
.pm-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pm-shot-drop {
  position: absolute; top: 3px; right: 3px; width: 20px; height: 20px; padding: 0;
  display: grid; place-items: center; cursor: pointer; font-size: 14px; line-height: 1;
  color: var(--on-scrim); background: var(--scrim); border: 0; border-radius: 999px;
}
.pm-shot-add {
  width: 78px; height: 78px; display: grid; place-items: center; cursor: pointer;
  font-size: 20px; color: var(--muted); background: transparent;
  border: 1.5px dashed var(--border); border-radius: 10px;
}
.pm-shot-add:hover { border-color: var(--accent); color: var(--ink); }

.pm-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  padding-top: 12px; border-top: 1px solid var(--border);
}
.pm-foot .hint { margin: 0; flex: 1; min-width: 140px; }

/* ---- the product card by hand, as the owner's mockup draws it (2026-10-18) ----
   «Add product» over two columns: what the product is and what sells it on the left, its
   photos and its prices on the right, a rule between them. Scoped to the card: the Avatar
   page borrows `.pm-shot`, and keeps its own small tiles. */
#product-modal .pm-panel { width: min(980px, 100%); padding: 30px 34px 22px; gap: 6px; border-radius: 20px; }
#product-modal .pm-panel h2 { font-size: 28px; font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
#product-modal .pm-panel > .hint { margin: 2px 0 18px; font-size: 15.5px; color: var(--muted); }
#product-modal .pm-close { top: 22px; right: 22px; width: 36px; height: 36px; color: var(--ink); }
#product-modal .pm-tabs { align-self: flex-start; width: min(584px, 100%); padding: 4px; border-radius: 12px; }
#product-modal .pm-tab { padding: 10px 12px; font-size: 14.5px; font-weight: 600; border-radius: 9px; }
#product-modal .pm-tab .bk-ic { flex: none; }
#product-modal .pm-soon {
  padding: 2px 8px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border);
  font-size: 11px; text-transform: none; letter-spacing: 0; font-weight: 600;
}
#product-modal .pm-body { padding: 22px 2px 6px; border-top: 1px solid var(--border); margin-top: 18px; }
.pm-manual { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 344px); gap: 0 36px; }
.pm-manual[hidden] { display: none; }
.pm-col { min-width: 0; display: flex; flex-direction: column; gap: 14px; }
/* Each block keeps its own height: in a column the card caps, a block that shrank would be
   overlaid by the next — the photos by «Upload photos». */
.pm-col > * { flex-shrink: 0; }
.pm-media { padding-left: 36px; border-left: 1px solid var(--border); }
.pm-h { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
.pm-h-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.pm-count { font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.pm-sub { margin: -8px 0 0; font-size: 14px; color: var(--muted); }
#product-modal .pm-body label.pm-field { margin: 0; display: flex; flex-direction: column; gap: 7px; font-size: 14px; font-weight: 600; color: var(--ink); }
#product-modal .pm-body label.pm-field input, #product-modal .pm-body label.pm-field textarea, #product-modal .pm-body label.pm-field select {
  margin: 0; min-height: 44px; padding: 10px 14px; font-size: 15px; font-weight: 400;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
#product-modal .pm-body label.pm-field textarea { resize: vertical; line-height: 1.45; }
#product-modal .pm-name { resize: none !important; }
.pm-lab { display: inline-flex; gap: 4px; align-items: baseline; }
.pm-points { display: flex; flex-direction: column; gap: 12px; margin-top: 4px; padding-top: 22px; border-top: 1px solid var(--border); }
#product-modal .pm-features { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.pm-point { display: grid; grid-template-columns: 36px minmax(0, 1fr) 36px; align-items: center; gap: 12px; }
.pm-point-n {
  width: 36px; height: 36px; display: grid; place-items: center; border-radius: 999px;
  font-size: 14px; font-weight: 700; color: var(--ink); background: var(--panel-2); border: 1px solid var(--border);
}
#product-modal .pm-feature { min-height: 44px; padding: 10px 14px; font-size: 15px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); }
.pm-point-drop, .pm-add-point {
  cursor: pointer; font: inherit; background: transparent; border: 0;
}
.pm-point-drop { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 8px; color: var(--muted); }
.pm-point-drop:hover { color: var(--danger); background: var(--panel-2); }
.pm-add-point {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 10px; padding: 6px 4px;
  font-size: 15px; font-weight: 700; color: var(--accent-ink);
}
.pm-add-point[hidden] { display: none; }
.pm-add-point:hover { text-decoration: underline; }
/* The photos: the main one large with its badge and its «⋯», three more under it. */
/* One line, never wrapping: in a column that wraps, the row of places is given its height
   before its width, and the three tiles hang out of a row 20 pixels tall. */
#product-modal .pm-shots { display: flex; flex-direction: column; flex-wrap: nowrap; gap: 10px; margin: 0; padding: 0; }
.pm-media.over { box-shadow: 0 0 0 2px var(--accent); border-radius: 12px; }
#product-modal .pm-shot { width: auto; height: auto; border-radius: 12px; background: var(--panel-2); }
#product-modal .pm-shot-main { position: relative; aspect-ratio: 5 / 4; width: 100%; border-radius: 14px; }
#product-modal .pm-shot-main img { object-fit: contain; }
#product-modal .pm-shot-main:hover { transform: none; box-shadow: none; }
.pm-shot-badge {
  position: absolute; top: 12px; left: 12px; padding: 5px 11px; border-radius: 999px;
  font-size: 12.5px; font-weight: 700; color: var(--ink); background: var(--panel); box-shadow: var(--shadow-1);
}
.pm-shot-more {
  position: absolute; top: 10px; right: 10px; width: 34px; height: 34px; padding: 0; display: grid; place-items: center;
  cursor: pointer; color: var(--ink); background: var(--panel); border: 0; border-radius: 9px; box-shadow: var(--shadow-1);
}
/* Seven places under the main photo, four to a row: the card keeps eight. */
.pm-shot-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
#product-modal .pm-shot-row > .pm-shot, #product-modal .pm-shot-row > .pm-shot-add { width: 100%; height: auto; aspect-ratio: 1 / 1; cursor: pointer; }
#product-modal .pm-shot-add { width: 100%; height: auto; aspect-ratio: 1 / 1; border-radius: 12px; border: 1.5px dashed var(--border); background: transparent; }
/* The arrows through the photos in the large frame, as the result's are. */
#product-modal .pm-shot-nav {
  position: absolute; top: 50%; z-index: 2; width: 36px; height: 44px; padding: 0; display: grid; place-items: center;
  transform: translateY(-50%); cursor: pointer; color: var(--ink); background: var(--panel);
  border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-1);
}
#product-modal .pm-shot-nav:hover { border-color: var(--accent); }
#product-modal .pm-shot-nav.prev { left: 10px; }
#product-modal .pm-shot-nav.next { right: 10px; }
#product-modal .pm-shot-main:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
#product-modal button.pm-shot-setmain { cursor: pointer; border: 0; font: inherit; font-size: 12.5px; font-weight: 700; }
#product-modal button.pm-shot-setmain:hover { color: var(--accent-ink); }
/* The row: the one shown above is marked, and a tile is moved by the pointer, so a finger on
   it drags it rather than scrolling the dialog. */
#product-modal .pm-shot-row > .pm-shot { touch-action: none; }
#product-modal .pm-shot-row > .pm-shot.viewing { box-shadow: 0 0 0 2px var(--accent); }
#product-modal .pm-shot-row > .pm-shot.dragging { opacity: .45; cursor: grabbing; }
#product-modal .pm-shot.drop-at { box-shadow: 0 0 0 2px var(--accent), 0 0 0 5px var(--accent-soft); }
/* A photo the shop's CDN would not hand over: said, not drawn as a broken image. */
.pm-shot-broken { background: repeating-linear-gradient(45deg, var(--panel-2) 0 6px, var(--panel) 6px 12px); }
.pm-shot-broken img { visibility: hidden; }
#product-modal .pm-shot-add.pm-shot-main { aspect-ratio: 5 / 4; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; font-size: 14px; font-weight: 600; color: var(--muted); }
.pm-upload {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 44px;
  cursor: pointer; font: inherit; font-size: 15px; font-weight: 600; color: var(--ink);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
}
.pm-upload:hover:not(:disabled) { border-color: var(--ink); }
.pm-upload:disabled { cursor: default; opacity: .55; }
.pm-caption { margin: -6px 0 0; font-size: 13px; color: var(--muted); text-align: center; font-weight: 400; }
#product-modal label.pm-field .pm-caption { margin: 0; text-align: left; }
.pm-prices-block { display: flex; flex-direction: column; gap: 14px; margin-top: 4px; padding-top: 22px; border-top: 1px solid var(--border); }
.pm-prices { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: start; }
#product-modal .pm-body label.pm-small { font-size: 13px; }
#product-modal .pm-body label.pm-small input { min-height: 38px; padding: 8px 12px; font-size: 14px; }
#product-modal .pm-foot { margin-top: 10px; padding-top: 18px; }
.pm-required { margin: 0; font-size: 13.5px; color: var(--muted); }
.pm-required[hidden] { display: none; }
#product-modal .pm-foot .btn-row { margin-left: auto; display: flex; gap: 12px; }
#product-modal .pm-cancel, #product-modal .pm-save { min-height: 46px; padding: 0 22px; font-size: 15px; font-weight: 700; border-radius: 10px; }
#product-modal .pm-cancel { color: var(--ink); background: var(--panel); border: 1px solid var(--border); }
#product-modal .pm-save { display: inline-flex; align-items: center; gap: 10px; color: var(--on-solid); background: var(--solid); border: 1px solid var(--solid); }
#product-modal .pm-save:hover { background: var(--solid-2); }
#product-modal .pm-save[hidden] { display: none; }
@media (max-width: 760px) {
  #product-modal .pm-panel { padding: 22px 16px 16px; }
  .pm-manual { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .pm-media { padding-left: 0; border-left: 0; padding-top: 22px; border-top: 1px solid var(--border); }
}

/* The head of a screen that has one: a title and a line under it. Generations and the
   catalogue use it; Settings has its own, below, because its mockups draw a larger one
   with a breadcrumb over it. */
.view-head { margin: 0 0 16px; max-width: 720px; }
.view-head h1 { margin: 0; font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.view-head .hint { margin: 5px 0 0; font-size: 13px; }

/* ---------- Settings · frame, profile, preferences ----------
   The account's screen from the owner's mockups: the frame all four tabs share, and
   the two pages that are not about money (Profile, 18; Preferences, 17). The other two
   have the block below this one. What the mockups share with the Brand pages comes
   from the `.bk-*` block — the card and its head, the crumbs, the pink link, the two
   buttons, the select, the page's own dialog — and the tabs are the Brand's own
   `.brand-tab`. What is here is only what is Settings' alone.

   No token is added and no colour is a literal. Every wash travels with its own ink,
   the pairs measured in the `:root` comments and by the block below: `--ok` on
   `--ok-soft`, `--accent-ink` on `--accent-soft` (5.47:1), `--danger-ink` on
   `--danger-soft`, `--warn` on `--warn-soft`. The switch's knob is `--on-accent` on
   the accent (4.06:1) and `--muted` on `--panel-3` when off (5.3:1 light, 6.0:1 dark,
   computed for this rule), which clears the 3:1 a control needs.

   The theme pictures are the one place a colour must not follow the theme: the tile
   that shows the light one has to stay light while the page is dark. So they are
   drawn from the tokens that do not move between themes — `--on-scrim` and
   `--on-code-block` for the light one, `--code-block` for the dark, mixed for the
   lines between — which is a job those tokens already do for what sits on a picture.

   Widths are the screen's own (`settings` is a container), not the window's: the
   column beside it folds to 60px, and a page that read the window would lay two cards
   side by side in a gap meant for one. */
/* The rows are `max-content`, not `auto`, and the difference is the tab bar. The view is
   the scroller, so its height is the window's; a page taller than that leaves the grid
   no room to share out, and an `auto` row is then given only its item's minimum — which
   for the tab bar, a scroll container sideways, is zero. The bar vanished on
   Preferences and stayed on the Profile, which fits: measured, not supposed. */
.settings-view {
  container: settings / inline-size;
  display: grid; grid-template-columns: minmax(0, 1220px); grid-template-rows: repeat(3, max-content);
  align-content: start; padding: 10px 8px 36px;
}
/* The three rows of the frame, each on its own named track. Every page is on the
   third, named: three of the four are `hidden` at any moment, and a hidden grid child
   leaves the grid — with auto placement the page left showing would slide onto
   whatever track the hidden ones vacated, which is how the Studio's inspector once
   shipped thirteen pixels wide. */
.set-head { grid-row: 1; grid-column: 1; margin: 0 0 22px; }
.set-tabs { grid-row: 2; grid-column: 1; }
.settings-view > .set-panel { grid-row: 3; grid-column: 1; min-width: 0; }

.set-crumbs { margin: 0 0 12px; font-size: 13.5px; }
.set-crumb { color: var(--muted); white-space: nowrap; }
.set-crumbs .bk-crumb-here { font-weight: 600; }
/* The Brand's words-with-a-line, on a hairline that runs the width of the page. Out of
   width they scroll sideways rather than wrap, as the Brand's do. */
/* The tabs sit edge to edge, their own padding the space between them: eight labels with a gap as well came to 1037px in
   the 960px a 1280 window gives the page, and the last one was cut mid-word. */
.set-tabs {
  display: flex; gap: 0; margin: 0 0 26px; border-bottom: 1px solid var(--border);
  overflow-x: auto; scrollbar-width: none; overscroll-behavior-x: contain;
}
.set-tabs::-webkit-scrollbar { display: none; }
.set-tabs .brand-tab { padding: 0 12px; font-size: 15px; }
/* Out of width — always on a phone, on a narrow window too — the bar scrolls sideways inside its own box, and never the
   page: eight tabs wrapped onto three lines pushed the page under them out of the first screen. Each label stays whole
   (`.brand-tab` neither shrinks nor wraps), the open one is scrolled into the bar when it is opened (`tabBarReveal` in
   tab-bar.js), and each edge fades over 28px while there is more past it — the right while the row goes on, the left once
   it has been scrolled — so a label cut mid-word reads as a row that goes on. The fade is a mask on the bar's own content
   and paints no colour of its own, so it follows the theme. */
.set-tabs.set-tabs-more { -webkit-mask-image: linear-gradient(90deg, black calc(100% - 28px), transparent); mask-image: linear-gradient(90deg, black calc(100% - 28px), transparent); }
.set-tabs.set-tabs-back { -webkit-mask-image: linear-gradient(90deg, transparent, black 28px); mask-image: linear-gradient(90deg, transparent, black 28px); }
.set-tabs.set-tabs-more.set-tabs-back {
  -webkit-mask-image: linear-gradient(90deg, transparent, black 28px, black calc(100% - 28px), transparent);
  mask-image: linear-gradient(90deg, transparent, black 28px, black calc(100% - 28px), transparent);
}
@media (max-width: 600px) {
  .set-tabs .brand-tab { padding: 0 11px; font-size: 14.5px; }
}

/* Team, Sub-companies and White label, as tabs of Settings: each panel carries its old screen's class, for the rules and the
   container written for it, and gives back the padding that screen had round it, which the frame already draws. */
.settings-view > .set-panel:is(.team-view, .chl-view, .wl-view) { padding: 0; }
.set-panel .set-pane-head { margin: 0 0 22px; }
.set-panel .set-pane-head .set-pane-title { margin: 0; font-size: 22px; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.set-panel .set-pane-head .set-sub { margin: 6px 0 0; }
.team-view .team-exit { display: grid; gap: 10px; justify-items: start; }

/* ---- the cards and their rows ---- */
.set-card.bk-card { padding: 24px 26px; }
.set-card .bk-card-title { font-size: 21px; }
.set-card .bk-card-sub { margin: 5px 0 0; font-size: 14.5px; }
#set-prefs > .bk-card + .bk-card { margin-top: 20px; }
/* A row: a round glyph, what it is, and its control at the end. */
.set-line { display: flex; align-items: center; gap: 16px; padding: 18px 0; }
.set-line + .set-line { border-top: 1px solid var(--border); }
.set-line[hidden] + .set-line { border-top: 0; }
.set-line-wrap { flex-wrap: wrap; }
.set-ic {
  display: grid; place-items: center; flex: none; width: 48px; height: 48px; border-radius: 50%;
  color: var(--ink); background: var(--panel-2);
}
.set-ic.accent { color: var(--accent-ink); background: var(--accent-soft); }
.set-ic.danger { color: var(--danger-ink); background: var(--danger-soft); }
.set-line-text { display: flex; flex-direction: column; gap: 3px; flex: 1 1 200px; min-width: 0; }
.set-line-title { font-size: 15.5px; font-weight: 600; color: var(--ink); }
.set-line-lead { font-size: 15px; color: var(--text); }
.set-line-sub { font-size: 14px; color: var(--muted); }
.set-line-end { flex: none; margin-left: auto; }
.set-line-note { max-width: 240px; font-size: 13.5px; color: var(--muted); text-align: right; }
.set-kicker { font-size: 13.5px; color: var(--muted); }
.set-value-row { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; }
.set-value { font-size: 19px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
/* A state said as a pill with a dot: «Active», «Current session». */
.set-pill {
  display: inline-flex; align-items: center; gap: 7px; padding: 4px 12px; white-space: nowrap;
  font-size: 13px; font-weight: 500; border: 1px solid transparent; border-radius: 999px;
}
.set-pill::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.set-pill.ok { color: var(--ok); background: var(--ok-soft); border-color: var(--ok-line); }

/* ---- Profile ---- */
.set-profile { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.set-profile > .bk-card { margin: 0; }
.set-profile > .set-personal { grid-column: 1; grid-row: 1; }
.set-profile > .set-account { grid-column: 2; grid-row: 1; }
.set-photo {
  display: flex; align-items: center; gap: 22px; margin-top: 18px; padding: 4px 0 22px;
  border-bottom: 1px solid var(--border);
}
.side-avatar.set-avatar { width: 76px; height: 76px; font-size: 26px; }
.set-photo-lb { font-size: 15px; font-weight: 500; color: var(--text); }
.set-facts { margin: 0; }
.set-fact {
  display: grid; grid-template-columns: minmax(110px, 34%) minmax(0, 1fr); gap: 12px; align-items: baseline;
  padding: 16px 0; border-bottom: 1px solid var(--border);
}
.set-fact dt { font-size: 14px; color: var(--muted); }
.set-fact dd { margin: 0; font-size: 15px; color: var(--text); overflow-wrap: anywhere; }
.set-fact dd.set-empty { color: var(--muted); }
.set-locked { display: flex; align-items: center; gap: 10px; margin: 18px 0 0; font-size: 14px; color: var(--muted); }
.set-locked svg { flex: none; }
.set-account .set-line:first-of-type { margin-top: 10px; }
.set-box { margin-top: 18px; padding: 0 18px; border: 1px solid var(--border); border-radius: 12px; }
.set-box > .set-line { padding: 16px 0; }
.set-dots { font-size: 17px; line-height: 1.1; letter-spacing: 2px; color: var(--ink); }
.set-pw-err { margin: 10px 0 0; font-size: 13.5px; }

/* ---- Preferences ---- */
.bk-select.set-lang { width: min(240px, 100%); }
/* Light, dark, system: a picture of each, the radio and its name under it. */
.set-themes { display: grid; grid-template-columns: repeat(3, minmax(0, 164px)); gap: 14px; }
.set-theme {
  display: flex; flex-direction: column; gap: 10px; min-width: 0; margin: 0; padding: 10px 10px 12px;
  cursor: pointer; font-size: 14px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  transition: border-color .13s, background .13s;
}
.set-theme:hover { border-color: var(--accent-line); }
.set-theme:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 1px var(--accent); }
.set-theme:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.set-theme-name { display: flex; align-items: center; gap: 9px; min-width: 0; }
.set-theme-name input { flex: none; width: 17px; height: 17px; margin: 0; padding: 0; accent-color: var(--accent); cursor: pointer; }
.set-theme-name input:focus { outline: none; }
/* The window in miniature: a column down the left, a bar, a card, and the accent.
   «System» is the light one with the dark one laid over its right half. */
.set-theme-pic {
  --pic-ground: var(--on-scrim);
  --pic-side: var(--on-code-block);
  --pic-line: color-mix(in srgb, var(--on-code-block) 70%, var(--on-scrim));
  position: relative; display: block; height: 72px; overflow: hidden;
  background: var(--pic-ground); border: 1px solid var(--border); border-radius: 6px;
}
.set-theme-pic[data-pic="dark"], .set-theme-half {
  --pic-ground: var(--code-block);
  --pic-side: color-mix(in srgb, var(--on-code-block) 14%, var(--code-block));
  --pic-line: color-mix(in srgb, var(--on-code-block) 26%, var(--code-block));
}
.set-theme-half { position: absolute; top: 0; right: 0; bottom: 0; width: 50%; background: var(--pic-ground); }
.set-theme-pic::before, .set-theme-half::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 24%; background: var(--pic-side);
}
.set-theme-pic::after, .set-theme-half::after {
  content: ''; position: absolute; top: 16%; right: 10%; bottom: 16%; left: 34%;
  background:
    linear-gradient(var(--pic-line), var(--pic-line)) 0 0 / 60% 16% no-repeat,
    linear-gradient(var(--pic-line), var(--pic-line)) 0 38% / 100% 32% no-repeat,
    linear-gradient(var(--accent), var(--accent)) 0 100% / 30% 12% no-repeat;
}
/* The switch: a checkbox that says «switch» to a screen reader and draws one. */
.set-switch { position: relative; display: inline-block; flex: none; width: 52px; height: 30px; margin: 0; cursor: pointer; }
.set-switch input {
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; margin: 0; padding: 0;
  opacity: 0; cursor: inherit;
}
.set-switch-track {
  position: absolute; inset: 0; border-radius: 999px;
  background: var(--panel-3); border: 1px solid var(--border);
  transition: background .15s, border-color .15s;
}
.set-switch-track::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%;
  background: var(--muted); box-shadow: var(--shadow-1);
  transition: transform .15s, background .15s;
}
.set-switch input:checked + .set-switch-track { background: var(--accent); border-color: var(--accent); }
.set-switch input:checked + .set-switch-track::after { transform: translateX(22px); background: var(--on-accent); }
.set-switch input:focus-visible + .set-switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.set-switch:has(input:disabled) { cursor: not-allowed; }
.set-switch input:disabled + .set-switch-track { opacity: .45; }
@media (prefers-reduced-motion: reduce) {
  .set-switch-track, .set-switch-track::after, .set-theme { transition: none; }
}
/* How much of the open generation is safe: green when all of it is, amber while some
   of it waits, grey with nothing open. The glyph follows the state. */
.set-line:has(+ .set-archive:not([hidden])) { border-bottom: 1px solid var(--border); }
.set-archive {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; margin-top: 16px;
  padding: 12px 16px; font-size: 14.5px; color: var(--text);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
}
.set-archive[data-state="ok"] { background: var(--ok-soft); border-color: var(--ok-line); }
.set-archive[data-state="pending"] { background: var(--warn-soft); border-color: var(--warn-line); }
.set-archive-ic { flex: none; }
.set-archive-ok { color: var(--ok); }
.set-archive-wait { color: var(--warn); }
.set-archive:not([data-state="ok"]) .set-archive-ok,
.set-archive:not([data-state="pending"]) .set-archive-wait { display: none; }
/* «3 of 3 files» strong and «safe» regular, as drawn. */
.set-archive-said { flex: 1 1 180px; min-width: 0; }
.set-archive-said strong { font-weight: 700; }
.set-archive[data-state="empty"] .set-archive-said { color: var(--muted); }
.set-archive-acts { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 18px; margin-left: auto; }
.set-archive-note { margin: 14px 0 0; font-size: 13.5px; }
/* «Clear generation»: the danger's ink as a bordered button, as the mockup draws it —
   a red fill is kept for the question that follows, which is the real commitment. */
.btn.bk-btn.set-danger { color: var(--danger-ink); border-color: var(--danger-line); }
.btn.bk-btn.set-danger:hover { background: var(--danger-soft); border-color: var(--danger-ink); }
.set-foot { display: flex; align-items: center; gap: 10px; margin: 22px 2px 0; font-size: 14px; color: var(--muted); }
.set-foot .bk-ic { flex: none; }
.build.set-build { margin: 10px 2px 0; font-family: var(--mono); font-size: 11.5px; color: var(--muted); }

/* ---- as the width runs out ---- */
@container settings (max-width: 900px) {
  .set-profile { grid-template-columns: minmax(0, 1fr); }
  .set-profile > .set-personal, .set-profile > .set-account { grid-column: 1; grid-row: auto; }
}
@container settings (max-width: 720px) {
  .set-themes { grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; }
  .set-line-wrap > .set-line-end { margin-left: 0; }
}
@container settings (max-width: 560px) {
  .set-card.bk-card { padding: 18px 16px; }
  .set-line { flex-wrap: wrap; gap: 12px 14px; }
  .set-ic { width: 40px; height: 40px; }
  .set-line-end { margin-left: 0; }
  .bk-select.set-lang { width: 100%; }
  .set-line-note { max-width: none; text-align: left; }
  .set-box { padding: 0 14px; }
  .set-photo { gap: 16px; }
  .side-avatar.set-avatar { width: 64px; height: 64px; font-size: 22px; }
  .set-fact { grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .set-theme { padding: 8px 8px 10px; font-size: 13px; }
  .set-theme-name { gap: 6px; }
  .set-theme-pic { height: 56px; }
  .set-archive-acts { margin-left: 0; }
}

/* ---------- Settings · plan and credits ----------
   The two money tabs of Settings, as the owner's mockups draw them: «Plan and billing»
   (16) and «Credits and history» (19). `app/js/billing.js` and `app/js/credit-log.js`
   are the behaviour; this block is the look. What the mockups share with the Brand
   pages comes from the `.bk-*` block — the card, the search, the select, the two
   buttons, the pink link — and only what is theirs is here: the balance card, the plan
   cards and their period switch, and the history as a table.

   No token is added and no colour is a literal. Every fill travels with its ink:
   `--solid` / `--on-solid` for the balance card, `--accent` / `--on-accent` for the pink
   button and the chosen period, and each badge's wash with its own ink — measured on the
   white card, `--ok` on `--ok-soft` 5.9:1, `--accent-ink` on `--accent-soft` 5.47:1
   (the `:root` figure), `--violet-ink` on `--violet-soft` 6.5:1, `--warn` on
   `--warn-soft` 6.1:1; the dark theme's inks were stepped for its own card. Pink as
   text is `--accent-ink`, always.

   Both tabs lay out by the width they are given (`cred` and `bill` are containers),
   not the window's: the column beside them folds to 60px, and a page that read the
   window would put four plan cards in a gap meant for two. */

/* ---- «Credits and history»: the page, and the two cards on top ---- */
.cred-page { container: cred / inline-size; }
.cred-top { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 18px; margin: 0 0 18px; }
/* Each names its track: the balance card is `hidden` where the credit system is not
   installed, and `[hidden]` takes a child out of the grid — the plan card would slide
   into the wide column by accident rather than take the row on purpose. */
.cred-top > .cred-balance { grid-column: 1; }
.cred-top > .cred-plan { grid-column: 2; }
.cred-top > .cred-balance[hidden] + .cred-plan { grid-column: 1 / -1; }

/* Dark on the light theme, as drawn, and legible when the theme flips because it is the
   filled pair: on the dark theme `--solid` is the light fill, and the card is the one
   bright thing on the page rather than a dark card lost on a dark one. The glow and the
   rings are the accent, so an agency's skin shows through them rather than ours. */
.cred-balance {
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: center; gap: 20px; min-width: 0; min-height: 188px; padding: 28px 30px;
  border-radius: 16px; background: var(--solid); color: var(--on-solid);
}
.cred-balance::before, .cred-balance::after { content: ''; position: absolute; z-index: -1; pointer-events: none; }
.cred-balance::before {
  inset: 0;
  background:
    radial-gradient(70% 130% at 100% 0%, color-mix(in srgb, var(--accent) 38%, transparent) 0%, transparent 65%),
    radial-gradient(50% 90% at 86% 115%, color-mix(in srgb, var(--accent) 18%, transparent) 0%, transparent 70%);
}
/* The rings in the corner: one-pixel circles every sixteen, fading in and out again. */
.cred-balance::after {
  top: -150px; right: -150px; width: 360px; height: 360px; border-radius: 50%; opacity: .55;
  background: repeating-radial-gradient(circle, transparent 0 15px, color-mix(in srgb, var(--accent) 60%, transparent) 15px 16px);
  -webkit-mask-image: radial-gradient(circle, transparent 18%, black 40%, transparent 72%);
  mask-image: radial-gradient(circle, transparent 18%, black 40%, transparent 72%);
}
.cred-balance-ic {
  display: grid; place-items: center; flex: none; align-self: flex-start; width: 58px; height: 58px; border-radius: 14px;
  color: var(--on-solid); background: color-mix(in srgb, var(--on-solid) 14%, transparent);
}
.cred-balance-body { flex: 1; min-width: 0; }
.cred-balance-title { margin: 0; font-size: 17px; font-weight: 500; line-height: 1.3; color: inherit; }
.cred-balance-figure { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 12px; margin: 6px 0 0; }
.cred-balance-n {
  font-size: 50px; font-weight: 800; line-height: 1.05; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.cred-balance-unit { font-size: 22px; font-weight: 500; color: color-mix(in srgb, var(--on-solid) 82%, transparent); }
.cred-balance-sub { margin: 8px 0 0; font-size: 15px; color: color-mix(in srgb, var(--on-solid) 78%, transparent); }
.btn.bk-cta.cred-buy { flex: none; align-self: flex-end; min-height: 50px; padding: 0 24px; font-size: 16px; border-radius: 12px; }
/* The accent's own ring would vanish into the button it surrounds; the card's ink does not. */
.btn.bk-cta.cred-buy:focus-visible { outline: 2px solid var(--on-solid); outline-offset: 3px; }

.cred-plan { display: flex; flex-direction: column; justify-content: space-between; gap: 18px; min-width: 0; padding: 26px 28px; }
.cred-plan-row { display: flex; align-items: flex-start; gap: 18px; min-width: 0; }
/* The line between the plan and «Manage plan», only where the link is there to be divided from. */
.cred-plan:has(> .cred-plan-go:not([hidden])) > .cred-plan-row { padding-bottom: 20px; border-bottom: 1px solid var(--border); }
.cred-plan-ic {
  display: grid; place-items: center; flex: none; width: 58px; height: 58px; border-radius: 14px;
  color: var(--accent-ink); background: var(--accent-soft);
}
.cred-plan-text { min-width: 0; }
.cred-plan-title { margin: 0; font-size: 16px; font-weight: 500; line-height: 1.3; color: var(--text); }
.cred-plan-line { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; margin: 4px 0 0; }
.cred-plan-name { font-size: 34px; font-weight: 800; line-height: 1.1; letter-spacing: -.02em; color: var(--ink); overflow-wrap: anywhere; }
.bk-link.cred-plan-go { align-self: flex-start; font-size: 15px; }

/* «Active»: a plan is held. Green is the one colour here that says «in order». */
.cred-active {
  display: inline-flex; align-items: center; gap: 7px; padding: 4px 12px 4px 10px; white-space: nowrap;
  font-size: 14px; font-weight: 500; line-height: 1.3;
  color: var(--ok); background: var(--ok-soft); border: 1px solid var(--ok-line); border-radius: 999px;
}
.cred-active::before { content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }

/* ---- the history ---- */
.cred-history { padding: 26px 28px 22px; }
.cred-history-head { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: 14px 20px; margin: 0 0 18px; }
.cred-title { margin: 0; font-size: 26px; font-weight: 800; line-height: 1.2; letter-spacing: -.02em; color: var(--ink); }
.cred-sub { margin: 4px 0 0; font-size: 15px; color: var(--muted); }
.cred-bar { gap: 12px; }
.cred-bar > .cred-search { flex: 1 1 320px; }
.cred-bar > .cred-pick { flex: 1 1 220px; max-width: 340px; }
/* The month picker's calendar sits in front; its chevron keeps the place every select gives it. */
.cred-month-pick > .cred-lead { left: 14px; right: auto; }
.cred-month-pick > select { padding-left: 44px; }

/* A table, and a real one: five columns the mockup names, read by a screen reader as
   columns. Automatic layout, with the widths as the mockup's proportions, so a figure
   is never cut to make room — the activity is the column that wraps. */
.cred-table { width: 100%; border-collapse: separate; border-spacing: 0; }
.cred-table th {
  padding: 12px 14px; text-align: left; white-space: nowrap;
  font-size: 14px; font-weight: 600; color: var(--text); background: var(--panel-2);
}
.cred-table th:first-child { padding-left: 22px; border-radius: 10px 0 0 10px; }
.cred-table th:last-child { padding-right: 22px; border-radius: 0 10px 10px 0; }
.cred-table th.cred-c-act { width: 32%; }
.cred-table th.cred-c-model { width: 19%; }
.cred-table th.cred-c-when { width: 17%; }
.cred-table th.cred-c-kind { width: 16%; }
.cred-table th.cred-c-num { text-align: right; }
.cred-table td {
  padding: 10px 14px; vertical-align: middle;
  font-size: 15px; color: var(--text); border-bottom: 1px solid var(--border);
}
.cred-table td:first-child { padding-left: 22px; }
.cred-table td:last-child { padding-right: 22px; }
.cred-table tbody tr.cred-row:hover > td { background: color-mix(in srgb, var(--panel-2) 55%, transparent); }

.cred-act-in { display: flex; align-items: center; gap: 16px; min-width: 0; }
.cred-ico {
  display: grid; place-items: center; flex: none; width: 38px; height: 38px;
  color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.cred-body { display: flex; flex-direction: column; min-width: 0; }
.cred-what { font-size: 15px; font-weight: 600; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.cred-by { margin-top: 2px; font-size: 12.5px; line-height: 1.35; color: var(--muted); overflow-wrap: anywhere; }
/* Whose hand it was, in the accent's ink: the one line in the table that is not routine —
   the money was spent by somebody who is not the person reading. */
.cred-by.actor { color: var(--accent-ink); }
.cred-model { overflow-wrap: anywhere; }
.cred-model.none { color: var(--muted); }
.cred-day { display: block; white-space: nowrap; }
.cred-hour { display: block; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cred-kind {
  display: inline-block; padding: 4px 14px; white-space: nowrap;
  font-size: 13.5px; font-weight: 500; line-height: 1.35;
  color: var(--text); background: var(--panel-2); border-radius: 999px;
}
.cred-kind.k-refund, .cred-kind.k-dispute_restore, .cred-kind.k-refund_restore { color: var(--ok); background: var(--ok-soft); }
.cred-kind.k-topup, .cred-kind.k-agency_in { color: var(--accent-ink); background: var(--accent-soft); }
.cred-kind.k-plan { color: var(--violet-ink); background: var(--violet-soft); }
.cred-kind.k-adjustment { color: var(--warn); background: var(--warn-soft); }
.cred-kind.k-refund_reversal, .cred-kind.k-dispute_reversal { color: var(--warn); background: var(--warn-soft); }
/* The sign drives the colour and not the kind: an adjustment goes either way, and what is
   wanted at a glance is whether it came in or went out. */
.cred-num { text-align: right; white-space: nowrap; font-size: 16px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cred-num.in { color: var(--ok); }
.cred-num.out { color: var(--ink); }

/* A conversation: the whole line is the target, not a chevron the size of a full stop. */
.cred-open {
  width: 100%; margin: 0; padding: 0; text-align: left; cursor: pointer;
  font: inherit; color: inherit; background: none; border: 0;
}
.cred-open:hover .cred-what { color: var(--accent-ink); }
.cred-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 8px; }
.cred-chev { flex: none; color: var(--muted); transition: transform .15s ease; }
.cred-open[aria-expanded="true"] .cred-chev { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .cred-chev { transition: none; } }
.cred-table tr.cred-group.open > td { border-bottom-color: transparent; }
/* The turns, bracketed rather than merely indented: a rail down their left and a line
   closing under the last one, then room before the next movement — a shape that ends,
   so nobody has to count rows to find where the conversation stopped. */
.cred-table tr.cred-turns > td { padding: 0 22px 14px 76px; }
.cred-turn-list {
  margin: 0; padding: 2px 0 8px 14px; list-style: none;
  border-left: 1px solid var(--border); border-bottom: 1px solid var(--border); border-bottom-left-radius: 10px;
}
.cred-turn {
  display: grid; grid-template-columns: 56px minmax(0, 1fr) minmax(0, .8fr) auto; gap: 12px; align-items: baseline;
  padding: 6px 0; font-size: 13.5px; color: var(--muted);
}
.cred-turn-hour { font-variant-numeric: tabular-nums; }
.cred-turn-what { color: var(--text); overflow-wrap: anywhere; }
.cred-turn-model { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cred-turn-num { text-align: right; white-space: nowrap; font-weight: 600; font-variant-numeric: tabular-nums; }
.cred-turn.in .cred-turn-num { color: var(--ok); }

/* Loading, empty, failed: one line across the table, and the way on where there is one. */
.cred-table tr.cred-state > td { padding: 36px 22px; text-align: center; font-size: 14.5px; color: var(--muted); }
.cred-state-text { display: block; }
.bk-link.cred-retry { margin-top: 10px; }

.cred-tfoot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 16px; margin: 16px 0 0; }
.cred-count { margin: 0; font-size: 14.5px; color: var(--text); font-variant-numeric: tabular-nums; }
.cred-pages { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.cred-page-btn, .cred-page-now {
  display: grid; place-items: center; width: 42px; height: 42px; border-radius: 10px;
  font: inherit; font-size: 15px; font-weight: 700; color: var(--ink);
}
.cred-page-btn { padding: 0; cursor: pointer; background: var(--panel); border: 1px solid var(--border); }
.cred-page-btn:hover:not(:disabled) { border-color: var(--ink); }
.cred-page-btn:disabled { cursor: default; color: var(--muted); opacity: .5; }
.cred-page-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cred-page-now { background: var(--panel-2); font-variant-numeric: tabular-nums; }
.cred-capped { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.cred-capped:empty, .cred-status:empty { display: none; }
.cred-note { display: flex; align-items: center; gap: 12px; margin: 18px 0 0; padding: 0 6px; font-size: 14.5px; color: var(--text); }
.cred-note > .bk-ic { flex: none; color: var(--muted); }
.cred-status { margin: 10px 0 0; font-size: 13.5px; color: var(--text); }

@container cred (max-width: 820px) {
  .cred-top { grid-template-columns: minmax(0, 1fr); }
  .cred-top > .cred-plan { grid-column: 1; }
}
/* Narrow, the table becomes stacked rows: the activity and its figure on the first line,
   the type, the day and the model wrapping under it. A wrapping line and not a grid of
   columns, for the reason the memory table gives — a column each overflowed a 390px row
   by a different amount on every row. The header stays, for a screen reader. */
@container cred (max-width: 700px) {
  .cred-history { padding: 20px 16px 18px; }
  .cred-title { font-size: 22px; }
  .cred-bar > .cred-pick { max-width: none; }
  .cred-table, .cred-table tbody { display: block; }
  .cred-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* Each heading cell the same 1px, and not only the head round them: clipped, a row of five headings still laid out
     five headings wide past the right edge of a 390px window — `th.cred-c-kind` and `th.cred-c-num` out of the page. */
  .cred-table thead tr, .cred-table thead th { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; }
  /* The glyph hangs in a gutter of its own, so both lines start at the same edge whichever
     of the second line's facts a row has. */
  .cred-table tr.cred-row {
    position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 0 12px;
    padding: 14px 2px 14px 56px; border-bottom: 1px solid var(--border);
  }
  .cred-table tr.cred-row .cred-ico { position: absolute; left: 2px; top: 12px; }
  .cred-table tr.cred-row > td { display: block; padding: 0; border: 0; }
  /* The label takes what the figure leaves, and a line break of no height follows the
     figure, so a short fact of the second line — «Veo 3.1» — cannot climb up beside it,
     and a long figure squeezes the label rather than the page. Only here: on the wide
     table a pseudo-element on a row would be a cell. */
  .cred-table tr.cred-row::after { content: ''; order: 1; flex: 0 0 100%; height: 0; }
  .cred-table tr.cred-row > .cred-act { flex: 1 1 0; min-width: 0; }
  .cred-table tr.cred-row > .cred-num { flex: 0 0 auto; order: 1; font-size: 15px; }
  .cred-table tr.cred-row > .cred-type,
  .cred-table tr.cred-row > .cred-when,
  .cred-table tr.cred-row > .cred-model { order: 2; margin-top: 6px; font-size: 13px; color: var(--muted); }
  .cred-table tr.cred-row > .cred-model.none { display: none; }
  .cred-table .cred-when > .cred-day, .cred-table .cred-when > .cred-hour { display: inline; font-size: 13px; }
  .cred-table .cred-when > .cred-hour { margin-left: 6px; }
  .cred-kind { padding: 2px 10px; font-size: 12.5px; }
  .cred-table tr.cred-group.open { border-bottom-color: transparent; }
  .cred-table tr.cred-turns, .cred-table tr.cred-state { display: block; }
  .cred-table tr.cred-turns > td, .cred-table tr.cred-state > td { display: block; }
  .cred-table tr.cred-turns > td { padding: 0 2px 14px 30px; border-bottom: 1px solid var(--border); }
  .cred-turn { grid-template-columns: 48px minmax(0, 1fr) auto; }
  .cred-turn-model { display: none; }
  .cred-balance { flex-wrap: wrap; min-height: 0; padding: 22px; }
  .cred-balance-n { font-size: 38px; }
  .btn.bk-cta.cred-buy { width: 100%; }
  .cred-plan { padding: 20px; }
  .cred-plan-name { font-size: 28px; }
}

/* ---- «Plan and billing» ---- */
.bill-page { container: bill / inline-size; }
.bill-current { display: flex; align-items: center; flex-wrap: wrap; gap: 14px 20px; padding: 20px 26px; }
.bill-crown {
  display: grid; place-items: center; flex: none; width: 54px; height: 54px; border-radius: 50%;
  color: var(--accent-ink); background: var(--accent-soft);
}
.bill-current-text { min-width: 0; }
.bill-current-label { margin: 0; font-size: 14px; color: var(--muted); }
.bill-current-name { margin: 2px 0 0; font-size: 20px; font-weight: 700; line-height: 1.2; color: var(--ink); overflow-wrap: anywhere; }
.bill-current > .cred-active { margin-left: 8px; }
.bk-link.bill-manage { margin-left: auto; font-size: 15px; }

.bill-head { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 20px 40px; margin: 36px 0 28px; }
.bill-head-text { flex: 1 1 380px; min-width: 0; max-width: 560px; }
/* Narrow enough to break where the mockup breaks it: «Paghi per quello che / generi.» */
.bill-title { max-width: 470px; margin: 0; font-size: 40px; font-weight: 800; line-height: 1.08; letter-spacing: -.03em; color: var(--ink); }
.bill-sub { margin: 12px 0 0; font-size: 16px; line-height: 1.55; color: var(--text); }
.bill-period-box { display: grid; justify-items: end; gap: 12px; min-width: 0; }
.bill-period { display: inline-flex; gap: 4px; padding: 5px; background: var(--panel); border: 1px solid var(--border); border-radius: 999px; }
.bill-period-opt {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 46px; padding: 0 22px;
  cursor: pointer; font: inherit; font-size: 15px; font-weight: 500; color: var(--text);
  background: none; border: 0; border-radius: 999px;
}
.bill-period-opt:hover { background: var(--panel-2); }
.bill-period-opt[aria-pressed="true"] { font-weight: 600; color: var(--on-accent); background: var(--accent); }
.bill-period-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bill-save {
  padding: 3px 9px; white-space: nowrap; border-radius: 999px;
  font-size: 12px; font-weight: 600; color: var(--accent-ink); background: var(--accent-soft);
}
/* On the pink of the chosen period: the card's own surface and the ink that reads on it in
   both themes — the pairing the chips' count already uses on the same pink. */
.bill-period-opt[aria-pressed="true"] .bill-save { color: var(--accent-ink); background: var(--panel); }
.bill-note { margin: 0; max-width: 540px; font-size: 13.5px; color: var(--muted); text-align: right; }

.bill-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.bill-card {
  display: flex; flex-direction: column; min-width: 0; padding: 26px 26px 22px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px;
}
/* The one the mockup lifts: the accent's line round it, and its wash fading down from the top. */
.bill-card.featured {
  border: 1.5px solid var(--accent);
  background: linear-gradient(180deg, var(--accent-soft) 0%, transparent 55%), var(--panel);
}
/* Not priced: drawn as the one card whose edges are still to be agreed. */
.bill-card.custom { border-style: dashed; background: color-mix(in srgb, var(--panel-2) 45%, var(--panel)); }
.bill-kicker {
  display: flex; align-items: center; gap: 10px; margin: 0 0 10px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--accent-ink);
}
.bill-kicker::before { content: ''; flex: none; width: 22px; height: 1.5px; background: var(--accent); }
.bill-name { margin: 0; font-size: 30px; font-weight: 800; line-height: 1.1; letter-spacing: -.02em; color: var(--ink); }
/* It grows, so the prices under three descriptions of different lengths start on one line. */
.bill-desc { flex: 1 0 auto; margin: 12px 0 0; font-size: 15.5px; line-height: 1.5; color: var(--muted); }
.bill-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 10px; margin: 24px 0 0; }
.bill-amount { font-size: 44px; font-weight: 800; line-height: 1; letter-spacing: -.03em; color: var(--ink); font-variant-numeric: tabular-nums; }
.bill-per { font-size: 16px; color: var(--muted); }
.bill-billed { margin: 10px 0 0; font-size: 14.5px; color: var(--muted); }
.bill-facts { margin: 18px 0 22px; }
.bill-fact { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 12px 0; border-top: 1px solid var(--border); }
.bill-fact dt { font-size: 14.5px; color: var(--text); }
.bill-fact dd { margin: 0; white-space: nowrap; font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.btn.bill-go { width: 100%; min-height: 48px; margin-top: auto; border-radius: 999px; font-size: 15.5px; }
/* The plan already held: said, not offered — legible, because it is an answer and not a
   control somebody failed to reach. */
.bill-agreed {
  margin: 20px 0 0; padding-top: 16px; border-top: 1px solid var(--border);
  font-size: 12px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.bill-terms { display: grid; gap: 12px; margin: 14px 0 24px; padding: 0; list-style: none; }
.bill-terms > li { display: flex; align-items: center; gap: 12px; font-size: 15px; color: var(--text); }
.bill-terms .bk-ic { flex: none; color: var(--accent-ink); }

.bill-strip { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 0; margin-top: 18px; padding: 20px 26px; }
.bill-strip-title {
  margin: 0 28px 0 0; padding-right: 28px; border-right: 1px solid var(--border);
  font-size: 17px; font-weight: 700; color: var(--ink);
}
.bill-strip-links { display: flex; flex-wrap: wrap; gap: 12px 36px; }
.bill-strip-links > .bk-link { font-size: 15px; }
.bill-status { margin: 12px 0 0; font-size: 13.5px; color: var(--text); }
.bill-status:empty { display: none; }
/* The live parts: the cycle and renewal under the current plan, the warning about what a
   subscription's end takes, and the top-ups section. The warning is --warn on --warn-soft
   (the same pair the interface uses for a notice), never a literal colour. */
.bill-current-cycle, .bill-current-renews, .bill-current-ends, .bill-current-pending { margin: 4px 0 0; font-size: 14px; color: var(--text); }
.bill-current-ends { font-weight: 600; color: var(--ink); }
.bill-current-hint { margin: 4px 0 0; font-size: 13.5px; line-height: 1.45; color: var(--muted); }
.bill-warn {
  margin: 10px 0 0; max-width: 620px; padding: 9px 12px; font-size: 13.5px; line-height: 1.5;
  color: var(--warn); background: var(--warn-soft); border: 1px solid var(--warn-line); border-radius: 10px;
}
.bill-vat { margin: 14px 0 0; font-size: 13px; color: var(--muted); }
.bill-topups { margin-top: 18px; padding: 22px 26px; }
.bill-topups-title { margin: 0; font-size: 22px; font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
.bill-topups-sub { margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: var(--text); }
.bill-pockets { margin: 14px 0 0; font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.bill-topups .bill-warn { margin-top: 12px; }
.bill-rate { margin: 14px 0 0; font-size: 13.5px; color: var(--muted); }
.bill-sizes { display: flex; flex-wrap: wrap; gap: 12px; margin: 14px 0 0; padding: 0; list-style: none; }
.bill-size {
  display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 150px; padding: 12px 18px;
  border-radius: 14px;
}
.bill-size-n { font-size: 15.5px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.bill-size-price { font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }

@container bill (max-width: 1080px) {
  .bill-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container bill (max-width: 860px) {
  .bill-period-box { justify-items: start; }
  .bill-note { text-align: left; }
}
@container bill (max-width: 560px) {
  .bill-cards { grid-template-columns: minmax(0, 1fr); }
  .bill-title { font-size: 30px; }
  .bill-current, .bill-strip { padding: 18px; }
  .bk-link.bill-manage { margin-left: 0; }
  .bill-period-box { width: 100%; justify-items: stretch; }
  /* Three equal options, the saving under its name, so the switch fits a phone's width
     without scrolling sideways. */
  .bill-period { display: flex; border-radius: 18px; }
  .bill-period-opt { flex: 1 1 0; flex-direction: column; gap: 4px; min-width: 0; min-height: 58px; padding: 6px 4px; border-radius: 14px; font-size: 14px; }
  .bill-save { padding: 2px 7px; font-size: 11px; }
  .bill-strip-title { width: 100%; margin: 0; padding: 0; border-right: 0; }
}

.file-label { font-size: 12.5px; color: var(--muted); cursor: pointer; }
.file-label input[type="file"] { margin-top: 4px; font-size: 12px; }

/* ---------- Images inside the conversation ----------

   A row of pictures at one height, each at its own shape: `--r` is the shape asked for
   (`showInChat`), then the file's own once it has loaded, so the box is held before the
   bytes arrive and never grows under somebody reading the bottom. A picture is never
   wider than the column — a landscape in a narrow one shrinks, height and all — and a
   row of several scrolls sideways instead of stacking photos down the conversation; past
   the first, each leaves a sliver of the next in view to say there is more.

   The row's padding is the room the arrival's 8px slide and the hover's lift need: the
   row scrolls, so it clips whatever leaves its box. And it does not shrink: the log is a
   column flexbox, and a child that scrolls has no minimum height of its own, so in a long
   conversation the row is the one child the column could squeeze to fit.

   Its scrollbar is a hairline with no arrows. The standard pair (`scrollbar-width`,
   `scrollbar-color`) is only for a browser without the WebKit pseudo-elements: Chromium
   reads the pair first and ignores the rest, and with classic scrollbars it then draws
   its ◂ ▸ buttons at the two ends of a row that is a few pictures wide. */
.msg.shots {
  --shot-h: 220px;
  flex: 0 0 auto;
  max-width: 100%; align-self: stretch; background: transparent; border: 0; padding: 3px 1px 8px;
  display: flex; gap: 10px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
}
.msg.shots::-webkit-scrollbar { height: 6px; }
.msg.shots::-webkit-scrollbar-track { background: transparent; }
.msg.shots::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; }
.msg.shots:hover::-webkit-scrollbar-thumb { background: var(--muted); }
@supports not selector(::-webkit-scrollbar) {
  .msg.shots { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
}
.shot-in-chat {
  margin: 0; flex: 0 0 auto; min-width: 0; scroll-snap-align: start;
  width: min(calc(var(--shot-h) * var(--r, 1)), 100%);
  animation: shot-in .28s ease-out both;
}
.shot-in-chat.settled { animation: none; }
.msg.shots:has(> .shot-in-chat + .shot-in-chat) > .shot-in-chat { width: min(calc(var(--shot-h) * var(--r, 1)), 86%); }
.shot-in-chat img {
  display: block; width: 100%; height: auto; aspect-ratio: var(--r, 1); object-fit: cover;
  border-radius: 8px; border: 1px solid var(--border); background: var(--panel-2);
  cursor: zoom-in; transition: transform .14s, box-shadow .14s;
}
.shot-in-chat img:hover { transform: translateY(-2px); box-shadow: var(--shadow-1); }
/* A picture deleted for good: its box stays, so the conversation does not jump, and says so. */
.shot-in-chat.removed { position: relative; }
.shot-in-chat.removed img { visibility: hidden; }
.shot-removed {
  position: absolute; inset: 0 0 auto 0; aspect-ratio: var(--r, 1); display: grid; place-items: center;
  font-size: 12.5px; color: var(--muted); background: var(--panel-2); border: 1px dashed var(--border); border-radius: 8px;
}
.shot-in-chat figcaption {
  margin-top: 5px; font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@keyframes shot-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (max-width: 700px) {
  .msg.shots { --shot-h: 180px; }
}
@media (prefers-reduced-motion: reduce) {
  .shot-in-chat { animation: none; }
  .shot-in-chat img:hover { transform: none; }
}

/* ---------- Collapsible prompt ---------- */

/* We draw the triangle ourselves: the native one cannot be coloured and disappears
   on a light ground. */

/* ---------- Autopilot / PRO ---------- */
.mode-switch { display: flex; gap: 4px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px; padding: 3px; }
.mode {
  background: transparent; border: 0; color: var(--muted); font: inherit; font-size: 12.5px;
  padding: 5px 12px; border-radius: 6px; cursor: pointer;
}
.mode:hover { color: var(--text); }
.mode.on { background: var(--panel); color: var(--text); font-weight: 600; box-shadow: var(--shadow-1); }
/* The chosen mode is the accent rather than a raised white pill: «which mode am I
   in» should be answerable from across the desk, and beside Send it has to hold its
   own next to a primary button. It was written for the head and moved with the
   switch — the reason was never about the head. */
.composer-bar .mode.on { background: var(--accent-soft); color: var(--accent-ink); box-shadow: none; }

/* ---------- Characters ---------- */
/* The whole width, like every Brand tab: the grid and the side panel share the row. */
.portraits { display: block; min-width: 0; }
.pt-preview { margin: 12px 0 0; }
.pt-preview:empty { display: none; }
.pt-preview img { width: 220px; aspect-ratio: 1; object-fit: cover; border-radius: 10px; border: 1px solid var(--border); display: block; }
.pt-preview figcaption { font-size: 11.5px; color: var(--muted); margin-top: 5px; }
.pt-result {
  margin-top: 12px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 12px; border-radius: 9px;
  background: var(--ok-soft); border: 1px solid var(--ok-line);
}
.pt-id { font-family: var(--mono); font-size: 12px; color: var(--ink-2); }

/* ---------- Brand · characters ----------
   The tab as the owner's mockup draws it: a grid of faces, the picked one drawn again
   underneath with its photos, and the «New character» panel beside them. The header,
   the search, the chips, the card, the side panel, the dot and the drop zone are the
   shared `.bk-*` pieces; what is here is only what a face needs that a product does
   not. */

/* Two fifths of the row for the side panel, which is what the mockup gives it: it
   holds a drop zone with two buttons side by side, and the shared 380px stacks them. */
.bf-split { --bk-aside: clamp(360px, 40%, 560px); }

/* The toolbar: the search as wide as the mockup draws it, the three chips beside it. */
.bf-bar .bk-search { max-width: 420px; }
.bf-bar .bk-chips { margin: 0; }

/* A card is a face: the photo edge to edge and square, which with the three lines
   under it makes the tall card the mockup draws. The whole card selects; the name is
   the button that lets the keyboard do the same, and it lends the card its focus. */
.bf-grid { --bk-min: 200px; }
.bf-card { position: relative; padding: 0; overflow: hidden; cursor: pointer; --bk-ratio: 1 / 1; }
.bf-card .bk-media { border-radius: 0; }
.bf-card .bk-media > .bk-letter { font-size: 56px; }
.bf-card > p { padding: 0 14px; }
.bf-card .bk-item-name { margin-top: 12px; }
.bf-state { margin: 8px 0 14px; }
.bf-pick {
  display: block; max-width: 100%; padding: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font: inherit; color: inherit; text-align: left; cursor: pointer; background: none; border: 0;
}
.bf-pick:focus-visible { outline: none; }
.bf-card:has(.bf-pick:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Written the way the name field teaches it, «Giulia — presenter»: capitalised on the
   card as the mockup has it, without touching the name that was registered. */
.bf-role::first-letter { text-transform: uppercase; }
.bf-empty { margin: 0; }
.bf-empty.err { color: var(--danger-ink); }

/* The picked character, again and larger. */
.bf-detail-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px 18px; flex-wrap: wrap; margin: 0 0 18px; }
.bf-detail-head > div { flex: 1 1 260px; min-width: 0; }
.bf-detail-head > .btn { flex: none; }
.bf-detail-name {
  display: flex; align-items: center; gap: 6px 14px; flex-wrap: wrap; margin: 0;
  font-size: 22px; font-weight: 700; line-height: 1.2; letter-spacing: -.01em; color: var(--ink); overflow-wrap: anywhere;
}
.bf-detail-state { font-size: 13px; font-weight: 400; letter-spacing: 0; }
.bf-detail-about { margin-top: 6px; font-size: 14.5px; }
.bf-detail-label { margin: 0 0 10px; font-size: 14px; font-weight: 600; color: var(--text); }
.bf-photos { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 140px)); gap: 12px; }
.bf-photos > img {
  display: block; width: 100%; aspect-ratio: 5 / 4; object-fit: cover;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
}

/* The side panel: one column with one space between its lines, so the form reads as
   the mockup's list of fields. While it sits beside the grid it stays in view, and a
   panel taller than the screen scrolls inside itself — otherwise «Send for approval»,
   its last line, would be below the edge for as long as the panel is stuck there.

   The line is a whole 20px — what 13.5px type at 1.5 draws anyway, rounded — because
   a scroll container is sized in whole pixels and its lines are not: with quarter
   pixels in every label the panel came out a pixel and a half shorter than what it
   holds, and that pixel and a half drew a scrollbar on a panel with nothing to
   scroll. Measured in Chrome at 1584×992: 756px given, 757.5px held. */
.bf-aside { max-height: calc(100vh - var(--bk-sticky, 16px) - 16px); overflow-y: auto; line-height: 20px; }
.bf-aside > * { margin: 0; }
.bf-aside > * + * { margin-top: 16px; }
/* Its two full-width buttons as blocks: an inline box in a block container sits on a
   line, and the line adds the space under a letter's descender to the button's. */
.bf-aside > .btn { display: flex; }
.bf-status:empty { display: none; }

/* The drop zone holds every way a photo comes in: the photos already in, the
   invitation and the real limits, the two buttons, the link to a hosted image. */
.bf-drop { gap: 8px; padding: 22px 18px 16px; }
.bf-drop.dropping { border-color: var(--accent); background: var(--accent-soft); }
.bf-drop-ic { color: var(--ink-2); }
.bf-drop-limits { font-size: 12.5px; color: var(--muted); }
.bf-shots { justify-content: center; margin: 0 0 6px; }
.bf-drop-btns {
  justify-self: stretch; display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; margin-top: 10px;
}
/* Side by side as the mockup draws them, and allowed to wrap rather than overflow: at
   the panel's narrowest a longer language's «Choose from the Studio» needs two lines. */
.bf-drop-btns > .btn { min-width: 0; padding: 0 12px; white-space: normal; }
.bf-url {
  justify-self: start; display: flex; align-items: center; gap: 4px 6px; flex-wrap: wrap;
  margin: 6px 0 0; font-size: 13.5px; text-align: left; color: var(--muted);
}
/* Ink and underlined rather than the accent: in the mockup it is the quiet road. */
.bf-url .bk-link { font-weight: 500; color: var(--text); }
.bf-url-text { text-decoration: underline; text-underline-offset: 2px; }
.bf-url-row { justify-self: stretch; }
.bf-url-row > input { margin: 0; }

/* «Create a portrait from the photos»: full width and grey, the second road; the pink
   button under it is the tab's main verb. */
.btn.bf-generate {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 48px;
  font-size: 14.5px; font-weight: 600; color: var(--text); background: var(--panel-2); border-color: var(--border); border-radius: 10px;
}
.btn.bf-generate > .bk-ic { flex: none; }
.bf-aside .btn.bk-cta.bk-wide { min-height: 48px; font-size: 15px; }

@media (max-width: 1100px) {
  /* Under the grid rather than beside it, the panel is part of the page again: no
     height of its own and nothing to scroll inside it. */
  .bf-aside { max-height: none; overflow: visible; }
}
@media (max-width: 560px) {
  /* Two faces a row on a phone: one would be a 250px square per character, and the
     grid is for telling them apart at a glance. */
  .bf-grid { --bk-min: 110px; }
  .bf-bar .bk-chip { padding: 0 11px; }
  .bf-card > p { padding: 0 10px; }
  .bf-card .bk-media > .bk-letter { font-size: 40px; }
  .bf-bar .bk-search { max-width: none; }
  .bf-detail-name { font-size: 19px; }
}

/* ---------- Brand · voices and templates ----------
   The Voices and Template tabs, drawn with the shared `.bk-*` pieces and adding only
   what is theirs: a voice row with its player, the three roads of «Create a voice», a
   template's format tile and the detail beside it. Every colour is a token, every fill
   travels with its ink, and each grid that can lose a child names its own tracks. */

/* ---------- Voices: the page ---------- */
.voices .bk-split { --bk-aside: clamp(340px, 30vw, 440px); }
.bv-off { margin: 0 0 18px; }
.bv-count { font-weight: 500; color: var(--muted); }
.bv-find { display: block; margin: 0 0 6px; }
/* The list is the container its rows measure: the room a row has depends on whether
   the side panel is open, not on the window. */
.bv-list { display: flex; flex-direction: column; min-width: 0; container: bv-list / inline-size; }
.bv-list > .bk-empty { margin: 12px 0 0; }
.bv-mine .hint:empty, .bv-catalogue .hint:empty { display: none; }

/* A voice as a row: the letter, the name over its line, the player, the length and the
   «⋯» — or, on a result, «+ Save». The player's three pieces each name their area, and
   so does the button that stands where they would on a voice with no sample yet. The
   waveform's track is a share of the list and never more than 180px, so the name is
   the one that grows and never the one squeezed. */
.bv-row {
  display: grid; align-items: center; gap: 6px 14px;
  grid-template-columns: 40px minmax(0, 1fr) 36px min(26cqi, 180px) 38px auto;
  grid-template-areas: "av text play wave dur end";
  padding: 12px 0; border-top: 1px solid var(--border);
}
.bv-row:first-child { border-top: 0; }
.bv-row > .bv-av { grid-area: av; --bk-letter: 40px; }
.bv-row > .bv-text { grid-area: text; min-width: 0; }
.bv-row > .bv-play { grid-area: play; }
.bv-row > .bv-wave { grid-area: wave; }
.bv-row > .bv-dur { grid-area: dur; }
.bv-row > .bk-more, .bv-row > .bv-save { grid-area: end; justify-self: end; }
.bv-row > .bv-sample, .bv-row > .bv-listen { grid-area: play-start / play-start / dur-end / dur-end; justify-self: start; max-width: 100%; }
.bv-name { display: flex; align-items: center; gap: 8px; min-width: 0; margin: 0; font-size: 14.5px; font-weight: 600; color: var(--ink); }
.bv-name > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bv-badge { flex: none; padding: 1px 8px; font-size: 11.5px; }
.bv-meta { margin: 2px 0 0; font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The round ▶: an outline at rest and the accent's fill while it plays, with the
   accent's own ink on it so the glyph holds in both themes. */
.bv-play {
  display: grid; place-items: center; width: 36px; height: 36px; padding: 0; cursor: pointer;
  color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 50%;
}
.bv-play:hover { border-color: var(--ink); }
.bv-play.on { color: var(--on-accent); background: var(--accent); border-color: var(--accent); }
.bv-play:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Two copies of the same bars: the whole in grey, and the part already played in the
   accent, uncovered from the left as the sample plays. A mark and not text, so the
   accent's 4.18:1 on white clears the 3:1 a graphic needs. */
.bv-wave { position: relative; display: block; min-width: 0; height: 26px; color: var(--muted); }
.bv-wave > svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.bv-wave > svg:first-child { opacity: .45; }
.bv-wave > svg.played { color: var(--accent); clip-path: inset(0 calc(100% - var(--bv-at, 0%)) 0 0); }
.bv-dur { font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--muted); text-align: right; white-space: nowrap; }
.bv-price { font-weight: 500; white-space: nowrap; }
.btn.bk-btn.bv-sample, .btn.bk-btn.bv-listen, .btn.bk-btn.bv-save { gap: 6px; }
.btn.bk-btn.bv-save:disabled { opacity: 1; color: var(--ok); border-color: var(--ok-line); background: var(--ok-soft); cursor: default; }

/* ---------- Voices: the catalogue ---------- */
/* Bases that add up under the main column's width with the side panel open, so the
   four controls stay one line there and wrap only on a narrow screen. */
.bv-cat-bar > .bk-search { flex: 1 1 200px; }
.bv-cat-bar > .bk-select { flex: 0 1 168px; }
.btn.primary.bv-go { min-height: 44px; padding: 0 20px; border-radius: 10px; font-size: 14px; }
/* The thirty presets as cards: the letter beside the name, its descriptor and what it is good
   for; then the ▶ (or the player once heard) and «+ Save» under them. */
.bv-list.bv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 12px; margin: 4px 0 0; }
.bv-grid > .bv-row {
  grid-template-columns: 40px minmax(0, 1fr) 38px auto;
  grid-template-areas: "av text text text" "play wave dur end";
  align-content: start; gap: 12px 10px; padding: 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel);
}
.bv-grid > .bv-row:first-child { border-top: 1px solid var(--border); }
.bv-grid > .bv-row > .bv-av { align-self: start; }
.bv-grid > .bv-row > .bv-play { justify-self: start; }
.bv-use { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45; color: var(--text); }
/* «Direct a voice»: the moments a line can hold, as chips that write their tag where the cursor
   is, and the three quick choices of how it is said, side by side in the panel. */
.bv-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: -6px 0 6px; }
.bv-road > .bv-caps { margin: 0 0 14px; }
.bv-direct { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }

/* ---------- Voices: «Create a voice» ----------
   Beside the lists it stays in view, and taller than the screen it scrolls inside
   itself: the road's last line is the one that saves. The room is the window less
   where the panel sticks (under the frame) and the page's breathing space below it. */
.bv-make { max-height: calc(100vh - var(--bk-sticky, 16px) - 16px); overflow-y: auto; }
.bv-roads { margin: 0 0 18px; }
/* Three roads in one strip, so a long name wraps inside its segment rather than
   pushing the strip wider than the panel. */
.bv-roads > button { padding: 4px 8px; line-height: 1.25; }
.bv-road .bk-select { display: block; }
.bv-road textarea { resize: vertical; }
.bv-custom { margin: -8px 0 14px; font-size: 13px; }
.bv-custom summary { cursor: pointer; color: var(--muted); }
.bv-custom summary:hover { color: var(--text); }
.bv-custom .bk-field { margin: 8px 0 0; }
.bv-road > .hint { margin: 10px 0 0; }
.btn.bk-btn.bv-file { margin: 0 0 16px; }
/* The text to read sits in its own box, at reading size: it is read aloud, from a
   little further away than a hint, and a hint's grey is the wrong colour for it. */
.bv-script {
  margin: 0 0 14px; padding: 12px 14px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 12px;
}
.bv-script p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--text); }
.bk-label.bv-script-title { display: block; margin: 0 0 6px; }
/* One under the other: the panel is narrow, and two labels this long side by side ran past its edge. */
.bv-take { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; margin: 0 0 16px; }
.bv-take .btn.bk-btn.bv-file { width: 100%; min-width: 0; margin: 0; justify-content: center; white-space: normal; }
.bv-take .btn.bv-file[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
.bv-road > .bv-off { margin: 0 0 14px; }
.bv-road > .bv-formats { margin: -8px 0 14px; }
.bv-take-play { display: block; width: 100%; margin: 0 0 16px; }
.bv-consent { margin: 0 0 16px; }
.bv-player {
  display: grid; grid-template-columns: 36px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  margin: 14px 0 0; padding: 10px 12px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
}
.bv-keep { margin: 16px 0 0; }
.btn.primary.bv-keep-go { min-height: 42px; border-radius: 10px; font-size: 14px; }

/* The player under the name, on a line of its own, when the list is narrow — a phone,
   or a laptop with the side panel open: beside the name there is no room for either. */
@container bv-list (max-width: 480px) {
  .bv-row {
    grid-template-columns: 40px minmax(0, 1fr) auto;
    grid-template-areas: "av text end" "play wave dur";
  }
}
@media (max-width: 560px) {
  .bv-cat-bar > .bk-select { flex: 1 1 140px; }
  .btn.primary.bv-go { flex: 1 1 100%; }
}

/* ---------- Template: the grid ----------
   A template has no picture of its own — keeping one would mean storing frames of the
   video it came from, and a frame would say «this template is that product», which is
   exactly what a template is not. So a card draws its shape: a rectangle of its aspect
   on the ground a photograph would have, with the duration and the aspect as badges. */
.bt-split { --bk-aside: clamp(340px, 32vw, 480px); }
.bt-bar > .bk-search { flex: 1 1 240px; }
.bt-bar > .bk-select { flex: 0 1 260px; }
.bt-view { flex: none; }
.bt-view > button { display: grid; place-items: center; width: 44px; padding: 0; }
.bt-grid { --bk-min: 210px; }
.bt-grid > .bk-empty { grid-column: 1 / -1; }
.bt-card { position: relative; }
.bt-open {
  display: block; width: 100%; margin: 0; padding: 0; cursor: pointer; text-align: left;
  font: inherit; color: inherit; background: none; border: 0; border-radius: 10px;
}
.bt-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.bt-tile { display: block; --bk-ratio: 5 / 4; }
.bt-frame {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: grid; place-items: center; color: var(--muted);
  background: var(--panel); border: 1.5px solid var(--border); border-radius: 6px; box-shadow: var(--shadow-1);
}
.bt-frame.free { border-style: dashed; box-shadow: none; }
.bt-tile > .bk-badge { position: absolute; padding: 2px 8px; font-size: 12px; font-weight: 600; }
.bt-tile > .bt-dur { top: 10px; right: 10px; }
.bt-tile > .bt-ar { left: 10px; bottom: 10px; gap: 5px; }
.bt-text { display: block; min-width: 0; padding-right: 40px; }
.bt-text > span { display: block; }
.bt-card > .bk-more { position: absolute; right: 12px; bottom: 16px; }
.bt-text > .bt-line { display: none; }
/* The list: the tile shrinks to a thumbnail beside the name, and the badges it has no
   room for are said on a line under it instead. */
.bt-grid.list { grid-template-columns: minmax(0, 1fr); gap: 10px; }
.bt-grid.list .bt-open { display: grid; grid-template-columns: 104px minmax(0, 1fr); align-items: center; gap: 16px; }
.bt-grid.list .bt-tile > .bk-badge { display: none; }
.bt-grid.list .bt-text .bk-item-name { margin: 0; }
.bt-grid.list .bt-text > .bt-line { display: block; }
.bt-grid.list .bt-card > .bk-more { top: 50%; bottom: auto; transform: translateY(-50%); }

/* ---------- Template: the detail ---------- */
.bt-detail { max-height: calc(100vh - var(--bk-sticky, 16px) - 16px); overflow-y: auto; }
/* The beats as three frames of text: the opening, the one in the middle, the closing.
   As many columns as there are frames, so a two-beat template is two wide ones. */
.bt-frames { display: grid; grid-template-columns: repeat(var(--bt-n, 3), minmax(0, 1fr)); gap: 10px; margin: 0 0 18px; }
.bt-frames > .bt-frames-note { grid-column: 1 / -1; margin: 0; padding: 14px; background: var(--panel-2); border-radius: 10px; }
.bt-shot { min-width: 0; margin: 0; }
.bt-shot-card {
  display: flex; flex-direction: column; gap: 6px; aspect-ratio: 3 / 4; padding: 10px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 10px;
}
/* The ink variant, because the magenta itself is under AA as text: 5.8:1 on --panel-2
   in the light theme, measured. */
.bt-shot-when { font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--accent-ink); }
.bt-shot-what {
  margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--text); overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 8; -webkit-box-orient: vertical; overflow: hidden;
}
.bt-shot figcaption { margin: 6px 0 0; font-size: 13px; color: var(--text); }
.bt-facts { margin: 0 0 18px; padding: 16px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.bt-facts dd { min-width: 0; overflow-wrap: anywhere; }
.bt-facts dd > span { display: block; }
.bt-facts dd > span + span { margin-top: 3px; }
.bt-product { margin: 0 0 14px; }
.bt-product .bk-select { display: block; }
.btn.bk-cta.bt-use { min-height: 48px; font-size: 15px; }
.bt-keep { margin: 10px 0 0; text-align: center; font-size: 13px; color: var(--muted); }

/* ---------- Template: «Create from a video» ---------- */
.bt-sheet-status:empty { display: none; }
.bt-projects { display: flex; flex-direction: column; gap: 6px; max-height: 46vh; overflow-y: auto; }
.bt-project {
  display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; cursor: pointer; text-align: left;
  font: inherit; color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.bt-project:hover { border-color: var(--accent-line); }
.bt-project:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bt-project[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.bt-project-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 600; }
.bt-project-when { font-size: 12.5px; color: var(--muted); }
.bt-sheet-form { margin: 14px 0 0; }

@media (max-width: 1100px) {
  /* Under the lists rather than beside them, the two panels scroll with the page:
     a box that scrolls inside a page that scrolls is two scrollbars for one read. */
  .bv-make, .bt-detail { max-height: none; overflow: visible; }
}
@media (max-width: 560px) {
  .bt-bar > .bk-select { flex: 1 1 160px; }
  .bt-frames { gap: 6px; }
  .bt-shot-card { padding: 8px; }
}

/* ---------- the door ----------

   It covers everything, and it is not a separate page: the same screen serves at
   startup and mid-work, when a session expires and the request has to be remade
   instead of lost. So it is a veil over the app, not a view inside it.

   Two halves. The left one is the form, on the theme's own card, so it follows the
   theme like everything else; the right one is a photograph, which is the same in
   both themes because a photograph did not change when the menus did — so it is
   drawn with the tokens made for things laid on an image (`--scrim`, `--on-scrim`).
   Under 900px the photograph goes and the form is the whole screen.

   `.gate-card` is the whole left half and not a box inside it, and that is the
   white-label check's doing as much as the design's: the smoke reads the logo, the
   agency's word and the password field *inside* `.gate .gate-card`, and the logo
   sits at the top of this half, outside the form. */
/* The studio stays out of sight from somebody signed out until the door has decided.
   The page is the studio's markup from its first frame, and the door is drawn over it
   only once `/api/session` has answered — so somebody signed out saw the studio for a
   moment and then the sign-in, which reads as being thrown out of it. `data-door` is
   put on <html> by the head of index.html, before the first paint, on a browser with
   no record of being in; `requireLogin` takes it off when it lets somebody through.
   `visibility` and not `display`, so the boot still measures a laid-out page; on the
   descendants too and `!important`, because a child that sets `visibility: visible`
   (Explore's slides do) would show through a hidden parent. */
html[data-door="pending"] body > :not(.gate),
html[data-door="pending"] body > :not(.gate) * { visibility: hidden !important; }

.gate {
  /* The field's outline: the muted grey halfway into the card. 2.37:1 on the light
     card and 3.17:1 on the dark one — under 3:1 on light, where the label above
     every field is what identifies it; the mock's hairline was 1.4:1. */
  --gate-line: color-mix(in srgb, var(--muted) 55%, var(--panel));
  --gate-display: var(--font-display);
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: stretch;
  color: var(--text);
  background: var(--panel);
}
.gate-card {
  flex: 0 0 44%;
  min-width: 460px;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 28px;
  padding: 36px clamp(28px, 3.4vw, 48px) 28px;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--panel);
}
.gate-top { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px 20px; }
.gate-brand { display: flex; align-items: center; gap: 12px; min-width: 0; }
/* The design draws the lockup in midnight ink straight on the white card. The white
   artwork with its magenta dot (see `brandmark.js`) used to sit on a plate of its own
   here, for want of an ink one; the ink lockup is that artwork with its white
   recoloured and its dot kept, so the light card shows it bare, and the dark card —
   `--panel` turns dark with the theme — shows the white one, bare as well. */
.gate-logo { display: flex; align-items: center; flex: none; }
.gate-logo .brand-ours-full { display: none; width: auto; height: 40px; }
.gate-logo .brand-ours-ink { display: block; width: auto; height: 40px; }
:root[data-theme="dark"] .gate-logo .brand-ours-full { display: block; }
:root[data-theme="dark"] .gate-logo .brand-ours-ink { display: none; }
/* The fold is the column's, not this card's: there is no folded sign-in screen, and
   `brandLogoNode` is asked for the lockup alone here. The rule is belt over braces
   — if the mark ever arrives it is not two logos side by side. */
.gate-logo .brand-ours-icon { display: none; }
/* An agency's own, where they have one, gets the room the lockup had rather than
   the 30px the column allows: this is the screen the logo plays logo on. */
.gate-logo .brand-logo { max-width: 240px; max-height: 52px; }
.gate-word:empty { display: none; }
.gate-word {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--gate-display); font-size: 24px; font-weight: 700; letter-spacing: -.02em;
  color: var(--ink);
}
.gate-switch { margin: 0; font-size: 15px; color: var(--muted); }
/* A link that is a button: it changes the form, it does not leave the page. The
   accent as text is `--accent-ink` — 6.38:1 on the light card, 7.09:1 on the dark —
   because the magenta itself is 4.18:1 on white. */
.gate-link {
  padding: 0; font: inherit; font-weight: 600; color: var(--accent-ink);
  background: none; border: 0; cursor: pointer;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
}
.gate-link:hover { text-decoration-thickness: 2px; }
.gate-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.gate-link-quiet { font-size: 14px; font-weight: 500; }
.gate-main { flex: 1 0 auto; display: flex; flex-direction: column; justify-content: center; }
.gate-form { width: 100%; max-width: 440px; margin: 0 auto; display: flex; flex-direction: column; gap: 18px; }
.gate-title {
  margin: 0; font-family: var(--gate-display); font-size: clamp(30px, 2.9vw, 42px); font-weight: 700;
  line-height: 1.08; letter-spacing: -.03em; color: var(--ink);
}
.gate-sub { margin: -10px 0 6px; font-size: 18px; line-height: 1.45; color: var(--muted); }
.gate-sub strong { color: var(--text); font-weight: 600; }
/* An address somebody typed can be one long word. */
.gate-wrap { overflow-wrap: anywhere; }

/* «Continue with Google», and the outlined button the other forms use for their
   second action. The «G» keeps Google's four colours, as their guidelines ask. */
.gate-google, .gate-ghost {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  min-height: 52px; padding: 0 18px;
  font: inherit; font-size: 16px; font-weight: 600; color: var(--text);
  background: var(--panel); border: 1px solid var(--gate-line); border-radius: 10px;
  cursor: pointer; transition: background .15s, border-color .15s;
}
.gate-google:hover, .gate-ghost:hover { background: var(--panel-2); }
.gate-google:focus-visible, .gate-ghost:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gate-google:disabled, .gate-ghost:disabled { cursor: progress; opacity: .6; }
.gate-g { flex: none; }
.gate-or { display: flex; align-items: center; gap: 14px; font-size: 14.5px; color: var(--muted); }
.gate-or::before, .gate-or::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.gate-field { display: flex; flex-direction: column; gap: 8px; }
.gate-field-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.gate-field label { font-size: 15px; font-weight: 600; color: var(--text); }
/* 16px and not less: a phone zooms into any field whose text is smaller. */
.gate-field input {
  width: 100%; height: 50px; padding: 0 16px;
  font: inherit; font-size: 16px; color: var(--text);
  /* The card's own ground, as the drawing has it: the outline is what marks the field. */
  background: var(--panel); border: 1px solid var(--gate-line); border-radius: 10px;
  transition: border-color .15s, box-shadow .15s;
}
.gate-field input::placeholder { color: var(--muted); }
.gate-field input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-halo); }
.gate-secret { position: relative; }
.gate-secret input { padding-right: 54px; }
.gate-reveal {
  position: absolute; top: 5px; right: 5px; width: 40px; height: 40px;
  display: grid; place-items: center; padding: 0;
  color: var(--muted); background: none; border: 0; border-radius: 8px; cursor: pointer;
}
.gate-reveal:hover { color: var(--text); background: var(--panel-2); }
.gate-reveal:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
.gate-hint { margin: -10px 0 0; font-size: 14px; color: var(--muted); }

/* The one filled button, in the brand's magenta, with the colour that goes on it.
   White on this magenta is 4.18:1, under AA for body text and over it for large
   text — which is why the label is 19px bold, the size WCAG counts as large (14pt
   bold), rather than the 16px the rest of the form is set in. Under a skin
   `--on-accent` is measured for the agency's colour by `app/js/skin.js`. Hover adds
   a halo rather than changing the fill, so the pair is never re-measured mid-hover. */
.gate-go {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 54px; margin-top: 6px; padding: 0 20px;
  font: inherit; font-size: 19px; font-weight: 700;
  color: var(--on-accent); background: var(--accent);
  border: 0; border-radius: 10px; cursor: pointer; transition: box-shadow .15s;
}
.gate-go:hover { box-shadow: 0 0 0 4px var(--accent-halo); }
.gate-go:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 3px; }
.gate-go:disabled { cursor: progress; opacity: .72; box-shadow: none; }
.gate-go .gate-ic { flex: none; transition: transform .15s; }
.gate-go:hover:not(:disabled) .gate-ic { transform: translateX(3px); }

/* The error appears under the button and not above the form: whoever has just
   pressed is looking there, and a message at the top of a long form gets read
   afterwards. */
.gate-err {
  margin: 0; padding: 10px 14px; font-size: 14px; line-height: 1.45;
  color: var(--danger-ink); background: var(--danger-soft);
  border: 1px solid var(--danger-line); border-radius: 10px;
}
.gate-status { margin: 0; font-size: 14px; line-height: 1.45; color: var(--muted); }
.gate-note { margin: 0; font-size: 14px; line-height: 1.5; color: var(--muted); }
/* The invitation's sentence above the form: the one line that says whose the door is for. */
.gate-invite { margin: 0 0 16px; padding: 12px 14px; border-radius: 10px; background: var(--panel-2); font-size: 14px; line-height: 1.5; }
.gate-back { margin: 0; text-align: center; }
.gate-legal { margin: 4px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--muted); }
.gate-legal-link { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.gate-legal-link:hover { color: var(--text); }
.gate-legal-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

/* While Google's answer is exchanged: nothing to type into. */
.gate-working {
  display: flex; flex-direction: column; align-items: center; gap: 18px;
  padding: 48px 0; text-align: center;
}
.gate-working-text { margin: 0; font-size: 17px; color: var(--muted); }
.gate-spin {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid var(--border); border-top-color: var(--accent);
  animation: spin .8s linear infinite;
}

.gate-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; font-size: 14.5px; color: var(--muted); }
.gate-copy { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gate-lang-box { position: relative; display: inline-flex; align-items: center; flex: none; color: var(--muted); }
.gate-lang {
  appearance: none; -webkit-appearance: none;
  padding: 6px 28px 6px 10px; font: inherit; font-size: 14.5px; color: inherit;
  background: transparent; border: 1px solid transparent; border-radius: 8px; cursor: pointer;
}
.gate-lang:hover { color: var(--text); background: var(--panel-2); }
.gate-lang:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.gate-lang-box .gate-ic { position: absolute; right: 8px; pointer-events: none; }

/* ---- the photographs ----

   Text on a photograph is measured against the worst photograph: white over the
   bottom shade, which is `--scrim-strong` at 65% where the headline starts, is
   6.3:1 even over pure white, and the chips sit on 37% of `--scrim` over the top
   shade's own. */
.gate-show {
  --gate-slide-time: 6s;
  position: relative; flex: 1 1 auto; min-width: 0; overflow: hidden; isolation: isolate;
  color: var(--on-scrim); background: var(--code-block);
}
.gate-slides { position: absolute; inset: 0; z-index: -2; }
.gate-slide { position: absolute; inset: 0; margin: 0; opacity: 0; transition: opacity .8s ease; }
.gate-slide.on { opacity: 1; }
.gate-slide img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* A picture that did not arrive leaves the dark ground and the words, not a broken
   image icon in the middle of the door. */
.gate-slide-missing img { visibility: hidden; }
.gate-show-shade {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(to bottom, color-mix(in srgb, var(--scrim-strong) 55%, transparent), transparent 22%),
    linear-gradient(to bottom, transparent 30%, color-mix(in srgb, var(--scrim-strong) 70%, transparent) 58%, color-mix(in srgb, var(--scrim-strong) 92%, transparent));
}
.gate-show-top { position: absolute; top: 32px; left: 40px; right: 40px; display: flex; justify-content: space-between; gap: 12px; }
.gate-chip {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 18px;
  font-family: var(--mono); font-size: 13px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--on-scrim); background: color-mix(in srgb, var(--scrim) 50%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-scrim) 55%, transparent); border-radius: 999px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.gate-show-kind:empty { display: none; }
.gate-show-foot { position: absolute; left: 40px; right: 40px; bottom: 36px; display: flex; flex-direction: column; }
.gate-show-title {
  margin: 0; max-width: 14ch;
  font-family: var(--gate-display); font-size: clamp(40px, 4.6vw, 72px); font-weight: 700;
  line-height: 1.02; letter-spacing: -.035em; color: var(--on-scrim);
  text-shadow: 0 2px 28px color-mix(in srgb, var(--scrim-strong) 45%, transparent);
}
.gate-show-count { margin: 14px 0 26px; font-family: var(--mono); font-size: 16px; letter-spacing: .08em; }
.gate-show-bar { display: flex; align-items: flex-start; gap: 28px; }
.gate-thumbs { flex: 1 1 auto; min-width: 0; max-width: 680px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.gate-thumb {
  position: relative; display: block; min-width: 0; padding: 0 0 14px;
  font: inherit; color: var(--on-scrim); text-align: left;
  background: none; border: 0; cursor: pointer;
}
.gate-thumb-pic {
  position: relative; display: block; aspect-ratio: 5 / 4; overflow: hidden;
  border: 2px solid color-mix(in srgb, var(--on-scrim) 35%, transparent); border-radius: 10px;
  background: var(--code-block);
}
.gate-thumb-pic img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .4s ease; }
.gate-thumb-pic::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, color-mix(in srgb, var(--scrim-strong) 75%, transparent), transparent 60%);
}
.gate-thumb:hover .gate-thumb-pic img { transform: scale(1.05); }
.gate-thumb-label {
  position: absolute; left: 10px; right: 8px; bottom: 8px; z-index: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 500;
}
.gate-thumb[aria-current="true"] .gate-thumb-pic { border-color: var(--accent); }
.gate-thumb:focus-visible { outline: none; }
.gate-thumb:focus-visible .gate-thumb-pic { outline: 2px solid var(--on-scrim); outline-offset: 2px; }
/* The slideshow's clock: this fill finishing is the slide turning (`doorCarousel`),
   so holding it is pausing the slideshow, and the two cannot disagree. */
.gate-thumb-bar {
  position: absolute; left: 4px; right: 4px; bottom: 0; height: 3px; overflow: hidden;
  border-radius: 3px; background: color-mix(in srgb, var(--on-scrim) 28%, transparent); opacity: 0;
}
.gate-thumb[aria-current="true"] .gate-thumb-bar { opacity: 1; }
.gate-thumb-bar > i { position: absolute; inset: 0; border-radius: inherit; background: var(--accent); transform-origin: left center; scale: 0 1; }
.gate-thumb[aria-current="true"] .gate-thumb-bar > i { animation: gate-fill var(--gate-slide-time) linear forwards; }
.gate-held .gate-thumb[aria-current="true"] .gate-thumb-bar > i { animation-play-state: paused; }
@keyframes gate-fill { from { scale: 0 1; } to { scale: 1 1; } }
.gate-show-nav { flex: none; display: flex; align-items: center; gap: 12px; margin-top: 18px; }
.gate-round {
  display: grid; place-items: center; width: 48px; height: 48px; padding: 0;
  color: var(--on-scrim); background: color-mix(in srgb, var(--scrim) 40%, transparent);
  border: 1px solid color-mix(in srgb, var(--on-scrim) 55%, transparent); border-radius: 50%;
  cursor: pointer; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); transition: background .15s;
}
.gate-round:hover { background: color-mix(in srgb, var(--scrim) 70%, transparent); }
.gate-round:focus-visible { outline: 2px solid var(--on-scrim); outline-offset: 2px; }

/* Stillness, for whoever asked for it: no cross-fade, no zoom, no sliding arrow. The
   clock itself is not switched off here — the slideshow starts paused instead, and
   pressing play is the person's own choice (`doorCarousel`). */
@media (prefers-reduced-motion: reduce) {
  .gate-slide, .gate-thumb-pic img, .gate-go .gate-ic, .gate-field input { transition: none; }
  .gate-thumb:hover .gate-thumb-pic img, .gate-go:hover:not(:disabled) .gate-ic { transform: none; }
  .gate-spin { animation-duration: 2.4s; }
}
/* A short window — a laptop at 800px, a browser with all its bars — keeps the whole
   sign-up form and its foot above the fold: the same form, a little tighter. */
@media (max-height: 860px) and (min-width: 561px) {
  .gate-card { gap: 20px; padding-top: 28px; padding-bottom: 20px; }
  .gate-form { gap: 14px; }
  .gate-sub { margin-bottom: 2px; font-size: 17px; }
  .gate-field input { height: 46px; }
  .gate-google, .gate-ghost { min-height: 48px; }
  .gate-go { min-height: 50px; margin-top: 4px; }
  .gate-hint { margin-top: -8px; }
}
/* A narrower window: the photograph's controls get tighter before it goes, and under
   1100px the thumbnails become what is left of them — the four segments of the clock —
   because four pictures fifty pixels wide are four pictures nobody can see. Each
   thumbnail carries its name as `aria-label` for this reason: the label inside the
   picture is not displayed here, and a button named by hidden text has no name. */
@media (max-width: 1180px) {
  .gate-show-top { left: 28px; right: 28px; top: 24px; }
  .gate-show-foot { left: 28px; right: 28px; bottom: 28px; }
  .gate-show-bar { gap: 16px; }
  .gate-show-nav { gap: 8px; }
  .gate-round { width: 42px; height: 42px; }
}
@media (max-width: 1100px) {
  .gate-show-bar { align-items: center; }
  .gate-thumbs { gap: 6px; }
  .gate-thumb { height: 22px; padding: 0; }
  .gate-thumb-pic { display: none; }
  .gate-thumb-bar { left: 0; right: 0; top: 50%; bottom: auto; margin-top: -1.5px; opacity: 1; }
  .gate-show-nav { margin-top: 0; }
  .gate-thumb:focus-visible .gate-thumb-bar { outline: 2px solid var(--on-scrim); outline-offset: 3px; }
}
/* Under 900px the photograph goes, and the form is the screen. */
@media (max-width: 899px) {
  .gate-show { display: none; }
  .gate-card { flex: 1 1 auto; min-width: 0; }
}
@media (max-width: 560px) {
  .gate-card { gap: 22px; padding: 18px 16px 20px; }
  .gate-logo .brand-ours-full, .gate-logo .brand-ours-ink { height: 34px; }
  .gate-switch { font-size: 14px; }
  .gate-title { font-size: 30px; }
  .gate-sub { font-size: 16px; }
  .gate-form { gap: 16px; }
}

/* The administration panel's ~240 lines sat here, in five disjoint regions, and
   they went with the screen: `admin/styles.css`. Nothing below this line paints a
   `.adm-*` — the whole of it was read by `app/js/admin.js`, which is now ten modules
   under `admin/js/`.

   What stayed is what a second reader still needs. `.pm-check` is below because the
   product form uses it; `.status` and `.mdl-*` went, because `#status` was markup
   inside the panel and nothing else in the studio draws a service row. */

/* The checkbox with its label, inside a card. It was born for the administration
   panel — the first place in the product to have one, everything else being text
   fields, dropdowns and buttons — and it stayed behind when that screen left,
   because the product form has one too. */
.pm-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; }
.pm-check input { width: 15px; height: 15px; accent-color: var(--accent); cursor: pointer; }

/* The price list in Settings: read only, two columns, the numbers right-aligned and
   tabular — it is a table of prices, and it is read down the column. */

/* ---------- The app's dialogs ----------
   In place of `confirm()` and `prompt()`, which opened the browser's own window:
   another application on top of ours, with the domain name written across it, at
   exactly the moment the message has to be read carefully ("delete this user?"). Here
   the question wears the face of the product asking it, and the field has a type — a
   password is typed into a password field. */
.dlg {
  position: fixed; inset: 0; z-index: 95; display: grid; place-items: center;
  padding: 20px; background: var(--overlay); backdrop-filter: blur(3px);
}
.dlg-card {
  width: 100%; max-width: 400px; display: flex; flex-direction: column; gap: 10px;
  padding: 20px 22px 18px; background: var(--panel);
  border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-3);
}
.dlg-card h2 { margin: 0; font-size: 16.5px; letter-spacing: -.01em; }
.dlg-msg { margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); white-space: pre-line; }
.dlg-field { display: flex; flex-direction: column; gap: 5px; margin-top: 2px; }
.dlg-field > span { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.dlg-field input {
  padding: 9px 11px; font: inherit; font-size: 14.5px;
  color: var(--text); background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 9px;
}
.dlg-field input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; background: var(--panel); }
.dlg-field .hint { margin: 0; font-size: 11.5px; line-height: 1.45; }
.dlg-err { margin: 0; font-size: 13px; color: var(--danger-ink); }
/* The buttons at the bottom right, with the confirmation last: it is the order things
   are read in, and the last thing read is the thing about to be done. */
/* `.dlg-actions` is the export's, the picker's and the crop's own name for the same row, and
   it had no rule: their buttons sat at the left, in the order they were typed, beside
   dialogs whose buttons all sit at the right. */
.dlg-foot, .dlg-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.dlg-foot .btn:empty { display: none; }

/* ============================ ACCESSIBILITY ============================
   The corrections from the review in docs/interface-review.md, applied to today's
   interface — which is three times the one the review was carried out on, so the rules
   were rewritten against the current selectors rather than carried over from the
   branch.

   They all sit together and at the end on purpose: they are rules that override the
   ones above, and keeping them scattered would mean no longer knowing which they
   are. */

/* ---- a finger produces no hover ----
   Eight controls start at `opacity: 0` and are discovered by passing the mouse over
   them. `:focus-visible` was already alongside, so the keyboard had been thought about:
   the missing case is the third, touch, which produces neither hover nor focus until it
   touches — and you cannot touch what you cannot see. Downloading a generated video is
   one of the reasons the Gallery gets opened, and from a phone it could not be done. */
@media (hover: none) {
  .msg-copy,
  .ref-thumb .ref-x,
  .shot-dl,
  .word-drop,
  .vedit-handle { opacity: 1; }
  /* The jump to the end of the conversation stays conditional: it appears once you
     have scrolled back up to read, and there the condition is not the mouse. */
}

/* ---- 44px targets, drawing unchanged ----
   The standard is 44×44pt (Apple HIG) and 48×48dp (Material); these sit between 20 and
   26. The icon is not enlarged — the hit area is widened with a pseudo-element, so the
   drawing stays as it is and the finger finds the target. */

.msg-copy::after, .shot-dl::after, .gen-more::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
/* A reference's × in the box is an exception, and a deliberate one: it sits on the corner
   of a 46px picture that is tapped to enlarge, and it takes a reference away without asking.
   A 44px grip would cover the picture, and the price of a wrong tap is losing a character.
   Already absolute, so nothing to declare. */
.ref-thumb .ref-x::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 36px; height: 36px; transform: translate(-50%, -50%);
}
/* The video range's handle: a 12px drawing, a 44px grip. It is the app's most
   important precision gesture, and it had the smallest target. */
.vedit-handle::after { content: ''; position: absolute; inset: 0 -16px; }
/* The bin on a product photo, same case as the cast's and same answer: a 36px grip
   on a 78px tile rather than 44px, which would cover half the picture you are
   deciding about. It was missed when the list above was written, and already
   absolute like the rest. */
.pm-shot-drop::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 36px; height: 36px; transform: translate(-50%, -50%);
}
/* The archive's checkboxes are the one place a box is not inside its label — the
   row is a grid, and the label is the title next to it, which opens the generation
   instead of selecting it. So the box is the whole target, and at 15px it was the
   smallest one in the product, on the control that arms «move twelve things to the
   trash». The drawing stays 15px; the reach does not. */
.gens-row input[type="checkbox"] { position: relative; }
.gens-row input[type="checkbox"]::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 34px; height: 34px; transform: translate(-50%, -50%);
}

/* ---- the focus outline is not removed ----
   A read-only textarea stays reachable with Tab, and whoever gets there has to be able
   to see it. */
.vedit-target:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---- the skip to content ----
   Before the chat there are about ten fixed controls, to be crossed on every load with
   the keyboard. The link always exists and is visible only once it is reached. */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 60;
  padding: 10px 16px; border-radius: 0 0 10px 10px;
  background: var(--solid); color: var(--on-solid); font-weight: 600; text-decoration: none;
  transition: top .14s;
}
.skip-link:focus { top: 0; }

/* A generation named in the address (`/director/<id>?g=<ref>`), lit for a moment once scrolled to. */
.ref-asked { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 10px; transition: outline-color .4s; }

/* ---- the account bar (technical support, PR-20) ----
   Drawn in the accent, the one strip on screen saying «this is not your account».

   `--on-accent` and not `--on-solid` for the ink, for the reason the token exists:
   the accent is chosen by the agency and can be anything, so the ink over it is
   derived to clear 4.5:1 against the colour actually picked rather than assumed
   white over a colour we chose. Unskinned it is our magenta and the derivation
   lands on white anyway.

   Not `position: fixed`. The shell measures itself against the viewport and a
   fixed bar would sit over the top of the left column; in the flow it takes its
   own height and everything below it moves down, which is what a bar that must not
   be missed should do. */
.account-bar {
  display: flex; align-items: center; gap: 12px;
  /* Its own height and never a share of the leftover: `flex: none` is what keeps
     the shell below it in charge of the rest. */
  flex: none;
  padding: 10px 16px;
  background: var(--accent); color: var(--on-accent);
  font-size: 14px;
}
.account-bar[hidden] { display: none; }
/* The organisation's state (PR-8): the same bar in the flow, on a neutral surface, since it says a company is on hold. */
.org-state {
  flex: none;
  padding: 10px 16px;
  background: var(--panel, var(--surface-2, #f3f3f5)); color: var(--text);
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.org-state[hidden] { display: none; }
.org-state-said { margin: 0; }
.account-mark {
  flex: none; width: 10px; height: 10px; border-radius: 50%;
  background: var(--on-accent); opacity: .85;
}
.account-said { margin: 0; flex: 1 1 auto; min-width: 0; }
.account-said strong { font-weight: 700; }
/* The button reads on the accent rather than under it: a bordered ghost, because a
   filled one would need a third colour derived against a colour we do not know. */
.account-bar .btn {
  flex: none;
  background: transparent; color: var(--on-accent);
  border: 1px solid var(--on-accent);
}
.account-bar .btn:hover { background: var(--on-accent); color: var(--accent); }
@media (max-width: 620px) {
  .account-bar { flex-wrap: wrap; font-size: 13px; }
}

/* ---- below 620px the column becomes a strip ----
   At 375px a 216px column takes more than half the screen, and the work — which is the
   product — is left with 159. The icon strip already exists and is designed for exactly
   this: here it becomes the default, taking nothing away because the control that
   reopens it stays where it is.

   `--side-w` at 56 and not 60: on a narrow screen those four pixels are the only thing
   that can be given back to the work without breaking a target. */
@media (max-width: 620px) {
  .shell { --side-w: 56px; }
  .side { padding: 12px 6px; align-items: center; }
  .brand-word, .nav-lb, .kit-text, .kit-caret { display: none; }
  .side-account-name, .kit-org {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  }
  .nav-item { justify-content: center; padding: 12px 0; gap: 0; }
  /* The rows on end, as in the collapsed rail — which a phone gets whether or not
     anybody collapsed anything, so the rail's rules are repeated on the width. */
  .side > .side-kit { margin: 12px 0 0; }
  .side > .nav-cta { flex: none; width: 44px; height: 44px; margin: 10px 0 8px; padding: 0; border-radius: 50%; }
  .kit-btn { justify-content: center; width: 44px; min-height: 44px; padding: 4px; background: none; border-color: transparent; }
  /* The menu as wide as the strip, or `align-items: center` above shrinks each entry
     to its icon and the open one's wash to a 20px sliver. */
  .side-nav { width: 100%; }
  .side-foot { width: 100%; align-items: center; gap: 8px; padding-top: 12px; }
  .side-account { flex-direction: column; gap: 4px; }
  .side-me { flex: none; flex-direction: column; justify-content: center; gap: 3px; width: 44px; min-height: 56px; padding: 4px 0; }
  .side-jobs { flex-direction: column; }
  .cr-short { display: block; }
  .kit-menu,
  .jobs-panel {
    position: fixed; left: calc(var(--side-w) + 8px); right: auto; bottom: 12px;
    width: min(280px, calc(100vw - var(--side-w) - 16px));
  }
  .kit-menu {
    top: var(--kit-at, 12px); bottom: auto; max-height: calc(100vh - var(--kit-at, 12px) - 12px);
  }
  .side:has(.kit-menu:not([hidden]), .jobs-panel:not([hidden])) { z-index: 45; }
  .side-brand { flex-direction: column; gap: 8px; width: 100%; padding: 0 0 10px; }
  /* The lockup goes on the **width**, not on the fold. This column is a 56px strip
     here whether or not anybody collapsed it, and `body.nav-collapsed` — which is
     the other half of this swap — is not set by a media query. Without these four
     lines a phone gets 116px of logo in 56px of column. */
  .brand-mark { height: 30px; }
  .brand-ours-full { display: none; }
  .brand-ours-icon { display: block; width: 30px; height: 30px; }
  .brand-logo { max-width: 40px; max-height: 30px; }
  .main { padding: 10px 10px 12px; }
  /* Two fields side by side at 375px are two 130px fields: one under the other both
     of them read. */
  .grid2 { grid-template-columns: 1fr; }
}

/* The answer forming before your eyes.

   The blinking cursor is not decoration: without it, an answer that pauses for two
   seconds on a slow token looks finished, and the reader starts replying over it. It
   disappears when the bubble closes. */
.msg.assistant.streaming .msg-body > *:last-child::after {
  content: '';
  display: inline-block; width: .5em; height: 1em; margin-left: 2px;
  vertical-align: -.15em; background: var(--accent); border-radius: 1px;
}
@media (prefers-reduced-motion: no-preference) {
  .msg.assistant.streaming .msg-body > *:last-child::after { animation: caret 1s steps(1) infinite; }
}
@keyframes caret { 50% { opacity: 0; } }

/* What it is doing, next to the dots. */
.thinking-what { margin-left: 8px; font-size: 12.5px; color: var(--muted); vertical-align: 2px; }
.thinking-what:empty { display: none; }

/* ==========================================================================
   THE LARGE WINDOW — reference picker and advanced options
   ==========================================================================

   The shell is one for both, and not to save lines: a large window in this
   application has to close with Escape, with a click on the veil and with the ⨯ always
   in the same way, and three implementations diverge on the first detail.

   The measure is `min(1040px, 94vw)` and not a fixed width: the catalogue may have
   sixty products, and choosing one while looking at four tiles at a time is scrolling,
   not choosing. The height is governed, not free — head and foot stay put and only the
   body scrolls, so the button that confirms does not run away to the bottom of a list
   of two hundred files. */
.sheet {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  padding: 20px; background: var(--overlay);
}
/* Above the editors that open over the page (80), under a dialog asked over it (95). */
.sheet.sheet-over { z-index: 90; }
@media (prefers-reduced-motion: no-preference) {
  .sheet { animation: sheet-in .12s ease-out; }
}
@keyframes sheet-in { from { opacity: 0; } }

.sheet-card {
  display: flex; flex-direction: column; gap: 0; width: min(520px, 94vw);
  max-height: min(88vh, 900px); overflow: hidden;
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px;
  box-shadow: var(--shadow-3);
}
.sheet-wide { width: min(1040px, 94vw); }

.sheet-head {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 20px 22px 14px;
}
.sheet-id { flex: 1; min-width: 0; }
.sheet-head h2 { margin: 0; font-size: 19px; line-height: 1.25; letter-spacing: -.015em; }
.sheet-sub { margin: 4px 0 0; max-width: 68ch; font-size: 13px; line-height: 1.5; }
/* The director's mark, where a window wears it: the same spark the column's head
   carries, so the window reads as the director's and not as the browser's. */
.sheet-icon { flex: none; display: grid; place-items: center; margin-top: 1px; color: var(--accent); }
.sheet-x {
  flex: none; display: grid; place-items: center; width: 34px; height: 34px; padding: 0;
  font-size: 18px; line-height: 1; border-radius: 9px; background: var(--panel);
}

.sheet-body { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 22px 18px; }
.sheet-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px 22px; border-top: 1px solid var(--border); background: var(--panel);
}
.sheet-foot .btn-row { margin-left: auto; flex: none; }
.sheet-foot .btn { min-height: 42px; padding: 0 18px; border-radius: 10px; font-size: 14px; }

/* ---------- The avatar gallery's window (avatar-gallery.js) ----------
   The owner's screenshot: the search, the two shelves and the categories in a column on
   the left, the portraits on the right in 3:4 with the name over the picture. The column
   names its own track, so nothing that hides inside it can slide the grid under it. */
.ag .sheet-card { width: min(1120px, 94vw); }
.ag-layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 20px; align-items: start; }
.ag-side { grid-column: 1; position: sticky; top: 0; display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.ag-main { grid-column: 2; min-width: 0; }
.ag-side .pick-search, .ag-shelves { margin: 0; }
.ag-shelves .pick-tab { min-height: 40px; font-size: 13.5px; }
.ag-side-title {
  margin: 6px 0 0; font-size: 11.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted);
}
.ag-chips { margin: 0; }
.ag-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.ag-grid[hidden] { display: none; }
.ag-card { position: relative; min-width: 0; }
.ag-face {
  position: relative; display: block; width: 100%; aspect-ratio: 3 / 4; padding: 0; overflow: hidden;
  cursor: pointer; font: inherit; background: var(--panel-3); border: 2px solid transparent; border-radius: 14px;
}
.ag-face img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.ag-face:hover { border-color: var(--accent-line); }
.ag-face:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ag-face:disabled { cursor: default; }
.ag-card.on .ag-face { border-color: var(--accent); }
/* On top of a picture, so the pair that does not move with the theme. */
.ag-name {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 26px 10px 9px; text-align: left;
  font-size: 13.5px; font-weight: 600; color: var(--on-scrim);
  background: linear-gradient(transparent, var(--scrim));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ag-tick {
  position: absolute; top: 8px; right: 8px; display: grid; place-items: center;
  width: 24px; height: 24px; border-radius: 50%; color: var(--on-accent); background: var(--accent);
}
.ag-wait {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 13px; font-weight: 600; color: var(--on-scrim); background: var(--scrim);
}
.ag-letter { position: absolute; inset: 0; display: grid; place-items: center; font-size: 40px; font-weight: 700; color: var(--muted); }
.ag-drop {
  position: absolute; top: 6px; left: 6px; width: 28px; height: 28px; padding: 0; cursor: pointer;
  font-size: 16px; line-height: 1; color: var(--on-scrim); background: var(--scrim); border: 0; border-radius: 50%;
}
.ag-drop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ag-status { margin: 0 0 12px; }
.ag-status[hidden] { display: none; }
.ag-empty { margin: 24px 0; }
.ag-more { margin: 0; font-size: 13px; }
.ag-more-link {
  padding: 0; cursor: pointer; font: inherit; font-weight: 600; color: var(--accent-ink);
  background: none; border: 0; text-decoration: underline; text-underline-offset: 2px;
}
.ag-more-link[hidden] { display: none; }
@media (max-width: 760px) {
  .ag-layout { grid-template-columns: minmax(0, 1fr); }
  .ag-side, .ag-main { grid-column: 1; }
  .ag-side { position: static; }
  .ag-grid { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
}

/* ---------- The three tabs ----------
   One bar split in three, each with its mark, and the open one filled with the accent's
   wash and underlined in it — the owner's drawing of the window, which is also the
   only shape where the open tab can be told from the others without reading them. */
.pick-tabs {
  display: flex; margin-bottom: 16px; overflow: hidden;
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
}
.pick-tabs[hidden] { display: none; }
.pick-tab {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 46px; padding: 0 12px; border: 0; background: transparent;
  font: inherit; font-size: 14px; color: var(--muted); cursor: pointer;
  box-shadow: inset 0 -2px 0 transparent; transition: background .12s, color .12s;
}
.pick-tab + .pick-tab { border-left: 1px solid var(--border); }
.pick-tab:hover { color: var(--text); background: var(--panel-2); }
.pick-tab.on { background: var(--accent-soft); color: var(--accent-ink); font-weight: 600; box-shadow: inset 0 -2px 0 var(--accent); }
.pick-tab .sd-ic { flex: none; }

.pick-search { position: relative; display: block; margin-bottom: 14px; }
.pick-search > .sd-ic { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.pick-search input {
  width: 100%; margin: 0; min-height: 42px; padding-left: 42px; font-size: 14px;
  background: var(--panel-2); border-radius: 10px;
}
.pick-search[hidden] { display: none; }

/* The filters on the left, the order on the right, on one line. */
.pick-bar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.pick-bar[hidden] { display: none; }
.pick-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; flex: 1; min-width: 0; }
.pick-chips[hidden] { display: none; }
.pick-chip {
  padding: 7px 16px; border-radius: 999px; border: 1px solid var(--border);
  background: var(--panel); font: inherit; font-size: 13px; color: var(--text); cursor: pointer;
}
.pick-chip:hover { border-color: var(--ink-2); }
.pick-chip.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-ink); font-weight: 600; }
.pick-refresh { display: grid; place-items: center; width: 34px; height: 34px; padding: 0; border-radius: 999px; background: var(--panel); }
.pick-sort {
  display: inline-flex; align-items: center; gap: 8px; margin-left: auto; padding: 0 6px 0 12px;
  min-height: 38px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel);
}
.pick-sort[hidden] { display: none; }
.pick-sort > .sd-ic { color: var(--muted); flex: none; }
.pick-sort select { margin: 0; border: 0; background: transparent; font-size: 13.5px; font-weight: 600; color: var(--text); padding: 6px 4px; }
.pick-status { margin: 0 0 12px; }

/* The tiles. `auto-fill` and not a column count: the same grid serves a catalogue of
   three products and one of sixty, on a 1440 screen and on a 1280 laptop. */
.pick-grid.cards, .pick-grid.tiles {
  display: grid; gap: 18px 16px;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
}
.pick-card {
  display: flex; flex-direction: column; gap: 5px; padding: 0; text-align: left;
  background: transparent; border: 0; border-radius: 12px;
  font: inherit; color: inherit; cursor: pointer;
}
.pick-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* The chosen state shows in the frame *and* in the tick: colour alone is not enough
   for somebody who cannot tell it apart, and here the difference between chosen and
   not chosen is what is about to be paid for. */
.pick-card:hover .pick-media { box-shadow: 0 0 0 1px var(--ink-2); }
.pick-card.on .pick-media { box-shadow: 0 0 0 2px var(--accent); }
.pick-card[disabled] { opacity: .5; cursor: not-allowed; }
.pick-card strong { margin-top: 5px; font-size: 14px; line-height: 1.3; overflow-wrap: anywhere; }
.pick-card .hint { margin: 0; font-size: 12.5px; line-height: 1.35; }
.pick-meta { display: inline-flex; align-items: center; gap: 6px; }
.pick-meta .sd-ic { flex: none; }

.pick-media {
  position: relative; aspect-ratio: 4 / 3; border-radius: 12px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border);
  display: grid; place-items: center; transition: box-shadow .12s;
}
/* Laid over the plate rather than placed in it, for the reason the logo's rule below
   gives: as a grid item a picture sizes the plate's one row from its own proportions,
   so a portrait product shot made the row taller than the 4:3 plate and the plate's
   `overflow: hidden` kept only its top — a crop from the top edge instead of round the
   middle. */
.pick-media img, .pick-media video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
/* The tick, top right on every tile: an empty box at rest, which is what says the
   tile can be chosen at all, and filled with the accent once it is. */
.pick-check {
  position: absolute; top: 9px; right: 9px; display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 6px;
  background: var(--panel); border: 1.5px solid var(--border); color: transparent;
  box-shadow: var(--shadow-1);
}
.pick-card.on .pick-check { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
/* A logo nearly always sits on a transparent ground, and on a light grey a white logo
   disappears. The chequerboard says "there is nothing underneath here", which is exactly
   the information you need when looking at a PNG. Named twice so the foot's thumbnail
   wears it too: `.pick-thumb` below sets its own `background`, and that shorthand would
   otherwise wipe the squares off the one cell that shows a logo. */
.pick-alpha, .pick-thumb.pick-alpha {
  background-color: var(--panel);
  background-image:
    linear-gradient(45deg, var(--panel-3) 25%, transparent 25%, transparent 75%, var(--panel-3) 75%),
    linear-gradient(45deg, var(--panel-3) 25%, transparent 25%, transparent 75%, var(--panel-3) 75%);
  background-size: 14px 14px; background-position: 0 0, 7px 7px;
}
/* Contained with room around it, never stretched or cropped: a mark is read whole or it
   is not the mark. The room is a share of the plate, clamped, so a square logo sits on a
   visible margin of chequerboard in a 236px card and does not drown in a phone's
   full-width one. And laid over the plate rather than placed in it: as a grid item the
   picture sizes the plate's one row from its own proportions, so a square logo made the
   row taller than the 4:3 plate and the plate's `overflow: hidden` cut its bottom off: a
   square drawn as a wide block with nothing under it, which is what read as stretched. */
.pick-alpha img { position: absolute; inset: 0; object-fit: contain; padding: clamp(10px, 12%, 28px); }
.pick-noimg { font-size: 11.5px; color: var(--muted); }
.pick-badge {
  position: absolute; left: 8px; bottom: 8px; padding: 2px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; color: var(--on-scrim); background: var(--scrim);
}
/* The kit's tile and the catalogue's, each under a small heading, which is what lets one
   logo on a row of four read as a section rather than a stray card. A heading names its
   own track: a grid child placed by auto-flow lands in whatever cell is free, and a label
   one track wide would sit beside the logo instead of over it. */
.pick-group {
  grid-column: 1 / -1; margin: 2px 0 -8px;
  font-size: 12px; font-weight: 600; line-height: 1.3; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted);
}
.pick-group ~ .pick-group { margin-top: 8px; }

.pick-empty { grid-column: 1 / -1; margin: 18px 0; text-align: center; line-height: 1.6; }
.pick-empty strong { display: block; color: var(--text); font-size: 14px; margin-bottom: 3px; }

/* An empty catalogue is the start of one: the picture, the sentence, and the road. */
.pick-hero { display: grid; justify-items: center; gap: 8px; margin: 10px 0 4px; }
.pick-hero-art { width: 240px; max-width: 70%; height: auto; margin-bottom: 6px; }
.pick-hero strong { font-size: 21px; letter-spacing: -.015em; margin: 0; }
.pick-hero p { margin: 0 0 10px; max-width: 46ch; color: var(--muted); font-size: 14px; line-height: 1.55; }
.pick-hero .pick-empty-go { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 26px; border-radius: 10px; font-size: 14.5px; }
/* Under the kit's logo the empty catalogue lies down, flush with its heading: the picture
   beside the sentence and the road. Standing up, as it does when it is the whole tab, it
   sat a gap below the logo card and pushed «Add your first product» under the window's
   fold on a laptop — the one button this state is for, on a kit whose logo is the only
   thing in it. On a narrow window it stands up again, where the page scrolls anyway. */
.pick-group + .pick-hero { margin-top: 0; }
@media (min-width: 720px) {
  .pick-group + .pick-hero {
    grid-template-columns: auto minmax(0, 46ch); grid-template-rows: repeat(4, auto);
    justify-content: start; justify-items: start; align-items: center;
    column-gap: 28px; row-gap: 6px; margin: 0; text-align: left;
  }
  .pick-group + .pick-hero > * { grid-column: 2; }
  .pick-group + .pick-hero > .pick-hero-art { grid-column: 1; grid-row: 1 / -1; width: 210px; max-width: none; margin: 0; }
  .pick-group + .pick-hero p { margin: 0; }
  .pick-group + .pick-hero .pick-empty-go { margin-top: 8px; }
  .pick-group + .pick-hero .pick-empty-link { margin: 0; padding-inline: 0; }
}
.pick-empty-link {
  margin-top: 4px; padding: 6px 10px; border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--accent-ink);
}
.pick-empty-link:hover { text-decoration: underline; }
.ph-shadow { fill: var(--accent-soft); }
.ph-box { fill: var(--panel-2); stroke: var(--accent-line); stroke-width: 1.2; }
.ph-side { fill: var(--panel); stroke: var(--accent-line); stroke-width: 1.2; }
.ph-flap { fill: var(--panel); stroke: var(--accent-line); stroke-width: 1.2; }
.ph-card { fill: var(--panel); stroke: var(--border); stroke-width: 1.2; filter: drop-shadow(0 6px 10px var(--accent-soft)); }
.ph-shot { fill: var(--panel-2); }
.ph-ink { fill: var(--muted); opacity: .55; }
.ph-line { fill: var(--border); }
.ph-plus { fill: var(--accent); }
.ph-plus-x { stroke: var(--on-accent); stroke-width: 2.2; stroke-linecap: round; fill: none; }
.ph-spark { fill: var(--accent); }

/* ---------- Upload file ---------- */
.pick-grid.drop { display: grid; gap: 14px; }
.pick-drop {
  display: grid; justify-items: center; gap: 8px; padding: 32px 20px 26px; text-align: center;
  border: 2px dashed var(--border); border-radius: 16px; background: var(--panel);
  transition: border-color .12s, background .12s;
}
.pick-drop.on { border-color: var(--accent); background: var(--accent-soft); }
.pick-drop > strong { font-size: 20px; letter-spacing: -.015em; }
.pick-drop > .hint { margin: 0 0 8px; max-width: 48ch; font-size: 14px; }
/* Three cards fanned out — a picture, a clip, a sound — and the accent's arrow over
   them, which is what «drop it here» looks like before anything has been dropped. */
.pick-drop-art { position: relative; display: block; width: 170px; height: 96px; margin-bottom: 8px; }
.pd-card {
  position: absolute; top: 14px; display: grid; place-items: center; width: 62px; height: 66px;
  border-radius: 12px; background: var(--panel-2); border: 1px solid var(--border); color: var(--muted);
  box-shadow: var(--shadow-1);
}
.pd-card.l { left: 8px; transform: rotate(-9deg); }
.pd-card.r { right: 8px; transform: rotate(9deg); }
.pd-card.m { left: 50%; top: 0; z-index: 1; transform: translateX(-50%); background: var(--panel); width: 66px; height: 70px; color: var(--text); }
.pd-up {
  position: absolute; left: 50%; bottom: 0; z-index: 2; transform: translateX(-50%);
  display: grid; place-items: center; width: 40px; height: 40px; border-radius: 999px;
  background: var(--accent); color: var(--on-accent); box-shadow: 0 4px 12px var(--accent-halo);
}
.pick-choose { display: inline-flex; align-items: center; gap: 10px; min-height: 46px; padding: 0 28px; border-radius: 10px; font-size: 15px; }
.pick-formats { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 8px; }
.pick-formats span {
  padding: 5px 15px; border-radius: 999px; border: 1px solid var(--border);
  font-size: 13px; color: var(--text); background: var(--panel);
}
.pick-audio { margin: 2px 0 0; font-size: 13px; }
.pick-note {
  display: flex; align-items: center; gap: 14px; margin: 0; padding: 14px 18px;
  border-radius: 12px; background: var(--panel-2); color: var(--muted); font-size: 13.5px;
}
.pick-note .sd-ic { flex: none; color: var(--text); }
.pick-file { display: none; }
.pick-files { display: flex; flex-wrap: wrap; gap: 7px; }
.pick-fchip {
  display: inline-flex; align-items: center; gap: 7px; padding: 5px 6px 5px 11px;
  border-radius: 999px; background: var(--panel-2); border: 1px solid var(--border); font-size: 12.5px;
}

/* ---------- The foot: what is about to be added ---------- */
.pick-summary { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1; }
.pick-count { flex: none; font-size: 14px; color: var(--muted); }
.pick-count.some { color: var(--text); font-weight: 600; }
.pick-thumbs { display: flex; gap: 8px; min-width: 0; overflow-x: auto; padding: 6px 6px 6px 0; }
.pick-thumb {
  position: relative; flex: none; width: 46px; height: 46px; border-radius: 9px;
  background: var(--panel-2); border: 1px solid var(--border);
}
.pick-thumb img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; display: block; }
/* The logo's thumbnail keeps its whole mark, as its card does. */
.pick-thumb.pick-alpha img { object-fit: contain; padding: 5px; }
.pick-thumb.none { display: grid; place-items: center; color: var(--muted); }
.pick-thumb-x {
  position: absolute; top: -6px; right: -6px; display: grid; place-items: center;
  width: 18px; height: 18px; padding: 0; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
  font: inherit; font-size: 12px; line-height: 1; box-shadow: var(--shadow-1);
}
.pick-thumb-x:hover { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.pick-ok { display: inline-flex; align-items: center; gap: 8px; }

/* ==========================================================================
   PRO: a mode, not a panel
   ==========================================================================

   Switching PRO on used to open a card at the bottom of the right column. Two defects
   in one: it appeared where nobody was looking — you type on the left — and it appeared
   all at once, ten levers, in order to change nearly always one of the four that now sit
   below.

   The box's border was the only thing PRO changed before anything is touched, answering
   «am I in PRO right now?» where the question gets asked. The owner's third picture of
   the bar draws the same pink hairline round the box in both modes (`.composer`, above),
   so what answers it now is the switch in the bar, lit — and what PRO changes on screen
   is the models pill on the levers' line, and the sliders where a job has more to set. */
/* No «PRO» tag riding the border any more: the switch in the bar says it, lit, an
   inch below — and the tag sat exactly on the seam where a docked question meets the
   box, which is the one place on this screen two things already share a line. */
/* A query container, too: the bar inside it decides what the models pill can say by
   how wide the box is (`@container composer`, below). It makes the box a stacking
   context, which matters once: the settings panel is drawn out of it, over the
   conversation, so the box is lifted over the «latest messages» pill (4) while the
   panel is open. */
.composer { position: relative; container: composer / inline-size; }
.composer:has(.strip-panel) { z-index: 5; }

/* ---------- The PRO strip: levers in the bar ----------
   It was a two-column grid of labelled dropdowns, then a row of chips between the box
   and the bar — an icon, the value, a chevron — which at the column's width wrapped
   onto a third line. The owner's pictures put it in the bar itself: the models as one
   pill, the two quick pills beside it, a round sliders button that opens the levers the
   bar does not show in a panel over the box, and the figure beside Send.

   Every lever is still the one `strip-pick.js` draws — a button that opens a menu of
   what can be chosen — so nothing about choosing changed, only where the choice sits at
   rest. The levers' line takes what the bar has, and the models pill is what shrinks
   in it. */
.pro-strip {
  display: flex; align-items: center; flex: 1 1 auto; flex-wrap: nowrap; gap: 6px; min-width: 0;
}
.pro-strip[hidden] { display: none; }
.strip-field { display: inline-flex; align-items: center; min-width: 0; max-width: 100%; }
/* The models pill is the one lever that gives way, and it gives way by shrinking rather
   than by pushing the sliders onto a line of their own: a basis of nothing, so the line
   is laid out as if it took no room past its floor, and then it grows into what is left
   up to what it says — «Veo 3.1 Fast» whole where it fits, cut with an ellipsis where
   it does not. The floor is «Auto» and its chevron, which is never cut. */
.pro-strip > .strip-field { flex: 1 1 0; min-width: 68px; max-width: max-content; }
.pro-strip > .strip-tune { flex: none; }

/* The chip: what is chosen, between the icon that says what kind of thing it is and a
   small chevron that says it opens. A pill on the composer's paper, hairlined, and it
   takes the paper's lift on hover — the same gesture as the attach button beside it. */
.strip-pick {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 220px; height: 30px;
  margin: 0; padding: 0 8px 0 9px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 12.5px; font-weight: 600; line-height: 1;
  text-align: left; cursor: pointer; transition: border-color .12s, background .12s, box-shadow .12s;
}
.strip-pick:hover { background: var(--panel-2); border-color: color-mix(in srgb, var(--ink) 22%, var(--border)); }
.strip-pick:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Open: the accent as a border, not a fill — the fill belongs to the chosen row inside
   the menu, and two pink things on screen would be two answers to one question. */
.strip-pick[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.strip-pick:disabled { opacity: .5; cursor: not-allowed; }
.strip-pick:disabled:hover { border-color: var(--border); background: var(--panel); }
.strip-pick-icon, .strip-pick-chev { flex: none; display: inline-flex; }
.strip-pick-icon .sd-ic { width: 15px; height: 15px; color: var(--accent-ink); }
/* At rest, naming a lever nobody has touched: the same chip, one step quieter, so a
   value somebody chose is what stands out on the row. */
.strip-pick.is-auto { color: var(--ink-2); font-weight: 500; }
.strip-pick.is-auto .strip-pick-icon .sd-ic { color: var(--muted); }
.strip-pick-icon:empty { display: none; }
.strip-pick-chev .sd-ic { width: 13px; height: 13px; }
.strip-pick-value { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.strip-pick-chev { color: var(--muted); transition: transform .15s; }
.strip-pick[aria-expanded="true"] .strip-pick-chev { transform: rotate(180deg); }

/* The models pill: «Models: Auto», in the full ink whether or not anything is pinned —
   it is the lever PRO exists for, not a lever nobody touched — and the one thing in the
   bar that shrinks. Open, the border goes to the accent and the chevron turns up, the
   rule above. */
.strip-pick[data-look="models"] { max-width: 200px; padding: 0 9px 0 12px; color: var(--text); font-weight: 600; }
.strip-pick[data-look="models"] .strip-pick-chev { color: var(--ink-2); }

/* The two quick pills, «Aspect ratio» and «Resolution», as icon chips on the bar's one
   line: the lever's mark — the shape itself for the shape — and the value in bold, the
   height of the modes beside them. The lever's small name stays in the button for a
   screen reader and the tooltip, out of sight; the chevron goes, the chip's border and
   its hover already say it opens. The value is the full ink whether or not anything is
   chosen: «Auto» is an answer here. Open, the accent's border over the faintest of its
   tints. */
.strip-pick.strip-quick { flex: none; height: 32px; max-width: 170px; gap: 6px; padding: 0 12px 0 9px; color: var(--text); }
/* The model's pill is the one that gives way on the levers' line, as the models pill does in
   PRO: the shape and the steps keep what they say, the engine's name takes an ellipsis. */
.strip-pick.strip-quick.strip-note[data-key="models"] { flex: 0 1 auto; min-width: 52px; max-width: 160px; }
.strip-pick.strip-quick.is-auto { color: var(--text); font-weight: 600; }
/* A shape the person bound that the engine in charge does not make (`aspectOff`), or an
   engine in charge this deploy has no key for — on the models pill of either mode
   (`engineOff`): the value in the warning ink behind a small dot, and the reason on the
   tooltip. Kept, not changed — the pill only stops pretending all is well. */
.strip-pick.is-off .strip-pick-value { color: var(--warn); }
.strip-pick.is-off .strip-pick-value::before {
  content: ''; display: inline-block; width: 6px; height: 6px; margin: 0 5px 1px 0;
  border-radius: 50%; background: currentColor; vertical-align: middle;
}
.strip-pick.strip-quick .strip-pick-icon .sd-ic,
.strip-pick.strip-quick.is-auto .strip-pick-icon .sd-ic { width: 18px; height: 18px; color: var(--ink-2); }
.strip-pick.strip-quick:not(.is-auto) .strip-pick-icon .sd-ic { color: var(--accent-ink); }
.strip-pick.strip-quick[aria-expanded="true"] { background: color-mix(in srgb, var(--accent) 5%, var(--panel)); }
.strip-quick .strip-pick-chev { display: none; }
.strip-quick-text { display: flex; align-items: center; flex: 0 1 auto; min-width: 0; }
.strip-quick-name {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.strip-quick .strip-pick-value { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 700; line-height: 1.15; font-variant-numeric: tabular-nums; }
/* What the director decided, said where «Auto» was (the owner's word of 2026-10-24): the
   sparkle of the bar's «Automatic» rows before it, so it never reads as the person's own
   setting — and for a screen reader the words (`stripAutoMark`). */
.strip-auto-mark { display: inline-flex; margin-right: 3px; vertical-align: -1px; color: var(--accent-ink); }
.strip-auto-mark .sd-ic { width: 12px; height: 12px; }
/* A note pill's card: the sentence, and the one way on. */
.strip-note-text { margin: 2px 2px 10px; font-size: 13px; line-height: 1.45; color: var(--text); }
.strip-note-go { width: 100%; justify-content: center; }
/* The models pill stands the same height beside them, and says «Auto» in the same type as
   their values, so the three words share a baseline. */
.pro-strip > .strip-field .strip-pick[data-look="models"] { height: 32px; font-size: 12.5px; line-height: 1.15; }

/* The sliders: a round control the size of the picture-and-plus, quiet like it, the
   accent's border while its panel is open, and a dot when a lever inside is set. */
.btn.icon.strip-tune {
  position: relative; display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; padding: 0; border-radius: 50%;
  background: transparent; border-color: var(--border); color: var(--ink-2);
  transition: background .14s, color .14s, border-color .14s;
}
.btn.icon.strip-tune:hover { background: var(--panel-2); color: var(--ink); border-color: color-mix(in srgb, var(--ink) 25%, var(--border)); }
.btn.icon.strip-tune[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); color: var(--accent-ink); }
.strip-tune .sd-ic { display: block; }
.strip-tune-dot {
  position: absolute; top: 3px; right: 3px; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 2px var(--field);
}

/* The settings panel, over the conversation and against the top of the box: a card the
   width of the box, with a row per lever — its name on the left, its chip on the right.
   Under the lever menus it opens (50, on the body) and over the «latest messages» pill,
   through the box's own lift (`.composer:has(.strip-panel)`). */
.strip-panel {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 8px); z-index: 30;
  display: flex; flex-direction: column; gap: 4px; padding: 10px 12px 12px;
  background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-2);
}
.strip-panel-title { padding: 0 0 4px; font-size: 13px; font-weight: 600; color: var(--text); }
.strip-panel .strip-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 36px; }
.strip-panel .strip-row .strip-field-label { flex: 0 1 auto; min-width: 0; font-size: 13px; color: var(--ink-2); }
.strip-panel .strip-row .strip-pick { flex: 0 1 auto; max-width: 62%; }
@media (prefers-reduced-motion: no-preference) {
  .strip-panel { animation: strip-pop-up .12s ease-out; }
}

/* The menu: a card on `document.body`, fixed beside its lever by `stripPickPlace`, so
   neither the composer's corners nor the column's overflow can clip it. Above the
   page's own popovers (40) and under every dialog and sheet (60 and up): a dialog is
   opened by a press, and a press outside has already closed it. */
.strip-pop {
  position: fixed; z-index: 50; display: flex; flex-direction: column; gap: 2px;
  padding: 6px; overflow-y: auto; overscroll-behavior: contain;
  background: var(--panel); color: var(--text); font-size: 14px; line-height: 1.3;
  border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow-2);
}
.strip-pop:focus { outline: none; }
/* Scrolled, never squashed: in a column capped by `max-height` a row with a second
   line would otherwise be shrunk to its 40px minimum and spill over its neighbour. */
.strip-pop > * { flex-shrink: 0; }
@media (prefers-reduced-motion: no-preference) {
  .strip-pop { animation: strip-pop-in .12s ease-out; }
  .strip-pop[data-side="above"] { animation-name: strip-pop-up; }
}
@keyframes strip-pop-in { from { opacity: 0; transform: translateY(-3px); } }
@keyframes strip-pop-up { from { opacity: 0; transform: translateY(3px); } }
/* The listbox inside the card: every option and nothing else, so the tabs, the title
   and the fold sit beside it rather than in it. */
.strip-list { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.strip-opt {
  display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 7px 10px;
  border-radius: 10px; color: var(--text); cursor: pointer; user-select: none;
}
.strip-opt:hover { background: var(--panel-2); }
.strip-opt:focus { outline: none; }
.strip-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The chosen row: the accent's tint under its ink — 5.47:1 light, the figure recorded on
   `--accent-ink` in `:root`, and 5.95:1 measured on the dark card — and a tick, because
   the tint alone would be colour carrying the whole difference. The second line keeps
   `--muted`, measured on the tint at 5.24:1 light and 6.3:1 dark. After `:hover`, so
   pointing at the chosen row does not unchoose it. */
.strip-opt[aria-selected="true"] { background: var(--accent-soft); color: var(--accent-ink); }
.strip-opt-icon, .strip-opt-check { flex: none; display: inline-flex; }
.strip-opt-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.strip-opt-label { font-weight: 500; overflow-wrap: anywhere; }
.strip-opt-sub { font-size: 12px; line-height: 1.35; color: var(--muted); }
/* What an entry cannot do with what is already chosen — «Does not make 8:1» on a model's
   row — in the warning ink, under its name: the one line in the menu worth reading first. */
.strip-opt-warn { font-size: 12px; line-height: 1.35; font-weight: 500; color: var(--warn); }
/* The director's choice in an Autopilot pill's menu (`stripDecidedMark`): the pill says
   «Auto», and the entry it stands for wears the accent and says whose it is. On a tile of
   shapes there is no room for the words, so it is a sparkle on the corner and the words are
   kept for a screen reader. */
.strip-opt.is-decided {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent);
}
.strip-opt-decided { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; font-weight: 600; line-height: 1.3; color: var(--accent-ink); }
.strip-tile .strip-opt-decided {
  position: absolute; top: -5px; left: -5px; justify-content: center; width: 16px; height: 16px; padding: 0;
  font-size: 0; color: var(--on-solid, #fff); background: var(--accent); border-radius: 50%; box-shadow: 0 0 0 2px var(--panel);
}
.strip-opt-tag { display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px; font-size: 11px; font-weight: 500; line-height: 1.5; color: var(--muted); background: var(--panel-2); border: 1px solid var(--border); vertical-align: 1px; white-space: nowrap; }

/* The models menu, as the owner drew it: «Images | Video» as two segments over the
   list, the one showing in the accent's tint; then «Automatic» with its sparkle, pink on
   a pink row whether or not it is the one chosen — it is the director's road, and it
   reads as one — and the engines as plain rows with a tick on the chosen one. The tint
   is taken off a chosen engine's row on purpose: two pink rows in one list would be two
   answers to «which is chosen?», and the tick and the weight carry it. */
.strip-tabs {
  display: flex; gap: 2px; flex: none; margin: 0 0 6px; padding: 2px;
  background: var(--panel-2); border-radius: 10px;
}
.strip-tab {
  flex: 1 1 0; display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-width: 0;
  height: 34px; margin: 0; padding: 0 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--ink-2); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.strip-tab:hover { color: var(--text); }
.strip-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.strip-tab[aria-selected="true"] { background: var(--accent-soft); color: var(--accent-ink); }
.strip-tab .sd-ic { flex: none; width: 16px; height: 16px; }
.strip-pop-models .strip-opt[aria-selected="true"] { background: transparent; color: var(--text); }
.strip-pop-models .strip-opt[aria-selected="true"] .strip-opt-label { font-weight: 600; }
.strip-pop-models .strip-opt:hover { background: var(--panel-2); }
.strip-pop-models .strip-opt.strip-opt-auto { background: var(--accent-soft); color: var(--accent-ink); }
.strip-pop-models .strip-opt.strip-opt-auto:hover { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.strip-opt-auto .strip-opt-label { font-weight: 600; }
.strip-opt-auto .strip-opt-icon .sd-ic { color: var(--accent); }

/* A card's title, and the tiles a ratio is drawn on: the aspect pill's card is the one
   place the shapes are, as a grid of them (`.strip-quick-pop .strip-grid`, below). */
.strip-pop-title { padding: 6px 8px 4px; font-size: 13px; font-weight: 600; color: var(--text); }
.strip-grid { display: grid; gap: 6px; }
.strip-opt.strip-tile {
  flex-direction: column; justify-content: center; min-height: 0;
  border: 1px solid var(--border); background: var(--panel); text-align: center;
}
.strip-opt.strip-tile:hover { background: var(--panel-2); }
.strip-opt.strip-tile.is-decided { border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); background: color-mix(in srgb, var(--accent) 7%, var(--panel)); }
.strip-tile .strip-opt-label { font-variant-numeric: tabular-nums; }
.strip-tile-shape { display: inline-flex; }

/* A quick pill's card, as the owner drew it: a white card over its pill with a small
   arrow pointing back at it, the title, the choice, and a footnote under a hairline.
   The card itself does not scroll — its body does — so the arrow can be drawn outside
   the card's edge without being clipped by it; `--strip-arrow-x` is where the pill's
   middle is, set by `stripPickPlace`. */
.strip-pop.strip-quick-pop { padding: 0; gap: 0; overflow: visible; border-radius: 12px; font-size: 13px; }
.strip-pop > .strip-quick-body { flex-shrink: 1; }
.strip-quick-body {
  display: flex; flex-direction: column; gap: 6px; min-height: 0; padding: 10px 10px 8px;
  overflow-y: auto; overscroll-behavior: contain; border-radius: inherit;
}
.strip-quick-body > * { flex-shrink: 0; }
.strip-quick-pop::after {
  content: ""; position: absolute; left: var(--strip-arrow-x, 50%); bottom: -7px; width: 12px; height: 12px;
  background: var(--panel); border: solid var(--border); border-width: 0 1px 1px 0;
  transform: translateX(-50%) rotate(45deg); pointer-events: none;
}
.strip-quick-pop[data-side="below"]::after { top: -7px; bottom: auto; border-width: 1px 0 0 1px; }
.strip-quick-pop .strip-pop-title { padding: 0 2px 2px; font-size: 13.5px; font-weight: 700; }
/* The rows touch, as the picture stacks them: the chosen one's tint is its own edge. */
.strip-radios { display: flex; flex-direction: column; gap: 0; }
/* The title of each medium's steps, on a job that makes both. */
.strip-quick-group {
  display: flex; align-items: center; gap: 6px; margin: 2px 2px -2px;
  font-size: 11px; font-weight: 600; color: var(--muted);
}
.strip-quick-group .sd-ic { flex: none; }
/* The round tick: the accent, filled, a white check in it — on the chosen tile's corner
   and at the chosen row's end. */
.strip-quick-tick {
  flex: none; display: inline-grid; place-items: center; width: 16px; height: 16px; margin-left: auto;
  border-radius: 50%; background: var(--accent); color: var(--on-accent);
}
.strip-quick-tick .sd-ic { width: 11px; height: 11px; stroke-width: 2.6; }
/* The rows: a framed picture, the name over its line, the tick — each row about a pill's
   height, as the picture has them. The chosen one on the accent's tint, its name and
   line in their own inks — the tick and the tint carry it. Every mark in the ink,
   «Automatica»'s included: the picture frames all four alike. */
.strip-opt.strip-quick-row { gap: 10px; min-height: 36px; padding: 3px 8px; border-radius: 9px; }
.strip-quick-row .strip-opt-icon .sd-ic { width: 18px; height: 18px; color: var(--ink-2); }
.strip-quick-row .strip-opt-text { gap: 0; }
.strip-quick-row .strip-opt-label { font-size: 13px; font-weight: 600; line-height: 1.3; }
.strip-quick-row .strip-opt-sub { font-size: 11px; line-height: 1.3; }
.strip-quick-row[aria-checked="true"] { background: var(--accent-soft); color: var(--text); }
/* «Automatiche» over the shapes: one row across the card on the card's own white,
   hairlined like the tiles under it, its sparkle in the ink of its word. */
.strip-pop-quick-aspect .strip-opt.strip-quick-row {
  min-height: 34px; padding: 4px 10px; border: 1px solid var(--border); background: var(--panel);
}
.strip-pop-quick-aspect .strip-opt.strip-quick-row:hover { background: var(--panel-2); }
.strip-pop-quick-aspect .strip-quick-row + .strip-quick-row { margin-top: 6px; }
.strip-pop-quick-aspect .strip-opt.strip-quick-row .strip-opt-label { font-weight: 500; }
.strip-pop-quick-aspect .strip-opt.strip-quick-row[aria-checked="true"] { border-color: var(--accent); background: var(--accent-soft); }
.strip-quick-auto .strip-opt-icon .sd-ic { color: var(--ink-2); }
/* The shapes three to a row, each tile on its own paper, the chosen one tinted and
   bordered in the accent with the tick riding its corner. */
/* Every name in the same semibold, the chosen one in the accent's ink at that weight:
   the picture tells the chosen tile by its tint, border and tick, not by a heavier word. */
.strip-quick-pop .strip-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; padding: 8px 0 2px; }
.strip-quick-pop .strip-opt.strip-tile { position: relative; height: 54px; gap: 5px; padding: 4px 2px; border-radius: 9px; }
.strip-quick-pop .strip-opt.strip-tile .strip-tile-shape { color: var(--ink-2); }
.strip-quick-pop .strip-tile .strip-opt-label { font-size: 11.5px; font-weight: 600; color: var(--text); }
.strip-quick-pop .strip-opt.strip-tile[aria-checked="true"] { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); }
.strip-quick-pop .strip-opt.strip-tile[aria-checked="true"] .strip-tile-shape,
.strip-quick-pop .strip-tile[aria-checked="true"] .strip-opt-label { color: var(--accent-ink); }
.strip-quick-pop .strip-tile .strip-quick-tick { position: absolute; top: -5px; right: -5px; box-shadow: 0 0 0 2px var(--panel); }
.strip-quick-note {
  margin: 0; padding: 7px 2px 0; border-top: 1px solid var(--border);
  font-size: 11px; line-height: 1.4; color: var(--muted);
}

/* Narrow: the box is the column, and at 1440 the column is some 418px wide. The container
   is the box's content — the bar's width, about 363px at 1440 and 317 at 1280 — and
   under 700px of it the models pill lets go of «Models:» and says what is chosen —
   «Auto», or the engine, cut with an ellipsis — while its name stays whole in
   `aria-label` and `title`. Under 400 the gaps and the paddings tighten by a few pixels,
   and under 340 the shape's chip keeps its mark alone — the mark is the shape, drawn in
   the accent when somebody chose it — and the modes their words at a smaller size: what
   the one line holds in Autopilot on a phone. In PRO the models and the sliders join it,
   and where they do not fit the last controls take a second line, Send keeping the
   right edge. Nothing ever passes the box. */
@container composer (max-width: 699.98px) {
  .strip-pick[data-look="models"] .strip-pick-frame { display: none; }
  .strip-pick[data-look="models"] { padding: 0 7px 0 10px; }
}
/* **Lines, not hidden values** (the owner's word of 2026-10-24): in a box narrower than the
   starting page's — the director's column — the attach, the modes and Send make the first
   line, under the words, and the three levers, model, shape and steps, the whole line under
   it, so each can say what it holds. A lever that does not fit beside the others takes the
   next line rather than cutting the model's name to «Na…» (a picture-and-video job names two
   engines); only a name longer than the whole line is cut, and it is whole on the tooltip.
   On the starting page's wide box the bar is one line, as the mockup draws it; narrow, its
   «Start creating» is the box's last line, the width of the box. */
@container composer (max-width: 599.98px) {
  .composer-bar { flex-wrap: wrap; align-items: center; row-gap: 7px; }
  .composer-tools { display: contents; }
  .composer-bar #chat-send { order: 1; }
  .composer-tools > .pro-strip:not([hidden]) { order: 2; display: flex; flex: 1 0 100%; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
  .pro-strip > .strip-pick.strip-quick,
  .pro-strip > .strip-pick.strip-quick.strip-note[data-key="models"],
  .pro-strip > .strip-field,
  .pro-strip > .strip-field > .strip-pick[data-look="models"] { flex: none; min-width: 0; max-width: 100%; }
  .chat-view[data-fresh] .composer-bar #chat-send { order: 3; flex: 1 0 100%; justify-content: center; }
}
/* A phone's starting page: the attach button gives its word back, so the modes stay beside
   it on the first line. */
@container composer (max-width: 419.98px) {
  .chat-view[data-fresh] .attach-word { display: none; }
  .chat-view[data-fresh] .btn.icon.composer-attach { width: 36px; padding: 0; }
}
@container composer (max-width: 400px) {
  .composer-bar, .composer-tools { gap: 5px; }
  .composer-bar .mode { padding: 0 9px; }
  .strip-pick.strip-quick { gap: 5px; padding: 0 10px 0 8px; }
}
/* The levers' own line is the one that gets tight: their paddings first, then the values
   cut with an ellipsis — never dropped, since what each holds is what the line is for. The
   whole value stays their accessible name and their tooltip (`aria-labelledby`, `title`). */
@container composer (max-width: 339.98px) {
  .composer-bar .mode { padding: 0 8px; font-size: 12px; }
  .strip-pick.strip-quick { padding: 0 8px; }
}
/* A phone: a little less air everywhere. */
@container composer (max-width: 299.98px) {
  .composer-bar, .composer-tools { gap: 4px; }
  .composer-bar .mode { padding: 0 7px; font-size: 11.5px; }
  .strip-pick.strip-quick { padding: 0 7px; gap: 4px; }
}
/* The box's own padding gives a few pixels back on a phone, where they are the difference
   between one line and two. Read off the column, since the box's own width is the query. */
@container composer (max-width: 299.98px) {
  .composer-bar #chat-send { width: 34px; height: 34px; }
}

/* A finger is wider than a pointer: the rows grow to the 44px the rest of the studio
   holds its targets to, and the chips to 36px, which with the 6px between them clears
   the 24px minimum of WCAG 2.5.8 with room to spare. */
@media (pointer: coarse) {
  .strip-opt:not(.strip-tile) { min-height: 44px; }
  .strip-pick { height: 36px; }
}

@media (max-width: 620px) {
  /* On a phone the bar's container query has already given the levers a line of their
     own; a chip in it may take that line's width. */
  .strip-pick { max-width: 100%; }
  .sheet { padding: 0; }
  .sheet-card { width: 100vw; max-height: 100dvh; height: 100dvh; border-radius: 0; border: 0; }
}

/* ======================== THE STUDIO ========================
   Three editors on one screen, dressed against the one in `editor/` — which is the
   only part of this product anybody has called good-looking, so its tokens are
   copied rather than re-invented: a near-white ground, a light stage with a dot
   grid, white panels hairlined in #EAEAEE, radii of 8/11/16, and two shadows that
   are barely there.

   Three rules hold the whole block together, and each one is a mistake the first
   attempt made:

   - **The chrome is thin and the stage is everything else.** An editor is judged
     by how much room the work gets. There is one bar, one toolbar, one dock; the
     title and the paragraph that used to sit above them are gone.
   - **Nothing is an emoji.** Every glyph is a stroked SVG at 1.7, the same weight
     as the navigation rail, which is what makes the sidebar and the editors read
     as one application rather than two.
   - **One accent, used once per view.** The magenta marks what is selected and
     the single action that commits. Spread over every control it stops meaning
     anything, which is what a row of pink buttons taught. */
/* The editor's own scale, scoped so the rest of the app keeps its own — and shared
   with the image editor when it opens over the conversation, which is the same
   editor and draws with the same tokens. */
.studio-view, .edov-retouch {
  --sd-stage: #E9E9EE;
  --sd-line: #EAEAEE;
  --sd-field: #F5F5F7;
  --sd-r-sm: 8px;
  --sd-r-md: 11px;
  --sd-r-lg: 16px;
  --sd-sh-1: 0 1px 2px rgba(24, 24, 27, .05);
  --sd-sh-2: 0 4px 16px -4px rgba(24, 24, 27, .12);
  --sd-sh-pop: 0 12px 32px -8px rgba(24, 24, 27, .22), 0 2px 6px rgba(24, 24, 27, .08);
  /* A scene's colour on the timeline (docs/motion.md), the same in both themes as every bar
     of it is: its bar over the video and the ink on it — 8.83:1 — and its block on the video
     row, under the clips' white label chip, 8.82:1 against that chip. */
  --sd-scene: #d9ecff;
  --sd-on-scene: #133e74;
  --sd-scene-block: #1f4a86;
}
.studio-view { display: flex; flex-direction: column; height: calc(100dvh - 34px); min-height: 540px; gap: 0; }
:root[data-theme="dark"] .studio-view, :root:not([data-theme="light"]) .studio-view,
:root[data-theme="dark"] .edov-retouch, :root:not([data-theme="light"]) .edov-retouch {
  --sd-stage: #16161b;
  --sd-line: rgba(255, 255, 255, .09);
  --sd-field: rgba(255, 255, 255, .05);
}

/* ---------- the Studio's front page (studio-home.js) ----------
   What the menu's entry lands on: the two doors, the tools, the pieces to pick up. The
   editors' chrome is taken out while it is up rather than hidden behind it, and the view
   gives up the fixed height the editors need, so the page scrolls like every other one. */
.studio-view[data-home] { height: auto; min-height: 0; }
.studio-view[data-home] > :not(.sh) { display: none; }
.sh { display: flex; flex-direction: column; }
.sh[hidden] { display: none; }
.sh-page { width: 100%; max-width: var(--page-max); margin: 0 auto; padding: 0 0 36px; }

/* The two doors: a picture of the editor over its name, the whole card one button. */
.sh-doors { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; margin: 36px 0 48px; }
.sh-door, .sh-tool, .sh-piece, .sh-all { font: inherit; color: inherit; text-align: left; cursor: pointer; }
.sh-door {
  display: flex; flex-direction: column; min-width: 0; padding: 0; overflow: hidden;
  border: 1px solid var(--border); border-radius: 18px; background: var(--panel);
  box-shadow: 0 1px 2px rgba(24, 24, 27, .04);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.sh-door:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); box-shadow: 0 16px 36px -16px rgba(24, 24, 27, .24); }
.sh-door:focus-visible, .sh-tool:focus-visible, .sh-piece:focus-visible, .sh-all:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sh-door-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 22px 26px 24px; }
.sh-door-words { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.sh-door-t { font-size: 22px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.sh-door-s { font-size: 14px; color: var(--muted); }
.sh-arrow {
  flex: none; display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent-ink);
}

/* The pictures. Drawn, so they follow the width and the theme; their colours are the
   brand's and stay what they are, only the grounds and the white cards go dark. */
.sh-art { position: relative; height: 240px; overflow: hidden; }
.sh-art-design {
  background-color: #fbe4ee;
  background-image: linear-gradient(rgba(236, 30, 121, .08) 1px, transparent 1px), linear-gradient(90deg, rgba(236, 30, 121, .08) 1px, transparent 1px);
  background-size: 28px 28px;
}
.sh-a-tools, .sh-a-swatches, .sh-a-chip, .sh-a-timeline { background: #fff; box-shadow: 0 8px 18px -10px rgba(24, 24, 27, .35); }
.sh-a-tools {
  position: absolute; left: 6%; top: 50%; transform: translateY(-50%);
  display: flex; flex-direction: column; gap: 14px; padding: 12px 9px; border-radius: 12px; color: #3a3a55;
}
.sh-a-poster {
  position: absolute; left: 35%; top: 12px; width: 30%; height: 112%; padding: 16px 14px;
  display: flex; flex-direction: column; overflow: hidden; border-radius: 4px; transform: rotate(-3deg);
  background: linear-gradient(160deg, #f0277f, #d41266); color: #fff; box-shadow: 0 20px 34px -18px rgba(150, 10, 70, .65);
}
.sh-a-poster-top, .sh-a-poster-foot { position: relative; font-size: 7px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; opacity: .85; }
.sh-a-poster-sun {
  position: absolute; right: -16%; top: 12%; width: 64%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #ffd8a0, #f39a5c 58%, #e2587c);
}
.sh-a-poster-t {
  position: relative; margin: 34% 0 0; font-family: Georgia, "Times New Roman", serif; font-style: italic; font-weight: 700;
  font-size: clamp(20px, 2.5vw, 34px); line-height: .95; transform: rotate(-5deg);
}
.sh-a-poster-foot { margin-top: 14px; }
.sh-a-swatches { position: absolute; right: 7%; top: 52px; display: flex; gap: 6px; padding: 8px 10px; border-radius: 999px; }
.sh-a-dot { width: 13px; height: 13px; border-radius: 50%; }
.sh-a-dot-a { background: #ec1e79; }
.sh-a-dot-b { background: #f6b8d2; }
.sh-a-dot-c { background: #f2c94c; }
.sh-a-dot-d { background: #12123a; }
.sh-a-chip {
  position: absolute; right: 6%; bottom: 40px; display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 11px; border-radius: 6px; font-size: 10px; color: #3a3a55;
}
.sh-a-chip-dot { width: 6px; height: 6px; border-radius: 50%; background: #ec1e79; }
.sh-art-video { background: linear-gradient(160deg, #eee8fc, #dcd2f6); }
.sh-a-screen {
  position: absolute; left: 19%; right: 15%; top: 4px; height: 64%; padding: 18px 22px; overflow: hidden;
  border-radius: 8px; transform: rotate(2.5deg); color: #fff;
  background: linear-gradient(135deg, #24103a, #3b1a56 60%, #5a2a7a); box-shadow: 0 20px 34px -18px rgba(40, 10, 70, .65);
}
.sh-a-screen-t {
  position: relative; z-index: 1; display: block; max-width: 55%;
  font-family: Georgia, "Times New Roman", serif; font-style: italic; font-size: clamp(18px, 2.2vw, 28px); line-height: 1.05;
}
.sh-a-orb {
  position: absolute; right: -6%; top: 8%; width: 46%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f5c6ff, #b56bf0 45%, #6c2bb0 80%);
}
.sh-a-play {
  position: absolute; right: 20%; top: 38%; z-index: 1; display: grid; place-items: center; width: 36px; height: 36px;
  border-radius: 50%; border: 1px solid rgba(255, 255, 255, .5); background: rgba(255, 255, 255, .22); color: #fff;
}
.sh-a-screen-foot { position: absolute; left: 22px; bottom: 14px; z-index: 1; font-size: 7px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; opacity: .8; }
.sh-a-timeline {
  position: absolute; left: 11%; right: 11%; bottom: 12px; height: 38%; padding: 8px 12px;
  display: flex; flex-direction: column; justify-content: center; gap: 5px; border-radius: 8px; transform: rotate(-2deg);
}
.sh-a-ruler { display: flex; justify-content: space-between; font-size: 7px; color: #9a97ad; }
.sh-a-clips { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.sh-a-clip { height: 16px; border-radius: 3px; background: linear-gradient(90deg, #7d4fbe, #a77ad2); }
.sh-a-clip:nth-child(2) { background: linear-gradient(90deg, #c07ab6, #d9a3c9); }
.sh-a-clip:nth-child(3) { background: linear-gradient(90deg, #8b5ec9, #b28ad8); }
.sh-a-clip:nth-child(4) { background: linear-gradient(90deg, #b07fc4, #d1a8d4); }
.sh-a-wave { height: 10px; border-radius: 3px; background: repeating-linear-gradient(90deg, #8fd9b6 0 2px, transparent 2px 4px), #e7f8ef; }
.sh-a-head { position: absolute; left: 40%; top: 7px; bottom: 5px; width: 2px; border-radius: 1px; background: #ec1e79; }
.sh-a-head::before { content: ""; position: absolute; top: -3px; left: -3px; width: 8px; height: 8px; border-radius: 2px; background: #ec1e79; }
:root[data-theme="dark"] .sh-art-design { background-color: color-mix(in srgb, #ec1e79 14%, var(--panel)); }
:root[data-theme="dark"] .sh-art-video { background: linear-gradient(160deg, color-mix(in srgb, #8b5cf6 18%, var(--panel)), color-mix(in srgb, #8b5cf6 28%, var(--panel))); }
:root[data-theme="dark"] .sh-a-dot-d { box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .35); }
:root[data-theme="dark"] .sh-a-tools, :root[data-theme="dark"] .sh-a-swatches,
:root[data-theme="dark"] .sh-a-chip, :root[data-theme="dark"] .sh-a-timeline { background: var(--panel-2); color: var(--text); }

/* A row's heading, with what goes with it on the right. */
.sh-row-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin: 0 0 14px; }
.sh-row-say { font-size: 13px; color: var(--muted); }
.sh-all { display: inline-flex; align-items: center; gap: 6px; padding: 4px 0; border: 0; background: none; font-size: 13px; color: var(--muted); }
.sh-all:hover { color: var(--ink); }

/* The tools: three cards in a row. */
.sh-tools { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; margin: 0 0 44px; }
.sh-tool {
  display: flex; align-items: center; gap: 14px; min-width: 0; padding: 20px 20px; border: 1px solid var(--border);
  border-radius: 14px; background: var(--panel); transition: border-color .15s ease, box-shadow .15s ease;
}
.sh-tool:hover { border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); box-shadow: 0 10px 24px -16px rgba(24, 24, 27, .3); }
.sh-tool-ic { flex: none; display: inline-grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; background: var(--accent-soft); color: var(--accent-ink); }
.sh-tool-words { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.sh-tool-t { font-size: 15px; font-weight: 600; color: var(--ink); }
.sh-tool-s { font-size: 13px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-tool .sh-arrow { width: 28px; height: 28px; background: none; color: var(--muted); }

/* The pieces to pick up: one row of three. */
.sh-recent { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.sh-recent-say { grid-column: 1 / -1; margin: 0; padding: 18px 0; font-size: 14px; color: var(--muted); }
.sh-piece { display: flex; align-items: center; gap: 14px; min-width: 0; padding: 6px; border: 0; border-radius: 12px; background: none; }
.sh-piece:hover { background: var(--panel-2); }
.sh-piece-thumb {
  position: relative; flex: none; display: grid; place-items: center; width: 76px; height: 72px; overflow: hidden;
  border-radius: 10px; background: var(--panel-2); color: var(--muted); border: 1px solid var(--border);
}
.sh-piece-thumb img { width: 100%; height: 100%; object-fit: cover; }
.sh-piece-play { position: absolute; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: rgba(18, 18, 58, .55); color: #fff; }
.sh-piece-words { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.sh-piece-t { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sh-piece-now { flex: none; padding: 2px 7px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); font-size: 11px; font-weight: 600; }
.sh-piece-s { font-size: 13px; color: var(--muted); }

/* The Image Editor's start page, as the owner's mockup draws it: the way back to the Studio
   over the page, the question on the left over three fanned sheets, the three roads as wide
   cards one under another on the right, each with its pastel picture and its button, and the
   three formats as chips under them. Every child names its track. The question is the page's
   title, in the page's own type (`.page-title`). */
.sh > .sh-crumbs { width: 100%; max-width: var(--page-max); margin: 0 auto; }
.sh-crumbs { display: flex; align-items: center; gap: 10px; font-size: 15px; color: var(--muted); }
.sh-crumb { padding: 0; border: 0; background: none; font: inherit; color: var(--muted); cursor: pointer; }
.sh-crumb:hover { color: var(--ink); text-decoration: underline; }
.sh-crumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.sh-crumb-now { color: var(--muted); }

.sh-start {
  display: grid; grid-template-columns: minmax(0, 4.3fr) minmax(0, 7fr); grid-template-rows: auto auto;
  gap: 30px 48px; align-items: start; padding-top: 40px;
}
.sh-start-hero { grid-column: 1; grid-row: 1 / span 2; align-self: center; padding-left: 4%; }
.sh-roads { grid-column: 2; grid-row: 1; display: flex; flex-direction: column; gap: 18px; }
.sh-start-formats { grid-column: 2; grid-row: 2; }
.sh-start .sh-title { max-width: 9em; }

/* The three sheets under the question, fanned like the mockup's: lilac at the back, pink,
   the white page in front. */
.sh-start-art { position: relative; width: 280px; height: 250px; margin: 56px 0 0 44px; }
.sh-sa-sheet { position: absolute; width: 172px; height: 212px; border-radius: 16px; }
.sh-sa-lilac { left: 0; top: 34px; transform: rotate(-12deg); background: #f1eefb; box-shadow: 0 18px 40px -26px rgba(18, 18, 58, .35); }
.sh-sa-pink { left: 34px; top: 20px; transform: rotate(-6deg); background: #fbe4ee; box-shadow: 0 18px 40px -26px rgba(18, 18, 58, .35); }
.sh-sa-white { left: 80px; top: 0; transform: rotate(5deg); background: #fff; box-shadow: 0 30px 60px -28px rgba(18, 18, 58, .4), 0 2px 6px rgba(18, 18, 58, .05); }

.sh-road, .sh-format { font: inherit; color: inherit; text-align: left; cursor: pointer; }
.sh-road {
  display: grid; grid-template-columns: 140px minmax(0, 1fr) auto; align-items: center; gap: 24px;
  min-width: 0; padding: 20px 24px 20px 20px;
  border: 1px solid var(--border); border-radius: 18px; background: var(--panel);
  box-shadow: 0 1px 2px rgba(24, 24, 27, .04); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.sh-road:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); box-shadow: 0 16px 36px -16px rgba(24, 24, 27, .24); }
.sh-road:focus-visible, .sh-format:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sh-road-words { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.sh-road-t { font-size: 23px; font-weight: 700; letter-spacing: -.02em; line-height: 1.2; color: var(--ink); }
.sh-road-s { font-size: 16px; line-height: 1.4; color: var(--muted); }
.sh-road-types { margin-top: 6px; font-size: 14px; color: var(--muted); }
.sh-road-go {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px; width: 236px; height: 60px; padding: 0 20px;
  border-radius: 10px; border: 1.5px solid color-mix(in srgb, var(--ink) 16%, var(--border)); background: var(--panel);
  font-size: 17px; font-weight: 600; color: var(--ink); white-space: nowrap;
}
.sh-road-go.primary { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.sh-road:hover .sh-road-go:not(.primary) { border-color: var(--accent); color: var(--accent-ink); }
.sh-road:hover .sh-road-go.primary { background: var(--accent-hi); border-color: var(--accent-hi); }

/* The roads' pictures: a pastel tile, the sheets on it. */
.sh-road-art { position: relative; display: block; width: 140px; height: 132px; border-radius: 16px; overflow: hidden; }
.sh-road-art-blank { background: #fbe4ee; }
.sh-road-art-upload { background: #eeeafb; }
.sh-road-art-templates { background: #fdf0e3; }
.sh-ra-sheet {
  position: absolute; display: grid; place-items: center; width: 86px; height: 86px; border-radius: 12px;
  background: #fff; color: #5f6680; box-shadow: 0 10px 22px -12px rgba(18, 18, 58, .4);
}
.sh-road-art-blank .sh-ra-sheet { left: 26px; top: 22px; width: 88px; height: 88px; transform: rotate(-8deg); color: var(--accent); }
.sh-road-art-upload .sh-ra-sheet { left: 24px; top: 24px; transform: rotate(-9deg); }
.sh-ra-badge {
  position: absolute; right: 18px; bottom: 22px; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%;
  background: #fff; color: var(--ink); box-shadow: 0 8px 18px -8px rgba(18, 18, 58, .45);
}
.sh-road-art-templates .sh-ra-back { left: 18px; top: 38px; width: 68px; height: 68px; transform: rotate(-8deg); }
.sh-road-art-templates .sh-ra-front { right: 14px; top: 22px; width: 60px; height: 60px; transform: rotate(7deg); background: #f3efff; color: #4b3fb8; }

/* The formats: a heading and three chips in a row. */
.sh-formats-t { margin: 18px 0 16px; font-size: 18px; font-weight: 500; color: var(--muted); }
.sh-formats { display: flex; flex-wrap: wrap; gap: 14px; }
.sh-format {
  display: inline-flex; align-items: center; gap: 10px; min-width: 0; height: 56px; padding: 0 22px 0 20px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel); transition: border-color .15s ease, box-shadow .15s ease;
  font-size: 16px; white-space: nowrap;
}
.sh-format:hover { border-color: color-mix(in srgb, var(--accent) 30%, var(--border)); box-shadow: 0 10px 24px -16px rgba(24, 24, 27, .3); }
.sh-format-shape { flex: none; height: 22px; max-width: 22px; margin-right: 6px; border-radius: 3px; border: 2px solid var(--ink); background: none; }
.sh-format-t { color: var(--ink); }
.sh-format-dot, .sh-format-s { color: var(--muted); }

:root[data-theme="dark"] .sh-road-art-blank { background: color-mix(in srgb, #ec1e79 16%, var(--panel)); }
:root[data-theme="dark"] .sh-road-art-upload { background: color-mix(in srgb, #8b5cf6 18%, var(--panel)); }
:root[data-theme="dark"] .sh-road-art-templates { background: color-mix(in srgb, #f59e0b 16%, var(--panel)); }
:root[data-theme="dark"] .sh-ra-sheet, :root[data-theme="dark"] .sh-ra-badge { background: var(--panel-2); color: var(--text); }
:root[data-theme="dark"] .sh-sa-white { background: var(--panel-2); }
:root[data-theme="dark"] .sh-sa-pink { background: color-mix(in srgb, #ec1e79 18%, var(--panel)); }
:root[data-theme="dark"] .sh-sa-lilac { background: color-mix(in srgb, #8b5cf6 18%, var(--panel)); }

@media (max-width: 1100px) {
  .sh-start { grid-template-columns: minmax(0, 1fr); gap: 28px; padding-top: 36px; }
  .sh-start-hero { grid-column: 1; grid-row: 1; padding-left: 0; }
  .sh-roads { grid-column: 1; grid-row: 2; }
  .sh-start-formats { grid-column: 1; grid-row: 3; }
  .sh-start-art { display: none; }
}
@media (max-width: 900px) {
  /* On a phone a road is its picture beside its words, and its button under both. */
  .sh-road { grid-template-columns: 88px minmax(0, 1fr); gap: 14px 16px; padding: 16px; }
  .sh-road-art { grid-column: 1; width: 88px; height: 84px; transform: scale(1); }
  .sh-road-art .sh-ra-sheet { transform-origin: top left; scale: .58; }
  .sh-road-art .sh-ra-badge { scale: .7; right: 8px; bottom: 10px; }
  .sh-road-words { grid-column: 2; }
  .sh-road-t { font-size: 19px; }
  .sh-road-s { font-size: 15px; }
  .sh-road-go { grid-column: 1 / -1; min-width: 0; width: 100%; height: 52px; font-size: 16px; }
  .sh-formats { flex-direction: column; gap: 10px; }
  .sh-format { width: 100%; }
  .sh-doors { grid-template-columns: 1fr; gap: 16px; margin: 28px 0 36px; }
  .sh-tools, .sh-recent { grid-template-columns: 1fr; gap: 10px; }
  .sh-art { height: 200px; }
  .sh-row-say { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .sh-door, .sh-tool, .sh-road, .sh-format { transition: none; }
  .sh-door:hover, .sh-road:hover { transform: none; }
}

/* ---------- the one bar ----------
   Two rows, declared rather than wrapped. `flex-wrap` with the actions pushed right
   by `margin-left: auto` produced a different bar per tab: the picture's five slots
   fitted on one line and the banner's ten pushed the name and the Export button
   onto a third, costing ninety pixels of stage on the tab that needs them most.
   A grid says it once: what the screen is on the left of row one, what is done to
   it on the right, the sizes underneath. */
/* One row, and what acts on the document is on the right, because that is the hand's
   side. The slot's size left this row entirely — it is about the document's shape, and
   it sits over the document now. */
/* The header every mockup shares: a breadcrumb over a title, the state of the save
   beside it, and on the right the history and the way out. Two tracks and no line
   under it — the cards below are what separates the header from the work. */
/* Two tracks: where you are on the left — the way back, the name, the state of its save —
   and what acts on the piece on the right. There is no switch between the two editors in
   the middle any more (the owner's word, 2026-10-24): a piece opens on the editor it was
   made in, and the other is reached from the Studio's front page. The two ends are at
   least as wide as what is in them — a name squeezed under its own text is a name nobody
   can read — and under the width where they stop fitting the ways out take a row of their
   own (further down). Every child names its track: the video editor's slots fill and empty
   with the mode. */
.sd-bar {
  display: grid; grid-template-columns: minmax(max-content, 1fr) auto;
  align-items: center; gap: 16px; padding: 0 2px 8px; flex: 0 0 auto;
}
.sd-bar-start { grid-column: 1; display: flex; align-items: flex-start; gap: 6px; min-width: 0; }
.sd-bar-end { grid-column: 2; grid-row: 1; display: flex; align-items: center; gap: 10px; justify-self: end; }
/* What the video editor brings up into the bar: the arrows beside the state of the
   save, behind a hairline as the mockup draws them, and the size before the ways
   out. Empty in Design, where both are over the canvas. */
.sd-bar-slot { display: inline-flex; align-items: center; gap: 2px; }
.sd-bar-slot:empty { display: none; }
.sd-bar-edit { padding-left: 12px; border-left: 1px solid var(--sd-line); }
.sd-bar-fmt { gap: 6px; }
.sd-bar-fmt .sd-fmt-btn { height: 42px; border-radius: 12px; }
/* A target of 28 pixels, from 22 — under the 24 a pointer is promised — with margins that
   give the six back, so the arrow and the name beside it stand where they did. */
.sd-back {
  display: inline-grid; place-items: center; width: 28px; height: 28px; margin: -5px -3px -3px; padding: 0;
  border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer;
}
.sd-back svg { width: 16px; height: 16px; }
.sd-back:hover { background: var(--panel-2); color: var(--text); }
.sd-titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sd-crumb { display: flex; align-items: center; gap: 7px; margin: 0; line-height: 18px; font-size: 13px; color: var(--muted); }
.sd-crumb-sep { opacity: .6; }
.sd-title-row { display: flex; align-items: center; gap: 14px; min-width: 0; }

/* The name is the page's heading and is typed into where it stands. The pencil after
   it says so: an input with no border reads as a heading somebody forgot to style,
   and one with a border reads as a form. */
.sd-name-wrap {
  display: inline-flex; align-items: center; gap: 8px; min-width: 0; padding: 2px 4px 2px 0;
  border-radius: 8px; cursor: text;
}
.sd-name-wrap:focus-within { box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-name { min-width: 0; }
.sd-name-ic {
  display: inline-grid; place-items: center; width: 28px; height: 28px; flex: 0 0 auto;
  border-radius: 50%; background: var(--sd-field); color: var(--muted);
}
.sd-name-ic svg { width: 14px; height: 14px; }

/* The state of the save, which is the button that changes it. Three states and one
   control: a tick when there is nothing to write, the word when there is, and neither
   while it is happening. «Saved» is the green pill the mockups draw; the dirty one is
   the only one that asks to be pressed, so it is the only one that carries the accent. */
.sd-save {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 14px;
  border: 1px solid transparent; border-radius: 999px; background: var(--panel);
  color: var(--muted); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
  white-space: nowrap;
}
.sd-save svg { width: 14px; height: 14px; }
.sd-save:hover { background: var(--panel-2); color: var(--text); }
.sd-save[data-state="clean"] { background: var(--ok-soft, #e8f7ee); color: var(--ok, #2f9e5e); cursor: default; }
.sd-save[data-state="clean"]:hover { background: var(--ok-soft, #e8f7ee); color: var(--ok, #2f9e5e); }
.sd-save[data-state="dirty"] { border-color: var(--accent-line); color: var(--accent); }
.sd-save[data-state="saving"] { opacity: .6; cursor: progress; }

/* The outlined button beside Export, which is what «Revisions» is in every mockup. */
.sd-ghost-b {
  display: inline-flex; align-items: center; gap: 8px; height: 42px; padding: 0 16px;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel);
  color: var(--text); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
  box-shadow: var(--sd-sh-1);
}
.sd-ghost-b svg { width: 17px; height: 17px; color: var(--muted); }
.sd-ghost-b:hover { border-color: var(--border); background: var(--panel-2); }
.sd-ghost-b[aria-expanded="true"] { border-color: var(--accent-line); }

/* The brand card at the foot of the Page panel: a colour, two lines, a chevron. */
.sd-brand-card {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 12px 14px; text-align: left;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel); color: var(--text);
  font: inherit; cursor: pointer;
}
.sd-brand-card:hover { border-color: var(--accent-line); }
.sd-brand-card > span:nth-child(2) { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.sd-brand-card b { font-size: 13.5px; font-weight: 600; }
.sd-brand-card small { font-size: 12px; color: var(--muted); }
.sd-brand-card svg { transform: rotate(-90deg); color: var(--muted); }
.sd-brand-dot { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%; background: var(--sd-field); border: 1px solid var(--sd-line); }

/* The export's own settings, under the kinds in its menu. */
.sd-export-extras { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; padding: 10px 6px 4px; border-top: 1px solid var(--sd-line); }
.sd-export-extras .sd-slider { padding: 0 3px 6px; }
.sd-more-pop.sd-export-pop { min-width: 300px; }
.sd-pop-note { margin: 2px 3px; font-size: 11.5px; line-height: 1.45; color: var(--muted); }
/* «Export» in the video editor, as the owner's mockup draws it: the video on a card of its
   own, tinted with the accent and with its way on at the right; then «Download extra files»,
   each file a row with its glyph, its name over a line saying what it is for, and its kind
   on a badge. */
.sd-more-pop.sd-export-pop.sd-xm { min-width: 0; width: min(380px, calc(100vw - 32px)); padding: 10px; gap: 2px; border-radius: 16px; }
.sd-xm-row {
  display: grid; grid-template-columns: 22px minmax(0, 1fr) auto; align-items: center; column-gap: 14px;
  width: 100%; padding: 11px 12px; border: 0; border-radius: 12px; background: transparent;
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.sd-xm-row:hover { background: var(--panel-2); }
.sd-xm-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.sd-xm-row[aria-disabled="true"] { opacity: .45; cursor: default; }
.sd-xm-row[aria-disabled="true"]:hover { background: transparent; }
.sd-xm-ic { display: grid; place-items: center; color: var(--muted); }
.sd-xm-words { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sd-xm-words b { font-size: 14px; font-weight: 600; }
.sd-xm-words small { font-size: 12.5px; line-height: 1.35; color: var(--muted); }
.sd-xm-badge {
  padding: 3px 7px; border: 1px solid var(--sd-line); border-radius: 6px;
  font-size: 11px; font-weight: 700; letter-spacing: .04em; color: var(--muted);
}
.sd-xm-main { padding: 14px 12px; background: var(--accent-soft); }
.sd-xm-main:hover { background: var(--accent-soft); box-shadow: inset 0 0 0 1px var(--accent-line); }
.sd-xm-main .sd-xm-ic, .sd-xm-main .sd-xm-words b { color: var(--accent); }
.sd-xm-main > svg { color: var(--muted); }
.sd-xm-head { margin: 14px 12px 4px; font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.sd-xm-sep { margin: 6px 12px; border: 0; border-top: 1px solid var(--sd-line); }

/* The history: what changed, and how long ago, one row per step. */
.sd-more-pop.sd-history-pop { min-width: 300px; max-height: 60vh; overflow-y: auto; }
.sd-pop-head { margin: 4px 9px 6px; font-size: 11px; font-weight: 700; color: var(--muted); }
.sd-pop-none { margin: 2px 9px 8px; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-history-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.sd-history-row small { flex: 0 0 auto; font-size: 11px; color: var(--muted); }

/* ---------- the video editor's bar ----------
   As the owner's mockups 23–24 draw it: the name, the two arrows and the state of the save
   beside them between hairlines; at the right the history as a glyph, the pink «Export»
   with its arrow, and the dots. **And the switch between the two editors in the middle, as
   in the Design**: the owner had it under the name as «Video editor ▾» for a week, and asked
   for «Design | Video editor» back where it is in the other editor — the place where you
   are is read in one place in both. Every rule is the video editor's alone; the Design's
   bar is the one above. */
/* The title block a grid of its own: the name, then the arrows and the save. `display:
   contents` lets the row's three children take the block's tracks, in the order they are read. */
.studio-view[data-mode="video"] .sd-titles {
  display: grid; grid-template-columns: auto auto auto; align-items: center; gap: 0;
}
.studio-view[data-mode="video"] .sd-title-row { display: contents; }
/* `margin: 0` because the name's box is a `<label>`, and every label has the form's 10px. */
.studio-view[data-mode="video"] .sd-name-wrap { grid-column: 1; grid-row: 1; margin: 0; }
.studio-view[data-mode="video"] .sd-bar-edit {
  grid-column: 2; grid-row: 1; height: 40px; margin-left: 18px; padding: 0 12px;
  border-right: 1px solid var(--sd-line);
}
.studio-view[data-mode="video"] .sd-save { grid-column: 3; grid-row: 1; margin-left: 10px; padding: 0 10px; font-size: 14px; }
.studio-view[data-mode="video"] .sd-name { height: 26px; font-size: 18px; font-weight: 600; letter-spacing: -.01em; }
/* The pencil while the name is pointed at or typed in: the mockups draw the name alone. */
.studio-view[data-mode="video"] .sd-name-ic { width: 24px; height: 24px; opacity: 0; transition: opacity .12s ease; }
.studio-view[data-mode="video"] .sd-name-wrap:hover .sd-name-ic,
.studio-view[data-mode="video"] .sd-name-wrap:focus-within .sd-name-ic { opacity: 1; }
/* «Saved» is the mockups' quiet green word with its cloud, not the Design's pill: `--ok` on
   the page's ground, 6.1:1 in the light theme. */
.studio-view[data-mode="video"] .sd-save[data-state="clean"],
.studio-view[data-mode="video"] .sd-save[data-state="clean"]:hover { background: transparent; color: var(--ok); }
.studio-view[data-mode="video"] .sd-save svg { width: 18px; height: 18px; }
/* The history as its glyph, its word kept for a screen reader (and its tooltip). */
.studio-view[data-mode="video"] #sd-history {
  width: 42px; padding: 0; justify-content: center; border-color: transparent; background: transparent; box-shadow: none;
}
.studio-view[data-mode="video"] #sd-history:hover,
.studio-view[data-mode="video"] #sd-history[aria-expanded="true"] { background: var(--panel-2); }
.studio-view[data-mode="video"] #sd-history svg { width: 21px; height: 21px; color: var(--text); }
.studio-view[data-mode="video"] #sd-history > span {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* «Export» with the arrow out of the editor, white on the accent as `--on-accent` pairs it. */
.sd-go-ic { display: none; }
.studio-view[data-mode="video"] .sd-go { display: inline-flex; align-items: center; gap: 10px; color: var(--on-accent); }
.studio-view[data-mode="video"] .sd-go-ic { display: block; flex: 0 0 auto; }
/* On a phone the name has the block's first line to itself, and the arrows and the save
   share the second. */
@media (max-width: 620px) {
  .studio-view[data-mode="video"] .sd-titles { grid-template-columns: auto minmax(0, 1fr); row-gap: 2px; }
  .studio-view[data-mode="video"] .sd-name-wrap { grid-column: 1 / -1; }
  .studio-view[data-mode="video"] .sd-bar-edit { grid-column: 1; grid-row: 2; height: 30px; margin-left: 2px; padding: 0 2px; }
  .studio-view[data-mode="video"] .sd-bar-edit .sd-icon-b { width: 28px; height: 28px; }
  .studio-view[data-mode="video"] .sd-save { grid-column: 2; grid-row: 2; justify-self: start; height: 30px; margin-left: 2px; padding: 0 6px; font-size: 13px; }
}

/* ---------- the canvas row ----------
   Over the canvas, what is about the canvas: the arrows on the left, the two ways of
   looking at the piece in the middle, the slot's size and full screen on the right.
   Three tracks so the middle stays in the middle whatever the two ends carry. */
/* Two ends, since the switch went up into the bar: the arrows on the left, the
   slot's size and full screen on the right. And none of it in the video editor,
   whose row over the stage is the clip's own tools. */
.sd-head {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 0 4px 10px;
}
.studio-view[data-mode="video"] .sd-head { display: none; }
/* Nor the breadcrumb over the name: the video editor's bar is one line in the mockup,
   and the twenty-four pixels are the picture's. The arrow back comes down beside the
   name it was over. */
.studio-view[data-mode="video"] .sd-crumb { display: none; }
.studio-view[data-mode="video"] .sd-bar-start { align-items: center; }
.studio-view[data-mode="video"] .sd-back { margin-top: -3px; }
.sd-head-start { display: flex; align-items: center; gap: 4px; }
.sd-head-end { display: flex; align-items: center; justify-content: flex-end; gap: 8px; }
.sd-head .sd-custom { margin: 0; }
/* Pressed in the video editor, where the canvas row is gone: an arrow that has
   nothing to undo yet says so by being grey rather than by doing nothing. */
.sd-icon-b:disabled { opacity: .4; cursor: default; }
.sd-icon-b:disabled:hover { background: transparent; color: var(--muted); }

.sd-icon-b {
  display: inline-grid; place-items: center; width: 32px; height: 32px; padding: 0;
  border: none; border-radius: 9px; background: transparent; color: var(--muted); cursor: pointer;
}
.sd-icon-b svg { width: 17px; height: 17px; }
.sd-icon-b:hover { background: var(--panel-2); color: var(--text); }

/* The things pressed once a month. */
.sd-more-wrap { position: relative; display: inline-flex; }
.sd-more-pop {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30; min-width: 190px;
  display: flex; flex-direction: column; gap: 2px; padding: 6px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-md); background: var(--panel);
  box-shadow: var(--sd-sh-pop);
}
.sd-more-pop[hidden] { display: none; }
.sd-more-pop .sd-saved { padding: 5px 9px; font-size: 11px; color: var(--muted); }
.sd-more-row {
  padding: 8px 9px; border: none; border-radius: var(--sd-r-sm); background: transparent;
  color: var(--text); font: inherit; font-size: 12.5px; text-align: left; cursor: pointer;
}
.sd-more-row:hover { background: var(--panel-2); }
/* «Clear timeline» with nothing on the timeline: there, and not a press. */
.sd-more-row:disabled { opacity: .4; cursor: default; background: transparent; }


/* A slot, not a ratio: the name people use over the pixels it really is.
   One button and a list behind it, rather than eleven chips across the whole width
   of a screen whose scarce thing is the stage. */
.sd-formats { position: relative; display: flex; align-items: center; gap: 6px; }
.sd-fmt-btn {
  display: inline-flex; align-items: center; gap: 12px; height: 40px; padding: 0 14px;
  border: 1px solid var(--sd-line); border-radius: 11px; background: var(--panel);
  color: var(--text); font: inherit; cursor: pointer; white-space: nowrap; box-shadow: var(--sd-sh-1);
}
.sd-fmt-btn:hover { border-color: var(--accent-line); }
.sd-fmt-btn b { font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums; }
.sd-fmt-btn > span { font-size: 11px; font-weight: 600; color: var(--muted); }
.sd-fmt-btn svg { color: var(--muted); }
/* **Anchored right, because the pill is at the right.** It opened from its left edge
   and grew rightwards, which was fine while `.sd-head` centred its one child; the
   «Canvas» heading made that row `space-between` and put the pill against the right
   edge of the screen, where 230px of menu lands outside `.main` — and `.main` is
   `overflow: hidden`, so under about 1180px the whole list of formats was cut away
   rather than merely tight. Moving a control is what changes which way its menu can
   open, and that is not visible in the diff that moves it. */
.sd-fmt-pop {
  position: absolute; top: calc(100% + 6px); right: 0; left: auto; z-index: 40; min-width: 230px;
  max-height: 60vh; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 1px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-md); background: var(--panel);
  box-shadow: var(--sd-sh-pop);
}
.sd-fmt-pop[hidden] { display: none; }
.sd-fmt-group { margin: 8px 8px 3px; font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); }
.sd-fmt-group:first-child { margin-top: 2px; }
.sd-fmt {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  min-height: 30px; padding: 4px 8px; border: 1.5px solid transparent;
  border-radius: 7px; background: transparent; color: var(--text); font: inherit;
  cursor: pointer; white-space: nowrap; text-align: left; transition: background .12s ease, border-color .12s ease;
}
.sd-fmt:hover { background: var(--sd-field); }
.sd-fmt.on { background: var(--accent-soft); border-color: var(--accent-line); box-shadow: none; }
.sd-fmt b { font-size: 12px; font-weight: 700; line-height: 1.1; }
.sd-fmt span { font-size: 10px; font-weight: 600; line-height: 1; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-fmt.on b { color: var(--accent-ink); }
.sd-fmt.on span { color: var(--accent-ink); opacity: .75; }
.sd-fmt-res { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 0 4px 4px; }
.sd-fmt-res-b {
  height: 30px; border: 1.5px solid var(--sd-line); border-radius: 7px; background: transparent;
  color: var(--text); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.sd-fmt-res-b:hover { background: var(--sd-field); }
.sd-fmt-res-b.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-ink); }
.sd-custom { display: inline-flex; align-items: center; gap: 5px; color: var(--muted); font-size: 11px; }
.sd-custom input {
  width: 62px; height: 30px; padding: 0 8px; border: 1px solid var(--border); border-radius: 7px;
  background: var(--field); color: var(--text); font-family: var(--mono); font-size: 11.5px;
}
/* As wide as what is written in it: a fixed width put the pencil and the state of the
   save a hand's breadth away from a short name, which is not where the mockup draws
   them. `field-sizing` does it in the browsers that have it; the others keep a width
   that fits a usual name. */
.sd-name {
  width: 14ch; max-width: 42vw; height: 30px; padding: 0; border: 0; background: transparent;
  color: var(--text); font: inherit; font-size: 22px; font-weight: 700; letter-spacing: -.015em;
  min-width: 4ch;
}
@supports (field-sizing: content) {
  .sd-name { width: auto; field-sizing: content; }
}
.sd-name::placeholder { color: var(--muted); }
.sd-name:focus-visible { outline: none; }
.sd-custom input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sd-saved { font-size: 10.5px; color: var(--muted); }
.sd-go {
  height: 30px; padding: 0 13px; border-radius: 8px; font: inherit; font-size: 12.5px;
  font-weight: 600; cursor: pointer; transition: filter .12s ease, background .12s ease;
}

.sd-go {
  border: 0; background: linear-gradient(135deg, var(--accent), var(--accent-hi));
  color: var(--on-solid); box-shadow: 0 6px 18px -8px var(--accent);
}
/* The one pink button on the screen, as tall as the outlined one beside it. */
.sd-bar .sd-go { height: 42px; padding: 0 20px; border-radius: 12px; font-size: 14px; }
.sd-go:hover { filter: brightness(1.06); }
.sd-warn { margin: 8px 0 0; flex: 0 0 auto; }

/* ---------- the three columns ----------
   Each child names its own track, and that is not decoration. The left column is
   the banner's, and `hidden` takes it out of the grid entirely — so with auto flow
   the middle and the right slid one track left, the inspector was handed the `1fr`
   leftover, and it drew **thirteen pixels wide** with all five of its cards inside
   it. On the picture and the cut, which are the two tabs that hide that column. The
   banner looked right for the one reason that it does not hide it. */
.sd-body {
  display: grid; grid-template-columns: auto minmax(0, 1fr) 300px; gap: 14px;
  flex: 1 1 auto; min-height: 0; padding-top: 6px;
}
.sd-left { grid-column: 1; }
.sd-main { grid-column: 2; display: flex; flex-direction: column; gap: 9px; min-width: 0; min-height: 0; }
.sd-insp { grid-column: 3; }
/* **The video editor's timeline is a row of its own**, under the panel and the picture,
   the width of the screen — the mockups draw it from edge to edge. Only that editor has
   the row: on the base rule the Design tab would carry an empty one. The columns over it
   name their row too, because with two rows auto placement is free to put a column in
   the second. */
.sd-vdock {
  grid-column: 1 / -1; grid-row: 2; min-width: 0;
  display: flex; flex-direction: column; min-height: 0; max-height: 40vh; overflow: auto; padding: 10px 14px 12px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel);
  box-shadow: var(--sd-sh-1);
}
.sd-vdock[hidden] { display: none; }
/* **In the video editor the grid is two columns and two rows**, the arrangement of the
   owner's mockup 2: the picture, and the panel — Library and Create with AI — at its
   right, with the dock the whole width under both. The montage chat, while it is open,
   is a third column at the left of the picture (below, with its own block). No rail and
   no inspector's column — the inspector's three nodes are moved into the panel
   (`#sd-vprops`), so its own column is not drawn. The Design's three are the base rule
   above. Every child here names its track: the panel folds and is never `hidden`, but a
   child that disappears leaves the grid, and with auto placement the panel would slide
   into the picture's track. */
.studio-view[data-mode="video"] .sd-body { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: minmax(0, 1fr) auto; }
.studio-view[data-mode="video"] .sd-main { grid-column: 1; grid-row: 1; overflow: hidden; }
.studio-view[data-mode="video"] .sd-vpanel { grid-column: 2; grid-row: 1; }
.studio-view[data-mode="video"] .sd-vdock { grid-column: 1 / -1; grid-row: 2; }
.studio-view[data-mode="video"] .sd-insp,
.studio-view[data-mode="video"] .sd-left { display: none; }
/* The panel is that editor's column, and nothing of it shows in Design. */
.studio-view:not([data-mode="video"]) .sd-vpanel { display: none; }
/* The stage gives way in the video editor rather than running under the timeline: on a
   laptop's 760 pixels the Design's 280 left what is under it behind the timeline, where
   nobody could press it. The picture shrinks; nothing is covered. */
.studio-view[data-mode="video"] .sd-stage { min-height: 140px; }
/* The mockups are drawn at 1740 wide. Below that the two columns give the stage their
   room back rather than squeezing it: at 1440 the widths above left it four hundred
   pixels, which is less than the slot on most phones. */
/* Scoped to the view so they outrank the column rules further down the file, which
   are the same specificity and would otherwise win by coming later. */
@media (max-width: 1520px) {
  .studio-view .sd-body { grid-template-columns: auto minmax(0, 1fr) 272px; gap: 12px; }
  .studio-view .sd-vpanel { width: 360px; }
  .studio-view .sd-left-panel { width: 278px; padding: 18px 14px; }
  .studio-view .sd-rail { width: 64px; }
  .studio-view .sd-insp { padding: 16px 13px 0; }
}
@media (max-width: 1280px) {
  .studio-view .sd-body { grid-template-columns: auto minmax(0, 1fr) 256px; }
  .studio-view .sd-vpanel { width: 320px; }
  .studio-view .sd-left-panel { width: 250px; }
}
/* Under 1180, where the screen is one column, the two ends do not fit beside each other —
   the Design's at 1024 on the name every piece gets when it saves itself, «Senza titolo ·
   26 set, 02:58», measured in Italian, the longer language: the ways out go under the name.
   The video editor's keep the row until a phone. */
@media (max-width: 1180px) {
  .studio-view .sd-bar { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .studio-view .sd-bar-end { grid-column: 1; grid-row: 2; }
  .studio-view[data-mode="video"] .sd-bar { grid-template-columns: minmax(0, 1fr) auto; }
  .studio-view[data-mode="video"] .sd-bar-end { grid-column: 2; grid-row: 1; }
}
/* The video editor's two ends stop fitting beside each other on a phone: the ways out
   go under the name, at the right where the hand is. */
@media (max-width: 760px) {
  .studio-view[data-mode="video"] .sd-bar { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .studio-view[data-mode="video"] .sd-bar-end { grid-column: 1; grid-row: 2; justify-self: end; }
}

/* The stage: the reference's own radial ground and dot grid. It is what makes the
   work look placed rather than pasted, and it costs two declarations. */
.sd-stage {
  position: relative; flex: 1 1 auto; min-height: 280px;
  display: flex; align-items: center; justify-content: center; padding: 14px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); overflow: hidden;
  background:
    radial-gradient(rgba(24, 24, 27, .055) 1px, transparent 1px) 0 0 / 22px 22px,
    radial-gradient(120% 90% at 50% 0%, #EFEFF3 0%, var(--sd-stage) 70%);
}
:root[data-theme="dark"] .sd-stage, :root:not([data-theme="light"]) .sd-stage {
  background:
    radial-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px) 0 0 / 22px 22px,
    radial-gradient(120% 90% at 50% 0%, #1d1d24 0%, var(--sd-stage) 70%);
}
.sd-pane { width: 100%; height: 100%; display: flex; flex-direction: column; gap: 8px; align-items: center; justify-content: center; }
.sd-pane[hidden] { display: none; }
.sd-frame {
  position: relative; max-width: 100%; max-height: 100%; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--sd-r-md); overflow: hidden; box-shadow: var(--sd-sh-pop);
}
.sd-frame-dark { background: #05060a; }
/* The banner's room, and not a black rectangle around it. The slot carries its own
   shadow, so the frame only has to give it the space and let the stage's dot grid
   show through — which is what the editor this is dressed against does, and what
   makes a 300×250 read as a banner placed on a desk rather than as a small picture
   inside a big television. */
.sd-frame-fill { width: 100%; height: 100%; background: transparent; box-shadow: none; }

/* ---------- the video editor's picture ----------
   One canvas the player paints, and over it the handles of what it drew — the clips, the
   layers, the lines — placed on the boxes the painter drew them in, in its order. */
.sd-vid-canvas { display: block; width: 100%; height: 100%; }
/* The players the painter reads its frames from: in the page, because a browser may stop
   decoding a video nobody can see, and a pixel square, which nobody does. */
.sd-vid-shelf { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }
.sd-vid-src { width: 1px; height: 1px; }
.sd-vid-overlay { position: absolute; inset: 0; pointer-events: none; }
.sd-cap-h {
  position: absolute; pointer-events: auto; cursor: move;
  border: 1.5px dashed transparent; border-radius: 4px;
}
.sd-cap-h:hover { border-color: rgba(255, 255, 255, .7); }
.sd-cap-h.on { border-style: solid; border-color: var(--accent); box-shadow: 0 0 0 1px rgba(0, 0, 0, .25); }
/* A clip's handle: its box on the picture, under the layers' and the lines' handles, so a
   press picks it only where it is the one on top. Selected, dragged by the middle it moves
   and by the corner it scales about its centre. */
.sd-clip-h {
  position: absolute; pointer-events: auto; cursor: move;
  border: 1.5px dashed transparent;
}
.sd-clip-h:hover { border-color: rgba(255, 255, 255, .55); }
.sd-clip-h.on { border-style: solid; border-color: var(--accent); box-shadow: 0 0 0 1px rgba(0, 0, 0, .25); }
/* The corner grip is the selected element's alone, and none on a locked track, whose
   elements a press still picks and no drag moves. */
.sd-clip-h:not(.on) > .sd-clip-grip, .sd-cap-h:not(.on) > .sd-clip-grip, .held > .sd-clip-grip { display: none; }
.sd-clip-h.held, .sd-cap-h.held { cursor: default; }
.sd-clip-grip {
  position: absolute; right: 2px; bottom: 2px; width: 14px; height: 14px;
  background: #fff; border: 1.5px solid var(--accent); border-radius: 3px; cursor: nwse-resize;
}
.sd-cap-edit {
  position: absolute; z-index: 2; pointer-events: auto; margin: -4px 0 0 -6px; padding: 2px 5px;
  border: 1.5px solid var(--accent); border-radius: 6px; background: rgba(12, 12, 16, .72);
  color: #fff; line-height: 1.15; resize: none; outline: none;
}
/* The crop: the whole file fitted in the frame, and the part that is kept drawn clear. */
.sd-vcrop {
  position: absolute; pointer-events: auto; cursor: move;
  border: 1.5px solid #fff; box-shadow: 0 0 0 9999px rgba(8, 9, 14, .55);
}
.sd-vcrop-g {
  position: absolute; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  background: #fff; border-radius: 3px; box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
}
.sd-vcrop-n { left: 50%; top: 0; cursor: ns-resize; }
.sd-vcrop-s { left: 50%; top: 100%; cursor: ns-resize; }
.sd-vcrop-e { left: 100%; top: 50%; cursor: ew-resize; }
.sd-vcrop-w { left: 0; top: 50%; cursor: ew-resize; }
.sd-vcrop-ne { left: 100%; top: 0; cursor: nesw-resize; }
.sd-vcrop-nw { left: 0; top: 0; cursor: nwse-resize; }
.sd-vcrop-se { left: 100%; top: 100%; cursor: nwse-resize; }
.sd-vcrop-sw { left: 0; top: 100%; cursor: nesw-resize; }
/* «Preview» and the transport's corner: the frame alone, letterboxed, and no handles. */
#sd-vid-frame:fullscreen { width: 100vw !important; height: 100vh !important; border-radius: 0; background: #000; }
#sd-vid-frame:fullscreen .sd-vid-canvas { object-fit: contain; }
#sd-vid-frame:fullscreen .sd-vid-overlay, #sd-vid-frame:fullscreen .sd-empty { display: none; }
.sd-empty {
  position: absolute; inset: 0; display: flex; flex-direction: column; gap: 10px;
  align-items: center; justify-content: center;
  padding: 24px; text-align: center; color: var(--muted); font-size: 12.5px; background: var(--panel);
}
.sd-empty p { margin: 0; max-width: 34ch; line-height: 1.5; }
.sd-empty-ic { display: inline-flex; width: 38px; height: 38px; opacity: .42; }
.sd-empty-ic svg { width: 100%; height: 100%; }
.sd-frame-dark .sd-empty { background: #05060a; }
/* A new project's picture: not a black screen but a card, with a photo and a clip drawn on it,
   what is missing and how to fill it — the mockup's. The canvas behind it stays the player's. */
.sd-frame-dark .sd-vid-none { background: var(--panel); gap: 6px; }
.sd-vid-none-art { width: clamp(96px, 16vw, 168px); height: auto; margin-bottom: 8px; overflow: visible; }
.sd-vid-none-art .bk { fill: #ece6fa; }
.sd-vid-none-art .sun { fill: #f6b8d3; }
.sd-vid-none-art .hill { fill: #cfc3ee; }
.sd-vid-none-art .fr { fill: #fff; stroke: #ece8f3; stroke-width: 1; filter: drop-shadow(0 8px 14px rgba(18, 18, 58, .12)); }
.sd-vid-none-art .pk { fill: var(--accent); stroke: var(--accent); stroke-width: 3; stroke-linejoin: round; }
.sd-vid-none-art .ln { fill: none; stroke: var(--accent); stroke-width: 2.4; stroke-linecap: round; }
.sd-vid-none-t { margin: 0; font-size: clamp(15px, 1.9vw, 22px); font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.sd-vid-none p { font-size: clamp(12.5px, 1.35vw, 16px); max-width: 38ch; }
:root[data-theme="dark"] .sd-vid-none-art .bk, :root:not([data-theme="light"]) .sd-vid-none-art .bk { fill: rgba(255, 255, 255, .08); }
:root[data-theme="dark"] .sd-vid-none-art .hill, :root:not([data-theme="light"]) .sd-vid-none-art .hill { fill: rgba(255, 255, 255, .16); }
:root[data-theme="dark"] .sd-vid-none-art .fr, :root:not([data-theme="light"]) .sd-vid-none-art .fr { fill: #23232c; stroke: rgba(255, 255, 255, .1); }
.sd-busy {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--veil-strong); color: var(--text); font-size: 12.5px; font-weight: 600;
}
.sd-spin { width: 15px; height: 15px; border-radius: 50%; border: 2px solid var(--border); border-top-color: var(--accent); animation: sd-turn .8s linear infinite; }
@keyframes sd-turn { to { transform: rotate(360deg); } }

/* The crop rectangle over the picture. */
.sd-crop { position: absolute; border: 1px solid var(--on-scrim); box-shadow: 0 0 0 9999px rgba(8, 9, 14, .5); cursor: move; }
.sd-crop-h { position: absolute; width: 12px; height: 12px; background: var(--on-scrim); border-radius: 3px; }
.sd-crop-h[data-corner="nw"] { left: -6px; top: -6px; cursor: nwse-resize; }
.sd-crop-h[data-corner="ne"] { right: -6px; top: -6px; cursor: nesw-resize; }
.sd-crop-h[data-corner="sw"] { left: -6px; bottom: -6px; cursor: nesw-resize; }
.sd-crop-h[data-corner="se"] { right: -6px; bottom: -6px; cursor: nwse-resize; }

.sd-transport { display: flex; align-items: center; gap: 9px; width: 100%; max-width: 720px; }
.sd-play {
  display: grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--panel); color: var(--text); cursor: pointer;
}
.sd-play:hover { border-color: var(--ink); }
.sd-clock { font-family: var(--mono); font-size: 11.5px; color: var(--muted); min-width: 108px; white-space: nowrap; }
/* The video editor's transport, as the mockup draws it: the sound at the left edge, a
   clip back, play in a dark disc and a clip on in the middle with the clock, and the
   whole screen at the right edge. */
.sd-vtp { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; max-width: none; padding: 2px 4px; }
.sd-vtp-mid { display: flex; align-items: center; justify-content: center; gap: 14px; min-width: 0; }
.sd-vtp-b {
  display: inline-grid; place-items: center; width: 36px; height: 36px; padding: 0;
  border: 0; border-radius: 10px; background: transparent; color: var(--text); cursor: pointer;
}
.sd-vtp-b:hover:not(:disabled) { background: var(--panel-2); }
.sd-vtp-b:disabled { opacity: .35; cursor: default; }
/* The play disc is the dark fill of the mockups, 48 pixels, its glyph in the colour that
   goes on that fill — light on dark, and dark on the light disc of the dark theme. */
.sd-vtp .sd-play { width: 48px; height: 48px; border: 0; background: var(--solid); color: var(--on-solid); }
.sd-vtp .sd-play:hover:not(:disabled) { filter: brightness(1.25); }
.sd-vtp .sd-play:disabled { opacity: .4; cursor: default; }
/* «00:07.50 / 00:18.00» in a monospaced face, as the mockups set it: the playhead's figure
   in ink, the cut's length after it in grey. To the hundredth the first figure changes on
   every frame, and in this face every figure is as wide as every other, so the clock is
   always as wide as its box and nothing beside it moves. */
.sd-vtp .sd-clock {
  flex: 0 0 auto; min-width: 0; margin-left: 6px; font-family: var(--mono); font-size: 13.5px; font-weight: 700;
  letter-spacing: 0; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.sd-vtp .sd-clock-of { font-weight: 500; color: var(--muted); }
/* **The playhead's figure lays out alone.** It changes on every frame of playback, and a text
   written into the line relaid the whole page each time — seven hundred boxes, most of what a
   frame cost. Contained and sized (its width set to its characters by `paintClock`), it is a
   layout boundary: a new figure lays out its own box. Top-aligned on a line exactly as tall as
   its own, so it sits where the figures beside it sit. */
.sd-vtp .sd-clock { line-height: 1.5; }
.sd-vtp .sd-clock-now { display: inline-block; vertical-align: top; height: 1.5em; contain: size layout; }
/* **The clock is never narrower than its figures.** With the panel open on a laptop the
   middle of the transport had 222 pixels for 253 of buttons and clock, the clock was the one
   thing allowed to shrink, and «00:01 / 00:09» ran fourteen pixels out of its own box
   towards the full-screen button. In a narrow transport the middle tightens instead. The
   transport is as wide as its column (`.sd-transport`), so it can be its own container. */
.sd-vtp { container: sd-vtp / inline-size; }
@container sd-vtp (max-width: 440px) {
  .sd-vtp-mid { gap: 6px; }
  .sd-vtp .sd-vtp-b { width: 32px; }
  .sd-vtp .sd-clock { margin-left: 0; font-size: 12px; }
}
/* And narrower still, the play disc gives back eight pixels and the cut's length is left to
   the timeline's ruler: the playhead's figure is the one the transport is for. */
@container sd-vtp (max-width: 330px) {
  .sd-vtp .sd-play { width: 40px; height: 40px; }
  .sd-vtp .sd-clock-of { display: none; }
}

/* ---------- the video editor's centre ----------
   One surface, as the mockups draw it: the stage's own grey under the «Preview» row, the
   picture and its transport, with no card of its own inside it. The column clips what
   overflows it; what opens over the picture — the size's list, the clip bar's menus — stays
   inside it, opening downward from the row at its top. */
.studio-view[data-mode="video"] .sd-main {
  gap: 4px; padding: 8px 16px 10px; border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg);
  background: var(--sd-stage);
}
#view-studio[data-mode="video"] .sd-stage { padding: 4px 0 0; border: 0; border-radius: 0; background: none; }
/* The row over the picture: «Preview» on the left, the selected clip's tools after it, then
   the project's gear and the size at the right. Each names its track: the clip bar comes and
   goes, and the gear and the size must not slide into its place. */
.sd-vhead {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; column-gap: 10px;
  flex: 0 0 auto; min-height: 44px;
}
.sd-vhead[hidden] { display: none; }
/* «Preview» in the ink of the column titles, as mockup 2 writes it: it names the column, as
   «Montage chat» and «Library» name theirs. */
.sd-vhead-t { grid-column: 1; grid-row: 1; margin: 0 6px 0 0; font-size: 15.5px; font-weight: 600; color: var(--text); }
.sd-vhead > .sd-clipbar {
  grid-column: 2; grid-row: 1; justify-self: start; max-width: 100%; min-width: 0;
  min-height: 40px; padding: 2px 6px; border-radius: 12px;
}
.sd-vhead .sd-cb-b { height: 34px; }
.sd-vhead > .sd-vproject { grid-column: 3; grid-row: 1; }
.sd-vhead > .sd-bar-fmt { grid-column: 4; grid-row: 1; }
.sd-vhead .sd-fmt-btn { height: 36px; gap: 10px; padding: 0 12px; border-radius: 10px; }
.sd-vhead .sd-fmt-btn b { font-size: 13.5px; font-weight: 500; }
/* **Where the picture's column is narrow** — the montage chat open beside it at 1280 px leaves it
   some 360 px — the clip's tools take a row of their own under the word, the gear and the size,
   as on a phone: in the row they shared, four of their five buttons were past its edge. Asked of
   the column, not of the window, because it is the chat that narrows it. */
.studio-view[data-mode="video"] .sd-main { container: sd-picture / inline-size; }
@container sd-picture (max-width: 600px) {
  /* The second row is kept whether a clip is selected or not: one that came with the selection
     pushed the picture down under the pointer that had just pressed it. */
  .sd-vhead { grid-template-columns: minmax(0, 1fr) auto auto; grid-template-rows: auto 40px; row-gap: 6px; }
  .sd-vhead > .sd-vproject { grid-column: 2; }
  .sd-vhead > .sd-bar-fmt { grid-column: 3; }
  .sd-vhead > .sd-clipbar { grid-column: 1 / -1; grid-row: 2; }
}
/* On a phone the row has room for the word, the gear and the size: the clip's tools take
   a row of their own under them. */
@media (max-width: 620px) {
  .sd-vhead { grid-template-columns: minmax(0, 1fr) auto auto; row-gap: 6px; }
  .sd-vhead > .sd-vproject { grid-column: 2; }
  .sd-vhead > .sd-bar-fmt { grid-column: 3; }
  .sd-vhead > .sd-clipbar { grid-column: 1 / -1; grid-row: 2; }
  .studio-view[data-mode="video"] .sd-main { padding: 8px 10px 10px; }
}

/* ---------- the clip bar ----------
   Over the picture in the video editor, where the Design has its canvas row: a glyph
   and a word per tool, hairlines between the groups, a menu under the carets. */
.sd-clipbar {
  display: flex; align-items: center; gap: 2px; flex: 0 0 auto; min-height: 46px; padding: 4px 8px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel); box-shadow: var(--sd-sh-1);
}
.sd-clipbar[hidden] { display: none; }
.sd-cb-wrap { position: relative; display: inline-flex; }
.sd-cb-b {
  display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px;
  border: 0; border-radius: 9px; background: transparent; color: var(--text);
  font: inherit; font-size: 13.5px; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.sd-cb-b:hover:not(:disabled) { background: var(--panel-2); }
.sd-cb-b:disabled { opacity: .4; cursor: default; }
.sd-cb-b.on { color: var(--accent); }
.sd-cb-b svg { flex: 0 0 auto; }
.sd-cb-sep { width: 1px; height: 22px; margin: 0 6px; background: var(--sd-line); }
.sd-cb-say { margin-right: auto; padding: 0 8px; font-size: 13px; color: var(--muted); }
/* Too narrow for its words, the bar keeps its glyphs (`fitClipbar` measures it): each button
   named by its tooltip, the caret still on Flip, nothing past the column's edge. */
.sd-clipbar.sd-cb-tight .sd-cb-t { display: none; }
.sd-clipbar.sd-cb-tight .sd-cb-b { gap: 3px; padding: 0 9px; }
.sd-clipbar.sd-cb-tight .sd-cb-sep { margin: 0 3px; }
.sd-more-pop.sd-cb-pop { left: 0; right: auto; min-width: 200px; }
.sd-more-pop.sd-cb-adjust { min-width: 280px; padding: 12px; gap: 8px; }
.sd-more-row.sd-more-bad { color: var(--danger); }

/* ---------- the montage chat (studio-video-chat.js) ----------
   docs/studio-video-montage.md §4: a third column of the video editor's body **only while it
   is open**, and the first one, as the owner's mockup 2 draws it. Open,
   `.sd-body[data-chat="open"]` is three columns — the chat, the picture and the panel — with
   the chat the whole height and the timeline under the other two, and every child names its
   track, for the reason written over `.sd-body`: a child that disappears leaves the grid, and
   auto placement slides the rest into its track. Closed, the chat is `hidden` and takes no
   track at all, so the two columns are exactly the ones they were; a tab on the picture's left
   edge opens it. `--sd-chat-w` is its width, set by the handle on its right edge between 300
   and 560. Under 1180 pixels the body is one column and the chat a row of its own under the
   timeline. */
.sd-vchat {
  position: relative; display: flex; flex-direction: column; min-width: 0; min-height: 0;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel); box-shadow: var(--sd-sh-1);
  container: sd-vchat / inline-size;
}
.sd-vchat[hidden] { display: none; }
.studio-view:not([data-mode="video"]) .sd-vchat, .studio-view:not([data-mode="video"]) .sd-vchat-tab { display: none; }
/* At a laptop's 1280 the menu, the panel at 320, the chat at its 300 and the gaps leave the
   picture 332 pixels, under the 360 it keeps: while the chat is open there, the panel gives up
   32 of its own, which a folded column, or a closed chat, gives back. */
@media (min-width: 1181px) and (max-width: 1340px) {
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-vpanel:not([data-collapsed]) { width: 288px; }
}
@media (min-width: 1181px) {
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] { grid-template-columns: var(--sd-chat-w, 360px) minmax(0, 1fr) auto; }
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-vchat { grid-column: 1; grid-row: 1 / -1; }
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-main { grid-column: 2; grid-row: 1; }
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-vpanel { grid-column: 3; grid-row: 1; }
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-vdock { grid-column: 2 / 4; grid-row: 2; }
}
@media (max-width: 1180px) {
  /* One column: the picture, the timeline, the chat at full width, and the panel last. */
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] { grid-template-rows: auto auto auto auto; }
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-vchat { grid-column: 1; grid-row: 3; height: min(560px, 75vh); }
  .studio-view[data-mode="video"] .sd-body[data-chat="open"] .sd-vpanel { grid-column: 1; grid-row: 4; }
  .sd-vchat-grip { display: none; }
}

/* The handle on the right edge, in the grid's gap beside the picture: a line of the accent
   while it is held or focused, and the column's width follows the pointer. */
.sd-vchat-grip {
  position: absolute; top: 12px; bottom: 12px; right: -11px; z-index: 3; width: 10px; cursor: col-resize; touch-action: none;
  border-radius: 5px;
}
.sd-vchat-grip::after {
  content: ''; position: absolute; top: 50%; left: 50%; width: 4px; height: 36px; transform: translate(-50%, -50%);
  border-radius: 2px; background: var(--sd-line); transition: background .12s ease, height .12s ease;
}
.sd-vchat-grip:hover::after, .sd-vchat-grip.on::after, .sd-vchat-grip:focus-visible::after { height: 72px; background: var(--accent); }
.sd-vchat-grip:focus-visible { outline: none; }

/* The head: its name in the navy of the titles with the accent's mark, «New chat», the fold. */
.sd-vchat-head { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; padding: 12px 8px 4px 16px; }
.sd-vchat-title {
  flex: 1 1 auto; display: flex; align-items: center; gap: 9px; min-width: 0; margin: 0;
  font-size: 15.5px; font-weight: 600; color: var(--text); white-space: nowrap;
}
.sd-vchat-title span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sd-vchat-title svg { flex: 0 0 auto; color: var(--accent); }
.sd-vchat-new {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; height: 32px; padding: 0 10px;
  border: 1px solid var(--sd-line); border-radius: 9px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 13px; font-weight: 600; white-space: nowrap; cursor: pointer;
}
.sd-vchat-new:hover { background: var(--panel-2); }
.sd-vchat-new svg { color: var(--accent-ink); }
@container sd-vchat (max-width: 340px) {
  .sd-vchat-new { width: 32px; padding: 0; justify-content: center; }
  .sd-vchat-new span { display: none; }
}
.sd-vchat-fold { flex: 0 0 auto; }

/* The messages: the person's on the right on the accent's wash, the chat's on the left on the
   card's grey, what changed as a list under the reply, and a line of the panel's own centred. */
.sd-vchat-log { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 10px; padding: 14px 14px 10px; }
.sd-vchat-msg { display: flex; flex-direction: column; gap: 6px; max-width: 88%; padding: 9px 12px; border-radius: 14px; font-size: 13.5px; line-height: 1.45; }
.sd-vchat-msg[data-role="user"] { align-self: flex-end; border-bottom-right-radius: 4px; background: var(--accent-soft); color: var(--text); }
.sd-vchat-msg[data-role="assistant"] { align-self: flex-start; border-bottom-left-radius: 4px; background: var(--panel-2); color: var(--text); }
.sd-vchat-msg[data-role="note"] { align-self: center; max-width: 100%; padding: 4px 10px; background: transparent; color: var(--muted); font-size: 12.5px; text-align: center; }
.sd-vchat-msg.bad .sd-vchat-text { color: var(--danger); }
.sd-vchat-text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.sd-vchat-files, .sd-vchat-did { display: flex; flex-direction: column; gap: 3px; margin: 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--muted); }
.sd-vchat-files li, .sd-vchat-did li { display: flex; align-items: center; gap: 6px; min-width: 0; }
.sd-vchat-files svg, .sd-vchat-did svg { flex: 0 0 auto; }
.sd-vchat-did svg { color: var(--ok); }
.sd-vchat-undo {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  border: 1px solid var(--accent-line); border-radius: 8px; background: var(--panel); color: var(--accent-ink);
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.sd-vchat-undo:hover { background: var(--accent-soft); }
.sd-vchat-undone { margin: 0; font-size: 12px; color: var(--muted); }
/* «Send again» under a message the cut moved under, and «Resync subtitles» under the cut that
   moved under the subtitles: the Undo's look, centred under a line of the panel's own. */
.sd-vchat-again {
  align-self: center; display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px;
  border: 1px solid var(--accent-line); border-radius: 8px; background: var(--panel); color: var(--accent-ink);
  font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.sd-vchat-again:hover:not(:disabled) { background: var(--accent-soft); }
.sd-vchat-again:disabled { opacity: .5; cursor: default; }
.sd-vchat-busy { flex-direction: row; gap: 5px; padding: 12px 14px; }
.sd-vchat-busy i { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: sd-vchat-dot 1.2s infinite ease-in-out; }
.sd-vchat-busy i:nth-child(2) { animation-delay: .15s; }
.sd-vchat-busy i:nth-child(3) { animation-delay: .3s; }
@keyframes sd-vchat-dot { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .sd-vchat-busy i { animation: none; opacity: .6; } }

/* The chat's turn, mockups 2 and 3: its round mark on the left, and beside it a column of its
   own — the notes as it works, the reply, the question or the plan as a card, the chips. */
.sd-vchat-turn { display: flex; align-items: flex-start; gap: 8px; align-self: stretch; min-width: 0; }
.sd-vchat-avatar {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 32px; height: 32px; overflow: hidden;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent-ink);
}
.sd-vchat-avatar img { display: block; width: 32px; height: 32px; }
.sd-vchat-col { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; flex: 1 1 auto; min-width: 0; }
.sd-vchat-turn .sd-vchat-msg { max-width: 100%; }
.sd-vchat-bubble {
  max-width: 100%; margin: 0; padding: 9px 12px; border-radius: 14px; border-bottom-left-radius: 4px;
  background: var(--panel-2); color: var(--text); font-size: 13.5px; line-height: 1.45; overflow-wrap: anywhere;
}
/* The model's notes: small, quiet bubbles; folded away under a finished reply. */
.sd-vchat-steps { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; max-width: 100%; }
.sd-vchat-step {
  max-width: 100%; margin: 0; padding: 5px 10px; border-radius: 10px; background: var(--panel-2);
  color: var(--muted); font-size: 12.5px; line-height: 1.4; overflow-wrap: anywhere;
}
.sd-vchat-notes { max-width: 100%; font-size: 12px; color: var(--muted); }
.sd-vchat-notes summary { cursor: pointer; padding: 2px 0; }
.sd-vchat-notes[open] summary { margin-bottom: 4px; }
/* What the turn is doing: its dots and a line. */
.sd-vchat-phase { display: inline-flex; align-items: center; gap: 8px; margin: 0; padding: 6px 2px; font-size: 12.5px; color: var(--muted); }
.sd-vchat-phase .sd-vchat-busy { display: inline-flex; padding: 0; gap: 4px; }
.sd-vchat-saved, .sd-vchat-trace { display: flex; align-items: center; gap: 5px; margin: 0; font-size: 12px; color: var(--muted); }
.sd-vchat-trace { font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

/* The cards: a question of options (mockup 3) and a plan of steps (mockup 2). */
.sd-vchat-card {
  display: flex; flex-direction: column; gap: 10px; width: 100%; box-sizing: border-box; padding: 12px;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel);
}
.sd-vchat-card-head { display: flex; flex-direction: column; gap: 2px; }
.sd-vchat-card-title { font-size: 11.5px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; color: var(--text); }
.sd-vchat-card-sub { font-size: 12px; color: var(--muted); }
.sd-vchat-options { display: flex; flex-direction: column; gap: 6px; }
.sd-vchat-option {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 9px 10px; text-align: left;
  border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); color: var(--text); font: inherit; cursor: pointer;
}
.sd-vchat-option:hover:not(:disabled) { border-color: var(--accent-line); }
.sd-vchat-option.on { border-color: var(--accent); background: var(--accent-soft); }
.sd-vchat-option:disabled { cursor: default; }
.sd-vchat-option:disabled:not(.on) { opacity: .6; }
.sd-vchat-option:focus-visible, .sd-vchat-plan-step:focus-visible, .sd-vchat-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sd-vchat-option-mark {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px;
  border: 2px solid var(--muted); border-radius: 50%; box-sizing: border-box;
}
.sd-vchat-option-mark.multi { border-radius: 5px; }
.sd-vchat-option.on .sd-vchat-option-mark { border-color: var(--accent); box-shadow: inset 0 0 0 3px var(--panel); background: var(--accent); color: var(--on-solid); }
.sd-vchat-option.on .sd-vchat-option-mark.multi { box-shadow: none; }
.sd-vchat-option-words { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; min-width: 0; }
.sd-vchat-option-words b { font-size: 13.5px; font-weight: 600; }
.sd-vchat-option-words small { flex-basis: 100%; font-size: 12.5px; color: var(--muted); }
.sd-vchat-badge {
  display: inline-flex; align-items: center; height: 20px; padding: 0 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-ink); font-size: 11.5px; font-weight: 600;
}
.sd-vchat-other {
  display: flex; align-items: center; gap: 8px; padding: 0 10px; height: 38px;
  border: 1px solid var(--sd-line); border-radius: 10px; color: var(--muted);
}
.sd-vchat-other:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-vchat-other input { flex: 1 1 auto; min-width: 0; border: 0; outline: none; background: transparent; color: var(--text); font: inherit; font-size: 13px; }
.sd-vchat-other input::placeholder { color: var(--muted); }
.sd-vchat-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 12px; color: var(--muted); }
.sd-vchat-continue {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto; height: 32px; padding: 0 10px 0 14px;
  border: 0; border-radius: 9px; background: linear-gradient(135deg, var(--accent), var(--accent-hi)); color: var(--on-solid);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sd-vchat-continue:disabled { opacity: .45; cursor: default; }
.sd-vchat-answered { margin: 0; font-size: 12.5px; color: var(--text); overflow-wrap: anywhere; }
.sd-vchat-plan-title { margin: 0; font-size: 14.5px; font-weight: 600; color: var(--text); }
.sd-vchat-plan-steps { display: flex; flex-direction: column; gap: 2px; margin: 0; padding: 0; list-style: none; }
.sd-vchat-plan-step {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 6px 4px; text-align: left;
  border: 0; border-radius: 8px; background: transparent; color: var(--text); font: inherit; font-size: 13.5px; cursor: pointer;
}
.sd-vchat-plan-step:hover:not(:disabled) { background: var(--panel-2); }
.sd-vchat-plan-step:disabled { cursor: default; }
.sd-vchat-plan-step:not(.on) { color: var(--muted); }
.sd-vchat-plan-step:not(.on) span:last-child { text-decoration: line-through; }
.sd-vchat-tick {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 20px; height: 20px; box-sizing: border-box;
  border: 2px solid var(--muted); border-radius: 50%;
}
.sd-vchat-plan-step.on .sd-vchat-tick { border-color: var(--accent); background: var(--accent); color: var(--on-solid); }
.sd-vchat-plan-ic { flex: 0 0 auto; color: var(--muted); }
.sd-vchat-apply {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 38px; padding: 0 14px;
  border: 1px solid var(--accent); border-radius: 10px; background: var(--panel); color: var(--accent-ink);
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.sd-vchat-apply:hover:not(:disabled) { background: var(--accent-soft); }
.sd-vchat-apply:disabled { opacity: .45; cursor: default; }
.sd-vchat-applied { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; font-weight: 600; color: var(--ok); }
/* The animated scenes card: the plan card's frame, a row per scene with its use's mark in the
   timeline's own scene colour (`--sd-scene` under `--sd-on-scene`, 8.83:1), the button that
   carries the figure, and «No, thanks» as a quiet second. */
.sd-vchat-scene-list { display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 0; list-style: none; }
.sd-vchat-scene { display: flex; align-items: flex-start; gap: 10px; }
.sd-vchat-scene-ic {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 30px; height: 30px; border-radius: 8px;
  background: var(--sd-scene); color: var(--sd-on-scene);
}
.sd-vchat-scene-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sd-vchat-scene-where { font-size: 12.5px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
.sd-vchat-scene-idea { margin: 0; font-size: 13px; line-height: 1.4; color: var(--text); overflow-wrap: anywhere; }
.sd-vchat-scene-copy { margin: 0; font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
/* Where in the frame it goes, in the chat's own words: what the paid writer is sent, said quietly. */
.sd-vchat-scene-place { margin: 0; font-size: 12px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.sd-vchat-scene-photo { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); }
/* Where a scene goes in, and its brand kit's switch (docs/studio-video-montage.md §14). */
.sd-vchat-scene-at { font-style: italic; }
.sd-vchat-scene-brand { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); cursor: pointer; }
.sd-vchat-scene-brand input { margin: 0; accent-color: var(--accent); }
/* The final check against the original, under the chat's messages (§14). */
.sd-vchat-check { gap: 8px; }
.sd-vchat-check-sum, .sd-vchat-check-wait { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-vchat-check-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 4px; }
.sd-vchat-check-list li { display: flex; align-items: flex-start; gap: 6px; font-size: 12.5px; line-height: 1.4; overflow-wrap: anywhere; }
.sd-vchat-check-list li svg { flex: none; margin-top: 2px; }
.sd-vchat-check-list li.ok svg { color: var(--ok); }
.sd-vchat-check-list li.bad svg { color: var(--accent); }
.sd-vchat-check-fix { align-self: flex-start; }
.sd-vchat-scene-why { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-vchat-scene-state { margin: 0; font-size: 12.5px; color: var(--muted); }
/* The figure on its button whole, however narrow the column: the button grows a line rather than
   cutting «22.5 credits» in two, and «No, thanks» sits under it at the same width. */
.sd-vchat-scene-foot { display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
.sd-vchat-scene-go { height: auto; min-height: 38px; padding: 8px 14px; line-height: 1.25; text-align: center; }
.sd-vchat-scene-no {
  height: 34px; padding: 0 12px; border: 0; border-radius: 10px; background: transparent; color: var(--muted);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.sd-vchat-scene-no:hover { background: var(--panel-2); color: var(--text); }
.sd-vchat-scene-go:focus-visible, .sd-vchat-scene-no:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sd-vchat-scenes.done .sd-vchat-scene { opacity: .8; }
/* Scenes paid for and not on the timeline yet: a line that says so, then a row each — what it is,
   why it waits, and its free «Add to the timeline» in the apply button's own outline. */
.sd-vchat-kept { display: flex; flex-direction: column; gap: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
.sd-vchat-kept-lead { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--text); }
.sd-vchat-kept-list { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.sd-vchat-kept-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sd-vchat-kept-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12.5px; color: var(--text); overflow-wrap: anywhere; }
.sd-vchat-kept-why { font-size: 12px; line-height: 1.4; color: var(--muted); }
.sd-vchat-kept-add { flex: 0 0 auto; height: 34px; font-size: 13px; }
.sd-vchat-kept-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* The card of generations — «To generate»: the scenes card's frame, a row per item with its kind's
   mark in the accent's wash under the accent's ink (the badge's own pairing), the row's figure at
   its right in tabular digits, the total over the button that carries it, and «No, thanks» quiet
   under it. What was paid for and could not land is listed like the scenes kept, with its own names. */
.sd-vchat-gen-list { display: flex; flex-direction: column; gap: 12px; margin: 0; padding: 0; list-style: none; }
.sd-vchat-gen { display: flex; align-items: flex-start; gap: 10px; }
.sd-vchat-gen-ic {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 30px; height: 30px; border-radius: 8px;
  background: var(--accent-soft); color: var(--accent-ink);
}
.sd-vchat-gen-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.sd-vchat-gen-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.sd-vchat-gen-name { min-width: 0; font-size: 13px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.sd-vchat-gen-price { flex: 0 0 auto; font-size: 12.5px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sd-vchat-gen-facts { margin: 0; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
/* The words the engine is sent, said in full: they are what is paid for. */
.sd-vchat-gen-prompt { margin: 0; font-size: 12.5px; line-height: 1.4; color: var(--text); overflow-wrap: anywhere; }
.sd-vchat-gen-line { margin: 0; font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.sd-vchat-gen-photo { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); }
.sd-vchat-gen-why, .sd-vchat-gen-state { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-vchat-gen-total {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0; padding-top: 8px;
  border-top: 1px solid var(--border); font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums;
}
.sd-vchat-gen-foot { display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
.sd-vchat-gen-go { height: auto; min-height: 38px; padding: 8px 14px; line-height: 1.25; text-align: center; }
.sd-vchat-gen-no {
  height: 34px; padding: 0 12px; border: 0; border-radius: 10px; background: transparent; color: var(--muted);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.sd-vchat-gen-no:hover { background: var(--panel-2); color: var(--text); }
.sd-vchat-gen-go:focus-visible, .sd-vchat-gen-no:focus-visible, .sd-vchat-gen-kept-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sd-vchat-gens.done .sd-vchat-gen { opacity: .8; }
.sd-vchat-gen-kept { display: flex; flex-direction: column; gap: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
.sd-vchat-gen-kept-lead { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--text); }
.sd-vchat-gen-kept-list { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.sd-vchat-gen-kept-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sd-vchat-gen-kept-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; font-size: 12.5px; color: var(--text); overflow-wrap: anywhere; }
.sd-vchat-gen-kept-why { font-size: 12px; line-height: 1.4; color: var(--muted); }
.sd-vchat-gen-kept-add { flex: 0 0 auto; height: 34px; font-size: 13px; }
/* The next steps the chat suggests: pills of the accent's ink, a press sends the words. */
.sd-vchat-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sd-vchat-chip {
  height: 32px; padding: 0 12px; border: 1px solid var(--accent-line); border-radius: 999px;
  background: var(--panel); color: var(--accent-ink); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.sd-vchat-chip:hover { background: var(--accent-soft); }

/* The empty chat: what it is for, and three requests that fill the field. */
.sd-vchat-empty { display: flex; flex-direction: column; align-items: center; gap: 8px; margin: auto 0; padding: 12px 6px; text-align: center; }
.sd-vchat-empty-ic { display: inline-grid; place-items: center; width: 48px; height: 48px; border-radius: 14px; background: var(--accent-soft); color: var(--accent-ink); }
.sd-vchat-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 600; color: var(--text); }
.sd-vchat-empty p { margin: 0; max-width: 300px; font-size: 13px; line-height: 1.5; color: var(--muted); }
.sd-vchat-tries { display: flex; flex-direction: column; align-items: stretch; gap: 6px; width: 100%; max-width: 320px; margin-top: 8px; }
.sd-vchat-tries-l { font-size: 12px; font-weight: 600; color: var(--muted); text-align: left; }
.sd-vchat-try {
  padding: 8px 12px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 13px; line-height: 1.35; text-align: left; cursor: pointer;
}
.sd-vchat-try:hover { border-color: var(--accent-line); background: var(--accent-soft); }

/* The composer: the files attached, what the chat is told of where you are, the field with
   «Attach» and Send in its foot, and the budget under it. */
.sd-vchat-compose { position: relative; display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; padding: 10px 12px 12px; border-top: 1px solid var(--sd-line); }
.sd-vchat-atts { display: flex; flex-wrap: wrap; gap: 6px; max-height: 128px; overflow-y: auto; }
.sd-vchat-atts[hidden] { display: none; }
.sd-vchat-att {
  position: relative; display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; flex: 1 1 140px;
  padding: 5px 4px 5px 5px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); overflow: hidden;
}
.sd-vchat-att[data-tone="bad"] { border-color: var(--danger-line); }
/* In a column under 440 pixels each file has a row of its own: two side by side left neither its name. */
@container sd-vchat (max-width: 440px) { .sd-vchat-att { flex-basis: 100%; } }
.sd-vchat-att-words { display: flex; flex-direction: column; gap: 1px; flex: 1 1 auto; min-width: 0; }
.sd-vchat-att-words b { overflow: hidden; font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; text-overflow: ellipsis; }
.sd-vchat-att-words small { overflow: hidden; font-size: 11.5px; color: var(--muted); white-space: nowrap; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.sd-vchat-att[data-tone="ok"] small { color: var(--ok); }
.sd-vchat-att[data-tone="bad"] small { color: var(--danger); }
.sd-vchat-att .sd-ib { width: 26px; height: 26px; }
.sd-vchat-att-meter { position: absolute; left: 0; bottom: 0; height: 2px; width: calc(var(--sent, 0) * 100%); background: var(--accent); transition: width .2s ease; }
.sd-vchat-pic {
  position: relative; display: inline-grid; place-items: center; flex: 0 0 auto; width: 36px; height: 36px; overflow: hidden;
  border-radius: 7px; background: var(--panel-2); color: var(--muted);
}
.sd-vchat-pic img, .sd-vchat-pic video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* What the chat is told of where you are, mockups 2 and 3: chips — the clip selected with its
   picture («v1 · 15.1 s»), the range, the playhead after its ▶ — each with its × for this message. */
.sd-vchat-ctx { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; font-size: 12.5px; color: var(--muted); }
.sd-vchat-ctx[hidden] { display: none; }
.sd-vchat-ctx-ic { flex: 0 0 auto; color: var(--accent); }
.sd-vchat-ctx-part {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 30px; padding: 0 8px;
  border: 1px solid var(--sd-line); border-radius: 9px; background: var(--panel); color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.sd-vchat-ctx-part .sd-vchat-pic { width: 24px; height: 24px; margin-left: -5px; border-radius: 6px; }
.sd-vchat-ctx-part .sd-vchat-pic svg { display: none; }
.sd-vchat-ctx-part > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sd-vchat-ctx-part[data-part="range"] { background: var(--accent-soft); color: var(--accent-ink); }
.sd-vchat-ctx-part:has(.sd-vchat-ctx-x) { padding-right: 2px; }
.sd-vchat-ctx-x {
  display: inline-grid; place-items: center; width: 20px; height: 20px; padding: 0; border: 0; border-radius: 50%;
  background: transparent; color: inherit; cursor: pointer; opacity: .7;
}
.sd-vchat-ctx-x:hover { opacity: 1; background: var(--panel-3); }
/* The field: one box, the text on top and its tools in its foot. */
.sd-vchat-box {
  display: flex; flex-direction: column; border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.sd-vchat-box:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-vchat-field {
  display: block; width: 100%; box-sizing: border-box; min-height: 56px; max-height: 176px; resize: none; padding: 10px 12px 4px;
  border: 0; border-radius: 12px; background: transparent; color: var(--text); font: inherit; font-size: 13.5px; line-height: 20px; outline: none;
}
.sd-vchat-field::placeholder { color: var(--muted); }
.sd-vchat-bar { display: flex; align-items: center; gap: 6px; padding: 4px 6px 6px; }
.sd-vchat-attach-wrap { position: relative; display: inline-flex; }
.sd-vchat-attach {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px;
  border: 0; border-radius: 9px; background: transparent; color: var(--muted); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sd-vchat-attach:hover, .sd-vchat-attach.on { background: var(--panel-2); color: var(--text); }
.sd-more-pop.sd-vchat-pop { top: auto; bottom: calc(100% + 6px); left: 0; right: auto; min-width: 200px; }
.sd-vchat-pop-row { display: flex; align-items: center; gap: 9px; font-size: 13px; }
.sd-vchat-pop-row svg { color: var(--muted); }
.sd-vchat-count { margin-left: auto; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-vchat-count.full { color: var(--danger); }
.sd-vchat-count[hidden] { display: none; }
.sd-vchat-send {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; margin-left: auto; padding: 0 14px;
  border: 0; border-radius: 10px; background: linear-gradient(135deg, var(--accent), var(--accent-hi)); color: var(--on-solid);
  font: inherit; font-size: 13.5px; font-weight: 600; white-space: nowrap; cursor: pointer;
}
.sd-vchat-count:not([hidden]) + .sd-vchat-send { margin-left: 0; }
.sd-vchat-send:hover:not(:disabled) { filter: brightness(1.06); }
.sd-vchat-send:disabled { opacity: .45; cursor: default; }
.sd-vchat-send.busy { cursor: progress; }
.sd-vchat-send-ic { display: inline-flex; }
/* While the chat edits the timeline the button is its Stop: the outline of the accent, never off. */
.sd-vchat-send.stop { border: 1px solid var(--accent); background: var(--panel); color: var(--accent-ink); }
.sd-vchat-send.stop:hover:not(:disabled) { filter: none; background: var(--accent-soft); }
.sd-vchat-price { font-size: 12px; font-weight: 600; opacity: .9; font-variant-numeric: tabular-nums; }
.sd-vchat-price[hidden] { display: none; }
.sd-vchat-budget { margin: -2px 2px 0; font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-vchat-budget[hidden] { display: none; }
/* «From library»: over the composer, the files on hand to pick several of, and Attach. */
.sd-vchat-lib {
  position: absolute; left: 8px; right: 8px; bottom: calc(100% - 4px); z-index: 20; display: flex; flex-direction: column; gap: 10px;
  max-height: min(440px, 62vh); padding: 12px; border: 1px solid var(--sd-line); border-radius: var(--sd-r-md);
  background: var(--panel); box-shadow: var(--sd-sh-pop);
}
.sd-vchat-lib[hidden] { display: none; }
.sd-vchat-lib-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sd-vchat-lib-top h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--text); }
.sd-vchat-lib-search { flex: 0 0 auto; height: 38px; }
.sd-vchat-lib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; min-height: 0; overflow-y: auto; padding: 2px; }
.sd-vchat-lib-tile {
  position: relative; display: flex; flex-direction: column; gap: 4px; min-width: 0; padding: 4px;
  border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.sd-vchat-lib-tile:hover:not(:disabled) { border-color: var(--accent-line); }
.sd-vchat-lib-tile.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-halo); }
.sd-vchat-lib-tile:disabled { opacity: .45; cursor: default; }
.sd-vchat-lib-tile .sd-vchat-pic { width: 100%; height: auto; aspect-ratio: 16 / 10; }
.sd-vchat-lib-name { overflow: hidden; font-size: 11.5px; white-space: nowrap; text-overflow: ellipsis; }
.sd-vchat-lib-mark {
  position: absolute; top: 8px; right: 8px; display: none; place-items: center; width: 20px; height: 20px;
  border-radius: 50%; background: var(--accent); color: var(--on-solid);
}
.sd-vchat-lib-tile.on .sd-vchat-lib-mark { display: inline-grid; }
.sd-vchat-lib-empty { grid-column: 1 / -1; margin: 6px 0; font-size: 13px; color: var(--muted); text-align: center; }
.sd-vchat-lib-foot { display: flex; justify-content: flex-end; gap: 8px; }
.sd-vchat-lib-cancel, .sd-vchat-lib-add {
  height: 34px; padding: 0 14px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel);
  color: var(--text); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sd-vchat-lib-add { border-color: transparent; background: linear-gradient(135deg, var(--accent), var(--accent-hi)); color: var(--on-solid); }
.sd-vchat-lib-add:disabled { opacity: .45; cursor: default; }

/* The closed chat: a tab on the picture's left edge, where the column opens, which takes no
   track of the grid. */
.sd-vchat-tab {
  position: absolute; top: 50%; left: 0; z-index: 6; display: inline-flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 12px 7px; transform: translateY(-50%);
  border: 1px solid var(--sd-line); border-left: 0; border-radius: 0 12px 12px 0; background: var(--panel);
  color: var(--accent-ink); box-shadow: var(--sd-sh-2); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.sd-vchat-tab span { writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: .02em; }
.sd-vchat-tab:hover { background: var(--accent-soft); }
.sd-vchat-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.sd-vchat-tab[hidden] { display: none; }

/* ---------- the video editor's panel, at the picture's right ----------
   Mockup 2's right-hand panel, a white card beside the picture: 420 pixels where there is
   room, less on a laptop (the media queries above), and folded to a strip of 56 pixels on
   request — never `hidden` in that editor. Two regions: `#sd-vp-main`, the panel
   `studio-video-panels.js` draws again on every paint, and `#sd-vprops`, which is never
   rebuilt: the inspector's three nodes are moved into it, under the panel's way back. */
.sd-vpanel {
  grid-column: 2; grid-row: 1; display: flex; flex-direction: column; width: 420px; min-width: 0; min-height: 0;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel); box-shadow: var(--sd-sh-1);
}
.studio-view .sd-vpanel[data-collapsed] { width: 56px; }
.sd-vp-main, .sd-vprops { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.sd-vp-main[hidden], .sd-vprops[hidden] { display: none; }
.sd-vprops { padding: 10px 16px 0; }
.sd-vprops-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex: 0 0 auto; margin: 0 -6px 10px -8px; }
.sd-vprops-back {
  display: inline-flex; align-items: center; gap: 8px; height: 34px; padding: 0 10px 0 8px;
  border: 0; border-radius: 9px; background: transparent; color: var(--muted); font: inherit; font-size: 14.5px; cursor: pointer;
}
.sd-vprops-back:hover { background: var(--panel-2); color: var(--text); }
/* The folded column: the way to open it, then the two tabs' glyphs, and «Properties» while
   something is selected. */
.sd-vp-strip { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 0; }
.sd-vp-strip-b {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 40px; height: 40px; padding: 0;
  border: 0; border-radius: 10px; background: transparent; color: var(--muted); cursor: pointer;
}
.sd-vp-strip-b:hover { background: var(--panel-2); color: var(--text); }
.sd-vp-strip-b.on { background: var(--accent-soft); color: var(--accent-ink); }
.sd-vp-unfold { margin-bottom: 6px; color: var(--text); }
/* `#sd-vp-main` measures itself, so the head and the lists tighten in a laptop's 320
   pixels without a threshold per window. */
.sd-vp-main { container: sd-vpm / inline-size; }
/* The head, as the mockups draw it: «Library» and «Create with AI», two halves of one grey
   well, the open one on the accent's wash with its word in the accent's ink — `--accent-ink`
   on `--accent-soft` over `--panel-2` measures 5.0:1 light and 5.4:1 dark — and the fold
   beside them. */
.sd-vp-head { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; padding: 14px 12px 2px 18px; }
.sd-vp-vtabs {
  flex: 1 1 auto; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); min-width: 0;
  border-radius: 12px; background: var(--panel-2);
}
.sd-vp-vtab {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px; min-width: 0; height: 48px; padding: 0 10px;
  border: 0; border-radius: 12px; background: transparent; color: var(--muted);
  font: inherit; font-size: 15px; font-weight: 500; white-space: nowrap; cursor: pointer;
}
.sd-vp-vtab svg { flex: 0 0 auto; }
.sd-vp-vtab span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sd-vp-vtab:hover { color: var(--text); }
.sd-vp-vtab.on { background: var(--accent-soft); color: var(--accent-ink); }
.sd-vp-x {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 32px; height: 32px; padding: 0;
  border: 0; border-radius: 9px; background: transparent; color: var(--muted); cursor: pointer;
}
.sd-vp-x:hover { background: var(--panel-2); color: var(--text); }
.sd-vp-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 12px;
  padding: 12px 18px 18px;
}
/* The body scrolls; what is in it does not shrink to fit, as the inspector learnt. */
.sd-vp-body > * { flex-shrink: 0; }
.sd-vp-note { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-vp-h { margin: 6px 0 -4px; font-size: 13px; font-weight: 700; color: var(--text); }
.sd-vp-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 40px; padding: 0 14px;
  border: 1px solid var(--sd-line); border-radius: 9px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
}
.sd-vp-btn:hover:not(:disabled) { border-color: var(--border); background: var(--panel-2); }
.sd-vp-btn:disabled { opacity: .45; cursor: default; }
/* A pink outline: a line of subtitles added, the logo put on the video. */
.sd-vp-upload { min-height: 46px; border: 1.5px solid var(--accent-line); color: var(--accent); }
.sd-vp-upload:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-soft); }
/* **The panel's one filled action**, as the mockups draw «Upload photos and videos» and
   «Generate video»: the accent as a fill, and `--on-accent` on it — white here, 4.06:1 as
   `:root` records, a decision about the brand; measured again by the skin when an agency's
   accent is worn. */
.sd-vp-btn.sd-vp-fill { min-height: 46px; border: 0; background: var(--accent); color: var(--on-accent); font-size: 14.5px; }
.sd-vp-btn.sd-vp-fill:hover:not(:disabled) { border: 0; background: var(--accent-hi); }
.sd-vp-row { display: flex; flex-wrap: wrap; gap: 8px; }
.sd-vp-row .sd-vp-btn { flex: 1 1 auto; }

/* Library's three, underlined as the mockup draws them: the word in ink, the bar in the
   accent — a bar is a graphical object, held to 3:1, which the magenta clears on both cards. */
.sd-vp-tabs { display: flex; gap: 2px; flex: 0 0 auto; margin: 8px 18px 0; border-bottom: 1px solid var(--sd-line); }
.sd-vp-tab {
  position: relative; height: 42px; padding: 0 20px; border: 0; background: transparent; color: var(--muted);
  font: inherit; font-size: 15px; font-weight: 500; cursor: pointer;
}
.sd-vp-tab:hover { color: var(--text); }
.sd-vp-tab.on { color: var(--text); font-weight: 600; }
.sd-vp-tab.on::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--accent); border-radius: 2px; }
.sd-vp-find { display: flex; gap: 8px; }
.sd-vp-search {
  flex: 1 1 auto; display: flex; align-items: center; gap: 10px; min-width: 0; height: 42px; padding: 0 12px;
  border: 1px solid var(--sd-line); border-radius: 9px; color: var(--muted); background: var(--panel);
}
.sd-vp-search:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-vp-search input {
  flex: 1 1 auto; min-width: 0; border: 0; background: transparent; color: var(--text);
  font: inherit; font-size: 13.5px; outline: none;
}
.sd-vp-filter-wrap { position: relative; display: inline-flex; }
.sd-vp-filter {
  display: inline-grid; place-items: center; width: 40px; height: 40px; padding: 0;
  border: 1px solid var(--sd-line); border-radius: 9px; background: var(--panel); color: var(--text); cursor: pointer;
}
.sd-vp-filter.on { border-color: var(--accent-line); color: var(--accent-ink); }
.sd-more-pop.sd-vp-pop { right: 0; left: auto; min-width: 190px; }
/* The filter's two questions, each under its name: what kind of file, and where it came from. */
.sd-vp-pop-h { margin: 4px 9px 2px; font-size: 11.5px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.sd-vp-pop-h:not(:first-child) { margin-top: 6px; padding-top: 8px; border-top: 1px solid var(--sd-line); }
/* Media's two lists and Audio's, each under its heading — «Project contents» with how many it
   holds at the right, then «From your library» — and the way to use them at the foot. */
.sd-vp-lists { display: flex; flex-direction: column; gap: 20px; }
.sd-vp-sec { display: flex; flex-direction: column; gap: 10px; }
.sd-vp-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.sd-vp-sec-head .sd-vp-h { margin: 0; font-size: 15px; font-weight: 600; }
.sd-vp-count { flex: 0 0 auto; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-vp-hint { display: flex; align-items: center; justify-content: center; gap: 6px; margin: 0; font-size: 12.5px; color: var(--muted); }
.sd-vp-hint svg { flex: 0 0 auto; }
.sd-vp-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px 12px; }
.sd-vp-grid > .sd-vp-note { grid-column: 1 / -1; }
/* A tile and what else it offers: its round «+» in the picture's top-right corner, and a
   photo's «Add as overlay» (C7) in the top-left — beside the tile's own button rather than
   inside it, since a button holds no button. */
.sd-vp-cell { position: relative; display: flex; flex-direction: column; min-width: 0; }
/* What sits on a file's picture keeps the scrim's pair in both themes, because the picture
   did not change with them: the length, the overlay button and «This session only» dark with
   white on them; the «+» and «AI» the same pair the other way round, white with the scrim's
   ink, as the mockups draw them. */
.sd-vp-over {
  position: absolute; top: 8px; left: 8px; display: inline-grid; place-items: center; width: 30px; height: 30px; padding: 0;
  border: 0; border-radius: 8px; background: var(--scrim); color: var(--on-scrim); cursor: pointer;
}
.sd-vp-over:hover, .sd-vp-over:focus-visible { background: var(--accent); color: var(--on-accent); }
.sd-vp-add {
  position: absolute; top: 8px; right: 8px; display: inline-grid; place-items: center; width: 30px; height: 30px; padding: 0;
  border: 0; border-radius: 50%; background: var(--on-scrim); color: var(--scrim-strong); box-shadow: var(--shadow-1); cursor: pointer;
}
.sd-vp-add:hover, .sd-vp-add:focus-visible { background: var(--accent); color: var(--on-accent); }
.sd-vp-tile {
  display: flex; flex-direction: column; min-width: 0; padding: 0;
  border: 0; background: transparent; color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.sd-vp-pic {
  position: relative; display: block; aspect-ratio: 16 / 10; overflow: hidden;
  border: 2px solid transparent; border-radius: 10px; background: var(--sd-field);
}
.sd-vp-pic img, .sd-vp-pic video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
/* Under the picture, what kind of file it is: the glyph shows while a thumbnail loads, and
   where one never does — a clip whose first frame this browser cannot decode. */
.sd-vp-ph { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); opacity: .55; }
.sd-vp-tile:hover .sd-vp-pic { border-color: var(--border); }
/* The file of the clip that is selected, in pink: the mockup's way of saying which. */
.sd-vp-tile.on .sd-vp-pic { border-color: var(--accent); }
.sd-vp-dur, .sd-vp-ai {
  position: absolute; left: 8px; bottom: 8px; padding: 2px 7px; border-radius: 6px;
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.sd-vp-dur { background: var(--scrim); color: var(--on-scrim); }
.sd-vp-ai { background: var(--on-scrim); color: var(--scrim-strong); font-weight: 700; letter-spacing: .02em; }
.sd-vp-dur[hidden] { display: none; }
.sd-vp-name { margin-top: 8px; overflow: hidden; font-size: 14px; font-weight: 500; color: var(--text); text-overflow: ellipsis; white-space: nowrap; }
.sd-vp-kind { margin-top: 2px; overflow: hidden; font-size: 12.5px; color: var(--muted); text-overflow: ellipsis; white-space: nowrap; }
/* A file on its way into the archive: a bar along the foot of its picture, filling as it
   travels. And one that stayed on this page instead, marked in the corner the «+» leaves. */
.sd-vp-up {
  position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
  background: var(--scrim);
}
.sd-vp-up-fill { display: block; height: 100%; background: var(--accent); transition: width .2s linear; }
.sd-vp-local {
  position: absolute; right: 8px; bottom: 8px; padding: 2px 7px; border-radius: 6px;
  background: var(--scrim); color: var(--on-scrim); font-size: 11px; font-weight: 600;
}
@container sd-vpm (max-width: 340px) {
  .sd-vp-vtab { gap: 6px; padding: 0 6px; font-size: 14px; }
  .sd-vp-tab { padding: 0 14px; }
  .sd-vp-grid { gap: 14px 10px; }
  .sd-vp-name { font-size: 13px; }
}
/* Under the picture and the timeline, where one column gives the panel the screen's width,
   the tiles stay the size the mockups draw them and more of them share a row. */
@container sd-vpm (min-width: 560px) {
  .sd-vp-grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
}
.sd-vi-relink, .sd-vi-gone { display: flex; flex-direction: column; gap: 10px; }
.sd-vi-relink .hint, .sd-vi-gone .hint { margin: 0; }
/* An item on a locked track: the sentence that says so and the way out, over the controls it
   switched off — the relink box's shape, on the field's ground so it reads as a state. */
.sd-vi-locked {
  display: flex; flex-direction: column; gap: 10px; margin: 2px 0 14px; padding: 12px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-md); background: var(--sd-field);
}
.sd-vi-locked .hint { margin: 0; color: var(--text); }
/* The export while it records: what is happening, a bar, and the clock it is at. */
.sd-export-card { width: min(460px, calc(100vw - 32px)); }
/* The track in the line colour, not the field's #F5F5F7, which on the white card was no track
   at all: a bar a quarter full read as a short pink line with no length to be a quarter of. */
.sd-export-bar { position: relative; height: 8px; margin: 18px 0 8px; border-radius: 999px; background: var(--border); overflow: hidden; }
.sd-export-fill { display: block; width: 0; height: 100%; border-radius: inherit; background: var(--accent); transition: width .2s linear; }
.sd-export-clock { margin: 0; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--muted); }

/* ---------- the export as mockup 4 draws it (studio-video-export.js) ----------
   Three cards on the dialogs' veil: «Export video», the settings; «Exporting», the export's
   own layout of the progress dialog above (`.sd-export-file`), with «—» that makes it a pill;
   and «Your video is ready». Every colour is a token, and every fill carries its pair: the
   accent's buttons and the switch's track are `--accent` under `--on-accent` (4.06:1, the
   decision `:root` records about the brand), the «Recommended» badge `--accent-ink` on
   `--accent-soft` over the card's `--panel` (5.48:1 light, 5.95:1 dark, measured for this
   card), «Back to the editor» `--accent-ink` on `--panel` (6.38:1, 7.09:1), the check `--ok`
   on `--ok-soft` (5.91:1 light, 7.91:1 dark, the table at the foot of this sheet). */
.sd-xd {
  width: min(760px, calc(100vw - 32px)); max-width: none; max-height: calc(100vh - 32px); overflow-y: auto;
  gap: 18px; padding: 24px 28px 22px; border-radius: 20px;
}
.sd-xd-head, .sd-export-head, .sd-xr-head { display: flex; align-items: center; gap: 12px; }
.sd-xd-head h2, .sd-export-head h2, .sd-xr-head h2 { flex: 1 1 auto; min-width: 0; font-size: 22px; font-weight: 700; letter-spacing: -.015em; color: var(--text); }
.sd-xd-top { display: grid; grid-template-columns: minmax(0, 244px) minmax(0, 1fr); gap: 28px; align-items: start; }
.sd-xd-cover { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.sd-xd-thumb {
  display: grid; place-items: center; aspect-ratio: 16 / 10; overflow: hidden;
  border-radius: 12px; background: var(--panel-2);
}
.sd-xd-pic { display: block; max-width: 100%; max-height: 100%; }
.sd-xd-coverb {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 36px; padding: 0 12px;
  border: 0; border-radius: 10px; background: var(--panel-2); color: var(--text);
  font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
}
.sd-xd-coverb:hover, .sd-xd-coverb[aria-expanded="true"] { background: var(--accent-soft); color: var(--accent-ink); }
.sd-xd-scrub { display: flex; align-items: center; gap: 10px; }
.sd-xd-scrub[hidden] { display: none; }
.sd-xd-scrub input { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.sd-xd-at { flex: 0 0 auto; font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--muted); }
.sd-xd-note { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-xd-note[hidden] { display: none; }
.sd-xd-fields { display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.sd-xd-field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.sd-xd-label-row { display: flex; align-items: center; gap: 10px; min-height: 24px; }
.sd-xd-label { font-size: 14.5px; font-weight: 600; color: var(--text); }
.sd-xd-badge {
  padding: 3px 10px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink);
  font-size: 12.5px; font-weight: 600; white-space: nowrap;
}
.sd-xd-badge[hidden] { display: none; }
/* The name with its extension, one field drawn as two halves. */
.sd-xd-name {
  display: flex; align-items: stretch; height: 46px; overflow: hidden;
  border: 1px solid var(--border); border-radius: 11px; background: var(--panel);
}
.sd-xd-name:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-xd-name input {
  flex: 1 1 auto; min-width: 0; padding: 0 14px; border: 0; background: transparent; color: var(--text);
  font: inherit; font-size: 15px; outline: none;
}
.sd-xd-ext {
  display: flex; align-items: center; flex: 0 0 auto; padding: 0 14px; border-left: 1px solid var(--border);
  background: var(--panel-2); color: var(--muted); font-size: 15px;
}
/* A select in the dialog's look: the browser's own control, its caret drawn by the studio's glyph. */
.sd-xd-select { position: relative; display: flex; align-items: center; min-width: 0; }
.sd-xd-select select {
  width: 100%; height: 46px; padding: 0 40px 0 14px; appearance: none; -webkit-appearance: none;
  border: 1px solid var(--border); border-radius: 11px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 15px; cursor: pointer;
}
.sd-xd-select select:focus-visible { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-xd-caret { position: absolute; right: 13px; pointer-events: none; color: var(--text); }
.sd-xd-select-ic > svg:first-child { position: absolute; left: 14px; pointer-events: none; color: var(--text); }
.sd-xd-select-ic select { padding-left: 46px; }
.sd-xd-sep { width: 100%; margin: 0; border: 0; border-top: 1px solid var(--sd-line); }
.sd-xd-three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.sd-xd-switchrow { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.sd-xd-words { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sd-xd-words b { font-size: 15px; font-weight: 600; color: var(--text); }
.sd-xd-words small { font-size: 13.5px; line-height: 1.4; color: var(--muted); }
/* The switch: a track of the line's colour off, of the accent on, its knob the panel's and then `--on-accent`. */
.sd-xd-switch {
  position: relative; flex: 0 0 auto; width: 52px; height: 30px; margin: 0; appearance: none; -webkit-appearance: none;
  border-radius: 999px; background: var(--border); cursor: pointer; transition: background .15s ease;
}
.sd-xd-switch::before {
  content: ''; position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%;
  background: var(--panel); box-shadow: var(--sd-sh-1); transition: transform .15s ease;
}
.sd-xd-switch:checked { background: var(--accent); }
.sd-xd-switch:checked::before { transform: translateX(22px); background: var(--on-accent); }
.sd-xd-switch:disabled { opacity: .45; cursor: default; }
.sd-xd-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .sd-xd-switch, .sd-xd-switch::before { transition: none; } }
.sd-xd-adv {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14px; width: 100%;
  padding: 4px 2px; border: 0; background: transparent; color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.sd-xd-adv > svg:first-child { color: var(--text); }
.sd-xd-advcaret { color: var(--muted); transition: transform .15s ease; }
.sd-xd-adv[aria-expanded="true"] .sd-xd-advcaret { transform: rotate(90deg); }
.sd-xd-adv:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }
.sd-xd-advbody { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
.sd-xd-advbody[hidden] { display: none; }
/* What it comes to, on the card's grey, with the two ways out at its right. */
.sd-xd-foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 14px;
  margin: 2px -12px -8px; padding: 16px 18px; border-radius: 16px; background: var(--panel-2);
}
.sd-xd-sum { display: flex; align-items: center; gap: 14px; min-width: 0; color: var(--text); }
.sd-xd-sum b { font-variant-numeric: tabular-nums; }
.sd-xd-actions { margin: 0; gap: 12px; }
.sd-xd-cancel { height: 48px; padding: 0 26px; border-radius: 12px; background: var(--panel); color: var(--text); font-size: 15.5px; font-weight: 600; }
.sd-xd-go, .sd-xr-download {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px; height: 48px; padding: 0 24px;
  border: 0; border-radius: 12px; background: var(--accent); color: var(--on-accent);
  font: inherit; font-size: 16px; font-weight: 600; cursor: pointer;
}
.sd-xd-go:hover, .sd-xr-download:hover { background: var(--accent-hi); }
.sd-xd-go:focus-visible, .sd-xr-download:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sd-xd-go:disabled { opacity: .55; cursor: progress; }
.sd-xd-go:disabled:hover { background: var(--accent); }
@media (max-width: 680px) {
  .sd-xd { padding: 20px 18px 18px; }
  .sd-xd-top, .sd-xd-three, .sd-xd-advbody { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .sd-xd-foot { margin: 0; }
}

/* «Exporting», the export's own card: the title with «—», the cover and the name, the share
   over the bar, the time left, and a line under it. */
.sd-export-card.sd-export-file { width: min(480px, calc(100vw - 32px)); max-width: none; gap: 0; padding: 22px 26px 18px; border-radius: 20px; }
.sd-export-file .sd-export-row, .sd-export-ready .sd-export-row { display: flex; align-items: center; gap: 16px; margin: 18px 0 14px; min-width: 0; }
.sd-export-thumb {
  display: grid; place-items: center; flex: 0 0 auto; width: 72px; height: 72px; overflow: hidden;
  border-radius: 10px; background: var(--panel-2);
}
.sd-export-thumb canvas { width: 100%; height: 100%; object-fit: cover; }
.sd-export-name { min-width: 0; overflow: hidden; font-size: 16px; font-weight: 600; color: var(--text); white-space: nowrap; text-overflow: ellipsis; }
.sd-export-pct { margin: 0; font-size: 16px; font-weight: 700; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.sd-export-pct[hidden] { display: none; }
.sd-export-file .sd-export-bar { margin: 8px 0 14px; }
.sd-export-file .sd-export-clock { font-size: 16px; color: var(--text); }
.sd-export-file .hint { margin: 4px 0 0; }
.sd-export-file .dlg-actions { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--sd-line); }
.sd-export-file .dlg-actions .btn { height: 44px; padding: 0 24px; border-radius: 12px; background: var(--panel); color: var(--text); font-size: 15px; }
.sd-export-shrink[hidden] { display: none; }
/* The pill: the veil gives the picture back to the eye and keeps the page from the hand — the
   export is stepping the same players — and the card shrinks to its title, share and bar. */
.dlg.sd-export-shrunk { place-items: end; background: transparent; backdrop-filter: none; }
.sd-export-shrunk .sd-export-card.sd-export-file { width: min(320px, calc(100vw - 32px)); padding: 12px 14px 14px; box-shadow: var(--sd-sh-pop); }
.sd-export-shrunk .sd-export-file .sd-export-head h2 { font-size: 15px; }
.sd-export-shrunk .sd-export-file .sd-export-row,
.sd-export-shrunk .sd-export-file .hint,
.sd-export-shrunk .sd-export-file .dlg-actions { display: none; }
.sd-export-shrunk .sd-export-file .sd-export-bar { margin: 4px 0 6px; }
.sd-export-shrunk .sd-export-file .sd-export-clock { font-size: 13px; color: var(--muted); }

/* «Your video is ready». */
.sd-export-ready { width: min(480px, calc(100vw - 32px)); max-width: none; gap: 0; padding: 22px 26px 16px; border-radius: 20px; }
.sd-xr-ok { display: grid; place-items: center; flex: 0 0 auto; width: 38px; height: 38px; border-radius: 50%; background: var(--ok-soft); color: var(--ok); }
.sd-xr-words { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sd-xr-facts { font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-xr-note { margin: 0 0 16px; font-size: 13px; line-height: 1.45; color: var(--muted); }
.sd-xr-note[hidden] { display: none; }
/* The file read back (`studioExportCheck`): a line while it is read, then one per finding — a
   tick in the ink's green when it is fine, the accent's mark when it is not. */
.sd-xr-check { list-style: none; margin: -6px 0 16px; padding: 0; display: grid; gap: 6px; font-size: 12.5px; line-height: 1.4; color: var(--muted); }
.sd-xr-check[hidden] { display: none; }
.sd-xr-check li { display: flex; align-items: flex-start; gap: 7px; }
.sd-xr-check li > svg { flex: 0 0 auto; margin-top: 1px; }
.sd-xr-check-ok > svg { color: var(--ok, #1f9d55); }
.sd-xr-check-warn { color: var(--text); }
.sd-xr-check-warn > svg { color: var(--accent); }
.sd-xr-download { width: 100%; height: 52px; }
.sd-export-ready .sd-xd-sep { margin: 16px 0 6px; }
.sd-xr-back {
  align-self: center; height: 40px; padding: 0 14px; border: 0; border-radius: 10px; background: transparent;
  color: var(--accent-ink); font: inherit; font-size: 15px; font-weight: 600; cursor: pointer;
}
.sd-xr-back:hover { background: var(--accent-soft); }

.sd-vp-preset {
  display: flex; flex-direction: column; gap: 5px; padding: 14px 16px; border: 1px solid transparent; border-radius: 12px;
  background: #121319; color: #fff; font: inherit; text-align: left; cursor: pointer;
}
.sd-vp-preset:hover { border-color: var(--accent-line); }
.sd-vp-preset-name { font-size: 10.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: rgba(255, 255, 255, .58); }
.sd-vp-preset-sample { font-size: 15px; line-height: 1.2; }
.sd-vp-preset-title .sd-vp-preset-sample { font-size: 24px; font-weight: 800; letter-spacing: -.02em; }
.sd-vp-preset-subtitle .sd-vp-preset-sample { font-size: 17px; font-weight: 600; }
.sd-vp-preset-body .sd-vp-preset-sample { font-size: 13.5px; font-weight: 400; line-height: 1.35; }
.sd-vp-preset-quote .sd-vp-preset-sample { font-family: 'Playfair Display', Georgia, serif; font-size: 19px; font-weight: 500; }
/* The brand kit at the foot of Text, under a hairline: the Brand panel as it was. */
.sd-vp-brand { display: flex; flex-direction: column; gap: 12px; margin-top: 6px; padding-top: 16px; border-top: 1px solid var(--sd-line); }
.sd-vp-brand > .sd-vp-h:first-child { margin: 0; font-size: 15px; font-weight: 600; }

.sd-vp-subs { display: flex; flex-direction: column; gap: 10px; }
.sd-vp-sub { display: flex; flex-direction: column; gap: 7px; padding: 10px; border: 1px solid var(--sd-line); border-radius: 10px; }
.sd-vp-sub-times { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.sd-vp-sub-times input {
  width: 64px; height: 30px; padding: 0 7px; border: 1px solid var(--sd-line); border-radius: 7px;
  background: var(--field); color: var(--text); font: inherit; font-size: 12.5px; font-variant-numeric: tabular-nums;
}
/* Never squeezed by the times beside it, which a narrow panel left it seventeen pixels for. */
.sd-vp-del {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 30px; height: 30px; margin-left: auto; padding: 0;
  border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer;
}
.sd-vp-sub-times input { min-width: 0; }
.sd-vp-del:hover { background: var(--danger-soft); color: var(--danger-ink); }
.sd-vp-sub-text {
  width: 100%; resize: vertical; padding: 7px 9px; border: 1px solid var(--sd-line); border-radius: 8px;
  background: var(--field); color: var(--text); font: inherit; font-size: 13px; line-height: 1.4;
}

.sd-vp-seg { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 4px; border-radius: 10px; background: var(--sd-field); }

/* Create with AI: «All AI tools», a row per tool — its glyph in a well, its name over what it
   makes, a chevron — the five forms, then under their own heading the two roads to a clip of
   the cut. A road with nothing to act on is off, and says why on its own second line. */
.sd-vai-h { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -.02em; color: var(--text); }
.sd-vai-tools { display: flex; flex-direction: column; gap: 8px; }
.sd-vai-tools-h { margin: 4px 0 -2px; }
.sd-vai-tool {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 12px; width: 100%;
  padding: 9px 12px 9px 9px; border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel);
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.sd-vai-tool-ic { display: inline-grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--panel-2); color: var(--ink-2); }
.sd-vai-tool-t { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.sd-vai-tool-t b { font-size: 14.5px; font-weight: 600; }
.sd-vai-tool-t small { font-size: 12.5px; line-height: 1.35; color: var(--muted); }
.sd-vai-tool-go { color: var(--muted); }
.sd-vai-tool:hover:not(.off) { border-color: var(--accent-line); }
.sd-vai-tool:hover:not(.off) .sd-vai-tool-ic { background: var(--accent-soft); color: var(--accent-ink); }
.sd-vai-tool.off { cursor: default; }
.sd-vai-tool.off b, .sd-vai-tool.off .sd-vai-tool-ic { color: var(--muted); }
.sd-vai-tool.off .sd-vai-tool-go { opacity: .35; }
/* «← All AI tools», over the open tool's title. */
.sd-vai-back {
  display: inline-flex; align-self: flex-start; align-items: center; gap: 8px; min-height: 32px; margin: -4px 0 -4px -8px; padding: 0 10px 0 8px;
  border: 0; border-radius: 8px; background: transparent; color: var(--muted); font: inherit; font-size: 14.5px; cursor: pointer;
}
.sd-vai-back:hover { background: var(--panel-2); color: var(--text); }
/* A tool's form: a description, the choices that move the price, and the one button that
   carries it. Segments of three, four or five sit on one row. */
.sd-vai-form .sd-vp-seg { display: flex; }
/* A choice whose words take two lines in a narrow panel grows to hold them, as the
   inspector's own AI form does: «Effetto sonoro» ran out of its 34 pixels at 1280. */
.sd-vai-form .sd-vp-seg-b { flex: 1 1 0; min-width: 0; height: auto; min-height: 34px; padding: 6px 4px; line-height: 1.2; }
.sd-vai-form { display: flex; flex-direction: column; gap: 12px; }
/* «Create a video», as the mockup draws it: the question, «Try:», the clip it follows when there
   is one, «8 s · 16:9» with its settings unfolded in the flow under it, where it goes, the
   figure in grey, the button, and what happens after. */
.sd-vai-ask > span { font-size: 15px; }
.sd-vai-try { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin-top: -2px; font-size: 13px; color: var(--muted); }
.sd-vai-chip {
  min-height: 30px; padding: 0 10px; border: 0; border-radius: 7px; background: var(--panel-2); color: var(--ink-2);
  font: inherit; font-size: 13px; cursor: pointer;
}
.sd-vai-chip:hover { background: var(--accent-soft); color: var(--accent-ink); }
.sd-vai-ref {
  display: grid; grid-template-columns: 84px minmax(0, 1fr) auto; align-items: center; gap: 14px;
  padding: 8px 8px 8px 8px; border: 1px solid var(--sd-line); border-radius: 12px;
}
.sd-vai-ref-pic { display: block; aspect-ratio: 16 / 10; border-radius: 8px; background: var(--sd-field) center / cover; }
.sd-vai-ref-name { overflow: hidden; font-size: 14px; text-overflow: ellipsis; white-space: nowrap; }
.sd-vai-sum {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 42px; padding: 3px 4px 3px 14px;
  border-radius: 10px; background: var(--panel-2); font-size: 13.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.sd-vai-set {
  display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 10px; border: 0; border-radius: 8px;
  background: transparent; color: var(--text); font: inherit; font-size: 13.5px; cursor: pointer;
}
.sd-vai-set:hover, .sd-vai-set[aria-expanded="true"] { background: var(--panel); }
.sd-vai-settings { display: flex; flex-direction: column; gap: 12px; padding: 12px 14px 14px; border: 1px solid var(--sd-line); border-radius: 12px; }
.sd-vai-model-row, .sd-vai-where-row { display: flex; flex-direction: column; gap: 7px; font-size: 13.5px; color: var(--muted); }
.sd-vai-model, .sd-vai-place {
  width: 100%; height: 42px; padding: 0 10px; border: 1px solid var(--sd-line); border-radius: 9px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 14px;
}
.sd-vai-cost { margin: 0; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-vai-first { margin: -4px 0 0; font-size: 13px; line-height: 1.45; text-align: center; color: var(--muted); }
.sd-vai-field { display: flex; flex-direction: column; gap: 6px; font-size: 13px; font-weight: 700; color: var(--text); }
.sd-vai-field textarea {
  width: 100%; box-sizing: border-box; resize: vertical; min-height: 64px; padding: 10px 12px;
  border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 13.5px; font-weight: 400; line-height: 1.45;
}
.sd-vai-field textarea:focus { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-vai-voice {
  width: 100%; height: 40px; padding: 0 10px; border: 1px solid var(--sd-line); border-radius: 9px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 13.5px;
}
.sd-vai-engine { margin: 0; font-size: 12.5px; color: var(--muted); }
.sd-vai-why { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--danger); }
/* «Animated scene»: the line of what is being written, and what came of it — red when nothing did. */
.sd-vai-scene-line { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-vai-scene-line.bad { color: var(--danger); }
/* «Reels from a long video»: the video chosen, the run's bar, the moments found to tick and the reels made. */
.sd-vai-reels-file { display: grid; gap: 6px; }
.sd-vai-reels-file strong { font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-vai-reels-file span { font-size: 12.5px; color: var(--muted); }
.sd-vai-reels-bar { display: block; height: 6px; border-radius: 999px; background: var(--sd-field); overflow: hidden; }
.sd-vai-reels-bar[hidden] { display: none; }
.sd-vai-reels-bar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .3s ease; }
.sd-vai-reels-clips, .sd-vai-reels-made { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.sd-vai-reels-clip {
  display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: start; padding: 10px 12px;
  border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel);
}
.sd-vai-reels-clip input { margin-top: 3px; }
.sd-vai-reels-clip div { display: grid; gap: 3px; min-width: 0; }
.sd-vai-reels-clip strong { font-size: 13.5px; }
.sd-vai-reels-clip em { font-size: 12.5px; color: var(--text); }
.sd-vai-reels-clip p { margin: 0; font-size: 12px; line-height: 1.45; color: var(--muted); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.sd-vai-reels-meta { font-size: 12px; color: var(--muted); }
.sd-vai-reels-made li { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; }
.sd-vai-reels-made li span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-vai-reels-made small.bad { color: var(--danger); font-size: 12px; }
/* «Dub into another language»: what the cut says, the language, the lines — the sentence heard over
   its translation, which the person may change — and the voice. */
.sd-vai-dub-heard { margin: 0; font-size: 12.5px; color: var(--muted); }
.sd-vai-dub-waiting { display: grid; gap: 8px; padding: 10px 12px; border: 1px solid var(--sd-line); border-radius: 10px; }
.sd-vai-dub-waiting p { margin: 0; font-size: 13px; }
.sd-vai-dub-language, .sd-vai-dub-voice { width: 100%; min-height: 36px; padding: 4px 8px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--sd-field); color: var(--text); font: inherit; font-size: 13px; }
.sd-vai-dub-lines { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; max-height: 360px; overflow-y: auto; }
.sd-vai-dub-lines li { display: grid; gap: 4px; padding: 8px; border: 1px solid var(--sd-line); border-radius: 10px; }
.sd-vai-dub-heardline { margin: 0; font-size: 12px; line-height: 1.4; color: var(--muted); overflow-wrap: anywhere; }
.sd-vai-dub-said { width: 100%; min-height: 44px; resize: vertical; padding: 6px 8px; border: 1px solid var(--sd-line); border-radius: 8px; background: var(--sd-field); color: var(--text); font: inherit; font-size: 13px; line-height: 1.4; }
.sd-vai-go { width: 100%; }
.sd-vai-waiting, .sd-vai-made { display: flex; flex-direction: column; gap: 8px; }
.sd-vai-waiting:empty, .sd-vai-made:empty { display: none; }
.sd-vai-wait {
  display: grid; gap: 6px; padding: 12px; border: 1px solid var(--accent-line); border-radius: 10px; background: var(--accent-soft);
  font-size: 13px; color: var(--text);
}
.sd-vai-wait b { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-vai-bar { display: block; height: 6px; border-radius: 999px; background: var(--sd-field); overflow: hidden; }
.sd-vai-fill { display: block; width: 32%; height: 100%; border-radius: inherit; background: var(--accent); animation: sd-vai-run 1.6s ease-in-out infinite; }
@keyframes sd-vai-run { 0% { transform: translateX(-100%); } 100% { transform: translateX(320%); } }
@media (prefers-reduced-motion: reduce) { .sd-vai-fill { animation: none; width: 100%; opacity: .5; } }
.sd-vai-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border: 1px solid var(--sd-line); border-radius: 10px;
  background: var(--panel); font-size: 13px; color: var(--text);
}
.sd-vai-item > span { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-vai-add { min-height: 32px; padding: 0 10px; font-size: 12.5px; }
.sd-vai-where { color: var(--danger); font-size: 11.5px; font-weight: 600; }
/* A form's generation, in the form's place, as the owner's mockup draws it: a stage washed in
   the accent with the kind and the format on a badge, the ring that turns round a sparkle,
   «Generation in progress» and where it will be; under a hairline, the prompt as it was
   written and the model it went to. What comes back takes the ring's place. */
.sd-vai-job { display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--sd-line); border-radius: 14px; background: var(--panel); }
.sd-vai-job-stage {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px;
  min-height: 236px; padding: 52px 18px 24px; text-align: center;
  background: linear-gradient(155deg, rgba(236, 30, 121, .05) 0%, rgba(236, 30, 121, .08) 38%, rgba(124, 92, 255, .09) 100%);
}
.sd-vai-job-badge {
  position: absolute; top: 12px; left: 12px; padding: 5px 10px; border-radius: 8px; background: var(--panel);
  box-shadow: var(--sd-sh-1); font-size: 12.5px; font-weight: 500; color: var(--text); font-variant-numeric: tabular-nums;
}
.sd-vai-job-ring {
  position: relative; display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%;
  background: var(--panel); color: var(--accent); box-shadow: var(--sd-sh-1);
}
.sd-vai-job-ring::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  border: 3px solid var(--accent-soft); border-top-color: var(--accent); border-right-color: var(--accent);
  animation: sd-turn 1.1s linear infinite;
}
.sd-vai-job[data-state="failed"] .sd-vai-job-ring { color: var(--danger); }
.sd-vai-job[data-state="failed"] .sd-vai-job-ring::before, .sd-vai-job[data-state="later"] .sd-vai-job-ring::before { animation: none; border-color: var(--sd-line); }
.sd-vai-job[data-state="done"] .sd-vai-job-ring::before { animation: none; border-color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .sd-vai-job-ring::before { animation: none; } }
.sd-vai-job-words { display: flex; flex-direction: column; align-items: center; gap: 5px; max-width: 100%; }
.sd-vai-job-t { font-size: 17px; font-weight: 700; color: var(--text); }
.sd-vai-job-s { font-size: 13.5px; line-height: 1.45; color: var(--muted); overflow-wrap: anywhere; }
.sd-vai-job-clock { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* What came back fills the stage's width and keeps its own proportions inside it: a small
   picture is drawn up to the stage, a tall one down to it, and the shadow follows the picture. */
.sd-vai-job-out { display: flex; justify-content: center; width: 100%; height: 210px; }
.sd-vai-job-out img, .sd-vai-job-out video {
  display: block; width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 3px 10px rgba(12, 12, 40, .16));
}
.sd-vai-job-sound { flex-direction: column; align-items: center; justify-content: center; gap: 12px; height: auto; color: var(--accent-ink); }
.sd-vai-job-sound audio { width: 100%; }
.sd-vai-job-foot { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px 16px; border-top: 1px solid var(--sd-line); }
.sd-vai-job-foot small { font-size: 12.5px; color: var(--muted); }
.sd-vai-job-prompt {
  margin: 0; font-size: 15px; line-height: 1.45; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; overflow: hidden;
}
.sd-vai-job-model { display: inline-flex; align-items: center; gap: 7px; margin-top: 8px; font-size: 13px; color: var(--muted); }
.sd-vai-job-on { display: flex; align-items: center; gap: 9px; margin: 2px 2px 0; font-size: 13.5px; color: var(--muted); }
.sd-vai-job-on > svg { flex: 0 0 auto; }
.sd-vai-job-acts { display: flex; flex-direction: column; gap: 8px; }
.sd-vai-job-acts .sd-vp-btn, .sd-vai-job-again { width: 100%; justify-content: center; }
/* On the index, a form whose card is working says so on its row, its glyph in the accent. */
.sd-vai-tool[data-job="working"] .sd-vai-tool-ic, .sd-vai-tool[data-job="done"] .sd-vai-tool-ic { background: var(--accent-soft); color: var(--accent-ink); }
.sd-vai-tool[data-job] small { color: var(--accent-ink); }
.sd-vp-seg-b {
  height: 34px; border: 1px solid transparent; border-radius: 8px; background: transparent; color: var(--muted);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sd-vp-seg-b.on { border-color: var(--accent-line); background: var(--panel); color: var(--accent); }
.sd-vp-sounds { display: flex; flex-direction: column; gap: 6px; }
/* A sound as a row: its glyph, its name, its length, and the «+» a press or a drag puts on. */
.sd-vp-sound {
  display: flex; align-items: center; gap: 10px; min-width: 0; padding: 8px 8px 8px 12px; border: 1px solid var(--sd-line); border-radius: 10px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
}
.sd-vp-sound > svg { flex: 0 0 auto; color: var(--muted); }
.sd-vp-sound-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-vp-sound:hover { border-color: var(--accent-line); }
.sd-vp-sound small { flex: 0 0 auto; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-vp-plus { flex: 0 0 auto; display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: var(--panel-2); color: var(--text); }
.sd-vp-sound:hover .sd-vp-plus { background: var(--accent); color: var(--on-accent); }

.sd-vp-swatches { display: flex; flex-wrap: wrap; gap: 8px; }
.sd-vp-swatch { width: 34px; height: 34px; padding: 0; border: 1px solid var(--sd-line); border-radius: 50%; cursor: pointer; }
.sd-vp-swatch.on { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--accent); }
.sd-vp-swatch:disabled { opacity: .4; cursor: default; }
/* «None» among an edge's colours: a white disc struck through, the empty colour. */
.sd-vi-none { background: linear-gradient(135deg, transparent 46%, #e5484d 46%, #e5484d 54%, transparent 54%), #fff; }
.sd-vi-check { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.sd-vp-colour {
  width: 34px; height: 34px; padding: 0; overflow: hidden; border: 1px solid var(--sd-line); border-radius: 50%;
  background: none; cursor: pointer; -webkit-appearance: none; appearance: none;
}
/* Inside a labelled field — the inspector's colour rows — `.sd-field input` gave the picker the
   field's whole width and forty pixels, an oval of the colour under the swatches; it is one
   swatch more, as the rule above means it to be. */
.sd-field .sd-vi-swatches input.sd-vp-colour { width: 34px; height: 34px; padding: 0; border-radius: 50%; }
/* The picker's own swatch, round like the ones beside it rather than a square in a frame. */
.sd-vp-colour::-webkit-color-swatch-wrapper { padding: 0; }
.sd-vp-colour::-webkit-color-swatch { border: 0; border-radius: 50%; }
.sd-vp-colour::-moz-color-swatch { border: 0; border-radius: 50%; }
.sd-vp-logo { display: grid; place-items: center; height: 90px; border: 1px solid var(--sd-line); border-radius: 12px; background: var(--sd-field); }
.sd-vp-logo img { max-width: 70%; max-height: 64px; object-fit: contain; }

/* ---------- the toolbar ---------- */
.sd-tools {
  display: flex; align-items: center; gap: 3px; flex-wrap: wrap; flex: 0 0 auto;
  padding: 5px 7px; background: var(--panel); border: 1px solid var(--sd-line);
  border-radius: var(--sd-r-md); box-shadow: var(--sd-sh-1);
}
.sd-tool {
  display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 11px;
  border: 1.5px solid transparent; border-radius: var(--sd-r-sm); background: transparent;
  color: var(--ink-2); font: inherit; font-size: 12.5px; font-weight: 500; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}

.sd-tool:hover:not(:disabled) { background: var(--sd-field); color: var(--text); }

.sd-tool.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-ink); font-weight: 600; }

.sd-tool:disabled { opacity: .4; cursor: default; }
.sd-font-list::-webkit-scrollbar { width: 7px; height: 7px; }
.sd-dock::-webkit-scrollbar-track, .sd-left::-webkit-scrollbar-track,
.sd-font-list::-webkit-scrollbar-track { background: transparent; }
.sd-dock::-webkit-scrollbar-thumb, .sd-left-panel::-webkit-scrollbar-thumb,
.sd-font-list::-webkit-scrollbar-thumb {
  background: var(--border); border-radius: 7px;
}
.sd-dock:hover::-webkit-scrollbar-thumb,
.sd-left-panel:hover::-webkit-scrollbar-thumb { background: var(--muted); }
.studio-view { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.sd-tile {
  flex: 0 0 auto; width: 88px; height: 62px; padding: 0; overflow: hidden;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-sm); background: var(--sd-field); cursor: pointer;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.sd-tile img, .sd-tile video { width: 100%; height: 100%; object-fit: cover; display: block; }
.sd-tile:hover { border-color: var(--ink); }
.sd-tile.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-halo); }
.sd-tile-audio { width: auto; height: auto; padding: 7px 11px; font-size: 11.5px; color: var(--text); display: inline-flex; align-items: center; gap: 6px; }

/* ---------- the video editor's inspector ----------
   The mockup's «Clip video»: a card with the clip's picture, name, length and size;
   Base and Animation; folds open where the mockup opens them; and rows with the label
   at the left and the value at the right. The controls are `studio-ui.js`'s, so these
   are the Design's classes, and what follows is only what the video adds to them. */
.sd-vi-card { display: grid; grid-template-columns: 92px minmax(0, 1fr) auto; align-items: center; gap: 12px; padding: 16px 0; }
.sd-vi-pic { display: block; aspect-ratio: 16 / 10; border-radius: 9px; background: #2a2b33 center / cover; }
/* An animated scene has no frame of a file to show: its mark, on the timeline's scene colour. */
.sd-vi-pic:has(> svg) { display: grid; place-items: center; background: var(--sd-scene); color: var(--sd-on-scene); }
/* Its card: what it shows, what stops it drawing, a field per parameter, and the way to the chat. */
.sd-vi-scene { display: flex; flex-direction: column; gap: 10px; }
.sd-vi-scene-idea { margin: 0; font-size: 13px; line-height: 1.45; color: var(--text); overflow-wrap: anywhere; }
.sd-vi-scene-why { display: block; font-family: var(--mono); font-size: 11.5px; line-height: 1.45; color: var(--muted); overflow-wrap: anywhere; }
.sd-vi-scene .hint { margin: 0; }
.sd-vi-words { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.sd-vi-name {
  width: 100%; min-width: 0; margin-left: -5px; padding: 3px 5px; border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--text); font: inherit; font-size: 14.5px; font-weight: 600; text-overflow: ellipsis;
}
.sd-vi-name:hover { border-color: var(--sd-line); }
.sd-vi-name:focus-visible { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft); }
.sd-vi-words small { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.sd-vi-words small span { white-space: nowrap; }
.sd-more-pop.sd-vi-pop { right: 0; left: auto; min-width: 190px; }
.sd-vi-frame { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: stretch; }
.sd-vi-frame .sd-ib { width: 42px; height: auto; min-height: 40px; border: 1px solid var(--sd-line); border-radius: 10px; }
.sd-vi-frame .sd-ib.on { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }
/* The folds are flat, a line over each, as the mockup's «Inquadratura ^» and «> Colore». */
.sd-disc.sd-fold { border: 0; border-top: 1px solid var(--sd-line); border-radius: 0; overflow: visible; }
.sd-fold > .sd-disc-head { padding: 14px 0; font-size: 14px; font-weight: 600; }
.sd-fold > .sd-disc-head:hover { background: transparent; color: var(--accent); }
.sd-fold > .sd-disc-body { gap: 14px; padding: 0 0 16px; }
/* A row, as the mockup has «Durata  [7,0 s]»: the label at the left, the value at the right. */
.sd-field.inline { flex-direction: row; align-items: center; justify-content: space-between; gap: 12px; color: var(--text); font-size: 14px; font-weight: 500; }
/* Both ends may give way, the label first: a long word and a long option must not
   push the column sideways, which is where «Verso la clip dopo» took it. */
.sd-field.inline > span { flex: 1 1 auto; min-width: 0; }
.sd-field.inline > :last-child { flex: 0 1 auto; min-width: 0; max-width: 62%; }
.sd-field.inline select { width: auto; min-width: 96px; max-width: 100%; text-overflow: ellipsis; }
.sd-insp-body > .sd-field.inline { padding: 12px 0; border-top: 1px solid var(--sd-line); }
.sd-num { position: relative; display: inline-flex; align-items: center; }
.sd-num input {
  width: 108px; height: 40px; padding: 0 30px 0 12px; border: 1px solid var(--sd-line); border-radius: 10px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 14px; font-variant-numeric: tabular-nums; text-align: right;
}
.sd-num input:focus-visible { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft); }
.sd-num small { position: absolute; right: 12px; font-size: 13px; color: var(--muted); pointer-events: none; }
/* The loudspeaker in the label's place, the slider and the figure on one line. */
.sd-slider.sd-slider-icon { grid-template-columns: auto minmax(0, 1fr) 64px; grid-template-areas: "name range out"; }
.sd-slider-icon > span { display: inline-flex; color: var(--text); }
/* «Modifica con AI»: the mockup's pink outline, the one call in the column that spends. */
.sd-wide.outline { border: 1.5px solid var(--accent-line); background: var(--panel); color: var(--text); }
.sd-wide.outline svg { color: var(--accent); }
.sd-wide.outline:hover:not(:disabled) { border-color: var(--accent); background: var(--accent-soft); }
.sd-insp-body > .sd-wide { margin: 14px 0; }
/* The form it opens, under it: what to do to the piece, and the button with the figure. */
.sd-vi-ai { display: flex; flex-direction: column; gap: 12px; margin: 14px 0; }
.sd-vi-ai-form {
  display: flex; flex-direction: column; gap: 12px; padding: 14px;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel-2);
}
.sd-vi-ai-form .sd-seg button { height: auto; min-height: 36px; padding: 6px 8px; line-height: 1.2; white-space: normal; }
.sd-vi-ai-text {
  width: 100%; box-sizing: border-box; resize: vertical; min-height: 72px; padding: 10px 12px;
  border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); color: var(--text);
  font: inherit; font-size: 13.5px; font-weight: 400; line-height: 1.45;
}
.sd-vi-ai-text:focus { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-vi-ai-form .hint { margin: 0; }
.sd-vi-ai-form .sd-vi-ai-why { color: var(--danger); }
.sd-vi-ai-go { width: 100%; }
.sd-vi-facts { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px 16px; margin: 0; font-size: 13.5px; }
.sd-vi-facts dt { color: var(--muted); }
.sd-vi-facts dd { margin: 0; color: var(--text); font-weight: 500; text-align: right; font-variant-numeric: tabular-nums; }
/* §7 of docs/studio-video-montage.md, by hand. A slider whose field may be left to the
   editor's own rule — a line's width, its box's corners — with «Auto» as a pill over its
   right end, on the label's row: lit while the rule holds. The pill is the accent's ink on
   the accent's tint, 5.47:1 as `:root` records, and stays one line at the panel's 288. */
.sd-vi-auto { position: relative; }
.sd-vi-auto-b {
  position: absolute; top: -3px; right: 0; height: 24px; padding: 0 10px; border: 1px solid var(--sd-line); border-radius: 999px;
  background: var(--panel); color: var(--muted); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.sd-vi-auto-b:hover:not(:disabled) { border-color: var(--accent-line); color: var(--text); }
.sd-vi-auto-b.on { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-ink); cursor: default; }
.sd-vi-auto-b:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sd-vi-auto-b:disabled { opacity: .5; cursor: default; }
/* The label gives the pill its room rather than running under it. */
.sd-vi-auto .sd-slider > span { padding-right: 64px; }
/* The ready-made movements: two to a row at every width the panel takes, a long name on two
   lines rather than a button wider than its column. «None» lit while nothing moves. */
.sd-vi-moves { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.sd-vi-move {
  min-width: 0; min-height: 40px; padding: 6px 10px; border: 1px solid var(--sd-line); border-radius: 10px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 13px; font-weight: 500; line-height: 1.2; text-align: center; cursor: pointer;
}
.sd-vi-move:hover:not(:disabled) { border-color: var(--accent-line); background: var(--panel-2); }
.sd-vi-move.on { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-ink); }
.sd-vi-move:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sd-vi-move:disabled { opacity: .5; cursor: default; }
.sd-vi-movement .sd-wide { margin: 0; }
/* «N keyframes» under a place that follows them, with the diamond the timeline draws. */
.sd-vi-keyed { display: flex; align-items: flex-start; gap: 6px; margin: 0; }
.sd-vi-keyed > svg { flex: 0 0 auto; margin-top: 2px; color: var(--accent-ink); }
.sd-vi-spoken .hint, .sd-vi-duck .hint, .sd-vi-arrive .hint { margin: 0; }

/* ---------- the video editor's timeline: the dock ----------
   The owner's mockups 23–24, under the picture the width of the screen, in three parts. A
   head: two tabs — «Cut», with its glyph, and «Subtitles» — and at its right the tools:
   Split, Duplicate and Delete on the selection, and «Generate here» at the playhead. A middle
   that scrolls: the track names down the left with their eye and lock, a ruler, and the rows
   — the clips as strips of their own frames, the lines in lavender with their «T», the sound
   in mint — under a pink playhead held by its handle. And a foot: what the cut holds, the two
   views and the zoom. */
/* The pane fills the dock, and the dock's three parts share it: the head and the foot keep
   their height and the middle gives way, scrolling — so the foot is always in sight. */
.sd-vdock > .sd-dock-pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.sd-vtl { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.sd-vtl-head { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; padding: 0 0 6px; }
/* The tabs, as the mockup draws them: the open one on a grey pill in ink, the other in grey
   with nothing behind it — the accent is kept for what is selected on the timeline. */
.sd-vtl-dtabs { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.sd-vtl-dtab {
  display: inline-flex; align-items: center; gap: 9px; height: 38px; padding: 0 14px;
  border: 0; border-radius: 10px; background: transparent; color: var(--muted);
  font: inherit; font-size: 14.5px; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.sd-vtl-dtab:hover { color: var(--text); }
.sd-vtl-dtab.on { background: var(--panel-2); color: var(--text); font-weight: 600; }
.sd-vtl-dtab:focus-visible, .sd-vtl-verb:focus-visible, .sd-vtl-ib:focus-visible, .sd-vtl-seg-b:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
.sd-vtl-sep { width: 1px; height: 24px; margin: 0 4px; background: var(--sd-line); flex: 0 0 auto; }
.sd-vtl-verbs { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.sd-vtl-verb {
  display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 12px;
  border: 0; border-radius: 9px; background: transparent; color: var(--text);
  font: inherit; font-size: 14px; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.sd-vtl-verb:hover:not(:disabled) { background: var(--panel-2); }
.sd-vtl-verb:disabled { opacity: .4; cursor: default; }
/* The middle: the tracks, the Scenes or the subtitles' list, whichever the tab and the view say. */
.sd-vtl-body { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* The foot, under a hairline: the count at the left, the views and the zoom at the right. */
.sd-vtl-foot {
  display: flex; align-items: center; gap: 6px; flex: 0 0 auto; flex-wrap: wrap; min-height: 39px;
  margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--sd-line);
}
.sd-vtl-count { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sd-vtl-seg { display: inline-flex; gap: 2px; margin-left: auto; padding: 2px; border-radius: 9px; background: var(--panel-2); }
.sd-vtl-seg-b {
  display: inline-grid; place-items: center; width: 32px; height: 28px; padding: 0;
  border: 0; border-radius: 7px; background: transparent; color: var(--muted); cursor: pointer;
}
.sd-vtl-seg-b:hover { color: var(--text); }
.sd-vtl-seg-b.on { background: var(--panel); color: var(--text); box-shadow: var(--sd-sh-1); }
.sd-vtl-zoom { display: flex; align-items: center; gap: 4px; }
.sd-vtl-foot .sd-vtl-ib { width: 30px; height: 30px; }
/* The zoom's slider filled in the accent up to its thumb, as the mockup draws it. */
.sd-vtl-zoom input[type="range"] {
  width: 120px; height: 4px; margin: 0 4px; border-radius: 4px; -webkit-appearance: none; appearance: none; cursor: pointer;
  background: linear-gradient(to right, var(--accent) var(--at, 50%), var(--sd-line) var(--at, 50%));
}
.sd-vtl-zoom input[type="range"]::-webkit-slider-thumb {
  width: 18px; height: 18px; border: 1px solid var(--border); border-radius: 50%; background: var(--panel);
  box-shadow: var(--sd-sh-1); -webkit-appearance: none; appearance: none;
}
.sd-vtl-zoom input[type="range"]::-moz-range-thumb {
  width: 18px; height: 18px; border: 1px solid var(--border); border-radius: 50%; background: var(--panel); box-shadow: var(--sd-sh-1);
}
.sd-vtl-ib {
  display: inline-grid; place-items: center; width: 32px; height: 32px; padding: 0; flex: 0 0 auto;
  border: 0; border-radius: 8px; background: transparent; color: var(--text); cursor: pointer;
}
.sd-vtl-ib:hover:not(:disabled) { background: var(--panel-2); }
/* A switch that is on says so by more than its glyph's colour: the magnet, a lock, an eye
   that hides, the taller timeline — tinted, as the views' chosen tab is, hovered or not. */
.sd-vtl-ib.on, .sd-vtl-ib.on:hover:not(:disabled) { color: var(--accent); background: var(--accent-soft); }
.sd-vtl-ib:disabled { opacity: .4; cursor: default; }
/* The state of a row's shared switches, shown on a row that has none of its own. */
.sd-vtl-ib.sd-vtl-with { cursor: default; }
/* C8: a layer's bin, where the eye sits on a row that has one — in the danger's ink when the
   pointer is on it, since what it takes is everything on the layer. */
.sd-vtl-ib[data-tl^="layer-remove-"]:hover:not(:disabled) { color: var(--danger-ink); background: var(--danger-soft); }

.sd-vtl-main { display: grid; grid-template-columns: 188px minmax(0, 1fr); min-height: 0; }
.sd-vtl-heads { display: flex; flex-direction: column; }
.sd-vtl-rulerpad { height: 30px; flex: 0 0 auto; }
.sd-vtl-th { display: flex; align-items: center; gap: 2px; padding: 0 6px 0 4px; flex: 0 0 auto; }
.sd-vtl-th-name { display: inline-flex; align-items: center; gap: 12px; flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 500; color: var(--text); }
/* The glyph keeps its size where the column is narrow, and the word gives way: at 1180 the
   glyphs were squeezed to half their size beside the eye and the lock. */
.sd-vtl-th-name > svg { flex: 0 0 auto; }
.sd-vtl-th-word { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Each row a lane or more tall: things that play at the same time are stacked in lanes,
   and a row and its head grow together, from the same number. */
.sd-vtl-h-video, .sd-vtl-video { height: 58px; }
.sd-vtl-text, .sd-vtl-h-text, .sd-vtl-layer, .sd-vtl-h-layer { --lane-h: 34px; }
.sd-vtl-music, .sd-vtl-h-music, .sd-vtl-voice, .sd-vtl-h-voice { --lane-h: 38px; }
.sd-vtl-tall .sd-vtl-h-video, .sd-vtl-tall .sd-vtl-video { height: 86px; }
.sd-vtl-tall .sd-vtl-text, .sd-vtl-tall .sd-vtl-h-text,
.sd-vtl-tall .sd-vtl-layer, .sd-vtl-tall .sd-vtl-h-layer { --lane-h: 48px; }
.sd-vtl-tall .sd-vtl-music, .sd-vtl-tall .sd-vtl-h-music,
.sd-vtl-tall .sd-vtl-voice, .sd-vtl-tall .sd-vtl-h-voice { --lane-h: 52px; }
.sd-vtl-text, .sd-vtl-h-text, .sd-vtl-layer, .sd-vtl-h-layer, .sd-vtl-music, .sd-vtl-h-music, .sd-vtl-voice, .sd-vtl-h-voice {
  height: calc(6px + var(--lanes, 1) * var(--lane-h));
}
/* C8: «New layer», a slim row under the layers to drop a video or a photo on — the words in the
   lane, in a dashed box the width of the room, and its head in grey: nothing is on it yet. */
.sd-vtl-fresh, .sd-vtl-h-fresh { height: 30px; }
.sd-vtl-h-fresh .sd-vtl-th-name { color: var(--muted); font-weight: 500; }
.sd-vtl-fresh-say {
  position: absolute; left: 2px; right: 2px; top: 3px; bottom: 3px; display: flex; align-items: center; gap: 8px; padding: 0 10px;
  border: 1.5px dashed var(--sd-line); border-radius: 6px; color: var(--muted); font-size: 12.5px; white-space: nowrap; overflow: hidden;
  pointer-events: none;
}
.sd-vtl-fresh-say > svg { flex: 0 0 auto; }
.sd-vtl-scroll.taking .sd-vtl-fresh-say { border-color: var(--accent); color: var(--accent-ink); background: var(--accent-soft); }
/* Taller, the timeline takes more of the screen, and the picture gives the room up. */
.sd-vdock:has(.sd-vtl-tall) { max-height: 56vh; }

.sd-vtl-scroll { position: relative; overflow-x: auto; overflow-y: hidden; min-width: 0; touch-action: pan-y; user-select: none; }
.sd-vtl-lane { position: relative; min-width: 100%; }
/* Its ticks are drawn to the next figure past the cut's end, so a trim of a frame does not
   draw it again (B5); past the lane they are cut, and add no room to scroll into. */
.sd-vtl-ruler { position: relative; height: 30px; overflow: hidden; cursor: text; }
.sd-vtl-tick { position: absolute; bottom: 3px; width: 1px; height: 5px; background: var(--border); }
.sd-vtl-mark { position: absolute; top: 1px; transform: translateX(-50%); font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sd-vtl-mark.first { transform: none; }
.sd-vtl-rows { position: relative; display: flex; flex-direction: column; }
.sd-vtl-row { position: relative; flex: 0 0 auto; }
.sd-vtl-empty { position: absolute; left: 8px; top: 50%; transform: translateY(-50%); font-size: 12px; color: var(--muted); white-space: nowrap; }

.sd-vtl-clip {
  position: absolute; top: 4px; bottom: 4px; overflow: hidden; cursor: grab;
  border: 2px solid transparent; border-radius: 8px; background: #2a2b33 left center / auto 100% repeat-x;
}
.sd-vtl-clip.on { border-color: var(--accent); }
/* The clip's own frames, as the mockup draws its strips: drawn by studio-video-film.js at the
   width it was drawn for, over the single frame the block's background repeats — which is
   what shows until the strip has a frame, and for good where the file cannot be read. */
.sd-vtl-film { position: absolute; left: 0; top: 0; display: block; height: 100%; pointer-events: none; }
.sd-vtl-label {
  position: absolute; left: 8px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; gap: 8px;
  max-width: calc(100% - 64px); padding: 5px 10px; overflow: hidden; border-radius: 6px;
  background: rgba(255, 255, 255, .94); color: #111; font-size: 13px; font-weight: 500; white-space: nowrap;
  pointer-events: none;
}
.sd-vtl-num { font-weight: 700; font-variant-numeric: tabular-nums; }
.sd-vtl-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sd-vtl-len {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%); padding: 4px 8px; border-radius: 6px;
  background: rgba(12, 12, 16, .78); color: #fff; font-size: 12.5px; font-weight: 600; white-space: nowrap; pointer-events: none;
}
/* Too narrow for its words, a clip keeps its number, and then only its picture. The number
   has the clip's width then, not the width less the length chip it no longer shows: a clip of
   a second at 1440 was left eleven pixels for «04». */
.sd-vtl-clip.narrow .sd-vtl-len, .sd-vtl-clip.narrow .sd-vtl-name { display: none; }
.sd-vtl-clip.narrow .sd-vtl-label { max-width: calc(100% - 28px); }
.sd-vtl-clip.tiny .sd-vtl-label { display: none; }
/* A join sits on the line between two clips, half over each, and over the number of the clip
   after it and the length of the one before: both are set in by the join's half. */
.sd-vtl-join ~ .sd-vtl-clip .sd-vtl-label { left: 17px; }
.sd-vtl-clip:has(~ .sd-vtl-join) .sd-vtl-len { right: 15px; }
.sd-vtl-grip { position: absolute; top: 0; bottom: 0; width: 8px; cursor: ew-resize; z-index: 1; }
.sd-vtl-grip.sd-vtl-start { left: -2px; }
.sd-vtl-grip.sd-vtl-end { right: -2px; }
.sd-vtl-clip.on .sd-vtl-grip, .sd-vtl-bar.on .sd-vtl-grip { background: var(--accent); }
.sd-vtl-join {
  position: absolute; top: 50%; z-index: 2; display: inline-grid; place-items: center; width: 26px; height: 26px; padding: 0;
  transform: translate(-50%, -50%); border: 1px solid var(--sd-line); border-radius: 7px; background: var(--panel);
  color: var(--text); cursor: pointer; box-shadow: var(--sd-sh-1);
}
.sd-vtl-join.on { border-color: var(--accent-line); color: var(--accent); }
.sd-vtl-join:disabled { cursor: default; opacity: .6; }
.sd-more-pop.sd-vtl-joinpop { top: calc(100% - 2px); right: auto; min-width: 210px; z-index: 5; }
/* Where «Create a video» will put its clip, while it is being chosen: a dashed «+» centred on
   its cut and as tall as the clips, held off them by a ring of the dock's own ground, as the
   mockup draws the clips parting round it. Nothing in the cut moves for it — it is a place,
   not a gap — and the join it sits on gives the cut up to it. 44 pixels wide: `SD_VTL_SLOT`.
   The «+» is a glyph on the panel, in the accent's ink: 6.38:1 on white as `:root` records. */
.sd-vtl-slot {
  position: absolute; top: 4px; bottom: 4px; z-index: 2; display: grid; place-items: center; width: 44px; padding: 0;
  transform: translateX(-50%); border: 1.5px dashed var(--accent); border-radius: 8px;
  background: var(--panel); color: var(--accent-ink); cursor: pointer; box-shadow: 0 0 0 4px var(--panel);
}
.sd-vtl-slot:hover { background: linear-gradient(var(--accent-soft), var(--accent-soft)) var(--panel); }
.sd-vtl-slot:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* §7: a block's keyframes, as small diamonds along its foot — on a clip's frames and on a
   picture's bar alike, so each is ringed in the panel's own ground to stand off both. They
   take no press: the inspector's Animation tab puts them and takes them away. */
.sd-vtl-keys { position: absolute; left: 0; right: 0; bottom: 3px; z-index: 1; height: 9px; pointer-events: none; }
.sd-vtl-key {
  position: absolute; top: 0; width: 7px; height: 7px; margin-left: -3.5px; border-radius: 1px;
  background: var(--accent); box-shadow: 0 0 0 1.5px var(--panel); transform: rotate(45deg);
}

/* The timeline's right-click menu: the Studio's menu rows at the pointer — placed in the window
   by `studioMenuPopup`, which flips it left of the pointer and above it near the edges — with
   each row's keys on its right, and the reason a row cannot act as its tooltip. */
.sd-more-pop.sd-vtl-ctx { position: fixed; top: 0; left: 0; right: auto; z-index: 60; min-width: 236px; max-width: min(360px, calc(100vw - 16px)); overflow-y: auto; outline: none; }
.sd-vtl-ctx .sd-ctx-row { display: flex; align-items: center; gap: 10px; width: 100%; }
.sd-vtl-ctx .sd-ctx-words { flex: 1 1 auto; min-width: 0; }
.sd-vtl-ctx .sd-ctx-keys { flex: 0 0 auto; margin-left: 18px; font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sd-vtl-ctx .sd-ctx-caret { flex: 0 0 auto; transform: rotate(-90deg); color: var(--muted); }
.sd-vtl-ctx .sd-ctx-mark { flex: 0 0 14px; width: 14px; height: 14px; }
.sd-vtl-ctx .sd-ctx-row:focus-visible { background: var(--panel-2); outline: 2px solid var(--accent); outline-offset: -2px; }
.sd-vtl-ctx .sd-ctx-row[aria-expanded="true"] { background: var(--panel-2); }
/* Off, as a menu row that cannot be pressed is drawn — and still reachable with the arrows, so a
   screen reader hears it and why. */
.sd-vtl-ctx .sd-ctx-row[aria-disabled="true"] { opacity: .45; cursor: default; }
.sd-vtl-ctx .sd-ctx-row[aria-disabled="true"]:hover { background: transparent; }
.sd-vtl-ctx .sd-ctx-sep { height: 1px; margin: 4px 6px; background: var(--sd-line); }
/* The block the menu gives the focus back to, said as a focus is. */
.sd-vtl-clip:focus-visible, .sd-vtl-bar:focus-visible, .sd-vtl-scene:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.sd-vtl-bar {
  position: absolute; top: calc(3px + var(--lane, 0) * var(--lane-h)); height: calc(var(--lane-h) - 2px); display: flex; align-items: center; gap: 8px; padding: 0 12px;
  overflow: hidden; border: 1.5px solid transparent; border-radius: 6px; cursor: grab;
  font-size: 13.5px; white-space: nowrap;
}
.sd-vtl-text .sd-vtl-bar { background: #e6e0fb; color: #3b2a78; }
/* C7, C8: the pictures and the clips over the video, on their layers' rows, in a colour of
   their own — with their own picture at the head of each bar. */
.sd-vtl-layer .sd-vtl-bar { background: #fde4cf; color: #7a3410; padding-left: 4px; }
.sd-vtl-bar-pic {
  position: relative; z-index: 1; flex: 0 0 auto; align-self: stretch; width: 40px; margin: 3px 0; border-radius: 4px;
  background: #2a2b33 center / cover no-repeat; pointer-events: none;
}
.sd-vtl-bar-pic[hidden] { display: none; }
.sd-vtl-layer .sd-vtl-bar:has(.sd-vtl-bar-pic[hidden]) { padding-left: 12px; }
.sd-vtl-music .sd-vtl-bar, .sd-vtl-voice .sd-vtl-bar { background: #cdf2e3; color: #0f5c46; }
/* A scene, drawn by its code and cut from no file: its block on the video row and its bar over
   the video in a colour of their own, with the glyph of motion before its name. */
.sd-vtl-clip.motion { background-color: var(--sd-scene-block); }
.sd-vtl-layer .sd-vtl-bar.motion { background: var(--sd-scene); color: var(--sd-on-scene); padding-left: 12px; }
.sd-vtl-mark-scene { flex: 0 0 auto; }
/* A sound's name and length sit on its waveform, whose strokes ran through the words: each on
   a chip of the bar's own colour, as a clip's number sits on a chip over its picture. */
.sd-vtl-music .sd-vtl-bar-t, .sd-vtl-voice .sd-vtl-bar-t,
.sd-vtl-music .sd-vtl-bar-len, .sd-vtl-voice .sd-vtl-bar-len { padding: 1px 6px; border-radius: 5px; background: inherit; }
.sd-vtl-bar.on { border-color: var(--accent); }
/* What a held drag carries floats over its row, in front of whatever it passes over: the rows
   keep the lanes the drag found them in until the release (`holdLanes`), so a bar dragged over
   another lies on it rather than opening a lane and pushing every row under it down. A clip of
   the video row carried onto a layer, or a picture carried down onto the row, is drawn so too. */
.sd-vtl-bar.carried, .sd-vtl-clip.carried { z-index: 3; cursor: grabbing; box-shadow: 0 6px 18px rgba(12, 12, 16, .35); }
.sd-vtl-bar-t { position: relative; z-index: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; pointer-events: none; }
.sd-vtl-bar-len { position: relative; z-index: 1; margin-left: auto; font-variant-numeric: tabular-nums; pointer-events: none; }
.sd-vtl-wave { position: absolute; left: 0; top: 6px; width: 100%; height: calc(100% - 12px); pointer-events: none; }
.sd-vtl-wave path { stroke: #2cc79a; stroke-width: .7; fill: none; opacity: .9; }
/* The glyph a bar starts with, in the bar's own ink: a sound's note, a line's «T», a picture. */
.sd-vtl-bar > svg:not(.sd-vtl-wave) { position: relative; z-index: 1; flex: 0 0 auto; pointer-events: none; }
/* B4: what an older sound plays past its file's end — silence — hatched at the bar's end. */
.sd-vtl-past {
  position: absolute; top: 0; right: 0; bottom: 0; z-index: 0; pointer-events: auto;
  background: repeating-linear-gradient(135deg, rgba(15, 92, 70, .28) 0 3px, transparent 3px 7px);
  border-left: 1px dashed rgba(15, 92, 70, .6);
}

/* E3: a file in the air over the Studio, and the lane it can be put on. No veil: the rows
   under it are where it is aimed. A file of the left panel carried over the lane says the
   same, on the lane alone (`taking`). */
.studio-view.dropping { box-shadow: inset 0 0 0 2px var(--accent); }
.studio-view.dropping .sd-vtl-scroll, .sd-vtl-scroll.taking { background: var(--accent-soft); }
/* B1: where a dragged edge landed, while the drag lasts. */
.sd-vtl-snapline { position: absolute; top: 0; bottom: 0; left: 0; width: 0; margin-left: -1px; border-left: 2px dashed var(--accent); opacity: .85; pointer-events: none; z-index: 4; }
.sd-vtl-snapline[hidden] { display: none; }
/* Placed by `transform` from the lane's left edge, never by `left`: a transform is the
   compositor's, and the playhead moves sixty times a second (B5). It starts at its handle, in
   the ruler under the figures, and runs down every row. */
.sd-vtl-now { position: absolute; top: 16px; bottom: 0; left: 0; width: 2px; margin-left: -1px; background: var(--accent); pointer-events: none; z-index: 3; will-change: transform; }
/* The handle, as the mockup draws it: a pink tab on the line. The time it stands at is in it
   for a screen reader, and on screen in the clock under the picture. */
.sd-vtl-flag {
  position: absolute; top: 0; left: 50%; width: 12px; height: 16px; transform: translateX(-50%);
  border-radius: 4px; background: var(--accent); box-shadow: var(--sd-sh-1);
}
/* Centred on the line — but never past the lane's start, where half of it was cut off at
   00:00: `--x` is the line's distance from the start (`paintPlayhead`), up to the handle's half. */
.sd-vtl-now .sd-vtl-flag { transform: translateX(max(-50%, calc(-1 * var(--x, 64px)))); }
/* The range the montage chat is told about, marked with I and O: a wash of the accent over
   the ruler and the rows, edged in it, and a bar in the ruler under the figures. Drawn over
   the blocks and under the playhead; it takes no press, it only says where the range is. */
.sd-vtl-range {
  position: absolute; top: 0; bottom: 0; left: 0; z-index: 2; pointer-events: none;
  border-inline: 1.5px solid var(--accent-line); background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.sd-vtl-range[hidden] { display: none; }
.sd-vtl-range::before { content: ''; position: absolute; left: 0; right: 0; top: 24px; height: 5px; border-radius: 3px; background: var(--accent); opacity: .7; }

.sd-vtl-scenes { display: flex; gap: 12px; padding: 6px 2px 10px; overflow-x: auto; }
.sd-vtl-scene {
  position: relative; display: flex; flex-direction: column; gap: 6px; flex: 0 0 170px; padding: 6px;
  border: 2px solid var(--sd-line); border-radius: 10px; background: var(--panel); cursor: grab;
}
.sd-vtl-scene.on { border-color: var(--accent); }
.sd-vtl-scene.dragging { opacity: .5; }
.sd-vtl-scene-pic { position: relative; display: block; aspect-ratio: 16 / 9; border-radius: 6px; background: #2a2b33 center / cover; }
.sd-vtl-scene-pic .sd-vtl-len { top: auto; bottom: 6px; right: 6px; transform: none; }
.sd-vtl-scene-name { display: flex; gap: 6px; min-width: 0; font-size: 13px; font-weight: 500; overflow: hidden; white-space: nowrap; }

/* The dock's «Subtitles»: the list the left column's panel was, the width of the screen — the
   lines as cards side by side in the order they play, in the panel's own look (`.sd-vp-sub`).
   Its tools are the dock's head while the tab is open: «Add a subtitle», «Import file» and
   «Download ▾», whose menu names the two formats with what reads each. */
.sd-vtl-subs { display: flex; flex-direction: column; gap: 10px; padding: 2px 2px 4px; }
.sd-subs-caret { margin-left: -3px; opacity: .7; }
.sd-more-pop.sd-subs-pop { min-width: 280px; }
.sd-subs-row { display: flex; align-items: center; gap: 10px; padding: 9px 10px; }
.sd-subs-row > svg { flex: 0 0 auto; color: var(--muted); }
.sd-subs-row > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sd-subs-row b { font-size: 13.5px; font-weight: 600; }
.sd-subs-row small { font-size: 12px; color: var(--muted); }
.sd-vtl-subs .sd-vp-subs { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
.sd-vtl-subs .sd-vp-subs > .sd-vp-note { grid-column: 1 / -1; }
/* Beside the picture the middle keeps the height the tracks had (`--sd-vtl-held`): the picture
   over the dock does not jump when the tab changes, and the list scrolls inside it. In one
   column the page scrolls, and the list is as tall as it is. */
@media (min-width: 1181px) {
  .sd-vtl[data-dtab="subs"] > .sd-vtl-body { height: var(--sd-vtl-held, auto); }
}

@media (max-width: 1180px) {
  .sd-vtl-main { grid-template-columns: 132px minmax(0, 1fr); }
  .sd-vtl-th-name { gap: 6px; font-size: 13px; }
  .sd-vtl-th-name > svg { width: 18px; height: 18px; }
  .sd-vtl-th .sd-vtl-ib { width: 28px; }
}
/* **The head and the foot stay one row each on a laptop.** The tabs and the tools are some
   640 pixels in Italian, the count, the views and the zoom some 560: at 1280 the dock gives
   them about 1230. From 1366 down the slider is shorter and the buttons a little tighter all
   the same, where the old head of the three verbs and the zoom had wrapped. */
@media (min-width: 1181px) and (max-width: 1365px) {
  .sd-vtl-zoom input[type="range"] { width: 72px; }
  .sd-vtl-verb { padding: 0 10px; }
}
/* **On a phone the tools give their words up**: their glyphs are named by their label, and the
   tabs keep theirs. The head and the foot wrap where they still do not fit, the count above
   the zoom; the slider is shorter. */
@media (max-width: 620px) {
  .sd-vtl-head, .sd-vtl-foot { flex-wrap: wrap; row-gap: 6px; }
  .sd-vtl-dtab { padding: 0 10px; gap: 7px; }
  .sd-vtl-verb { padding: 0 9px; }
  .sd-vtl-verb .sd-vtl-word { display: none; }
  /* The rows keep their glyphs, their eye and their lock, and give the lane the room their
     words took: a third of the dock on a phone. The word is still there for a screen reader. */
  .sd-vtl-main { grid-template-columns: 92px minmax(0, 1fr); }
  .sd-vtl-th-word { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  /* The zoom on a row of its own under the count, its slider taking what the buttons leave. */
  .sd-vtl-foot > .sd-vtl-sep { display: none; }
  .sd-vtl-foot .sd-vtl-zoom { flex: 1 1 100%; min-width: 0; }
  .sd-vtl-zoom input[type="range"] { flex: 1 1 0; width: 0; min-width: 48px; }
  .sd-vtl-subs .sd-vp-subs { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- the inspector ---------- */
/* A card, as the left panel is: the mockups draw the two columns as two white sheets
   either side of the stage, and a hairline down one side read as a table's border. */
.sd-insp {
  display: flex; flex-direction: column; min-height: 0; padding: 18px 16px 0;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel);
  box-shadow: var(--sd-sh-1);
}
/* What the column is about, over the tabs. The left column has six labelled
   buttons and this one had nothing, so it read as a box of controls rather than as
   a panel addressing something — and on the slot the first thing drawn was a
   sentence asking the reader to select one. The icon is the subject's own, so the
   change of subject is visible before the words are read. */
.sd-insp-head {
  display: flex; align-items: center; gap: 10px;
  padding: 0 2px 14px; flex: 0 0 auto; color: var(--ink);
}
.sd-insp-head h2 { margin: 0; font-size: 17px; font-weight: 700; letter-spacing: -0.015em; }
.sd-insp-head svg { flex: 0 0 auto; width: 20px; height: 20px; color: var(--ink-2); }
.sd-insp-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--sd-line); flex: 0 0 auto; }
.sd-insp-tabs[hidden] { display: none; }

/* Align: six buttons on one row, because they are one gesture with six answers and
   a two-row grid would read as two groups. Square, so the icon — which is the whole
   of what each one says — has room to be a picture of the edge it lands on. */
/* Two groups of three, the way the mockup draws them: the horizontal edges, a gap,
   the vertical ones. Each button is a picture of the edge it lands on. */
.sd-align { display: grid; grid-template-columns: repeat(3, 1fr) 12px repeat(3, 1fr); gap: 0; }
.sd-align-gap { display: block; }
.sd-align-b {
  display: flex; align-items: center; justify-content: center;
  height: 40px; padding: 0; cursor: pointer;
  border: 1px solid var(--sd-line); border-radius: 0; margin-left: -1px;
  background: var(--sd-field); color: var(--ink-2);
}
.sd-align-b svg { width: 18px; height: 18px; }
.sd-align > .sd-align-b:nth-child(1), .sd-align > .sd-align-gap + .sd-align-b { border-radius: 10px 0 0 10px; margin-left: 0; }
.sd-align > .sd-align-b:nth-child(3), .sd-align > .sd-align-b:last-child { border-radius: 0 10px 10px 0; }
.sd-align-b:hover { color: var(--accent); background: var(--accent-soft); position: relative; z-index: 1; }

/* The turn: the number in its box and the button that puts it back to zero. */
.sd-turn { display: flex; align-items: flex-end; gap: 10px; }
.sd-turn .sd-field { flex: 1 1 auto; }
.sd-turn .sd-icon-b { width: 40px; height: 40px; border: 1px solid var(--sd-line); border-radius: 10px; }
.sd-turn .sd-icon-b:disabled { opacity: .4; cursor: default; }

/* ---------- the brand, as mockup a4 draws it ----------
   On the left the kit's pieces to press — the logo, the colours, the two faces — and
   on the right, with nothing selected, whether the piece keeps to them. */
.sd-left-block .sd-sec { padding: 16px 0 0; border-top: 0; gap: 12px; }
.sd-left-block .sd-sec:first-of-type { padding-top: 6px; }
.sd-kit-logo {
  display: flex; flex-direction: column; align-items: center; gap: 8px; width: 108px; padding: 10px 8px 8px;
  border: 1.5px solid var(--accent); border-radius: 12px; background: var(--panel);
  color: var(--muted); font: inherit; font-size: 12.5px; cursor: pointer;
}
.sd-kit-logo img { display: block; width: 88px; height: 56px; object-fit: contain; }
.sd-kit-logo:hover { background: var(--accent-soft); }
.sd-kit-font-role { margin: 4px 0 -4px; font-size: 13px; color: var(--muted); }
.sd-kit-font {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; padding: 12px 16px;
  border: 1px solid transparent; border-radius: 12px; background: var(--sd-field); color: var(--text);
  font: inherit; text-align: left; cursor: pointer;
}
button.sd-kit-font:hover { border-color: var(--accent-line); background: var(--accent-soft); }
.sd-kit-font b { font-size: 24px; font-weight: 600; line-height: 1.15; letter-spacing: -.01em; }
.sd-kit-font small { font-size: 12.5px; color: var(--muted); }
.sd-kit-font-static { cursor: default; padding: 10px 14px; }
.sd-kit-font-static b { font-size: 20px; }
.sd-left-block > .sd-wide { margin-top: 20px; }

.sd-rules-say { margin: 0 0 4px; }
.sd-sec h3 { display: flex; align-items: center; gap: 6px; }
.sd-rules-logo {
  display: grid; place-items: center; height: 92px; padding: 14px;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel);
}
.sd-rules-logo img {
  display: block; max-width: 70%; max-height: 52px; object-fit: contain;
  outline: 1.5px dashed var(--accent); outline-offset: 10px; border-radius: 2px;
}
.sd-rules-palette { display: flex; flex-wrap: wrap; gap: 6px; }
.sd-rules-palette i { width: 26px; height: 26px; border-radius: 50%; border: 1px solid var(--sd-line); }
.sd-check { display: flex; flex-direction: column; gap: 4px; padding: 4px 0 8px; }
.sd-check + .sd-check { border-top: 1px dashed var(--sd-line); padding-top: 10px; }
.sd-check-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.sd-check-name { display: inline-flex; align-items: center; gap: 9px; font-size: 14px; font-weight: 500; color: var(--text); }
.sd-check-name svg { color: var(--ink-2); }
.sd-check.off .sd-check-name { color: var(--muted); }
.sd-check-mark {
  display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
  font-size: 12px; font-weight: 800; line-height: 1; color: #fff;
}
.sd-check-mark.ok { background: var(--ok); }
.sd-check-mark.bad { background: var(--danger, #e5484d); }
.sd-check-mark.warn { background: #f5a524; border-radius: 4px; }
.sd-check-mark.none, .sd-check-mark.off { display: none; }
.sd-check-mark svg { width: 12px; height: 12px; stroke-width: 3; }
.sd-check-say { margin: 0 0 0 26px; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.sd-check[data-state="warn"] .sd-check-say { color: #b7791f; }
.sd-check[data-state="bad"] .sd-check-say { color: var(--danger-ink); }
.sd-rules-list { display: flex; flex-wrap: wrap; gap: 5px; margin: 4px 0 0 26px; }
.sd-rules-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--danger-line); background: var(--danger-soft); font-size: 11.5px; color: var(--ink-2);
}
.sd-insp-tab {
  flex: 1 1 0; padding: 10px 8px; margin-bottom: -1px; border: 0; border-bottom: 2px solid transparent;
  background: transparent; color: var(--muted); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
}
.sd-insp-tab:hover { color: var(--text); }
.sd-insp-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.sd-insp-body {
  flex: 1 1 auto; overflow-y: auto; padding: 4px 2px 22px; margin-right: -8px; padding-right: 8px;
  display: flex; flex-direction: column; gap: 0;
}
/* The column scrolls; what is in it does not shrink. A button of a set height — a sound's
   42-pixel Delete — was squeezed to the 23 of its words when the column was long. */
.sd-insp-body > * { flex-shrink: 0; }
.sd-insp-body::-webkit-scrollbar { width: 8px; }
.sd-insp-body::-webkit-scrollbar-thumb { background: #DEDEE4; border-radius: 8px; border: 3px solid var(--panel); }
/* **Flat, with one hairline between two**, which is the whole difference between the
   mockups' inspector and the one that was here: a column of boxed cards with 9px
   capitals over them read as a settings dump, and a heading in the reader's own
   words over controls that are simply there reads as a panel about the thing. */
.sd-sec { display: flex; flex-direction: column; gap: 12px; padding: 18px 0; border-top: 1px solid var(--sd-line); }
.sd-sec:first-child { border-top: 0; padding-top: 12px; }
.sd-sec h3 { margin: 0; font-size: 14px; font-weight: 600; letter-spacing: -.005em; color: var(--text); }
/* What a section says when the control it would hold has nothing to offer. */
.sd-sec-say { margin: -4px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.sd-file { display: flex; gap: 9px; align-items: center; }
.sd-file-thumb { width: 46px; height: 36px; border-radius: 7px; background: var(--sd-field) center/cover; flex: 0 0 auto; border: 1px solid var(--sd-line); }
.sd-file div { display: flex; flex-direction: column; min-width: 0; }
.sd-file b { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-file .hint { margin: 1px 0 0; font-size: 10.5px; }
/* A label over its control, never beside it: a 74px column of labels was what made
   every row a table, and it cut «Rounded corners» into two lines on the one screen
   where the words are the only thing that says what a slider does. */
.sd-slider {
  display: grid; grid-template-columns: minmax(0, 1fr) 58px; grid-template-areas: "name name" "range out";
  align-items: center; column-gap: 12px; row-gap: 8px; font-size: 13px; color: var(--muted);
}
.sd-slider > span { grid-area: name; }
.sd-slider input[type="range"] { grid-area: range; width: 100%; accent-color: var(--accent); }
.sd-slider b {
  grid-area: out; display: grid; place-items: center; height: 36px;
  border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel);
  font-family: inherit; font-size: 13px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--text);
}
/* `margin: 0` because these are `<label>`s and the app gives every label ten pixels
   above and below: inside a flex column that has its own gap, that was a second gap
   nobody declared, and it is why the sliders stood a thumb's height further apart than
   the fields. */
.sd-field { display: flex; flex-direction: column; align-items: stretch; gap: 7px; margin: 0; font-size: 13px; color: var(--muted); }
.sd-slider { margin: 0; }

/* Two fields side by side — X and Y, width and height — which is how every mockup
   pairs the two halves of one quantity. */
.sd-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* A number with its unit inside the box, on the right, the way the mockups write
   «120 px» and «0.6 s». The unit is part of what the field says, so it is drawn in it
   rather than in the label, where it would be one more word to read before the value. */
.sd-unit-box { position: relative; display: block; }
.sd-unit-box input { padding-right: 34px; font-variant-numeric: tabular-nums; }
.sd-unit-box i {
  position: absolute; right: 12px; top: 50%; transform: translateY(-50%);
  font-style: normal; font-size: 12px; color: var(--muted); pointer-events: none;
}
.sd-unit-box input::-webkit-outer-spin-button, .sd-unit-box input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.sd-unit-box input { -moz-appearance: textfield; }

/* A setting that is on or off, with the sentence that says what «on» does under it.
   A switch and not a checkbox, because the mockups draw switches and because the
   state is what the eye has to find: a pink track is legible from across the column. */
.sd-toggle { display: flex; flex-direction: column; gap: 6px; }
.sd-toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sd-toggle-name { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; color: var(--text); }
.sd-toggle p { margin: 0; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.sd-switch {
  position: relative; flex: 0 0 auto; width: 44px; height: 26px; padding: 0; border: 0;
  border-radius: 999px; background: var(--sd-line); cursor: pointer; transition: background .15s ease;
}
.sd-switch::after {
  content: ''; position: absolute; left: 3px; top: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(12, 12, 14, .25); transition: transform .15s ease;
}
.sd-switch[aria-checked="true"] { background: var(--accent); }
.sd-switch[aria-checked="true"]::after { transform: translateX(18px); }
.sd-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sd-switch:disabled { opacity: .45; cursor: default; }

/* One of a few, all visible at once: Colour / Gradient / Image. The chosen one is a
   white pill with the accent's outline inside the trough, the same drawing as the two
   modes over the canvas. */
.sd-seg { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 3px; padding: 3px; border-radius: 11px; background: var(--sd-field); }
.sd-seg button {
  height: 36px; padding: 0 8px; border: 1px solid transparent; border-radius: 8px; background: transparent;
  color: var(--muted); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer; white-space: nowrap;
}
.sd-seg button:hover { color: var(--text); }
.sd-seg button.on { background: var(--panel); border-color: var(--accent-line); color: var(--accent); box-shadow: var(--sd-sh-1); }

/* A small «i» after a heading, whose title is the sentence the heading cannot hold. */
.sd-info { display: inline-grid; place-items: center; width: 16px; height: 16px; color: var(--muted); cursor: help; }
.sd-info svg { width: 15px; height: 15px; }

/* A full-width outlined button at the foot of a section — «Background picture…»,
   «Group», «Manage kit» — the one shape a secondary action has in the mockups. */
.sd-wide {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  height: 42px; padding: 0 14px; border: 1px solid var(--sd-line); border-radius: 11px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
}
.sd-wide:hover { border-color: var(--border); background: var(--panel-2); }
.sd-wide.go { border-color: transparent; background: linear-gradient(135deg, var(--accent), var(--accent-hi)); color: var(--on-solid); }
.sd-wide.go:hover { filter: brightness(1.06); }
.sd-wide:disabled { opacity: .5; cursor: default; }
.sd-wide svg { width: 16px; height: 16px; }
.sd-field input, .sd-field select {
  width: 100%; height: 40px; padding: 0 12px; border: 1px solid var(--sd-line); border-radius: 10px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 14px;
}
.sd-field select { padding-right: 32px; }
.sd-field input:focus-visible, .sd-field select:focus-visible { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft); }
.sd-field input[type="color"] { padding: 2px; height: 28px; }
.sd-field input[type="checkbox"] { width: auto; height: auto; }
.sd-input, .sd-textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--sd-line); border-radius: 10px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 14px;
}
.sd-input { height: 40px; padding-block: 0; }
.sd-textarea { resize: vertical; line-height: 1.4; }
.sd-row { display: flex; gap: 5px; flex-wrap: wrap; }
.sd-row .btn { border-radius: var(--sd-r-sm); }
.sd-looks { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.sd-look {
  display: flex; flex-direction: column; gap: 3px; padding: 3px; border: 1.5px solid transparent;
  border-radius: var(--sd-r-sm); background: var(--sd-field); color: var(--muted); font: inherit;
  font-size: 10px; cursor: pointer;
}
.sd-look.on { border-color: var(--accent); color: var(--accent-ink); }
.sd-look-chip { height: 34px; border-radius: 6px; background: var(--panel) center/cover; }

/* An icon-only control. 28px is under the 44px a finger wants, and it is the right
   answer here: these sit inside a 306px inspector on a screen that needs a mouse to
   be usable at all. The name is in `aria-label` and in `title`, never absent. */
.sd-ib {
  display: grid; place-items: center; width: 28px; height: 28px; flex: 0 0 auto; padding: 0;
  border: 1px solid transparent; border-radius: 7px; background: transparent; color: var(--muted);
  cursor: pointer; transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.sd-ib:hover:not(:disabled) { background: var(--sd-field); color: var(--text); border-color: var(--sd-line); }

.sd-ib:disabled { opacity: .3; cursor: default; }
.sd-ib:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Export, which is a menu on the tab that can produce four files. The caret is part
   of the button and not a second target: splitting it gives a two-pixel strip that is
   a different command from the thing beside it. */
.sd-go-menu { display: inline-flex; align-items: center; gap: 7px; }
.sd-go-caret { font-size: 10px; opacity: .85; }
.sd-export-pop { right: 0; left: auto; min-width: 150px; }
.sd-export-pop .sd-more-row.on { color: var(--accent); font-weight: 600; }

.sd-swatches { display: flex; gap: 10px; flex-wrap: wrap; }
/* Round, which is the mockups' own hand. The sixteen the table holds stay sixteen:
   the mockup draws nine because nine fitted its two rows, and dropping seven colours
   to match a picture is a loss nobody asked for. */
.sd-swatch { width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--sd-line); cursor: pointer; padding: 0; }
.sd-swatch:hover { transform: scale(1.08); }
/* The one in use, ringed in the accent with a white gap, which is how every mockup
   marks a chosen colour: a ring on the colour itself, not a tick over it. */
.sd-swatch.on { box-shadow: 0 0 0 2px var(--panel), 0 0 0 4px var(--accent); }

/* One accent per view. The gradient is the action that produces the deliverable —
   the HTML5, the PNG, the saved cut — and nothing else wears it. Everything else
   that is not a ghost is a plain filled control: still clearly a button, and it
   stops the inspector reading as a column of equally urgent requests. */
.sd-sec > .btn:not(.ghost) {
  background: var(--sd-field); border-color: var(--sd-line); color: var(--text);
  font-weight: 600; padding: 9px 13px; border-radius: var(--sd-r-sm);
}
.sd-sec > .btn:not(.ghost):hover { border-color: var(--ink); background: var(--field); }
.sd-sec > .btn.go {
  background: linear-gradient(135deg, var(--accent), var(--accent-hi)); border-color: transparent;
  color: var(--on-solid); box-shadow: 0 6px 18px -8px var(--accent);
}
.sd-sec > .btn.go:hover { filter: brightness(1.06); border-color: transparent; }
.sd-sec > .btn:not(.ghost):disabled { background: var(--sd-field); color: var(--muted); box-shadow: none; border-color: var(--sd-line); }

.sd-pick-card { width: min(760px, 92vw); }
.sd-pick-grid { display: flex; flex-wrap: wrap; gap: 7px; max-height: 52vh; overflow-y: auto; margin: 10px 0; }

/* ---------- rich media: the left column and the banner ---------- */
/* The rail and the panel it fills. `.sd-left` was a single scrolling column and is
   now a row of two: the six icons stay put while the panel beside them scrolls, which
   is the whole point of a rail — a control that scrolls away is a control you have to
   go looking for. The scrolling therefore moves to `.sd-left-panel`, the scrollbar
   rules above with it. */
.sd-left { display: flex; flex-direction: row; gap: 12px; min-height: 0; }
.sd-left[hidden] { display: none; }
.sd-rail { flex: 0 0 auto; width: 72px; display: flex; flex-direction: column; gap: 6px; }
.sd-rail-b {
  display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 11px 2px 10px;
  border: 1px solid transparent; border-radius: 12px; background: transparent;
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 500; line-height: 1.2;
  text-align: center; cursor: pointer;
}
.sd-rail-b svg { width: 22px; height: 22px; }
.sd-rail-b:hover { background: var(--panel-2); color: var(--text); }
.sd-rail-b.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent); }
/* The panel is a fixed width and the rail is beside it, so folding the panel gives
   the stage exactly the panel back rather than half of it. */
.sd-left-panel {
  position: relative; flex: 0 0 auto; width: 322px; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 22px; padding: 20px 18px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel);
  box-shadow: var(--sd-sh-1);
}
.sd-left-panel[hidden] { display: none; }
/* One fold for the column, pinned to its corner: some panels draw several groups,
   so a chevron in a heading would be three chevrons on one panel. */
.sd-left-fold {
  position: absolute; right: 12px; top: 16px; width: 26px; height: 26px;
  display: grid; place-items: center; padding: 0;
  border: none; border-radius: var(--sd-r-sm); background: transparent;
  color: var(--muted); cursor: pointer;
}
.sd-left-fold:hover { background: var(--panel-2); color: var(--text); }

/* The four doors on a picture, and the sections underneath them.
   Closed at rest: an inspector that opens every card is a column somebody scrolls
   to reach the one control they came for. */
.sd-act-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
/* «Improve quality»: a row of its own under the four, not an orphan in half of one. */
.sd-act[data-act="enhance"] { grid-column: 1 / -1; }
.sd-act {
  display: flex; align-items: center; gap: 7px; padding: 9px 10px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-sm); background: var(--sd-field);
  color: var(--text); font: inherit; font-size: 11px; font-weight: 600; text-align: left; cursor: pointer;
}
.sd-act:hover:not(:disabled) { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-ink); }
.sd-act.on { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-ink); }
.sd-act:disabled { opacity: .45; cursor: default; }
.sd-act-ic { display: inline-flex; flex: 0 0 auto; color: var(--muted); }
.sd-act:hover:not(:disabled) .sd-act-ic, .sd-act.on .sd-act-ic { color: var(--accent-ink); }

.sd-disc { border: 1px solid var(--sd-line); border-radius: var(--sd-r-sm); overflow: hidden; }
.sd-disc-head {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 9px 10px; border: 0; background: transparent; color: var(--text);
  font: inherit; font-size: 11px; font-weight: 700; text-align: left; cursor: pointer;
}
.sd-disc-head:hover { background: var(--panel-2); }
.sd-disc-head svg { color: var(--muted); transition: transform .15s ease; }
.sd-disc.on .sd-disc-head svg { transform: rotate(180deg); }
.sd-disc-body { display: flex; flex-direction: column; gap: 9px; padding: 0 10px 10px; }

/* The image editor's door on a picture: what it is for, and the one button that
   opens it — the mockup's «Draw and edit» card, over the crop, fill and adjust tiles. */
.sd-rt-card { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 4px; padding: 14px; border: 1px solid var(--accent-line); border-radius: var(--sd-r-lg); background: var(--accent-soft); }
.sd-rt-card-ic { width: 30px; height: 30px; display: grid; place-items: center; border-radius: 9px; background: var(--panel); color: var(--accent); }
.sd-rt-card h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--text); }
.sd-rt-card p { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }

/* The archive, as squares. Same tile as the picker's, one row narrower. */
.sd-asset-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
.sd-asset { padding: 0; height: 58px; overflow: hidden; border: 1px solid var(--sd-line); border-radius: var(--sd-r-sm); background: var(--sd-field); cursor: pointer; }
.sd-asset:hover { border-color: var(--accent-line); }
.sd-asset.on { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-asset img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The same tiles on the Page panel, three to a row: the inspector is narrower than the
   left column, and six photographs in two rows is the whole of what it offers. */
.sd-ground-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.sd-ground-grid .sd-asset { height: 54px; }

/* The stack. Topmost first, because that is how somebody looking at the slot reads
   into it, and the eye is the only writer `visible` has ever had. */
/* ---------- Layers, as the mockup draws them ----------
   The document as a group you can fold, and a row per layer: a handle, an eye, a
   picture of the layer, its name, a lock and a menu. The selected row is the pink
   one; a hidden one is faded; a locked one says so with its padlock. */
.sd-lay-group {
  display: flex; align-items: center; gap: 9px; width: 100%; height: 44px; padding: 0 12px;
  border: 0; border-radius: 12px; background: var(--sd-field); color: var(--text);
  font: inherit; font-size: 14px; text-align: left; cursor: pointer;
}
.sd-lay-group b { flex: 1 1 auto; min-width: 0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-lay-group small { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.sd-lay-group svg { color: var(--muted); flex: 0 0 auto; }
.sd-lay-group .sd-lay-fold { transform: rotate(-90deg); transition: transform .15s ease; }
.sd-lay-group.on .sd-lay-fold { transform: none; }
.sd-lay-list { position: relative; display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.sd-lay {
  display: flex; align-items: center; gap: 4px; min-height: 58px; padding: 0 6px 0 4px;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel);
}
.sd-lay:hover { border-color: var(--border); }
.sd-lay.on { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 1px var(--accent-line); }
.sd-lay.drag { opacity: .55; }
.sd-lay-grip { display: inline-grid; place-items: center; width: 18px; height: 32px; color: var(--muted); cursor: grab; touch-action: none; flex: 0 0 auto; }
.sd-lay-grip:active { cursor: grabbing; }
.sd-lay-name {
  display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0; height: 50px; padding: 0 4px;
  border: 0; background: transparent; color: var(--text); font: inherit; font-size: 14px; font-weight: 500;
  text-align: left; cursor: pointer;
}
.sd-lay-name span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-lay-b {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 30px; height: 30px; padding: 0;
  border: 0; border-radius: 8px; background: transparent; color: var(--ink-2); cursor: pointer;
}
.sd-lay-b:hover { background: var(--panel-2); color: var(--text); }
.sd-lay-b:disabled { opacity: .35; cursor: default; }
.sd-lay-b.off { color: var(--muted); opacity: .6; }
.sd-lay-lock { color: var(--muted); }
.sd-lay-lock.on { color: var(--accent); }
.sd-lay.hid .sd-lay-name { opacity: .45; }
/* The picture at the start of a row: the layer itself, small. */
.sd-lay-thumb {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 40px; height: 40px; overflow: hidden;
  border: 1px solid var(--sd-line); border-radius: 9px; background: var(--sd-field) center / cover no-repeat; color: var(--ink-2);
}
.sd-lay-thumb.pic { background-color: var(--sd-field); }
.sd-lay-thumb-shape i { display: block; width: 24px; height: 24px; }
.sd-lay-thumb-cta i, .sd-lay-thumb-badge i {
  display: block; max-width: 34px; padding: 3px 4px; border-radius: 999px; overflow: hidden;
  font-style: normal; font-size: 7px; font-weight: 700; line-height: 1; white-space: nowrap; text-overflow: clip;
}
.sd-lay-thumb-badge i { border-radius: 3px; }
.sd-lay-thumb-hotspot i { display: block; width: 18px; height: 18px; border-radius: 50%; }
.sd-lay-more { position: relative; flex: 0 0 auto; }
.sd-lay-pop {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 30; min-width: 190px;
  display: flex; flex-direction: column; gap: 2px; padding: 6px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-md); background: var(--panel); box-shadow: var(--sd-sh-pop);
}
.sd-lay-pop .sd-more-row { display: flex; align-items: center; gap: 8px; }
.sd-lay-pop .sd-more-row:disabled { opacity: .4; cursor: default; }
/* Where a dragged row will land. */
.sd-lay-drop { position: absolute; left: 6px; right: 6px; height: 2px; border-radius: 2px; background: var(--accent); pointer-events: none; }
/* The panel says its own name, in the size a name is written in. It was 9.5px
   uppercase — a label, which is what you put *beside* something rather than at the
   top of it, and the panel it labelled was the one somebody could not identify. */
.sd-left-block h2 { margin: 0 0 3px; padding-right: 30px; font-size: 19px; font-weight: 700; letter-spacing: -.02em; color: var(--text); }
/* ---------- Elements, as mockup b2 draws it ----------
   A search, three tabs, the six families as big tiles, and rows of pieces each drawn
   as the thing it adds. The star in a card's corner is this viewer's favourite. */
.sd-el-find {
  display: flex; align-items: center; gap: 9px; height: 42px; margin: 4px 0 0; padding: 0 14px;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--sd-field); color: var(--muted);
}
.sd-el-find input { flex: 1 1 auto; min-width: 0; height: 100%; border: 0; background: transparent; color: var(--text); font: inherit; font-size: 13.5px; outline: none; }
.sd-el-tabs { display: grid; grid-template-columns: repeat(3, 1fr); margin: 14px 0 4px; border-bottom: 1px solid var(--sd-line); }
.sd-el-tab {
  padding: 10px 4px; margin-bottom: -1px; border: 0; border-bottom: 2px solid transparent; background: transparent;
  color: var(--muted); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
}
.sd-el-tab.on { color: var(--accent); border-bottom-color: var(--accent); }
.sd-el-sec { display: flex; flex-direction: column; gap: 10px; margin-top: 16px; }
.sd-el-sec h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--text); }
.sd-el-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.sd-el-grid.kinds { grid-template-columns: repeat(3, 1fr); }
.sd-el-grid.frames, .sd-el-grid.lines { grid-template-columns: repeat(4, 1fr); }
.sd-el-card-wrap { position: relative; min-width: 0; }
.sd-el-add {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; width: 100%;
  padding: 12px 8px; border: 1px solid var(--sd-line); border-radius: 12px; background: var(--sd-field);
  color: var(--text); font: inherit; font-size: 13px; text-align: center; cursor: pointer;
}
.sd-el-add:hover { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent-ink); }
.sd-el-add small { color: var(--muted); font-size: 11px; font-weight: 500; }
.sd-el-ic { display: inline-flex; color: var(--ink-2); }
.sd-el-add:hover .sd-el-ic { color: var(--accent); }
.sd-el-card.kind { min-height: 84px; }
.sd-el-grid.presets .sd-el-card { align-items: flex-start; justify-content: flex-start; text-align: left; padding: 10px; background: var(--panel); }
.sd-el-grid.frames .sd-el-card, .sd-el-grid.lines .sd-el-card { padding: 10px 4px 8px; gap: 6px; }
.sd-el-grid.frames .sd-el-name, .sd-el-grid.lines .sd-el-name { font-size: 10.5px; color: var(--muted); }
.sd-el-name { font-size: 12.5px; font-weight: 500; line-height: 1.25; }
.sd-el-star {
  position: absolute; top: 5px; right: 5px; display: grid; place-items: center; width: 22px; height: 22px; padding: 0;
  border: 0; border-radius: 6px; background: transparent; color: var(--muted); opacity: 0; cursor: pointer;
}
.sd-el-card-wrap:hover .sd-el-star, .sd-el-star:focus-visible, .sd-el-star.on { opacity: 1; }
.sd-el-star.on { color: #f5a524; }
.sd-el-star.on svg { fill: currentColor; }
.sd-el-none { margin-top: 14px; }
.sd-el-media { flex-direction: row; justify-content: flex-start; gap: 10px; text-align: left; padding: 10px 12px; }
.sd-el-media small { display: none; }
/* The pictures on the cards: each piece drawn as what it adds. */
.sd-el-sample { display: flex; align-items: center; justify-content: center; width: 100%; min-height: 40px; color: var(--ink); }
.sd-el-sample svg { width: 100%; height: 16px; }
.sd-el-sample-swatch { width: 44px; min-height: 44px; border-radius: 10px; border: 1px solid var(--sd-line); }
.sd-el-sample-logo img { max-width: 100%; max-height: 40px; object-fit: contain; }
.sd-el-sample-card { justify-content: flex-start; gap: 8px; }
.sd-el-sample-card i { flex: 0 0 auto; width: 40px; height: 40px; border-radius: 8px; background: var(--sd-field) center / cover no-repeat; }
.sd-el-sample-card span { display: flex; flex-direction: column; min-width: 0; }
.sd-el-sample-card b { font-size: 11px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sd-el-sample-card small { font-size: 10.5px; color: var(--muted); }
.sd-el-sample-hotspot { height: 40px; border-radius: 8px; background: linear-gradient(135deg, #eadbc8, #cfb89c); }
.sd-el-sample-hotspot i { display: grid; place-items: center; width: 20px; height: 20px; border-radius: 50%; background: #111; color: #fff; font-style: normal; font-size: 11px; font-weight: 700; }
.sd-el-sample-editorial { font-family: 'Playfair Display', Georgia, serif; font-size: 13px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; justify-content: flex-start; }
.sd-el-sample-label { font-family: 'Playfair Display', Georgia, serif; font-size: 10.5px; font-weight: 600; letter-spacing: .2em; white-space: pre-line; text-align: center; line-height: 1.35; }
.sd-el-sample-frame1 i, .sd-el-sample-frame2 i, .sd-el-sample-frame3 i, .sd-el-sample-collage i {
  display: block; height: 30px; border: 1.5px solid var(--ink-2); border-radius: 2px; background: var(--panel);
}
.sd-el-sample-frame1 i { width: 26px; }
.sd-el-sample-frame2, .sd-el-sample-frame3 { gap: 3px; }
.sd-el-sample-frame2 i { width: 17px; }
.sd-el-sample-frame3 i { width: 11px; background: var(--ink-2); border: 0; opacity: .55; }
.sd-el-sample-collage { display: grid; grid-template-columns: 17px 11px; grid-template-rows: 13px 13px; gap: 3px; justify-content: center; }
.sd-el-sample-collage i { width: auto; height: auto; }
.sd-el-sample-collage i:first-child { grid-row: 1 / 3; }

/* The product a hotspot is linked to, and the list it is picked from. */
.sd-prod {
  display: flex; align-items: center; gap: 12px; width: 100%; padding: 10px; text-align: left;
  border: 1px solid var(--sd-line); border-radius: 12px; background: var(--panel); color: var(--text); font: inherit;
}
.sd-prod-pic { flex: 0 0 auto; width: 64px; height: 64px; border-radius: 10px; background: var(--sd-field) center / cover no-repeat; }
.sd-prod-words { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
.sd-prod-words b { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-prod-words small { font-size: 13px; color: var(--text); }
.sd-prod-x { flex: 0 0 auto; width: 28px; height: 28px; font-size: 18px; line-height: 1; }
.sd-prod-list { display: flex; flex-direction: column; gap: 6px; max-height: 260px; overflow-y: auto; }
.sd-prod-pick { cursor: pointer; }
.sd-prod-pick:hover { border-color: var(--accent-line); background: var(--accent-soft); }
.sd-prod-pick .sd-prod-pic { width: 44px; height: 44px; }
.sd-foot-note { display: flex; align-items: center; gap: 8px; margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--sd-line); }
.sd-foot-note svg { flex: 0 0 auto; }

/* An icon's twelve marks, as a grid of the marks themselves. */
.sd-glyphs { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
.sd-glyph {
  display: grid; place-items: center; aspect-ratio: 1; padding: 7px; border: 1px solid var(--sd-line); border-radius: 9px;
  background: var(--sd-field); color: var(--ink-2); cursor: pointer;
}
.sd-glyph:hover { border-color: var(--accent-line); color: var(--accent); }
.sd-glyph.on { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.sd-glyph svg { width: 100%; height: 100%; }
.sd-lay-thumb-icon i { display: block; width: 24px; height: 24px; }
.sd-lay-thumb-icon svg { width: 100%; height: 100%; }
/* Four tabs on the hotspot, in a column made for three. */
.sd-insp-tabs.four .sd-insp-tab { font-size: 12.5px; padding-inline: 4px; }
/* A line under a heading: what the panel is, where «Layout» alone is only its name. */
.sd-left-say { margin: 0 0 12px; font-size: 12px; line-height: 1.4; color: var(--muted); }

/* Searching a list that is nine long today and is the sort that grows. */
.sd-find-wrap { position: relative; display: block; margin-bottom: 10px; }
.sd-find-wrap svg { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--muted); pointer-events: none; }
.sd-find {
  width: 100%; padding: 9px 11px 9px 33px;
  border: 1px solid var(--sd-line); border-radius: 999px; background: var(--sd-field);
  color: var(--text); font: inherit; font-size: 12px;
}
.sd-find::placeholder { color: var(--muted); }
.sd-find:focus { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 2px var(--accent-soft); }

/* The filters, derived from what the table actually carries. */
.sd-pills { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.sd-pill {
  padding: 7px 15px; border: 1px solid var(--sd-line); border-radius: 999px;
  background: var(--sd-field); color: var(--muted); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.sd-pill:hover { border-color: var(--accent-line); color: var(--text); }
.sd-pill.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.sd-pills-tight .sd-pill { padding: 7px 11px; }

/* The starting layouts, each drawn as the layout it is. A coloured square said
   «theme»; the words in the font they are set in say what kind of layout this is,
   which is the question somebody is asking of a panel of nine. */
.sd-tpl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 10px; }
.sd-tpl-grid .hint { grid-column: 1 / -1; margin: 2px 0; }
.sd-tpl {
  display: flex; flex-direction: column; align-items: stretch; gap: 5px; padding: 0;
  border: none; background: none; color: var(--text); font: inherit; font-size: 11px;
  font-weight: 500; text-align: left; cursor: pointer;
}
.sd-tpl-name { font-size: 12.5px; line-height: 1.25; }
.sd-tpl-mini {
  position: relative; display: block; aspect-ratio: 1 / 1; overflow: hidden;
  border: 1.5px solid var(--sd-line); border-radius: var(--sd-r-md);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.sd-tpl:hover .sd-tpl-mini { border-color: var(--accent-line); }
.sd-tpl.on .sd-tpl-mini { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.sd-tpl.on { color: var(--accent-ink); font-weight: 600; }
/* The tick on the one this document was started from. */
.sd-tpl-on {
  position: absolute; right: 7px; top: 7px; width: 22px; height: 22px; z-index: 2;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
}
/* The photograph of the layout, over the silhouette rather than instead of it: a
   file that 404s takes itself off and what was underneath is still a preview. */
.sd-tpl-shot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; z-index: 1; }
.sd-tpl-bit {
  position: absolute; display: block; overflow: hidden;
  white-space: pre; letter-spacing: -.01em;
}
.sd-tpl-bit-headline { max-width: 84%; }
.sd-tpl-bit-body { max-width: 78%; opacity: .8; }
.sd-tpl-bit-badge { border-radius: 3px; }
.sd-tpl-bit-cta { border-radius: 999px; }
.sd-tpl-bit-hotspot { width: 7%; height: 7%; border-radius: 50%; background: #fff; }
.sd-tpl-bit-scrim { width: 100%; height: 100%; left: 0 !important; top: 0 !important; background: rgba(0, 0, 0, .3); }
.sd-tpl-bit-image, .sd-tpl-bit-video {
  border: 1px dashed rgba(255, 255, 255, .5); border-radius: 3px; background: rgba(255, 255, 255, .16);
}

.sd-b-ctx {
  position: absolute; z-index: 20; display: inline-flex; align-items: center; gap: 2px;
  padding: 4px; border-radius: 10px; background: var(--panel); border: 1px solid var(--border);
  box-shadow: var(--sd-sh-pop); white-space: nowrap;
}
.sd-b-ctb {
  display: inline-flex; align-items: center; gap: 5px; border: 0; background: transparent;
  color: var(--ink); border-radius: 7px; padding: 4px 8px; font: inherit; font-size: 12px; cursor: pointer;
}
.sd-b-ctb:hover { background: var(--panel-2); }
.sd-b-ctb.on { background: var(--accent-soft); color: var(--accent-ink); }
.sd-b-ctb-ic { padding: 0; width: 28px; justify-content: center; }
/* A bar wider than the frame cannot be held inside it, so it wraps instead: the
   clamp works on whatever height that leaves. `max-content` is what makes that
   height the one the clamp measured: an absolute box shrinks to the room left of
   its own `left`, so measured at one place and moved to another it wrapped a second
   time — a row taller than the clamp knew, under the frame's bottom edge. */
.sd-b-ctx { flex-wrap: wrap; width: max-content; max-width: calc(100% - 8px); }
.sd-b-ctb-sep { width: 1px; align-self: stretch; margin: 2px 3px; background: var(--border); }
.sd-b-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 7px 10px 0; font-size: 11.5px; color: var(--muted); flex: 0 0 auto;
}
.sd-b-facts { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The zoom as one object rather than four chips: a pill holding the hand, the two
   steps, the figure and the fit. «Fit» was a word among numbers, which is a word
   that gets read every time and needed reading once. */
.sd-b-zoom {
  display: inline-flex; align-items: center; gap: 2px; flex: 0 0 auto; padding: 3px;
  border: 1px solid var(--sd-line); border-radius: 999px; background: var(--panel);
}
.sd-b-hand { display: inline-grid; place-items: center; width: 26px; height: 26px; color: var(--muted); }
.sd-b-hand svg, .sd-b-zfit svg { width: 15px; height: 15px; }
.sd-b-zb {
  display: inline-grid; place-items: center; min-width: 26px; height: 26px; padding: 0 6px;
  border: none; border-radius: 999px; background: transparent; color: var(--ink);
  font: inherit; font-size: 13px; line-height: 1; cursor: pointer;
}
.sd-b-zb:hover { background: var(--panel-2); }
.sd-b-zb:disabled { opacity: .4; cursor: default; background: transparent; }
.sd-b-zval { min-width: 46px; text-align: center; font-variant-numeric: tabular-nums; font-size: 12.5px; color: var(--text); }

/* ---------- the design's video half (mockup a1) ----------
   The stage with time on screen: a transport under the slot, a timeline in the dock,
   the movements on the rail. Colours for the bars are tokens with a dark pair,
   because a lilac that reads on white is a glare on navy. */
.studio-view {
  --sd-mt-text: #E6DEFF; --sd-mt-text-ink: #34236E;
  --sd-mt-chip: #FDD5E7; --sd-mt-chip-ink: #7A1644;
  --sd-mt-mark: #DCE8F6; --sd-mt-mark-ink: #1F3A5C;
}
:root[data-theme="dark"] .studio-view, :root:not([data-theme="light"]) .studio-view {
  --sd-mt-text: #3A2F6B; --sd-mt-text-ink: #E6DEFF;
  --sd-mt-chip: #5A1C3A; --sd-mt-chip-ink: #FDD5E7;
  --sd-mt-mark: #1E3450; --sd-mt-mark-ink: #DCE8F6;
}
.sd-b-player { display: inline-flex; align-items: center; gap: 12px; min-width: 0; }
.sd-b-player[hidden] { display: none; }
.sd-b-play {
  display: inline-grid; place-items: center; width: 38px; height: 38px; padding: 0; flex: 0 0 auto;
  border: 0; border-radius: 50%; background: var(--ink); color: var(--panel); cursor: pointer;
  box-shadow: var(--sd-sh-2);
}
.sd-b-play svg { width: 16px; height: 16px; }
.sd-b-play:not(.on) svg { margin-left: 2px; }
.sd-b-play:hover { filter: brightness(1.15); }
.sd-b-clock { font-size: 14px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The fold for the timeline, beside the clock it belongs with. Marked while open. */
.sd-b-tl {
  display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px;
  border: 1px solid var(--sd-line); border-radius: 999px; background: var(--panel);
  color: var(--ink-2); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.sd-b-tl svg { width: 15px; height: 15px; }
.sd-b-tl:hover { border-color: var(--accent-line); color: var(--text); }
.sd-b-tl.on { background: var(--accent-soft); border-color: var(--accent-line); color: var(--accent-ink); }
/* The foot holds three things now, and the sentence is the one that gives way. */
.sd-b-player { flex: 0 0 auto; }
.sd-b-facts { flex: 1 1 auto; text-align: center; }

/* The dock holds the timeline in its own card, and scrolls rather than taking the
   stage: eight layers is eight rows, and the slot is still the thing being made. */
#sd-dock-rich:not(:empty) {
  max-height: 38vh; overflow: auto; padding: 10px 14px 12px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-lg); background: var(--panel);
}
.sd-mt { display: grid; grid-template-columns: 128px minmax(0, 1fr); column-gap: 12px; }
.sd-mt > .hint { grid-column: 1 / -1; margin: 6px 0; }
.sd-mt-labels { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.sd-mt-corner, .sd-mt-ruler { height: 30px; flex: 0 0 auto; }
.sd-mt-label {
  display: flex; align-items: center; gap: 9px; height: 40px; padding: 0 10px; min-width: 0;
  border: 0; border-radius: 10px; background: transparent; color: var(--text);
  font: inherit; font-size: 13px; text-align: left; cursor: pointer;
}
.sd-mt-label svg { flex: 0 0 auto; color: var(--muted); }
.sd-mt-label span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sd-mt-label:hover { background: var(--sd-field); }
.sd-mt-label.on { background: var(--accent-soft); color: var(--accent-ink); }
.sd-mt-label.on svg { color: var(--accent-ink); }
.sd-mt-label.off { opacity: .5; }
.sd-mt-lane { position: relative; display: flex; flex-direction: column; gap: 6px; min-width: 0; touch-action: none; cursor: col-resize; }
.sd-mt-ruler { position: relative; }
.sd-mt-tick {
  position: absolute; bottom: 6px; transform: translateX(-50%);
  font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.sd-mt-tick:first-child { transform: none; }
.sd-mt-tick:last-child { transform: translateX(-100%); }
.sd-mt-track { position: relative; height: 40px; flex: 0 0 auto; border-radius: 10px; background: var(--sd-field); }
.sd-mt-bar {
  position: absolute; top: 0; bottom: 0; display: flex; align-items: center; min-width: 14px;
  border-radius: 10px; overflow: hidden; cursor: grab; box-sizing: border-box;
  border: 1.5px solid transparent;
}
.sd-mt-bar:active { cursor: grabbing; }
.sd-mt-bar.on { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-halo); }
.sd-mt-bar.off { opacity: .45; }
.sd-mt-text { background: var(--sd-mt-text); color: var(--sd-mt-text-ink); }
.sd-mt-chip { background: var(--sd-mt-chip); color: var(--sd-mt-chip-ink); }
.sd-mt-mark { background: var(--sd-mt-mark); color: var(--sd-mt-mark-ink); }
/* A strip of the picture, as the mockup's filmstrip: the frame repeated at the track's
   height, which is what a picture that does not change over time looks like. */
.sd-mt-pic { background-color: var(--sd-mt-mark); background-size: auto 100%; background-repeat: repeat-x; background-position: left center; }
.sd-mt-word {
  position: relative; z-index: 1; min-width: 0; padding: 0 14px; font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; pointer-events: none;
}
/* The way in and the way out, as a lighter wash at each end of the stay. */
.sd-mt-in, .sd-mt-out { position: absolute; top: 0; bottom: 0; pointer-events: none; background: rgba(255, 255, 255, .38); }
.sd-mt-in { left: 0; }
.sd-mt-out { right: 0; }
:root[data-theme="dark"] .sd-mt-in, :root[data-theme="dark"] .sd-mt-out,
:root:not([data-theme="light"]) .sd-mt-in, :root:not([data-theme="light"]) .sd-mt-out { background: rgba(255, 255, 255, .1); }
.sd-mt-grip { position: absolute; top: 0; bottom: 0; z-index: 2; width: 9px; cursor: ew-resize; }
.sd-mt-grip-start { left: 0; }
.sd-mt-grip-end { right: 0; }
.sd-mt-bar:hover .sd-mt-grip, .sd-mt-bar.on .sd-mt-grip { background: rgba(236, 30, 121, .28); }
.sd-mt-head { position: absolute; top: 4px; bottom: 0; z-index: 3; width: 2px; margin-left: -1px; background: var(--accent); pointer-events: none; }
.sd-mt-pill {
  position: absolute; top: -4px; left: 50%; transform: translateX(-50%); padding: 3px 7px;
  border-radius: 7px; background: var(--accent); color: #fff; font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* The Animations panel: the mockup's three-column grid of cards, a tile over a name. */
.sd-mo-fam { margin: 14px 0 6px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.sd-mo-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 8px; margin-top: 10px; }
.sd-mo-fam + .sd-mo-grid { margin-top: 0; }
.sd-mo-card {
  display: flex; flex-direction: column; align-items: center; gap: 7px; min-width: 0; padding: 0;
  border: 0; background: transparent; color: var(--text); font: inherit; font-size: 12.5px; cursor: pointer;
}
.sd-mo-ic {
  display: grid; place-items: center; width: 100%; aspect-ratio: 1 / 1; max-height: 84px;
  border: 1.5px solid var(--sd-line); border-radius: 12px; background: var(--sd-field); color: var(--accent-ink);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.sd-mo-name { max-width: 100%; text-align: center; line-height: 1.25; overflow-wrap: anywhere; }
.sd-mo-card:hover:not(:disabled) .sd-mo-ic { border-color: var(--accent-line); }
.sd-mo-card.on .sd-mo-ic { border-color: var(--accent); background: var(--accent-soft); box-shadow: 0 0 0 3px var(--accent-halo); }
.sd-mo-card:disabled { cursor: default; opacity: .55; }

/* The preview, as a card that is one button. */
.sd-mo-preview {
  display: flex; align-items: center; gap: 14px; width: 100%; padding: 16px 14px; margin-top: 4px;
  border: 1px solid var(--sd-line); border-radius: var(--sd-r-md); background: var(--sd-field);
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.sd-mo-preview:hover { border-color: var(--accent-line); }
.sd-mo-preview-go {
  display: grid; place-items: center; width: 42px; height: 42px; flex: 0 0 auto;
  border-radius: 50%; background: var(--panel); color: var(--ink); box-shadow: var(--sd-sh-2);
}
.sd-mo-preview-go svg { margin-left: 2px; }
.sd-mo-preview-words { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.sd-mo-preview-words b { font-size: 13.5px; }
.sd-mo-preview-words small { font-size: 12px; color: var(--muted); }
/* The frame scrolls once the stage is bigger than the room: a zoom that cannot go
   past «fit» is a magnifier that only shrinks. */
#sd-b-frame { overflow: auto; }
/* The generation's veil hangs off the pane and not off the frame, exactly because of
   the line above: `inset: 0` inside a scrolling box is the scrolled content's inset,
   so at any zoom past «fit» the spinner would sit somewhere off-screen. */
#sd-pane-rich { position: relative; }

/* ---------- the image editor ----------
   The photo alone on the stage's dot grid, the tool column floating at its left, the
   three steps over it, the line under it — and the Edit image panel in the inspector's
   column. Every painted area has a number and a colour, and the box that asks what
   changes there opens beside it. The stage keeps its canvases at the picture's own
   pixels and only its box is scaled, so a stroke's width in the picture does not
   change with the zoom; the brush's circle is drawn at that width on screen. */
.sd-rt-frame { position: relative; overflow: hidden; }
.sd-rt-frame[hidden] { display: none; }
.sd-rt-view { position: absolute; inset: 0; overflow: auto; }
.rt-scale { display: grid; place-items: center; min-width: 100%; min-height: 100%; padding: 40px 40px 40px 110px; box-sizing: border-box; }
.rt-stage { position: relative; flex: 0 0 auto; border-radius: 4px; overflow: hidden; background: #fff; box-shadow: var(--sd-sh-pop); touch-action: none; cursor: none; }
.rt-stage.busy { cursor: progress; }
.rt-stage.comparing { cursor: ew-resize; }
.rt-stage > img, .rt-stage > canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; user-select: none; -webkit-user-drag: none; }
.rt-stage > canvas[hidden], .rt-stage > img[hidden] { display: none; }
.rt-overlay { opacity: .55; }
.rt-pins { position: absolute; inset: 0; pointer-events: none; }
.rt-pins[hidden], .rt-cursor[hidden], .rt-split[hidden], .rt-tag[hidden] { display: none; }
.rt-pin { position: absolute; transform: translate(-50%, -50%); width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center; color: #fff; font: inherit; font-size: 12px; font-weight: 700; box-shadow: 0 0 0 3px #fff, 0 2px 6px rgba(0, 0, 0, .25); pointer-events: auto; cursor: pointer; }
.rt-pin.on { box-shadow: 0 0 0 3px #fff, 0 0 0 5px var(--ink), 0 2px 6px rgba(0, 0, 0, .25); }
.rt-pin.empty { animation: rt-ask 1.6s ease-in-out infinite; }
@keyframes rt-ask { 50% { transform: translate(-50%, -50%) scale(1.12); } }
@media (prefers-reduced-motion: reduce) { .rt-pin.empty { animation: none; } }
.rt-cursor { position: absolute; transform: translate(-50%, -50%); border-radius: 50%; border: 1.5px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, .45); pointer-events: none; }
.rt-cursor.erase { border-style: dashed; }
/* Before on the left, after on the right of a line somebody drags: the view's own
   comparison, where no composition is there to show the candidate in. */
.rt-split { position: absolute; top: 0; bottom: 0; width: 0; border-left: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, .25); transform: translateX(-1px); outline: none; }
.rt-split > span { position: absolute; top: 50%; left: -15px; width: 28px; height: 28px; margin-top: -14px; border-radius: 50%; background: #fff; box-shadow: var(--sd-sh-1); }
.rt-split > span::before { content: '‹ ›'; position: absolute; inset: 0; display: grid; place-items: center; color: var(--ink); font-size: 13px; font-weight: 700; letter-spacing: 1px; }
.rt-split:focus-visible > span { box-shadow: 0 0 0 3px var(--accent); }
.rt-tag { position: absolute; top: 10px; padding: 3px 8px; border-radius: 6px; background: rgba(0, 0, 0, .55); color: #fff; font-size: 11.5px; font-weight: 600; pointer-events: none; }
.rt-tag.before { left: 10px; }
.rt-tag.after { right: 10px; }
/* The box beside an area: what changes here. In the view and not in the stage, which
   clips at the picture's edge; docked along the foot where there is no room beside. */
.rt-bubble { position: absolute; z-index: 4; width: 300px; box-sizing: border-box; display: flex; flex-direction: column; gap: 10px; padding: 12px; border-radius: 14px; background: var(--panel); color: var(--text); box-shadow: var(--sd-sh-pop); }
.rt-bubble[hidden] { display: none; }
.rt-bubble.docked { width: auto; }
.rt-bubble-head { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.rt-bubble-drop { margin-left: auto; width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; }
.rt-bubble-drop:hover { background: var(--sd-field); color: var(--danger); }
.rt-bubble-say { width: 100%; min-height: 56px; resize: vertical; box-sizing: border-box; padding: 9px 11px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--sd-field); color: var(--text); font: inherit; font-size: 13.5px; line-height: 1.45; }
.rt-bubble-say:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.rt-starters { display: flex; flex-wrap: wrap; gap: 6px; }
.rt-starter { padding: 5px 10px; border: 1px solid var(--sd-line); border-radius: 999px; background: var(--panel); color: var(--text); font: inherit; font-size: 12px; cursor: pointer; }
.rt-starter:hover { border-color: var(--accent-line); color: var(--accent-ink); }
.rt-bubble-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--muted); font-size: 11.5px; }
.rt-bubble-ok { padding: 6px 14px; border: 0; border-radius: 8px; background: var(--accent); color: #fff; font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer; }
.rt-n { flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; color: #fff; font-size: 11.5px; font-weight: 700; }
.sd-rt-tools { position: absolute; left: 16px; top: 50%; z-index: 3; transform: translateY(-50%); }
.rt-tools { display: flex; flex-direction: column; gap: 4px; padding: 6px; border-radius: 12px; background: var(--panel); box-shadow: var(--sd-sh-1); }
.rt-tools[hidden] { display: none; }
.rt-tool { display: flex; flex-direction: column; align-items: center; gap: 3px; width: 58px; padding: 8px 4px; border: 0; border-radius: 9px; background: transparent; color: var(--muted); font: inherit; font-size: 11px; cursor: pointer; }
.rt-tool:hover:not(:disabled) { background: var(--sd-field); color: var(--text); }
.rt-tool.on { background: var(--accent-soft); color: var(--accent); }
.rt-tool:disabled { opacity: .45; cursor: default; }
.rt-tool-sep { height: 1px; margin: 2px 6px; background: var(--sd-line); }
.rt-sizes { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.rt-size { width: 58px; height: 26px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; }
.rt-size:hover:not(:disabled) { background: var(--sd-field); }
.rt-size.on { background: var(--accent-soft); color: var(--accent); }
.rt-size:disabled { opacity: .45; cursor: default; }
.rt-dot { display: block; border-radius: 50%; background: currentColor; }
.sd-rt-top { position: absolute; left: 16px; right: 16px; top: 14px; z-index: 3; pointer-events: none; }
.rt-top { display: flex; align-items: center; justify-content: center; gap: 10px; }
.rt-top[hidden] { display: none; }
.rt-top > * { pointer-events: auto; }
.rt-steps { display: inline-flex; align-items: center; gap: 4px; margin: 0; padding: 4px; list-style: none; border-radius: 999px; background: var(--panel); box-shadow: var(--sd-sh-1); }
.rt-step { display: inline-flex; align-items: center; gap: 7px; padding: 5px 12px 5px 5px; border-radius: 999px; color: var(--muted); font-size: 12.5px; }
.rt-step-n { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; background: var(--sd-field); font-size: 11px; font-weight: 700; }
.rt-step.on { background: var(--accent-soft); color: var(--accent-ink); font-weight: 600; }
.rt-step.on .rt-step-n { background: var(--accent); color: #fff; }
.rt-step.done .rt-step-n { background: var(--ink); color: #fff; }
.sd-rt-hint { position: absolute; left: 0; right: 0; bottom: 10px; z-index: 3; display: flex; justify-content: center; pointer-events: none; }
.rt-hint { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 12.5px; color: var(--muted); }
.rt-sec-head { display: flex; align-items: center; gap: 8px; }
.rt-count { margin-left: auto; padding: 2px 7px; border-radius: 6px; background: var(--sd-field); color: var(--muted); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
.rt-spark { margin-left: auto; width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; }
.rt-spark:hover, .rt-spark.on { background: var(--accent-soft); color: var(--accent); }
.rt-say { width: 100%; min-height: 96px; resize: vertical; box-sizing: border-box; padding: 10px 12px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--sd-field); color: var(--text); font: inherit; font-size: 13.5px; line-height: 1.5; }
.rt-suggest { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.rt-suggest-b { padding: 8px 10px; border: 1px solid var(--sd-line); border-radius: 9px; background: var(--panel); color: var(--text); font: inherit; font-size: 12px; text-align: left; cursor: pointer; }
.rt-suggest-b:hover:not(:disabled) { border-color: var(--accent-line); color: var(--accent-ink); }
/* The list of changes: one row per area, its number, its sentence and its ×. */
.rt-areas { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; }
/* Wrapping only so the pictures under a row take a line of their own: the sentence's
   button starts from nothing and grows, so a long sentence never pushes the icon and the
   × off its line. */
.rt-area { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rt-area-open { flex: 1 1 0; min-width: 0; display: flex; align-items: flex-start; gap: 10px; padding: 9px 10px; border: 1px solid var(--sd-line); border-radius: 10px; background: var(--panel); color: var(--text); font: inherit; font-size: 13px; line-height: 1.4; text-align: left; cursor: pointer; }
.rt-area-open:hover:not(:disabled) { border-color: var(--accent-line); }
.rt-area.on .rt-area-open { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.rt-area-say { min-width: 0; overflow-wrap: anywhere; padding-top: 1px; }
.rt-area-say.empty { color: var(--danger); font-style: italic; }
.rt-area-drop { flex: 0 0 auto; width: 30px; height: 30px; border: 0; border-radius: 8px; background: transparent; color: var(--muted); font: inherit; font-size: 18px; line-height: 1; cursor: pointer; }
.rt-area-drop:hover:not(:disabled) { background: var(--sd-field); color: var(--danger); }
.rt-areas.asked .rt-area { flex-direction: column; align-items: stretch; gap: 6px; padding: 8px 10px; border-radius: 10px; background: var(--sd-field); }
.rt-area-line { display: flex; align-items: flex-start; gap: 10px; font-size: 12.5px; line-height: 1.45; }
.rt-redo { align-self: flex-start; padding: 5px 10px; border: 1px solid var(--sd-line); border-radius: 8px; background: var(--panel); color: var(--text); font: inherit; font-size: 12px; cursor: pointer; }
.rt-redo:hover:not(:disabled) { border-color: var(--accent-line); color: var(--accent-ink); }
.rt-redo:disabled { opacity: .5; cursor: default; }
.rt-note { display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 10px 12px; border-radius: 10px; background: var(--sd-field); color: var(--muted); font-size: 12.5px; line-height: 1.45; }
.rt-note svg { flex: 0 0 auto; margin-top: 1px; }
.rt-error { margin: 0; padding: 10px 12px; border-radius: 10px; background: color-mix(in srgb, var(--danger) 10%, transparent); color: var(--danger); font-size: 12.5px; line-height: 1.45; }
.rt-reason { margin: 0; color: var(--muted); font-size: 12.5px; }
.rt-wait { display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 12px 14px; }
.rt-wait .rw-pct { font-size: 26px; }
.rt-wait-say { color: var(--muted); font-size: 12.5px; }
.rt-link { align-self: center; border: 0; background: none; color: var(--accent-ink); font: inherit; font-size: 12.5px; text-decoration: underline; cursor: pointer; }
.rt-cands { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.rt-cand { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 4px; border: 1.5px solid transparent; border-radius: 10px; background: none; color: var(--muted); font: inherit; font-size: 11.5px; cursor: pointer; }
.rt-cand img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; border-radius: 7px; background: var(--sd-field); }
.rt-cand.on { border-color: var(--accent); color: var(--accent); }
.rt-asked { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; }
.rt-asked q { color: var(--muted); line-height: 1.5; }
/* The pictures attached to a change: small, numbered as the request cites them (the
   photo is image 1), each with its × — and the button that attaches another. Under an
   area's row they take a line of their own; beside it the button is an icon, so a row
   with nothing attached keeps the height it had. */
.rt-refs { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.rt-ref { position: relative; flex: 0 0 auto; width: 40px; height: 40px; border-radius: 8px; background: var(--sd-field); box-shadow: 0 0 0 1px var(--sd-line); }
.rt-ref img { display: block; width: 100%; height: 100%; object-fit: cover; border-radius: 8px; }
.rt-ref-n { position: absolute; left: -5px; bottom: -5px; min-width: 18px; height: 18px; padding: 0 4px; box-sizing: border-box; border-radius: 9px; display: grid; place-items: center; background: var(--ink); color: #fff; font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums; box-shadow: 0 0 0 2px var(--panel); }
.rt-ref-x { position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; padding: 0; border: 0; border-radius: 50%; display: grid; place-items: center; background: var(--panel); color: var(--muted); font: inherit; font-size: 13px; line-height: 1; box-shadow: var(--sd-sh-1); cursor: pointer; }
.rt-ref-x:hover:not(:disabled) { color: var(--danger); }
.rt-ref-x:disabled { opacity: .5; cursor: default; }
.rt-ref-add { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; border: 1px dashed var(--sd-line); border-radius: 8px; background: transparent; color: var(--muted); font: inherit; font-size: 12px; cursor: pointer; }
.rt-ref-add:hover:not(:disabled) { border-color: var(--accent-line); color: var(--accent-ink); }
.rt-ref-add:disabled { opacity: .5; cursor: default; }
.rt-ref-add.bare { flex: 0 0 auto; width: 30px; height: 30px; padding: 0; justify-content: center; border: 0; }
.rt-ref-add.bare:hover:not(:disabled) { background: var(--sd-field); }
.rt-ref-hint { margin: 0; color: var(--muted); font-size: 11.5px; line-height: 1.4; }
.rt-bubble-refs { display: flex; flex-direction: column; gap: 6px; }
.rt-bubble-head .rt-ref-add.bare { width: 28px; height: 28px; margin-left: auto; }
.rt-bubble-head .rt-ref-add.bare + .rt-bubble-drop { margin-left: 0; }
.rt-bubble-refs:empty { display: none; }
.rt-area > .rt-refs { flex: 1 0 100%; padding: 4px 0 2px 10px; }
.rt-asked .rt-refs { padding-top: 2px; }
.rt-ref img:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* One of those pictures enlarged beside its thumbnail, while the pointer or the keyboard
   is on it (`retouchPeekShow` in studio-retouch.js). In `body` and fixed, because every
   strip sits in a column that scrolls or a frame that clips: grown in place it was cut at
   the column's edge. So it reads the root's tokens — the `--sd-*` ones stop at
   `.studio-view` and `.edov-retouch`, and here they would resolve to no border and no
   shadow. Above the editors that open over the page (80), under every window opened over
   them (90) and a dialog (95); never a target. The padding and the caption's margin are
   the six pixels `retouchPeekPlace` reserves, and the caption is one line per row so its
   height does not depend on the width. It fades with opacity alone: the box is measured
   where it stands, and a scale would move what was measured. */
.rt-peek {
  position: fixed; left: 0; top: 0; z-index: 85; box-sizing: border-box; padding: 6px;
  border-radius: 12px; background: var(--panel); box-shadow: var(--shadow-2), 0 0 0 1px var(--border);
  pointer-events: none;
}
.rt-peek img { display: block; border-radius: 8px; object-fit: contain; }
.rt-peek-cap { display: block; margin-top: 6px; color: var(--muted); font-size: 11.5px; line-height: 16px; }
.rt-peek-cap > span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rt-peek-cap > .rt-peek-n { color: var(--text); font-weight: 600; }
@media (prefers-reduced-motion: no-preference) {
  .rt-peek:not([hidden]) { animation: rt-peek-in .12s ease-out; }
}
@keyframes rt-peek-in { from { opacity: 0; } }
/* What the rest of the Studio does while a photo is open in the editor: the stage,
   the player, the timeline and the format controls step aside; the rail stays,
   dimmed and inert, as the mockup draws it. In the preview the composition comes
   back with the candidate in it, and the editor's own frame goes — and the player,
   the timeline and the left column stay aside there too: with them back, a 1080
   square was judged at a tenth of its size, in the hundred and fifty pixels they
   left over. */
#sd-main[data-retouch="editor"] #sd-b-frame,
#sd-main[data-retouch] #sd-b-player,
#sd-main[data-retouch] .sd-dock,
#sd-main[data-retouch] #sd-formats,
#sd-main[data-retouch] #sd-custom,
#sd-main[data-retouch] #sd-full { display: none !important; }
#sd-main[data-retouch="preview"] #sd-rt-frame { display: none; }
.sd-left[inert] { opacity: .55; }
.sd-rt-back { display: inline-flex; align-items: center; gap: 6px; margin-left: 6px; padding: 7px 12px; border: 0; border-radius: 9px; background: transparent; color: var(--text); font: inherit; font-size: 13px; font-weight: 500; white-space: nowrap; cursor: pointer; }
.sd-rt-back svg { width: 16px; height: 16px; flex: 0 0 auto; }
.sd-rt-back:hover:not(:disabled) { background: var(--sd-field); }
.sd-rt-back:disabled { opacity: .5; cursor: default; }
.sd-rt-back[hidden], .sd-rt-title[hidden] { display: none; }
.sd-rt-title { display: inline-flex; align-items: center; gap: 8px; color: var(--text); font-size: 13px; font-weight: 600; }
.sd-rt-file { color: var(--muted); font-weight: 400; }
.sd-rt-file::before { content: '·'; margin-right: 8px; }
/* An icon beside a segment's word. */
.sd-seg button > svg { margin-right: 6px; vertical-align: -3px; }
.sd-b-compare { display: flex; justify-content: center; }
.sd-b-compare[hidden] { display: none; }
.sd-b-compare .sd-seg { width: min(320px, 90%); }
.sd-b-note { position: absolute; left: 50%; top: 14px; z-index: 40; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; padding: 9px 14px; border-radius: 12px; background: var(--panel); box-shadow: var(--sd-sh-pop); color: var(--text); font-size: 13px; white-space: nowrap; }
.sd-b-note[hidden] { display: none; }
.sd-b-note button { border: 0; background: none; color: var(--accent); font: inherit; font-weight: 600; cursor: pointer; }

/* The crop window. The rectangle and its four handles are `.sd-crop` / `.sd-crop-h`
   above — the picture tab's, unchanged — and this is the box they are positioned
   against. `overflow: hidden` is not decoration: the rectangle darkens everything
   outside itself with a 9999px shadow, which without a clip paints the whole page. */
.sd-crop-card { max-width: min(900px, 92vw); }
/* `width: fit-content` and no `object-fit`, and the two go together: the rectangle is
   placed in percentages of this box, so the box has to *be* the canvas's drawn area.
   Letterbox the picture inside a wider element and the overlay lines up with the
   element while the person is looking at the picture. */
.sd-cropbox { position: relative; overflow: hidden; width: fit-content; max-width: 100%; margin: 0 auto; border-radius: var(--sd-r-sm); line-height: 0; }
.sd-cropbox canvas { display: block; max-width: 100%; max-height: 62vh; }
.sd-b-scale { position: relative; }
.sd-b-stage { position: relative; overflow: hidden; transform-origin: 0 0; box-shadow: var(--sd-sh-pop); }
.sd-b-scrim { position: absolute; inset: 0; pointer-events: none; z-index: 2; }
.sd-b-layer { position: absolute; z-index: 5; cursor: move; }
/* Being typed on. The outline says the words are open rather than selected, and the
   text cursor says where a click will land — which on a layer whose normal cursor is
   «move» is the whole difference between «I can edit this» and «I can drag this». */
.sd-b-layer.sd-b-typing { cursor: text; outline: 2px solid var(--accent); outline-offset: 3px; z-index: 9; }
.sd-b-layer.sd-b-typing .sd-b-in { cursor: text; outline: none; }
.sd-b-layer.on { outline: 1.5px solid var(--accent); outline-offset: 2px; }
.sd-b-in { display: inline-block; white-space: pre-wrap; margin: 0; }
.sd-b-chip { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; line-height: 1.1; }
.sd-b-in img, .sd-b-in video { display: block; width: 100%; }
.sd-b-empty {
  display: flex; align-items: center; justify-content: center; min-width: 120px; min-height: 88px;
  border: 1px dashed var(--on-scrim); color: var(--on-scrim); font-size: 10.5px; background: rgba(255, 255, 255, .08);
}
/* The safe area and the guides: over the layers, under the pointer, never in a file.
   Their strokes are multiplied by `--sd-k`, the inverse of the stage's zoom, so a
   dashed line is a dashed line at 30% as well as at 100%. */
.sd-b-guides { position: absolute; inset: 0; z-index: 8; pointer-events: none; }
.sd-b-safe {
  position: absolute; border: calc(1.5px * var(--sd-k, 1)) dashed var(--accent);
  border-radius: calc(4px * var(--sd-k, 1));
  box-shadow: 0 0 0 9999px rgba(233, 30, 99, .06);
}
.sd-b-gl { position: absolute; display: block; background: transparent; }
.sd-b-gl-x { top: 0; bottom: 0; border-left: calc(1px * var(--sd-k, 1)) dashed rgba(59, 130, 246, .55); }
.sd-b-gl-y { left: 0; right: 0; border-top: calc(1px * var(--sd-k, 1)) dashed rgba(59, 130, 246, .55); }
.sd-b-gl.mid.sd-b-gl-x { border-left-style: solid; border-left-color: rgba(59, 130, 246, .7); }
.sd-b-gl.mid.sd-b-gl-y { border-top-style: solid; border-top-color: rgba(59, 130, 246, .7); }

/* What you grab, at the size you grab it. `--sd-k` is the inverse of the stage's
   own scale, set in `fit()`: everything inside the stage is shrunk by one transform,
   which is right for the design and wrong for its handles — a 1080 square fitted
   into this column draws at about a fifth, and a corner grip came out two pixels
   across. Multiplying by k undoes exactly that, and only for these. */
.sd-b-grip {
  position: absolute; z-index: 7; background: var(--accent);
  width: calc(10px * var(--sd-k, 1)); height: calc(10px * var(--sd-k, 1));
  border: calc(1.5px * var(--sd-k, 1)) solid var(--on-scrim);
  border-radius: calc(2px * var(--sd-k, 1));
}
.sd-b-grip[data-corner="nw"] { left: calc(-6px * var(--sd-k, 1)); top: calc(-6px * var(--sd-k, 1)); cursor: nwse-resize; }
.sd-b-grip[data-corner="ne"] { right: calc(-6px * var(--sd-k, 1)); top: calc(-6px * var(--sd-k, 1)); cursor: nesw-resize; }
.sd-b-grip[data-corner="sw"] { left: calc(-6px * var(--sd-k, 1)); bottom: calc(-6px * var(--sd-k, 1)); cursor: nesw-resize; }
.sd-b-grip[data-corner="se"] { right: calc(-6px * var(--sd-k, 1)); bottom: calc(-6px * var(--sd-k, 1)); cursor: nwse-resize; }
/* The angle, on the picture rather than in the column. **Below** the bottom edge:
   above it is where the floating toolbar sits, and the toolbar is `z-index: 20` —
   the first arrangement had them on top of each other, so every press meant for the
   handle went to the bar. The tether says which layer it belongs to. */
.sd-b-spin {
  position: absolute; left: 50%; transform: translateX(-50%); z-index: 7;
  bottom: calc(-30px * var(--sd-k, 1));
  width: calc(22px * var(--sd-k, 1)); height: calc(22px * var(--sd-k, 1));
  display: grid; place-items: center;
  border: calc(1.5px * var(--sd-k, 1)) solid var(--on-scrim); border-radius: 50%;
  background: var(--accent); color: var(--on-accent); cursor: grab;
}
.sd-b-spin svg { width: calc(12px * var(--sd-k, 1)); height: calc(12px * var(--sd-k, 1)); }
.sd-b-spin::after {
  content: ''; position: absolute; left: 50%; bottom: 100%;
  width: calc(1.5px * var(--sd-k, 1)); height: calc(8px * var(--sd-k, 1)); background: var(--accent);
}
.sd-b-spin:active { cursor: grabbing; }
.sd-b-dot { position: relative; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 50%; color: var(--on-scrim); box-shadow: 0 4px 14px -2px rgba(0, 0, 0, .5); }
.sd-b-card {
  position: absolute; left: 42px; top: 50%; transform: translateY(-50%); min-width: 118px;
  padding: 8px 11px; border-radius: var(--sd-r-sm); background: #fff; box-shadow: var(--sd-sh-pop);
  font-size: 11.5px; line-height: 1.3; color: #18181B;
}
.sd-b-card b { display: block; font-size: 12.5px; }
.sd-b-card-pic { display: block; width: 100%; max-height: 90px; object-fit: contain; margin-bottom: 6px; border-radius: 6px; background: #f4f4f6; }
.sd-b-card-buy { display: block; margin-top: 7px; padding: 6px 10px; border-radius: 999px; color: #fff; font-style: normal; font-size: 11.5px; font-weight: 600; text-align: center; }
.sd-b-card span { display: block; margin-top: 2px; color: #666; }

.sd-font { display: flex; flex-direction: column; gap: 5px; }
.sd-font-list { max-height: 196px; overflow-y: auto; border: 1px solid var(--sd-line); border-radius: var(--sd-r-sm); background: var(--field); padding: 3px; }
.sd-font-cat { margin: 6px 6px 2px; font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em; color: var(--muted); }
.sd-font-row { display: block; width: 100%; padding: 6px 8px; border: 0; border-radius: 6px; background: transparent; color: var(--text); font-size: 14px; text-align: left; cursor: pointer; }
.sd-font-row:hover { background: var(--sd-field); }
.sd-font-row.on { background: var(--accent-soft); color: var(--accent-ink); }

/* The loops, at rest. The exported banner carries the same declarations —
   `studio-banner.js` writes them — because a preview that animates differently from
   the file it previews is worse than no preview. The entrances are not here: the
   stage plays them through the Web Animations API, from the table the exported
   keyframes are held to, and nothing on this page drew them from CSS any more. */
@keyframes sd-b-pulse { 0%, 100% { transform: scale(1) } 50% { transform: scale(1.06) } }
@keyframes sd-b-float { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(-9px) } }
@keyframes sd-b-bob { 0%, 100% { transform: translateY(0) } 50% { transform: translateY(7px) } }
@keyframes sd-b-sway { 0%, 100% { transform: rotate(-3.5deg) } 50% { transform: rotate(3.5deg) } }
@keyframes sd-b-spin { from { transform: perspective(680px) rotateY(0) } to { transform: perspective(680px) rotateY(360deg) } }
@keyframes sd-b-rotate { from { transform: rotate(0) } to { transform: rotate(360deg) } }
@keyframes sd-b-shimmer { 0%, 100% { opacity: 1 } 50% { opacity: .55 } }
.sd-b-loop-pulse { animation: sd-b-pulse 2.4s ease-in-out infinite; }
.sd-b-loop-float { animation: sd-b-float 3s ease-in-out infinite; }
.sd-b-loop-bob { animation: sd-b-bob 2.6s ease-in-out infinite; }
.sd-b-loop-sway { animation: sd-b-sway 3.2s ease-in-out infinite; }
.sd-b-loop-spin { animation: sd-b-spin 3.6s linear infinite; }
.sd-b-loop-rotate { animation: sd-b-rotate 6s linear infinite; }
.sd-b-loop-shimmer { animation: sd-b-shimmer 2.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .sd-b-layer, .sd-b-in { animation: none !important; }
  .sd-swatch:hover { transform: none; }
}

@media (max-width: 1180px) {
  /* The inspector goes under the stage rather than beside it: below this width a
     306px column leaves the work narrower than the panel describing it.

     **Scoped to the view, like the two breakpoints above it**, and that is the fix:
     those are `.studio-view .sd-body` and outrank a bare `.sd-body`, so under 1180
     the three columns of the 1280 rule went on winning — every child stacked into
     the first track, 596px wide beside 256px of nothing, and the grid squeezed the
     stage's row under its own content until the stage lay over the inspector. */
  .studio-view .sd-body { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  /* One column, so the explicit tracks above have to be released — a child still
     asking for `grid-column: 3` in a one-track grid gets an implicit third column
     and the row goes back to being three screens wide. */
  .studio-view .sd-left, .studio-view .sd-main, .studio-view .sd-insp { grid-column: 1; }
  /* And so are the video editor's: one column, each child on a row it names — the
     picture, the timeline it is cut on under it, and the panel last. Children still
     asking for row 1 of a one-column grid would be drawn on top of each other. */
  .studio-view[data-mode="video"] .sd-body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; }
  .studio-view[data-mode="video"] .sd-main { grid-column: 1; grid-row: 1; }
  .studio-view[data-mode="video"] .sd-vdock { grid-column: 1; grid-row: 2; max-height: none; }
  .studio-view[data-mode="video"] .sd-vpanel { grid-column: 1; grid-row: 3; width: auto; height: min(560px, 75vh); }
  /* Folded, the panel is a row of its glyphs rather than a column of them. */
  .studio-view[data-mode="video"] .sd-vpanel[data-collapsed] { width: auto; height: auto; }
  .studio-view[data-mode="video"] .sd-vpanel[data-collapsed] .sd-vp-strip { flex-direction: row; padding: 8px 10px; }
  .studio-view[data-mode="video"] .sd-vpanel[data-collapsed] .sd-vp-unfold { margin: 0 6px 0 0; transform: rotate(-90deg); }
  /* Rows as tall as what is in them: the page scrolls, the stage does not shrink. */
  .studio-view .sd-main { min-height: auto; }
  /* The rail lies down across the top and its panel opens under it: six buttons
     standing in a strip 200px tall spilled over the stage's own toolbar. */
  .studio-view .sd-left { flex-direction: column; gap: 10px; }
  .studio-view .sd-rail { flex-direction: row; width: auto; overflow-x: auto; }
  .studio-view .sd-rail-b { flex: 0 0 auto; min-width: 78px; }
  .studio-view .sd-left-panel { width: auto; max-height: 320px; }
  /* A panel as wide as the screen fills its width with more cards, not bigger ones:
     two layouts four hundred pixels wide are two posters in a strip 320px tall. */
  .studio-view .sd-tpl-grid, .studio-view .sd-asset-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .studio-view .sd-ground-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
  .studio-view .sd-mo-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
  .studio-view { height: auto; }
  .studio-view .sd-stage, .studio-view[data-mode="video"] .sd-stage { min-height: 320px; }
  /* The cut's picture as tall as the column's width gives it room for, within reason: at
     320 a 16:9 frame was half the width of the column it sat in. */
  .studio-view[data-mode="video"] .sd-stage { min-height: clamp(320px, 42vw, 520px); }
}
/* And on a phone, no taller than a phone's picture needs: the 16:9 frame is as wide as the
   screen, and the room over and under it was empty. */
@media (max-width: 620px) {
  .studio-view[data-mode="video"] .sd-stage { min-height: clamp(240px, 64vw, 420px); }
}

/* ================= GENERATIONS, as the owner drew it =================
   Four drawings — by generation, by project, by content, the Studio's documents — and
   one frame around them: a title with its line, the one thing each view is for on the
   right, four tabs underlined rather than boxed, and each view in a single white card
   with its bar at the top — or, for the list and the files, on the page with no card
   round them. Everything here is scoped to the screen: the tab, the pill and the card
   are words other screens use for other drawings. */
/* The page's content runs as wide as every other's and is centred past it, with the
   scrollbar left at the screen's edge: the padding is what is left over, not a wrapper. */
.gens-view { display: block; padding-inline: max(0px, (100% - var(--page-max)) / 2); }

.gens-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin: 0 0 10px; }
/* The title with the list's count beside it, and the line under both. Every child names
   its column: the count and the two lines come and go with the tab, and a grid child
   that can disappear has to say where it goes or the others slide into its place. */
.gens-top-text { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 12px; }
.gens-top-text > .gens-eyebrow { grid-column: 1 / -1; }
.gens-top-text > h1 { grid-column: 1; }
.gens-top-text > .gens-total { grid-column: 2; justify-self: start; }
.gens-top-text > .gens-lead { grid-column: 1 / -1; }
/* How many the archive holds, «+» when the listing stopped at its cap. Empty until the
   list has been read, and then it takes no room at all. */
.gens-total {
  display: inline-flex; align-items: center; height: 32px; padding: 0 13px; border-radius: 99px;
  font-size: 15px; font-weight: 600; color: var(--ink); background: var(--panel-3); font-variant-numeric: tabular-nums;
}
.gens-total:empty { display: none; }
.gens-top-act { display: flex; gap: 8px; flex: none; }
.gens-cta {
  display: inline-flex; align-items: center; gap: 10px; height: 46px; padding: 0 22px; border-radius: 12px; font-size: 16px; font-weight: 700;
  box-shadow: 0 12px 26px -14px color-mix(in srgb, var(--accent) 80%, transparent);
}
.gens-cta .sd-ic { stroke-width: 2.2; }
.gens-cta[hidden] { display: none; }

#view-generations .gens-modes {
  display: flex; gap: 0 18px; margin: 4px 0 18px; padding: 0; overflow-x: auto; scrollbar-width: none;
  background: none; border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
}
#view-generations .gens-modes::-webkit-scrollbar { display: none; }
#view-generations .gens-modes .mode {
  flex: none; min-height: 46px; padding: 0 12px; cursor: pointer;
  font: inherit; font-size: 15.5px; font-weight: 600; color: var(--ink-2); white-space: nowrap;
  background: none; border: 0; border-radius: 0; box-shadow: inset 0 -3px 0 transparent;
  transition: color .13s, box-shadow .13s;
}
/* Wider than the strip — a phone, in Italian — the strip scrolls, and the edge with more
   beyond it fades: `gensStripEdges` in generations.js says which. */
#view-generations .gens-modes.more-after { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 40px), transparent); }
#view-generations .gens-modes.more-before { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 40px), transparent); }
#view-generations .gens-modes.more-before.more-after {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 40px, #000 calc(100% - 40px), transparent);
}
#view-generations .gens-modes .mode:hover { color: var(--ink); }
#view-generations .gens-modes .mode:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; border-radius: 8px; }
/* The tab on show in the ink, on the accent's line — the mockup's: the pink is the line
   that says where you are, not the word. */
#view-generations .gens-modes .mode.on { color: var(--ink); font-weight: 700; background: none; box-shadow: inset 0 -3px 0 var(--accent); }

#view-generations .gens-card { display: flex; flex-direction: column; min-height: 0; margin: 0 0 14px; padding: 10px 14px 12px; border-radius: 14px; }
/* `hidden` is an attribute and loses against a class declaring `display`: without
   this line the hidden panel stayed visible, and switching to "By content" looked
   like it did nothing because the listing went on sitting above it. */
#view-generations .gens-card[hidden] { display: none; }

.gens-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding: 0 0 10px; border-bottom: 1px solid var(--border); }
.gens-find { position: relative; display: flex; align-items: center; flex: 0 1 400px; min-width: 180px; margin: 0; }
.gens-find.wide { flex: 1 1 auto; }
.gens-find > .sd-ic { position: absolute; left: 11px; color: var(--muted); pointer-events: none; }
.gens-find .gens-search { width: 100%; height: 34px; margin: 0; padding: 0 12px 0 32px; border-radius: 8px; font-size: 13px; }
.gens-select { width: 168px; height: 34px; margin: 0; padding: 0 10px; border-radius: 8px; font-size: 13px; background: var(--panel); }
.gens-bar-end { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.gens-tally { font-size: 13px; color: var(--muted); }
.gens-trash, .gens-pick-mode {
  display: inline-flex; align-items: center; gap: 7px; height: 34px; padding: 0 12px;
  border-radius: 8px; background: var(--panel); font-size: 13px; color: var(--text);
}
.gens-trash b { font-weight: 500; }
.gens-trash.on, .gens-pick-mode.on { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent); }
.gens-views { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); }
.gens-view-b {
  display: grid; place-items: center; width: 32px; height: 28px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 0; border-radius: 6px;
}
.gens-view-b:hover { color: var(--ink); }
.gens-view-b.on { color: var(--accent-ink); background: var(--accent-soft); }

/* The selection bar: it appears only when something is selected, and it is the one
   thing on the page that changes the meaning of the controls next to it. */
.gens-bulk {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  margin-top: 12px; padding: 9px 12px;
  background: var(--accent-soft); border: 1px solid var(--accent); border-radius: 10px;
}
.gens-bulk[hidden] { display: none; }
.gens-bulk strong { font-size: 13px; color: var(--ink); margin-right: 4px; }
.gens-bulk .gens-select { width: auto; height: 30px; }

/* The objectives, as a row of pills with their counts. The dot takes the kind's own
   colour from `[data-kind]`, the same declaration the badge in the table reads, so the
   pill and the row it filters can never disagree; «All» has no kind and no dot. */
.gens-kinds { display: flex; flex-wrap: wrap; gap: 10px; margin: 16px 0 4px; }
.gens-kind-pill {
  display: inline-flex; align-items: center; gap: 9px; height: 40px; padding: 0 16px; cursor: pointer;
  font: inherit; font-size: 14.5px; font-weight: 500; color: var(--ink);
  background: var(--panel); border: 1px solid var(--border); border-radius: 99px;
  transition: border-color .13s, background .13s, color .13s;
}
/* A shelf is named, not drawn: the categories have no mark of their own, and «All» none. */
.gens-kind-pill b { font-size: 13.5px; font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; }
/* The favourites have a star where a kind has its dot, filled in the ink of a star that
   is on: 6.38:1 on the pill's white, 7.09:1 on the dark card. */
.gens-kind-pill > .sd-ic { flex: none; color: var(--accent-ink); fill: currentColor; }
.gens-kind-pill:hover { border-color: var(--k, var(--accent)); }
/* The pill chosen, filled in the ink with the ground's colour on it — the mockup's dark
   «All» — whichever it is, its icon and count in the same colour as its words. */
.gens-kind-pill.on { font-weight: 600; color: var(--panel); border-color: var(--ink); background: var(--ink); }
.gens-kind-pill.on b, .gens-kind-pill.on > svg { color: inherit; opacity: .85; }
/* The one kind left at zero is the one chosen: dimmed, and still the way back out. */
.gens-kind-pill.none { opacity: .45; }

.gens-warn { margin: 0 0 14px; padding: 10px 12px; border: 1px solid var(--danger-line); border-radius: 10px; }
.gens-warn[hidden] { display: none; }

/* ---- By generation: the owner's drawing (mockup 22) ----
   On the page, like the files beside it (`gens-flat`): the bar, the chips, one card per
   generation, the footer. A card is ≈116px: the newest file at 260×100; where it is filed
   above the title, its kind and what it made below; on the right when it was touched,
   the star and the «…», and the way in under them.

   A grid with named areas rather than a row of boxes, because three of a card's children
   come and go — the pill of a card to resume, the star outside the trash, the «done»
   badge — and a grid child that can disappear names its own track. The same areas stack
   up again for the tiles and for the phone. */
/* The drawn widths — 490 for the search, about 200 for each menu — as ceilings rather than
   bases. A wrapping row breaks on the bases, so with the drawn ones it broke at 1280 and
   sent the switch onto a line of its own; from these it keeps one line down to ~1000px. */
#view-generations .gens-list .gens-find { flex: 2 1 220px; max-width: 470px; }
.gens-list .gen-sel { flex: 1 1 190px; max-width: 245px; }
/* Grid or list: one control of two halves, at the end of the bar. Each half rounds its own
   outer corners rather than the group clipping them, which would clip the focus ring too. */
.gens-list .gens-views { margin-left: auto; gap: 0; padding: 0; border-radius: 12px; }
.gens-list .gens-view-b { width: 56px; height: 46px; border-radius: 11px 0 0 11px; color: var(--ink-2); }
.gens-list .gens-view-b + .gens-view-b { border-left: 1px solid var(--border); border-radius: 0 11px 11px 0; }
.gens-list .gens-view-b.on { color: var(--accent-ink); background: var(--accent-soft); }
.gens-list .gens-view-b:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.gens-table { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.gens-row {
  display: grid; align-items: center; column-gap: 20px; row-gap: 0;
  grid-template-columns: 260px minmax(0, 1fr) auto 184px;
  grid-template-areas: "shot body state side";
  position: relative; padding: 7px 18px 7px 14px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  transition: border-color .13s, box-shadow .13s;
}
.gens-row:hover { border-color: var(--accent-line); }
.gens-row.picked { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* Waiting for somebody — open in the conversation, or with a generation still running:
   the card washed in the accent over its own ground, edged in the accent's line. What is
   written on the wash, measured on it (light · dark): the title 15.39 · 13.28, the
   project and the time in --muted 5.25 · 6.30, the counts 15.39 · 12.48, a star that is
   on 5.48 · 5.95 — and the pill, the same wash once more under --accent-ink, 4.77 · 4.77. */
.gens-row.todo { background: linear-gradient(var(--accent-soft), var(--accent-soft)), var(--panel); border-color: var(--accent-line); }
/* And marked down its left edge in the accent, as the mockup draws the one card waiting:
   out of the grid's flow, so it takes no track. */
.gens-row.todo::before {
  content: ''; position: absolute; left: -1px; top: 14px; bottom: 14px; width: 4px;
  border-radius: 0 4px 4px 0; background: var(--accent); pointer-events: none;
}

/* The preview: the last file produced. A title is read, a frame is recognised — and
   in a list of thirty jobs that is the difference between scrolling and finding. When
   there is nothing yet the goal's icon remains, which says "it has produced no files
   yet" instead of looking like a broken image. Out of flow, so the frame keeps its size
   whatever shape the file is. */
.gens-thumb {
  grid-area: shot; position: relative; display: grid; place-items: center;
  width: 260px; height: 100px; overflow: hidden; cursor: pointer;
  background: var(--panel-2); border-radius: 10px;
}
.gens-thumb img, .gens-thumb video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.gens-thumb video { background: #0f1119; }
.gens-thumb.empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  color: var(--k, var(--muted)); background: color-mix(in srgb, var(--k, var(--muted)) 10%, var(--panel-2));
}
.gens-thumb.empty .kind-ic { background: transparent; }
/* «No preview» under the job's icon, in the muted ink: what is missing, said. */
.gens-thumb-none { font-size: 14px; color: var(--muted); }
/* The box that selects, on the picture where a tile's box is. It waits for the pointer
   or the keyboard, is on every card once anything is selected, and is always there
   where nothing can hover (the `hover: none` line after it). Its 34px reach is the
   `.gens-row input[type="checkbox"]` rule near the top of the sheet, which also sets a
   `position` — this selector is as specific and later, so the box stays on the picture. */
.gens-thumb > input.gens-check {
  position: absolute; top: 9px; left: 9px; z-index: 2; width: 18px; height: 18px; margin: 0;
  accent-color: var(--accent); cursor: pointer; opacity: 0; transition: opacity .12s;
}
.gens-row:hover .gens-thumb > input.gens-check,
.gens-row:focus-within .gens-thumb > input.gens-check,
.gens-table.picking .gens-thumb > input.gens-check { opacity: 1; }
@media (hover: none) { .gens-thumb > input.gens-check { opacity: 1; } }
/* A clip's length on its cover, bottom left, on the scrim every badge over a picture
   wears: the picture did not change with the theme, so neither does the badge. */
.gens-clip {
  position: absolute; left: 7px; bottom: 7px; z-index: 1; display: inline-flex; align-items: center; gap: 6px;
  height: 26px; padding: 0 9px 0 8px; border-radius: 7px; pointer-events: none;
  font-size: 12.5px; font-weight: 600; color: var(--on-scrim); background: var(--scrim-strong); font-variant-numeric: tabular-nums;
}
.gens-clip > .sd-ic { flex: none; }

.gens-body { grid-area: body; display: flex; flex-direction: column; align-items: flex-start; gap: 7px; min-width: 0; }
.gens-where { display: inline-flex; align-items: center; gap: 7px; max-width: 100%; font-size: 13px; line-height: 1.3; color: var(--muted); }
.gens-where > .sd-ic { flex: none; }
.gens-where > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gens-name { display: flex; align-items: center; gap: 10px; max-width: 100%; min-width: 0; }
.gens-open {
  min-width: 0; padding: 0; cursor: pointer; text-align: left;
  font: inherit; font-size: 20px; font-weight: 800; line-height: 1.3; letter-spacing: -.02em; color: var(--ink);
  background: none; border: 0;
}
.gens-open strong { display: block; font-weight: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gens-open:hover strong { color: var(--accent-ink); }
.gens-done {
  flex: none; padding: 1px 7px; border-radius: 999px;
  font-size: 11px; color: var(--ok); background: var(--ok-soft); border: 1px solid var(--ok-line);
}
/* The kind as a pill in its own colour, then — past a short rule — what it made. */
.gens-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 14px; min-width: 0; }
.gens-meta .kind-badge {
  gap: 6px; height: 30px; padding: 0 11px 0 8px; border-radius: 8px;
  background: color-mix(in srgb, var(--k) 9%, var(--panel));
}
/* As specific as the dark theme's `.kind-ic` wash and later, so the icon sits on the
   badge's own tint in both themes rather than on a second disc in one of them. */
.gens-meta .kind-badge .kind-ic { width: 1.3em; height: 1.3em; background: none; }
.gens-meta .kind-lb { font-size: 13px; font-weight: 500; white-space: nowrap; }
.gens-made { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text); white-space: nowrap; }
.gens-made::before { content: ''; flex: none; width: 1px; height: 16px; margin-right: 6px; background: var(--border); }
/* «2 images · 1 video»: a dot between what it made, as the mockup writes it. */
.gens-made > span + span::before { content: '·'; margin-right: 1px; color: var(--muted); font-weight: 700; }
.gens-made > span { display: inline-flex; align-items: center; gap: 7px; }
.gens-made .sd-ic { flex: none; color: var(--ink-2); }
.gens-made.none { color: var(--muted); }

/* «● To resume», in its own column, level with the title's line rather than the card's
   middle, as drawn. */
.gens-state {
  grid-area: state; align-self: start; margin-top: 22px;
  display: inline-flex; align-items: center; gap: 8px; height: 30px; padding: 0 14px 0 12px; border-radius: 99px;
  font-size: 13px; font-weight: 500; color: var(--accent-ink); background: var(--accent-soft); white-space: nowrap;
}
.gens-state::before { content: ''; flex: none; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* When, the star and the «…» on one line, the way in under them. The time keeps its
   column, so on a page of cards it starts at the same place on every one. */
.gens-side {
  grid-area: side; display: grid; align-items: center; column-gap: 2px; row-gap: 12px;
  grid-template-columns: minmax(0, 1fr) auto auto auto; grid-template-areas: "time star bin dots" "go go go go";
}
/* «Delete» beside the «⋯»: quiet at rest, red on the pointer. */
.gens-bin {
  grid-area: bin; display: grid; place-items: center; width: 30px; height: 30px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 0; border-radius: 7px; transition: color .12s, background-color .12s;
}
.gens-bin:hover { color: var(--danger-ink); background: var(--danger-soft); }
.gens-bin:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.gens-time { grid-area: time; min-width: 0; font-size: 13.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-variant-numeric: tabular-nums; }
/* At rest only on a favourite: a page of empty stars reads as a page of things undone.
   Faded rather than removed, so the time does not move when the pointer arrives. */
.gens-star {
  grid-area: star; display: grid; place-items: center; width: 30px; height: 30px; padding: 0; cursor: pointer;
  color: var(--muted); background: none; border: 0; border-radius: 7px; opacity: 0; transition: opacity .12s, color .12s;
}
.gens-star:hover { color: var(--ink); background: var(--panel-2); }
.gens-star.on { opacity: 1; color: var(--accent-ink); }
.gens-star.on .sd-ic { fill: currentColor; }
.gens-row:hover .gens-star, .gens-row:focus-within .gens-star { opacity: 1; }
@media (hover: none) { .gens-star { opacity: 1; } }
.gens-side > .gens-dots { grid-area: dots; width: 30px; height: 30px; }
/* «Open →» on the card's own ground, «Resume →» filled (`.btn.accent` carries the fill
   and its ink), «Restore» in the trash. */
.gens-go {
  grid-area: go; justify-self: end; display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  height: 40px; padding: 0 16px 0 20px; border-radius: 9px; font-size: 14.5px; font-weight: 500;
  color: var(--ink); background: var(--panel); box-shadow: var(--shadow-1);
}
.gens-go.accent { font-weight: 600; box-shadow: none; }
.gens-go > .sd-ic { flex: none; }

.gens-dots {
  display: grid; place-items: center; width: 28px; height: 26px; padding: 0; cursor: pointer;
  color: var(--ink); background: none; border: 0; border-radius: 6px;
}
.gens-dots:hover, .gens-dots[aria-expanded="true"] { background: var(--panel-2); }
.gens-empty { padding: 22px 6px; }

/* ---- The same cards as tiles: the grid, twelve to a page ----
   The side goes to the foot of the tile, so the buttons of a row of tiles line up even
   when one of them carries the pill and the others do not. */
.gens-table[data-as="grid"] { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); gap: 14px; }
.gens-table[data-as="grid"] > .gens-empty { grid-column: 1 / -1; }
.gens-table[data-as="grid"] .gens-row {
  grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto 1fr;
  grid-template-areas: "shot" "body" "state" "side";
  align-items: start; row-gap: 12px; padding: 10px 10px 12px;
}
.gens-table[data-as="grid"] .gens-thumb { width: 100%; height: auto; aspect-ratio: 16 / 9; }
.gens-table[data-as="grid"] .gens-body { padding: 0 2px; }
.gens-table[data-as="grid"] .gens-open { font-size: 15.5px; }
.gens-table[data-as="grid"] .gens-state { justify-self: start; margin: 0; }
.gens-table[data-as="grid"] .gens-side { align-self: end; padding: 0 2px; }
.gens-table[data-as="grid"] .gens-go { justify-self: stretch; }

/* ---- The foot: «1–5 of 100 generations», the pages, and the trash past a rule ----
   It stays when there is nothing to page through: the trash is still the way in. */
.gens-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 14px; margin-top: 18px; }
.gens-foot > .gens-pager { flex: 1 1 auto; min-width: 0; }
.gens-foot-end { display: flex; align-items: center; gap: 8px; margin-left: auto; padding-left: 14px; border-left: 1px solid var(--border); }
.gens-foot .gens-trash { height: 40px; padding: 0 16px; border-radius: 10px; }
.gens-pager { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; }
.gens-range { font-size: 13px; color: var(--muted); }
.gens-pages { display: flex; align-items: center; gap: 8px; }
.gens-page {
  display: grid; place-items: center; min-width: 38px; height: 38px; padding: 0 10px; cursor: pointer;
  font: inherit; font-size: 14px; color: var(--text); background: var(--panel-2); border: 1px solid transparent; border-radius: 10px;
}
.gens-page:hover { border-color: var(--border); }
.gens-page.on { color: var(--on-accent); background: var(--accent); font-weight: 600; }
.gens-page.gens-step { background: var(--panel); border-color: var(--border); }
.gens-gap { padding: 0 2px; color: var(--muted); }

/* Where we are: the line that appears when the listing is no longer the whole
   archive but a folder's contents. Without it, "three generations" looks like
   everything there is instead of everything there is in here. */
.gens-crumb { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; margin: 12px 0 0; font-size: 13px; color: var(--ink); }
.gens-crumb[hidden] { display: none; }
.crumb-back { padding: 0; cursor: pointer; font: inherit; font-size: 13px; color: var(--ink-2); background: none; border: 0; }
.crumb-back:hover { color: var(--accent-ink); }
.crumb-back::after { content: ' /'; color: var(--muted); }
.crumb-specs { flex: 1; min-width: 0; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Projects ----
   A list by default, as the drawing has it: the cover, the name, what it is for and
   the channels its generations were made for, then the counts. The same parts as cards
   in the grid. */
.folder-list[data-as="list"] { margin-top: 14px; border: 1px solid var(--border); border-radius: 12px; }
.folder-row {
  display: grid; align-items: center; gap: 16px;
  grid-template-columns: minmax(0, 1fr) 110px 110px 130px 40px;
  padding: 8px 14px; border-bottom: 1px solid var(--border);
}
.folder-row:last-child { border-bottom: 0; }
.folder-head { padding: 10px 14px; font-size: 12px; color: var(--muted); }
.folder-row .folder-num, .folder-row .folder-when { text-align: center; font-size: 13px; color: var(--text); font-variant-numeric: tabular-nums; }
.folder-head .folder-num, .folder-head .folder-when { font-size: 12px; }
.folder-acts { display: flex; justify-content: flex-end; }
.folder-open {
  display: flex; align-items: center; gap: 16px; width: 100%; min-width: 0; padding: 0; cursor: pointer;
  text-align: left; background: none; border: 0; font: inherit; color: var(--text);
}
.folder-cover {
  position: relative; flex: none; width: 112px; height: 72px; border-radius: 7px; overflow: hidden;
  display: grid; place-items: center; color: var(--muted); background: var(--panel-2);
}
.folder-cover img, .folder-cover video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.folder-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.folder-name { font-size: 14.5px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folder-open:hover .folder-name { color: var(--accent-ink); }
.folder-about { font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.folder-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 3px; }
.folder-tag { padding: 2px 9px; border-radius: 6px; font-size: 11.5px; color: var(--c, var(--ink-2)); background: color-mix(in srgb, var(--c, var(--ink-2)) 10%, var(--panel)); }
.folder-tag[data-channel="instagram"] { --c: #b8135e; }
.folder-tag[data-channel="meta"] { --c: #1f56c4; }
.folder-tag[data-channel="youtube"] { --c: #c41a1a; }
.folder-tag[data-channel="tiktok"] { --c: var(--ink); }
.folder-tag[data-channel="google"] { --c: #6d4fd6; }
.folder-tag[data-channel="native"] { --c: #0f7f72; }
.folder-tag[data-channel="email"] { --c: #0b6b49; }
:root[data-theme="dark"] .folder-tag[data-channel="instagram"] { --c: #ff74ae; }
:root[data-theme="dark"] .folder-tag[data-channel="meta"] { --c: #7bb4ee; }
:root[data-theme="dark"] .folder-tag[data-channel="youtube"] { --c: #ff8f8f; }
:root[data-theme="dark"] .folder-tag[data-channel="google"] { --c: #a894ff; }
:root[data-theme="dark"] .folder-tag[data-channel="native"] { --c: #5fd4cf; }
:root[data-theme="dark"] .folder-tag[data-channel="email"] { --c: #4ade80; }
.folder-facts { font-size: 12px; color: var(--muted); }

.folder-list[data-as="grid"] { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); gap: 14px; margin-top: 12px; }
.folder-card { position: relative; min-width: 0; padding: 10px; background: var(--panel); border: 1px solid var(--border); border-radius: 14px; }
.folder-card:hover { border-color: var(--accent-line); }
.folder-card .folder-open { flex-direction: column; align-items: stretch; gap: 10px; }
.folder-card .folder-cover { width: 100%; height: auto; aspect-ratio: 16 / 10; }
.folder-card .folder-name { font-size: 14px; }
.folder-card .folder-about { font-size: 12px; }
.folder-card .folder-tag { padding: 2px 8px; font-size: 11px; }
.folder-card .gens-dots { position: absolute; top: 16px; right: 16px; background: var(--panel); box-shadow: var(--shadow-1); }

/* The generations in no project: not a row among the projects, a card under them. */
#view-generations .folder-loose { flex-direction: row; align-items: center; gap: 16px; padding: 12px 14px; }
.folder-loose-ic { display: grid; place-items: center; flex: none; width: 44px; height: 44px; color: var(--ink); border: 1px solid var(--border); border-radius: 12px; }
.folder-loose-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.folder-loose-text strong { font-size: 14.5px; font-weight: 600; color: var(--ink); }
.folder-loose-text span { font-size: 13px; color: var(--muted); }
.folder-loose-text small { font-size: 11.5px; color: var(--muted); }
.folder-loose-go { display: inline-flex; align-items: center; gap: 8px; flex: none; height: 34px; padding: 0 16px; border-radius: 8px; background: var(--panel); font-size: 13px; }

/* ---- Content: every file, in its own proportions ----
   The owner's third drawing: no card round this view — the bar, the pills and the
   pictures sit on the page — and pictures big enough to recognise, five tall ones to a
   row at a laptop's width, each with what it is and its shape on it, and under it its
   name, its project and when.

   Justified rows, the way a photo library lays them out: every frame in a row at one
   height, every frame as wide as its file's proportions make it at that height, and the
   row as wide as the view. A 9:16 clip stands in a tall narrow frame and a wider file in
   a wider one, held to 4:5 at most so one landscape banner does not break the wall of
   five (`frameRatio` in gallery.js); the badge still says its real shape. `--r` is the frame's ratio,
   written onto the tile by `gallery.js` once the file has said what it is; the rows
   themselves are laid out there too (`justify`), each frame's `flex` written from the
   width there is, because a row in flexbox can only grow to fill, never take one frame
   more and shrink. The `flex` below is only what a frame stands on before that. */
#view-generations .gens-flat { padding: 0; background: none; border: 0; border-radius: 0; box-shadow: none; }
.gens-flat .gens-bar { gap: 8px; padding: 0; border-bottom: 0; }
/* A third of the row, as drawn, so the gap before «Select» is the drawing's too. */
.gens-flat .gens-find { flex: 0 1 390px; }
.gens-flat .gens-find > .sd-ic { left: 14px; color: var(--ink); stroke-width: 2.2; }
.gens-flat .gens-find .gens-search {
  height: 48px; padding: 0 16px 0 44px; border-radius: 12px; font-size: 14.5px;
  background: var(--panel); border-color: var(--border);
}
.gen-sel { position: relative; display: flex; align-items: center; flex: 0 1 172px; min-width: 0; }
.gen-sel > .sd-ic { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: var(--ink); stroke-width: 2; pointer-events: none; }
.gen-sel > .gens-select {
  -webkit-appearance: none; appearance: none; width: 100%; height: 48px; padding: 0 40px 0 16px; cursor: pointer;
  border-radius: 12px; font-size: 14.5px; font-weight: 600; color: var(--ink); background: var(--panel);
}
/* A menu that opens with what it is about: the folder before the projects, the arrows
   before the order. */
.gen-sel > .gens-sel-ic { right: auto; left: 16px; color: var(--ink-2); stroke-width: 1.8; }
.gens-sel-lead > .gens-select { padding-left: 48px; }
.gens-flat .gens-pick-mode { height: 48px; padding: 0 16px; border-radius: 12px; font-size: 14.5px; font-weight: 500; color: var(--ink); }
.gens-flat .gens-bulk { margin-top: 14px; }

.gen-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin: 11px 0 0; }
#view-generations .gen-bar .chip {
  display: inline-flex; align-items: center; gap: 7px; height: 35px; padding: 0 12px 0 13px; cursor: pointer;
  font-size: 13.5px; font-weight: 500; color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 99px;
}
#view-generations .gen-bar .chip .sd-ic { color: var(--k, var(--muted)); stroke-width: 2; }
#view-generations .gen-bar .chip b {
  min-width: 20px; margin-left: -1px; padding: 1px 5px; border-radius: 6px; text-align: center;
  font-size: 12px; font-weight: 600; color: var(--muted); background: var(--panel-2); font-variant-numeric: tabular-nums;
}
#view-generations .gen-bar .chip.on { font-weight: 600; color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent); }
#view-generations .gen-bar .chip.on b { color: inherit; background: none; }

.gen-grid { display: flex; flex-wrap: wrap; gap: 22px 14px; margin-top: 12px; }
.gen-grid > .hint { flex: 1 1 100%; }
/* A container, so a caption can tell how narrow its own tile is (the `@container` below). */
.gen { position: relative; flex: 0 0 calc(var(--r, .8) * 300px); min-width: 0; margin: 0; container-type: inline-size; }
.gen-media { position: relative; aspect-ratio: var(--r, .8); border-radius: 12px; overflow: hidden; background: var(--panel-2); }
/* Out of flow, so the frame keeps the ratio it was given whatever the file asks for. */
.gen-media img, .gen-media video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.gen-media img { cursor: zoom-in; }
.gen-media video { background: #0f1119; }
/* A frame is cropped to 4:5 at the widest; a clip playing is shown whole, on black. */
.gen.playing .gen-media video { object-fit: contain; }
.gen-grid.selecting .gen-media img { cursor: pointer; }
.gen.picked .gen-media { box-shadow: 0 0 0 3px var(--accent); }
.gen-current .gen-media { box-shadow: 0 0 0 1px var(--accent-line); }
.gen-gone {
  position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--muted); font-size: 12px; border: 1px dashed var(--border); border-radius: 12px;
}
/* ---------- a generation's window, as the owner's mockups draw it (2026-10-18) ----------
   What a tile of «By content» opens (`app/js/gen-detail.js`): the head with the kind, the
   name, «3 of 13» and the arrows; the preview on the left — narrow beside a portrait file,
   wide beside a landscape one (`.gd-wide`) — and the facts and the download on the right. */
.gd.bk-modal[hidden] { display: none; }
.gd-card { width: min(1000px, 100%); padding: 0; border-radius: 20px; overflow: hidden auto; }
.gd-card.gd-wide { width: min(1180px, 100%); }
.gd-head { display: flex; align-items: center; gap: 18px; padding: 22px 26px; border-bottom: 1px solid var(--border); }
.gd-kind { flex: none; display: grid; place-items: center; width: 56px; height: 56px; border-radius: 14px; color: var(--accent); background: var(--accent-soft); }
.gd-words { flex: 1 1 auto; min-width: 0; }
.gd-title { margin: 0; font-size: 24px; font-weight: 800; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gd-sub { margin: 4px 0 0; font-size: 15px; color: var(--muted); }
.gd-nav { flex: none; display: flex; align-items: center; gap: 6px; }
.gd-count { margin-right: 10px; font-size: 15px; color: var(--muted); white-space: nowrap; }
.gd-arrow, .gd-x { display: grid; place-items: center; width: 40px; height: 40px; padding: 0; cursor: pointer; color: var(--ink); background: transparent; border: 0; border-radius: 10px; }
.gd-arrow:hover:not(:disabled), .gd-x:hover { background: var(--panel-2); }
.gd-arrow:disabled { color: var(--muted); opacity: .45; cursor: default; }
.gd-x { width: 44px; height: 44px; background: var(--panel-2); }
.gd-rule { width: 1px; height: 28px; margin: 0 8px; background: var(--border); }
.gd-body { display: grid; grid-template-columns: auto minmax(0, 1fr); }
.gd-wide .gd-body { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
.gd-stage { grid-column: 1; min-width: 0; display: flex; flex-direction: column; border-right: 1px solid var(--border); }
.gd-wide .gd-stage { justify-content: center; gap: 12px; padding: 28px; }
/* The frame has the file's own shape (`--gd-r`, its width over its height, set from the file
   once it loads), so no black band shows at its sides: as large as 420px wide and 64vh tall
   allow beside a portrait file — the column is that wide, and the bar under it does not
   widen it — and as wide as the column beside a landscape one, in its middle. */
.gd-frame {
  position: relative; display: grid; place-items: center; align-self: center; flex: none;
  width: min(420px, calc(64vh * var(--gd-r, .5625))); max-width: 100%; aspect-ratio: var(--gd-r, .5625);
  background: #0e0e12; overflow: hidden;
}
.gd-wide .gd-frame { width: min(100%, calc(64vh * var(--gd-r, 1.7778))); border-radius: 14px; }
/* A heavy version, shown by the picture it was made from: its own size, bottom left. */
.gd-heavy {
  position: absolute; left: 10px; bottom: 10px; z-index: 2; pointer-events: none;
  padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 700; color: #fff; background: rgba(15, 17, 40, .72);
}
.gd-frame-plain { width: 420px; aspect-ratio: auto; min-height: 260px; }
.gd-media { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; }
.gd-sound-plate { display: grid; justify-items: center; gap: 12px; padding: 60px 20px; color: #fff; font-size: 15px; text-align: center; }
.gd-gone { margin: 0; padding: 60px 20px; color: #fff; }
.gd-badge {
  position: absolute; top: 16px; display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px;
  font-size: 14px; font-weight: 600; color: #111; background: #fff; border-radius: 9px; box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
}
.gd-badge-kind { left: 16px; }
.gd-ratio { right: 16px; }
.gd-badge[hidden] { display: none; }
.gd-big-play {
  position: absolute; top: 50%; left: 50%; width: 84px; height: 84px; margin: -42px 0 0 -42px; display: grid; place-items: center;
  padding: 0; cursor: pointer; color: #111; background: #fff; border: 0; border-radius: 50%; box-shadow: 0 6px 24px rgba(0, 0, 0, .25);
}
.gd-big-play[hidden] { display: none; }
.gd-fullscreen {
  position: absolute; right: 16px; bottom: 16px; display: grid; place-items: center; width: 40px; height: 40px; padding: 0;
  cursor: pointer; color: #111; background: #fff; border: 0; border-radius: 10px; box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
}
.gd-fullscreen:hover { background: #ececf1; }
.gd-bar { display: flex; align-items: center; gap: 12px; padding: 14px 20px; contain: inline-size; }
.gd-wide .gd-bar { padding: 0; }
.gd-bar-play, .gd-sound { flex: none; display: grid; place-items: center; width: 34px; height: 34px; padding: 0; cursor: pointer; color: var(--ink); background: transparent; border: 0; border-radius: 8px; }
.gd-bar-play:hover, .gd-sound:hover { background: var(--panel-2); }
.gd-seek { flex: 1 1 auto; min-width: 0; accent-color: var(--accent); }
.gd-clock { flex: none; font-size: 14px; color: var(--muted); font-variant-numeric: tabular-nums; }
.gd-res { flex: none; padding: 2px 8px; font-size: 13px; color: var(--accent-ink); background: var(--accent-soft); border-radius: 6px; }
.gd-res[hidden] { display: none; }
.gd-full { margin: 0; font-size: 14px; color: var(--muted); }
.gd-card:not(.gd-wide) .gd-full, .gd-full:empty { display: none; }
/* On the whole screen: the file as large as the screen holds it, the clip's bar under it. */
.gd-stage:fullscreen { width: 100vw; height: 100vh; padding: 0; gap: 0; justify-content: flex-start; background: #0e0e12; border: 0; }
.gd-stage:fullscreen .gd-frame { flex: 1 1 auto; align-self: stretch; width: auto; max-width: none; aspect-ratio: auto; min-height: 0; border-radius: 0; }
.gd-stage:fullscreen .gd-bar { padding: 14px 20px; background: var(--panel); }
.gd-stage:fullscreen .gd-full { display: none; }
.gd-side { grid-column: 2; min-width: 0; display: flex; flex-direction: column; }
.gd-info { flex: 1 1 auto; padding: 26px 30px 8px; }
.gd-info > * + * { border-top: 1px solid var(--border); }
.gd-prompt { padding-bottom: 20px; }
.gd-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.gd-sec-title { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.gd-copy, .gd-more { display: inline-flex; align-items: center; gap: 8px; padding: 4px 6px; cursor: pointer; font: inherit; font-size: 15px; background: transparent; border: 0; border-radius: 8px; }
.gd-copy { color: var(--muted); }
.gd-copy:hover { color: var(--ink); background: var(--panel-2); }
.gd-more { margin-top: 8px; padding: 0; color: var(--accent-ink); font-weight: 600; }
.gd-prompt-text { margin: 0; font-size: 16px; line-height: 1.65; color: var(--text); white-space: pre-line; overflow-wrap: anywhere; }
.gd-prompt-text.folded { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.gd-model { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 18px 0; }
.gd-model-label { font-size: 16px; color: var(--muted); }
.gd-model-name { display: inline-flex; align-items: center; gap: 8px; font-size: 17px; font-weight: 700; color: var(--ink); }
.gd-model-name > svg { color: var(--accent); }
.gd-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px 24px; padding: 20px 0; }
.gd-cell { display: flex; align-items: flex-start; gap: 14px; min-width: 0; }
.gd-cell > svg { flex: none; margin-top: 2px; color: var(--muted); }
.gd-cell-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.gd-cell-label { font-size: 14px; color: var(--muted); }
.gd-cell-value { font-size: 17px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.gd-by { margin: 0; padding: 12px 0 0; font-size: 14px; color: var(--muted); }
.gen-by { margin: 0; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gd-filed { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 0; }
.gd-folder { display: inline-flex; align-items: center; gap: 10px; min-width: 0; font-size: 15px; color: var(--muted); }
.gd-done { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--ok); }
.gd-done::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.gd-acts { padding: 18px 30px 22px; border-top: 1px solid var(--border); }
.gd-download {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; min-height: 54px;
  font-size: 16px; font-weight: 700; color: #fff; background: var(--accent); border: 1px solid var(--accent); border-radius: 12px;
}
.gd-download:disabled { opacity: .5; cursor: default; }
/* The star beside the download, square to its height. */
.gd-act-row { display: flex; gap: 10px; }
/* «Improve quality», under the download: the same height, outlined, the whole width. */
.gd-enhance {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px; margin-top: 10px;
  font-weight: 600; color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 12px; cursor: pointer;
}
.gd-enhance:hover { border-color: var(--accent); color: var(--accent-ink); }
.gd-enhance:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gd-act-row .gd-download { flex: 1 1 auto; width: auto; }
.gd-star {
  flex: none; display: grid; place-items: center; width: 54px; min-height: 54px; padding: 0;
  color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 12px; cursor: pointer;
}
.gd-star:hover { background: var(--panel-2); }
.gd-star[aria-pressed="true"] { color: var(--accent-ink); border-color: var(--accent-line); }
.gd-star[aria-pressed="true"] .sd-ic { fill: currentColor; }
/* «Delete» after the download: the same square as the star, red on the pointer. */
.gd-del {
  flex: none; display: grid; place-items: center; width: 54px; min-height: 54px; padding: 0;
  color: var(--muted); background: var(--panel); border: 1px solid var(--border); border-radius: 12px; cursor: pointer;
}
.gd-del:hover { color: var(--danger-ink); background: var(--danger-soft); border-color: var(--danger-ink); }
.gd-format { margin: 12px 0 0; font-size: 13.5px; color: var(--muted); text-align: center; }
@media (max-width: 860px) {
  .gd-body, .gd-wide .gd-body { grid-template-columns: minmax(0, 1fr); }
  .gd-stage { border-right: 0; border-bottom: 1px solid var(--border); }
  .gd-side { grid-column: 1; }
  .gd-head { flex-wrap: wrap; padding: 16px; }
  .gd-info { padding: 20px 18px 8px; }
  .gd-acts { padding: 16px 18px 18px; }
}

/* A sound's tile: the note it was made as, over the panel, where a picture would be; the
   player's bar takes the foot of the frame once it plays. */
.gen-sound {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; padding: 18px 16px 64px; color: var(--accent); text-align: center;
  background: linear-gradient(160deg, var(--accent-soft, var(--panel-2)), var(--panel-2));
}
.gen-sound > span {
  max-width: 100%; color: var(--ink); font-size: 13.5px; font-weight: 600; line-height: 1.3;
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.gen-media audio { position: absolute; left: 10px; right: 10px; bottom: 10px; width: calc(100% - 20px); }
.gen-media audio:not([controls]) { display: none; }
.gen-audio .gen-play { top: 42%; }
/* The box is a control of «Select», and only there. */
.gen-pick { display: none; position: absolute; top: 10px; left: 10px; z-index: 2; width: 18px; height: 18px; margin: 0; accent-color: var(--accent); cursor: pointer; }
.gen-grid.selecting .gen-pick { display: block; }
/* At rest the «…» waits for the pointer, the keyboard or «Select»; where there is no
   pointer to hover with it is always there (the `hover: none` line just below). */
.gen-more {
  position: absolute; top: 8px; right: 8px; z-index: 2; display: grid; place-items: center;
  width: 30px; height: 30px; padding: 0; cursor: pointer;
  color: var(--ink); background: var(--panel); border: 0; border-radius: 8px; box-shadow: var(--shadow-1);
  opacity: 0; transition: opacity .12s;
}
.gen:hover .gen-more, .gen:focus-within .gen-more, .gen-grid.selecting .gen-more { opacity: 1; }
/* Here and not in the shared `hover: none` block above: that block comes earlier in the
   file, and the `opacity: 0` just written would win over it. */
@media (hover: none) { .gen-more { opacity: 1; } }
/* The star, left of the «…»: at rest only on a favourite, as a generation's star is, and with
   the «…» on the pointer, on focus, and always where there is no pointer to hover with. */
.gen-star {
  position: absolute; top: 8px; right: 44px; z-index: 2; display: grid; place-items: center;
  width: 30px; height: 30px; padding: 0; cursor: pointer;
  color: var(--ink); background: var(--panel); border: 0; border-radius: 8px; box-shadow: var(--shadow-1);
  opacity: 0; transition: opacity .12s;
}
.gen-star .sd-ic { stroke-width: 2; }
.gen-star[aria-pressed="true"] { opacity: 1; color: var(--accent-ink); }
.gen-star[aria-pressed="true"] .sd-ic { fill: currentColor; }
.gen:hover .gen-star, .gen:focus-within .gen-star { opacity: 1; }
.gen-star:focus-visible { opacity: 1; outline: 2px solid var(--accent); outline-offset: 1px; }
@media (hover: none) { .gen-star { opacity: 1; } }
/* A file that lives only on Ark, and how long it has left there: top left, and under
   the box once «Select» puts one there. */
.gen-temp {
  position: absolute; top: 10px; left: 10px; z-index: 2; display: inline-flex; align-items: center; gap: 4px;
  max-width: calc(100% - 56px); padding: 3px 8px; border-radius: 7px; overflow: hidden; white-space: nowrap;
  font-size: 11.5px; font-weight: 500; color: var(--warn);
  background: var(--panel); box-shadow: inset 0 0 0 99px var(--warn-line), var(--shadow-1);
}
.gen-grid.selecting .gen-temp { top: 38px; }
.gen-temp > span { overflow: hidden; text-overflow: ellipsis; }
.gen-temp.gone { color: var(--danger-ink); box-shadow: inset 0 0 0 99px var(--danger-soft, rgba(185, 28, 28, .12)), var(--shadow-1); }
.gen-play {
  position: absolute; left: 50%; top: 50%; z-index: 1; transform: translate(-50%, -50%);
  display: grid; place-items: center; width: 56px; height: 56px; padding: 0 0 0 3px; cursor: pointer;
  color: var(--on-scrim); background: rgba(15, 17, 26, .4); border: 2px solid rgba(255, 255, 255, .92); border-radius: 50%;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .28); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.gen-play .sd-ic { fill: currentColor; }
/* What the file is and its shape, bottom left; a clip's length, or a heavy version's size, bottom right. */
.gen-ratio, .gen-length, .gen-heavy {
  position: absolute; bottom: 10px; z-index: 1; display: inline-flex; align-items: center; gap: 6px;
  max-width: calc(100% - 20px); height: 28px; padding: 0 9px; border-radius: 8px; pointer-events: none; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; color: var(--on-scrim); background: rgba(18, 19, 28, .92); font-variant-numeric: tabular-nums;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.gen-ratio .sd-ic { flex: none; stroke-width: 2; }
.gen-ratio { left: 10px; }
.gen-length { right: 10px; }
/* A version too large to decode, drawn by the picture it was made from: its own size, beside the shape. */
.gen-heavy { right: 10px; max-width: calc(60% - 14px); overflow: hidden; text-overflow: ellipsis; }
.gen-ratio > span[hidden], .gen-length[hidden] { display: none; }
/* Playing, the clip has its own bar along the bottom: the badges step aside. */
.gen.playing .gen-ratio, .gen.playing .gen-length { display: none; }
.gen figcaption { display: flex; flex-direction: column; gap: 5px; margin-top: 10px; min-width: 0; }
.gen-label { min-width: 0; font-size: 14.5px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gen-meta { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 12.5px; color: var(--muted); }
.gen-folder { display: inline-flex; align-items: center; gap: 7px; flex: 1 1 auto; min-width: 0; }
.gen-folder > .sd-ic { flex: none; stroke-width: 1.8; }
.gen-folder > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gen-when { flex: none; margin-left: auto; font-size: 11.5px; white-space: nowrap; }
/* A narrow tile — two to a row on a phone — puts the time under the project rather than
   cutting the project's name to three letters to keep them on one line. */
@container (max-width: 190px) {
  .gen-meta { flex-wrap: wrap; row-gap: 2px; }
  .gen-folder { flex-basis: 100%; }
  .gen-when { margin-left: 23px; }
  /* And the expiry badge goes under the «…», which is always there on a phone, so it has
     the tile's width for «Expires in 18 h» rather than cutting off the hours. */
  .gen-grid .gen-temp, .gen-grid.selecting .gen-temp { top: 46px; max-width: calc(100% - 20px); }
}
.gen-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 20px; }
.gen-foot[hidden] { display: none; }
#gen-shown { margin: 0; font-size: 12.5px; color: var(--muted); }
#gen-more { height: 32px; padding: 0 14px; border-radius: 8px; background: var(--panel); font-size: 13px; }
#gen-more[hidden] { display: none; }

/* ---- The Studio's saved work, as cards ----
   A picture in its own bordered tile, the name with its «…», when it was last written,
   the size it is made at and the way in. Three to a row at the width this screen is
   used at, folding to two and one.

   `minmax(0, 1fr)` and not `1fr`: a grid track's minimum is its content, so one long
   document name with no spaces in it widens its column and the row stops being equal
   — which is the one thing a grid of cards has to be. */
.sdocs-grid { display: grid; gap: 14px; margin-top: 12px; grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); }
.sdocs-empty { grid-column: 1 / -1; margin: 18px 0; }
/* **No `overflow: hidden` here**, and that is the whole of a bug rather than a
   preference: the card contains the «…» menu, and a card that clips cut two thirds of
   it off. The picture rounds its own corners one rule down.

   **`--border` and not `--line`.** `--line` is the mockup's name for this colour and
   this stylesheet has never defined it; an unresolved `var()` leaves `border-style` on
   its initial `none`, and only a check that reads a computed border can tell. */
.sdoc {
  display: flex; flex-direction: column; min-width: 0; padding: 9px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--panel);
}
.sdoc:hover { border-color: var(--accent-line); }
/* Above the cards after it, which is the other half of not clipping: a menu that
   escapes its own card would otherwise be painted over by the next one. */
.sdoc:has(.sdoc-pop) { position: relative; z-index: 2; }
.sdoc-shot {
  position: relative; display: block; width: 100%; aspect-ratio: 16 / 10; padding: 0; cursor: pointer;
  border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--panel-2);
}
.sdoc-shot:focus-visible { outline: 2px solid var(--accent-line); outline-offset: 2px; }
/* **Out of flow, and that is what makes the ratio hold.** `aspect-ratio` gives the tile
   a height only while nothing inside it asks for a taller one, and a picture laid out
   in flow asks for its own: a square preview made a square tile. Absolutely placed, the
   picture contributes no height at all and the ratio is the whole of it. */
.sdoc-shot img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
.sdoc-now {
  position: absolute; top: 8px; left: 8px; display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px 2px 7px; border-radius: 999px; background: var(--panel);
  box-shadow: 0 1px 4px rgba(12, 12, 14, .18); font-size: 11px; font-weight: 600; color: var(--text);
}
.sdoc-now::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--ok, #2f9e5e); }
.sdoc-foot { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 6px; row-gap: 2px; padding: 9px 3px 1px; }
.sdoc-name { grid-column: 1; grid-row: 1; min-width: 0; font-size: 13px; font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Named rather than placed by the flow: it is the child that can be the shortest. */
.sdoc-more { grid-column: 2; grid-row: 1; position: relative; }
.sdoc-dots {
  display: grid; place-items: center; width: 26px; height: 24px; padding: 0; cursor: pointer;
  color: var(--ink); background: transparent; border: none; border-radius: 6px;
}
.sdoc-dots:hover { background: var(--panel-2); }
/* **Upwards, over the card's own picture**, which is always there above the dots: a
   menu opening downwards from a card on the bottom row hangs outside the scrollable
   content where nobody can reach it. */
.sdoc-pop {
  position: absolute; right: 0; bottom: 34px; top: auto; z-index: 6; min-width: 150px; padding: 5px;
  border: 1px solid var(--border); border-radius: 11px; background: var(--panel);
  box-shadow: 0 10px 28px -12px rgba(12, 12, 14, .4);
}
.sdoc-row {
  display: block; width: 100%; padding: 7px 10px; border: none; border-radius: 7px; cursor: pointer;
  background: transparent; color: var(--text); font: inherit; font-size: 13px; text-align: left;
}
/* Downwards after all, when there is no room above — `placeMenu()` in `studio-docs.js`
   decides, because a menu off the top of the scroller is simply gone. */
.sdoc-pop.sdoc-pop-down { top: 34px; bottom: auto; }
.sdoc-row:hover { background: var(--panel-2); }
.sdoc-row-bad { color: var(--danger, #c0392b); }
/* The same cards as rows: the picture at the left, the rest beside it. */
.sdocs-grid[data-as="list"] { grid-template-columns: minmax(0, 1fr); gap: 10px; }
.sdocs-grid[data-as="list"] .sdoc { flex-direction: row; align-items: center; gap: 18px; }
.sdocs-grid[data-as="list"] .sdoc-shot { flex: none; width: 150px; }
.sdocs-grid[data-as="list"] .sdoc-foot { flex: 1; min-width: 0; grid-template-columns: minmax(0, 1fr) auto 180px; padding: 0; }
.sdocs-grid[data-as="list"] .sdoc-meta { grid-column: 1 / -1; }

/* ---- A row's «…» ---- one menu at a time, above the page, where the anchor is. */
.row-menu {
  position: fixed; z-index: 60; min-width: 170px; max-width: 300px; max-height: min(380px, 70vh); overflow: auto;
  padding: 5px; background: var(--panel); border: 1px solid var(--border); border-radius: 11px;
  box-shadow: 0 12px 32px -12px rgba(12, 12, 14, .4);
}
.row-menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; width: 100%;
  padding: 7px 10px; cursor: pointer; text-align: left; white-space: nowrap;
  font: inherit; font-size: 12.5px; color: var(--text); background: none; border: 0; border-radius: 7px;
}
.row-menu-item:hover, .row-menu-item:focus-visible { background: var(--panel-2); outline: none; }
.row-menu-item.danger { color: var(--danger-ink); }
.row-menu-item.has-sub::after { content: '›'; color: var(--muted); }
.row-menu-item.on::after { content: '✓'; color: var(--accent-ink); }
.row-menu-back { font-size: 12.5px; color: var(--muted); }
/* The stage's ⋯ (chat-ui.js): an icon before the words, and an entry that is off says why
   under its name rather than only in a tooltip. */
.row-menu-item.has-icon { justify-content: flex-start; gap: 10px; }
.row-menu-item.has-icon > svg { flex: none; color: var(--muted); }
.row-menu-item.danger.has-icon > svg { color: inherit; }
.row-menu-words { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.row-menu-note { font-size: 11px; color: var(--muted); white-space: normal; }
.row-menu-item:disabled { cursor: default; opacity: .55; }
.row-menu-item:disabled:hover { background: none; }

/* Narrower, a card gives up room in the order it can spare it, and the title and the
   way in always stay — they are why the page was opened. The pill of a card to resume
   goes under the title first; then the picture shrinks, 200×82 and 150×64; then the
   time, the star, the «…» and the way in drop under the picture, where beside it they
   left the title a few dozen pixels; and on a phone the card stacks like a tile. The
   projects' table drops its columns one at a time. */
@media (max-width: 1280px) {
  .gens-row { grid-template-columns: 260px minmax(0, 1fr) 184px; grid-template-areas: "shot body side" "shot state side"; }
  .gens-state { justify-self: start; margin-top: 8px; }
}
@media (max-width: 1100px) {
  .gens-row { grid-template-columns: 200px minmax(0, 1fr) 160px; }
  .gens-thumb { width: 200px; height: 82px; }
  .gens-open { font-size: 17px; }
  .folder-row { grid-template-columns: minmax(0, 1fr) 90px 90px 40px; }
  .folder-row .folder-when { display: none; }
}
@media (max-width: 860px) {
  .gens-row {
    grid-template-columns: 150px minmax(0, 1fr); grid-template-areas: "shot body" "shot state" "side side";
    column-gap: 14px; padding: 8px 12px 10px 8px;
  }
  .gens-thumb { width: 150px; height: 64px; align-self: start; margin-top: 2px; }
  .gens-open { font-size: 16px; }
  .gens-side { grid-template-columns: minmax(0, 1fr) auto auto auto auto; grid-template-areas: "time star bin dots go"; column-gap: 4px; margin-top: 10px; }
  .gens-go { height: 36px; }
  .gens-find { flex: 1 1 100%; }
  .gens-bar-end { margin-left: 0; }
  .gens-flat .gens-find, #view-generations .gens-list .gens-find { flex: 1 1 100%; max-width: none; }
  .gen-sel, .gens-list .gen-sel { flex: 1 1 140px; max-width: none; }
  .folder-row { grid-template-columns: minmax(0, 1fr) 40px; }
  .folder-row .folder-num { display: none; }
  .folder-cover { width: 88px; height: 56px; }
  .gens-top { flex-wrap: wrap; }
}
@media (max-width: 560px) {
  .gens-table .gens-row { grid-template-columns: minmax(0, 1fr); grid-template-areas: "shot" "body" "state" "side"; align-items: start; padding: 10px 10px 12px; }
  .gens-table .gens-thumb { width: 100%; height: auto; aspect-ratio: 16 / 9; }
  .gens-side { margin-top: 2px; }
  /* Both shapes are a column of tiles here, so the switch would switch nothing. */
  .gens-list .gens-views { display: none; }
  .gens-foot-end { padding-left: 0; border-left: 0; }
  #view-generations .folder-loose { flex-wrap: wrap; }
}

/* ================= ADS (campaigns) =================
   The client's planned campaigns: a list, then each campaign's three steps — the brief,
   the creatives to approve, the live figures. `app/js/campaigns.js` and
   `app/js/campaign-results.js` are the behaviour; this block is the look.

   «Ads» is only the word on screen. Every class here is `cmp-`, never `ads-`: EasyList,
   which every common ad blocker ships with, hides some two hundred and fifty `.ads-*`
   classes, and a screen named after its label is empty for whoever runs one — while the
   smoke's browser, which runs none, would see nothing wrong (`docs/campaigns.md`).

   What it shares with the Brand pages comes from the `.bk-*` block — the card, the two
   buttons, the chips, the note, the facts, the empty state — and the tables are the
   credit history's `.cred-table`. No token is added and no colour is a literal. Every
   wash travels with its own ink, measured for this block on the three grounds it sits on
   (card, page, `--panel-2`), light then dark:

     --accent-ink on --accent-soft   5.48 · 5.14 · 5.01     5.95 · 6.51 · 5.42
     --ok         on --ok-soft       5.91 · 5.54 · 5.40     7.91 · 8.84 · 7.05
     --warn       on --warn-soft     6.15 · 5.78 · 5.64     8.21 · 9.17 · 7.33
     --violet-ink on --violet-soft   6.60 · 6.21 · 6.05     6.41 · 7.17 · 5.74

   so every chip clears 4.5:1 wherever it lands. A bar is a mark, not a word: the meter's
   `--chart-1` fill against its `--accent-soft` track is 3.28:1 at the worst (3:1 is the
   floor for a graphical object), and the day chart's bars are `--chart-1` on the card,
   4.18:1 light and 4.26:1 dark as `:root` records. The current step's number is the
   filled pair, `--solid` under `--on-solid`.

   The badge on the column's entry is drawn in the column's own pair, not the page's: the
   column is dark in both themes, so the figure is `--side-ink` on the accent mixed a
   third into `--side-bg` — 12.4:1 — with an accent rim, 4.67:1 against the column. The
   accent as a fill under white would be 4.06:1, under AA for a twelve-pixel figure.

   Widths are the screen's own (`cmp` is a container), never the window's: the column
   beside it folds to 60px, and a page that read the window would lay the brief beside
   the contract in a gap meant for one of them. A grid child names its track. */
.cmp-view { container: cmp / inline-size; padding: 10px 8px 36px; }
.cmp-view > * { max-width: 1220px; }

/* ---- the column's entry: how many campaigns wait for the client ---- */
.cmp-nav-badge {
  flex: none; display: inline-grid; place-items: center; margin-left: auto;
  min-width: 22px; height: 22px; padding: 0 7px; border-radius: 999px;
  font-size: 12px; font-weight: 700; line-height: 1;
  color: var(--side-ink); background: color-mix(in srgb, var(--accent) 34%, var(--side-bg));
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* Folded, the bell's dot: at 9px no figure reads, and the sentence stays for a screen reader. */
body.nav-collapsed .cmp-nav-badge {
  position: absolute; top: 7px; right: 8px; min-width: 0; width: 9px; height: 9px; margin: 0; padding: 0;
  font-size: 0; color: var(--on-accent); background: var(--accent); box-shadow: 0 0 0 2px var(--side-bg);
}

/* ---- the head of the screen ---- */
.cmp-head { margin: 0 0 22px; }
.cmp-back { margin: 0 0 12px; }
.cmp-back .bk-ic { transform: scaleX(-1); }
.cmp-title-row { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; }
.cmp-title { min-width: 0; overflow-wrap: anywhere; }
/* Focused only by the code, on arriving at a campaign, so a screen reader starts there. */
.cmp-title:focus { outline: none; }
.cmp-meta { display: flex; flex-wrap: wrap; gap: 4px 18px; margin: 8px 0 0; font-size: 14px; color: var(--muted); }
.cmp-loading { margin: 0; font-size: 14px; color: var(--muted); }
.cmp-empty .err-hint { margin: 0; }

/* ---- a state, said as a word on a wash ---- */
.cmp-chip {
  display: inline-flex; align-items: center; gap: 6px; flex: none; padding: 3px 10px; white-space: nowrap;
  font-size: 12.5px; font-weight: 600; line-height: 1.4;
  color: var(--text); background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px;
}
.cmp-chip::before { content: ''; flex: none; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.cmp-chip[data-tone="client"] { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
.cmp-chip[data-tone="team"] { color: var(--violet-ink); background: var(--violet-soft); border-color: var(--violet-line); }
.cmp-chip[data-tone="ok"] { color: var(--ok); background: var(--ok-soft); border-color: var(--ok-line); }
.cmp-chip[data-tone="warn"] { color: var(--warn); background: var(--warn-soft); border-color: var(--warn-line); }

/* How much of a whole is done. A mark with nothing on it, so no ink travels with it. */
.cmp-meter { height: 8px; overflow: hidden; border-radius: 4px; background: var(--accent-soft); }
.cmp-meter > span { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--chart-1); }

/* ---- the list: one card per campaign, the whole card the target ---- */
.cmp-list {
  display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
  margin: 0; padding: 0; list-style: none;
}
.cmp-card {
  position: relative; display: flex; flex-direction: column; gap: 10px; min-width: 0; padding: 20px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  transition: border-color .13s, box-shadow .13s;
}
.cmp-card:hover { border-color: var(--accent-line); }
.cmp-card:has(.cmp-card-open:focus-visible) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-card[aria-busy="true"] { opacity: .6; }
.cmp-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px 12px; }
.cmp-card-name { margin: 0; min-width: 0; font-size: 17px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.cmp-card-open {
  padding: 0; cursor: pointer; font: inherit; color: inherit; text-align: left;
  background: none; border: 0; overflow-wrap: anywhere;
}
/* The title's button stretched over the card: one control, one name, the whole card to press. */
.cmp-card-open::after { content: ''; position: absolute; inset: 0; border-radius: 14px; }
.cmp-card-open:focus-visible { outline: none; }
.cmp-card-meta { margin: 0; font-size: 13.5px; color: var(--muted); }
.cmp-card-figure { margin: 0; font-size: 13px; color: var(--text); }
.cmp-card-turn { margin: 0; font-size: 13px; font-weight: 700; color: var(--accent-ink); }

/* ---- the three steps ---- */
.cmp-steps-nav { margin: 0 0 22px; }
.cmp-steps { display: flex; gap: 28px; margin: 0; padding: 0; list-style: none; }
.cmp-step-item { position: relative; display: flex; flex: 1 1 0; min-width: 0; }
/* The line between two steps, drawn in the gap: inside an item it would take its width
   from the second and third step and leave the first one wider than the others. */
.cmp-step-item + .cmp-step-item::before {
  content: ''; position: absolute; top: 50%; left: -22px; width: 16px; height: 2px;
  border-radius: 1px; background: var(--border);
}
.cmp-step {
  display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; min-height: 56px; padding: 8px 14px;
  cursor: pointer; font: inherit; text-align: left; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  transition: border-color .13s, box-shadow .13s;
}
.cmp-step:hover:not(:disabled) { border-color: var(--ink); }
.cmp-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-step:disabled { cursor: default; color: var(--muted); background: var(--panel-2); }
/* The step on screen; `aria-current` is the one the campaign is on, and they can differ. */
.cmp-step[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-step-n {
  display: grid; place-items: center; flex: none; width: 32px; height: 32px; border-radius: 50%;
  font-size: 14px; font-weight: 700; color: var(--muted); background: var(--panel-2); border: 1px solid var(--border);
}
.cmp-step[data-state="now"] .cmp-step-n { color: var(--on-solid); background: var(--solid); border-color: var(--solid); }
.cmp-step[data-state="done"] .cmp-step-n { color: var(--ok); background: var(--ok-soft); border-color: var(--ok-line); }
.cmp-step-lb { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.cmp-step-k { font-size: 12px; color: var(--muted); }
.cmp-step-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 15px; font-weight: 600; }

/* ---- what the steps share ---- */
.cmp-card-head { margin: 0 0 16px; }
.cmp-card-head .bk-card-sub { margin: 4px 0 0; }
.bk-card-title.cmp-card-title { margin: 0 0 14px; }
.cmp-note { align-items: center; }
.cmp-note[data-tone="ok"] { background: var(--ok-soft); border-color: var(--ok-line); }
.cmp-note[data-tone="ok"] > .bk-ic { color: var(--ok); }
.cmp-note[data-tone="client"] { background: var(--accent-soft); border-color: var(--accent-line); }
.cmp-note[data-tone="client"] > .bk-ic { color: var(--accent-ink); }
.cmp-creatives-step, .cmp-results { display: flex; flex-direction: column; gap: 18px; }
.cmp-creatives-step > *, .cmp-results > *,
.cmp-creatives-step > .bk-card, .cmp-results > .bk-card { margin: 0; }

/* ---- step 1: the contract beside the brief ---- */
.cmp-brief-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 340px); gap: 18px; align-items: start; }
.cmp-brief-grid > .cmp-brief-main { grid-column: 1; grid-row: 1; display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.cmp-brief-grid > .cmp-contract { grid-column: 2; grid-row: 1; position: sticky; top: 10px; margin: 0; }
.cmp-brief-main > .bk-card, .cmp-brief-main > .bk-note { margin: 0; }
/* A label beside a value of several lines sits level with its first line, not its middle. */
.cmp-facts > dt { align-self: start; }
.cmp-fact-list { display: grid; gap: 2px; margin: 0; padding: 0; list-style: none; }
.cmp-fact-note { display: block; margin: 2px 0 0; font-size: 12.5px; color: var(--muted); }

/* The brief's fields. A label of its own with `for`, so the name a screen reader says is
   the label alone — the hint and the error are descriptions, read after it. */
.cmp-field > .bk-label { margin: 0 0 7px; font-size: 13.5px; font-weight: 600; color: var(--text); }
.cmp-star { color: var(--danger-ink); font-weight: 700; }
.cmp-field textarea.cmp-control { min-height: 84px; line-height: 1.45; resize: vertical; }
.cmp-hint { display: block; margin: 6px 0 0; font-size: 12.5px; font-weight: 400; color: var(--muted); }
.cmp-field[role="group"] > .cmp-hint { margin: 0 0 10px; }
.cmp-err { display: block; margin: 6px 0 0; font-size: 13px; font-weight: 500; color: var(--danger-ink); }
.cmp-field.bad .cmp-control { border-color: var(--danger-ink); box-shadow: 0 0 0 1px var(--danger-ink); }
.cmp-field.bad .cmp-toggle { border-color: var(--danger-line); }
.bk-chips.cmp-toggles { margin: 0; }
/* A chosen style carries a tick as well as its wash: the colour is never the only sign. */
.cmp-tick { display: none; }
.cmp-toggle[aria-pressed="true"] .cmp-tick { display: block; }
.cmp-actions {
  display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px;
  margin: 6px 0 0; padding-top: 16px; border-top: 1px solid var(--border);
}

/* A list field as a dropdown of checkboxes. The panel is laid out of flow at the place
   it would take in it — right under its button — and over the fields below, so opening
   it moves nothing on the page. */
.cmp-dd { position: relative; }
.cmp-field > .bk-label .cmp-kit-badge { margin-left: 8px; padding: 1px 8px; font-size: 12px; vertical-align: 1px; }
.cmp-dd-btn {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; min-height: 44px;
  margin: 0; padding: 10px 14px; cursor: pointer; font: inherit; font-size: 14.5px; text-align: left; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.cmp-dd-btn.empty { color: var(--muted); }
.cmp-dd-btn:hover { border-color: var(--ink); }
.cmp-dd-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-dd.open .cmp-dd-btn { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-dd-sum { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmp-dd-chev { flex: none; color: var(--muted); transition: transform .15s; }
.cmp-dd.open .cmp-dd-chev { transform: rotate(180deg); }
/* Its edge has to read over the field it lands on: the last row is cut by the scroll, and
   a soft shadow alone let it run into the label below. */
.cmp-dd-panel {
  position: absolute; left: 0; right: 0; z-index: 30; margin-top: 6px; max-height: min(360px, 60vh); overflow-y: auto;
  padding: 8px; background: var(--panel); border: 1px solid color-mix(in srgb, var(--ink) 18%, var(--border)); border-radius: 12px;
  box-shadow: 0 18px 40px -8px color-mix(in srgb, var(--ink) 30%, transparent), 0 2px 6px color-mix(in srgb, var(--ink) 10%, transparent);
}
.cmp-dd-panel:focus { outline: none; }
/* Specific enough to beat the brand kit's field rule, which dresses every input it holds. */
.cmp-dd-panel input.cmp-dd-search {
  position: sticky; top: 0; z-index: 1; display: block; width: 100%; min-height: 40px; margin: 0 0 6px;
  padding: 8px 12px; font: inherit; font-size: 14px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
}
.cmp-dd-panel input.cmp-dd-search:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-dd-group { margin: 0; padding: 0; border: 0; min-width: 0; }
.cmp-dd-group + .cmp-dd-group { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); }
.cmp-dd-legend { padding: 6px 8px 4px; font-size: 12px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: var(--muted); }
/* `margin: 0` against the sheet's rule for every label, which spaces a list of fifty
   options ten pixels apart above and below. */
.cmp-dd-opt {
  display: flex; align-items: center; gap: 10px; min-height: 36px; margin: 0; padding: 6px 8px; cursor: pointer;
  font-size: 14px; font-weight: 500; color: var(--text); border-radius: 8px;
}
.cmp-dd-opt:hover { background: var(--panel-2); }
.cmp-dd-opt > input { flex: none; width: 17px; height: 17px; margin: 0; accent-color: var(--accent); }
.cmp-dd-opt:has(input:checked) { color: var(--accent-ink); font-weight: 600; }
.cmp-dd-none { margin: 0; padding: 10px 8px; font-size: 13.5px; color: var(--muted); }
.cmp-dd-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 0; padding: 0; list-style: none; }
.cmp-dd-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 3px 8px 3px 11px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--accent-ink);
  background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: 999px;
}
.cmp-dd-chip:hover { border-color: var(--accent); }
.cmp-dd-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The brand kit's answer, one click away under a field left empty. */
.cmp-kit-use { margin: 8px 0 0; font-size: 13px; }
.cmp-brief > .cmp-kit-note { margin: 0 0 18px; }

/* The brief once it is sent: what was asked, what was answered. */
.cmp-readonly { display: grid; grid-template-columns: minmax(120px, 32%) minmax(0, 1fr); margin: 0; }
.cmp-readonly dt, .cmp-readonly dd { padding: 12px 0; border-bottom: 1px solid var(--border); }
.cmp-readonly dt { padding-right: 16px; font-size: 13.5px; color: var(--muted); }
.cmp-readonly dd { margin: 0; font-size: 14.5px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.cmp-readonly dd.cmp-none { color: var(--muted); font-style: italic; }
.cmp-readonly > :nth-last-child(-n + 2) { border-bottom: 0; }
.cmp-link { color: var(--accent-ink); }

/* ---- step 1: materials ---- */
.cmp-materials-head { display: flex; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: 12px 16px; margin: 0 0 14px; }
.cmp-materials-head > .cmp-card-head { flex: 1 1 260px; min-width: 0; margin: 0; }
.cmp-pick-row { display: flex; flex-wrap: wrap; gap: 8px; }
.cmp-pick { flex: none; }
.cmp-refusals {
  margin: 0 0 12px; padding: 10px 14px; list-style: none; font-size: 13.5px;
  background: var(--danger-soft); border: 1px solid var(--danger-line); border-radius: 10px;
}
.cmp-refusals li + li { margin-top: 4px; }
/* Each material as a tile with its picture: what was sent is seen, not read off a name. */
.cmp-files {
  display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(150px, 100%), 1fr));
  margin: 0; padding: 0; list-style: none;
}
.cmp-files + .cmp-files { margin-top: 12px; }
.cmp-files-none { margin: 0; }
.cmp-file {
  position: relative; display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
}
.cmp-file.failed { background: var(--danger-soft); border-color: var(--danger-line); }
.cmp-file-open { display: block; }
.cmp-file-thumb {
  position: relative; display: grid; place-items: center; aspect-ratio: 4 / 3; overflow: hidden;
  color: var(--muted); background: var(--panel); border-bottom: 1px solid var(--border);
}
.cmp-file-thumb > img, .cmp-file-thumb > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cmp-file-thumb.doc { gap: 4px; align-content: center; }
.cmp-file-kind { font-size: 11.5px; font-weight: 700; letter-spacing: .06em; color: var(--muted); }
.cmp-file-play {
  position: absolute; left: 8px; bottom: 8px; display: grid; place-items: center; width: 26px; height: 26px;
  color: var(--on-scrim); background: var(--scrim); border-radius: 50%;
}
.cmp-file-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; padding: 8px 10px 10px; }
.cmp-file-name {
  display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 13.5px; color: var(--text);
}
a.cmp-file-name { font-weight: 600; color: var(--accent-ink); text-decoration: none; }
a.cmp-file-name:hover { text-decoration: underline; }
a.cmp-file-name:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.cmp-file-size { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cmp-file-err { font-size: 12.5px; color: var(--danger-ink); overflow-wrap: anywhere; }
.cmp-bar { display: block; height: 6px; overflow: hidden; border-radius: 3px; background: var(--accent-soft); }
.cmp-bar > span {
  display: block; width: 0; height: 100%; border-radius: 0 3px 3px 0;
  background: var(--accent); color: var(--on-accent); transition: width .2s linear;
}
/* A copy made on the server reports no figure: the bar runs, it does not fill. */
.cmp-bar.busy > span { width: 35%; border-radius: 3px; animation: cmp-bar-run 1.3s ease-in-out infinite; }
@keyframes cmp-bar-run { from { transform: translateX(-100%); } to { transform: translateX(290%); } }
@media (prefers-reduced-motion: reduce) { .cmp-bar.busy > span { width: 100%; animation: none; opacity: .5; } }
.cmp-x { flex: none; width: 36px; height: 36px; }
/* Over the picture, on the dark disc a photograph cannot swallow. */
.cmp-file > .cmp-x { position: absolute; top: 6px; right: 6px; width: 32px; height: 32px; color: var(--on-scrim); background: var(--scrim); border-radius: 8px; }
.cmp-file > .cmp-x:hover { color: var(--on-scrim); background: var(--scrim); opacity: .85; }

/* ---- step 2: the creatives ---- */
.cmp-step-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 16px; }
.cmp-step-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
.cmp-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); align-items: start; }
.cmp-grid > .cmp-creative { margin: 0; }
.cmp-creative { display: flex; flex-direction: column; gap: 10px; padding: 14px; }
.cmp-creative:focus { outline: none; }
.cmp-creative:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The frame keeps the creative's own shape up to a height, and the picture sits inside it
   out of flow: a 9:16 story would otherwise make every card in its row as tall as it is. */
.cmp-media {
  position: relative; overflow: hidden; aspect-ratio: var(--cmp-ratio, 1 / 1); max-height: 360px;
  background: var(--panel-2); border-radius: 10px;
}
.cmp-media > img, .cmp-media > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.cmp-media-none { position: absolute; inset: 0; display: grid; place-items: center; padding: 12px; text-align: center; font-size: 13px; color: var(--muted); }
.cmp-creative-head { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.cmp-creative-title { flex: 1; min-width: 0; margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.cmp-version { flex: none; }
.cmp-creative-row { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px 10px; }
.cmp-creative-meta { font-size: 13px; color: var(--muted); }
.cmp-caption { margin: 0; font-size: 14px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.cmp-open-file { align-self: flex-start; font-size: 13px; }
.cmp-asked { padding: 10px 12px; background: var(--warn-soft); border: 1px solid var(--warn-line); border-radius: 10px; }
.cmp-asked-label { display: block; font-size: 12px; font-weight: 700; color: var(--warn); }
.cmp-asked-text { margin: 4px 0 0; font-size: 14px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.cmp-decide { display: flex; flex-wrap: wrap; gap: 8px; }
.cmp-creative > .cmp-decide, .cmp-creative > .cmp-change { margin-top: auto; padding-top: 4px; }
.cmp-change { display: grid; gap: 10px; }
.cmp-change .bk-field { margin: 0; }

/* The requests, newest first, the team's reply under each. */
.cmp-requests-none { margin: 0; }
.cmp-request-list { margin: 0; padding: 0; list-style: none; }
.cmp-request { padding: 14px 0; border-top: 1px solid var(--border); }
.cmp-request:first-child { padding-top: 0; border-top: 0; }
.cmp-request:last-child { padding-bottom: 0; }
.cmp-request-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; font-size: 13px; color: var(--muted); }
.cmp-request-msg { margin: 8px 0 0; font-size: 14.5px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.cmp-reply { margin: 10px 0 0; padding: 10px 12px; background: var(--panel-2); border-left: 3px solid var(--accent); border-radius: 0 10px 10px 0; }
.cmp-reply-label { display: block; font-size: 12px; font-weight: 700; color: var(--accent-ink); }
.cmp-reply-text { margin: 4px 0 0; font-size: 14px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }

/* ---- step 3: the dashboard ----
   One range of days, chosen in the bar on top (`cmpResults`), and everything under it cut
   to it — the hero's figure, the tiles, the trend, the split, the channels, the shelf —
   with the team's notes under the hero and the contract's delivery beside its figure.

   No token is added. The dashboard's own colours are scoped to the screen — `.cmp-view`,
   because the overview's cards and calendar and the contract's split wear the same channel
   colours as the dashboard — the theme's mixed or the dataviz skill's documented palette,
   and measured against the surfaces they are drawn on, light then dark:

     --cmp-plan   --muted itself: the plan line under the delivery, 6.11:1 and 7.51:1.

     --cmp-ch-*   one colour per channel, the same channel the same colour on every chart
                  (`cmpTint` puts `data-ch` on a mark; `[data-ch]` below hands it
                  `--cmp-c`). Five of the skill's eight hues, assigned to the channels in the
                  order that keeps the most pairs apart under every pair-up a legend can
                  make (all pairs, not only neighbours: a channel taken out of the trend
                  puts two others side by side). Validated with the skill's validator on
                  #ffffff and #15162a:
                    light  meta #2a78d6  tiktok #e87ba4  youtube #eda100
                           programmatic #008300  ctv #4a3aa7
                           every pair ≥ 13.0 apart for a red-green reader and ≥ 16.3 for
                           anybody — all checks pass;
                    dark   #3987e5  #d55181  #c98500  #008300  #9085e9
                           every pair but one ≥ 6.9 and ≥ 19.3: Meta's blue and connected
                           TV's violet are 1.9 apart for a protan reader and 9.8 for
                           anybody, on the dark card only. Nothing on this page tells those
                           two apart by colour alone: every chart names its parts — the
                           trend's switches, the split's legend and percentages, the shares
                           under every bar — the tooltip lists every channel, two pixels of
                           card separate touching marks, and each chart has a table.
                  Contrast as marks: all five ≥ 3:1 on the dark card; on the light one
                  TikTok's pink (2.69:1) and YouTube's yellow (2.17:1) are under it, and the
                  same names, percentages and tables are the relief the skill asks for.
                  Text never wears these: a label sits beside its swatch in ink.

   The hero is a band of its own colours in both themes: `--solid` under `--on-solid`
   light (17.90:1), `--panel-2` under `--ink` dark (14.32:1), with two glows of `--accent`
   (42% and 18%) and the headline figure's days drawn as a wash of it (16%) — an agency's
   skin recolours all three, and the worst point of the text on them is 8.5:1. Its
   secondary text is the ink at 80% into the ground, never `--muted`, which on the dark
   band's glow falls to 4.11:1. The chips on it stand on `--panel`, because a wash meant
   for a card lets the band through and `--ok` on navy is not legible. The meter on it is
   `--accent` on the ink at 18%: 4.29:1 against the light band, 3.86:1 against the dark.

   The single-figure marks are `--chart-1`, 4.18:1 light and 4.26:1 dark on the card. The
   deltas are the chips' measured pairs (`--ok`, `--warn` on their washes, 5.40:1 at the
   worst), always with an arrow and the change in words. */
.cmp-view {
  --cmp-plan: var(--muted);
  --cmp-ch-meta: #2a78d6;
  --cmp-ch-tiktok: #e87ba4;
  --cmp-ch-youtube: #eda100;
  --cmp-ch-programmatic: #008300;
  --cmp-ch-ctv: #4a3aa7;
}
:root[data-theme="dark"] .cmp-view {
  --cmp-ch-meta: #3987e5;
  --cmp-ch-tiktok: #d55181;
  --cmp-ch-youtube: #c98500;
  --cmp-ch-programmatic: #008300;
  --cmp-ch-ctv: #9085e9;
}
.cmp-view [data-ch="meta"] { --cmp-c: var(--cmp-ch-meta); }
.cmp-view [data-ch="tiktok"] { --cmp-c: var(--cmp-ch-tiktok); }
.cmp-view [data-ch="youtube"] { --cmp-c: var(--cmp-ch-youtube); }
.cmp-view [data-ch="programmatic"] { --cmp-c: var(--cmp-ch-programmatic); }
.cmp-view [data-ch="ctv"] { --cmp-c: var(--cmp-ch-ctv); }
.cmp-scoped { display: flex; flex-direction: column; gap: 18px; }
.cmp-scoped > *, .cmp-scoped > .bk-card { margin: 0; }
.cmp-card-lede { margin: -8px 0 14px; }
/* A channel's colour beside its name: a square, or a short stroke where it stands for a line. */
.cmp-swatch { display: inline-block; flex: none; width: 11px; height: 11px; border-radius: 3px; background: var(--cmp-c, var(--chart-1)); }
.cmp-swatch.line { width: 14px; height: 3px; border-radius: 2px; }

/* ---- the hero ---- */
.cmp-hero {
  --cmp-hero-ground: var(--solid);
  --cmp-hero-ink: var(--on-solid);
  --cmp-hero-soft: color-mix(in srgb, var(--cmp-hero-ink) 80%, var(--cmp-hero-ground));
  position: relative; isolation: isolate; overflow: hidden;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 18px 36px;
  padding: 30px 34px 34px; border-radius: 18px;
  color: var(--cmp-hero-ink);
  background:
    radial-gradient(110% 150% at 100% 0%, color-mix(in srgb, var(--accent) 42%, transparent), color-mix(in srgb, var(--accent) 0%, transparent) 62%),
    radial-gradient(80% 120% at 0% 100%, color-mix(in srgb, var(--accent) 18%, transparent), color-mix(in srgb, var(--accent) 0%, transparent) 60%),
    var(--cmp-hero-ground);
  box-shadow: var(--shadow-2);
}
:root[data-theme="dark"] .cmp-hero { --cmp-hero-ground: var(--panel-2); --cmp-hero-ink: var(--ink); border: 1px solid var(--border); }
.cmp-hero-art { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; pointer-events: none; }
.cmp-hero-curve { fill: none; stroke: color-mix(in srgb, var(--accent) 55%, transparent); stroke-width: 1.4; vector-effect: non-scaling-stroke; }
.cmp-hero-area { fill: color-mix(in srgb, var(--accent) 16%, transparent); }
.cmp-hero-line { fill: none; stroke: color-mix(in srgb, var(--accent) 70%, transparent); stroke-width: 2; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.cmp-hero-main { grid-column: 1; min-width: 0; }
.cmp-hero-eyebrow { display: flex; align-items: center; gap: 7px; margin: 0 0 12px; font-size: 13px; font-weight: 700; letter-spacing: .01em; color: var(--cmp-hero-soft); }
.cmp-hero-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 0; line-height: 1; }
/* The one hero figure of the page: the interface's own sans, proportional figures. */
.cmp-hero-value { font-size: 58px; font-weight: 800; letter-spacing: -.035em; overflow-wrap: anywhere; }
.cmp-hero-unit { font-size: 20px; font-weight: 700; color: var(--cmp-hero-soft); }
.cmp-hero-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 16px 0 0; }
.cmp-hero-vs { font-size: 13.5px; color: var(--cmp-hero-soft); }
.cmp-hero-text { margin: 12px 0 0; max-width: 70ch; font-size: 15px; font-weight: 600; line-height: 1.5; color: var(--cmp-hero-ink); overflow-wrap: anywhere; }
.cmp-hero-meta { display: flex; align-items: center; gap: 7px; margin: 10px 0 0; font-size: 13px; color: var(--cmp-hero-soft); }
.cmp-hero .cmp-delta, .cmp-hero .cmp-chip { background: var(--panel); }
/* A grid child that can be alone names its track: the goal is the second column, or the second row. */
.cmp-hero-figure {
  grid-column: 2; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 230px; padding: 16px 18px; text-align: right;
  background: color-mix(in srgb, var(--cmp-hero-ground) 78%, var(--cmp-hero-ink) 6%); border: 1px solid color-mix(in srgb, var(--cmp-hero-ink) 16%, transparent); border-radius: 14px;
  backdrop-filter: blur(6px);
}
.cmp-hero-goal-lb { margin: 0 0 4px; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--cmp-hero-soft); }
.cmp-hero-goal { margin: 0; font-size: 36px; font-weight: 800; line-height: 1; letter-spacing: -.02em; }
.cmp-hero-label { margin: 0; font-size: 13.5px; font-weight: 600; }
.cmp-hero .cmp-meter { width: 100%; min-width: 190px; margin-top: 8px; background: color-mix(in srgb, var(--cmp-hero-ink) 18%, transparent); }
.cmp-hero .cmp-meter > span { background: var(--accent); }
.cmp-hero-note { margin: 4px 0 0; font-size: 12.5px; color: var(--cmp-hero-soft); font-variant-numeric: tabular-nums; }
.cmp-hero-figure > .cmp-chip { margin-top: 8px; }

/* ---- the team's notes: a section of their own, under the hero ---- */
.cmp-notes {
  padding: 20px 22px 22px; border: 1px solid var(--accent-line); border-radius: 16px; box-shadow: var(--shadow-1);
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 7%, var(--panel)), var(--panel) 140px);
}
.cmp-notes-head { display: flex; align-items: center; gap: 14px; margin: 0 0 16px; }
.cmp-notes-ic { display: grid; place-items: center; flex: none; width: 42px; height: 42px; border-radius: 12px; color: var(--on-accent); background: var(--accent); }
.cmp-notes-words { min-width: 0; }
.cmp-notes-title { margin: 0; font-size: 20px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
.cmp-notes-sub { margin: 2px 0 0; font-size: 13.5px; color: var(--muted); }
.cmp-notes-head > .cmp-chip { margin-left: auto; }
.cmp-notes-list { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); margin: 0; padding: 0; list-style: none; }
.cmp-memo { display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 14px 16px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; }
.cmp-memo[hidden] { display: none; }
.cmp-memo.latest { border-color: var(--accent-line); box-shadow: inset 3px 0 0 var(--accent); }
.cmp-memo-top { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; font-size: 12.5px; color: var(--muted); }
.cmp-memo-ic { display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 50%; color: var(--accent-ink); background: var(--accent-soft); }
.cmp-memo-new { padding: 2px 9px; font-size: 11.5px; font-weight: 700; color: var(--on-solid); background: var(--solid); border-radius: 999px; }
.cmp-memo-ch { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; color: var(--text); }
.cmp-memo-when { margin-left: auto; }
.cmp-memo-title { margin: 2px 0 0; font-size: 16px; font-weight: 700; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.cmp-memo.latest .cmp-memo-title { font-size: 18px; }
.cmp-memo-text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
.cmp-memo-text[data-folded="true"] { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 5; line-clamp: 5; overflow: hidden; }
.cmp-memo-more { align-self: flex-start; font-size: 13px; }
.cmp-notes-more { margin: 14px 0 0; }

/* ---- the pacing ---- */
.cmp-pacing-line { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px; }
.cmp-pacing-text { flex: 1 1 280px; margin: 0; font-size: 14.5px; color: var(--text); }
.cmp-pacing-detail { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.cmp-pace { margin: 16px 0 0; }
.cmp-pace-plan { fill: none; stroke: var(--cmp-plan); stroke-width: 1.5; }
.cmp-pace-line { fill: none; stroke: var(--chart-1); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cmp-pace-area { fill: color-mix(in srgb, var(--chart-1) 10%, transparent); }
.cmp-pace-dot { fill: var(--chart-1); stroke: var(--panel); stroke-width: 2; }
.cmp-pace-cross { stroke: var(--muted); stroke-width: 1; }
/* Text wears text tokens, never the line's colour: the line beside it says which it is. */
.cmp-pace-label { fill: var(--ink); font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cmp-pace-label.muted { fill: var(--muted); font-weight: 600; }

/* ---- the bar on top: on top of the screen while the figures under it scroll ----
   The slot, not the bar inside it, is what sticks: a sticky element sticks inside its
   parent, and the slot's parent is the whole step. */
.cmp-results > .cmp-filters-slot { position: sticky; top: 0; z-index: 6; margin: 0 -8px; }
.cmp-filters {
  display: flex; flex-direction: column; gap: 6px; padding: 10px 8px 12px;
  background: var(--bg); border-bottom: 1px solid var(--border);
}
.cmp-filters-row { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.cmp-filters-note { margin: 0; font-size: 13px; color: var(--muted); }
.cmp-export { display: inline-flex; align-items: center; gap: 7px; margin-left: auto; }

/* The range: a button that says it, and the calendar it opens. */
.cmp-range { position: relative; }
.cmp-range-btn {
  display: inline-flex; align-items: center; gap: 10px; min-height: 46px; padding: 6px 12px; cursor: pointer;
  font: inherit; color: var(--ink); text-align: left; background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-1); transition: border-color .12s, box-shadow .12s;
}
.cmp-range-btn:hover { border-color: var(--ink); }
.cmp-range-btn[aria-expanded="true"] { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.cmp-range-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-range-btn:disabled { cursor: default; opacity: .7; box-shadow: none; }
.cmp-range-btn:disabled:hover { border-color: var(--border); }
.cmp-range-btn > .sd-ic { flex: none; color: var(--accent-ink); }
.cmp-range-words { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.cmp-range-name { font-size: 11.5px; font-weight: 600; color: var(--muted); }
.cmp-range-period { font-size: 14.5px; font-weight: 700; white-space: nowrap; }
.cmp-range-caret { display: grid; flex: none; color: var(--muted); transition: transform .15s; }
.cmp-range-btn[aria-expanded="true"] .cmp-range-caret { transform: rotate(180deg); }
.cmp-range-pop {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 30;
  display: grid; grid-template-columns: auto auto; grid-template-areas: "presets cal" "foot foot";
  width: max-content; max-width: min(780px, calc(100vw - 32px));
  background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-2);
  animation: cmp-pop .16s cubic-bezier(.2, .8, .2, 1);
}
@keyframes cmp-pop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.cmp-range-presets { grid-area: presets; min-width: 190px; max-height: 372px; margin: 0; padding: 10px; overflow-y: auto; list-style: none; border-right: 1px solid var(--border); }
.cmp-range-preset {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 36px; padding: 6px 10px; cursor: pointer;
  font: inherit; font-size: 13.5px; color: var(--text); text-align: left; background: none; border: 0; border-radius: 9px;
}
.cmp-range-preset:hover { background: var(--panel-2); }
.cmp-range-preset[aria-pressed="true"] { font-weight: 700; color: var(--ink); }
.cmp-range-preset:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The selection is a 16px bold check, never a wash that would compete with a hover. */
.cmp-range-tick { display: grid; flex: none; width: 16px; color: var(--accent-ink); }
.cmp-range-tick .sd-ic { stroke-width: 2.6; }
.cmp-range-cal { grid-area: cal; position: relative; min-width: 0; padding: 12px 14px 8px; }
.cmp-cal-nav { position: absolute; top: 10px; left: 10px; right: 10px; display: flex; justify-content: space-between; pointer-events: none; }
.cmp-cal-step {
  display: grid; place-items: center; width: 34px; height: 34px; padding: 0; cursor: pointer; pointer-events: auto;
  color: var(--ink); background: none; border: 0; border-radius: 9px;
}
.cmp-cal-step:hover { background: var(--panel-2); }
.cmp-cal-step:disabled { opacity: .3; cursor: default; background: none; }
.cmp-cal-step:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cmp-cal-months { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 22px; }
.cmp-cal-month { min-width: 0; }
.cmp-cal-title { margin: 8px 0 10px; font-size: 14px; font-weight: 700; text-align: center; color: var(--ink); }
.cmp-cal-grid { border-collapse: separate; border-spacing: 0 2px; }
.cmp-cal-grid th { width: 38px; padding: 0 0 4px; font-size: 11.5px; font-weight: 600; text-align: center; color: var(--muted); }
.cmp-cal-grid td { padding: 0; text-align: center; }
.cmp-cal-day {
  width: 38px; height: 36px; padding: 0; cursor: pointer;
  font: inherit; font-size: 13px; font-variant-numeric: tabular-nums; color: var(--text); background: none; border: 0; border-radius: 9px;
}
.cmp-cal-day:hover { background: var(--panel-2); }
.cmp-cal-day.in { color: var(--ink); background: var(--accent-soft); border-radius: 0; }
.cmp-cal-day.start, .cmp-cal-day.end { font-weight: 700; color: var(--on-solid); background: var(--solid); }
.cmp-cal-day.start { border-radius: 9px 0 0 9px; }
.cmp-cal-day.end { border-radius: 0 9px 9px 0; }
.cmp-cal-day.start.end { border-radius: 9px; }
/* A day without figures keeps the week straight and says it has none; it is not a choice. */
.cmp-cal-day[aria-disabled="true"] { cursor: default; color: color-mix(in srgb, var(--muted) 55%, var(--panel)); background: none; }
.cmp-cal-day:focus-visible { position: relative; z-index: 1; outline: 2px solid var(--accent); outline-offset: -2px; }
.cmp-range-foot { grid-area: foot; display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; padding: 12px 14px; border-top: 1px solid var(--border); }
.cmp-range-fields { display: flex; flex-wrap: wrap; gap: 8px 12px; }
.cmp-range-said { flex: 1 1 160px; margin: 0; font-size: 13px; color: var(--muted); }
.cmp-range-actions { display: flex; gap: 8px; margin-left: auto; }
.cmp-date { display: inline-flex; align-items: center; gap: 7px; margin: 0; font-size: 13px; color: var(--muted); }
.cmp-date-in {
  min-height: 34px; padding: 5px 8px; font: inherit; font-size: 13.5px; color: var(--text);
  background: var(--field); border: 1px solid var(--border); border-radius: 9px;
}
.cmp-date-in:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* A row of choices of which one is on: a pressed button is the card colour on the rail. */
.cmp-seg {
  display: inline-flex; flex-wrap: wrap; gap: 2px; max-width: 100%; padding: 3px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
}
.cmp-seg-btn {
  min-height: 32px; padding: 5px 12px; cursor: pointer; white-space: nowrap;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--muted);
  background: transparent; border: 0; border-radius: 9px; transition: background .12s, color .12s;
}
.cmp-seg-btn:hover { color: var(--ink); }
.cmp-seg-btn[aria-pressed="true"] { color: var(--ink); background: var(--panel); box-shadow: var(--shadow-1), 0 0 0 1px var(--border); }
.cmp-seg-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.cmp-tools { display: flex; flex-wrap: wrap; gap: 8px 12px; margin: 0 0 12px; }

/* ---- the tiles ---- */
.cmp-kpis { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(min(200px, 100%), 1fr)); }
.cmp-kpi {
  display: flex; flex-direction: column; gap: 8px; min-width: 0; overflow: hidden; padding: 16px 18px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
}
.cmp-kpi-top { display: flex; align-items: center; gap: 10px; }
.cmp-kpi-ic { display: grid; place-items: center; flex: none; width: 34px; height: 34px; border-radius: 50%; color: var(--accent-ink); background: var(--accent-soft); }
.cmp-kpi-label { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--muted); }
/* Proportional figures: a standalone number in tabular ones reads loose. */
.cmp-kpi-value { margin: 0; font-size: 28px; font-weight: 800; line-height: 1.1; letter-spacing: -.02em; color: var(--ink); overflow-wrap: anywhere; }
.cmp-kpi-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.cmp-kpi-sub { margin: 0; font-size: 13px; color: var(--muted); }
/* The sparkline runs to the tile's edges and sits on its floor; in a channel's card it wears the channel. */
.cmp-spark { display: block; flex: none; width: calc(100% + 36px); height: 34px; margin: 4px -18px -16px; }
.cmp-spark-line { fill: none; stroke: var(--cmp-c, var(--chart-1)); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.cmp-spark-area { fill: color-mix(in srgb, var(--cmp-c, var(--chart-1)) 10%, transparent); }
.cmp-delta {
  display: inline-flex; align-items: center; gap: 3px; padding: 2px 8px 2px 6px; white-space: nowrap;
  font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text); background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px;
}
.cmp-delta[data-tone="up"] { color: var(--ok); background: var(--ok-soft); border-color: var(--ok-line); }
.cmp-delta[data-tone="down"] { color: var(--warn); background: var(--warn-soft); border-color: var(--warn-line); }

/* ---- two cards side by side: the trend beside the split, the shares beside the pacing ---- */
.cmp-duo { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); align-items: start; gap: 18px; }
.cmp-duo.cmp-duo-mix { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.cmp-duo > .bk-card { margin: 0; }
.cmp-duo > :first-child { grid-column: 1; }
.cmp-duo > :nth-child(2) { grid-column: 2; }
.cmp-duo.solo { grid-template-columns: minmax(0, 1fr); }
.cmp-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin: 0 0 8px; padding: 0; list-style: none; font-size: 12.5px; color: var(--muted); }
.cmp-legend-item { display: inline-flex; align-items: center; gap: 7px; }
.cmp-key { display: inline-block; flex: none; width: 12px; height: 12px; border-radius: 3px; }
.cmp-key-line, .cmp-key-plan { width: 16px; height: 3px; border-radius: 2px; }
.cmp-key-line { background: var(--chart-1); }
.cmp-key-plan { background: var(--cmp-plan); }
/* In a tooltip a key is a short stroke: at that density a filled box is ink doing a label's job. */
.cmp-tip-line .cmp-swatch { margin-right: 6px; vertical-align: middle; }

/* The channels of the trend, each a switch: pressed, it is in the chart; out, its square is hollow and its name struck. */
.cmp-switches { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.cmp-switch {
  display: inline-flex; align-items: center; gap: 8px; min-height: 36px; padding: 5px 12px; cursor: pointer;
  font: inherit; font-size: 13px; color: var(--ink); background: var(--panel); border: 1px solid var(--border); border-radius: 999px;
  transition: border-color .12s, background .12s, color .12s;
}
.cmp-switch:hover { border-color: var(--ink); }
.cmp-switch[aria-pressed="true"] { background: color-mix(in srgb, var(--cmp-c) 10%, var(--panel)); border-color: color-mix(in srgb, var(--cmp-c) 60%, var(--border)); }
.cmp-switch[aria-pressed="false"] { color: var(--muted); }
.cmp-switch[aria-pressed="false"] .cmp-swatch { background: transparent; box-shadow: inset 0 0 0 2px var(--cmp-c); }
.cmp-switch[aria-pressed="false"] .cmp-switch-name { text-decoration: line-through; }
.cmp-switch[aria-disabled="true"] { cursor: default; }
.cmp-switch:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-switch-name { font-weight: 600; }
.cmp-switch-n { color: var(--muted); font-variant-numeric: tabular-nums; }

/* The days, drawn in pixels at the width their box measures (`cmpDayChart`), never
   scaled: a scaled chart's ticks scale with it, eighteen pixels on a wide card and five
   on a phone. Under 420px it scrolls sideways instead. The box holds the plot's height
   before the first measurement, so nothing below it jumps; the tooltip sits beside the
   scroller, never inside it. */
.cmp-chart { position: relative; border-radius: 10px; }
.cmp-chart:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.cmp-chart-scroll { min-height: 260px; overflow-x: auto; }
.cmp-chart-svg { display: block; }
.cmp-chart-grid { stroke: var(--border); stroke-width: 1; }
.cmp-chart-tick { fill: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.cmp-chart-seg { fill: var(--cmp-c, var(--chart-1)); transition: opacity .12s; }
.cmp-chart-day.on > .cmp-chart-seg { opacity: .74; }
.cmp-chart-line { fill: none; stroke: var(--cmp-c, var(--chart-1)); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.cmp-chart-dot { fill: var(--cmp-c, var(--chart-1)); stroke: var(--panel); stroke-width: 2; }
.cmp-chart-cross { stroke: var(--muted); stroke-width: 1; }
.cmp-chart-band { fill: var(--accent-soft); stroke: var(--accent-line); stroke-width: 1; }
.cmp-chart-hit { fill: transparent; }
.cmp-chart-hit.brush { cursor: crosshair; }
.cmp-chart-hint { display: flex; align-items: center; gap: 6px; margin: 8px 0 0; }
/* The columns rise from the baseline once, when the chart first appears; the lines draw themselves. */
.cmp-chart-svg.rise .cmp-chart-day { transform-box: fill-box; transform-origin: 50% 100%; animation: cmp-rise .6s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes cmp-rise { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.cmp-chart-svg.rise .cmp-chart-line { stroke-dasharray: 1; animation: cmp-draw .9s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes cmp-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
.cmp-tip {
  position: absolute; top: 2px; z-index: 3; transform: translateX(-50%); pointer-events: none;
  display: flex; flex-direction: column; gap: 1px; padding: 6px 9px; white-space: nowrap;
  font-size: 12px; color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 9px;
  box-shadow: var(--shadow-2);
}
.cmp-tip-day { font-weight: 700; color: var(--ink); }
.cmp-tip-line { color: var(--muted); font-variant-numeric: tabular-nums; }
.cmp-tip-line strong { font-weight: 700; color: var(--text); }

/* ---- the split by channel: a ring and its legend ---- */
.cmp-split > .cmp-seg { margin: 0 0 14px; }
.cmp-split-body { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 24px; }
.cmp-donut { flex: none; }
.cmp-donut-svg { display: block; overflow: visible; }
.cmp-donut-slice {
  fill: var(--cmp-c); stroke: var(--panel); stroke-width: 2; stroke-linejoin: round;
  transform-box: view-box; transform-origin: 50% 50%; transition: transform .15s, opacity .15s;
}
.cmp-donut-slice.on { transform: translate(var(--dx), var(--dy)); }
.cmp-donut-svg:has(.cmp-donut-slice.on) .cmp-donut-slice:not(.on) { opacity: .45; }
.cmp-donut-svg.rise .cmp-donut-slice { animation: cmp-ring .7s cubic-bezier(.2, .8, .2, 1); }
@keyframes cmp-ring { from { opacity: 0; transform: rotate(-24deg) scale(.88); } to { opacity: 1; transform: none; } }
.cmp-donut-value { fill: var(--ink); font-size: 26px; font-weight: 800; letter-spacing: -.02em; }
.cmp-donut-cap { fill: var(--muted); font-size: 12.5px; font-weight: 600; }
.cmp-donut-pct { fill: var(--text); font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.cmp-split-legend { flex: 1 1 210px; display: grid; gap: 4px; min-width: 0; margin: 0; padding: 0; list-style: none; }
.cmp-split-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 10px;
  padding: 7px 10px; font-size: 13.5px; border-radius: 9px; transition: background .12s;
}
.cmp-split-row.on { background: color-mix(in srgb, var(--cmp-c) 12%, var(--panel)); }
.cmp-split-name { min-width: 0; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.cmp-split-value { color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.cmp-split-share { min-width: 44px; font-weight: 800; text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-split-none { margin: 0; }

/* ---- the channels' shares of the funnel: a bar per figure, cut into the channels ---- */
.cmp-mix-rows { display: grid; gap: 16px; }
.cmp-mix-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin: 0 0 6px; }
.cmp-mix-name { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.cmp-mix-total { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cmp-mix-bar { display: flex; gap: 2px; height: 14px; overflow: hidden; border-radius: 7px; background: var(--panel-3); }
.cmp-mix-seg { flex: 1 1 0; min-width: 2px; background: var(--cmp-c); }
.cmp-mix-shares { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 6px 0 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--muted); }
.cmp-mix-share { display: inline-flex; align-items: center; gap: 6px; }
.cmp-mix-share strong { color: var(--ink); font-variant-numeric: tabular-nums; }

/* ---- the channels side by side ---- */
/* `auto-fit`: two channels share the row between them rather than leave three empty tracks beside them. */
.cmp-chcards { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); margin: 0; padding: 0; list-style: none; }
.cmp-chcard {
  display: flex; flex-direction: column; gap: 8px; min-width: 0; overflow: hidden; padding: 16px;
  background: var(--panel-2); border: 1px solid var(--border); border-top: 3px solid var(--cmp-c, var(--border)); border-radius: 14px;
}
.cmp-chcard-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.cmp-chcard-name { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); }
.cmp-chcard-share { font-size: 12.5px; color: var(--muted); white-space: nowrap; }
.cmp-chcard-badges { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.cmp-badge {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px;
  font-size: 12px; font-weight: 700; color: var(--accent-ink);
  background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: 999px;
}
.cmp-chcard-value { margin: 2px 0 0; font-size: 24px; font-weight: 800; line-height: 1.1; color: var(--ink); }
.cmp-chcard-unit { margin: 0; font-size: 12.5px; color: var(--muted); }
.cmp-chcard-facts { display: grid; gap: 6px; margin: 4px 0 0; }
.cmp-chcard-fact { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.cmp-chcard-fact dt { color: var(--muted); }
.cmp-chcard-fact dd { margin: 0; font-weight: 600; text-align: right; color: var(--text); font-variant-numeric: tabular-nums; }
.cmp-chcard .cmp-spark { width: calc(100% + 32px); margin: 6px -16px -16px; }

/* ---- the content ---- */
.cmp-top > .cmp-seg { margin: 0 0 14px; }
.cmp-top-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(250px, 100%), 1fr)); margin: 0; padding: 0; list-style: none; }
.cmp-top-item {
  position: relative; display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  transition: border-color .13s, box-shadow .13s;
}
.cmp-top-item:hover { border-color: var(--accent-line); box-shadow: var(--shadow-2); }
.cmp-top-media { position: relative; display: grid; place-items: center; aspect-ratio: 4 / 3; color: var(--muted); background: var(--panel-3); }
.cmp-top-media > img, .cmp-top-media > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* A creative the campaign no longer has: a frame that says so, never a broken picture. */
.cmp-top-media.gone { color: var(--muted); background: repeating-linear-gradient(135deg, var(--panel-3) 0 14px, var(--panel-2) 14px 28px); }
.cmp-top-item.gone .cmp-top-name { color: var(--muted); }
.cmp-top-report { margin: 0; font-size: 12.5px; color: var(--muted); overflow-wrap: anywhere; }
.cmp-top-play, .cmp-top-time, .cmp-top-rank { color: var(--on-solid); background: color-mix(in srgb, var(--solid) 84%, transparent); }
.cmp-top-play {
  position: absolute; left: 10px; bottom: 10px; display: grid; place-items: center;
  width: 38px; height: 38px; padding: 0; cursor: pointer; border: 0; border-radius: 50%;
}
.cmp-top-play:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-top-time { position: absolute; left: 56px; bottom: 17px; padding: 1px 8px; font-size: 12px; font-weight: 700; border-radius: 999px; font-variant-numeric: tabular-nums; }
.cmp-top-rank {
  position: absolute; top: 10px; right: 10px; display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; font-size: 12px; font-weight: 700; background: var(--solid); border-radius: 999px; box-shadow: var(--shadow-1);
}
.cmp-top-body { display: flex; flex: 1; flex-direction: column; gap: 3px; padding: 14px 16px 16px; }
.cmp-top-name { margin: 0; font-size: 15.5px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.cmp-top-ch { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: 13px; color: var(--muted); }
.cmp-top-figs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 6px 18px; margin: 10px 0 12px; }
/* The term comes first in the list, the figure is what the eye looks for: stood on top. */
.cmp-top-fig { display: flex; flex-direction: column-reverse; min-width: 0; }
.cmp-top-fig dt { font-size: 12px; color: var(--muted); }
.cmp-top-fig dd { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-top-fig.lead dd { font-size: 22px; font-weight: 800; letter-spacing: -.01em; }
.cmp-top-go { display: inline-flex; align-items: center; justify-content: center; gap: 6px; width: 100%; margin-top: auto; }
.cmp-top-go .sd-ic { transition: transform .15s; }
.cmp-top-go[aria-expanded="true"] .sd-ic { transform: rotate(180deg); }
.cmp-top-more { margin: 12px 0 0; }
.cmp-top-none { margin: 0; }

/* One creative, studied under the shelf. */
.cmp-study { margin: 16px 0 0; padding: 18px; background: var(--panel-2); border: 1px solid var(--accent-line); border-radius: 14px; }
.cmp-study-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 0 0 12px; }
.cmp-study-title { margin: 0; font-size: 16.5px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.cmp-study-close { display: inline-flex; flex: none; align-items: center; gap: 4px; }
.cmp-study-facts { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(min(170px, 100%), 1fr)); margin: 0 0 14px; }
.cmp-study-fact { min-width: 0; padding: 12px 14px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; }
.cmp-study-fact dt { font-size: 12.5px; color: var(--muted); }
.cmp-study-value { margin: 2px 0 0; font-size: 20px; font-weight: 800; color: var(--ink); }
.cmp-study-sub { margin: 2px 0 0; font-size: 12.5px; color: var(--muted); }
.cmp-study-chart-lb { margin: 0 0 6px; font-size: 13px; font-weight: 600; color: var(--text); }
.cmp-study .cmp-chart { padding: 6px 4px 0; background: var(--panel); border-radius: 12px; }
.cmp-study-sub-title { margin: 16px 0 8px; font-size: 14px; font-weight: 700; color: var(--ink); }

/* ---- the tables every chart has a twin in ---- */
.cmp-tableview { margin: 10px 0 0; }
.cmp-tableview > summary { width: fit-content; padding: 4px 0; cursor: pointer; font-size: 13px; color: var(--muted); }
.cmp-tableview > summary:hover { color: var(--ink); }
.cmp-tableview > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
.cmp-tableview > .cmp-table-wrap { max-height: 320px; margin-top: 8px; overflow: auto; }
.cmp-table-wrap { overflow-x: auto; }
.cmp-table { min-width: 520px; }
.cmp-table th, .cmp-table td { font-size: 14px; }
.cmp-table .num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cmp-table-note { margin: 10px 0 0; }
.cmp-cell-creative { display: flex; align-items: center; gap: 12px; min-width: 0; }
.cmp-thumb { flex: none; width: 40px; height: 40px; object-fit: cover; background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px; }
.cmp-cell-words { display: flex; flex-direction: column; min-width: 0; }
.cmp-cell-name { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.cmp-cell-sub { font-size: 12.5px; color: var(--muted); }
.cmp-cell-ch { display: inline-flex; align-items: center; gap: 6px; }

/* ---- the overview: the portfolio, the cards, the calendar, and how it works ----
   `app/js/campaign-hub.js` draws it, before a campaign is opened. No token is added.

   A campaign's phase wears a colour of the chart palette, the same on its card's top edge,
   its stage marks, its bar in the calendar and the band's tile that filters it, and never
   alone: every mark of a phase sits beside its name (the chip, the legend, the tile's
   label, the bar's name and tooltip). As marks against the card, light then dark:

     you    --chart-1   4.18:1   4.26:1        live   --chart-4   4.92:1  10.36:1
     ready  --chart-2   7.77:1   4.14:1        done   --muted     6.11:1   7.51:1

   The two bands — the portfolio and the guide's opening — are the dashboard hero's ground
   and its measured ink (`.cmp-hero` above): `--solid` under `--on-solid` light, `--panel-2`
   under `--ink` dark, the secondary text the ink at 80% into the ground. The phase dots on
   the band are decoration beside a figure and a word, ringed in the band's ink.

   The calendar's bars are the phase colour at a quarter on the card, edged in the full
   colour (the edge is the mark that clears 3:1); what a live campaign has delivered fills
   the bar in the full colour. Today is the accent, labelled «Today» on `--on-accent`.

   The model's curves are the channels' colours (`--cmp-c`): the part a split spends on a
   channel at three pixels, the rest of its curve dashed and faint — what the whole budget
   would find there — and every curve named in the legend under it with its spend and its
   people, so no colour is the only thing that says which curve is which. */
.cmp-view [data-phase="you"] { --cmp-ph: var(--chart-1); }
.cmp-view [data-phase="ready"] { --cmp-ph: var(--chart-2); }
.cmp-view [data-phase="live"] { --cmp-ph: var(--chart-4); }
.cmp-view [data-phase="done"] { --cmp-ph: var(--muted); }

/* The two tabs: what the brand has bought, and how it works. */
.cmp-hub { display: flex; flex-direction: column; gap: 20px; }
.cmp-hub-tabs { display: flex; flex-wrap: wrap; gap: 4px; border-bottom: 1px solid var(--border); }
.cmp-hub-tab {
  display: inline-flex; align-items: center; gap: 8px; min-height: 46px; margin: 0 0 -1px; padding: 8px 16px;
  cursor: pointer; font: inherit; font-size: 14.5px; font-weight: 600; color: var(--muted);
  background: none; border: 0; border-bottom: 2px solid transparent; border-radius: 10px 10px 0 0;
  transition: color .12s, border-color .12s, background .12s;
}
.cmp-hub-tab:hover { color: var(--ink); background: var(--panel-2); }
.cmp-hub-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }
.cmp-hub-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.cmp-hub-tab-n {
  min-width: 22px; padding: 1px 7px; font-size: 12px; font-weight: 700; line-height: 18px; text-align: center;
  color: var(--muted); background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px;
}
.cmp-hub-tab[aria-selected="true"] .cmp-hub-tab-n { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
.cmp-hub-page, .cmp-guide { display: flex; flex-direction: column; gap: 22px; }
.cmp-hub-page > *, .cmp-guide > *, .cmp-hub-page > .bk-card, .cmp-guide > .bk-card { margin: 0; }
.cmp-hub-duo > .bk-card { min-width: 0; }

/* The three bands share the dashboard hero's ground: the portfolio, the guide's opening and
   its closing call to action. */
.cmp-port, .cmp-guide-hero, .cmp-call {
  --cmp-hero-ground: var(--solid);
  --cmp-hero-ink: var(--on-solid);
  --cmp-hero-soft: color-mix(in srgb, var(--cmp-hero-ink) 80%, var(--cmp-hero-ground));
  position: relative; isolation: isolate; overflow: hidden; border-radius: 18px;
  color: var(--cmp-hero-ink);
  background:
    radial-gradient(110% 150% at 100% 0%, color-mix(in srgb, var(--accent) 42%, transparent), color-mix(in srgb, var(--accent) 0%, transparent) 62%),
    radial-gradient(80% 120% at 0% 100%, color-mix(in srgb, var(--accent) 18%, transparent), color-mix(in srgb, var(--accent) 0%, transparent) 60%),
    var(--cmp-hero-ground);
  box-shadow: var(--shadow-2);
}
:root[data-theme="dark"] .cmp-port, :root[data-theme="dark"] .cmp-guide-hero, :root[data-theme="dark"] .cmp-call {
  --cmp-hero-ground: var(--panel-2); --cmp-hero-ink: var(--ink); border: 1px solid var(--border);
}
/* A soft tile on a band: the ground lifted a shade, edged in its own ink. */
.cmp-port-tile, .cmp-guide-fact, .cmp-port-fact {
  background: color-mix(in srgb, var(--cmp-hero-ground) 78%, var(--cmp-hero-ink) 6%);
  border: 1px solid color-mix(in srgb, var(--cmp-hero-ink) 16%, transparent);
}

/* ---- the portfolio's band ---- */
.cmp-port { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 380px); align-items: center; gap: 22px 34px; padding: 30px 32px; }
.cmp-port-main { grid-column: 1; min-width: 0; }
.cmp-port-eyebrow { display: flex; align-items: center; gap: 7px; margin: 0 0 12px; font-size: 13px; font-weight: 700; letter-spacing: .01em; color: var(--cmp-hero-soft); }
.cmp-port-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: 0; line-height: 1; color: var(--cmp-hero-ink); }
.cmp-port-value { font-size: 54px; font-weight: 800; letter-spacing: -.035em; overflow-wrap: anywhere; }
.cmp-port-unit { font-size: 19px; font-weight: 700; color: var(--cmp-hero-soft); }
.cmp-port .cmp-meter { max-width: 560px; margin: 18px 0 0; background: color-mix(in srgb, var(--cmp-hero-ink) 18%, transparent); }
.cmp-port .cmp-meter > span { background: var(--accent); }
.cmp-port-note { margin: 8px 0 0; font-size: 13.5px; color: var(--cmp-hero-soft); font-variant-numeric: tabular-nums; }
.cmp-port-facts { display: flex; flex-wrap: wrap; gap: 8px; margin: 18px 0 0; padding: 0; list-style: none; }
.cmp-port-fact { display: inline-flex; align-items: center; gap: 7px; padding: 6px 12px; font-size: 13px; color: var(--cmp-hero-soft); border-radius: 999px; }
.cmp-port-fact strong { font-weight: 800; color: var(--cmp-hero-ink); font-variant-numeric: tabular-nums; }
/* The phases, a tile each, and each tile the list's filter. A grid child names its track. */
.cmp-port-tiles { grid-column: 2; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.cmp-port-tile {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; min-height: 88px; padding: 14px 16px;
  cursor: pointer; font: inherit; text-align: left; color: var(--cmp-hero-ink); border-radius: 14px;
  transition: border-color .12s, transform .12s, background .12s, box-shadow .12s;
}
.cmp-port-tile:hover:not(:disabled) { transform: translateY(-1px); border-color: color-mix(in srgb, var(--cmp-hero-ink) 45%, transparent); }
.cmp-port-tile[aria-pressed="true"] { background: color-mix(in srgb, var(--accent) 22%, var(--cmp-hero-ground)); border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-port-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-port-tile:disabled { cursor: default; opacity: .6; }
.cmp-port-tile-n { font-size: 30px; font-weight: 800; line-height: 1; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.cmp-port-tile-lb { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 600; color: var(--cmp-hero-soft); }
.cmp-port-tile-lb::before {
  content: ''; flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--cmp-ph); box-shadow: 0 0 0 2px color-mix(in srgb, var(--cmp-hero-ink) 28%, transparent);
}

/* ---- what waits for the client ---- */
.cmp-waiting {
  padding: 20px 22px 22px; border: 1px solid var(--accent-line); border-radius: 16px; box-shadow: var(--shadow-1);
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 7%, var(--panel)), var(--panel) 140px);
}
.cmp-waiting-head { display: flex; align-items: center; gap: 14px; margin: 0 0 14px; }
.cmp-waiting-ic { display: grid; place-items: center; flex: none; width: 42px; height: 42px; border-radius: 12px; color: var(--on-accent); background: var(--accent); }
.cmp-waiting-words { min-width: 0; }
.cmp-waiting-title { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
.cmp-waiting-sub { margin: 2px 0 0; font-size: 13.5px; color: var(--muted); }
.cmp-waiting-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.cmp-waiting-row { display: flex; align-items: center; gap: 14px; padding: 12px 14px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; }
.cmp-waiting-mark { display: grid; place-items: center; flex: none; width: 38px; height: 38px; border-radius: 50%; color: var(--accent-ink); background: var(--accent-soft); }
.cmp-waiting-text { flex: 1; min-width: 0; }
.cmp-waiting-name { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.cmp-waiting-ask { margin: 2px 0 0; font-size: 13.5px; color: var(--muted); }
.cmp-waiting-go { display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex: none; min-height: 40px; }

/* ---- the list: its head, its bar, its cards ---- */
.cmp-hub-list { display: flex; flex-direction: column; gap: 14px; scroll-margin-top: 12px; }
.cmp-hub-list-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 14px; }
.cmp-hub-h2 { margin: 0; font-size: 20px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
.cmp-hub-found { margin: 0; font-size: 13.5px; color: var(--muted); }
.cmp-hub-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.cmp-hub-filter { display: inline-flex; align-items: center; gap: 7px; }
.cmp-hub-filter-n {
  min-width: 20px; padding: 0 6px; font-size: 11.5px; font-weight: 700; line-height: 18px; text-align: center;
  color: var(--muted); background: var(--panel-3); border-radius: 999px; font-variant-numeric: tabular-nums;
}
.cmp-hub-filter[aria-pressed="true"] .cmp-hub-filter-n { color: var(--accent-ink); background: var(--accent-soft); }
.cmp-hub-sort { display: inline-flex; align-items: center; gap: 8px; margin: 0 0 0 auto; font-size: 13px; font-weight: 600; color: var(--muted); }
.cmp-hub-sort select.cmp-hub-select {
  width: auto; min-height: 38px; margin: 0; padding: 6px 12px; cursor: pointer;
  font: inherit; font-size: 13.5px; font-weight: 600; color: var(--ink); background-color: var(--panel);
  border: 1px solid var(--border); border-radius: 10px;
}
.cmp-hub-sort select.cmp-hub-select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.cmp-hub-search {
  display: flex; align-items: center; gap: 8px; flex: 1 1 220px; max-width: 320px; min-height: 38px; margin: 0; padding: 0 12px;
  color: var(--muted); background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.cmp-hub-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-hub-search input.cmp-hub-q {
  flex: 1; min-width: 0; margin: 0; padding: 8px 0; font: inherit; font-size: 14px; color: var(--ink);
  background: none; border: 0; box-shadow: none; outline: none;
}
.cmp-hub-none {
  grid-column: 1 / -1; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 28px;
  text-align: center; color: var(--muted); background: var(--panel-2); border: 1px dashed var(--border); border-radius: 14px;
}
.cmp-hub-none > p { margin: 0; }

/* A card wears its phase on its top edge; everything else on it is words beside marks. */
.cmp-card[data-phase] { box-shadow: inset 0 3px 0 var(--cmp-ph); transition: border-color .13s, box-shadow .13s, transform .13s; }
.cmp-card[data-phase]:hover { transform: translateY(-2px); box-shadow: inset 0 3px 0 var(--cmp-ph), var(--shadow-2); }
.cmp-card[data-phase]:has(.cmp-card-open:focus-visible) { box-shadow: inset 0 3px 0 var(--cmp-ph), 0 0 0 1px var(--accent); }
.cmp-card-stage { display: flex; align-items: center; gap: 10px; min-width: 0; }
.cmp-card-stage-marks { display: flex; flex: none; gap: 3px; margin: 0; padding: 0; list-style: none; }
.cmp-card-stage-mark { width: 14px; height: 6px; border-radius: 3px; background: var(--panel-3); }
.cmp-card-stage-mark[data-state="done"] { background: color-mix(in srgb, var(--cmp-ph, var(--accent)) 45%, var(--panel)); }
.cmp-card-stage-mark[data-state="now"] { width: 24px; background: var(--cmp-ph, var(--accent)); }
.cmp-card-stage-lb { margin: 0; min-width: 0; font-size: 12.5px; font-weight: 600; color: var(--text); }
.cmp-card-flight { display: flex; align-items: center; gap: 10px; }
.cmp-card-flight-track { position: relative; flex: 1; min-width: 40px; height: 6px; border-radius: 3px; background: var(--panel-3); }
.cmp-card-flight-gone { position: absolute; inset: 0 auto 0 0; border-radius: 3px; background: color-mix(in srgb, var(--ink) 34%, var(--panel-3)); }
.cmp-card-flight-now {
  position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
  background: var(--panel); border: 3px solid var(--cmp-ph, var(--accent));
}
.cmp-card-flight-lb { flex: none; margin: 0; font-size: 12.5px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
.cmp-card-mix { display: flex; flex-direction: column; gap: 7px; }
.cmp-card-mix-bar { display: flex; gap: 2px; height: 10px; overflow: hidden; border-radius: 5px; background: var(--panel-3); }
.cmp-card-mix-seg { flex: 1 1 0; min-width: 3px; background: var(--cmp-c); }
.cmp-card-mix-names { display: flex; flex-wrap: wrap; gap: 4px 12px; margin: 0; padding: 0; list-style: none; font-size: 12.5px; color: var(--muted); }
.cmp-card-mix-name { display: inline-flex; align-items: center; gap: 6px; }
.cmp-card-mix-name strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-card-mix-note { margin: 0; font-size: 12.5px; color: var(--muted); }
.cmp-card-delivery { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 6px 10px; }
.cmp-card-delivery > .cmp-meter { grid-column: 1; grid-row: 1; }
.cmp-card-delivery > .cmp-card-pct { grid-column: 2; grid-row: 1; font-size: 13px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-card-delivery > .cmp-card-figure { grid-column: 1 / -1; grid-row: 2; }
.cmp-card-facts {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin: auto 0 0; padding: 12px 0 0;
  border-top: 1px solid var(--border);
}
.cmp-card-fact { min-width: 0; }
.cmp-card-fact > dt { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.cmp-card-fact > dd { margin: 2px 0 0; font-size: 14.5px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.cmp-card[data-phase] .cmp-card-turn {
  display: inline-flex; align-items: center; gap: 4px; align-self: flex-start; padding: 4px 8px 4px 12px;
  background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: 999px;
}

/* ---- the flights on one calendar ---- */
.cmp-flights-legend { margin: -4px 0 16px; }
.cmp-fl-key { background: color-mix(in srgb, var(--cmp-ph) 24%, var(--panel)); box-shadow: inset 0 0 0 1.5px var(--cmp-ph); }
.cmp-fl-key-fill { background: linear-gradient(90deg, var(--text) 50%, var(--panel-3) 50%); box-shadow: inset 0 0 0 1px var(--border); }
.cmp-fl { --fl-name: 190px; --fl-gap: 14px; position: relative; }
.cmp-fl-over { position: absolute; top: 0; bottom: 0; left: calc(var(--fl-name) + var(--fl-gap)); right: 0; z-index: 2; pointer-events: none; }
.cmp-fl-line { position: absolute; top: 18px; bottom: 0; border-left: 1px dashed var(--border); }
.cmp-fl-now { position: absolute; top: 0; bottom: 0; border-left: 2px solid var(--accent); }
.cmp-fl-now-lb {
  position: absolute; top: 0; left: 0; transform: translateX(-50%); padding: 1px 8px; white-space: nowrap;
  font-size: 11px; font-weight: 700; line-height: 16px; color: var(--on-accent); background: var(--accent); border-radius: 999px;
}
.cmp-fl-row { position: relative; z-index: 1; display: grid; grid-template-columns: var(--fl-name) minmax(0, 1fr); align-items: center; gap: var(--fl-gap); }
.cmp-fl-head { margin: 0 0 6px; }
.cmp-fl-track { position: relative; min-width: 0; height: 40px; }
.cmp-fl-head .cmp-fl-track { height: 38px; }
.cmp-fl-month {
  position: absolute; bottom: 2px; padding: 0 0 0 6px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  font-size: 11.5px; font-weight: 700; color: var(--muted);
}
.cmp-fl-rows { display: grid; gap: 8px; margin: 0; padding: 0 0 4px; list-style: none; }
.cmp-fl-name { display: flex; flex-direction: column; min-width: 0; }
.cmp-fl-title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 13.5px; font-weight: 700; color: var(--ink); }
.cmp-fl-sub { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 12px; color: var(--muted); }
.cmp-fl-bar {
  position: absolute; top: 50%; height: 28px; min-width: 10px; margin: -14px 0 0; padding: 0; overflow: hidden; cursor: pointer;
  background: color-mix(in srgb, var(--cmp-ph) 24%, var(--panel)); border: 1.5px solid var(--cmp-ph); border-radius: 8px;
  transition: transform .12s, box-shadow .12s;
}
.cmp-fl-bar:hover { transform: translateY(-1px); box-shadow: var(--shadow-2); }
.cmp-fl-bar:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-fl-fill { position: absolute; inset: 0 auto 0 0; background: var(--cmp-ph); }
.cmp-fl-tip { z-index: 6; }

/* ---- the channels, every campaign together ---- */
.cmp-hub-mix-body { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 12px 24px; }
.cmp-donut-slice.team { fill: color-mix(in srgb, var(--muted) 34%, var(--panel)); }
.cmp-swatch.team { background: color-mix(in srgb, var(--muted) 34%, var(--panel)); box-shadow: inset 0 0 0 1px var(--muted); }
.cmp-split-row[data-team="true"].on { background: var(--panel-2); }
.cmp-hub-mix-note { margin: 14px 0 0; }

/* ---- how it works: the opening band and the three capabilities ---- */
.cmp-guide-top { display: flex; flex-direction: column; gap: 14px; }
.cmp-guide-hero { padding: 36px 36px 32px; }
.cmp-guide-eyebrow { display: flex; align-items: center; gap: 7px; margin: 0 0 14px; font-size: 13px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: var(--cmp-hero-soft); }
.cmp-guide-title { max-width: 24ch; margin: 0; font-size: 40px; font-weight: 800; line-height: 1.06; letter-spacing: -.035em; color: var(--cmp-hero-ink); text-wrap: balance; }
.cmp-guide-lede { max-width: 66ch; margin: 14px 0 0; font-size: 16px; line-height: 1.55; color: var(--cmp-hero-soft); }
.cmp-guide-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 26px 0 0; padding: 0; list-style: none; }
.cmp-guide-fact { display: flex; flex-direction: column; gap: 4px; min-width: 0; padding: 14px 16px; border-radius: 14px; }
.cmp-guide-fact > strong { font-size: 28px; font-weight: 800; line-height: 1.05; letter-spacing: -.02em; color: var(--cmp-hero-ink); }
.cmp-guide-fact > span { font-size: 13px; line-height: 1.35; color: var(--cmp-hero-soft); }
.cmp-pillars { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin: 0; padding: 0; list-style: none; }
.cmp-pillar { display: flex; flex-direction: column; gap: 8px; min-width: 0; padding: 20px; background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-1); }
.cmp-pillar-ic { display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; color: var(--accent-ink); background: var(--accent-soft); }
.cmp-pillar-title { margin: 4px 0 0; font-size: 16.5px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
.cmp-pillar-text { margin: 0; font-size: 14px; line-height: 1.5; color: var(--text); }

/* The guide's ask, on its band: the button that leads to the card at the end of the page. */
.cmp-guide-acts { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 0; }
/* `.btn` doubled into the selector: the base `.btn.primary` is two classes, and would win. */
.btn.cmp-guide-go, .btn.cmp-call-go {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 46px; padding: 10px 20px;
  font-size: 15px; font-weight: 700; text-decoration: none;
  color: var(--on-accent); background: var(--accent); border-color: var(--accent); border-radius: 12px;
}
/* Hover lifts it rather than recolouring it: `--on-accent` was measured against the accent
   itself, by the skin when an agency chose it, and against nothing else. */
.btn.cmp-guide-go, .btn.cmp-call-go { transition: transform .12s, box-shadow .12s; }
.btn.cmp-guide-go:hover, .btn.cmp-call-go:hover {
  color: var(--on-accent); background: var(--accent); border-color: var(--accent);
  transform: translateY(-1px); box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 38%, transparent);
}
.btn.cmp-guide-go:focus-visible, .btn.cmp-call-go:focus-visible { outline: 2px solid var(--cmp-hero-ink, var(--ink)); outline-offset: 3px; }

/* ---- «Contact us»: the guide's last card ----
   The band's ground and ink, as above; what the client acts on — the button, the form, the
   answer — sits on a card of the page's own surface inside it, so a field reads as a field. */
.cmp-call {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 420px); align-items: center; gap: 24px 36px;
  padding: 32px 34px; scroll-margin: 24px;
}
.cmp-call-words { grid-column: 1; min-width: 0; }
.cmp-call-eyebrow { display: flex; align-items: center; gap: 7px; margin: 0 0 12px; font-size: 13px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: var(--cmp-hero-soft); }
.cmp-call-title { margin: 0; font-size: 30px; font-weight: 800; line-height: 1.1; letter-spacing: -.03em; color: var(--cmp-hero-ink); text-wrap: balance; }
.cmp-call-sub { max-width: 60ch; margin: 12px 0 0; font-size: 15.5px; line-height: 1.55; color: var(--cmp-hero-soft); }
.cmp-call-next { display: grid; gap: 8px; margin: 18px 0 0; padding: 0; list-style: none; counter-reset: cmp-call; }
.cmp-call-next > li {
  display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 600; color: var(--cmp-hero-ink);
  counter-increment: cmp-call;
}
.cmp-call-next > li::before {
  content: counter(cmp-call); display: grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: 50%;
  font-size: 12.5px; font-weight: 800; color: var(--on-accent); background: var(--accent);
}
.cmp-call-act {
  grid-column: 2; display: flex; flex-direction: column; align-items: stretch; gap: 12px; min-width: 0; padding: 20px;
  color: var(--text); background: var(--panel); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-2);
}
.cmp-call-act > .btn.cmp-call-go { width: 100%; }
.cmp-call-hint { margin: 0; text-align: center; overflow-wrap: anywhere; }
.cmp-call-form { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.cmp-call-label { margin: 0; font-size: 13.5px; font-weight: 700; color: var(--text); }
.cmp-call-form textarea.cmp-call-message {
  width: 100%; min-height: 110px; margin: 0; padding: 10px 12px; resize: vertical;
  font: inherit; font-size: 14.5px; line-height: 1.45; color: var(--ink);
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
}
.cmp-call-form textarea.cmp-call-message:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.cmp-call-err { margin: 0; }
.cmp-call-buttons { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; }
.cmp-call-sent { display: flex; align-items: flex-start; gap: 12px; }
.cmp-call-sent:focus { outline: none; }
.cmp-call-sent:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 8px; }
.cmp-call-sent-ic { display: grid; place-items: center; flex: none; width: 40px; height: 40px; border-radius: 50%; color: var(--ok); background: var(--ok-soft); }
.cmp-call-sent-words { min-width: 0; }
.cmp-call-sent-title { margin: 2px 0 0; font-size: 16px; font-weight: 800; color: var(--ink); }
.cmp-call-sent-sub { margin: 4px 0 0; font-size: 14px; line-height: 1.45; color: var(--text); }
.cmp-call-quote {
  margin: 10px 0 0; padding: 8px 12px; font-size: 13.5px; line-height: 1.45; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere;
  background: var(--panel-2); border-left: 3px solid var(--accent-line); border-radius: 0 8px 8px 0;
}
.cmp-call-again { align-self: flex-start; }

/* ---- the five stages: a rail of buttons and the one chosen, read out ---- */
.cmp-stage-rail {
  --cmp-stage-at: 0; position: relative; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px;
  margin: 0 0 16px; padding: 0; list-style: none;
}
/* The line under the five, and the part of it behind the stage being read. */
.cmp-stage-rail::before, .cmp-stage-rail::after { content: ''; position: absolute; top: 33px; left: 10%; height: 3px; border-radius: 2px; }
.cmp-stage-rail::before { right: 10%; background: var(--panel-3); }
.cmp-stage-rail::after { width: calc(80% * var(--cmp-stage-at) / 4); background: var(--accent); transition: width .3s cubic-bezier(.2, .8, .2, 1); }
.cmp-stage-item { position: relative; z-index: 1; display: flex; min-width: 0; }
.cmp-stage-btn {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; padding: 12px 6px 14px;
  cursor: pointer; font: inherit; text-align: center; color: var(--text); background: none; border: 1px solid transparent; border-radius: 14px;
  transition: background .12s, border-color .12s;
}
.cmp-stage-btn:hover { background: var(--panel-2); }
.cmp-stage-btn[aria-pressed="true"] { background: color-mix(in srgb, var(--accent) 7%, var(--panel)); border-color: var(--accent-line); }
.cmp-stage-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-stage-n { display: none; }
.cmp-stage-ic {
  display: grid; place-items: center; width: 44px; height: 44px; border-radius: 50%;
  color: var(--muted); background: var(--panel); border: 2px solid var(--border); transition: background .2s, color .2s, box-shadow .2s;
}
.cmp-stage-btn[data-state="before"] .cmp-stage-ic { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
.cmp-stage-btn[data-state="now"] .cmp-stage-ic { color: var(--on-accent); background: var(--accent); border-color: var(--accent); box-shadow: 0 0 0 5px var(--accent-soft); }
.cmp-stage-words { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cmp-stage-k { font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.cmp-stage-name { font-size: 13.5px; font-weight: 700; line-height: 1.25; color: var(--ink); overflow-wrap: anywhere; }
.cmp-stage-count {
  position: absolute; top: 6px; left: calc(50% + 14px); min-width: 20px; height: 20px; padding: 0 6px;
  font-size: 11.5px; font-weight: 800; line-height: 20px; text-align: center;
  color: var(--on-solid); background: var(--solid); border-radius: 999px; box-shadow: 0 0 0 2px var(--panel);
}
.cmp-stage-panel { padding: 22px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 16px; }
.cmp-stage-panel > * { animation: cmp-fade .3s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes cmp-fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.cmp-stage-head { display: flex; align-items: flex-start; gap: 16px; margin: 0 0 18px; }
.cmp-stage-big { display: grid; place-items: center; flex: none; width: 50px; height: 50px; border-radius: 14px; color: var(--on-accent); background: var(--accent); }
.cmp-stage-head .cmp-stage-k { margin: 0; }
.cmp-stage-title { margin: 2px 0 0; font-size: 21px; font-weight: 800; letter-spacing: -.015em; color: var(--ink); }
.cmp-stage-lede { max-width: 72ch; margin: 6px 0 0; font-size: 15px; line-height: 1.5; color: var(--text); }
.cmp-stage-cols { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 14px; }
.cmp-stage-col { min-width: 0; padding: 16px 18px; background: var(--panel); border: 1px solid var(--border); border-radius: 12px; }
.cmp-stage-col-title { margin: 0 0 12px; font-size: 12px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; color: var(--muted); }
.cmp-stage-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.cmp-stage-list > li { display: flex; align-items: flex-start; gap: 9px; font-size: 14px; line-height: 1.45; color: var(--text); }
.cmp-stage-list .sd-ic { flex: none; margin-top: 2px; color: var(--accent-ink); }
.cmp-stage-col:last-child .sd-ic { color: var(--ok); }
.cmp-stage-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 18px; margin: 16px 0 0; }
.cmp-stage-where { margin: 0; font-size: 13px; font-weight: 600; color: var(--muted); }
.cmp-stage-mine { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cmp-stage-mine-lb { font-size: 13px; font-weight: 600; color: var(--muted); }
.cmp-stage-chip {
  display: inline-flex; align-items: center; gap: 4px; min-height: 34px; padding: 4px 8px 4px 12px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 700; color: var(--accent-ink);
  background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: 999px;
}
.cmp-stage-chip:hover { border-color: var(--accent); }
.cmp-stage-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cmp-stage-none { margin: 0; font-size: 13px; color: var(--muted); }

/* ---- the reach the planning is for: the model ---- */
.cmp-reach-body { display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 1fr); align-items: start; gap: 24px; }
.cmp-reach-controls {
  grid-column: 1; display: flex; flex-direction: column; gap: 22px; min-width: 0; padding: 18px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 14px;
}
.cmp-reach-out { grid-column: 2; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.cmp-reach-field { display: flex; flex-direction: column; gap: 10px; }
.cmp-reach-field-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.cmp-reach-label { margin: 0; font-size: 13px; font-weight: 700; color: var(--text); }
.cmp-reach-value { font-size: 20px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-slider { display: block; width: 100%; margin: 0; cursor: pointer; accent-color: var(--accent); }
.cmp-slider-ch { accent-color: var(--cmp-c, var(--accent)); }
.cmp-slider:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.cmp-reach-shares { display: flex; flex-direction: column; gap: 12px; margin: 4px 0 0; }
.cmp-reach-share-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 6px; }
.cmp-reach-share-name { display: inline-flex; align-items: center; gap: 8px; margin: 0; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.cmp-reach-share-pct { font-size: 13px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-reach-share-bar { height: 8px; overflow: hidden; border-radius: 4px; background: var(--panel-3); }
.cmp-reach-share-bar > span { display: block; height: 100%; border-radius: 0 4px 4px 0; background: var(--cmp-c); }
.cmp-reach-lift {
  display: flex; align-items: center; gap: 18px; min-height: 84px; padding: 16px 20px; border: 1px solid var(--accent-line); border-radius: 14px;
  background: linear-gradient(120deg, color-mix(in srgb, var(--accent) 10%, var(--panel)), var(--panel));
}
.cmp-reach-lift-value { flex: none; margin: 0; font-size: 46px; font-weight: 800; line-height: 1; letter-spacing: -.03em; color: var(--accent-ink); font-variant-numeric: tabular-nums; }
.cmp-reach-lift-value[data-dir="down"] { color: var(--warn); }
.cmp-reach-lift-value[data-dir="same"] { color: var(--muted); }
.cmp-reach-lift-text { margin: 0; font-size: 15px; font-weight: 600; line-height: 1.45; color: var(--ink); }
.cmp-reach-compare { display: grid; gap: 10px; }
.cmp-reach-row { display: grid; grid-template-columns: minmax(0, 170px) minmax(0, 1fr) auto; align-items: center; gap: 12px; }
.cmp-reach-row-lb { font-size: 13.5px; font-weight: 600; color: var(--text); }
.cmp-reach-bar { height: 14px; overflow: hidden; border-radius: 7px; background: var(--panel-3); }
.cmp-reach-bar > span { display: block; height: 100%; border-radius: 0 7px 7px 0; background: var(--muted); transition: width .35s cubic-bezier(.2, .8, .2, 1); }
.cmp-reach-row[data-kind="split"] .cmp-reach-bar > span { background: var(--chart-1); }
.cmp-reach-row-value { min-width: 120px; font-size: 14px; font-weight: 800; text-align: right; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-reach-chart .cmp-chart-scroll { min-height: 270px; }
.cmp-reach-curve { fill: none; stroke: var(--cmp-c); stroke-width: 1.5; stroke-dasharray: 4 4; opacity: .6; }
.cmp-reach-used { fill: none; stroke: var(--cmp-c); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
.cmp-reach-dot { fill: var(--cmp-c); stroke: var(--panel); stroke-width: 2; }
.cmp-reach-ring { fill: var(--panel); stroke: var(--cmp-c); stroke-width: 2.5; }
.cmp-reach-mark { fill: var(--ink); font-size: 12px; font-weight: 700; }
.cmp-reach-legend { margin: 0; }
.cmp-reach-note { margin: 18px 0 0; max-width: 92ch; line-height: 1.5; }

/* ---- where the ads run: the channels as their platforms and their placements ----
   Five in a row where there is room; then three over two on a grid of six, so the second
   row is filled rather than left with a hole; then two, the last across both; then one. */
.cmp-where-list { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 14px; margin: 0; padding: 0; list-style: none; }
.cmp-where-item {
  display: flex; flex-direction: column; min-width: 0; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 16px;
  transition: transform .15s, box-shadow .15s, border-color .15s;
}
.cmp-where-item:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--cmp-c) 45%, var(--border)); }
.cmp-where-stage {
  display: flex; align-items: flex-end; justify-content: center; padding: 12px 0 0; overflow: hidden;
  background: radial-gradient(120% 95% at 50% 100%, color-mix(in srgb, var(--cmp-c) 34%, var(--panel)) 0%, color-mix(in srgb, var(--cmp-c) 10%, var(--panel)) 62%, var(--panel) 100%);
  border-bottom: 1px solid var(--border);
}
/* As wide as the tile and as tall as its drawing, up to a height a tile two columns wide
   would otherwise double: past it the drawing is centred in its own box. */
.cmp-where-shot { display: block; width: 100%; height: auto; max-height: 220px; aspect-ratio: 10 / 7; }
.cmp-where-device { filter: drop-shadow(0 6px 12px rgb(0 0 0 / .18)); }
.cmp-where-slot { fill: none; stroke: var(--cmp-c); stroke-width: 2; }
.cmp-where-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding: 14px 16px 0; }
.cmp-where-marks { display: inline-flex; align-items: center; gap: 6px; }
.cmp-where-logo { display: block; flex: none; fill: var(--ink); }
.cmp-where-ic { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 8px; color: #fff; background: var(--cmp-c); }
.cmp-where-name { margin: 0; font-size: 16px; font-weight: 800; letter-spacing: -.01em; color: var(--ink); }
.cmp-where-text { margin: 6px 0 0; padding: 0 16px 16px; font-size: 13.5px; line-height: 1.5; color: var(--text); }
.cmp-where-note { margin: 14px 0 0; }

/* ---- a creative for every placement ---- */
.cmp-formats-filter { margin: 0 0 14px; }
.cmp-fmt-list { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.cmp-fmt {
  display: grid; grid-template-columns: 68px minmax(0, 1fr) minmax(0, 240px); align-items: center; gap: 16px; padding: 14px 16px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 14px; animation: cmp-fade .3s cubic-bezier(.2, .8, .2, 1) both;
}
.cmp-fmt-glyph { position: relative; display: flex; align-items: center; justify-content: center; gap: 3px; width: 68px; height: 64px; }
.cmp-fmt-frame {
  display: grid; place-items: center; font-size: 10.5px; font-weight: 800; color: var(--ink);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel)); border: 2px solid var(--ink); border-radius: 6px;
}
.cmp-fmt-glyph[data-ratio="9:16"] .cmp-fmt-frame, .cmp-fmt-glyph[data-ratio="4:5"] .cmp-fmt-frame, .cmp-fmt-glyph[data-ratio="1:1"] .cmp-fmt-frame { height: 58px; }
.cmp-fmt-glyph[data-ratio="16:9"] .cmp-fmt-frame { width: 64px; }
.cmp-fmt-glyph[data-ratio="multi"] .cmp-fmt-frame { border-width: 1.5px; border-radius: 4px; }
.cmp-fmt-glyph[data-ratio="multi"] .cmp-fmt-frame:nth-child(1) { height: 24px; }
.cmp-fmt-glyph[data-ratio="multi"] .cmp-fmt-frame:nth-child(2) { width: 30px; }
.cmp-fmt-glyph[data-ratio="multi"] .cmp-fmt-frame:nth-child(3) { height: 32px; }
.cmp-fmt-glyph[data-ratio="stack"] .cmp-fmt-frame { position: absolute; height: 42px; }
.cmp-fmt-glyph[data-ratio="stack"] .cmp-fmt-frame:nth-child(1) { transform: translate(-11px, -7px); opacity: .45; }
.cmp-fmt-glyph[data-ratio="stack"] .cmp-fmt-frame:nth-child(2) { opacity: .7; }
.cmp-fmt-glyph[data-ratio="stack"] .cmp-fmt-frame:nth-child(3) { transform: translate(11px, 7px); }
.cmp-fmt-words { min-width: 0; }
.cmp-fmt-title { margin: 0; font-size: 15px; font-weight: 800; color: var(--ink); }
.cmp-fmt-shape { margin: 3px 0 0; font-size: 13.5px; color: var(--text); }
.cmp-fmt-where { margin: 2px 0 0; font-size: 13px; color: var(--muted); }
.cmp-fmt-channels { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin: 0; padding: 0; list-style: none; }
.cmp-fmt-channel {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; font-size: 12px; font-weight: 600; color: var(--ink);
  background: var(--panel); border: 1px solid color-mix(in srgb, var(--cmp-c) 45%, var(--border)); border-radius: 999px;
}

/* ---- one price, everything in it ---- */
.cmp-price-sum { display: flex; flex-wrap: wrap; align-items: stretch; gap: 14px 26px; }
.cmp-price-parts { flex: 1 1 520px; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 24px; margin: 0; padding: 0; list-style: none; }
.cmp-price-part {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 8px; min-width: 0; padding: 16px 10px;
  text-align: center; background: var(--panel-2); border: 1px solid var(--border); border-radius: 14px;
}
.cmp-price-part + .cmp-price-part::before {
  content: '+'; position: absolute; top: 50%; left: -18px; transform: translateY(-50%);
  font-size: 17px; font-weight: 800; color: var(--muted);
}
.cmp-price-ic { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; color: var(--accent-ink); background: var(--accent-soft); }
.cmp-price-lb { font-size: 13px; font-weight: 600; line-height: 1.3; color: var(--ink); overflow-wrap: anywhere; }
.cmp-price-total {
  flex: 0 1 240px; display: flex; flex-direction: column; justify-content: center; gap: 4px; padding: 16px 20px;
  color: var(--on-solid); background: var(--solid); border-radius: 14px; box-shadow: var(--shadow-2);
}
.cmp-price-eq { font-size: 20px; font-weight: 800; line-height: 1; color: color-mix(in srgb, var(--on-solid) 80%, var(--solid)); }
.cmp-price-one { font-size: 24px; font-weight: 800; letter-spacing: -.02em; }
.cmp-price-per { font-size: 12.5px; line-height: 1.4; color: color-mix(in srgb, var(--on-solid) 80%, var(--solid)); }
.cmp-price-notes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 16px 0 0; padding: 0; list-style: none; }
.cmp-price-note {
  display: flex; align-items: flex-start; gap: 10px; padding: 14px 16px; font-size: 14px; line-height: 1.45; color: var(--text);
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 12px;
}
.cmp-price-note .sd-ic { flex: none; margin-top: 1px; color: var(--ok); }

/* ---- what is delivered, and when ---- */
.cmp-moment-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin: 0; padding: 0; list-style: none; }
.cmp-moment { display: flex; flex-direction: column; gap: 14px; min-width: 0; padding: 18px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 14px; }
.cmp-moment-head { display: flex; align-items: center; gap: 10px; }
.cmp-moment-ic { display: grid; place-items: center; flex: none; width: 38px; height: 38px; border-radius: 11px; color: var(--violet-ink); background: var(--violet-soft); }
.cmp-moment[data-moment="during"] .cmp-moment-ic { color: var(--accent-ink); background: var(--accent-soft); }
.cmp-moment[data-moment="after"] .cmp-moment-ic { color: var(--ok); background: var(--ok-soft); }
.cmp-moment-title { margin: 0; font-size: 16px; font-weight: 800; color: var(--ink); }
.cmp-moment-items { display: grid; gap: 12px; margin: 0; padding: 0; list-style: none; }
.cmp-moment-item { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 9px; font-size: 13.5px; line-height: 1.45; color: var(--text); }
.cmp-moment-item > .sd-ic { margin-top: 2px; color: var(--ok); }
.cmp-moment-tag {
  grid-column: 2; justify-self: start; padding: 1px 9px; font-size: 11.5px; font-weight: 700; line-height: 1.5;
  color: var(--accent-ink); background: var(--accent-soft); border: 1px solid var(--accent-line); border-radius: 999px;
}

/* ---- a campaign's own page: the contract's split, and where its flight is ---- */
.cmp-fact-split { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.cmp-fact-channel { display: flex; align-items: center; gap: 7px; }
.cmp-fact-channel > strong { margin-left: auto; color: var(--ink); font-variant-numeric: tabular-nums; }
.cmp-meta-flight { font-weight: 600; color: var(--text); }

/* ---- the overview as the width runs out ---- */
@container cmp (max-width: 960px) {
  .cmp-port { grid-template-columns: minmax(0, 1fr); padding: 24px 22px; }
  .cmp-port-tiles { grid-column: 1; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .cmp-reach-body { grid-template-columns: minmax(0, 1fr); }
  .cmp-reach-controls, .cmp-reach-out { grid-column: 1; }
  .cmp-pillars, .cmp-moment-cols, .cmp-stage-cols { grid-template-columns: minmax(0, 1fr); }
  .cmp-guide-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cmp-price-parts { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 10px; }
  .cmp-price-part + .cmp-price-part::before { display: none; }
  .cmp-price-total { flex: 1 1 100%; }
  .cmp-fmt { grid-template-columns: 68px minmax(0, 1fr); }
  .cmp-fmt-channels { grid-column: 2; justify-content: flex-start; }
  .cmp-call { grid-template-columns: minmax(0, 1fr); padding: 26px 22px; }
  .cmp-call-act { grid-column: 1; }
  .cmp-where-list { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .cmp-where-item { grid-column: span 2; }
  .cmp-where-item:nth-last-child(-n+2) { grid-column: span 3; }
}
@container cmp (max-width: 640px) {
  .cmp-hub-tab { flex: 1 1 0; justify-content: center; padding: 8px 10px; font-size: 14px; }
  .cmp-port-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cmp-port-value { font-size: 40px; }
  .cmp-port-unit { font-size: 16px; }
  .cmp-waiting { padding: 16px; }
  .cmp-waiting-row { flex-wrap: wrap; }
  .cmp-waiting-go { flex: 1 1 100%; }
  .cmp-hub-sort { margin: 0; }
  .cmp-hub-filters { width: 100%; }
  .cmp-card-facts { gap: 6px; }
  /* The calendar a column wide: each name over its bar, the lines across both — and the
     name on the card's ground, above them, so today's line does not run through its words. */
  .cmp-fl { --fl-name: 0px; --fl-gap: 0px; }
  .cmp-fl-row { z-index: auto; grid-template-columns: minmax(0, 1fr); gap: 4px; }
  .cmp-fl-head > .cmp-fl-name { display: none; }
  .cmp-fl-rows > .cmp-fl-row > .cmp-fl-name { position: relative; z-index: 3; justify-self: start; max-width: 100%; padding: 0 8px 0 0; background: var(--panel); }
  .cmp-fl-rows > .cmp-fl-row > .cmp-fl-track { height: 32px; }
  .cmp-guide-hero { padding: 24px 20px; }
  .cmp-guide-title { font-size: 28px; }
  .btn.cmp-guide-go { width: 100%; }
  .cmp-call { padding: 22px 16px; }
  .cmp-call-title { font-size: 24px; }
  .cmp-call-act { padding: 16px; }
  .cmp-guide-lede { font-size: 15px; }
  .cmp-guide-fact > strong { font-size: 22px; }
  /* Five stages in a phone's width: their icons on the rail, the names in the panel under it. */
  .cmp-stage-rail { gap: 2px; }
  .cmp-stage-rail::before, .cmp-stage-rail::after { top: 31px; }
  .cmp-stage-btn { padding: 10px 2px 8px; }
  .cmp-stage-ic { width: 40px; height: 40px; }
  .cmp-stage-words { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .cmp-stage-panel { padding: 16px; }
  .cmp-stage-head { flex-direction: column; gap: 10px; }
  .cmp-stage-big { width: 42px; height: 42px; }
  .cmp-reach-lift { flex-direction: column; align-items: flex-start; gap: 8px; }
  .cmp-reach-lift-value { font-size: 38px; }
  .cmp-reach-row { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 10px; }
  .cmp-reach-row-lb { grid-column: 1 / -1; }
  .cmp-reach-row-value { min-width: 0; }
  .cmp-price-notes { grid-template-columns: minmax(0, 1fr); }
  .cmp-fmt { grid-template-columns: 56px minmax(0, 1fr); gap: 12px; padding: 12px; }
  .cmp-fmt-glyph { width: 56px; }
  .cmp-where-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .cmp-where-item, .cmp-where-item:nth-last-child(-n+2) { grid-column: auto; }
  .cmp-where-item:last-child:nth-child(odd) { grid-column: 1 / -1; }
  .cmp-where-head { padding: 12px 12px 0; }
  .cmp-where-text { padding: 0 12px 12px; font-size: 13px; }
}
/* A phone: the two tabs side by side on one line each, without their icons. */
@container cmp (max-width: 420px) {
  .cmp-hub-tab { gap: 6px; padding: 8px 6px; white-space: nowrap; font-size: 13.5px; }
  .cmp-hub-tab > .sd-ic { display: none; }
  .cmp-guide-facts { grid-template-columns: minmax(0, 1fr); }
  .cmp-guide-fact { flex-direction: row; align-items: baseline; gap: 10px; }
  .cmp-where-list { grid-template-columns: minmax(0, 1fr); }
}
@media (prefers-reduced-motion: reduce) {
  .cmp-where-item { transition: none; }
  .cmp-where-item:hover { transform: none; }
  .cmp-card[data-phase], .cmp-port-tile, .cmp-fl-bar, .cmp-stage-btn, .cmp-stage-ic, .cmp-hub-tab, .cmp-reach-bar > span, .cmp-stage-rail::after { transition: none; }
  .cmp-card[data-phase]:hover, .cmp-port-tile:hover:not(:disabled), .cmp-fl-bar:hover { transform: none; }
  .cmp-stage-panel > *, .cmp-fmt { animation: none; }
  .btn.cmp-guide-go, .btn.cmp-call-go { transition: none; }
  .btn.cmp-guide-go:hover, .btn.cmp-call-go:hover { transform: none; }
}

/* ---- as the width runs out ---- */
/* The second card of a pair under the first rather than beside it, once the first would be squeezed. */
@container cmp (max-width: 1080px) {
  .cmp-duo, .cmp-duo.cmp-duo-mix { grid-template-columns: minmax(0, 1fr); }
  .cmp-duo > :nth-child(2) { grid-column: 1; }
}
/* The newest note across two of the notes' columns, where there are two. */
@container cmp (min-width: 760px) {
  .cmp-memo.latest { grid-column: span 2; }
}
@container cmp (max-width: 900px) {
  .cmp-brief-grid { grid-template-columns: minmax(0, 1fr); }
  .cmp-brief-grid > .cmp-contract { grid-column: 1; grid-row: 1; position: static; }
  .cmp-brief-grid > .cmp-brief-main { grid-column: 1; grid-row: 2; }
  /* The hero's figure under its words, on the left like them. */
  .cmp-hero { grid-template-columns: minmax(0, 1fr); padding: 24px 22px; }
  .cmp-hero-figure { grid-column: 1; align-items: flex-start; min-width: 0; text-align: left; }
}
/* The calendar a column wide: the days on top, the ranges under them as a row of choices,
   and the whole card under the bar's row, from edge to edge. */
@container cmp (max-width: 640px) {
  .cmp-range { position: static; }
  .cmp-range-pop { left: 0; right: 0; width: auto; max-width: none; grid-template-columns: minmax(0, 1fr); grid-template-areas: "cal" "presets" "foot"; }
  .cmp-range-presets { display: flex; flex-wrap: wrap; gap: 4px; max-height: none; border-right: 0; border-top: 1px solid var(--border); }
  .cmp-range-presets > li { flex: 1 1 140px; }
  .cmp-cal-grid th { width: 36px; }
  .cmp-cal-day { width: 36px; }
  .cmp-notes { padding: 16px; }
  .cmp-notes-head { flex-wrap: wrap; }
}
@container cmp (max-width: 600px) {
  .cmp-card { padding: 16px; }
  .cmp-step { gap: 8px; min-height: 48px; padding: 6px 10px; }
  .cmp-step-k { display: none; }
  .cmp-step-n { width: 28px; height: 28px; font-size: 13px; }
  .cmp-step-name { font-size: 14px; }
  .cmp-steps { gap: 16px; }
  .cmp-step-item + .cmp-step-item::before { left: -12px; width: 8px; }
  .cmp-readonly { grid-template-columns: minmax(0, 1fr); }
  .cmp-readonly dt { padding: 12px 0 2px; border-bottom: 0; }
  .cmp-readonly dd { padding-top: 0; }
  .cmp-actions > .btn { flex: 1 1 auto; }
  /* Two tiles to a row: one each is five screens of scrolling for five numbers. */
  .cmp-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .cmp-kpi { padding: 12px 14px; }
  .cmp-kpi-value { font-size: 22px; }
  .cmp-kpi .cmp-spark { width: calc(100% + 28px); margin: 2px -14px -12px; }
  /* Half a phone's width is too narrow for an icon and «Visualizzazioni» side by side. */
  .cmp-kpi-top { flex-direction: column; align-items: flex-start; gap: 6px; }
  /* The bar stays on top on a phone too, so it is one row: the range, and the export as its
     icon — the quick ranges are in the calendar, and the export's name stays for readers. */
  .cmp-filters-row > .cmp-seg { display: none; }
  .cmp-export { justify-content: center; min-width: 46px; min-height: 46px; padding: 0 12px; }
  .cmp-export > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .cmp-hero-value { font-size: 44px; }
  .cmp-hero-unit { font-size: 17px; }
  .cmp-hero-goal { font-size: 30px; }
  /* The longest label no longer sets the column: «Guaranteed impressions» wraps, the value breathes. */
  .cmp-facts { grid-template-columns: minmax(0, 40%) minmax(0, 1fr); }
}
/* A phone: the three steps stand their number over their name, so all three still fit. */
@container cmp (max-width: 420px) {
  .cmp-steps { gap: 6px; }
  .cmp-step-item + .cmp-step-item::before { display: none; }
  .cmp-step { flex-direction: column; justify-content: center; gap: 4px; padding: 8px 4px; text-align: center; }
  .cmp-step-lb { align-items: center; max-width: 100%; }
  .cmp-step-name { font-size: 13px; }
}
@media (prefers-reduced-motion: reduce) {
  .cmp-card, .cmp-step, .cmp-chart-seg, .cmp-bar > span, .cmp-seg-btn, .cmp-top-item, .cmp-top-go .sd-ic,
  .cmp-switch, .cmp-range-btn, .cmp-range-caret, .cmp-donut-slice, .cmp-split-row { transition: none; }
  .cmp-chart-svg.rise .cmp-chart-day, .cmp-chart-svg.rise .cmp-chart-line, .cmp-donut-svg.rise .cmp-donut-slice, .cmp-range-pop { animation: none; }
  .cmp-chart-svg.rise .cmp-chart-line { stroke-dasharray: none; }
}

/* ============================== HELP AND SUPPORT ==============================
   `app/js/support.js`: the client's requests on the left, the form or one thread on the
   right. The two columns are named tracks, and the pane never hides — the form is what
   it shows when no request is open — so neither can slide onto the other's track. */
.sup-view { container: sup / inline-size; padding: 10px 8px 36px; }
.sup-view > * { max-width: 1220px; }
.sup-body { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: 18px; align-items: start; }
.sup-body > .sup-list { grid-column: 1; }
.sup-body > .sup-pane { grid-column: 2; }
.sup-body > .bk-card + .bk-card { margin-top: 0; }
@container sup (max-width: 760px) {
  .sup-body { grid-template-columns: minmax(0, 1fr); }
  .sup-body > .sup-list, .sup-body > .sup-pane { grid-column: 1; }
}
.sup-list-head, .sup-thread-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin: 0 0 14px; }
.sup-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.sup-item {
  display: grid; gap: 4px; width: 100%; padding: 10px 12px; cursor: pointer; font: inherit; text-align: left; color: var(--text);
  background: none; border: 1px solid var(--border); border-radius: 10px;
}
.sup-item:hover { border-color: var(--ink); }
.sup-item[aria-current="true"] { border-color: var(--accent); background: var(--accent-soft); }
.sup-item-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sup-item-subject { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.sup-item-meta { font-size: 12.5px; color: var(--muted); }
.sup-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.sup-chip {
  display: inline-flex; align-items: center; gap: 6px; flex: none; padding: 2px 9px; white-space: nowrap;
  font-size: 12px; font-weight: 600; line-height: 1.4; border: 1px solid var(--border); border-radius: 999px;
}
.sup-chip::before { content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.sup-chip-client { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
.sup-chip-team { color: var(--violet-ink); background: var(--violet-soft); border-color: var(--violet-line); }
.sup-chip-ok { color: var(--ok); background: var(--ok-soft); border-color: var(--ok-line); }
.sup-pane > .bk-card-sub { margin: 4px 0 18px; }
.sup-form textarea { width: 100%; resize: vertical; }
.sup-form :is(input, select) { width: 100%; }
.sup-ref { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 16px; font-size: 13.5px; }
.sup-ref .bk-label { margin: 0; }
.sup-ref code { padding: 2px 8px; border-radius: 6px; background: var(--panel-2); font-size: 12.5px; }
.sup-problem { color: var(--danger-ink); }
.sup-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.sup-thread { list-style: none; margin: 0 0 14px; padding: 0; display: grid; gap: 10px; }
.sup-msg { max-width: 85%; padding: 10px 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--panel-2); }
.sup-msg.me { justify-self: end; background: var(--accent-soft); border-color: var(--accent-line); }
.sup-msg-who { display: block; margin: 0 0 4px; font-size: 12px; color: var(--muted); }
.sup-msg-body { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; font-size: 14px; }
/* The guide (`support-guide.js`): a search, then one card per section of questions, each a
   `<details>` that opens on its question. The tabs are Settings' own bar; the guide and the
   requests below it take turns, by `hidden`, in a block layout where nothing can slide. */
.sup-tabs { margin: 0 0 18px; }
.sup-tab-badge {
  display: inline-block; margin-left: 7px; min-width: 18px; padding: 0 5px; border-radius: 999px; text-align: center;
  font-size: 11px; font-weight: 700; line-height: 18px; color: var(--on-accent); background: var(--accent);
}
.sup-guide { max-width: 860px; }
.sup-guide[hidden], .sup-body[hidden], .sup-access-pane[hidden] { display: none; }
/* Support access (the card moved here from Profile): a page of its own, read in one column, not a strip beside the guide. */
.sup-access-pane { max-width: 860px; }
.sup-access-pane > .set-card { margin: 0; }
.sup-access-title { margin: 18px 0 6px; font-size: 16px; font-weight: 600; color: var(--text); }
/* The consent: the box on the left of its words, which wrap at the width of the card, not one word to a line. */
.set-support-consent {
  display: flex; align-items: flex-start; gap: 10px; margin: 14px 0 4px; font-size: 14.5px; line-height: 1.45;
  color: var(--text); cursor: pointer; text-align: left;
}
.set-support-consent input { flex: none; margin: 3px 0 0; width: 16px; height: 16px; accent-color: var(--accent); }
.set-support-consent > span { flex: 1 1 0; min-width: 0; }
/* The card's open request, read top to bottom at every width: the state, the team's reason, the consent, the decision. As a
   row of the card's `.set-line` they stood side by side, and at 390 the reason ran past the card and Accept and Decline sat
   on the window's edge. */
.set-support-state { flex-direction: column; align-items: stretch; gap: 10px; }
.set-support-state > * { margin: 0; min-width: 0; }
.set-support-state > p:empty { display: none; }
.set-support-reason {
  padding: 10px 14px; border-left: 3px solid var(--border); border-radius: 0 8px 8px 0; background: var(--panel-2);
  font-size: 14px; line-height: 1.5; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere;
}
.sup-search-bar { margin: 0 0 18px; }
.sup-search {
  width: 100%; min-height: 48px; padding: 12px 16px; font: inherit; font-size: 15px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
}
.sup-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sup-faq-count { margin: 0 0 12px; }
.sup-faq-section { padding: 18px 22px; }
.sup-guide .bk-card + .bk-card { margin-top: 14px; }
.sup-faq-section > .bk-card-title { margin: 0 0 8px; font-size: 16px; }
.sup-faq { border-top: 1px solid var(--border); }
.sup-faq:first-of-type { border-top: 0; }
.sup-faq-q {
  display: flex; flex-direction: column; gap: 2px; padding: 12px 28px 12px 0; position: relative;
  cursor: pointer; list-style: none; font-size: 14.5px; font-weight: 600; color: var(--ink);
}
.sup-faq-q::-webkit-details-marker { display: none; }
.sup-faq-q::after {
  content: '+'; position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  font-size: 18px; font-weight: 400; color: var(--muted);
}
.sup-faq[open] > .sup-faq-q::after { content: '−'; }
.sup-faq-q:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }
.sup-faq-where { font-size: 12px; font-weight: 500; color: var(--muted); }
.sup-faq-a { padding: 0 0 14px; font-size: 14px; color: var(--text); }
.sup-faq-a p { margin: 0 0 8px; line-height: 1.55; }
.sup-faq-a p:last-child { margin: 0; }
.sup-contact .btn { display: inline-block; margin-top: 12px; text-decoration: none; }

/* ============================== ONBOARDING ==============================
   The screen a self-registered account lands in (`app/js/onboarding.js`): over the
   studio, below a confirmation card (`.dlg`, 95) and level with the door (`.gate`, 90)
   — which is appended later, so a session that expires here still asks over it.

   Drawn from the owner's four mockups (1440 wide, read at 1.3×): a white bar with the
   stepper, a light page with a faint pink glow, white cards with hairline borders, the
   navy for the actions and the magenta for what is current. Every colour is a token, so
   the dark theme is the same screen. The titles are the studio's (`--font-display`). */
html.onb-open, html.onb-open body { overflow: hidden; }
.onb {
  --onb-display: var(--font-display);
  /* The accent as small text: the magenta of the mockup one step darker, 5:1 on white,
     where the accent itself is 4.2:1 — the kickers, the credits, the selected chip. */
  --onb-pink: color-mix(in srgb, var(--accent) 90%, #000);
  --onb-dash: color-mix(in srgb, var(--muted) 34%, var(--panel));
  --onb-tile: color-mix(in srgb, var(--panel-2) 45%, var(--panel));
  --onb-lift: 0 16px 44px color-mix(in srgb, var(--ink) 6%, transparent);
  position: fixed; inset: 0; z-index: 90;
  display: flex; flex-direction: column;
  color: var(--text); background: var(--bg);
  font-family: var(--onb-display);
  overflow: hidden;
}
:root[data-theme="dark"] .onb { --onb-pink: var(--accent-ink); }
.onb [hidden] { display: none !important; }
/* The sheet's bare `label` and `input` carry the forms' margins and padding elsewhere;
   here every box sets its own. `:where` keeps this at the weight of those two rules, so
   any class below wins over it. */
:where(.onb) label { display: block; margin: 0; font-size: inherit; color: inherit; }
:where(.onb) input { margin: 0; }
.onb-glow { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }
.onb-glow i {
  position: absolute; width: 46vmax; height: 46vmax; border-radius: 50%;
  filter: blur(80px); opacity: .45;
  animation: onb-drift 22s ease-in-out infinite alternate;
}
.onb-glow i:nth-child(1) { left: -18vmax; top: -14vmax; background: var(--accent-soft); }
.onb-glow i:nth-child(2) { right: -10vmax; top: 4vh; background: var(--accent-soft); animation-delay: -7s; }
.onb-glow i:nth-child(3) { left: 30vw; bottom: -30vmax; background: var(--violet-soft); opacity: .3; animation-delay: -13s; }
@keyframes onb-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(3vmax, 2vmax, 0) scale(1.08); }
}

/* ---------- the bar: the mark, the stepper, the credits ---------- */
.onb-top {
  position: relative; z-index: 2;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 18px;
  min-height: 87px; padding: 0 46px;
  background: var(--panel); border-bottom: 1px solid var(--border);
}
.onb-mark { justify-self: start; display: flex; align-items: center; }
.onb-mark .brand-ours-full { display: none; width: auto; height: 32px; }
.onb-mark .brand-ours-ink { display: block; width: auto; height: 32px; }
:root[data-theme="dark"] .onb-mark .brand-ours-full { display: block; }
:root[data-theme="dark"] .onb-mark .brand-ours-ink { display: none; }
.onb-steps { display: flex; align-items: center; margin: 0; padding: 0; list-style: none; }
.onb-step {
  display: flex; align-items: center; gap: 11px;
  font-size: 14px; font-weight: 500; color: var(--muted); white-space: nowrap;
}
.onb-step + .onb-step::before {
  content: ''; width: 25px; height: 1px; margin: 0 4px 0 13px; background: var(--border);
}
.onb-step-dot {
  display: grid; place-items: center; flex: none; width: 26px; height: 26px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--panel); color: var(--muted);
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
  transition: background .3s, border-color .3s, box-shadow .3s;
}
.onb-step-dot svg { display: none; stroke-width: 2.4; }
.onb-step.now { color: var(--ink); font-weight: 700; }
.onb-step.now .onb-step-dot {
  border-color: var(--accent); background: var(--accent); color: var(--on-accent);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.onb-step.done .onb-step-dot { border-color: transparent; background: var(--accent-soft); color: var(--accent); }
.onb-step.done .onb-step-n { display: none; }
.onb-step.done .onb-step-dot svg { display: block; }
.onb-top-end { justify-self: end; display: flex; align-items: center; gap: 26px; }
.onb-wallet { display: flex; align-items: center; gap: 8px; color: var(--ink); font-size: 14px; }
.onb-wallet svg { color: var(--accent); }
.onb-wallet-n { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.onb-wallet-word { font-weight: 500; }
.onb-wallet.up .onb-wallet-n { animation: onb-bump .9s ease; }
@keyframes onb-bump {
  0%, 100% { color: inherit; }
  40% { color: var(--accent); }
}
.onb-skip {
  padding: 6px 2px; border: 0; background: none;
  color: var(--muted); font: inherit; font-size: 14px; cursor: pointer;
}
.onb-skip:hover { color: var(--ink); }
.onb-skip:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }

/* ---------- the page ---------- */
.onb-stage {
  position: relative; z-index: 1; flex: 1 1 auto;
  display: flex; flex-direction: column;
  overflow-x: hidden; overflow-y: auto; padding: 0 24px;
}
.onb-view {
  flex: 1 0 auto; width: min(1276px, 100%); margin: 0 auto;
  animation: onb-enter .55s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes onb-enter {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}
.onb-head { max-width: 100%; }
.onb-kicker {
  margin: 0; font-size: 12px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  color: var(--onb-pink);
}
.onb-kicker.dot { display: flex; align-items: center; gap: 13px; }
.onb-kicker.dot::before { content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.onb-title {
  margin: 18px 0 0; font-family: var(--onb-display); font-weight: 800;
  font-size: 46px; line-height: 1.07; letter-spacing: -.045em; color: var(--ink);
}
.onb-title:focus { outline: none; }
.onb-title-line { display: block; text-wrap: balance; }
.onb-title em { font-style: normal; color: var(--accent); }
.onb-sub { margin: 20px 0 0; font-size: 14px; line-height: 1.65; color: var(--muted); }
.onb-sub-line { display: block; }
.onb-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.onb-say { margin: 12px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--muted); }
.onb-say:empty { display: none; }
.onb-say.err { color: var(--danger-ink); }
.onb-say.ok { color: var(--ok); font-weight: 600; }
.onb-in { animation: onb-enter .6s cubic-bezier(.2, .8, .2, 1) both; animation-delay: var(--d, 0ms); }
@keyframes onb-pop {
  from { opacity: 0; transform: scale(.85); }
  to { opacity: 1; transform: none; }
}

/* the actions: navy for going on, the accent for spending, a white outline for looking */
.onb-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 11px;
  min-height: 50px; padding: 0 26px; border: 0; border-radius: 12px;
  background: var(--solid); color: var(--on-solid);
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer; text-decoration: none; white-space: nowrap;
  box-shadow: 0 10px 24px color-mix(in srgb, var(--solid) 20%, transparent);
  transition: transform .15s, background .2s, box-shadow .2s;
}
.onb-cta:hover { background: var(--solid-2); transform: translateY(-1px); }
.onb-cta:active { transform: none; }
.onb-cta:disabled { opacity: .5; cursor: default; transform: none; }
.onb-cta:focus-visible, .onb-outline:focus-visible, .onb-link:focus-visible, .onb-back:focus-visible, .onb-period:focus-visible {
  outline: 3px solid var(--accent-line); outline-offset: 2px;
}
.onb-cta.big {
  min-height: 52px; padding: 0 28px;
  background: var(--accent); color: var(--on-accent);
  box-shadow: 0 12px 28px var(--accent-halo);
}
.onb-cta.big:hover { background: var(--accent-hi); }
.onb-cta.small { min-height: 42px; padding: 0 18px; font-size: 13.5px; border-radius: 9px; box-shadow: none; }
.onb-cta.ghost { background: var(--panel); color: var(--ink); border: 1px solid var(--border); box-shadow: none; }
.onb-cta.ghost:hover { background: var(--panel-2); }
.onb-outline {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  min-height: 52px; padding: 0 26px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 700; cursor: pointer; white-space: nowrap;
}
.onb-outline:hover { background: var(--panel-2); }
.onb-link {
  display: inline-flex; align-items: center; gap: 10px; padding: 4px 0; border: 0; background: none;
  color: var(--muted); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
}
.onb-link:hover { color: var(--ink); }
.onb-icon-tile {
  display: grid; place-items: center; flex: none; width: 36px; height: 36px; border-radius: 9px;
  background: var(--panel-2); color: var(--ink-2);
}
.onb-icon-tile.pink { background: var(--accent-soft); color: var(--accent); }

/* the fields */
.onb-labelled { display: flex; flex-direction: column; gap: 10px; width: 100%; }
.onb-label { font-size: 13px; font-weight: 700; color: var(--ink); }
.onb-field {
  width: 100%; height: 52px; padding: 0 16px;
  font: inherit; font-size: 15px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
  transition: border-color .2s, box-shadow .2s;
}
.onb-field::placeholder, .onb-point-field::placeholder { color: color-mix(in srgb, var(--muted) 75%, var(--panel)); }
.onb-field:focus-visible { outline: none; border-color: var(--accent-line); box-shadow: 0 0 0 4px var(--accent-soft); }
.onb-url-shell {
  display: flex; align-items: center; gap: 12px;
  height: 66px; padding: 0 8px 0 18px; border-radius: 14px;
  background: var(--panel); border: 1px solid var(--border);
  box-shadow: 0 8px 24px color-mix(in srgb, var(--ink) 4%, transparent);
  color: var(--muted); transition: border-color .2s, box-shadow .2s;
}
.onb-url-shell:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 4px var(--accent-soft); }
.onb-url-shell svg { flex: none; }
.onb-url-shell .onb-field {
  flex: 1 1 auto; min-width: 0; height: 100%; padding: 0 2px;
  border: 0; border-radius: 0; background: transparent; box-shadow: none;
}
.onb-url-shell .onb-field:focus-visible { box-shadow: none; }
.onb-url-shell .onb-cta { flex: none; min-height: 50px; padding: 0 22px; border-radius: 10px; }
.onb-url-shell.small { height: 54px; padding: 0 6px 0 14px; border-radius: 11px; box-shadow: none; }
.onb-url-shell.small .onb-field { font-size: 14px; }
.onb-url-shell.small .onb-cta { min-height: 42px; padding: 0 18px; border-radius: 8px; }

/* ---------- 1. the brand: the words on the left, the kit on the right ---------- */
.onb-brand { display: flex; flex-direction: column; }
.onb-brand-cols {
  flex: 1 0 auto; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px; align-items: start; align-content: center; padding: 40px 0;
}
/* Both columns start at the top, the pair centred in the page: the left one grows and
   shrinks as the site is read, and a column centred on its own would jump each time. */
.onb-brand-copy { min-width: 0; max-width: 612px; padding-top: 17px; display: flex; flex-direction: column; align-items: flex-start; }
.onb-gift {
  display: inline-flex; align-items: center; gap: 10px; margin: 0 0 27px;
  padding: 7px 14px; border-radius: 8px;
  background: var(--accent-soft); color: var(--onb-pink);
  font-size: 13.5px; font-weight: 500;
  animation: onb-pop .6s cubic-bezier(.2, 1.4, .4, 1) both;
}
.onb-gift svg { color: var(--accent); }
.onb-head.huge .onb-title { margin-top: 30px; font-size: 60px; line-height: 1.03; letter-spacing: -.05em; }
.onb-head.huge .onb-sub { margin-top: 30px; max-width: 492px; font-size: 16px; line-height: 1.75; }
.onb-brand-copy .onb-sub-line { display: inline; }
.onb-url { width: 100%; margin-top: 26px; }
.onb-url-label { display: block; margin-bottom: 12px; font-size: 13px; font-weight: 700; color: var(--ink); }
.onb-nosite { margin-top: 20px; }
.onb-promise { display: flex; flex-wrap: wrap; gap: 10px 26px; margin: 40px 0 0; padding: 0; list-style: none; }
.onb-promise li { display: flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--muted); }
.onb-promise svg { color: var(--ok); }

/* the site being read: the lines that tick off, and the bar */
.onb-scan-log { width: 100%; margin-top: 26px; display: flex; flex-direction: column; gap: 16px; }
.onb-ticks { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.onb-tick {
  display: flex; align-items: center; gap: 10px; font-size: 13.5px; color: var(--muted);
  animation: onb-enter .4s ease both;
}
.onb-tick svg {
  flex: 0 0 auto; padding: 3px; width: 20px; height: 20px; border-radius: 50%;
  color: transparent; border: 1.5px solid var(--onb-dash); transition: all .3s;
}
.onb-tick.ok { color: var(--text); }
.onb-tick.ok svg { color: var(--on-solid); background: var(--ok); border-color: var(--ok); }
.onb-progress { height: 5px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.onb-progress i {
  display: block; height: 100%; width: 0; border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-hi)); transition: width .25s linear;
}
.onb-kit-step { width: 100%; display: flex; flex-direction: column; align-items: flex-start; }
.onb-kit-step .onb-title { margin-top: 26px; font-size: 50px; line-height: 1.04; letter-spacing: -.05em; }
.onb-kit-step .onb-sub { max-width: 492px; font-size: 15px; }
.onb-kit-fields, .onb-manual { width: 100%; display: flex; flex-direction: column; gap: 18px; margin-top: 32px; }
.onb-kit-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 14px 26px; margin-top: 26px; }

/* the right column: the site, the wire, the kit */
.onb-brand-art { min-width: 0; display: flex; flex-direction: column; align-items: center; }
.onb-site {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 14px; width: min(286px, 100%);
  padding: 15px 18px 15px 16px; border-radius: 14px;
  background: var(--panel); border: 1px solid var(--border);
  box-shadow: 0 14px 40px color-mix(in srgb, var(--accent) 9%, transparent);
}
.onb-site-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.onb-site-title { font-size: 13.5px; font-weight: 700; color: var(--ink); }
.onb-site-sub { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.onb-site-end { display: flex; color: var(--muted); }
.onb-site.done .onb-site-end { color: var(--ok); }
.onb-beam { display: none; }
.onb-site.onb-scan .onb-beam {
  display: block; position: absolute; top: 0; bottom: 0; left: -40%; width: 40%;
  background: linear-gradient(90deg, transparent, var(--accent-soft));
  border-right: 2px solid var(--accent);
  animation: onb-sweep 1.5s ease-in-out infinite;
}
@keyframes onb-sweep {
  from { transform: translateX(0); }
  to { transform: translateX(350%); }
}
.onb-wire {
  position: relative; z-index: 1; width: 2px; height: 36px; margin-bottom: -4px;
  background: repeating-linear-gradient(180deg, var(--onb-dash) 0 3px, transparent 3px 6px);
}
.onb-wire::after {
  content: ''; position: absolute; left: 50%; bottom: 0; width: 7px; height: 7px; margin-left: -3.5px;
  border-radius: 50%; background: var(--accent);
}
.onb-brand.scanning .onb-wire {
  background: repeating-linear-gradient(180deg, var(--accent) 0 3px, transparent 3px 6px);
  animation: onb-flow .5s linear infinite;
}
.onb-brand.scanning .onb-wire::after { animation: onb-ping 1.2s ease-out infinite; }
@keyframes onb-flow { to { background-position: 0 6px; } }
@keyframes onb-ping {
  from { box-shadow: 0 0 0 0 var(--accent-line); }
  to { box-shadow: 0 0 0 9px transparent; }
}
.onb-kit {
  position: relative; width: min(542px, 100%);
  padding: 26px 27px 22px; border-radius: 18px;
  background: var(--panel); border: 1px solid var(--border);
  box-shadow: 0 24px 60px color-mix(in srgb, var(--ink) 7%, transparent), 0 0 90px color-mix(in srgb, var(--accent) 6%, transparent);
}
.onb-kit-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.onb-kit-kicker { margin: 0; font-size: 10.5px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase; color: var(--muted); }
.onb-kit-state {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  padding: 5px 9px; border-radius: 6px; background: var(--panel-2); color: var(--muted); font-size: 10.5px;
}
.onb-kit-state.ok { background: var(--ok-soft); color: var(--ok); font-weight: 600; animation: onb-pop .5s cubic-bezier(.2, 1.4, .4, 1) both; }
.onb-kit-state svg { stroke-width: 2.4; }
.onb-kit-title {
  margin: 22px 0 0; font-family: var(--onb-display); font-size: 28px; font-weight: 800;
  line-height: 1.15; letter-spacing: -.035em; color: var(--ink); overflow-wrap: anywhere;
}
.onb-kit-sub { margin: 8px 0 0; min-height: 1.45em; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.onb-kit-grid {
  margin-top: 24px; display: grid; gap: 12px;
  grid-template-columns: minmax(0, .81fr) minmax(0, 1fr);
}
.onb-kit-tile {
  position: relative; overflow: hidden; min-width: 0;
  display: flex; flex-direction: column; padding: 14px 15px; border-radius: 12px;
  background: var(--onb-tile); border: 1px solid var(--border);
}
.onb-kit-tile-head { display: flex; align-items: center; gap: 9px; margin: 0; font-size: 12.5px; font-weight: 500; color: var(--ink-2); }
.onb-kit-tile-head svg { color: var(--muted); }
.onb-kit-note { margin-top: 6px; font-size: 10.5px; line-height: 1.45; color: var(--muted); }
.onb-kit-logo-tile {
  grid-row: 1 / span 2; min-height: 198px; align-items: center; justify-content: center; text-align: center;
  border: 1.5px dashed var(--onb-dash);
}
.onb-kit-logo {
  display: grid; place-items: center; width: 48px; height: 48px; border-radius: 12px;
  border: 1.5px dashed var(--onb-dash); color: var(--muted);
}
.onb-kit-logo.has { width: 100%; max-width: 150px; height: 70px; border: 0; }
.onb-kit-logo.has.on-dark { padding: 8px 12px; border-radius: 10px; background: #111; }
.onb-kit-logo.has img { max-width: 100%; max-height: 70px; object-fit: contain; animation: onb-pop .6s cubic-bezier(.2, 1.3, .4, 1) both; animation-delay: var(--d, 0ms); }
.onb-kit-logo.initial {
  width: 58px; height: 58px; border: 0; border-radius: 15px;
  background: var(--accent-soft); color: var(--accent); font-size: 26px; font-weight: 800;
}
.onb-kit-tile-name { margin-top: 16px; font-size: 13px; font-weight: 500; color: var(--ink-2); }
.onb-kit-logo-tile .onb-kit-note { max-width: 180px; }
.onb-kit-colours { min-height: 108px; }
.onb-swatches { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-top: 14px; }
.onb-slot, .onb-swatch { height: 26px; border-radius: 7px; }
.onb-slot { border: 1.5px dashed var(--onb-dash); }
.onb-swatch {
  background: var(--c); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .07);
  animation: onb-pop .5s cubic-bezier(.2, 1.5, .4, 1) both;
  animation-delay: calc(var(--d, 0ms) + var(--i, 0) * 90ms);
}
.onb-kit-colours .onb-kit-note { margin-top: 9px; font-size: 9.5px; }
.onb-kit-type { min-height: 76px; }
.onb-kit-fonts { margin-top: 12px; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.onb-bone { display: block; height: 5px; width: 72%; border-radius: 3px; background: var(--panel-2); }
.onb-bone.short { width: 48%; }
.onb-font {
  font-size: 16px; font-weight: 600; line-height: 1.2; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.onb-font + .onb-font { font-size: 12.5px; font-weight: 500; color: var(--muted); }
.onb-kit-voice {
  grid-column: 1 / -1; flex-direction: row; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 12px; min-height: 48px; padding: 9px 15px;
}
.onb-chips { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin: 0; padding: 0; list-style: none; }
.onb-chip-slot { width: 106px; height: 20px; border-radius: 6px; border: 1.5px dashed var(--onb-dash); }
.onb-chip { padding: 3px 10px; border-radius: 6px; background: var(--accent-soft); color: var(--onb-pink); font-size: 11.5px; font-weight: 600; }
.onb-kit-foot { display: flex; align-items: center; justify-content: center; gap: 10px; margin: 18px 0 0; font-size: 12px; color: var(--muted); text-align: center; }
.onb-kit-foot svg { flex: none; color: var(--accent); }
.onb-kit.reading .onb-kit-tile::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(110deg, transparent 30%, color-mix(in srgb, var(--accent) 8%, transparent) 50%, transparent 70%);
  background-size: 220% 100%; animation: onb-shimmer 1.4s linear infinite;
}
.onb-kit.reading .onb-kit-tile:nth-child(2)::after { animation-delay: .15s; }
.onb-kit.reading .onb-kit-tile:nth-child(3)::after { animation-delay: .3s; }
.onb-kit.reading .onb-kit-tile:nth-child(4)::after { animation-delay: .45s; }
/* A tile the free read already filled stops shimmering while the paid read goes on. */
.onb-kit.reading .onb-kit-tile.known::after { content: none; }
@keyframes onb-shimmer {
  from { background-position: 120% 0; }
  to { background-position: -120% 0; }
}
.onb-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px 24px; flex-wrap: wrap;
  padding: 26px 0 30px; border-top: 1px solid var(--border);
}
.onb-foot p { margin: 0; font-size: 12.5px; color: var(--muted); }
.onb-foot-line { display: flex; align-items: center; gap: 10px; }

/* ---------- 2. the product ---------- */
.onb-product { width: min(1076px, 100%); display: flex; flex-direction: column; padding: 46px 0 40px; }
.onb-product > .onb-head, .onb-plan > .onb-head { align-self: center; max-width: 820px; text-align: center; }
.onb-product .onb-title { line-height: 1.06; }
.onb-roads { margin-top: 26px; display: grid; grid-template-columns: minmax(0, 1fr) 36px minmax(0, 1fr); align-items: stretch; }
.onb-road { display: flex; flex-direction: column; min-height: 160px; border-radius: 17px; }
.onb-road-link {
  justify-content: space-between; gap: 18px; padding: 22px 25px;
  background: var(--panel); border: 1px solid var(--border); box-shadow: 0 10px 30px color-mix(in srgb, var(--ink) 4%, transparent);
}
.onb-road-head { display: flex; align-items: flex-start; gap: 14px; }
.onb-road-title { margin: 0; font-size: 14px; font-weight: 700; color: var(--ink); }
.onb-road-note { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
.onb-road-small { margin: 12px 0 0; font-size: 10.5px; color: var(--muted); }
.onb-or {
  align-self: center; justify-self: center; display: grid; place-items: center;
  min-width: 24px; height: 24px; padding: 0 5px; border-radius: 999px; background: var(--panel); border: 1px solid var(--border);
  font-size: 10px; color: var(--muted); white-space: nowrap;
}
.onb-drop {
  align-items: center; justify-content: center; padding: 22px; text-align: center; cursor: pointer;
  border: 1.5px dashed var(--onb-dash); background: color-mix(in srgb, var(--panel) 55%, transparent);
  transition: border-color .2s, background .2s;
}
.onb-drop .onb-icon-tile { width: 31px; height: 31px; border-radius: 8px; }
.onb-drop .onb-road-title { margin-top: 13px; font-size: 14.5px; }
.onb-drop .onb-road-note { margin-top: 9px; font-size: 12.5px; }
.onb-drop:hover, .onb-drop.over, .onb-drop:focus-within { border-color: var(--accent); background: var(--accent-soft); }
.onb-product-card {
  margin-top: 24px; display: grid; grid-template-columns: 219px minmax(0, 1fr); gap: 28px;
  padding: 30px 28px; border-radius: 18px;
  background: var(--panel); border: 1px solid var(--border); box-shadow: var(--onb-lift);
  transition: opacity .3s;
}
.onb-product-card.loading { opacity: .6; }
.onb-product-side { display: flex; flex-direction: column; align-items: center; gap: 14px; min-width: 0; }
.onb-product-frame {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 9px;
  padding: 13px 13px 11px; border-radius: 14px; background: var(--panel-2);
}
.onb-product-photo {
  width: 100%; aspect-ratio: 1; display: grid; place-items: center; align-content: center; gap: 8px;
  border-radius: 10px; overflow: hidden; background: var(--panel); border: 1.5px dashed var(--onb-dash);
  color: var(--muted); font-size: 12px; text-align: center;
}
.onb-product-photo.has { border: 0; background: #fff; }
.onb-product-photo img { width: 100%; height: 100%; object-fit: contain; animation: onb-fly .7s cubic-bezier(.2, 1.2, .3, 1) both; }
@keyframes onb-fly {
  from { opacity: 0; transform: translateY(24px) scale(.85) rotate(-3deg); }
  to { opacity: 1; transform: none; }
}
.onb-product-ready { display: flex; align-items: center; gap: 6px; margin: 0; font-size: 11px; color: var(--ok); }
.onb-product-change { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); cursor: pointer; }
.onb-product-change:hover { color: var(--ink); }
.onb-product-fields { min-width: 0; display: flex; flex-direction: column; }
.onb-details-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px 12px; }
.onb-details-title { margin: 0; font-size: 15.5px; font-weight: 700; letter-spacing: -.01em; color: var(--ink); }
.onb-imported {
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 11px; border-radius: 7px;
  background: var(--ok-soft); color: var(--ok); font-size: 10.5px;
}
.onb-product-fields .onb-labelled { margin-top: 18px; gap: 9px; }
.onb-product-fields .onb-label { font-size: 11.5px; }
.onb-product-fields .onb-field { height: 43px; padding: 0 13px; border-radius: 9px; font-size: 13.5px; }
.onb-points { margin-top: 18px; display: flex; flex-direction: column; gap: 8px; }
.onb-points-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 1px; }
.onb-points-max { font-size: 10.5px; color: var(--muted); }
.onb-point {
  display: flex; align-items: center; gap: 10px; height: 39px; padding: 0 13px; border-radius: 9px;
  background: var(--onb-tile); border: 1px solid var(--border); transition: border-color .2s, box-shadow .2s;
}
.onb-point:focus-within { border-color: var(--accent-line); box-shadow: 0 0 0 3px var(--accent-soft); }
.onb-point-n { flex: none; width: 18px; font-size: 10.5px; font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }
.onb-point-field { flex: 1 1 auto; min-width: 0; height: 100%; padding: 0; border: 0; border-radius: 0; background: transparent; font: inherit; font-size: 13px; color: var(--text); }
.onb-point-field:focus { outline: none; }
.onb-product > .onb-say { text-align: center; }
.onb-nav { margin-top: 26px; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: start; }
.onb-back {
  justify-self: start; margin-top: 15px; display: inline-flex; align-items: center; gap: 10px;
  border: 0; background: none; color: var(--muted); font: inherit; font-size: 14px; cursor: pointer;
}
.onb-back:hover { color: var(--ink); }
.onb-nav-main { grid-column: 2; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.onb-next { min-width: 241px; }
.onb-nav-note { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 11px; color: var(--muted); }

/* ---------- 3. the creatives: four frames in a row, at their own shapes ---------- */
.onb-create { display: flex; flex-direction: column; padding: 40px 0 36px; }
.onb-create-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; }
.onb-create-head .onb-head { min-width: 0; }
.onb-create .onb-sub { margin-top: 14px; font-size: 13.5px; }
.onb-create.made .onb-title { margin-top: 22px; }
.onb-made {
  display: inline-flex; align-items: center; gap: 9px; margin: 0; padding: 7px 12px; border-radius: 8px;
  background: var(--ok-soft); color: var(--ok); font-size: 12px; font-weight: 500;
}
.onb-campaign {
  flex: none; display: flex; align-items: center; gap: 14px; min-width: 206px; margin-bottom: 4px;
  padding: 14px 20px 14px 16px; border-radius: 12px;
  background: var(--panel); border: 1px solid var(--border); box-shadow: 0 10px 30px color-mix(in srgb, var(--ink) 5%, transparent);
  animation: onb-pop .6s cubic-bezier(.2, 1.3, .4, 1) both;
}
.onb-campaign-logo { display: grid; place-items: center; flex: none; width: 36px; height: 36px; }
.onb-campaign-logo img { max-width: 36px; max-height: 36px; object-fit: contain; }
.onb-campaign-words { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.onb-campaign-words b { font-size: 13px; font-weight: 600; color: var(--ink); }
.onb-campaign-done { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ok); }
.onb-grid { margin-top: 44px; display: grid; grid-template-columns: var(--onb-cols, repeat(4, minmax(0, 1fr))); column-gap: 18px; }
/* Two rows of the grid per tile: the frames on one, the captions on the next, so a longer
   caption never lifts its frame off the line the others stand on. */
.onb-tile { margin: 0; min-width: 0; display: grid; grid-row: span 2; grid-template-rows: subgrid; row-gap: 0; }
.onb-tile-top { align-self: end; min-width: 0; display: flex; flex-direction: column; }
.onb-tile-cap { align-self: start; }
.onb-tile.off { opacity: .45; }
.onb-tile-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 12px; font-size: 11.5px; color: var(--muted); }
.onb-tile-kind { display: flex; align-items: center; gap: 7px; min-width: 0; }
.onb-tile-ratio { font-variant-numeric: tabular-nums; }
.onb-tile-frame {
  position: relative; aspect-ratio: var(--ratio, 1); border-radius: 14px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border);
}
.onb-tile-ghost {
  position: absolute; inset: 20%; width: 60%; height: 60%; object-fit: contain;
  opacity: .22; filter: grayscale(.4);
}
.onb-tile:not(.ready) .onb-tile-frame::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(110deg, transparent 30%, color-mix(in srgb, var(--panel) 75%, transparent) 50%, transparent 70%);
  background-size: 220% 100%; animation: onb-shimmer 2.6s linear infinite;
}
.onb-tile.working .onb-tile-frame::after { animation-duration: 1.3s; animation-delay: var(--d, 0ms); }
.onb-ring {
  --p: 0;
  position: absolute; left: 50%; top: 50%; width: 54px; height: 54px; margin: -27px 0 0 -27px;
  border-radius: 50%; opacity: 0; transition: opacity .3s; z-index: 1;
  background: conic-gradient(var(--accent) calc(var(--p) * 1%), var(--onb-dash) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px));
}
.onb-tile.working .onb-ring { opacity: 1; }
.onb-tile-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  animation: onb-develop 1.1s cubic-bezier(.2, .8, .2, 1) both;
}
@keyframes onb-develop {
  from { opacity: 0; filter: blur(18px) saturate(.4); transform: scale(1.08); }
  to { opacity: 1; filter: none; transform: none; }
}
.onb-tile.ready .onb-tile-frame {
  border-color: transparent; cursor: zoom-in;
  box-shadow: 0 14px 34px color-mix(in srgb, var(--ink) 12%, transparent);
}
.onb-tile.failed .onb-tile-frame { border-color: var(--danger-line); background: var(--danger-soft); }
/* The corner button sits on the picture, so its colours are the picture's, not the theme's. */
.onb-zoom-open {
  position: absolute; right: 11px; bottom: 11px; z-index: 1;
  display: grid; place-items: center; width: 31px; height: 31px;
  border: 0; border-radius: 8px; background: var(--on-scrim); color: var(--scrim);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .2); cursor: pointer;
}
.onb-zoom-open:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.onb-retry {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1;
  padding: 8px 14px; border-radius: 10px; border: 1px solid var(--danger-line);
  background: var(--panel); color: var(--danger-ink); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.onb-tile-cap { margin-top: 15px; display: flex; flex-direction: column; gap: 6px; }
.onb-tile-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.onb-tile-name { font-size: 12.5px; font-weight: 700; color: var(--ink); }
.onb-tile-state { display: flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; color: var(--ok); white-space: nowrap; }
.onb-tile.working .onb-tile-state { color: var(--muted); font-weight: 500; }
.onb-tile-note { font-size: 11px; color: var(--muted); }
.onb-create-foot {
  margin-top: 26px;
  display: flex; align-items: center; justify-content: flex-start; gap: 18px 24px;
}
.onb-create-foot .onb-actions { justify-content: flex-start; }
.onb-create-left { min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.onb-create-left .onb-say { margin: 0; }
.onb-create-lead { font-size: 13px; font-weight: 700; color: var(--ink); }
.onb-create-note { margin: 0; font-size: 11.5px; color: var(--muted); }
.onb-actions { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 14px; }
.onb-closer { margin: 22px 0 0; text-align: center; font-size: 11.5px; color: var(--muted); }
.onb-zoom {
  position: absolute; inset: 0; z-index: 5; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; padding: 32px; background: var(--scrim-strong);
  animation: onb-enter .3s ease both;
}
.onb-zoom-stage { flex: 1 1 auto; min-height: 0; width: 100%; display: flex; align-items: center; justify-content: center; gap: 18px; }
.onb-zoom-img { min-width: 0; max-width: calc(100% - 140px); max-height: 100%; border-radius: 14px; object-fit: contain; box-shadow: var(--shadow-3); }
.onb-zoom-nav {
  display: grid; place-items: center; flex: none; width: 48px; height: 48px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .3); background: rgba(255, 255, 255, .08); color: var(--on-scrim); cursor: pointer;
}
.onb-zoom-nav:hover { background: rgba(255, 255, 255, .16); }
.onb-zoom-bar { display: flex; align-items: center; gap: 12px; }
.onb-zoom-count { color: var(--on-scrim); font-size: 13px; opacity: .8; font-variant-numeric: tabular-nums; }
.onb-zoom-close {
  display: inline-flex; align-items: center; gap: 6px; min-height: 42px; padding: 0 14px; border-radius: 9px;
  border: 1px solid rgba(255, 255, 255, .3); background: transparent; color: var(--on-scrim); font: inherit; cursor: pointer;
}

/* ---------- 4. the plans, over the creatives just made ---------- */
.onb-plan { position: relative; isolation: isolate; width: min(1138px, 100%); display: flex; flex-direction: column; align-items: center; padding: 46px 0 40px; }
.onb-plan::before {
  content: ''; position: absolute; z-index: -1; left: 50%; top: 0; width: min(980px, 100%); height: 560px; transform: translateX(-50%);
  background: radial-gradient(closest-side, color-mix(in srgb, var(--bg) 88%, transparent), transparent);
  pointer-events: none;
}
.onb-plan .onb-title { line-height: 1.12; }
.onb-wall {
  position: absolute; inset: 0; z-index: 0; display: grid; grid-template-columns: repeat(4, 1fr);
  opacity: .38; filter: blur(36px) saturate(1.15); pointer-events: none;
  -webkit-mask: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .65) 50%, transparent 92%);
  mask: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .65) 50%, transparent 92%);
}
.onb-wall img { width: 100%; height: 100%; object-fit: cover; }
.onb-periods {
  margin-top: 26px; display: inline-flex; align-items: center; gap: 4px; padding: 5px; border-radius: 12px;
  background: var(--panel); border: 1px solid var(--border); box-shadow: 0 8px 24px color-mix(in srgb, var(--ink) 6%, transparent);
}
.onb-period {
  display: inline-flex; align-items: center; gap: 9px; height: 42px; padding: 0 18px; border: 0; border-radius: 9px;
  background: transparent; color: var(--muted); font: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
}
.onb-period em { font-style: normal; font-size: 10px; font-weight: 600; padding: 3px 7px; border-radius: 5px; background: var(--ok-soft); color: var(--ok); }
.onb-period[aria-pressed="true"] { background: var(--solid); color: var(--on-solid); font-weight: 700; }
.onb-period[aria-pressed="true"] em { background: color-mix(in srgb, var(--on-solid) 16%, transparent); color: var(--on-solid); }
.onb-plans { width: 100%; margin-top: 34px; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px; align-items: stretch; }
.onb-plan-card {
  position: relative; display: flex; flex-direction: column; min-height: 423px; padding: 34px 28px 28px;
  border-radius: 18px; background: var(--panel); border: 1px solid var(--border); box-shadow: var(--onb-lift);
  transition: transform .2s, box-shadow .2s;
}
.onb-plan-card:hover { transform: translateY(-3px); }
.onb-plan-card.featured {
  border: 1.5px solid var(--accent);
  background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 6%, var(--panel)), var(--panel) 45%);
  box-shadow: 0 20px 50px var(--accent-halo);
}
.onb-plan-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 22px; }
.onb-plan-top svg { color: var(--accent); }
.onb-plan-kicker { margin: 0; font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.onb-plan-card.featured .onb-plan-kicker { color: var(--onb-pink); }
.onb-plan-name { margin: 16px 0 0; font-family: var(--onb-display); font-size: 25px; font-weight: 700; letter-spacing: -.02em; color: var(--ink); }
.onb-plan-price { margin: 26px 0 0; display: flex; align-items: baseline; gap: 3px; color: var(--ink); }
.onb-plan-cur { font-size: 13px; font-weight: 600; }
.onb-plan-amount { font-family: var(--onb-display); font-size: 48px; font-weight: 800; line-height: 1; letter-spacing: -.035em; }
.onb-plan-per { margin-left: 8px; font-size: 13px; color: var(--muted); }
.onb-plan-billed { margin: 12px 0 0; font-size: 11px; color: var(--muted); }
.onb-plan-credits { display: flex; align-items: center; gap: 9px; margin: 24px 0 0; font-size: 14px; font-weight: 700; color: var(--onb-pink); }
.onb-plan-credits svg { flex: none; color: var(--accent); }
.onb-plan-desc { margin: 16px 0 28px; font-size: 12.5px; line-height: 1.75; color: var(--muted); }
.onb-plan-pick { width: 100%; margin-top: auto; }
.onb-later {
  margin-top: 32px; color: var(--onb-pink); font-size: 14px;
  text-decoration: underline; text-underline-offset: 5px; text-decoration-thickness: 1px;
}
.onb-later:hover { color: var(--accent); }
.onb-plan > .onb-say { text-align: center; }
.onb-requested {
  width: min(560px, 100%); margin-top: 32px; display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 36px;
  text-align: center; background: var(--panel); border: 1px solid var(--accent-line); border-radius: 22px;
  box-shadow: 0 20px 50px var(--accent-halo); animation: onb-pop .6s cubic-bezier(.2, 1.3, .4, 1) both;
}
.onb-requested > svg { color: var(--accent); }
.onb-requested-title { margin: 0; font-family: var(--onb-display); font-size: 26px; font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
.onb-requested .onb-sub { margin: 0; }
.onb-burst { position: absolute; inset: 0; z-index: 6; pointer-events: none; overflow: hidden; }
.onb-burst i {
  position: absolute; top: -20px; left: var(--x); width: 10px; height: 16px; border-radius: 3px;
  background: var(--accent);
  animation: onb-fall 2.2s cubic-bezier(.3, .6, .4, 1) both; animation-delay: var(--d);
}
.onb-burst i:nth-child(4n + 1) { background: var(--violet-ink); }
.onb-burst i:nth-child(4n + 2) { background: var(--ok); }
.onb-burst i:nth-child(4n + 3) { background: var(--accent-hi); }
@keyframes onb-fall {
  from { transform: translateY(0) rotate(0); opacity: 1; }
  to { transform: translateY(105vh) rotate(var(--r)); opacity: .9; }
}

/* ---------- a phone: one column, the creatives two by two ---------- */
@media (max-width: 900px) {
  .onb-top { grid-template-columns: minmax(0, 1fr) auto; row-gap: 12px; min-height: 0; padding: 12px 16px; }
  .onb-mark .brand-ours-full, .onb-mark .brand-ours-ink { height: 26px; }
  .onb-steps { grid-column: 1 / -1; grid-row: 2; justify-content: center; }
  .onb-step-name { display: none; }
  .onb-step.now .onb-step-name { display: inline; }
  .onb-step + .onb-step::before { width: 14px; margin: 0 8px 0 0; }
  .onb-step { gap: 8px; }
  .onb-top-end { gap: 16px; }
  .onb-stage { padding: 0 16px; }
  .onb-title { font-size: 34px; }
  .onb-head.huge .onb-title, .onb-kit-step .onb-title { font-size: 40px; }
  .onb-sub-line { display: inline; }
  .onb-brand-cols { grid-template-columns: minmax(0, 1fr); gap: 36px; padding: 28px 0; }
  .onb-head.huge .onb-title { margin-top: 22px; }
  .onb-url { margin-top: 32px; }
  .onb-url-shell, .onb-url-shell.small { flex-wrap: wrap; height: auto; padding: 8px 8px 8px 14px; row-gap: 6px; }
  .onb-url-shell .onb-field { flex: 1 1 150px; height: 46px; }
  .onb-promise { margin-top: 32px; }
  .onb-kit { padding: 22px 18px 18px; }
  .onb-kit-logo-tile { min-height: 168px; }
  .onb-foot { flex-direction: column; align-items: flex-start; }
  .onb-product, .onb-plan { padding-top: 32px; }
  .onb-roads { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .onb-product-card { grid-template-columns: minmax(0, 1fr); gap: 22px; padding: 20px 18px; }
  .onb-product-side { width: 100%; max-width: 260px; margin: 0 auto; }
  .onb-nav { grid-template-columns: minmax(0, 1fr); justify-items: center; gap: 16px; }
  .onb-nav-main { grid-column: 1; grid-row: 1; width: 100%; }
  .onb-next { min-width: 0; width: 100%; }
  .onb-back { justify-self: center; margin-top: 0; }
  .onb-create { padding-top: 28px; }
  .onb-create-head { flex-direction: column; align-items: flex-start; }
  .onb-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: end; gap: 24px 14px; margin-top: 30px; }
  .onb-create-foot { flex-direction: column; align-items: stretch; }
  .onb-actions { justify-content: stretch; }
  .onb-actions > * { flex: 1 1 auto; }
  .onb-plans { grid-template-columns: minmax(0, 1fr); }
  .onb-plan-card { min-height: 0; }
  .onb-wall { grid-template-columns: repeat(2, 1fr); }
  .onb-zoom { padding: 16px; }
  .onb-zoom-stage { gap: 8px; }
  .onb-zoom-img { max-width: calc(100% - 96px); }
  .onb-zoom-nav { width: 40px; height: 40px; }
}
@media (max-width: 520px) {
  .onb-url-shell .onb-cta { flex: 1 1 100%; }
  .onb-head.huge .onb-title, .onb-kit-step .onb-title { font-size: 36px; }
  .onb-title { font-size: 31px; }
}
@media (prefers-reduced-motion: reduce) {
  .onb *, .onb *::before, .onb *::after { animation: none !important; transition: none !important; }
}

/* ---------- reading a site or a product page, as it happens (`app/js/site-scan.js`) ----------
   The owner's two mockups: the page being read on the left, with a scan line and a dashed
   box round what was found; the kit or the product card filling on the right, a spinner
   turning into a check; a bar and the step underneath. Hosted by the Brand kit's «Import
   from the site» dialog (`.bk-modal-card.ss-host`) and by the product card's URL tab
   (`.pm-panel.pm-wide`), which both widen to hold it. */
.bk-modal-card.ss-host { width: min(1140px, 100%); padding: 0; }
.pm-panel.pm-wide { width: min(1140px, 100%); }
.pm-panel.pm-wide > #pm-title, .pm-panel.pm-wide > .hint, .pm-panel.pm-wide > .pm-close, .pm-panel.pm-wide > .pm-foot { display: none; }
.pm-panel > .ss-head { padding: 6px 4px 14px; }
.pm-panel > .ss-head[hidden] { display: none; }
.pm-pane[data-pane="url"] .ss { padding: 4px 2px 0; }

.ss { position: relative; padding: 30px 38px 24px; color: var(--text); }
.ss-host .ss { padding: 34px 40px 26px; }
.ss-head { position: relative; padding-right: 44px; }
.ss-kicker {
  display: flex; align-items: center; gap: 8px; margin: 0 0 14px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-2);
}
.ss-kicker svg { color: var(--accent); }
.ss-title { margin: 0; font-size: clamp(26px, 3.2vw, 40px); line-height: 1.08; font-weight: 800; letter-spacing: -.02em; color: var(--ink); }
.ss-sub { margin: 8px 0 0; font-size: 17px; color: var(--muted); }
.ss-x {
  position: absolute; top: -6px; right: -8px; width: 36px; height: 36px; display: grid; place-items: center;
  border: 0; border-radius: 10px; background: none; color: var(--ink-2); cursor: pointer;
}
.ss-x:hover { background: var(--panel-2); color: var(--ink); }

.ss-bar {
  display: flex; align-items: center; gap: 12px; margin: 22px 0 0; padding: 9px 10px 9px 16px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 14px; color: var(--ink-2);
}
.ss-url {
  flex: 1 1 auto; min-width: 0; border: 0; background: none; padding: 6px 0;
  font-size: 17px; font-weight: 600; color: var(--ink); outline: none; box-shadow: none;
}
.ss-url:read-only { cursor: default; }
.ss-status { display: inline-flex; align-items: center; gap: 8px; flex: none; font-size: 14px; font-weight: 600; color: var(--accent); white-space: nowrap; }
.ss-status[hidden] { display: none; }
.ss-dot {
  width: 10px; height: 10px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 22%, transparent); animation: ssPulse 1.4s ease-in-out infinite;
}
.ss[data-state="done"] .ss-status { color: #1f9d55; }
.ss[data-state="done"] .ss-dot { background: #1f9d55; box-shadow: 0 0 0 4px rgba(31, 157, 85, .18); animation: none; }
.ss[data-state="failed"] .ss-status { color: var(--danger, #d23c3c); }
.ss[data-state="failed"] .ss-dot { background: var(--danger, #d23c3c); box-shadow: none; animation: none; }
.ss-go { flex: none; display: inline-flex; align-items: center; gap: 7px; }
.ss-go[hidden] { display: none; }
.ss-price { font-weight: 500; opacity: .85; }

.ss-cols { display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr); gap: 32px; margin: 26px 0 0; }
.ss-col { min-width: 0; }
.ss-label { margin: 0 0 12px; font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-2); }

/* The page being read. */
.ss-browser {
  position: relative; overflow: hidden; background: var(--panel); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: 0 10px 30px -18px rgba(18, 18, 58, .35);
}
.ss-chrome { display: flex; align-items: center; gap: 7px; height: 42px; padding: 0 14px; background: var(--panel-2); border-bottom: 1px solid var(--border); }
.ss-chrome > i { width: 11px; height: 11px; border-radius: 50%; background: #ff5f57; }
.ss-chrome > i:nth-child(2) { background: #febc2e; }
.ss-chrome > i:nth-child(3) { background: #28c840; }
.ss-addr {
  display: inline-flex; align-items: center; gap: 7px; width: min(300px, 55%); margin: 0 auto; padding: 5px 12px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px; font-size: 12.5px; color: var(--ink-2);
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.ss-page { position: relative; min-height: 330px; padding: 20px 24px 22px; }
/* The page as Extracto's browser saw it, in place of the rebuilt one. */
.ss[data-shot="on"] .ss-page { padding: 0; min-height: 0; }
.ss-shot { display: block; width: 100%; height: auto; }
.ss-scanline {
  position: absolute; left: 0; right: 0; top: 60px; height: 2px; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent, var(--accent) 18%, var(--accent) 82%, transparent);
  box-shadow: 0 0 22px 7px color-mix(in srgb, var(--accent) 35%, transparent);
}
.ss[data-state="reading"] .ss-scanline, .ss[data-state="preview"] .ss-scanline { opacity: 1; animation: ssScan 3.2s ease-in-out infinite alternate; }

.ss-skel {
  display: block; height: 12px; border-radius: 6px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--ink) 7%, transparent), color-mix(in srgb, var(--ink) 13%, transparent), color-mix(in srgb, var(--ink) 7%, transparent));
  background-size: 200% 100%; animation: ssShimmer 1.6s linear infinite;
}
.ss-skel + .ss-skel { margin-top: 9px; }
.ss-skel.pill { display: inline-block; width: 30%; height: 26px; border-radius: 999px; margin: 0 6px 0 0 !important; }
.ss-skel-row { display: flex; align-items: center; gap: 16px; }
.ss-skel-row .ss-skel { margin: 0; }
.ss-skel.logo { width: 110px; height: 30px; }
.ss-skel.nav { width: 54px; height: 9px; }
.ss-skel-hero { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 30px; align-items: center; }
.ss-skel.h { height: 26px; width: 92%; }
.ss-skel.h.short { width: 62%; }
.ss-skel.p { width: 80%; height: 9px; }
.ss-skel.btn { width: 46%; height: 30px; border-radius: 999px; margin-top: 18px; }
.ss-skel.img { height: 200px; border-radius: 12px; }

/* What was found, said with a dashed box and its label. */
.ss-spot { position: relative; display: inline-flex; border-radius: 4px; }
.ss[data-state="preview"] .ss-spot, .ss[data-state="done"] .ss-spot { outline: 2px dashed var(--accent); outline-offset: 5px; }
.ss[data-state="preview"] .ss-spot::before, .ss[data-state="done"] .ss-spot::before {
  content: attr(data-label); position: absolute; left: -7px; top: -34px; z-index: 2; padding: 3px 9px; white-space: nowrap;
  font-size: 11.5px; font-weight: 600; color: #fff; background: var(--accent); border-radius: 6px;
}

/* A site, rebuilt. */
.ss-site-nav { display: flex; align-items: center; gap: 18px; margin-top: 18px; min-height: 40px; }
.ss-site-nav > svg { margin-left: auto; color: var(--ink); flex: none; }
.ss-site-links { display: flex; gap: 18px; margin-left: auto; font-size: 12px; color: var(--ink); overflow: hidden; white-space: nowrap; }
.ss-brandmark { display: inline-flex; align-items: center; max-width: 180px; min-height: 30px; }
.ss-brandmark.on-dark { padding: 6px 10px; border-radius: 6px; background: #111; }
.ss-brandmark-sprite { display: block; flex: none; background-repeat: no-repeat; }
/* The site's header as a bar of its own colour, across the page's width. */
.ss-site-nav.has-bar { margin: -20px -24px 0; padding: 12px 24px; }
.ss-site-nav .ss-site-links { color: inherit; }
.ss-site-nav > svg { color: inherit; }
.ss-brandmark-img { max-height: 40px; max-width: 180px; object-fit: contain; display: block; }
.ss-wordmark { font-family: Georgia, 'Times New Roman', serif; font-size: 19px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink); }
.ss-hero { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px; align-items: center; margin-top: 26px; }
.ss-headline { margin: 0; font-family: system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-weight: 700; font-size: clamp(24px, 2.6vw, 38px); line-height: 1.04; color: var(--ink); overflow-wrap: anywhere; }
.ss-hero-text { margin: 12px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.ss-cta { display: inline-flex; align-items: center; gap: 8px; margin-top: 18px; padding: 9px 18px; border-radius: 999px; background: var(--ink); color: var(--panel); font-size: 12.5px; font-weight: 600; }
.ss-hero-pic { position: relative; aspect-ratio: 4 / 3; border-radius: 14px; overflow: hidden; background: var(--panel-2); }
.ss-hero-pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ss-hero-pic.empty { background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 14%, var(--panel-2)), var(--panel-2)); }

/* A product page, rebuilt. */
.ss-shop-top { display: flex; align-items: center; gap: 14px; color: var(--ink); }
.ss-search { flex: 1 1 auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; padding: 7px 12px; border: 1px solid var(--border); border-radius: 999px; font-size: 11.5px; color: var(--muted); }
.ss-shop-nav { display: flex; gap: 16px; margin: 14px 0 0; padding: 0 0 10px; border-bottom: 1px solid var(--border); font-size: 12px; color: var(--ink-2); overflow: hidden; white-space: nowrap; }
.ss-shop-nav span:last-child { color: var(--accent); }
.ss-pdp { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 20px; margin-top: 30px; }
.ss-pdp-photo { display: grid; place-items: center; width: 100%; aspect-ratio: 1; border-radius: 10px; background: var(--panel-2); color: var(--muted); overflow: visible; }
.ss-pdp-photo img { width: 100%; height: 100%; object-fit: contain; border-radius: 10px; }
.ss-thumbs { display: flex; gap: 8px; margin-top: 10px; }
.ss-thumb { width: 46px; height: 46px; border-radius: 8px; border: 1px solid var(--border); overflow: hidden; background: var(--panel-2); }
.ss-thumb:first-child { border-color: var(--accent); }
.ss-thumb img { width: 100%; height: 100%; object-fit: cover; }
.ss-pdp-name { margin: 0; font-size: 19px; line-height: 1.25; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.ss-pdp-price { margin: 12px 0 0; font-size: 21px; color: var(--ink); }
.ss-pdp-price s { font-size: 14px; color: var(--muted); }
.ss-pdp-price b { font-weight: 800; }
.ss-avail { display: flex; align-items: center; gap: 7px; margin: 8px 0 0; font-size: 12.5px; color: var(--ink-2); }
.ss-avail i { width: 8px; height: 8px; border-radius: 50%; background: #1f9d55; }
.ss-avail.out i { background: var(--muted); }
.ss-buy-row { display: flex; gap: 10px; margin-top: 16px; }
.ss-buy { display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px; border-radius: 9px; background: #135c3d; color: #fff; font-size: 13px; font-weight: 600; }
.ss-heart { display: grid; place-items: center; width: 40px; border: 1px solid var(--border); border-radius: 9px; color: var(--ink); }

/* The kit, or the product card, filling. */
.ss-cards { display: grid; gap: 12px; }
.ss-card { position: relative; padding: 16px 52px 16px 18px; background: var(--panel); border: 1px solid var(--border); border-radius: 14px; min-width: 0; }
.ss-card-label { display: flex; align-items: center; gap: 9px; margin: 0; font-size: 14px; font-weight: 600; color: var(--ink); }
.ss-card-label svg { color: var(--ink-2); flex: none; }
.ss-card-body { margin-top: 12px; min-width: 0; }
.ss-value { margin: 0; font-size: 19px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.ss-name-body { display: flex; align-items: center; gap: 16px; }
.ss-name-body .ss-value { flex: 1 1 auto; }
.ss-mark-tile {
  flex: none; display: grid; place-items: center; width: 70px; height: 70px; border-radius: 12px; overflow: hidden;
  background: #14163d; color: #fff; font-family: Georgia, 'Times New Roman', serif; font-size: 34px;
}
.ss-mark-tile:has(img), .ss-mark-tile.has-sprite { background: #fff; border: 1px solid var(--border); }
/* A sprite's piece in the tile, scaled down from its own size around its middle. */
.ss-mark-sprite { display: block; flex: none; transform-origin: center; }
.ss-mark-tile.on-dark:has(img) { background: #111; border-color: #111; }
.ss-mark-img { max-width: 84%; max-height: 84%; object-fit: contain; }
.ss-swatches { display: flex; gap: 10px; }
.ss-swatch { width: 66px; height: 50px; border-radius: 10px; background: color-mix(in srgb, var(--ink) 7%, transparent); transition: background-color .4s, transform .4s; }
.ss-swatch.on { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08); }
.ss-pills { display: flex; flex-wrap: wrap; gap: 7px; }
.ss-chip { padding: 5px 12px; border-radius: 999px; background: var(--panel-2); border: 1px solid var(--border); font-size: 13px; color: var(--ink); }
.ss-muted, .ss-desc { margin: 0; font-size: 13px; color: var(--muted); }
.ss-desc { color: var(--ink-2); line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.ss-card-main { display: grid; grid-template-columns: 116px minmax(0, 1fr); gap: 18px; align-items: center; }
.ss-photo { display: grid; place-items: center; width: 116px; height: 116px; border-radius: 12px; overflow: hidden; background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); }
.ss-photo img { width: 100%; height: 100%; object-fit: contain; }
.ss-main-info .ss-card-label { margin-top: 10px; font-size: 12.5px; font-weight: 500; color: var(--ink-2); }
.ss-main-info .ss-value { margin-top: 4px; font-size: 17px; }
.ss-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 8px; background: rgba(31, 157, 85, .12); color: #1a7f46; font-size: 12px; font-weight: 600; }
.ss-badge[hidden] { display: none; }
.ss-halves { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.ss-card.half .ss-card-label { font-size: 12.5px; font-weight: 500; color: var(--ink-2); }
.ss-card.half .ss-card-body { margin-top: 6px; }

/* The marks: waiting, working, found, not found. */
.ss-st { position: absolute; right: 16px; top: 50%; translate: 0 -50%; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; }
.ss-st[data-st="wait"] { border: 2px solid var(--border); }
.ss-st[data-st="spin"] { border: 2.5px solid color-mix(in srgb, var(--accent) 20%, transparent); border-top-color: var(--accent); animation: ssSpin .9s linear infinite; }
.ss-st[data-st="ok"] { background: rgba(31, 157, 85, .14); color: #1a7f46; }
.ss-st[data-st="none"] { border: 2px dashed var(--border); }
.ss-card-main > .ss-st { top: 22px; translate: none; }

/* The bar, the step and the way on. */
.ss-foot { margin-top: 26px; }
.ss-progress { height: 8px; border-radius: 999px; background: color-mix(in srgb, var(--ink) 8%, transparent); overflow: hidden; }
.ss-progress > i { display: block; height: 100%; width: 0; border-radius: inherit; background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 70%, #ff7bb5)); transition: width .35s ease; }
.ss-foot-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; margin-top: 16px; }
.ss-foot-words { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex: 1 1 auto; min-width: 0; flex-wrap: wrap; }
.ss-step { margin: 0; font-size: 14.5px; color: var(--ink); }
.ss-step.err { color: var(--danger, #d23c3c); }
.ss-note { display: inline-flex; align-items: center; gap: 7px; margin: 0; font-size: 13px; color: var(--muted); }
.ss-actions { display: flex; gap: 10px; flex: none; }
.ss-actions [hidden] { display: none; }
.ss-demo { margin: 6px 0 0; text-align: right; font-size: 11px; color: var(--muted); }

/* The colour picked off the page, on its way to the palette. */
.ss-trail { position: absolute; inset: 0; pointer-events: none; z-index: 4; overflow: visible; transition: opacity .4s; }
.ss-trail path { fill: none; stroke: var(--accent); stroke-width: 2; stroke-dasharray: 5 6; opacity: .75; }
.ss-trail.gone { opacity: 0; }
.ss-fly { position: absolute; z-index: 5; width: 28px; height: 28px; border-radius: 8px; box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--accent), 0 8px 20px -6px rgba(0, 0, 0, .4); pointer-events: none; }

@keyframes ssScan { from { top: 56px; } to { top: calc(100% - 14px); } }
@keyframes ssShimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@keyframes ssSpin { to { rotate: 360deg; } }
@keyframes ssPulse { 50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--accent) 10%, transparent); } }

@media (max-width: 900px) {
  .ss, .ss-host .ss { padding: 22px 16px 18px; }
  .ss-cols { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .ss-bar { flex-wrap: wrap; }
  .ss-url { flex-basis: 60%; }
  .ss-foot-row { flex-direction: column; align-items: stretch; }
  .ss-actions { justify-content: flex-end; }
}
@media (max-width: 520px) {
  .ss-hero, .ss-pdp, .ss-skel-hero { grid-template-columns: minmax(0, 1fr); }
  .ss-site-links, .ss-shop-nav span:nth-child(n + 4) { display: none; }
  .ss-card-main { grid-template-columns: 84px minmax(0, 1fr); }
  .ss-photo { width: 84px; height: 84px; }
  .ss-swatch { width: 52px; height: 40px; }
}
@media (prefers-reduced-motion: reduce) {
  .ss-scanline, .ss[data-state="reading"] .ss-scanline, .ss[data-state="preview"] .ss-scanline { animation: none; opacity: 0; }
  .ss-skel, .ss-dot, .ss-st[data-st="spin"] { animation: none; }
  .ss-progress > i, .ss-swatch { transition: none; }
}

/* ---------- a product photo, a little larger under the pointer ----------
   The owner's ask: passing over a photo of the product should show it a little better.
   The tile grows over its neighbours rather than inside its own box, where a zoom would
   only crop it — downwards, over the hint under the strip, and from its left edge for the
   first, because the form's scrolling body would cut what grew past its own edge. */
.pm-shot { transition: transform .16s ease, box-shadow .16s ease; transform-origin: center top; }
.pm-shot:first-child { transform-origin: left top; }
.pm-shot:hover { transform: scale(1.28); z-index: 3; box-shadow: 0 10px 26px -8px rgba(18, 18, 58, .45); }
/* The last column of the row grows to the left: a photo that grew past the form's right edge gave its scrolling body a
   sideways scrollbar, on a platform that keeps one, and the row moved under the pointer. */
.pm-shot-row > .pm-shot:nth-child(4n) { transform-origin: right top; }
@media (prefers-reduced-motion: reduce) {
  .pm-shot { transition: none; }
}
/* The same on the Products tab: the photo grows inside its own frame, which the card's
   rounded corner keeps. */
.bp-card .bk-media img { transition: transform .2s ease; }
.bp-card:hover .bk-media img { transform: scale(1.08); }
@media (prefers-reduced-motion: reduce) {
  .bp-card .bk-media img { transition: none; }
}

/* ---- Generations › Studio, as mockups 62 and 63 draw it ----
   No white card round it: a title with its line and the one action, the switch with its counts,
   then the search on the left and the order and the view on the right, over borderless cards. */
.gens-card.sdocs-pane { padding: 0; background: transparent; border: 0; box-shadow: none; }
.sdocs-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin: 6px 0 18px; }
.sdocs-head h2 { margin: 0; font-size: 28px; font-weight: 800; letter-spacing: -.01em; text-transform: none; color: var(--ink); }
.sdocs-head p { margin: 4px 0 0; font-size: 16px; color: var(--muted); }
.sdocs-new { display: inline-flex; align-items: center; gap: 9px; flex: none; height: 44px; padding: 0 20px; border-radius: 11px; font-size: 15.5px; font-weight: 700; white-space: nowrap; }
.sdocs-new .sd-ic { stroke-width: 2.2; }
.sdocs-kinds { display: inline-flex; width: fit-content; max-width: 100%; gap: 4px; padding: 4px; border-radius: 12px; background: var(--sd-field, var(--panel-2)); }
.sdocs-kind {
  display: inline-flex; align-items: center; gap: 10px; height: 36px; padding: 0 16px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--muted); font: inherit; font-size: 14.5px; font-weight: 600; white-space: nowrap; cursor: pointer;
}
.sdocs-kind:hover { color: var(--text); }
.sdocs-kind.on { background: var(--panel); color: var(--ink); box-shadow: 0 1px 3px rgba(12, 12, 14, .08); }
.sdocs-kind-n:empty { display: none; }
.sdocs-kind-n { min-width: 22px; padding: 1px 7px; border-radius: 999px; font-size: 12.5px; font-weight: 700; text-align: center; color: var(--muted); }
.sdocs-kind.on .sdocs-kind-n { color: var(--accent); background: var(--accent-soft); }
.sdocs-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 18px 0 4px; }
.sdocs-find { flex: 0 1 440px; }
.sdocs-find .gens-search { height: 42px; border-radius: 10px; background: var(--panel); }
.sdocs-pane .gens-select { height: 42px; border-radius: 10px; }
.gens-card.sdocs-pane .sdocs-grid { grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr)); gap: 26px 22px; margin-top: 22px; }
/* The card is its picture and two lines: no frame round it, as the mockups draw it. */
.sdocs-pane .sdoc { padding: 0; border: 0; border-radius: 0; background: transparent; }
.sdocs-pane .sdoc:hover { border-color: transparent; }
.sdocs-pane .sdoc:hover .sdoc-shot { border-color: var(--accent-line); }
.sdocs-pane .sdoc-shot { border-radius: 12px; }
.sdocs-pane .sdoc-foot { grid-template-columns: minmax(0, 1fr) auto; padding: 10px 2px 0; row-gap: 3px; }
.sdocs-pane .sdoc-name {
  min-width: 0; padding: 0; border: 0; background: transparent; cursor: pointer; text-align: left;
  font: inherit; font-size: 15px; font-weight: 700; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sdocs-pane .sdoc-name:hover { color: var(--accent-ink, var(--accent)); }
.sdoc-meta { grid-column: 1 / -1; min-width: 0; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A cut's tile: its frame contained on a grey ground, the film mark and its length over it. */
.sdoc-shot-video { background: color-mix(in srgb, var(--ink) 7%, var(--panel)); }
.sdoc-shot-video img, .sdoc-shot-video video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; }
.sdoc-film {
  position: absolute; top: 10px; left: 10px; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  background: color-mix(in srgb, var(--panel) 88%, transparent); color: var(--ink); box-shadow: 0 1px 3px rgba(12, 12, 14, .12);
}
.sdoc-length {
  position: absolute; right: 10px; bottom: 10px; padding: 3px 8px; border-radius: 7px;
  background: rgba(12, 12, 14, .72); color: #fff; font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.sdoc-shot-video .sdoc-now { top: 14px; left: 48px; }
/* A cut with nothing on it: «Draft», the camera and «No clips». */
.sdoc-shot-draft { background: color-mix(in srgb, var(--ink) 5%, var(--panel)); }
.sdoc-draft {
  position: absolute; top: 10px; left: 10px; padding: 3px 9px; border-radius: 7px;
  background: color-mix(in srgb, var(--ink) 55%, transparent); color: #fff; font-size: 12px; font-weight: 600;
}
.sdoc-empty { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--muted); font-size: 14px; }
/* A tile with no picture keeps its size and shows which editor the work is from. */
.sdoc-blank { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); }
.sdocs-pane .sdocs-grid[data-as="list"] .sdoc { gap: 18px; }
.sdocs-pane .sdocs-grid[data-as="list"] .sdoc-foot { grid-template-columns: minmax(0, 1fr) auto; }

/* The four tokens of the word diff (word-diff.js), in the studio's own block after the copied range: the panel's stylesheet
   copies that range byte for byte (test/build.test.js), and the panel keeps its own copy of these four in its own block. */
:root {
  /* The change in the debug drawer (app/js/debug-drawer.js) and in the panel's «Ask why»: a removed line, an added line,
     and the words that changed in each. They sit on --panel-2, and the text is --text on all four: 14.3:1 on a removed line,
     14.6:1 on an added one, 11.3:1 and 12.1:1 on the changed words. */
  --diff-del: rgba(190, 30, 30, .08);
  --diff-del-hit: rgba(190, 30, 30, .22);
  --diff-add: rgba(15, 138, 95, .09);
  --diff-add-hit: rgba(15, 138, 95, .24);
}
:root[data-theme="dark"] {
  /* The same four in the dark theme, measured on the dark --panel-2: 11.3:1 on a removed line, 11.0:1 on an added one,
     7.7:1 and 7.1:1 on the changed words. */
  --diff-del: rgba(255, 143, 143, .1);
  --diff-del-hit: rgba(255, 143, 143, .28);
  --diff-add: rgba(74, 222, 128, .1);
  --diff-add-hit: rgba(74, 222, 128, .28);
}

/* ---------- Debug mode (app/js/debug-drawer.js) ----------
   A side drawer on the open project, for the team's debuggers only. The word diff is the panel's «Ask why» diff, with the
   same classes and the same tokens: `word-diff*` is drawn by app/js/word-diff.js, which both bundles share. */
.debug-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 70; display: flex; flex-direction: column; gap: 10px;
  box-sizing: border-box; width: min(460px, 100vw); padding: 16px 18px;
  background: var(--panel); border-left: 1px solid var(--border); box-shadow: var(--shadow-3);
}
.debug-head { display: flex; align-items: flex-start; gap: 12px; }
.debug-id { flex: 1; min-width: 0; }
.debug-head h2 { margin: 0; font-size: 18px; line-height: 1.25; letter-spacing: -.015em; }
.debug-sub { margin: 4px 0 0; font-size: 12.5px; line-height: 1.5; }
.debug-focus {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 6px 10px;
  font-size: 12.5px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
}
.debug-focus span { font-family: var(--mono); font-size: 12px; overflow-wrap: anywhere; }
.debug-log { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; padding-right: 4px; }
.debug-q, .debug-a, .debug-draft { display: flex; flex-direction: column; gap: 6px; }
.debug-label { font-size: 10.5px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; color: var(--muted); }
.debug-text { margin: 0; font-size: 13px; line-height: 1.5; white-space: pre-line; overflow-wrap: anywhere; }
.debug-causes {
  margin: 0; padding-left: 18px; display: grid; gap: 6px; font-size: 12.5px; line-height: 1.45; overflow-wrap: anywhere;
}
.debug-causes code { font-family: var(--mono); font-size: 11.5px; }
.debug-link {
  padding: 0; font: inherit; font-size: 12px; color: var(--accent-ink); background: none; border: 0; cursor: pointer;
  text-decoration: underline; text-underline-offset: 2px;
}
.debug-link:hover { color: var(--accent); }
.debug-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }
.debug-draft { padding: 9px 11px; background: var(--panel); border: 1px solid var(--border); border-radius: 8px; }
.debug-draft > .hint { margin: 0; }
.debug-diff > .hint { margin: 0 0 6px; }
.debug-note { display: flex; flex-direction: column; gap: 4px; }
.debug-note textarea { margin: 0; font-size: 13px; }
.debug-draft > .btn { align-self: flex-start; }
.debug-saved { margin: 0; }
.debug-form { display: flex; align-items: flex-end; gap: 8px; }
.debug-input { flex: 1 1 auto; min-width: 0; min-height: 58px; margin: 0; font-size: 13px; }
.debug-status { margin: 0; }
.debug-status:empty, .debug-empty { margin: 0; }
.debug-status:empty { display: none; }
.debug-this { margin-top: 4px; padding: 2px 9px; font-size: 11.5px; align-self: flex-start; }
.gp-debug-why { font-size: 12px; }
/* Lit for a moment: the message or picture a cause points at. Under reduced motion it stays lit for the same time, without moving. */
.debug-flash { border-radius: 8px; outline: 2px solid var(--accent); outline-offset: 3px; animation: debug-flash 1.8s ease-out; }
@keyframes debug-flash {
  from { outline-color: var(--accent); }
  to { outline-color: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .debug-flash { animation: none; }
}
.word-diff {
  max-height: 340px; overflow: auto; padding: 6px 0; font-family: var(--mono); font-size: 12px; line-height: 1.5;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
}
.word-diff-row { min-height: 1.5em; padding: 0 10px 0 6px; white-space: pre-wrap; overflow-wrap: anywhere; }
.word-diff-del { background: var(--diff-del); }
.word-diff-add { background: var(--diff-add); }
.word-diff-sign { display: inline-block; width: 1.2em; color: var(--muted); user-select: none; }
.word-diff-hit { border-radius: 3px; }
.word-diff-del .word-diff-hit { background: var(--diff-del-hit); }
.word-diff-add .word-diff-hit { background: var(--diff-add-hit); }

/* ---------- Reference ads and their recreation (docs/recreate.md) ----------
   `rl-` for the library under Setup → Competitors, `rc-` for the window that recreates one,
   `rcc-` for the comparison. Never «ads» in a name: EasyList hides `.ads-*`. */
.rl-card { margin-top: 18px; }
.rl-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.rl-title { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.rl-sub { margin: 4px 0 0; max-width: 62ch; font-size: 14.5px; color: var(--muted); }
.rl-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.rl-status { min-height: 1.4em; margin: 10px 0 0; }
.rl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; margin-top: 12px; }
.rl-empty { grid-column: 1 / -1; margin: 6px 0; color: var(--muted); }
.rl-clip { display: flex; flex-direction: column; min-width: 0; overflow: hidden; border: 1px solid var(--border); border-radius: 12px; background: var(--panel-2); }
.rl-frame { position: relative; aspect-ratio: 16 / 10; background: var(--solid); }
.rl-frame video { width: 100%; height: 100%; object-fit: contain; display: block; }
.rl-length { position: absolute; right: 8px; bottom: 8px; padding: 2px 6px; border-radius: 6px; font: 12px var(--mono); color: var(--on-solid); background: rgba(0, 0, 0, 0.55); }
.rl-body { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px 4px; min-width: 0; }
.rl-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.rl-meta { margin: 0; font-size: 13px; color: var(--muted); }
.rl-state { align-self: flex-start; padding: 1px 8px; border-radius: 999px; font-size: 12px; color: var(--muted); border: 1px solid var(--border); }
.rl-state.on { color: var(--accent-ink); border-color: var(--accent); }
.rl-card-actions { display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 12px 12px; }
.rl-made { margin-top: 18px; }
.rl-made-title { margin: 0 0 8px; font-size: 15px; color: var(--ink); }
.rl-made-list { display: flex; flex-direction: column; gap: 6px; }
.rl-rec { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto auto auto; align-items: center; gap: 12px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 10px; font-size: 13.5px; }
.rl-rec-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-weight: 600; }
.rl-rec-what, .rl-rec-when { color: var(--muted); }
.rl-rec.refunded .rl-rec-state, .rl-rec.failed .rl-rec-state { color: var(--danger); }
.rl-pick { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 12px; }
.rl-pick-item { display: flex; flex-direction: column; gap: 6px; padding: 8px; text-align: left; border: 1px solid var(--border); border-radius: 10px; background: var(--panel-2); color: var(--text); cursor: pointer; }
.rl-pick-item:hover { border-color: var(--accent); }
.rl-pick-item video { width: 100%; aspect-ratio: 16 / 10; object-fit: contain; background: var(--solid); border-radius: 6px; }
@media (max-width: 720px) { .rl-rec { grid-template-columns: minmax(0, 1fr) auto; } .rl-rec-what, .rl-rec-when { display: none; } }

.rc-sheet .sheet-card { width: min(1240px, 96vw); }
.rc { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(300px, 1fr); gap: 20px; align-items: start; }
.rc[hidden] { display: none; }
.rc-stage { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.rc-video { width: 100%; max-height: 52vh; background: var(--solid); border-radius: 10px; }
.rc-track { position: relative; height: 30px; border-radius: 8px; background: var(--panel-2); border: 1px solid var(--border); overflow: hidden; }
.rc-scene { position: absolute; top: 3px; bottom: 3px; border: 0; border-right: 2px solid var(--panel); border-radius: 4px; background: var(--accent-soft); cursor: pointer; }
.rc-scene:hover, .rc-scene:focus-visible { background: var(--accent); outline: none; }
.rc-sel { position: absolute; top: 0; bottom: 0; border: 2px solid var(--accent); border-radius: 6px; pointer-events: none; }
.rc-range { display: flex; flex-wrap: wrap; align-items: end; gap: 8px; }
.rc-field, .rcc-field { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; color: var(--muted); }
.rc-field input, .rcc-field input { width: 92px; font-family: var(--mono); }
.rc-length { margin-left: auto; font: 14px var(--mono); color: var(--ink); }
.rc-segments { display: flex; flex-wrap: wrap; gap: 6px; }
.rc-analysis { padding: 12px; border: 1px solid var(--border); border-radius: 10px; }
.rc-analysis-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.rc-facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 4px 12px; margin: 8px 0 0; font-size: 13.5px; }
.rc-facts dt { color: var(--muted); }
.rc-facts dd { margin: 0; color: var(--text); }
.rc-side { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.rc-step { padding: 12px; border: 1px solid var(--border); border-radius: 10px; }
.rc-step[hidden] { display: none; }
.rc-step h3 { margin: 0 0 8px; font-size: 14.5px; color: var(--ink); }
.rc-step-body { display: flex; flex-direction: column; gap: 8px; }
.rc-line { margin: 0; font-size: 13.5px; }
.rc-toggle { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.rc-shots { display: flex; flex-wrap: wrap; gap: 8px; }
.rc-shot { position: relative; width: 64px; height: 64px; border: 2px solid var(--border); border-radius: 8px; overflow: hidden; cursor: pointer; }
.rc-shot.on { border-color: var(--accent); }
.rc-shot input { position: absolute; top: 3px; left: 3px; }
.rc-shot img { width: 100%; height: 100%; object-fit: cover; }
.rc-people { display: flex; flex-wrap: wrap; gap: 8px; }
.rc-person { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 84px; padding: 6px; border: 2px solid var(--border); border-radius: 10px; background: var(--panel-2); color: var(--text); font-size: 12px; cursor: pointer; }
.rc-person.on { border-color: var(--accent); }
.rc-person img { width: 64px; height: 64px; object-fit: cover; border-radius: 50%; }
.rc-row { display: flex; flex-wrap: wrap; gap: 6px; }
.rc-words { width: 100%; resize: vertical; }
.rc-setting { width: 100%; max-height: 180px; object-fit: contain; border-radius: 8px; background: var(--solid); }
.rc-foot { display: flex; flex-direction: column; gap: 8px; padding-top: 4px; }
.rc-foot-note { margin: 0; }
.rc-progress { min-height: 1.4em; margin: 0; }
@media (max-width: 860px) { .rc { grid-template-columns: minmax(0, 1fr); } }

.rcc { display: flex; flex-direction: column; gap: 12px; }
.rcc-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.rcc-side { margin: 0; display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.rcc-side video { width: 100%; max-height: 50vh; background: var(--solid); border-radius: 10px; }
.rcc-side figcaption { font-size: 13px; font-weight: 600; color: var(--muted); }
.rcc-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rcc-scrub { flex: 1; min-width: 160px; accent-color: var(--accent); }
.rcc-clock { font: 13px var(--mono); color: var(--muted); }
.rcc-facts { display: flex; flex-direction: column; gap: 2px; margin: 0; font-size: 13.5px; color: var(--text); }
.rcc-trim { display: flex; flex-wrap: wrap; align-items: end; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; }
.rcc-here { display: flex; gap: 6px; }
.rcc-check { padding: 12px; border: 1px solid var(--border); border-radius: 10px; }
.rcc-check-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.rcc-verdicts { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 0; padding: 0; list-style: none; }
.rcc-verdict { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; font-size: 13.5px; }
.rcc-v-name { min-width: 150px; font-weight: 600; color: var(--ink); }
.rcc-v-chip { padding: 1px 8px; border-radius: 999px; font-size: 12px; border: 1px solid var(--border); color: var(--muted); }
.rcc-verdict.ok .rcc-v-chip { color: var(--ok); border-color: var(--ok); }
.rcc-verdict.warn .rcc-v-chip { color: var(--warn); border-color: var(--warn); }
.rcc-verdict.fail .rcc-v-chip { color: var(--danger); border-color: var(--danger); }
.rcc-v-note { flex: 1 1 240px; color: var(--text); }
.rcc-at { padding: 0 6px; border: 1px solid var(--border); border-radius: 6px; background: transparent; font: 12px var(--mono); color: var(--accent-ink); cursor: pointer; }
.rcc-note { margin: 8px 0 0; }
.rcc-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; }
.rcc-said { margin: 0 auto 0 0; }
@media (max-width: 720px) { .rcc-pair { grid-template-columns: 1fr; } }

/* Sub-companies (PR-24, plan 9.6): the section's own column. The table scrolls sideways inside its card rather than
   pushing the page wider than a phone, and the figures sit on the right, where a balance is read. */
.chl-view { container: chl / inline-size; padding: 10px 8px 36px; }
.chl-view > * { max-width: 1220px; }
.chl-view .chl-pane { overflow-x: auto; }
.chl-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.chl-table th, .chl-table td { padding: 9px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.chl-table th { font-size: 12px; font-weight: 600; color: var(--muted); }
.chl-table tr.chl-off td:first-child { color: var(--muted); }
.chl-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.chl-num.up { color: var(--ok); }
.chl-num.down { color: var(--danger); }
.chl-actions { white-space: nowrap; }

/* White label (PR-24B): the screen's own column, as Sub-companies has. Each card is its own box with its padding, and the
   records table scrolls inside its card; a long record value breaks rather than widening the page (a 2000px DKIM key did). */
/* The Team screen: one card per subject, in the column of the Settings screen. A card is its own box, so a list in it is
   measured against the card and not against the page. */
/* The header: a small eyebrow, the name with its pencil, the lead and the seats; «Invite» sits at the end and wraps under on a phone. */
/* The rows of the members and of the invitations: an avatar, the name and address, then the role and the actions, wrapping on a phone. */
.chl-actions .btn { margin-right: 6px; }
.chl-actions .btn:disabled { opacity: .55; cursor: default; }
.chl-figures { display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0 0 18px; font-size: 14px; }
.chl-figures dt { color: var(--muted); }
.chl-figures dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.chl-block, .chl-movements { margin: 18px 0 0; }
.chl-block h3, .chl-movements h3, .chl-mail-history h3 { margin: 0 0 8px; font-size: 14px; }
.chl-link { background: none; border: 0; padding: 0; font: inherit; color: var(--accent-ink); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.chl-mail { display: grid; gap: 10px; max-width: 680px; }
.chl-mail-subject, .chl-mail-body, .chl-new-input { width: 100%; box-sizing: border-box; font: inherit; padding: 9px 11px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); }
.chl-mail-body { resize: vertical; }
.chl-mail-state.on { color: var(--ok); }
.chl-mail-state.off { color: var(--danger); }
.chl-mail-row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 12px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid var(--border); }
/* The header: the title and its line on the left, the mailing (secondary) and the new company (primary) on the right. */
.chl-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 14px 24px; margin: 0 0 22px; }
.chl-head-text { min-width: 0; flex: 1 1 320px; }
.chl-head-text .set-sub { max-width: 60ch; }
.chl-head-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.chl-mail-pane { margin-top: 16px; }
/* The opening form, in its sheet: a label over each field, and the help under it. */
.chl-new-form { display: grid; gap: 14px; }
.chl-new-field { display: grid; gap: 4px; font-size: 13px; color: var(--muted); }
.chl-new-field > span.hint { font-size: 12.5px; }
.chl-name { font-weight: 600; color: var(--ink); }
.chl-empty-cta { margin-top: 14px; }
/* On a phone each company is a card: the name on top, the figures as label/value lines, the actions wrapped at the foot. */
@media (max-width: 720px) {
  .chl-view .chl-pane { overflow-x: visible; }
  .chl-table thead { display: none; }
  .chl-table, .chl-table tbody { display: block; width: 100%; }
  .chl-table tr { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 6px 14px; padding: 14px 0; border-bottom: 1px solid var(--border); }
  .chl-table td { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; min-width: 0; padding: 0; border: 0; text-align: right; white-space: normal; }
  .chl-table td::before { content: attr(data-label); font-size: 12.5px; color: var(--muted); text-align: left; }
  .chl-table td.chl-name { grid-column: 1 / -1; display: flex; justify-content: flex-start; align-items: center; font-size: 15px; text-align: left; }
  .chl-table td.chl-name::before { content: none; }
  .chl-table td.chl-actions { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
  .chl-table td.chl-actions::before { content: none; }
  .chl-actions .btn { margin-right: 0; }
}

/* ===================== White label (2026-10-26) =====================
   Two panes under one switch: the brand, a form in sections beside a live preview of what
   a client sees, and the domain and its mail. The preview takes the draft's tokens on its own
   element (`paintPreview` in `whitelabel.js`), so nothing here reaches past it. */
.wl-view { container: wl / inline-size; padding: 10px 8px 48px; }
.wl-view > * { max-width: 1220px; }
.wl-view .wl-head { margin: 0 0 16px; }
.wl-view .wl-needs:not([hidden]) { padding: 10px 14px; border-radius: 10px; background: var(--warn-soft); border: 1px solid var(--warn-line); color: var(--text); }
.wl-view .wl-status:empty { display: none; }

.wl-live-card { display: flex; align-items: center; gap: 14px; padding: 14px 18px; margin: 0 0 18px; border-radius: 14px; border: 1px solid var(--border); background: var(--panel); }
.wl-live-card.on { border-color: color-mix(in srgb, var(--ok) 35%, var(--border)); background: color-mix(in srgb, var(--ok) 6%, var(--panel)); }
.wl-live-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: var(--muted); box-shadow: 0 0 0 4px color-mix(in srgb, var(--muted) 18%, transparent); }
.wl-live-card.on .wl-live-dot { background: var(--ok); box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 20%, transparent); animation: wl-pulse 2.4s ease-in-out infinite; }
@keyframes wl-pulse { 50% { box-shadow: 0 0 0 7px color-mix(in srgb, var(--ok) 8%, transparent); } }
.wl-live-words { flex: 1; min-width: 0; display: grid; gap: 2px; }
.wl-live-title { font-size: 14.5px; color: var(--ink); }
.wl-live-card .wl-live { margin: 0; font-size: 13px; color: var(--muted); }

/* The switch: a checkbox drawn as a track. */
.wl-switch { flex: none; display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--ink); }
.wl-switch-input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.wl-switch-track { position: relative; width: 40px; height: 22px; border-radius: 999px; background: var(--border); transition: background .18s; }
.wl-switch-track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: var(--shadow-1); transition: transform .18s; }
.wl-switch-input:checked + .wl-switch-track { background: var(--ok); }
.wl-switch-input:checked + .wl-switch-track::after { transform: translateX(18px); }
.wl-switch-input:focus-visible + .wl-switch-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.wl-switch-input:disabled + .wl-switch-track { opacity: .5; }

.wl-seg { display: inline-flex; gap: 4px; padding: 4px; margin: 0 0 18px; border-radius: 12px; background: var(--panel-2); border: 1px solid var(--border); }
.wl-seg-btn { display: inline-flex; align-items: center; gap: 7px; padding: 8px 16px; border: 0; border-radius: 9px; background: transparent; color: var(--muted); font: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer; }
.wl-seg-btn:hover { color: var(--ink); }
.wl-seg-btn.on { background: var(--panel); color: var(--ink); box-shadow: var(--shadow-1); }

/* The brand: the form, and the preview that stays in view beside it. */
.wl-studio { display: grid; grid-template-columns: minmax(0, 1fr) minmax(320px, 400px); gap: 22px; align-items: start; }
.wl-form { min-width: 0; display: grid; gap: 16px; }
.wl-aside { position: sticky; top: 12px; min-width: 0; }
@container wl (max-width: 900px) {
  .wl-studio { grid-template-columns: minmax(0, 1fr); }
  .wl-aside { position: static; order: -1; }
}
.wl-sec { padding: 0; overflow: hidden; }
.wl-sec + .wl-sec { margin-top: 0; }
.wl-sec-head { display: flex; gap: 12px; align-items: flex-start; padding: 18px 20px 0; }
.wl-sec-ic { flex: none; display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--accent-soft); color: var(--accent-ink); }
.wl-sec-words { min-width: 0; }
.wl-sec-title { margin: 0; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--ink); }
.wl-sec-sub { margin: 3px 0 0; font-size: 13px; color: var(--muted); line-height: 1.45; }
.wl-sec-body { padding: 16px 20px 20px; display: grid; gap: 14px; min-width: 0; }
.wl-grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px 18px; align-items: start; }
.wl-view .wl-field { display: grid; gap: 6px; margin: 0; min-width: 0; align-content: start; }
.wl-view .wl-label { font-size: 13px; font-weight: 600; color: var(--ink); }
.wl-view .wl-hint { margin: 0; font-size: 12.5px; }
.wl-view .wl-input { width: 100%; max-width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--field); color: var(--text); transition: border-color .15s, box-shadow .15s; }
.wl-view .wl-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-halo); }
.wl-view .wl-input.bad { border-color: var(--danger); }

/* Ready-made looks. */
.wl-looks { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
@container wl (max-width: 1100px) { .wl-looks { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.wl-look { display: grid; gap: 8px; padding: 8px; border: 1.5px solid var(--border); border-radius: 12px; background: var(--panel); cursor: pointer; text-align: left; font: inherit; transition: border-color .15s, transform .15s, box-shadow .15s; }
.wl-look:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.wl-look.on { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-halo); }
.wl-look-swatch { position: relative; display: flex; align-items: flex-end; height: 62px; padding: 8px 10px; border-radius: 8px; border: 1px solid rgba(0, 0, 0, .06); }
.wl-look-aa { font-size: 24px; font-weight: 700; line-height: 1; }
.wl-look-dot { position: absolute; right: 10px; top: 10px; width: 16px; height: 16px; border-radius: 50%; box-shadow: 0 0 0 2px rgba(255, 255, 255, .7); }
.wl-look-name { font-size: 12.5px; font-weight: 600; color: var(--ink); padding: 0 2px; }

/* Logos. */
.wl-logos { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; }
.wl-logo { display: grid; gap: 8px; min-width: 0; align-content: start; }
.wl-logo-top { display: grid; gap: 1px; }
.wl-logo-hint { font-size: 12px; color: var(--muted); }
.wl-logo-frame { position: relative; display: grid; place-items: center; height: 118px; border: 1.5px dashed var(--border); border-radius: 12px; cursor: pointer; overflow: hidden; transition: border-color .15s, background .15s;
  background-color: #fff; background-image: linear-gradient(45deg, #f1f2f6 25%, transparent 25%), linear-gradient(-45deg, #f1f2f6 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #f1f2f6 75%), linear-gradient(-45deg, transparent 75%, #f1f2f6 75%); background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0; }
.wl-logo-frame.dark { background-color: #12131f; background-image: linear-gradient(45deg, #1b1c2b 25%, transparent 25%), linear-gradient(-45deg, #1b1c2b 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #1b1c2b 75%), linear-gradient(-45deg, transparent 75%, #1b1c2b 75%); }
.wl-logo-frame:hover, .wl-logo-frame.over { border-color: var(--accent); }
.wl-logo-frame.over { box-shadow: inset 0 0 0 3px var(--accent-halo); }
.wl-logo-img { max-width: 82%; max-height: 74px; object-fit: contain; }
.wl-logo-empty { display: grid; justify-items: center; gap: 6px; padding: 0 14px; text-align: center; font-size: 12px; color: #6a6f86; }
.wl-logo-frame.dark .wl-logo-empty { color: #a9aecb; }
.wl-logo-file { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.wl-logo-row { display: flex; gap: 6px; align-items: center; }
.wl-logo-row .wl-input { flex: 1; min-width: 0; font-size: 12.5px; padding: 7px 10px; }
.wl-logo-clear { flex: none; display: grid; place-items: center; width: 32px; height: 32px; border: 1px solid var(--border); border-radius: 9px; background: var(--panel); color: var(--danger); cursor: pointer; }
.wl-logo-clear:hover { border-color: var(--danger); }
.wl-logo-note { margin: 0; min-height: 0; font-size: 12px; color: var(--muted); }
.wl-logo-note:empty { display: none; }

/* Colours. */
.wl-colour { display: grid; gap: 10px; min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel-2); }
.wl-colour-top { display: flex; align-items: center; gap: 12px; min-width: 0; }
.wl-colour-well { position: relative; flex: none; width: 52px; height: 52px; border-radius: 14px; overflow: hidden; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .1), var(--shadow-1); }
.wl-colour-well.empty { background: repeating-linear-gradient(45deg, var(--panel) 0 6px, var(--border) 6px 8px); }
.wl-colour-well.empty .wl-colour-input { opacity: 0; }
.wl-colour-input { position: absolute; inset: -10px; width: calc(100% + 20px); height: calc(100% + 20px); border: 0; padding: 0; cursor: pointer; background: none; }
.wl-colour-words { flex: 1; min-width: 0; display: grid; gap: 5px; }
.wl-colour-code { font-family: var(--mono) !important; text-transform: uppercase; max-width: 140px; padding: 6px 10px !important; }
.wl-contrast { flex: none; align-self: flex-start; padding: 3px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.wl-contrast:empty { display: none; }
.wl-contrast.aa { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.wl-contrast.large { color: var(--warn); background: var(--warn-soft); }
.wl-contrast.low { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }
.wl-swatches { display: flex; flex-wrap: wrap; gap: 7px; }
.wl-swatch { width: 24px; height: 24px; padding: 0; border-radius: 50%; border: 0; cursor: pointer; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .14); transition: transform .12s; }
.wl-swatch:hover { transform: scale(1.12); }
.wl-swatch.on { box-shadow: 0 0 0 2px var(--panel-2), 0 0 0 4px var(--ink); }
.wl-swatch-auto { width: auto; padding: 0 10px; border-radius: 999px; background: var(--panel); font: inherit; font-size: 11.5px; font-weight: 600; color: var(--ink); }
@container wl (max-width: 560px) { .wl-contrast { display: none; } }

/* Type. */
.wl-fonts-block { display: grid; gap: 8px; }
.wl-fonts { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
.wl-font { display: grid; gap: 4px; justify-items: start; padding: 12px 12px 10px; border: 1.5px solid var(--border); border-radius: 12px; background: var(--panel); color: var(--ink); cursor: pointer; font: inherit; text-align: left; transition: border-color .15s, background .15s; }
.wl-font:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.wl-font.on { border-color: var(--accent); background: var(--accent-soft); }
.wl-font-aa { font-size: 28px; line-height: 1.05; font-weight: 700; }
.wl-font-name { font-size: 12px; font-weight: 600; color: var(--muted); }
.wl-font.on .wl-font-name { color: var(--accent-ink); }

/* The save bar: it sticks to the bottom of the view while there is something to save. */
.wl-savebar { position: relative; bottom: 10px; z-index: 3; display: flex; align-items: center; gap: 10px; padding: 12px 14px 12px 18px; border-radius: 14px; border: 1px solid var(--border); background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(10px); box-shadow: var(--shadow-1); }
.wl-savebar.dirty { position: sticky; box-shadow: var(--shadow-2); border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.wl-dirty { flex: 1; font-size: 13px; font-weight: 600; color: var(--muted); }
.wl-savebar.dirty .wl-dirty { color: var(--accent-ink); }
.wl-savebar.dirty .wl-dirty::before { content: ""; display: inline-block; width: 8px; height: 8px; margin-right: 8px; border-radius: 50%; background: var(--accent); vertical-align: 1px; }

/* The preview: its own grounds, its own type, and the draft's tokens on its root. */
.wl-pv { --pv-bg: #f6f6fa; --pv-panel: #ffffff; --pv-line: #e6e7ef; --pv-text: #14152d; --pv-muted: #676c86;
  border: 1px solid var(--border); border-radius: 16px; background: var(--panel); padding: 12px; box-shadow: var(--shadow-2); display: grid; gap: 10px; }
.wl-pv[data-theme="dark"] { --pv-bg: #0f1020; --pv-panel: #17182c; --pv-line: #2a2c48; --pv-text: #ecedf7; --pv-muted: #9ea3c2; }
.wl-pv-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.wl-pv-label { display: inline-flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 700; color: var(--ink); }
.wl-pv-theme { display: inline-flex; gap: 2px; padding: 3px; border-radius: 9px; background: var(--panel-2); }
.wl-pv-tbtn { display: grid; place-items: center; width: 28px; height: 24px; border: 0; border-radius: 7px; background: transparent; color: var(--muted); cursor: pointer; }
.wl-pv-tbtn.on { background: var(--panel); color: var(--ink); box-shadow: var(--shadow-1); }
.wl-pv-tab { display: flex; align-items: center; gap: 8px; width: max-content; max-width: 100%; padding: 6px 14px 6px 8px; border-radius: 10px 10px 0 0; background: var(--panel-2); font-size: 12px; color: var(--text); margin-bottom: -10px; }
.wl-pv-fav { flex: none; display: grid; place-items: center; width: 16px; height: 16px; border-radius: 4px; background: var(--accent); color: var(--on-accent, #fff); font-size: 10px; font-weight: 700; overflow: hidden; }
.wl-pv-fav img { width: 100%; height: 100%; object-fit: contain; background: #fff; }
.wl-pv-tabname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wl-pv-app { display: grid; grid-template-columns: 112px minmax(0, 1fr); min-height: 230px; border-radius: 12px; overflow: hidden; border: 1px solid var(--pv-line); background: var(--pv-bg); font-family: var(--pv-body); color: var(--pv-text); transition: background .25s; }
.wl-pv-side { position: relative; display: grid; align-content: start; gap: 10px; padding: 12px 9px; background: var(--side-bg, #0a0c14); color: var(--side-text, #b9bfd4); overflow: hidden; }
.wl-pv:not(.own-side) .wl-pv-side { background: radial-gradient(120% 60% at 0% 0%, color-mix(in srgb, var(--accent) 38%, transparent), transparent 60%), radial-gradient(90% 60% at 100% 100%, color-mix(in srgb, var(--accent) 22%, transparent), transparent 60%), #0a0c14; }
.wl-pv.own-side .wl-pv-side { background: radial-gradient(120% 60% at 0% 0%, var(--side-glow-1), var(--side-glow-1-out) 60%), radial-gradient(90% 60% at 100% 100%, var(--side-glow-2), var(--side-glow-2-out) 60%), var(--side-bg); }
.wl-pv-mark { min-height: 22px; display: flex; align-items: center; }
.wl-pv-mark .wl-pv-logo { max-width: 92px; max-height: 24px; object-fit: contain; }
.wl-pv-word { font-family: var(--pv-display); font-size: 13.5px; font-weight: 800; color: var(--side-ink, #fff); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wl-pv-create { display: inline-flex; align-items: center; justify-content: center; gap: 5px; padding: 6px 8px; border-radius: 8px; background: var(--accent); color: var(--on-accent, #fff); font-size: 10.5px; font-weight: 700; box-shadow: 0 4px 12px color-mix(in srgb, var(--accent) 40%, transparent); }
.wl-pv-nav { display: grid; gap: 2px; }
.wl-pv-nav-item { display: flex; align-items: center; gap: 6px; padding: 5px 6px; border-radius: 6px; font-size: 10.5px; }
.wl-pv-nav-item.on { background: var(--side-bg-2, rgba(255, 255, 255, .06)); color: var(--side-ink, #fff); }
.wl-pv-main { display: grid; align-content: start; gap: 8px; padding: 16px 14px; min-width: 0; }
.wl-pv-h { font-family: var(--pv-display); font-size: 17px; font-weight: 800; letter-spacing: -.01em; line-height: 1.15; }
.wl-pv-p { margin: 0; font-size: 11.5px; line-height: 1.45; color: var(--pv-muted); }
.wl-pv-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.wl-pv-card { display: grid; gap: 5px; padding: 5px; border-radius: 8px; background: var(--pv-panel); border: 1px solid var(--pv-line); }
.wl-pv-thumb { height: 30px; border-radius: 5px; background: linear-gradient(135deg, var(--accent-soft), color-mix(in srgb, var(--accent) 30%, transparent)); }
.wl-pv-line { height: 5px; width: 70%; border-radius: 3px; background: var(--pv-line); }
.wl-pv-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 2px; }
.wl-pv-btn { display: inline-flex; padding: 6px 11px; border-radius: 8px; background: var(--accent); color: var(--on-accent, #fff); font-size: 11px; font-weight: 700; }
.wl-pv-chip { display: inline-flex; padding: 4px 9px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); font-size: 10.5px; font-weight: 600; }
.wl-pv-link { font-size: 11px; color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.wl-pv-cap { margin: 4px 2px -2px; font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.wl-pv-door { display: grid; gap: 8px; justify-items: start; padding: 18px; border-radius: 12px; border: 1px solid var(--pv-line); background: var(--pv-panel); color: var(--pv-text); font-family: var(--pv-body); }
.wl-pv-door-mark { min-height: 24px; display: flex; align-items: center; }
.wl-pv-door-mark .wl-pv-logo { max-width: 120px; max-height: 28px; object-fit: contain; }
.wl-pv-door-mark .wl-pv-word { color: var(--pv-text); font-size: 15px; }
.wl-pv-door-h { font-family: var(--pv-display); font-size: 18px; font-weight: 800; letter-spacing: -.01em; }
.wl-pv-door-sub { margin: -4px 0 2px; font-size: 11.5px; color: var(--pv-muted); }
.wl-pv-door-field { width: 100%; box-sizing: border-box; padding: 7px 10px; border-radius: 8px; border: 1px solid var(--pv-line); background: var(--pv-bg); font-size: 11px; color: var(--pv-muted); }
.wl-pv-door-btn { width: 100%; justify-content: center; box-sizing: border-box; }
.wl-pv-note { margin: 10px 4px 0; font-size: 12px; }

/* Domain and mail. */
.wl-domain-pane { display: grid; gap: 16px; max-width: 900px; }
.wl-steps { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.wl-step { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px 6px 6px; border-radius: 999px; border: 1px solid var(--border); background: var(--panel-2); font-size: 12.5px; font-weight: 600; color: var(--muted); }
.wl-step-n { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--panel); border: 1px solid var(--border); font-size: 11.5px; color: var(--ink); }
.wl-step.done { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 30%, var(--border)); background: color-mix(in srgb, var(--ok) 7%, var(--panel)); }
.wl-step.done .wl-step-n { background: var(--ok); border-color: var(--ok); color: #fff; }
.wl-view .wl-domain-add { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }
.wl-view .wl-domain-add .wl-field { flex: 1 1 240px; }
.wl-domain-line { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 14px; border-radius: 12px; background: var(--panel-2); border: 1px solid var(--border); }
.wl-domain-ic { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 10px; background: var(--panel); color: var(--ink); }
.wl-view .wl-domain-name { flex: 1; margin: 0; font-weight: 700; font-size: 15px; color: var(--ink); overflow-wrap: anywhere; }
.wl-domain-acts { display: flex; flex-wrap: wrap; gap: 8px; }
.wl-domain-have { display: grid; gap: 12px; }
.wl-pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; background: var(--panel); border: 1px solid var(--border); color: var(--muted); }
.wl-pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.wl-pill.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, var(--border)); }
.wl-pill.wait { color: var(--warn); border-color: var(--warn-line); }
.wl-dns { min-width: 0; overflow-x: auto; }
.wl-view .wl-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.wl-view .wl-table th { padding: 8px 10px; font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); text-align: left; border-bottom: 1px solid var(--border); background: var(--panel-2); }
.wl-view .wl-table td { padding: 10px; border-bottom: 1px solid var(--border); vertical-align: top; text-align: left; min-width: 0; }
.wl-view .wl-table tr:last-child td { border-bottom: 0; }
.wl-tag { display: inline-flex; padding: 2px 8px; border-radius: 6px; font-family: var(--mono); font-size: 11.5px; font-weight: 700; background: var(--accent-soft); color: var(--accent-ink); }
.wl-dns-code { display: inline; font-size: 12px; word-break: break-all; }
.wl-copy { display: inline-grid; place-items: center; width: 24px; height: 24px; margin-left: 6px; vertical-align: middle; border: 1px solid var(--border); border-radius: 7px; background: var(--panel); color: var(--muted); cursor: pointer; }
.wl-copy:hover { color: var(--ink); border-color: var(--ink); }
.wl-copy.done { color: var(--ok); border-color: var(--ok); }
.wl-sender-state { margin: 0; padding: 12px 14px; border-radius: 10px; background: var(--panel-2); font-size: 13.5px; color: var(--text); }
.wl-sender-state.ok { background: color-mix(in srgb, var(--ok) 8%, var(--panel)); color: var(--ok); font-weight: 600; }

/* ===================== Team (2026-10-26) =====================
   A strip of figures under the head, then two columns: the people, and what is done to the team. */
.team-view { container: team / inline-size; padding: 10px 8px 48px; }
.team-view > * { max-width: 1220px; }
.team-view .team-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 20px; margin: 0 0 18px; }
.team-view .team-head-text { min-width: 0; flex: 1 1 280px; }
.team-view .team-name-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.team-view .team-name { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.team-view .team-pencil { flex: none; display: inline-grid; place-items: center; width: 32px; height: 32px; padding: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--ink); cursor: pointer; }
.team-view .team-pencil:hover { background: var(--panel-2); }
.team-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; margin: 0 0 18px; }
@container team (max-width: 720px) { .team-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.team-stat { position: relative; display: grid; gap: 4px; padding: 16px 18px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel); overflow: hidden; }
.team-stat::after { content: ""; position: absolute; right: -24px; top: -24px; width: 80px; height: 80px; border-radius: 50%; background: var(--accent-soft); }
.team-stat-n { position: relative; z-index: 1; font-family: var(--font-display); font-size: 28px; font-weight: 800; line-height: 1.05; color: var(--ink); font-variant-numeric: tabular-nums; }
.team-stat-w { position: relative; z-index: 1; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.team-meter { height: 6px; margin-top: 6px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.team-meter-fill { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--accent-hi)); transition: width .6s cubic-bezier(.2, .8, .2, 1); }
.team-stat.full .team-meter-fill { background: var(--danger); }

.team-grid { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(300px, 1fr); gap: 16px; align-items: start; }
@container team (max-width: 860px) { .team-grid { grid-template-columns: minmax(0, 1fr); } }
.team-main, .team-side { display: grid; gap: 16px; min-width: 0; }
.team-view .team-card { min-width: 0; margin: 0; padding: 20px; }
.team-view .team-card + .team-card { margin-top: 0; }
.team-card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 0 0 6px; }
.team-view .team-h { margin: 0 0 10px; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--ink); }
.team-card-head .team-h { margin: 0; }
.team-view .team-seats { margin: 0; font-size: 12.5px; }
.team-view .team-lead { margin: -4px 0 12px; font-size: 12.5px; }
.team-view .team-link { display: grid; gap: 8px; margin-top: 12px; }
.team-view .team-link-url { width: 100%; max-width: 100%; box-sizing: border-box; font-family: var(--mono); font-size: 13px; }

.team-view .members-list, .team-view .members-pending { min-width: 0; }
.team-view .members-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; padding: 14px 4px; border-bottom: 1px solid var(--border); }
.team-view .members-row:last-child { border-bottom: 0; padding-bottom: 2px; }
.team-view .members-who { display: grid; flex: 1 1 200px; min-width: 0; gap: 2px; }
.team-view .members-who strong, .team-view .members-who span { overflow-wrap: anywhere; }
.team-view .members-who strong { font-weight: 600; color: var(--ink); }
.team-view .members-who .hint { font-size: 12.5px; }
.members-flag { justify-self: start; margin-top: 2px; padding: 1px 8px; border-radius: 999px; font-size: 11px; font-weight: 600; color: var(--warn); background: var(--warn-soft); }
.team-view .members-avatar { --hue: 260; flex: none; display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; font-weight: 700; font-size: 15px;
  color: hsl(var(--hue) 55% 32%); background: linear-gradient(135deg, hsl(var(--hue) 80% 90%), hsl(calc(var(--hue) + 40) 80% 84%)); }
:root[data-theme="dark"] .team-view .members-avatar { color: hsl(var(--hue) 80% 86%); background: linear-gradient(135deg, hsl(var(--hue) 40% 26%), hsl(calc(var(--hue) + 40) 40% 32%)); }
.team-view .members-avatar.pending { color: var(--muted); background: var(--panel-2); border: 1px dashed var(--border); }
.members-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-left: auto; }
.members-acts .btn { padding: 6px 12px; font-size: 12.5px; white-space: nowrap; }
.btn.danger-ghost:hover { color: var(--danger); border-color: var(--danger); }
.team-view .members-email, .team-view .members-role { box-sizing: border-box; font: inherit; font-size: 13.5px; padding: 8px 11px; border: 1px solid var(--border); border-radius: 10px; background: var(--field); color: var(--text); }
.members-acts .members-role { padding: 6px 30px 6px 11px; font-weight: 600; }
.team-view .members-email { flex: 1 1 220px; min-width: 0; max-width: 100%; }
.team-view .members-invite { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0; }
.team-invite .members-invite .members-email { flex: 1 1 100%; }
.team-invite .members-invite .members-role { flex: 1 1 120px; }
.team-view .members-reserve { flex: 1 1 100%; display: grid; gap: 6px; padding: 12px 14px; margin-left: 54px; border-radius: 10px; background: var(--panel-2); }
.team-view .members-reserve .members-invite { justify-content: flex-start; }
.team-view .members-reserve-amount { width: 9em; flex: 0 0 auto; }
.team-view .members-correct { flex: 1 1 100%; display: flex; gap: 8px; margin-left: 54px; }

.team-role-pill { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; white-space: nowrap; border: 1px solid transparent; }
.team-role-pill.role-owner { color: var(--accent-ink); background: var(--accent-soft); border-color: var(--accent-line); }
.team-role-pill.role-admin { color: #3b5bdb; background: rgba(59, 91, 219, .1); }
.team-role-pill.role-creator { color: var(--ok); background: color-mix(in srgb, var(--ok) 11%, transparent); }
.team-role-pill.role-viewer { color: var(--muted); background: var(--panel-2); }
:root[data-theme="dark"] .team-role-pill.role-admin { color: #9fb4ff; background: rgba(120, 150, 255, .14); }
.team-view .team-roles { display: grid; gap: 12px; }
.team-role { display: grid; gap: 6px; justify-items: start; }
.team-role .hint { margin: 0; font-size: 12.5px; line-height: 1.45; }
.team-view .team-exit { display: grid; gap: 10px; justify-items: start; }
@container team (max-width: 560px) {
  .team-view .team-card { padding: 16px; }
  .members-acts { margin-left: 54px; }
  .team-view .members-reserve, .team-view .members-correct { margin-left: 0; }
}
.members-acts .members-role { width: auto; max-width: 180px; flex: 0 0 auto; }
.members-acts > .hint { flex: 1 1 100%; margin: 0; font-size: 12px; text-align: right; }

/* ===================== Sub-companies (2026-10-26) ===================== */
.chl-view { padding: 10px 8px 48px; }
.chl-stats { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; margin: 0 0 18px; }
@container chl (max-width: 980px) { .chl-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@container chl (max-width: 560px) { .chl-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.chl-stats:empty { display: none; }
.chl-stat { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 16px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel); }
.chl-stat-ic { flex: none; display: grid; place-items: center; width: 38px; height: 38px; border-radius: 11px; background: var(--panel-2); color: var(--ink); }
.chl-stat.ok .chl-stat-ic { background: color-mix(in srgb, var(--ok) 12%, transparent); color: var(--ok); }
.chl-stat.accent .chl-stat-ic { background: var(--accent-soft); color: var(--accent-ink); }
.chl-stat-words { display: grid; gap: 2px; min-width: 0; }
.chl-stat-n { font-family: var(--font-display); font-size: 22px; font-weight: 800; line-height: 1.1; color: var(--ink); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chl-stat-w { font-size: 12px; font-weight: 600; color: var(--muted); }
.chl-view .chl-pane { padding: 20px; }
.chl-pane-top { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 20px; margin: 0 0 12px; }
.chl-pane-words { min-width: 0; }
.chl-pane-words .hint { margin: 0; }
.chl-view .chl-pane-title { font-family: var(--font-display); font-weight: 700; color: var(--ink); }
.chl-search { display: flex; align-items: center; gap: 8px; min-width: 220px; padding: 0 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--field); color: var(--muted); }
.chl-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-halo); }
.chl-search-input { flex: 1; min-width: 0; padding: 9px 0; border: 0; outline: none; background: transparent; font: inherit; font-size: 13.5px; color: var(--text); }
.chl-table-wrap { min-width: 0; overflow-x: auto; }
.chl-view .chl-table th { padding: 10px; font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); background: var(--panel-2); }
.chl-view .chl-table th:first-child { border-radius: 10px 0 0 10px; }
.chl-view .chl-table th:last-child { border-radius: 0 10px 10px 0; }
.chl-view .chl-table td { padding: 14px 10px; }
.chl-view .chl-table tbody tr { transition: background .15s; }
.chl-view .chl-table tbody tr:hover { background: color-mix(in srgb, var(--panel-2) 60%, transparent); }
.chl-view .chl-table tr:last-child td { border-bottom: 0; }
td.chl-name { min-width: 180px; }
.chl-name-in { display: flex; align-items: center; gap: 10px; }
.chl-avatar { --hue: 260; flex: none; display: inline-grid; place-items: center; width: 34px; height: 34px; border-radius: 10px; font-weight: 700; font-size: 14px; color: hsl(var(--hue) 55% 32%); background: linear-gradient(135deg, hsl(var(--hue) 80% 90%), hsl(calc(var(--hue) + 40) 80% 84%)); }
:root[data-theme="dark"] .chl-avatar { color: hsl(var(--hue) 80% 86%); background: linear-gradient(135deg, hsl(var(--hue) 40% 26%), hsl(calc(var(--hue) + 40) 40% 32%)); }
.chl-name-word { min-width: 0; overflow-wrap: anywhere; }
.chl-table tr.chl-off .chl-avatar { filter: grayscale(1); opacity: .6; }
.chl-balance { min-width: 110px; }
.chl-balance > span:first-child { display: block; font-weight: 600; color: var(--ink); }
.chl-bar { display: block; height: 5px; margin-top: 6px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.chl-bar-fill { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--accent), var(--accent-hi)); }
.chl-pill { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; margin: 2px 6px 2px 0; border-radius: 999px; font-size: 12px; font-weight: 600; white-space: nowrap; }
.chl-pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.chl-pill.ok { color: var(--ok); background: color-mix(in srgb, var(--ok) 11%, transparent); }
.chl-pill.off { color: var(--muted); background: var(--panel-2); }
.chl-pill.warn { color: var(--warn); background: var(--warn-soft); }
.chl-view .chl-actions { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }
.chl-view .chl-actions .btn { margin: 0; padding: 6px 11px; font-size: 12.5px; }
.chl-empty { display: grid; justify-items: center; gap: 8px; padding: 34px 16px; text-align: center; border: 1.5px dashed var(--border); border-radius: 14px; }
.chl-empty-ic { display: grid; place-items: center; width: 56px; height: 56px; border-radius: 50%; background: var(--accent-soft); color: var(--accent-ink); }
.chl-empty .chl-empty-cta { margin-top: 4px; }
.chl-none { padding: 18px 4px; }
.chl-view > .bk-card + .bk-card, .chl-view > .bk-card { margin-top: 16px; }
.chl-view > .chl-pane:first-of-type { margin-top: 0; }

/* ===================== Insights (2026-10-26) =====================
   Figures, a stacked trend that rises into place, two breakdowns and a table. Every colour of a series is
   the accent first, so the largest series wears the studio's (or the white label's) own colour. */
.settings-view > .set-panel.ins-view { padding: 0; }
.ins-view { container: ins / inline-size; padding: 10px 8px 48px; display: grid; gap: 16px; }
.ins-view > * { max-width: 1220px; min-width: 0; }
.ins-view .ins-head { margin: 0; }
.ins-view.loading .ins-kpis, .ins-view.loading .ins-chart-card, .ins-view.loading .ins-splits, .ins-view.loading .ins-table-card { opacity: .55; transition: opacity .2s; }
.ins-status:empty { display: none; }
.ins-status { margin: 0; padding: 10px 14px; border-radius: 10px; background: var(--warn-soft); border: 1px solid var(--warn-line); color: var(--text); }

.ins-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.ins-seg { display: inline-flex; gap: 3px; padding: 4px; border-radius: 12px; background: var(--panel-2); border: 1px solid var(--border); }
.ins-seg-btn { padding: 7px 13px; border: 0; border-radius: 9px; background: transparent; color: var(--muted); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; transition: color .15s, background .15s; }
.ins-seg-btn:hover { color: var(--ink); }
.ins-seg-btn.on { background: var(--panel); color: var(--ink); box-shadow: var(--shadow-1); }
.ins-seg.small { padding: 3px; border-radius: 10px; }
.ins-seg.small .ins-seg-btn { padding: 5px 10px; font-size: 12px; border-radius: 7px; }
.ins-custom { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.ins-arrow { color: var(--muted); }
.ins-date, .ins-select { font: inherit; font-size: 13px; padding: 8px 11px; border: 1px solid var(--border); border-radius: 10px; background: var(--field); color: var(--text); }
.ins-select { padding-right: 30px; font-weight: 600; max-width: 240px; }
.ins-filters { display: inline-flex; flex-wrap: wrap; gap: 8px; margin-left: auto; }
.ins-icon-btn { display: inline-grid; place-items: center; width: 36px; height: 36px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--ink); cursor: pointer; }
.ins-icon-btn:hover:not(:disabled) { border-color: var(--ink); }
.ins-icon-btn:disabled { opacity: .4; cursor: default; }

.ins-kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 12px; }
@container ins (max-width: 1000px) { .ins-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@container ins (max-width: 600px) { .ins-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.ins-kpi { --tone: var(--accent); position: relative; display: grid; gap: 6px; align-content: start; min-height: 116px; padding: 16px 16px 14px; border: 1px solid var(--border); border-radius: 16px; background: var(--panel); overflow: hidden; animation: ins-up .5s cubic-bezier(.2, .8, .2, 1) both; }
.ins-kpi:nth-child(2) { animation-delay: 60ms; } .ins-kpi:nth-child(3) { animation-delay: 120ms; } .ins-kpi:nth-child(4) { animation-delay: 180ms; } .ins-kpi:nth-child(5) { animation-delay: 240ms; }
.ins-kpi.blue { --tone: #4f7cff; } .ins-kpi.green { --tone: #10b981; } .ins-kpi.amber { --tone: #f59e0b; } .ins-kpi.violet { --tone: #8b5cf6; }
.ins-kpi::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: linear-gradient(90deg, var(--tone), color-mix(in srgb, var(--tone) 20%, transparent)); }
.ins-kpi-top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.ins-kpi-ic { flex: none; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; color: var(--tone); background: color-mix(in srgb, var(--tone) 13%, transparent); }
.ins-kpi-label { font-size: 12.5px; font-weight: 600; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ins-kpi-n { position: relative; z-index: 1; font-family: var(--font-display); font-size: 28px; font-weight: 800; letter-spacing: -.02em; line-height: 1.05; color: var(--ink); font-variant-numeric: tabular-nums; }
.ins-kpi-low { position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 12px; }
.ins-kpi-foot { color: var(--muted); }
.ins-delta { padding: 1px 7px; border-radius: 999px; font-weight: 700; font-size: 11.5px; }
.ins-delta.up { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
.ins-delta.down { color: var(--danger); background: color-mix(in srgb, var(--danger) 10%, transparent); }
.ins-spark { position: absolute; right: 0; bottom: 0; width: 58%; height: 46px; opacity: .9; pointer-events: none; }
.ins-spark-line { fill: none; stroke: var(--tone); stroke-width: 1.8; vector-effect: non-scaling-stroke; }
.ins-spark-area { fill: color-mix(in srgb, var(--tone) 14%, transparent); }

.ins-card { min-width: 0; padding: 20px; margin: 0; }
.ins-view > .bk-card + .bk-card { margin-top: 0; }
.ins-card-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px 18px; margin: 0 0 14px; }
.ins-card-words { min-width: 0; }
.ins-card-title { margin: 0 0 4px; font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--ink); }
.ins-card-sub { margin: 0; font-size: 12.5px; color: var(--muted); }
.ins-card-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

.ins-chart { position: relative; min-width: 0; }
.ins-svg { display: block; width: 100%; height: auto; overflow: visible; }
.ins-grid line { stroke: var(--border); stroke-dasharray: 3 4; }
.ins-grid text { fill: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.ins-line { fill: none; stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .12)); }
.ins-plot.rise { transform-box: fill-box; transform-origin: 50% 100%; animation: ins-rise 1.1s cubic-bezier(.2, .8, .2, 1) both; }
.ins-cross line { stroke: var(--ink); stroke-opacity: .35; stroke-dasharray: 4 4; }
.ins-hit { cursor: crosshair; }
.ins-empty { fill: var(--muted); font-size: 14px; }
.ins-tip { position: absolute; z-index: 4; min-width: 170px; max-width: 260px; padding: 10px 12px; border-radius: 12px; background: color-mix(in srgb, var(--panel) 94%, transparent); backdrop-filter: blur(8px); border: 1px solid var(--border); box-shadow: var(--shadow-2); pointer-events: none; font-size: 12.5px; transition: left .08s linear; }
.ins-tip-date { margin: 0 0 6px; font-weight: 700; color: var(--ink); }
.ins-tip-row { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
.ins-tip-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.ins-tip-row strong { font-variant-numeric: tabular-nums; color: var(--ink); }
.ins-tip-total { margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--border); }
.ins-tip-dot, .ins-legend-dot { flex: none; display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 2px; }
.ins-legend { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.ins-legend-item { display: inline-flex; align-items: center; gap: 7px; padding: 5px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel); font: inherit; font-size: 12.5px; color: var(--text); cursor: pointer; transition: opacity .15s, border-color .15s; }
.ins-legend-item:hover { border-color: var(--ink); }
.ins-legend-item.off { opacity: .45; }
.ins-legend-item.off .ins-legend-name { text-decoration: line-through; }
.ins-legend-n { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }

.ins-splits { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 16px; }
@container ins (max-width: 820px) { .ins-splits { grid-template-columns: minmax(0, 1fr); } }
.ins-bars { display: grid; gap: 6px; margin-top: 10px; }
.ins-bar-row { display: grid; gap: 6px; padding: 8px 10px; border: 1px solid transparent; border-radius: 10px; background: transparent; font: inherit; text-align: left; cursor: pointer; color: var(--text); }
.ins-bar-row:hover { background: var(--panel-2); }
.ins-bar-row.on { border-color: var(--accent-line); background: var(--accent-soft); }
.ins-bar-label { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; }
.ins-bar-name { font-weight: 600; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ins-bar-n { flex: none; color: var(--muted); font-variant-numeric: tabular-nums; }
.ins-bar-track { height: 8px; border-radius: 999px; background: var(--panel-2); overflow: hidden; }
.ins-bar-fill { display: block; height: 100%; width: var(--w); border-radius: inherit; background: linear-gradient(90deg, var(--c), color-mix(in srgb, var(--c) 55%, white)); animation: ins-grow .9s cubic-bezier(.2, .8, .2, 1) both; }
.ins-donut-wrap { display: flex; flex-wrap: wrap; align-items: center; gap: 18px; margin-top: 10px; }
.ins-donut { flex: none; width: 168px; height: 168px; }
.ins-donut-track { fill: none; stroke: var(--panel-2); stroke-width: 18; }
.ins-donut-seg { fill: none; stroke-width: 18; stroke-linecap: butt; animation: ins-ring 1s cubic-bezier(.2, .8, .2, 1) both; }
.ins-donut-n { font-family: var(--font-display); font-size: 24px; font-weight: 800; fill: var(--ink); }
.ins-donut-w { font-size: 11px; fill: var(--muted); }
.ins-donut-keys { flex: 1; min-width: 140px; display: grid; gap: 8px; }
.ins-donut-key { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.ins-donut-key .ins-legend-name { flex: 1; }

.ins-search { display: flex; align-items: center; gap: 8px; min-width: 240px; padding: 0 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--field); color: var(--muted); }
.ins-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-halo); }
.ins-search-input { flex: 1; min-width: 0; padding: 8px 0; border: 0; outline: none; background: transparent; font: inherit; font-size: 13px; color: var(--text); }
.ins-export { display: inline-flex; align-items: center; gap: 6px; }
.ins-table-wrap { min-width: 0; overflow-x: auto; }
.ins-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.ins-table th { padding: 0; background: var(--panel-2); text-align: left; }
.ins-table th:first-child { border-radius: 10px 0 0 10px; } .ins-table th:last-child { border-radius: 0 10px 10px 0; }
.ins-table th.num, .ins-table td.num { text-align: right; }
.ins-sort { display: inline-flex; align-items: center; gap: 6px; width: 100%; padding: 10px; border: 0; background: transparent; font: inherit; font-size: 11.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); cursor: pointer; white-space: nowrap; }
.ins-table th.num .ins-sort { justify-content: flex-end; }
.ins-sort.on { color: var(--ink); }
.ins-sort-arrow { opacity: .55; font-size: 12px; }
.ins-table td { padding: 11px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; white-space: nowrap; }
.ins-table td.num { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }
.ins-table tbody tr { transition: background .12s; }
.ins-table tbody tr:hover { background: color-mix(in srgb, var(--panel-2) 60%, transparent); }
.ins-table tbody tr:last-child td { border-bottom: 0; }
.ins-when { color: var(--muted); font-variant-numeric: tabular-nums; }
.ins-kind { display: inline-flex; padding: 2px 9px; border-radius: 6px; font-size: 12px; font-weight: 600; background: var(--panel-2); color: var(--ink); }
.ins-kind.k-image { color: #4f7cff; background: rgba(79, 124, 255, .11); }
.ins-kind.k-video { color: var(--accent-ink); background: var(--accent-soft); }
.ins-kind.k-audio { color: #0d9488; background: rgba(13, 148, 136, .12); }
.ins-status-pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; }
.ins-status-pill::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.ins-status-pill.s-ok { color: var(--ok); } .ins-status-pill.s-refunded { color: var(--danger); } .ins-status-pill.s-pending { color: var(--warn); }
.ins-ref { font-family: var(--mono); font-size: 11.5px; color: var(--muted); user-select: all; }
.ins-none { padding: 18px 4px; }
.ins-pager { display: flex; align-items: center; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.ins-pager:empty { display: none; }
.ins-page { font-size: 12.5px; color: var(--muted); margin-right: 4px; }

@keyframes ins-up { from { opacity: 0; transform: translateY(10px); } }
@keyframes ins-rise { from { transform: scaleY(0); opacity: 0; } 30% { opacity: 1; } }
@keyframes ins-grow { from { width: 0; } }
@keyframes ins-ring { from { stroke-dasharray: 0 999; } }
@media (prefers-reduced-motion: reduce) {
  .ins-kpi, .ins-plot.rise, .ins-bar-fill, .ins-donut-seg { animation: none; }
}
.ins-filters { flex-wrap: nowrap; }
.ins-filters .ins-select { max-width: 210px; }
.ins-table td .ins-legend-dot { margin-right: 8px; vertical-align: 0; }
.ins-spark { top: 46px; bottom: auto; width: 46%; height: 38px; }
.ins-kpi-low { margin-top: auto; }
.ins-splits > .bk-card, .team-grid .bk-card + .bk-card { margin-top: 0; }
