/* ==========================================================================
   ADIMATE — components, from the new tokens
   Figma 266:1579 (UI - ICO). Values read from the file, not from a screenshot.

   THE ICON BUTTON IS TWO BOXES, and that is the thing worth knowing before
   reading anything below: an OUTER frame that carries the size and a 1px edge,
   and an INNER plate 2px smaller with its own fill and its own edge. The two
   edges are what give the control its depth - one lighter ring around a darker
   well.

   Two of the four sizes break that pattern, and they break it deliberately:
     24px has NO inner plate. The fill and the edge are both on the outer box.
     13px has one, but positioned absolutely at 0,0 rather than centred, and at
     Disabled it is half-transparent instead of a different colour.
   Written out size by size rather than derived from a formula, because the
   design is not a formula - a rule that produced all four from one would be a
   guess dressed as a system.
   ========================================================================== */

/* The shared shape. Everything else is fill and border.
   NO PADDING. Figma's outer box carries 8/4, but a Figma frame lets its child
   overflow while a flex item gets SQUEEZED: 30px less two borders less 16px of
   padding leaves 12px of content, so the 28px plate was crushed to 12 wide and
   stayed 28 tall - a vertical bar. The plate's size is stated exactly, so the
   padding has nothing left to do. */
.ui-ico {
  display: inline-flex; align-items: center; justify-content: center;
  position: relative; box-sizing: border-box;
  border: 1px solid transparent;
}
/* THE INNER PLATE IS CALLED `.plate`, NOT `.box`.
 *
 * It was `.box`, and the page already uses `.box` for its outermost wrapper -
 * the one carrying `padding-bottom: 200px`. Every inner plate inherited that
 * padding and grew into a 200px column, which is the mess in the screenshot.
 * A component's class names have to be its own; a bare, common word like `box`
 * is certain to collide with the page it is dropped into. */
.ui-ico > .plate {
  display: flex; align-items: center; justify-content: center;
  box-sizing: border-box; border: 1px solid transparent;
  /* NEVER SHRINK. The plate is 2px smaller than the outer box, but the outer
     box has a 1px border on each side - so the space inside it is exactly the
     plate's size with nothing to spare, and flex's default `shrink: 1` takes
     the difference out of the width the moment anything rounds against it.
     Stating the size is not enough; a flex item has to be told to keep it. */
  flex: none;
}
/* The glyph. HOVER KEEPS THE GREY - only Enabled goes blue.
   I had hover turn blue too, on the assumption that hover and enabled share a
   look. The Hover variant's own variables are BX/DISABLED, BX/ENABLED,
   BX/STROKE HOVER and HL/ICON: HL/BLUE is not among them. Hover lights the
   OUTER EDGE and leaves the glyph alone; blue means the control is doing
   something, not that a pointer is over it. */
.ui-ico { color: var(--hl-icon); }
.ui-ico.is-enabled { color: var(--hl-blue); }

/* ---- 30px ---------------------------------------------------------------- */
.ui-ico.s30 { width: 30px; height: 30px; }
.ui-ico.s30 > .plate { width: 28px; height: 28px; }
.ui-ico.s30.is-disabled { border-color: var(--bx-stroke); }
.ui-ico.s30.is-disabled > .plate { background: var(--ui-main); border-color: var(--bx-disabled); }
.ui-ico.s30.is-hover { border-color: var(--bx-stroke-hover); }
.ui-ico.s30.is-hover > .plate { background: var(--bx-disabled); border-color: var(--bx-enabled); }
.ui-ico.s30.is-enabled { border-color: var(--bx-stroke-hover); }
.ui-ico.s30.is-enabled > .plate { background: var(--bx-enabled); border-color: var(--bx-enabled); }

 /* ---- 24px: it DOES have an inner plate now ---------------------------- 
    Earlier the file had none and the fill sat on the outer box; it has a 22px
    plate with a --bx/enabled edge and NO fill of its own, so the outer box
    shows through it. Re-read rather than assumed - this is exactly the kind of
    change that a formula would have hidden. */
.ui-ico.s24 { width: 24px; height: 24px; }
/* THE PLATE'S EDGE IS PER STATE, not shared.
   It was --bx/enabled for all three, copied off the Enabled variant because
   that is the only one I had fetched. The Disabled variant's own variables are
   BX/DISABLED, UI/MAIN LIGHT, BX/STROKE LIGHT and HL/ICON - BX/ENABLED does not
   appear in it at all, which is why its inner edge read as darker than the
   state warranted. */
.ui-ico.s24 > .plate { width: 22px; height: 22px; }
.ui-ico.s24.is-disabled { background: var(--ui-main-light); border-color: var(--bx-stroke-light); }
.ui-ico.s24.is-disabled > .plate { border-color: var(--bx-disabled); }
.ui-ico.s24.is-hover    { background: var(--bx-disabled);   border-color: var(--bx-stroke-hover); }
.ui-ico.s24.is-hover > .plate    { border-color: var(--bx-enabled); }
.ui-ico.s24.is-enabled  { background: var(--bx-enabled);    border-color: var(--bx-stroke-light); }
.ui-ico.s24.is-enabled > .plate  { border-color: var(--bx-enabled); }

/* 38 px (398:46157 / 398:47621 / 398:47636 / 398:47651)
 *
 * The largest button, and the only one whose inner box FILLS it rather than
 * sitting inside at a fixed size: the plate is flex:1 at full height, so the
 * 36 comes out of the 38 minus the outer edge rather than being stated.
 *
 * LINK is new to this size and to the set. Its outer edge is DASHED and blue -
 * the only dashed edge anywhere in the guide - which is what says "this button
 * is tied to another one" rather than "this button is on". The plate goes dark
 * with it. I would not have guessed the dash from the other states' grammar,
 * which is why it was read rather than inferred. */
.ui-ico.s38 { width: 38px; height: 38px; }
.ui-ico.s38 > .plate { flex: 1 0 0; height: 100%; min-width: 0; width: auto;
                       display: flex; align-items: center; justify-content: center; }

.ui-ico.s38.is-disabled { border-color: var(--bx-stroke); }
.ui-ico.s38.is-disabled > .plate { background: var(--ui-main);
                                   border-color: var(--bx-disabled); }

.ui-ico.s38.is-hover { border-color: var(--bx-stroke-hover); }
.ui-ico.s38.is-hover > .plate { background: var(--bx-disabled);
                                border-color: var(--bx-enabled); }

/* ENABLED: the outer edge and the plate's fill are Adi's, pasted from the
   file. The plate's EDGE is --bx/enabled - the same colour as its fill, so it
   contributes nothing visible, and every other Enabled in the set is built the
   same way. Said here because it is the one value that did not come from the
   paste. */
.ui-ico.s38.is-enabled { border-color: var(--bx-stroke-hover); }
.ui-ico.s38.is-enabled > .plate { background: var(--bx-enabled);
                                  border-color: var(--bx-enabled); }

.ui-ico.s38.is-link { border: 1px dashed var(--hl-blue); }
.ui-ico.s38.is-link > .plate { background: var(--bx-disabled);
                               border-color: var(--bx-enabled); }

/* 28 px (392:69620 / 392:71692 / 392:72466 / 392:72473)
 *
 * The only size that carries a LANGUAGE rather than a glyph - EN, DE, FR, IT -
 * which is why its inner box is a full-width label instead of a 10px plate with
 * an icon dropped on it.
 *
 * It also has a state none of the others do: SELECTED. A 2px --hl/blue edge on
 * the OUTER box, and the inner box one pixel smaller than the rest to make room
 * for it - so the button does not change size when it becomes the active
 * language, which is the whole reason the inner box shrinks rather than the
 * outer growing. */
.ui-ico.s28 { width: 28px; height: 28px; }
.ui-ico.s28 > .plate { width: 26px; height: 26px; flex: none;
                       display: flex; align-items: center; justify-content: center; }
.ui-ico.s28 > .plate > b {
  font: 700 10px/10px "Chakra Petch", "Segoe UI", system-ui, sans-serif;
  color: var(--tm-grey);
  text-align: center; word-break: break-word;
}

.ui-ico.s28.is-disabled { border-color: var(--bx-stroke-light); }
.ui-ico.s28.is-disabled > .plate { background: var(--ui-main); border: 0; }

.ui-ico.s28.is-hover    { border-color: var(--bx-stroke-light); }
.ui-ico.s28.is-hover > .plate { background: var(--ui-main-dark);
                                border-color: var(--bx-disabled); }

.ui-ico.s28.is-enabled  { border-color: var(--bx-stroke-light); }
.ui-ico.s28.is-enabled > .plate { background: var(--bx-disabled);
                                  border-color: var(--bx-enabled); }

/* The outer edge is 2px here, and the inner box 24 rather than 26: two pixels
   of border on each side need two pixels back, or the control grows when it is
   picked. */
.ui-ico.s28.is-selected { border: 2px solid var(--hl-blue); }
.ui-ico.s28.is-selected > .plate { width: 24px; height: 24px;
                                   background: var(--bx-disabled);
                                   border-color: var(--bx-enabled); }

/* 24 px - Timeline (296:7158)
 *
 * The same outer box as Disabled - --ui/main-light with a --bx/stroke-light
 * edge - and an inner plate carrying NOTHING: no fill, no border.
 *
 * That absence is the whole variant. Everywhere else the plate is a second
 * surface with its own edge, and the two rings are what give the control depth.
 * Here the button already sits ON --ui/main-light inside a panel, so a plate in
 * the same colour would add a ring around nothing and a plate in a different
 * one would look like a hole. The glyph is the content; the box is just its
 * hit area.
 *
 * Which is why it earns a variant rather than a tweak: it is the case where the
 * BACKGROUND the control stands on is already the plate. */
.ui-ico.s24.is-timeline { background: var(--ui-main-light);
                          border-color: var(--bx-stroke-light); }
.ui-ico.s24.is-timeline > .plate { background: none; border-color: transparent; }

/* ---- 20px ---------------------------------------------------------------- */
.ui-ico.s20 { width: 20px; height: 20px; }
.ui-ico.s20 > .plate { width: 18px; height: 18px; }
.ui-ico.s20.is-disabled { border-color: var(--bx-stroke); }
.ui-ico.s20.is-disabled > .plate { background: var(--ui-main); border-color: var(--bx-disabled); }
/* "Disabled Light" is the same control on a lighter panel - the only state in
   the set that exists because of what is BEHIND it rather than what it is
   doing. */
.ui-ico.s20.is-disabled-light { border-color: var(--bx-stroke-light); }
.ui-ico.s20.is-disabled-light > .plate { background: var(--ui-main-light); border-color: var(--bx-disabled); }
.ui-ico.s20.is-hover { border-color: var(--bx-stroke-hover); }
.ui-ico.s20.is-hover > .plate { background: var(--bx-disabled); border-color: var(--bx-enabled); }
.ui-ico.s20.is-enabled { border-color: var(--bx-stroke-hover); }
.ui-ico.s20.is-enabled > .plate { background: var(--bx-enabled); border-color: var(--bx-enabled); }

/* ---- 13px: the plate sits at the corner, not centred --------------------- */
.ui-ico.s13 { width: 13px; height: 13px; padding: 0; }
.ui-ico.s13 > .plate { position: absolute; left: 0; top: 0; width: 11px; height: 11px; }
.ui-ico.s13.is-disabled { background: var(--ui-main); border-color: var(--bx-stroke); }
/* Half-transparent rather than a fourth grey: at 11px a colour step would be
   invisible, and fading is the only difference the eye can still read. */
.ui-ico.s13.is-disabled > .plate { background: var(--ui-main); border-color: var(--bx-disabled); opacity: .5; }
.ui-ico.s13.is-hover { border-color: var(--bx-stroke-hover); }
.ui-ico.s13.is-hover > .plate { background: var(--bx-disabled); border-color: var(--bx-enabled); }
/* The only control in the set whose OUTER edge turns blue - 13px has no room
   for the glyph to carry the state on its own. */
.ui-ico.s13.is-enabled { background: var(--ui-main); border-color: var(--hl-blue); }
.ui-ico.s13.is-enabled > .plate { background: var(--bx-enabled); border-color: var(--bx-enabled); }

/* ---- the variant's card, on hover  (286:34409) ---------------------------
   Not a label - a small panel: the variant's name, a rule, then the tokens the
   variant is built from, each with its own swatch.

   That is the useful part. A name tells you which control you are pointing at;
   the list tells you what to change to fix it. It is the same question the
   colours page answers in the other direction.

   BELOW the control, aligned to its LEFT edge, 10px down. Centred above was my
   own choice and wrong: the row reads left to right, so a card that starts
   where the control starts can be read without the eye moving back.

   Built as a real element rather than ::after, because it has structure - a
   pseudo-element can carry one string and nothing else. */
.ui-ico[data-name] { cursor: default; }
.ui-ico .card, .ico-cell .card {
  position: absolute; left: 0; top: calc(100% + 10px);
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  padding: 10px; white-space: nowrap;
  background: var(--bx-disabled);
  /* TWO EDGES: blue outside, --bx/enabled inside. The same grammar as the nav's
     bottom rule - a lit edge naming the thing and a dark one settling it. One
     border cannot do both, so the outer is the element's own and the inner is
     drawn with an inset shadow, which costs no layout and cannot round to a
     different width than the border above it. */
  border: 1px solid var(--hl-blue);
  box-shadow: inset 0 0 0 1px var(--bx-enabled);
  opacity: 0; visibility: hidden; pointer-events: none; z-index: 3;
}
.ui-ico:hover .card, .ico-cell:hover .card { opacity: 1; visibility: visible; }
/* The hovered control lifts, so its card is never covered by a sibling that
   comes later in the row. */
.ui-ico:hover { z-index: 4; }

.ui-ico .card > b, .ico-cell .card > b { font: var(--ui-tab); font-weight: 600; color: var(--tx-light); }
/* The separator is TWO 1px lines, not one 2px line: a light one over a dark
   one, which is the same lifted edge the buttons themselves use. */
.ui-ico .card > hr, .ico-cell .card > hr {
  width: 100%; height: 2px; margin: 0; border: 0; padding: 0;
  background: linear-gradient(var(--bx-stroke-light) 0 1px, var(--bx-disabled) 1px 2px);
}
.ui-ico .card u, .ico-cell .card u { display: flex; align-items: center; gap: 8px; text-decoration: none; }
/* The swatch is the button in miniature - an outer ring and an inner square -
   so a colour is shown in the same shape it is used in. */
.ui-ico .card i, .ico-cell .card i {
  display: block; border: 1px solid var(--bx-stroke-hover); flex: none;
}
.ui-ico .card i > span, .ico-cell .card i > span {
  display: block; width: 12px; height: 12px; border: 1px solid var(--bx-enabled);
}
.ui-ico .card s, .ico-cell .card s { text-decoration: none; font: var(--ui-tab); color: var(--tx-dark); }

/* A stand-in glyph, so the plates can be judged without the icon set: a square
   in the icon's own colour. Replaced by the real glyphs when they land. */
.ui-ico .g { display: block; background: currentColor; }
.ui-ico.s30 .g { width: 10px; height: 10px; }
.ui-ico.s24 .g { width: 10px; height: 10px; }
.ui-ico.s20 .g { width: 10px; height: 10px; }
.ui-ico.s13 .g { position: relative; width: 7px; height: 7px; }

/* ==========================================================================
   OPTION — the field  (Figma 94:4700)

   The most repeated control in the app, and the one carrying the most logic:
   a NAME box on the left that shows either a letter or a 12px icon, a VALUE box
   holding an optional colour chip, the number, its unit, a dropdown arrow and
   an opacity field. Every one of those is optional, which is why one component
   covers the whole Properties panel.

   MEASURED: the Disabled variant, read out of 94:4701 in full.
   INFERRED: where Hover and Enabled put their differences. Their variable sets
   were read (107:1037, 107:1054) so the COLOURS are certain - Hover adds
   BX/STROKE HOVER, Enabled swaps in TX/BLACK, HL/BLUE and HL/BLUE LIGHT and
   drops BX/DISABLED - but which element each lands on is my reading, not the
   file's. Marked at each rule. Worth confirming before this goes near the app.
   ========================================================================== */

/* The frame: --bx/stroke on --bx/stroke, a 1px gap between NAME and VALUE that
   the frame's own colour shows through. That gap is the seam between the two
   halves and is why the frame is filled rather than transparent. */
.opt {
  display: flex; align-items: center; gap: 1px;
  width: 300px; height: 30px; box-sizing: border-box;
  background: var(--bx-stroke); border: 1px solid var(--bx-stroke);
  font: var(--ui-tab);
}

/* ---- NAME: the label, or an icon in its place ---------------------------- */
.opt .name {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  width: 28px; height: 28px; flex: none; box-sizing: border-box;
  padding: 4px 8px;
  background: var(--ui-main); border: 1px solid var(--bx-disabled);
  font: 700 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
  color: var(--tx-standard);
}
/* RESTING NAME (94:4701 / 606:142359, Adi 2026-10-23): a --bx/enabled edge
   with a second 1px --bx/stroke-light ring inside it (LEFT round a 26px NAME),
   on the frame's --ui/main - which is also what the 1px seam to VALUE shows
   now. HOVER, ENABLED and SIMPLE keep their own NAME (below). */
.opt:not(.is-simple) { background: var(--ui-main); }
.opt:not(.is-simple) .name { border-color: var(--bx-enabled);
  box-shadow: inset 0 0 0 1px var(--bx-stroke-light); }
.opt.is-hover .name, .opt.is-enabled .name,
.p-text .opt:not(.is-enabled):hover .name { box-shadow: none; }
/* The icon variant. Same box, 12px glyph instead of the letter - the swap is
   what lets one field serve both "X" and a padlock. */
.opt .name .ico { width: 12px; height: 12px; flex: none; background: var(--hl-arrow); }

/* ---- VALUE: everything else --------------------------------------------- */
.opt .value {
  display: flex; align-items: center; justify-content: space-between;
  flex: 1 0 0; min-width: 0; height: 100%; box-sizing: border-box;
  background: var(--bx-disabled); border: 1px solid var(--bx-enabled);
}
.opt .txt { display: flex; align-items: center; gap: 4px; height: 100%;
            padding: 0 8px; flex: none; }
/* The colour chip is the same two-ring shape as the swatch on the hover card -
   an outer --bx/stroke ring round a 12px square with a --bx/enabled edge. */
.opt .chip { display: flex; align-items: center; padding-right: 4px; flex: none; }
.opt .chip i { display: block; border: 1px solid var(--bx-stroke); }
.opt .chip i > span { display: block; width: 12px; height: 12px;
                      border: 1px solid var(--bx-enabled); background: var(--hl-blue); }
/* The number is 12px Bold and BLUE even in the resting state - "Disabled" here
   names the frame's appearance, not a greyed-out control. */
.opt .num { font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
            color: var(--hl-blue); white-space: nowrap; }
.opt .unit { font: 600 10px/1 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
             color: var(--hl-arrow); white-space: nowrap; }

/* Opacity sits behind TWO left edges: --ui/main on the outside and
   --bx/enabled on the box within it. The same lit-then-dark pair the buttons
   use, turned on its side. */
.opt .op { display: flex; align-items: center; justify-content: center;
           width: 44px; height: 100%; flex: none;
           border-left: 1px solid var(--ui-main); box-sizing: border-box; }
.opt .op > span { display: flex; align-items: center; justify-content: center; gap: 2px;
                  flex: 1 0 0; min-width: 0; height: 100%; padding: 0 8px;
                  border-left: 1px solid var(--bx-enabled); box-sizing: border-box;
                  font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; }
.opt .op b { font-weight: 600; color: var(--hl-arrow); }
.opt .op s { text-decoration: none; color: var(--bx-stroke-light); }

/* ---- states -------------------------------------------------------------- */
/* HOVER adds one token to the set: BX/STROKE HOVER. The frame is the only part
   that can carry it - INFERRED. */
.opt.is-hover { background: var(--bx-stroke-hover); border-color: var(--bx-stroke-hover); }
/* ENABLED drops BX/DISABLED and gains TX/BLACK, HL/BLUE and HL/BLUE LIGHT.
   Black type on a blue fill with a lighter edge is the chip this design uses
   everywhere for "this one is live", and NAME is the only element that takes
   type on a fill - INFERRED, and the part most worth checking. */
.opt.is-enabled { background: var(--bx-stroke); border-color: var(--bx-stroke); }
.opt.is-enabled .name { background: var(--hl-blue); border-color: var(--hl-blue-light);
                        color: var(--ui-white); }   /* white on blue, Adi 2026-10-11 (file has --tx/black) */
.opt.is-enabled .name .ico { background: var(--tx-black); }
.opt.is-enabled .value { background: var(--bx-enabled); }

/* CONFIRMED by the PROPERTIES panel (271:2386), which draws both states with
   their values: HOVER (107:1037) darkens NAME to --bx/disabled on a
   --bx/enabled edge and VALUE to --bx/enabled all round; ENABLED (107:1054)
   puts the frame on a --bx/enabled edge and the VALUE on an --hl/blue one. The
   OPACITY cell's outer edge follows the frame in each. */
.opt.is-hover .name { background: var(--bx-disabled); border-color: var(--bx-enabled); }
.opt.is-hover .value { background: var(--bx-enabled); border-color: var(--bx-enabled); }
.opt.is-hover .op { border-left-color: var(--bx-stroke-hover); }
.opt.is-enabled { border-color: var(--bx-enabled); }
.opt.is-enabled .value { border-color: var(--hl-blue); }
.opt.is-enabled .op { border-left-color: var(--hl-blue); }

/* ==========================================================================
   PANEL TAB — the layer row  (Figma 1:274)

   A left half carrying the name and a right half carrying the controls, and the
   join between them is the whole trick: the left is --ui/main, the right is
   --ui/main-dark, and the step between the two is what makes the row read as a
   tab rather than as a strip.

   THE GLOW is the part that would never be guessed. Down the RIGHT edge of the
   left half, and along the TOP of it, run two 1px gradients from 20% white to
   nothing - a highlight where the raised half catches the light. It is drawn in
   white at low alpha rather than as a token, deliberately: it has to work over
   whatever colour the half happens to be.
   ========================================================================== */
.tab {
  display: flex; align-items: center; justify-content: space-between;
  height: 20px; width: 100%; box-sizing: border-box;
  font: var(--ui-tab);
}
.tab .l {
  position: relative; display: flex; align-items: center; justify-content: center;
  gap: 10px; height: 100%; padding: 0 10px; flex: none;
  background: var(--ui-main); color: var(--tx-light);
}
/* The two gradients. Separate elements rather than one box-shadow: they run in
   different directions and fade independently. */
.tab .l::after,
.tab .l::before { content: ''; position: absolute; pointer-events: none; }
.tab .l::after  { right: 0; top: 0; width: 1px; height: 20px;
                  background: linear-gradient(rgba(255,255,255,.2), rgba(255,255,255,0)); }
.tab .l::before { right: 1px; top: 0; height: 1px; width: 20px;
                  background: linear-gradient(to left, rgba(255,255,255,.2), rgba(255,255,255,0)); }

.tab .r {
  display: flex; align-items: center; justify-content: flex-end;
  flex: 1 0 0; min-width: 0; height: 100%; box-sizing: border-box;
  background: var(--ui-main-dark);
  border-left: 1px solid var(--ui-bg); border-bottom: 1px solid var(--ui-bg);
}
/* The divider between controls is TWO 1px rules side by side - --bx/stroke then
   --bx/disabled - the same lit-then-dark pair as everywhere else, stood on end.
   19px tall inside a 20px row, so it stops a pixel short of the bottom edge. */
.tab .sep { width: 2px; height: 19px; flex: none;
            background: linear-gradient(to right,
                        var(--bx-stroke) 0 1px, var(--bx-disabled) 1px 2px); }
/* Each control is 19 wide INCLUDING a 1px --ui/main-dark right edge - BOTH of
   them carry it (279:20536 and 395:33457), and 1px of top padding drops the
   10px glyph onto the row's optical centre. The glyphs come from the sprite
   (nav-panel-*), each in its own colour, so nothing here paints them. */
.tab .ico { display: flex; align-items: center; justify-content: center;
            width: 19px; height: 100%; flex: none; box-sizing: border-box;
            padding-top: 1px; border-right: 1px solid var(--ui-main-dark); }
.tab .ico svg { display: block; width: 10px; height: 10px; }

/* ---- stances (Figma 1:274 DEFAULT, 395:35286 HOVER, 395:35400 LOCKED) ------
   A LIT control sits on a --bx/disabled plate: the lock on HOVER, the hide on
   LOCKED. The lock's right edge goes dark with its plate; the hide keeps its
   --ui/main-dark edge, as the file draws it. */
.tab .ico.lit { background: var(--bx-disabled); }
.tab .ico.lit.first { border-right-color: var(--bx-disabled); }

/* ==========================================================================
   SEPARATORS  (Figma 286:33551)
   ========================================================================== */

/* The 2px rule: --bx/stroke-light over --bx/disabled. Two 1px lines, not one
   2px line - the light one is the edge catching light and the dark one is the
   shadow under it, and a single colour cannot be both. */
.sep-line { width: 100%; height: 2px;
            background: linear-gradient(var(--bx-stroke-light) 0 1px,
                                        var(--bx-disabled) 1px 2px); }

/* The two header variants, 13px tall. OPTION carries a label; CLEAN is the same
   band with nothing in it - which is why they are one component and not two:
   the band's height holds the rhythm whether or not there is anything to say. */
.sep-hl { display: flex; align-items: center; height: 13px; width: 100%;
          font: var(--ui-tab); color: var(--tx-dark); }
/* CLEAN (395:38015) is the label WITHOUT the nav - the band shrinks to the
   label's own 8px. It used to be an empty transparent band; the file draws the
   label in it. */
.sep-hl.clean { height: 8px; }

/* ==========================================================================
   BG — the plates a glyph sits on  (Figma 272:3422)
   22, 20 and 12px. Every icon button on the page is one of these with something
   drawn in it, which is why they are shown on their own: get the plate wrong
   and every button inherits it.
   ========================================================================== */
.bg-plate { display: inline-block; box-sizing: border-box;
            background: var(--ui-main); border: 1px solid var(--bx-disabled); }
.bg-plate.p22 { width: 22px; height: 22px; }
.bg-plate.p20 { width: 20px; height: 20px; }
.bg-plate.p12 { width: 12px; height: 12px; }

/* ==========================================================================
   SLIDER  (Figma 275:4029 / 273:1205)

   A row of MARKS with LINE segments stretching between them. The marks sit at
   their stops; the lines take whatever is left, so the whole thing fits any
   width without the stops drifting off their labels.

   THE MARK IS A DIAMOND, and in the file it is drawn as twenty-four one-pixel
   divs - pixel art, one rectangle per step of the outline. Reproduced here as
   four nested diamonds with clip-path instead.

   That is a deliberate departure and worth stating: twenty-four divs per mark,
   five marks, is a hundred and twenty elements for a control that is one shape.
   The clip-path version is four, scales to any size, and changes colour by
   changing a variable rather than by editing twenty-four fills. What it gives
   up is the exact stair-stepping of the hand-placed pixels at 13px - the
   diagonals are antialiased rather than crisp.
   If that crispness turns out to matter at this size, the honest fix is an SVG
   with the real pixel outline, not twenty-four elements.
   ========================================================================== */

.sl { display: flex; align-items: flex-start; width: 349px; height: 22px; }

/* ---- the OPACITY row  (316:55478 -> 278:11307) --------------------------
   A 41px value field, a 10px gap, then the slider taking the rest.
   THE FIELD IS THE PRECISE ONE and the slider is the quick one. That division
   is the whole design: the marks jump to 0, 25, 50, 75 and 100 because those
   are the values anybody actually wants in a hurry, and anything else is typed
   in the box beside them - or reached by dragging a mark, which is the same
   number arrived at by hand.
   Which is why the marks can be a fixed five: they are not a scale, they are
   shortcuts. */
.opacity-row { display: flex; align-items: center; gap: 10px; width: 276px; }
.opacity-row .opt { width: 41px; flex: none; }
/* The slider takes what is left rather than a fixed 225: the panel is 276 wide
   today and the row should survive it being anything else. */
.opacity-row .sl { flex: 1 0 0; width: auto; min-width: 0; }

/* A stop: the mark, then its label, centred under it. */
.sl-stop { display: flex; flex-direction: column; align-items: center; gap: 4px;
           flex: none; }
/* The labels are 5px pixel-drawn digits in the file. Set in the UI face here
   at the smallest size that stays legible - a five-pixel bitmap digit and a
   hinted 8px glyph are the same idea done two ways, and only one of them can
   say "37%" without being redrawn.
   The stack is written out rather than taken from a --ui token: that token
   lives in chrome.css, and this file is loaded on its own by anything that
   wants the components without the page furniture. Naming a variable that may
   not be there would leave the labels in whatever the browser defaults to,
   which on Windows is Times. */
.sl-stop b { font: 600 8px/1 "Chakra Petch", "Segoe UI", system-ui, sans-serif;
             color: var(--tx-standard); }
.sl-stop.is-mid b { color: var(--hl-arrow); }
/* "0%": the digit in --tx/standard, the sign in --hl/arrow, as the file draws
   them (274:1755 and 275:1450). Only the first stop carries a sign. */
.sl-stop b s { text-decoration: none; color: var(--hl-arrow); }

/* ---- the line between stops --------------------------------------------
   Three stacked rules, not a border: a light 1px, a 3px well, a light 1px. The
   same lit-then-dark pair the buttons use, laid flat - which is why the track
   reads as a groove rather than as a line. */
.sl-line { flex: 1 0 0; min-width: 1px; padding-top: 4px; overflow: hidden; }
.sl-line i { display: block; }
.sl-line .t, .sl-line .b { height: 1px; background: var(--bx-stroke-light); }
.sl-line .f { height: 3px; background: var(--bx-disabled); position: relative; }
/* THE DASHED CENTRE (275:1572): a 1px --bx/stroke-light rule, 2 on 2 off, down
   the middle row of the well. The file draws it as an SVG line starting 1px
   left of the groove, so the first dash is cut to a single pixel - the -1px
   offset keeps that phase rather than starting on a full dash. */
.sl-line .f::after { content: ''; position: absolute; left: -1px; right: 0; top: 1px; height: 1px;
  background: repeating-linear-gradient(to right, var(--bx-stroke-light) 0 2px, transparent 2px 4px); }

/* ---- the mark ----------------------------------------------------------- */
/* ONLY THE CURRENT ONE IS A HANDLE.
 *
 * The grab cursor was on every mark, which promised that all five could be
 * dragged. They cannot: four of them are stops to jump TO, and only the one
 * holding the value is the thing you take hold of. A cursor that offers a
 * gesture the control does not have is worse than no cursor at all.
 *
 * So the stops get the same pointer as the track - they are click targets, and
 * clicking one is the same act as clicking the line beside it - and grab is
 * reserved for the handle. */
.sl-mark { position: relative; width: 13px; height: 13px; flex: none;
           cursor: var(--adi-pointer), default; }
.sl-mark.is-selected { cursor: var(--cur-move), move; }
/* THE WHOLE TRACK IS CLICKABLE, so it has to look it. A control that only
   responds on its 13px marks reads as broken the first time somebody aims at
   the line between them - which is the gesture this slider is mostly for. */
.sl-line { cursor: var(--adi-pointer), default; }
.sl.is-dragging .sl-mark.is-selected { cursor: var(--cur-move), move; }
/* The marks sit above the line so a press on the handle grabs it rather than
   snapping - dragging is the finer of the two gestures and should win where
   they overlap. */
.sl-stop { position: relative; z-index: 1; }

/* ==========================================================================
   SLIDER — the FREE variant  (.sl.is-free)
   
   The same track, a different idea about what the handle is.
   
   In the snapping version the five marks ARE the handle - one of them lights up
   and the others are shortcuts. Here there is a SIXTH thing: a handle that
   belongs to no stop and travels the whole track under the cursor. The five
   marks become ticks - they never move, and they brighten as the handle passes
   over them.
   
   The difference in feel is the point of having both. Snapping says "pick one
   of these"; this says "put it where you like, and here is where the round
   numbers are". Same control, different promise.
   ========================================================================== */
.sl.is-free { position: relative; }

/* The travelling handle. POSITIONED FROM JAVASCRIPT, not from a calc here.
 *
 * It was `left: calc(6.5px + (100% - 13px) * var(--v) / 100)`, which assumes
 * both end stops are exactly the width of their mark. They are not: the label
 * "100%" makes the last stop wider than its diamond, so the calc put the handle
 * past the end of the track by the difference.
 *
 * The script measures the first and last MARK and places the handle between
 * them - the same measurement it reads the pointer with, so the handle lands on
 * a tick exactly when the value equals it. One source of truth for both
 * directions beats two that agree until a label changes. */
.sl-head {
  position: absolute; top: 0; left: 0; width: 13px; height: 13px; z-index: 2;
  cursor: var(--cur-move), move;
}
/* The mark inside is a SPAN: in a stop it is a flex item and takes its 13x13,
   but in the head it is plain inline, where width and height do nothing - the
   diamond collapsed to 0x0 and the handle worked while drawing nothing
   (Adi 2026-10-23). */
.sl-head > .sl-mark { display: block; }
.sl.is-free.is-dragging .sl-head { cursor: var(--cur-move), move; }

/* HOLDING SHIFT SHOWS ITSELF. The behaviour changes - the handle stops
   following the cursor and starts landing on stops - so the control has to look
   different, or the key reads as broken while it is working. The ticks come up
   to the colour they use when hit, which says "these are what you are choosing
   between now".
   The TICKS only: the handle carries .sl-mark too, and lighting it here would
   repaint the one element that must keep saying "this is the value". */
.sl.is-free.is-snapping .sl-stop .sl-mark .st { background: var(--hl-arrow); }
.sl.is-free.is-snapping .sl-stop b { color: var(--tx-standard); }
/* No transition: the handle must sit under the cursor, not chase it. A quarter
   of a second of easing feels responsive on a button and feels broken on
   something you are holding. */

/* The ticks stop being buttons here - they are marks on a ruler. Left at the
   pointer cursor because clicking one still jumps to it, which is the one
   thing worth keeping from the other variant. */
.sl.is-free .sl-mark { cursor: var(--adi-pointer), default; }
/* Under the handle, so the handle is always the thing you grab. */
.sl.is-free .sl-stop { z-index: 1; }

/* A tick BRIGHTENS while the handle is over it, and its label with it. Not
   "selected" - the handle is what holds the value - just lit, the way a
   detent feels rather than looks. */
.sl.is-free .sl-mark.is-near .st { background: var(--hl-arrow); }
.sl.is-free .sl-stop.is-near b { color: var(--tx-light); }
.sl-mark i {
  position: absolute; display: block;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
/* Four diamonds, each one pixel inside the last: the outline, a dark ring, the
   face, and - only when the mark is live - the dot that says so. Nesting by
   inset rather than by stroking, because a clip-path has no border. */
.sl-mark .st { inset: 0;   background: var(--bx-stroke-light); }
.sl-mark .in { inset: 1px; background: var(--bx-enabled); }
.sl-mark .fl { inset: 2px; background: var(--bx-disabled); }
.sl-mark .se { inset: 4px; background: none; }

/* HOVER lifts the outline to --hl/arrow and puts a grey dot in the middle. */
.sl-mark.is-hover .st { background: var(--hl-arrow); }
.sl-mark.is-hover .se { inset: 3px; background: var(--bx-enabled); }
.sl-mark.is-hover .se::after {
  content: ''; position: absolute; inset: 1px; background: var(--hl-icon);
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
/* SELECTED is the same shape in blue - the ring dark blue, the dot bright, so
   the mark reads as filled rather than merely outlined. */
.sl-mark.is-selected .st { background: var(--hl-arrow); }
.sl-mark.is-selected .se { inset: 3px; background: var(--hl-blue); }
.sl-mark.is-selected .se::after {
  content: ''; position: absolute; inset: 1px; background: var(--hl-blue-dark);
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}

/* ==========================================================================
   PANEL - TOOLS   (330:59983)

   One column of 38px icon buttons - the size that was added for exactly this.
   The buttons are the ICON BUTTONS already in this guide, `.ui-ico.s38` with
   its own states, so the panel is assembly rather than new drawing and a
   change to the button reaches here.

   Nothing is chosen when the panel opens; click a tool to take it and click it
   again to let it go.
   ========================================================================== */
/* 52 FIXED for now. 38 + 7 + 7 = 52 exactly, so the button and the panel's
   edge line up with no pixel left over - which is what the 38 size was added
   for.
   Fixed rather than a minimum ON PURPOSE, for the moment: a min-width would
   let the panel quietly grow to whatever was put in it, and on a sheet whose
   job is to show the drawn size that hides the very thing being checked.
   Stretching gets tried in the application, where there is a window to
   stretch against. */
.p-tools { width: 52px; display: flex; flex-direction: column;
           align-items: flex-start; background: var(--ui-main); }

/* THE TAB IS THE SHARED COMPONENT, not a copy of it. `.tab` with its `.l` and
   `.r` already lives in this file for the PANEL TAB block on the INTERFACE
   sheet - label on the left, separators and the lock and hide controls on the
   right. I had written a stripped-down version here with just a label, which
   is how two tabs end up looking different after one of them is tweaked. */

/* THE SEPARATOR LOSES ITS RIGHT PIXEL HERE. `.tab .sep` is 2px - --bx/stroke
   then the darker --bx/disabled - because on the INTERFACE sheet the tab is one
   segment of a longer bar, and that second pixel is the START of the segment
   next to it. The tools panel has nothing to its right, so the pixel would be
   drawing the edge of something that is not there. */
.p-tools .tab .sep { width: 1px; background: var(--bx-stroke); }

.p-tools > .box { flex: 1 0 0; width: 100%; background: var(--ui-main);
                  display: flex; flex-direction: column; align-items: flex-start;
                  /* chrome.css gives the PAGE's `.box` a 200px tail; this one
                     inherited it, ran 200 past the end of every panel and
                     painted over the gaps between the three LINK panels. */
                  padding-bottom: 0; }

/* 7 of padding, 10 between - at 52 wide that is one button per row, and the
   wrap is what makes it a column without saying so twice. */
.p-tools .tools { display: flex; flex-wrap: wrap; gap: 10px; padding: 7px;
                  width: 100%; box-sizing: border-box; align-content: flex-start; }
.p-tools .tools .ui-ico { flex: none; }
.p-tools .tools .ui-ico svg { display: block; }

/* ---- the three states of a tool -----------------------------------------
 *
 * REST is the Disabled button - that is what the file draws for a tool nobody
 * has chosen, and it is why the panel reads as quiet until you point at it.
 * HOVER is the Hover button: a --bx/disabled plate.
 * CHOSEN is the ENABLED button: a --bx/enabled plate, which is darker. That
 * one pixel of difference is the whole distinction between "you are pointing
 * at this" and "you are holding this", and I had given the chosen tool Hover's
 * colours - so a tool you had picked looked the same as one under the cursor.
 *
 * BOTH GLYPHS ARE IN THE BUTTON AT ONCE, stacked, and the fade is between
 * their opacities. Swapping the <use> href cannot be animated - it is a
 * different file, and a file either is or is not being shown - so a cross-fade
 * needs both present. That also puts the whole state in CSS: one class on the
 * button and the stylesheet does the rest, instead of script rewriting hrefs
 * in three places.
 *
 * 120ms, which is about as short as a fade can be and still be seen. Long
 * enough to soften the edge, short enough that a toolbar still feels like
 * buttons rather than something that has to catch up with you. */
.p-tools .tools .ui-ico { cursor: var(--adi-pointer), default;
  transition: background-color 120ms ease, border-color 120ms ease; }
.p-tools .tools .ui-ico > .plate {
  transition: background-color 120ms ease, border-color 120ms ease; }

.p-tools .tools .ui-ico:hover { border-color: var(--bx-stroke-hover); }
.p-tools .tools .ui-ico:hover > .plate { background: var(--bx-disabled);
                                         border-color: var(--bx-enabled); }
/* Chosen wins over hover: pointing at the tool you are already holding must
   not step it back down to the lighter plate. */
.p-tools .tools .ui-ico.is-on,
.p-tools .tools .ui-ico.is-on:hover { border-color: var(--bx-stroke-hover); }
.p-tools .tools .ui-ico.is-on > .plate,
.p-tools .tools .ui-ico.is-on:hover > .plate { background: var(--bx-enabled);
                                               border-color: var(--bx-enabled); }

/* The two glyphs share one spot; the lit one is revealed rather than swapped
   in. `position:absolute` on both so neither claims the space twice. */
.p-tools .tools .plate { position: relative; }
/* ONLY THE GLYPHS INSIDE A BUTTON. This was `.p-tools .tools svg`, which also
   caught the link chain - and since its `.bar` is not positioned, the chain
   anchored to whatever was positioned far above and landed in the middle of
   the page. Absolute positioning needs to name what it is positioning. */
.p-tools .tools .ui-ico svg { display: block; position: absolute;
                      top: 50%; left: 50%; transform: translate(-50%, -50%);
                      transition: opacity 120ms ease; }
/* Scoped to the button as well, for the same reason: the chain is an svg
   inside .tools too, and `svg.lit` would have hidden it. */
.p-tools .tools .ui-ico svg.lit { opacity: 0; }
.p-tools .tools .ui-ico:hover svg.lit,
.p-tools .tools .ui-ico.is-on svg.lit { opacity: 1; }
/* The grey one fades the other way, so the middle of the transition is a blend
   rather than both at full strength. */
.p-tools .tools .ui-ico:hover svg.dim,
.p-tools .tools .ui-ico.is-on svg.dim { opacity: 0; }

/* ---- the spacer (398:42027) ---------------------------------------------
   Five groups butted together with NO gap between them - they are one strip,
   not five dots spaced out; I had put 4px between and it read as a dotted line
   instead of a grip.
   Each group is two studs: one at the origin, the second offset 3 right and 4
   down. A stud is a dark 2px square with a light one a pixel behind it, which
   is what makes it look raised rather than like a speck. */
.p-tools .spacer { display: flex; align-items: center; gap: 0;
                   padding: 7px; width: 100%; box-sizing: border-box; }
.p-tools .stud { position: relative; width: 6px; height: 7px; flex: none; }
.p-tools .stud i { position: absolute; width: 2px; height: 2px; display: block; }
/* Light behind, dark in front, one pixel apart - the light edge is what makes
   a 2px dot read as raised rather than as a speck of dirt. */
.p-tools .stud i:nth-child(1) { left: 1px; top: 1px; background: var(--bx-stroke-light); }
.p-tools .stud i:nth-child(2) { left: 0;   top: 0;   background: var(--bx-disabled); }
.p-tools .stud i:nth-child(3) { left: 4px; top: 5px; background: var(--bx-stroke-light); }
.p-tools .stud i:nth-child(4) { left: 3px; top: 4px; background: var(--bx-disabled); }

/* ---- the colour pair (316:26616) ----------------------------------------
   Grew with the panel: two 24px chips, the back one offset 13 down and right,
   in a 37x37 box. It was 21px chips at 9 - the numbers from when the panel was
   45 wide - so the pair sat small and high in the wider strip.
   Each chip is a 1px stroke around its fill, with a lit top-left and a shaded
   bottom-right edge. The front one is the fill colour, the one behind is the
   stroke. */
.p-tools .swatches { padding: 7px; width: 100%; box-sizing: border-box; }
.p-tools .pair { position: relative; width: 37px; height: 37px; }
/* SWITCH / ROTATE (378:51029) - the 9px mark in the bottom-left corner that
   swaps the selected colour.
   IT IS A PIXEL DRAWING, not a bordered box: seven 1px rectangles in three
   colours - an L of --hl/arrow, two --hl/icon strokes and a 3px --ui/black
   square. I had guessed it was a small square with an edge, which was wrong in
   kind, not just in colour. Drawn as rects so every pixel stays where it was
   put. */
.p-tools .switch { position: absolute; left: 2px; top: 27px;
                   width: 9px; height: 9px; display: block; cursor: var(--adi-pointer), default; }
.p-tools .switch rect.a { fill: var(--hl-arrow); }
.p-tools .switch rect.i { fill: var(--hl-icon); }
.p-tools .switch rect.k { fill: var(--ui-black); }
.p-tools .switch:hover rect.a { fill: var(--hl-icon); }

.p-tools .chip { position: absolute; width: 24px; height: 24px;
                 box-sizing: border-box; padding: 1px; }
.p-tools .chip.back  { left: 13px; top: 13px; border: 1px solid var(--hl-arrow); }
.p-tools .chip.front { left: 0;   top: 0;   background: var(--hl-arrow); }
.p-tools .chip > u { display: block; width: 100%; height: 100%;
                     box-sizing: border-box; text-decoration: none;
                     border: 1px solid var(--bx-enabled); position: relative; }
.p-tools .chip.back > u { border-color: var(--bx-disabled); }
/* The lit and shaded edges, at 15% as the file has them. */
.p-tools .chip > u::before, .p-tools .chip > u::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; }
.p-tools .chip > u::before { border-top: 1px solid rgba(255,255,255,.15);
                             border-left: 1px solid rgba(255,255,255,.15); }
.p-tools .chip > u::after  { border-bottom: 1px solid rgba(17,17,17,.15);
                             border-right: 1px solid rgba(17,17,17,.15); }

/* ==========================================================================
   LINK  (398:45605) - the little chain between two tool buttons.

   It ties the pointer to the transform tool: pick one and you get the other.
   Three states, and they differ in more than colour:

     DISABLED  a 38x8 box in --ui/main - the panel's own colour, so it reads
               as part of the panel - with the chain on it and no edge.
     HOVER     the box darkens to --bx/disabled and gains a --bx/enabled edge.
     ENABLED   box goes --bx/enabled with a --hl/blue edge, and the chain
               turns --hl/blue-light. Both tools go enabled with it.

   The 8px strip is the same width as the buttons and sits 1px from each, so
   the three read as one control rather than as two buttons with a decoration
   between them.
   ========================================================================== */
.p-link { display: flex; flex-direction: column; gap: 1px;
          align-items: flex-start; width: 38px; }

/* The strip: 38 x 8, the same width as the buttons above and below it.
   AT REST IT HAS A FILL BUT NO EDGE - --ui/main, the panel's own colour. It
   was transparent here, which looks identical against the panel and is not
   the same thing: a box that is painted keeps its colour wherever it is put,
   and a hole takes whatever is behind it.
   `border: 0` rather than a transparent 1px, because a transparent edge would
   still take its pixel and shift the chain against the other two states. */
.p-link > .bar { width: 100%; height: 8px; box-sizing: border-box;
                 display: flex; align-items: center; justify-content: center;
                 padding: 2px 8px; border: 0; background: var(--ui-main);
                 transition: background-color 120ms ease, border-color 120ms ease; }
.p-link > .bar svg { display: block; }
/* HOVER (398:45343): the box appears - --bx/disabled with a --bx/stroke-light
   edge - and it is 10 tall: the 8px lettering box plus its 1px edge top and
   bottom, which is why the HOVER and ENABLED panels are 122 and DISABLED 120.
   It used to stay 8 with the edge drawn inside, and on --bx/enabled. */
.p-link.is-hover > .bar { height: 10px; background: var(--bx-disabled);
                          border: 1px solid var(--bx-stroke-light); }

/* ENABLED (398:45477): darker box, blue edge, the lettering lit. */
.p-link.is-on > .bar { height: 10px; background: var(--bx-enabled);
                       border: 1px solid var(--hl-blue); }

/* The TAB of the DISABLED panel carries no glow (398:43597 - its GLOW group
   is empty); HOVER and ENABLED keep it. */
.tab.no-glow .l::before, .tab.no-glow .l::after { display: none; }

/* ---- the tab as the APP has it ------------------------------------------
   HOVER (395:35286): a blue-dark wash from the lower right under the name,
   linear-gradient(19.03deg, --ui/main 53.578%, --hl/blue-dark 139.91%), where
   the head can be GRABBED - the name and the empty strip, not the controls.
   A gradient cannot be transitioned, so only its blue end moves: --tab-glow
   is a registered colour at --ui/main at rest (a flat plate, as before) that
   eases to --hl/blue-dark - the wash fading in from nothing and back out.
   The cursor is the canvas's move pointer (core/cursors.css), as in the app. */
@property --tab-glow { syntax: '<color>'; inherits: false; initial-value: #333333; }
.tab .l { --tab-glow: var(--ui-main);
          background-image: linear-gradient(19.025606841120364deg,
                            var(--ui-main) 53.578%, var(--tab-glow) 139.91%);
          transition: --tab-glow .15s ease; }
.tab:hover:not(:has(.ico:hover, .sep:hover)) .l { --tab-glow: var(--hl-blue-dark); }
.tab { cursor: var(--cur-pointer-move), move; }
.tab .ico, .tab .sep { cursor: var(--adi-pointer), default; }
/* A still is a picture of a state - it does not light up or offer a grab. */
.p-tools.still .tab { pointer-events: none; }
/* SOLO - TOOLS in the app: no controls, the name plate is the whole head. */
.tab.solo .l { flex: 1 1 auto; }


/* ==========================================================================
   PANEL - TEXT   (383:52325, panel itself PANEL - CHARACTER 383:53457)

   The widest panel in the guide and the one that proves the components: apart
   from the quote box and the LANGUAGE row it is ENTIRELY made of things this
   file already defines - the TAB, the HL header, OPTION, LINE and the 28px
   icon button. Nothing new was drawn for it.

   300 wide with 12 of padding, so the content column is 276. Section spacing
   is taken from the file one by one rather than normalised, because the file
   does not normalise it: SOURCE puts 14 between its header and its box, the
   others put 10, LAYOUT puts 12, and the gap BETWEEN sections is 12
   everywhere. Those differences are reproduced, not tidied.
   ========================================================================== */
.p-text { width: 300px; display: flex; flex-direction: column;
          align-items: flex-start; background: var(--ui-main); }
/* `.body` AND `.well`, NOT `.box` — the same trap the plate fell into and the
   comment at the top of this file warns about. chrome.css gives the page's own
   `.box` `flex-direction: column` and `padding-bottom: 200px`, so the icon
   groups came out stacked vertically with a 200px tail under them. A
   component's inner parts have to carry the component's own names; a bare word
   like `box` is certain to collide with the page it is dropped into. */
.p-text > .body { width: 100%; box-sizing: border-box; padding: 12px;
                  display: flex; flex-direction: column; align-items: stretch;
                  gap: 12px; background: var(--ui-main); }

/* A section is its HL header, its rows, and the LINE that closes it. --sec-gap
   is the header-to-body distance, which is the one measurement that differs
   between them; 12 between everything at the top level is not. */
.p-text .sec { display: flex; flex-direction: column; align-items: stretch;
               gap: var(--sec-gap, 10px); }
.p-text .sec.source { --sec-gap: 14px; }
/* The band sits directly on the panel here and the label is set to the BOTTOM
   of it, not the middle. */
.p-text .sep-hl { align-items: flex-end; }
.p-text .rows { display: flex; flex-direction: column; gap: 10px; }
/* Two fields on one line, each taking half of what is left after the 10 gap. */
.p-text .pair-row { display: flex; gap: 10px; align-items: flex-start; }
.p-text .pair-row > .opt { flex: 1 0 0; min-width: 0; }
/* STROKE is the exception and the file means it to be: the colour field takes
   what is left and the width field is a fixed 61, because a stroke width is
   two digits and a hex is six. */
.p-text .stroke-row > .opt:last-child { flex: none; width: 61px; }
/* An OPTION inside this panel is as wide as the column, not the component's
   own drawn 300. */
.p-text .opt { width: auto; }

/* ---- the quote box (383:53213) ------------------------------------------
   The same two boxes as an OPTION - a --bx/stroke frame round a --bx/disabled
   well - but the well holds wrapped copy instead of a value, so it has 8 of
   padding all round. 60 tall as drawn, with the copy at the TOP of it: the box
   is sized for the longest string the panel expects, not for this one. The
   text is UI - NUMBERS (Bold 12) in --tx/light - the copy IS the value here,
   which is why it is set in the value face rather than in a label one. */
.p-text .quote { height: 60px; background: var(--bx-stroke);
                 border: 1px solid var(--bx-stroke);
                 box-sizing: border-box; display: flex; align-items: stretch; }
.p-text .quote > p { flex: 1 0 0; min-width: 0; margin: 0; padding: 8px;
                     background: var(--bx-disabled);
                     border: 1px solid var(--bx-enabled); box-sizing: border-box;
                     font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
                     color: var(--tx-light); }
/* the copy box's own scroll column (567:123077): 10 wide beside the well,
   --ui/main-dark with a --bx/enabled edge top, right and bottom and 1 of
   padding; the thumb --bx/stroke-light in a 1px --bx/stroke-hover edge. The
   app sizes and moves the thumb; with nothing to scroll it fills the column. */
.p-text .quote { position: relative; }
.p-text .quote .q-scroll { width: 10px; flex: none; box-sizing: border-box; padding: 1px;
  background: var(--ui-main-dark); border: 1px solid var(--bx-enabled); border-left: 0; }
.p-text .quote .q-scroll > i { display: block; width: 100%; height: 100%; box-sizing: border-box;
  background: var(--bx-stroke-light); border: 1px solid var(--bx-stroke-hover); }
/* the grip (567:123108): three dotted diagonals in --hl/arrow, 7 x 7, 2 in
   from the well's bottom right corner. Each dot is a 1px shadow of the
   (empty) first pixel, so the colour stays the token. */
/* the size buttons (567:123223): an 11 x 21 --bx/stroke frame, 2 in from the
   well's top right, split into two 9 x 9 --bx/disabled cells - a 5px plus
   (567:123183) over a 5px minus (567:123217), both --hl/arrow. They make the
   copy in the box bigger or smaller, as Ctrl + and Ctrl - do. */
.p-text .quote .q-zoom { position: absolute; right: 12px; top: 2px; width: 11px; height: 21px;
  box-sizing: border-box; padding: 1px; display: flex; flex-direction: column; gap: 1px;
  background: var(--bx-stroke); }
.p-text .quote .q-zoom > button { all: unset; display: block; width: 9px; height: 9px; flex: none;
  cursor: var(--adi-pointer), pointer;
  background: linear-gradient(var(--hl-arrow), var(--hl-arrow)) 2px 4px / 5px 1px no-repeat, var(--bx-disabled); }
.p-text .quote .q-zoom > .q-in {
  background: linear-gradient(var(--hl-arrow), var(--hl-arrow)) 2px 4px / 5px 1px no-repeat,
    linear-gradient(var(--hl-arrow), var(--hl-arrow)) 4px 2px / 1px 5px no-repeat, var(--bx-disabled); }
.p-text .quote .q-grip { position: absolute; right: 12px; bottom: 2px; width: 7px; height: 7px;
  cursor: ns-resize; }
.p-text .quote .q-grip::before { content: ''; position: absolute; left: 0; top: 0; width: 1px; height: 1px;
  box-shadow: 6px 6px var(--hl-arrow), 3px 6px var(--hl-arrow), 0 6px var(--hl-arrow),
    4px 5px var(--hl-arrow), 1px 5px var(--hl-arrow), 5px 4px var(--hl-arrow), 2px 4px var(--hl-arrow),
    6px 3px var(--hl-arrow), 3px 3px var(--hl-arrow), 4px 2px var(--hl-arrow), 5px 1px var(--hl-arrow),
    6px 0 var(--hl-arrow); }

/* ---- the LANGUAGE row (384:56651) ---------------------------------------
   The same grammar as the timeline's grouped buttons one size up: an outer
   --bx/stroke frame, an inner well in --bx/enabled, and 1px gaps that the well
   shows through. The label cell takes whatever the buttons leave. */
.p-text .langs { border: 1px solid var(--bx-stroke); box-sizing: border-box; }
.p-text .langs > .cont { display: flex; align-items: center; gap: 1px;
                         height: 30px; box-sizing: border-box;
                         background: var(--bx-enabled);
                         border: 1px solid var(--bx-enabled); }
.p-text .langs .left { flex: 1 0 0; min-width: 0; height: 28px; display: flex;
                       align-items: center; padding: 4px 8px; box-sizing: border-box;
                       background: var(--bx-disabled);
                       font: var(--ui-tab); color: var(--tx-standard);
                       transition: color 220ms ease; }
/* the label lights up while the pointer is anywhere on its bar - Language,
   Align, Image (Adi, 2026-10-16), eased like the buttons beside it */
.p-text .langs:hover .left { color: var(--tx-light); }

/* ---- the icon groups in LAYOUT (383:53295) ------------------------------
   Same construction as LANGUAGE, and that is the point of writing it once:
   ALIGN holds four buttons, TEXT holds five, and neither needs a rule of its
   own beyond how many fit. */
.p-text .igroup { border: 1px solid var(--bx-stroke); box-sizing: border-box;
                  display: inline-flex; }
.p-text .igroup > .well { display: flex; align-items: center; gap: 1px;
                          height: 30px; box-sizing: border-box;
                          background: var(--bx-enabled);
                          border: 1px solid var(--bx-enabled); }
.p-text .paragraph { display: flex; gap: 8px; align-items: flex-start; }

/* The 28px button carries an 18px glyph here where the language variant
   carries two letters. The plate is the same; only its content changes. */
.p-text .ui-ico.s28 > .plate > svg { display: block; }

/* ==========================================================================
   OPTION — the two parts the newer nodes added

   Both are ADDITIONS, not corrections: the OPTION block above was read from
   94:4700, and the nodes in PANEL - CHARACTER are the same component after it
   grew. Nothing above is changed.
   ========================================================================== */
/* NAME holding a glyph instead of a letter (395:43436 and siblings). The drawn
   padding is 4 on all sides, which leaves 18 inside a 28px box - so the glyph
   is centred in the full cell instead and nothing can be cropped.
   NO WIDTH AND HEIGHT HERE. The properties glyphs are 12x12; the file draws
   each inside a 20px ICO frame, and I had written that frame's size onto the
   glyph itself, which blew every one of them up by two thirds. `fit` reads the
   symbol's own viewBox, and that is the only size that can be right. */
.opt .name.glyph { padding: 0; }
.opt .name.glyph > svg { display: block; }
/* ENABLED swaps the name glyph for its -enabled twin, or for the same glyph
   in white where the set has no twin. */
.opt .name.glyph > svg.lit,
.opt.is-enabled .name.glyph > svg.dim { display: none; }
.opt.is-enabled .name.glyph > svg.lit { display: block; }
.opt .name.glyph > svg.white { filter: brightness(0) invert(1); }

/* THE DROPDOWN MARK IS A DRAWN GLYPH: a 26px cell holding arrows/arrow-down at
   12px. The CSS triangle `.arrow` it replaced is gone from every sheet. */
.opt .icon { display: flex; align-items: center; justify-content: center;
             width: 26px; height: 100%; flex: none; padding: 5px 4px;
             box-sizing: border-box; overflow: hidden; }
.opt .icon svg { display: block; }
.opt .icon { position: relative; }
/* THE STILL ARROW (Settings > Editor > dropdown arrows: still): the arrow's
   blue -hover twin (ui-controls.js ddStillPrep lays it over the grey one)
   crossfades in while the pointer is on the field and while its list is open */
.opt .icon > svg.dd-tw { position: absolute; inset: 0; margin: auto; opacity: 0; pointer-events: none;
                         transition: opacity 220ms ease; }
.opt .icon:has(> .dd-tw) > svg:not(.dd-tw) { transition: opacity 220ms ease; }
.opt:hover .icon > svg.dd-tw, .opt.is-open .icon > svg.dd-tw { opacity: 1; }
.opt:hover .icon:has(> .dd-tw) > svg:not(.dd-tw), .opt.is-open .icon:has(> .dd-tw) > svg:not(.dd-tw) { opacity: 0; }

/* THE DROPDOWN ARROW (FINAL, Adi 2026-10-17 - was the "Dropdown Alt"
   proposal; every dropdown gets it, ui-controls.js ddAltPrep makes the
   copies). The host is .dd-alt: the field, or for the font size the arrow
   cell (.icon.dd-alt), as it opens only there.
   A looping "this way" arrow. On hover the resting arrow at once moves down
   and out at the stream's speed - ONE even movement, no run-up (it used to
   start slowly and speed up, which read as a stall: Adi, 2026-10-17) - and
   behind it more of the same grey arrow come down from above at that same
   speed, 13px apart, so two are always in the cell - one leaving, the next
   already there - all at 50%. Off the field the last one in brightens to full
   on its way to the middle (ui-controls.js).
     the numbers fit together: the stream moves 39px (19.5 above to 19.5
     below) in 900ms with three arrows, 300ms = 13px apart, so 43px/s; the
     resting arrow covers its 19.5px at that speed, in 450ms. The arrows sit
     in the same 13px line: the first is already 13px above the middle when
     the hover starts (it is 150ms into its run, and fades in there), the
     next two enter 150 and 450ms in - the last as the resting arrow leaves. */
.dd-alt .icon > svg, .icon.dd-alt > svg { position: absolute; inset: 0; margin: auto; }
.dd-alt .icon > svg.a0, .icon.dd-alt > svg.a0 { transition: opacity 200ms ease; }
.dd-alt .icon > svg.s, .icon.dd-alt > svg.s { opacity: 0; transform: translateY(-19.5px); }
/* .dd-run, not :hover: ui-controls.js sets it on the way in and, on the way
   out, reads where every arrow is BEFORE taking it off - then lets the ones
   below the middle fall out and brings the next one in to rest (altSettle) */
.dd-alt.dd-run .icon > svg.a0, .icon.dd-alt.dd-run > svg.a0 { transform: translateY(19.5px); opacity: .5;
  transition: transform 450ms linear, opacity 200ms ease; }
.dd-alt.dd-run .icon > svg.s, .icon.dd-alt.dd-run > svg.s { opacity: .5; transition: opacity 200ms ease;
  animation: ddFall 900ms linear infinite both; }
.dd-alt.dd-run .icon > svg.s1, .icon.dd-alt.dd-run > svg.s1 { animation-delay: -150ms; }
.dd-alt.dd-run .icon > svg.s2, .icon.dd-alt.dd-run > svg.s2 { animation-delay: 150ms; }
.dd-alt.dd-run .icon > svg.s3, .icon.dd-alt.dd-run > svg.s3 { animation-delay: 450ms; }
@keyframes ddFall { from { transform: translateY(-19.5px); } to { transform: translateY(19.5px); } }

/* A value that is a NAME rather than a number - "Private Customers" - so it is
   set in the label face, not in the blue Bold 12 that means "you can edit
   this". The colour is what separates the two, and it has to. */
.opt .val-text { font: var(--ui-tab); color: var(--tx-standard); white-space: nowrap; }

/* ==========================================================================
   PANEL - PROPERTIES  (Figma 271:2386)

   The same construction as PANEL - CHARACTER, so the panel carries BOTH
   classes - `p-text p-props` - and everything the character panel already
   defines (sections, HL, OPTION, the 28px groups, the live states) applies
   unchanged. What is below is only where PROPERTIES measures differently:
   12 from the header to its rows (not 10), 12 between fields on a line (not
   10), and 12 between rows - except TRANSFORM, which puts 15, written inline
   where it happens. SHAPE's colour rows keep the 10 the STROKE row uses.
   ========================================================================== */
.p-props .sec { --sec-gap: 12px; }
.p-props .rows { gap: 12px; }
.p-props .pair-row { gap: 12px; }
.p-props .stroke-row { gap: 10px; }

/* POSITION's GRID (270:1498): a 30px --bx/stroke frame round the 28px
   anchor picture the file supplies as an SVG. */
.p-props .pos-grid { width: 30px; height: 30px; flex: none; box-sizing: border-box;
                     border: 1px solid var(--bx-stroke); display: flex; }
.p-props .pos-grid img { display: block; width: 28px; height: 28px; }
/* The lock beside W and H is the 30px icon button at rest. */
.p-props .ui-ico.s30 { flex: none; }
.p-props .ui-ico.s30 svg { display: block; }

/* OPACITY (278:11307): the 41px field and the slider with 10 between. The
   character panel's `.opt { width: auto }` would let the field shrink to its
   text, so the width is restated here. */
.p-props .opacity-row { width: 100%; }
.p-props .opacity-row > .opt { width: 41px; }

/* LAYOUT (270:1611): the LANGUAGE bar's construction - "Align" on the left of
   its cell, as the render of the file shows it - and a 4px --bx/disabled block
   between the horizontal and vertical trios (270:1630). */
.p-props .align-bar .vsep { width: 4px; height: 28px; flex: none; background: var(--bx-disabled); }

/* ==========================================================================
   HL — the header with its collapse controls  (395:37168)

   The band from SEPARATORS with the NAV the newer file gives it: two 13px
   buttons, each the two-ring shape everything else here uses - a --bx/stroke
   frame round a --ui/main-dark inner box.

   The label also carries a 1px shadow in --bx/disabled, which is what keeps it
   legible where the band sits directly on the panel.
   ========================================================================== */
.sep-hl { justify-content: space-between; }
.sep-hl > b { font: inherit; font-weight: 600; line-height: 8px;
              text-shadow: 1px 1px 0 var(--bx-disabled); }
/* border-bottom: 0 because chrome.css styles the PAGE's top bar as `.nav`
   with a 1px --bx/enabled underline, and the class name collides - it drew a
   black rule under the button pair wherever both files are loaded. */
.sep-hl .nav { display: flex; align-items: center; gap: 4px; flex: none; border-bottom: 0; }
.sep-hl .nav .ico { width: 13px; height: 13px; box-sizing: border-box; flex: none;
                    border: 1px solid var(--bx-stroke);
                    display: flex; align-items: stretch; }
.sep-hl .nav .ico > i { flex: 1 0 0; min-width: 0;
                        border: 1px solid var(--ui-main-dark);
                        display: flex; align-items: center; justify-content: center; }
.sep-hl .nav svg { display: block; width: 5px; height: 5px; }
/* HOVER (395:43222): the button under the pointer gets the --bx/disabled plate
   with a --bx/enabled inner edge, and its glyph turns blue - the second svg,
   so the swap is a class and not an href rewritten. */
/* EASED (Adi, 2026-10-17): the two glyphs sit on top of each other and
   cross in opacity, the plate and its edge in colour - all 220ms, as the 28
   bars. (They were display: none / block, which cannot be animated.) */
.sep-hl .nav .ico > i { position: relative;
                        transition: background-color 220ms ease, border-color 220ms ease; }
/* centred by margin, not by translate(-50%): half of 5px is 2.5, and a
   glyph drawn half a pixel off its grid goes soft */
.sep-hl .nav .ico > i > svg { position: absolute; inset: 0; margin: auto;
                              transition: opacity 220ms ease; }
.sep-hl .nav svg.lit { opacity: 0; }
/* AT REST THE ARROW IS --bx/stroke-hover, #555 (HL 276:7422, Adi 2026-10-25),
   not the sprite's --hl/icon #909090: 0x55 / 0x90 = 0.5903 of its brightness.
   The hover glyph keeps its own colour. */
.sep-hl .nav svg.dim { filter: brightness(.5903); }
.sep-hl .nav .ico.is-hover > i { background: var(--bx-disabled); border-color: var(--bx-enabled); }
.sep-hl .nav .ico.is-hover svg.lit { opacity: 1; }
.sep-hl .nav .ico.is-hover svg.dim { opacity: 0; }

/* ==========================================================================
   PANEL - TEXT — the live states

   The panel on this sheet RESPONDS, because a state you can only look at is a
   state nobody has checked. Every rule below maps a real gesture onto a
   variant the file already draws - Hover and Enabled on OPTION (94:4700),
   Hover, Enabled and Selected on the 28px button (392:69620 and siblings).
   Nothing here invents a state.
   ========================================================================== */

/* An OPTION lights under the pointer and goes ENABLED when you take hold of
   it. `:not(.is-enabled)` because the field you are holding must not step back
   down to the lighter frame when the pointer is over it - the same rule the
   tools panel needed. */
.p-text .opt { cursor: var(--adi-pointer), default; }
.p-text .opt:not(.is-enabled):hover { background: var(--bx-stroke-hover);
                                      border-color: var(--bx-stroke-hover); }
/* ...and the inside follows, as 107:1037 draws HOVER - so a field under the
   pointer looks exactly like the HOVER state the panels show held open. */
.p-text .opt:not(.is-enabled):hover .name { background: var(--bx-disabled); border-color: var(--bx-enabled); }
.p-text .opt:not(.is-enabled):hover .value { background: var(--bx-enabled); border-color: var(--bx-enabled); }
.p-text .opt:not(.is-enabled):hover .op { border-left-color: var(--bx-stroke-hover); }

/* The 28px button, same idea one size down. SELECTED is excluded as well as
   ENABLED: the language you are on carries the 2px blue edge and pointing at
   it must not take that away. */
.p-text .ui-ico.s28 { cursor: var(--adi-pointer), default; }
/* HOVER IS ALIGN'S EVERYWHERE NOW (Adi 2026-10-18): Text layout, Language,
   Library and the rest - pointing at a 28 draws its ENABLED plate and the
   glyph's -hover twin, eased, as the Align bar has since 10-14. */
.p-text .ui-ico.s28:not(.is-enabled):not(.is-selected):hover {
  border-color: var(--bx-stroke-light); }
.p-text .ui-ico.s28:not(.is-enabled):not(.is-selected):hover > .plate {
  background: var(--bx-disabled); border: 1px solid var(--bx-enabled); }
.p-text .ui-ico.s28:hover > .plate > svg.lit { opacity: 1; }
.p-text .ui-ico.s28:hover > .plate > svg.dim { opacity: 0; }

/* BOTH GLYPHS IN THE BUTTON AT ONCE, the grey one and the blue one, exactly as
   the tools panel does it: one class on the button is the whole state and the
   stylesheet does the rest, instead of script rewriting hrefs.
   HOVER KEEPS THE GREY here - only Enabled goes blue. That is the icon set's
   own rule and it is why the swap is keyed off .is-enabled and not off
   :hover. */
.p-text .ui-ico.s28 > .plate { position: relative; }
.p-text .ui-ico.s28 > .plate > svg { position: absolute; top: 50%; left: 50%;
                                     transform: translate(-50%, -50%);
                                     transition: opacity 120ms ease; }
.p-text .ui-ico.s28 > .plate > svg.lit { opacity: 0; }
.p-text .ui-ico.s28.is-enabled > .plate > svg.lit,
.p-text .ui-ico.s28.is-selected > .plate > svg.lit { opacity: 1; }
.p-text .ui-ico.s28.is-enabled > .plate > svg.dim,
.p-text .ui-ico.s28.is-selected > .plate > svg.dim { opacity: 0; }
/* EXCEPT ALIGN (Adi, 2026-10-14): its buttons are actions, not a state you
   leave on, so pointing at one is the moment it matters - hover draws the
   28 ENABLED plate and the glyph's -hover twin. */
.p-text .align-bar .ui-ico.s28:not(.is-enabled):not(.is-selected):hover { border-color: var(--bx-stroke-light); }
.p-text .align-bar .ui-ico.s28:not(.is-enabled):not(.is-selected):hover > .plate {
  background: var(--bx-disabled); border: 1px solid var(--bx-enabled); }
.p-text .align-bar .ui-ico.s28:hover > .plate > svg.lit { opacity: 1; }
.p-text .align-bar .ui-ico.s28:hover > .plate > svg.dim { opacity: 0; }
/* ...and EASED TOGETHER: the glyphs crossed in 120ms while the plate under
   them changed at once, which read as the icon jumping. Plate, edge and both
   glyphs now move in one 220ms ease. */
/* (Adi, 2026-10-16) the same ease on EVERY 28 bar - Language as well as
   Align and Image: .langs is the frame all three are built on. */
.p-text .ui-ico.s28,
.p-text .ui-ico.s28 > .plate { transition: background-color 220ms ease, border-color 220ms ease; }
/* At rest the plate has NO edge (border: 0) and hover gave it 1px - a real
   one-pixel shift of the box, and an edge that cannot fade in. A transparent
   1px edge at rest (the plate's colour shows through it, so rest looks the
   same) leaves hover only a colour to change. */
/* (2026-10-18: on every 28, not only .langs - the Text layout buttons still
   grew that pixel on hover, which flashed) */
.p-text .ui-ico.s28.is-disabled > .plate { border: 1px solid transparent; }
.p-text .ui-ico.s28 > .plate > svg { transition: opacity 220ms ease; }
.p-text .ui-ico.s28 > .plate > b { transition: color 220ms ease; }

/* SOURCE's "Transformt Source" bar (500:15840 > 540:46517) - the Align bar's
   construction, without its outer --bx/stroke frame: the file draws the
   30px CONT straight in the section. Its buttons (Adi, 2026-10-14):
     ACTIVE   - ENABLED with the PLAIN glyph (fit or fill, whichever is set)
     inactive - DISABLED with the plain glyph
     hover    - ENABLED with the -hover glyph (the Align hover above)
   So ENABLED here does not swap to the blue twin the way the other 28
   buttons do - only the pointer does. */
.p-text .src-bar { border: 0; }
.p-text .src-bar .ui-ico.s28.is-enabled > .plate > svg.lit { opacity: 0; }
.p-text .src-bar .ui-ico.s28.is-enabled > .plate > svg.dim { opacity: 1; }
.p-text .src-bar .ui-ico.s28.is-enabled:hover > .plate > svg.lit { opacity: 1; }
.p-text .src-bar .ui-ico.s28.is-enabled:hover > .plate > svg.dim { opacity: 0; }
/* .is-off: nothing to act on (no picture in the layer) - the pointer does not
   light it (.src-bar three times: the Align hover above is 0,8,0) */
.p-text .src-bar .ui-ico.s28.is-off { cursor: default; }
.p-text .src-bar.src-bar.src-bar .ui-ico.s28.is-off:hover { border-color: var(--bx-stroke-light); }
.p-text .src-bar.src-bar.src-bar .ui-ico.s28.is-off:hover > .plate { background: var(--ui-main); border-color: transparent; }
.p-text .src-bar .ui-ico.s28.is-off:hover > .plate > svg.lit { opacity: 0; }
.p-text .src-bar .ui-ico.s28.is-off:hover > .plate > svg.dim { opacity: 1; }

/* The two 13px header buttons. No positioning needed - one of the pair is
   simply not displayed, which at 5px is the whole of the difference anyway. */
.p-text .sep-hl .nav .ico { cursor: var(--adi-pointer), default; }
.p-text .sep-hl .nav svg.lit { opacity: 0; }
.p-text .sep-hl .nav .ico:hover svg.lit { opacity: 1; }
/* ...on the HOVER plate, as SEPARATORS draws it (395:43222) - --bx/disabled
   with a --bx/enabled inner edge. Only the glyph used to change here. */
.p-text .sep-hl .nav .ico:hover > i { background: var(--bx-disabled); border-color: var(--bx-enabled); }
.p-text .sep-hl .nav .ico:hover svg.dim { opacity: 0; }

/* A CLOSED SECTION KEEPS ITS LINE. The header says what is folded away and the
   rule says where the next section starts; dropping the rule as well would
   make two closed sections read as one. */
.p-text .sec.is-closed > :not(.sep-hl):not(.sep-line) { display: none; }

/* THE STOP LABELS ARE PICTURES (core/icons/slider) - drawn pixel by pixel in
   the file, not set in a font, and one colour in every state. The label's own
   font rules stay for anything still written as text. */
.sl-stop b > img { display: block; }
.sl-stop b:has(> img) { line-height: 0; }

/* ==========================================================================
   PANEL - TIMELINE  (Figma 282:9050, on the TIMELINE sheet 316:39527)

   1239 x 518: the PANEL TAB, then a 356 tall BOX of two columns - LAYERS
   (300) and the frame area (938) - with 1px between everything. The 1px
   seams are the box's own --ui/bg showing through, the same trick the icon
   grids use, so no row or column carries a border of its own.

   Rows are 24 tall on a 25 pitch in both columns, starting under two 40px
   bars. Frames are 10px wide, so the ruler's 50px cell is five frames.

   The small drawings - frame cells, ruler cell, grip dots, mask connector,
   playhead - are rect lists in timeline-art.js, not CSS.
   ========================================================================== */
.p-tl { width: 1239px; height: 518px; display: flex; flex-direction: column; }
.p-tl > .tab { flex: none; }
.p-tl .tl-box { position: relative; display: grid; grid-template-columns: 300px 938px;
                column-gap: 1px; height: 356px; background: var(--ui-bg); }
.p-tl .tl-col { position: relative; display: flex; flex-direction: column; gap: 1px;
                min-width: 0; overflow: hidden; }

/* ---- LAYERS: TIME (282:5669) ------------------------------------------- */
.p-tl .tl-time { height: 40px; flex: none; box-sizing: border-box; padding: 0 10px;
                 display: flex; align-items: center; justify-content: space-between;
                 background: var(--ui-main-light); }
.p-tl .tl-opt { display: flex; align-items: center; gap: 1px; height: 26px; box-sizing: border-box;
                background: var(--ui-main-light); border: 1px solid var(--bx-stroke-light); }
.p-tl .tl-opt > b { height: 24px; box-sizing: border-box; display: flex; align-items: center;
                    justify-content: center; background: var(--ui-main);
                    border: 1px solid var(--bx-disabled);
                    font: 700 10px/10px 'Chakra Petch', 'Segoe UI', sans-serif; color: var(--tx-standard); }
.p-tl .tl-opt > span { height: 24px; box-sizing: border-box; display: flex; align-items: center;
                       justify-content: center; background: var(--bx-disabled);
                       border: 1px solid var(--bx-enabled);
                       font: 700 12px/12px 'Chakra Petch', 'Segoe UI', sans-serif; color: var(--hl-blue); }

/* ---- LAYERS: ACTIONS (282:5673) ---------------------------------------- */
.p-tl .tl-actions { height: 40px; flex: none; box-sizing: border-box; padding-left: 10px;
                    display: flex; align-items: center; justify-content: space-between;
                    background: linear-gradient(to left, var(--bx-stroke), var(--ui-main)); }
.p-tl .tl-actions .main { display: flex; gap: 6px; }
.p-tl .tl-actions .addon { display: flex; gap: 4px; padding-right: 9px; }
/* the 20px button: a frame round an 18px plate, glyph centred */
.p-tl .b20 { width: 20px; height: 20px; box-sizing: border-box; display: flex;
             border: 1px solid var(--bx-stroke); }
.p-tl .b20 > i { flex: 1 0 0; display: flex; align-items: center; justify-content: center;
                 background: var(--ui-main); border: 1px solid var(--bx-disabled); }
.p-tl .addon .b20 { border-color: var(--bx-stroke-light); }
.p-tl .addon .b20 > i { background: var(--ui-main-light); }
.p-tl svg, .tl-comps svg { display: block; }

/* ---- LAYER rows (283:12741 / set 316:39540) ----------------------------- */
.tl-layer { position: relative; height: 24px; flex: none; display: flex; align-items: center;
            background: var(--ui-main); }
.tl-layer .lt { width: 146.5px; height: 100%; display: flex; align-items: center; }
.tl-layer .gap { width: 15px; height: 24px; flex: none; }
.tl-layer .gap.w26 { width: 26px; }
.tl-layer .nm { display: flex; align-items: center; gap: 8px; white-space: nowrap;
                font: 600 10px/1 'Chakra Petch', 'Segoe UI', sans-serif; color: #f0f0f0; }
.tl-layer .nm svg { flex: none; }
.tl-layer .ad { position: absolute; left: 240px; top: 3px; height: 18px; display: flex;
                align-items: center; gap: 1px; padding-right: 2px; }
.tl-layer .ad .ic { width: 20px; height: 18px; position: relative; }
.tl-layer .ad .ic svg { position: absolute; left: 5px; top: 4px; }
.tl-layer.t-mask, .tl-layer.t-masked, .tl-layer.t-masked-end,
.tl-layer.t-folder-inside { background: var(--ui-main-dark); }
.tl-layer.t-selected { background: var(--hl-blue-dark); }
/* MASK alone carries a 1px edge in its own colour, which sets its contents a
   pixel in from the others - invisible as an edge, visible as the shift. */
.tl-layer.t-mask .lt { margin-left: 1px; }

/* the empty column under the rows */
.p-tl .tl-scroll-l { flex: none; display: flex; flex-direction: column; gap: 1px; }
.p-tl .tl-scroll-l > i { display: block; height: 40px; background: var(--ui-main); }
.p-tl .tl-scroll-l > i + i { height: 8px; }

/* ---- TIMELINE: OPTIONS (282:5851) --------------------------------------- */
.p-tl .tl-opts { height: 40px; flex: none; box-sizing: border-box; padding: 10px;
                 display: flex; align-items: center; justify-content: space-between;
                 background: var(--ui-main-light); }
.p-tl .tl-grp { border: 1px solid var(--bx-stroke-light); display: flex; }
.p-tl .tl-grp > .cont { height: 26px; box-sizing: border-box; display: flex; align-items: center;
                        gap: 1px; background: var(--bx-disabled); border: 1px solid var(--bx-disabled); }
/* the 24px button: normal, pressed, toggled on */
.p-tl .b24 { width: 24px; height: 24px; box-sizing: border-box; display: flex;
             background: var(--ui-main-light); border: 1px solid var(--bx-stroke-light); }
.p-tl .b24 > i { flex: 1 0 0; display: flex; align-items: center; justify-content: center;
                 border: 1px solid transparent; }
.p-tl .b24.is-pressed { background: var(--bx-disabled); border-color: var(--bx-stroke-hover); }
.p-tl .b24.is-pressed > i { border-color: var(--bx-enabled); }
.p-tl .b24.is-on { background: var(--bx-enabled); }
.p-tl .b24.is-on > i { border-color: var(--bx-enabled); }
.p-tl .chev { width: 10px; height: 10px; position: relative; }
.p-tl .chev svg { position: absolute; left: 2px; top: 0; }
.p-tl .ease { height: 24px; box-sizing: border-box; padding: 4px 12px; display: flex;
              align-items: center; gap: 5px; background: var(--bx-disabled);
              font: 700 12px/12px 'Chakra Petch', 'Segoe UI', sans-serif; color: var(--hl-blue); }
.p-tl .ease.range { gap: 10px; font: 600 10px/10px 'Chakra Petch', 'Segoe UI', sans-serif;
                    color: var(--tx-standard); }
.p-tl .ease.range > i { width: 1px; height: 24px; background: var(--bx-stroke-light); }
.p-tl .nxt { height: 24px; box-sizing: border-box; padding: 4px 8px; display: flex; align-items: center;
             background: var(--ui-main-light); border: 1px solid var(--bx-stroke-light);
             font: 600 10px/10px 'Chakra Petch', 'Segoe UI', sans-serif; color: var(--tx-standard); }

/* ---- TIMELINE: RULER (282:5880) ----------------------------------------- */
.p-tl .tl-ruler { height: 40px; flex: none; display: flex; overflow: hidden; }
.tl-rcell { width: 50px; height: 40px; flex: none; position: relative; display: block; }
.tl-rcell > b { position: absolute; left: 2px; top: 25px; font: 600 10px/1 'Chakra Petch', 'Segoe UI', sans-serif;
                color: var(--tx-dark); }

/* ---- TIMELINE: frame rows ------------------------------------------------ */
.p-tl .tl-frames { position: relative; height: 24px; flex: none; display: flex; overflow: hidden; }
.p-tl .tl-frames > i { display: block; width: 10px; height: 24px; flex: none; }
/* the Folder row has no cells: 2px stripes in --tm/dark and --ui/bg */
.p-tl .tl-frames.is-folder { background: repeating-linear-gradient(90deg, #323232 0 2px, var(--ui-bg) 2px 4px); }
/* the selected layer's row: a half-strength blue laid over its cells */
.p-tl .tl-frames.is-selected::after { content: ''; position: absolute; inset: 0;
                                      background: rgba(55, 144, 240, 0.5); }

/* the scrollbar under the frames */
.p-tl .tl-scroll-r { flex: none; display: flex; flex-direction: column; gap: 1px; }
.p-tl .tl-scroll-r > i { display: block; height: 40px; background: var(--ui-main); }
.p-tl .tl-scroll-r > .bar { height: 8px; display: flex; gap: 1px; }
.p-tl .tl-scroll-r > .bar > i { flex: 1 0 0; background: var(--ui-main); }
.p-tl .tl-scroll-r > .bar > i.thumb { box-sizing: border-box; background: var(--hl-arrow);
                                      border: 1px solid var(--hl-icon); }

/* the playhead (303:14062) and the selected key (305:14121), placed in the
   frame column's own coordinates */
.p-tl .tl-ph { position: absolute; left: 199px; top: 41px; width: 11px; height: 306px; pointer-events: none; }
.p-tl .tl-ph > * { position: absolute; }
.p-tl .tl-ph .sh { width: 3px; height: 295px; top: 11px; opacity: .1; }
.p-tl .tl-ph .sh.a { left: 1px; transform: rotate(180deg); }
.p-tl .tl-ph .sh.b { left: 7px; }
.p-tl .tl-ph .ln { width: 1px; top: 14px; height: 292px; background: rgba(21, 21, 21, .5); }
.p-tl .tl-ph .ln.a { left: 4px; }
.p-tl .tl-ph .ln.b { left: 6px; }
.p-tl .tl-ph .in { left: 5px; top: 24px; width: 1px; height: 282px; background: var(--hl-blue); }
.p-tl .tl-ph .hd { left: 0; top: 0; }
.p-tl .tl-key { position: absolute; left: 150px; top: 132px; pointer-events: none; }

/* ---- COMPONENTS (316:39535) --------------------------------------------- */
.tl-comps { display: flex; gap: 20px; align-items: flex-start; }
.tl-comps > .pn { border: 1px solid var(--bx-stroke); box-sizing: border-box; flex: none; }
.tl-layers-set { width: 302px; height: 201px; background: var(--ui-bg); display: flex;
                 flex-direction: column; gap: 1px; }
.tl-legend { width: 424px; height: 134px; position: relative; }
.tl-legend .col { position: absolute; top: 1px; }
.tl-legend .it { height: 44px; box-sizing: border-box; padding: 10px; display: flex;
                 align-items: center; gap: 14px; white-space: nowrap;
                 font: var(--ui-tab); color: var(--tx-light); }
.tl-cells { width: 466px; height: 149px; position: relative; }
.tl-cells > * { position: absolute; }
.tl-cells .set > * { position: absolute; }

/* ==========================================================================
   INTERFACE: LISTS (284:21317, BOX 395:52098)
   The library list (LIB - LAYERS 395:51088) and the artboard list
   (OPTION 398:50495), plus the three status states the 28px button gained
   for the artboard list's LANGUAGE column.
   ========================================================================== */

/* ---- 28 px status states (505:38840 / 503:54484 / 505:46611) -------------
   APPROVED is Disabled with the language in blue. EMPTY and TO DO drop the
   plate and sink the whole button into --ui/bg; they differ only in the
   label: EMPTY all but gone (--bx/stroke at half), TO DO in --hl/arrow. */
.ui-ico.s28.is-approved { border-color: var(--bx-stroke-light); }
.ui-ico.s28.is-approved > .plate { background: var(--ui-main); border: 0; }
.ui-ico.s28.is-approved > .plate > b { color: var(--hl-blue); }
.ui-ico.s28.is-empty,
.ui-ico.s28.is-todo { background: var(--ui-bg); border-color: var(--ui-bg); }
.ui-ico.s28.is-empty > .plate,
.ui-ico.s28.is-todo > .plate { background: none; border: 0; }
.ui-ico.s28.is-empty > .plate > b { color: var(--bx-stroke); opacity: .5; }
.ui-ico.s28.is-todo > .plate > b { color: var(--hl-arrow); }
/* SELECTED - the label in --tx/light (Adi, 2026-10-16). After the status
   states on purpose: a picked language that is also Approved or To Do still
   reads white, the 2px blue edge already says which one it is. */
.ui-ico.s28.is-selected > .plate > b { color: var(--tx-light); opacity: 1; }

/* ---- shared by both lists ------------------------------------------------ */
.lst { display: flex; flex-direction: column;
       font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; }
.lst .r { display: flex; align-items: stretch; position: relative; flex: none; }
.lst .r > * { flex: none; }
.lst .c { display: flex; align-items: center; box-sizing: border-box;
          padding: 0 8px; white-space: nowrap; color: var(--tx-dark); }
.lst svg, .lst img { display: block; flex: none; }
.lst .ic { width: 14px; height: 14px; position: relative; flex: none; }
.lst .ic > * { position: absolute; }

/* The header row (395:51089 / 398:50543): 30 tall, a --bx/enabled strip with
   1px gaps between --ui/main cells that carry their own --bx/stroke edge. */
.lst .hd { height: 30px; gap: 1px; background: var(--bx-enabled); }
.lst .hd .c { background: var(--ui-main); border: 1px solid var(--bx-stroke);
              color: var(--tx-standard); gap: 8px; }
.lst .hd .c.name { flex: 1 0 0; min-width: 0; }

/* ---- LIB - LAYERS (395:51088): 544 wide, 30 tall rows -------------------- */
.lst.lib { width: 544px; }
.lib .hd .c:not(.name) { justify-content: center; }
.lib .w55 { width: 55px; } .lib .w70 { width: 70px; } .lib .w65 { width: 65px; }
/* (2026-10-18) every row: --rb shows in the 1px gaps, every cell on --cb;
   the columns' words sit at the right, the head's centred */
.lib .r:not(.hd) { height: 30px; gap: 1px; background: var(--rb, var(--bx-enabled)); }
.lib .r:not(.hd) .c { background: var(--cb, var(--ui-bg)); justify-content: flex-end; }
.lib .r:not(.hd) .c.name { flex: 1 0 0; min-width: 0; padding: 0; justify-content: flex-start;
  color: var(--nc, var(--tx-standard)); }
.lib .sp { width: 28px; height: 100%; display: flex; align-items: center;
           justify-content: center; flex: none; box-sizing: border-box; }
.lib .sp.n { width: 12px; }
.lib .dt { display: flex; align-items: center; gap: 10px; }
/* FOLDER (395:51647): --bx/disabled between --ui/main-dark cells, the name
   --tx/light. OPENED (395:53131): --bx/enabled between --ui/main-light.
   FILE in a folder (395:53268): all --bx/enabled. A file (IMAGE, VIDEO,
   SMART): --bx/enabled between --ui/bg. */
.lib .r.fold { --rb: var(--bx-disabled); --cb: var(--ui-main-dark); --nc: var(--tx-light); }
.lib .r.opened { --rb: var(--bx-enabled); --cb: var(--ui-main-light); --nc: var(--tx-light); }
.lib .r.file { --rb: var(--bx-enabled); --cb: var(--bx-enabled); }
/* SELECTED (571:130670, 571:131149, 571:131644): a 1px --hl/blue edge, the
   cells --bx/enabled; a folder's name turns --hl/blue, a file's stays. The
   icon is its -selected twin (lists.js). */
.lib .r.sel { --cb: var(--bx-enabled); outline: 1px solid var(--hl-blue); outline-offset: -1px; z-index: 1; }
.lib .r.fold.sel, .lib .r.opened.sel { --nc: var(--hl-blue); }
/* SYNC (572:142651): a folder from the campaign's SO - --bx/disabled between
   --ui/main-light cells, the name --tx/light. SELECTED (572:142918): --ui/black
   between --bx/enabled cells, the name stays --tx/light, and no edge is drawn */
.lib .r.sync { --rb: var(--bx-disabled); --cb: var(--ui-main-light); --nc: var(--tx-light); }
.lib .r.sync.sel { --rb: var(--ui-black); --cb: var(--bx-enabled); --nc: var(--tx-light); outline: 0; }
/* HOVER (395:52177): a 1px DASHED --hl/arrow edge, the name --tx/light */
.lib .r.hover { --nc: var(--tx-light); outline: 1px dashed var(--hl-arrow); outline-offset: -1px; z-index: 1; }
/* an External source reads --hl/blue */
.lib .r .c.ext { color: var(--hl-blue); }
/* SPACER (571:132307): 5px of --ui/main-dark */
.lib .r.spacer { height: 5px; background: var(--ui-main-dark); }
/* CHANGED (395:52718): a 4px --hl/blue bar down the left of the spacing. */
.lib .r.changed .sp { border-left: 4px solid var(--hl-blue); }
/* The folder caret points right; open, it points down. */
.lst .caret.down { transform: rotate(90deg); }
/* it turns rather than jumps (the app turns it, then redraws the list) */
.lst .caret { transition: transform .15s ease; }

/* ---- OPTION, the artboard list (398:50495): 590 wide, 28 tall rows ------- */
.lst.art { width: 590px; }
.art .w70 { width: 70px; } .art .w115 { width: 115px; } .art .w57 { width: 57px; }
.art .r:not(.hd) { height: 28px; }
/* NAV (the header) is 28 like every other row of this list, so the
   selection strip's cells are all one height (2026-10-11). */
.lst.art .hd { height: 28px; }
.art .r.row { gap: 1px; background: var(--bx-enabled); }
.art .r.row .c { background: var(--nb, var(--ui-main-dark)); color: var(--tx-light); }
/* a text too long for its cell is cut inside the cell, and 1px short of its
   right edge: the cell carries a 1px edge in its own colour, and overflow is
   clipped inside that edge, so the 1px gap to the next cell stays clean */
.art .r.row .c, .lst.art .hd .c { overflow: hidden; }
.art .r.row .c:not(.name) { border-right: 1px solid var(--nb, var(--ui-main-dark)); }
.art .r.row .c.name { flex: 1 0 0; min-width: 0; padding: 0; color: var(--tx-standard); }
.art .grp { display: flex; gap: 1px; background: var(--bx-enabled); }
.art .sp { width: 28px; display: flex; align-items: center; justify-content: center; flex: none; }
.art .gap7 { width: 7px; flex: none; }
.art .dt { display: flex; align-items: center; gap: 10px; }
/* the disabled language reads white in the rows */
.art .ui-ico.s28.is-disabled > .plate > b { color: var(--tx-light); }
.art .ui-ico.s28 > .plate > svg { display: block; }
.art .r.file { --nb: var(--ui-bg); }
.art .r.picked { background: var(--bx-disabled); --nb: var(--bx-enabled); }
.art .r.blank .c, .art .r.blank .c.name { color: var(--bx-stroke-hover); }
/* a group's name, and the Name of what is selected, read --tx/light */
.art .r.row[data-variant^="GROUP"] .c.name, .art .r.row.picked .c.name { color: var(--tx-light); }
/* ...but a group with no files yet (the plan's, all blank) stays --tx/standard */
.art .r.row.blank[data-variant^="GROUP"]:not(.picked) .c.name { color: var(--tx-standard); }
.art .r.blank .ic { opacity: .5; }
/* The SELECTED and HOVER rings sit over the row, 589 wide: solid --hl/blue
   when picked, dashed --hl/arrow under the pointer. */
.art .r.picked::after, .art .r.hover::after {
  content: ""; position: absolute; left: 0; top: 0; width: 589px; height: 28px;
  box-sizing: border-box; border: 1px solid var(--hl-blue); pointer-events: none;
  z-index: 5; }   /* over a hovered button (.ui-ico:hover is 4), not under it */
.art .r.hover::after { border: 1px dashed var(--hl-arrow); }
/* SET (505:66587) and SET - HOVER (533:90541): a line's header, 28 high, three
   --bx/enabled cells 1px apart on --ui/black. LEFT 28 the lib-group glyph,
   CENTER the Ready count, the name, the Approved count, CLOSE 28 the arrow.
   Hovered (.hv draws it still) the glyph turns blue. */
.art .r.set { display: flex; align-items: stretch; gap: 1px; height: 28px; padding: 0;
              box-sizing: border-box; background: var(--ui-black); }
.art .r.set .lft, .art .r.set .cls { flex: 0 0 28px; display: flex; align-items: center;
              justify-content: center; background: var(--bx-enabled); }
.art .r.set .ctr { flex: 1 1 0; min-width: 0; display: flex; align-items: center;
              justify-content: space-between; gap: 10px; padding: 0 10px; background: var(--bx-enabled); }
.art .r.set .nm { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: clip;
              font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light); }
.art .r.set .cnt { flex: none; display: flex; align-items: center; gap: 8px;
              font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; white-space: nowrap; }   /* 8 in the file, 10 by Adi's call: 8 did not read */
.art .r.set .cnt b { font-weight: 600; color: var(--tx-dark); }
.art .r.set .cnt i { font-style: normal; color: var(--tx-light); }
.art .r.set .cnt .l { width: 1px; height: 12px; background: var(--bx-stroke); }
.art .r.set .sg2 { display: flex; }
.art .r.set .sg2 svg { display: block; }
.art .r.set .sg2 .h,
.art .r.set:hover .lft .sg2 .n, .art .r.set.hv .lft .sg2 .n, .art .r.set .cls:hover .sg2 .n { display: none; }
.art .r.set:hover .lft .sg2 .h, .art .r.set.hv .lft .sg2 .h, .art .r.set .cls:hover .sg2 .h { display: block; }
/* the arrow is the popup's (arrow-down); folded it turns to point right, as
   the popup's section arrow does */
.art .r.set .cls .sg2 { transition: transform .2s ease; }
.art .r.set.folded .cls .sg2 { transform: rotate(-90deg); }
/* SPACER (505:42720) */
.art .r.spacer { height: 5px; background: var(--ui-main-dark); }

/* OPTION 30 px - SIMPLE (384:56913): the Disabled field with a quiet number,
   10px SemiBold in --tx/standard instead of the 12px blue. */
.opt.is-simple .num { font: 600 10px/1 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
                      color: var(--tx-standard); }

/* ==========================================================================
   PANELS: ARTBOARDS (396:33286) and LIBRARY (395:51285)
   The PANEL TAB over a --ui/main body, 12 in and 12 apart, assembled from
   the OPTION field, the 28px button and the two lists above.
   ========================================================================== */
.p-list { display: flex; flex-direction: column; background: var(--ui-main); flex: none; }
.p-list.p-art { width: 637px; }
.p-list.p-lib { width: 559px; height: 817px; }
.p-list > .body { display: flex; flex-direction: column; gap: 12px; padding: 12px;
                  box-sizing: border-box; flex: 1 0 0; min-height: 0; }
.p-list.p-art > .body { flex: none; }
.p-list .bar { display: flex; gap: 12px; align-items: flex-start; flex: none; }
.p-list .bar.ends { justify-content: space-between; gap: 0; }
.p-list .bar.g6 { gap: 6px; }
/* SEARCH (395:47583, Adi 2026-10-18): ONE box - a --bx/enabled frame and
   well, Search and Replace with two --bx/disabled cells 1 apart, the 28
   play button closing it */
.p-list .bar.srch { gap: 1px; align-items: center; height: 30px; box-sizing: border-box;
                    background: var(--bx-enabled); border: 1px solid var(--bx-enabled); }
.p-list .bar.srch > .c { flex: 1 0 0; min-width: 0; height: 28px; box-sizing: border-box;
                         padding: 4px 8px; display: flex; align-items: center; background: var(--bx-disabled);
                         font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
                         color: var(--tx-standard); white-space: nowrap; overflow: hidden; }
.p-list .bar.srch > .ui-ico { flex: none; }
/* the bottom bar's LEFT and RIGHT (571:140478 / 571:141025), the groups 10
   apart. Not 200 wide each (Adi 2026-10-18: the fixed sides stopped the panel
   narrowing): three columns, the outer two sharing what is left equally, so
   COMPRESS stays in the middle at any width and each side keeps its content */
/* (2026-10-19) each column at least its content: narrowed, the groups close
   up to their own width and stop there instead of sliding over each other */
.p-list .bar.ends:has(> .bar.side) { display: grid; align-items: start;
  grid-template-columns: minmax(max-content, 1fr) max-content minmax(max-content, 1fr); }
.p-list .bar.ends > .bar.side { gap: 10px; }
.p-list .bar.ends > .bar.side.r { justify-content: flex-end; }

/* The OPTION field without its NAME cell: dropdowns, search boxes and the
   text field. 30 tall, the ARTBOARDS nav included. */
.p-list .opt.fld { width: auto; flex: 1 0 0; min-width: 0; }
/* h32 is 30 like every other field (Adi, 2026-10-18): campaign and subject
   sat at two heights in one bar */
.p-list .opt.fld.h32 { height: 30px; }
.p-list .opt.fld.w150 { flex: none; width: 150px; }
.p-list .opt.fld .txt { flex: 1 0 0; min-width: 0; overflow: hidden; }
/* Stacked straight in the body, a field keeps its height and takes the width. */
.p-list > .body > .opt.fld { flex: none; }
/* A DROPDOWN here answers the pointer as one in the Text panel does (Adi,
   2026-10-17: the campaign and subject fields stayed flat): the frame to
   --bx/stroke-hover, the value to --bx/enabled. Only a field holding a
   select - the search and remove-words boxes keep their own look. */
.p-list .opt.fld:has(select) { cursor: var(--adi-pointer), default; }
.p-list .opt.fld:has(select):not(.is-enabled):hover { background: var(--bx-stroke-hover);
                                                     border-color: var(--bx-stroke-hover); }
.p-list .opt.fld:has(select):not(.is-enabled):hover .value { background: var(--bx-enabled); border-color: var(--bx-enabled); }
.p-list .browser > .well { overflow: hidden; }

/* A group of 28px buttons: a --bx/stroke frame round a --bx/enabled strip,
   the buttons 1 apart. */
.p-list .bgrp { border: 1px solid var(--bx-stroke); flex: none; display: flex; }
.p-list .bgrp > .in { display: flex; align-items: center; gap: 1px; height: 30px;
                      box-sizing: border-box; background: var(--bx-enabled);
                      border: 1px solid var(--bx-enabled); }
.p-list .bgrp.pl1 { padding-left: 1px; }
/* The label cell in front of the compress buttons (395:54841). */
.p-list .bgrp .lbl { height: 28px; box-sizing: border-box; padding: 4px 8px;
                     display: flex; align-items: center; background: var(--bx-disabled);
                     font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
                     color: var(--tx-standard); }
.p-list .ui-ico > .plate > svg { display: block; }
/* The ALIGN set's 18px glyphs carry a 1px drop shadow in the file. */
.p-list .ui-ico svg.sh { filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, .25)); }

/* ---- the BROWSER: --bx/stroke frame, then a --bx/disabled well ---------- */
.p-list .browser { border: 1px solid var(--bx-stroke); flex: none; }
.p-list .browser > .well { background: var(--bx-disabled); border: 1px solid var(--bx-enabled); }
.p-art .browser .lst.art { width: 589px; gap: 1px; background: var(--bx-enabled); }
/* A group of rows that belong together (IN PROGRESS, APPROVED) - the same 1
   between them, and the parent for the APPROVED ring. */
.lst .frm { display: flex; flex-direction: column; gap: 1px; position: relative; }
/* The ring round the files of an approved group (505:49863): left, right and
   bottom in --hl/arrow, open at the top where the group row sits. */
.lst .frm > .ring { position: absolute; left: 0; top: 28px; width: 589px; height: 116px;
                    box-sizing: border-box; border: 1px solid var(--hl-arrow);
                    border-top: 0; pointer-events: none; }
.art .r.fill { height: 28px; background: var(--bx-disabled); }

.p-lib .browser { flex: 1 0 0; min-height: 0; display: flex; }
.p-lib .browser > .well { flex: 1 0 0; min-width: 0; }
.p-lib .browser .lst.lib { width: auto; gap: 1px; background: var(--ui-main-dark);
                           border-bottom: 1px solid var(--ui-main-dark); }

/* ---- the LIBRARY preview (PREVIEW in 395:51285) -------------------------- */
.p-list .pv { border: 1px solid var(--bx-stroke); flex: none; }
.p-list .pv > .fld { height: 172px; box-sizing: border-box; display: flex;
                     background: var(--bx-disabled); border: 1px solid var(--bx-enabled); }
.pv .prev { flex: 1 0 0; min-width: 0; display: flex; flex-direction: column; }
.pv .safe { flex: 1 0 0; border-bottom: 1px solid var(--bx-stroke); }
.pv .chips { display: flex; gap: 4px; padding: 4px; }
.pv .chips > span { height: 20px; box-sizing: border-box; padding: 4px 6px;
                    background: var(--bx-enabled); border: 1px solid var(--bx-stroke-light);
                    font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
                    color: var(--tx-standard); white-space: nowrap; }
.pv .progress { height: 25px; display: flex; align-items: flex-end; }
/* The two strips along the bottom have a literal black top edge in the file. */
.pv .time { width: 70px; height: 25px; box-sizing: border-box; flex: none;
            display: flex; align-items: center; gap: 4px; padding: 0 8px;
            background: var(--bx-enabled); border-top: 1px solid #000;
            font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif;
            color: var(--tx-standard); white-space: nowrap; }
.pv .time i { font-style: normal; color: var(--bx-stroke); }
.pv .wave { flex: 1 0 0; height: 25px; box-sizing: border-box; position: relative;
            overflow: hidden; background: var(--bx-enabled); border-top: 1px solid #000; }
.pv .wave img { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; }
.pv .wave .cue { position: absolute; left: 83px; top: 0; width: 1px; height: 24px;
                  background: var(--hl-blue); }
.pv .vol { width: 18px; flex: none; box-sizing: border-box; border-left: 1px solid var(--bx-enabled);
           display: flex; flex-direction: column; gap: 1px; }
.pv .vol .spk { height: 17px; flex: none; position: relative; background: var(--bx-stroke); }
.pv .vol .spk img { position: absolute; left: 4px; top: 4.8px; }
.pv .vol .trk { flex: 1 0 0; background: var(--bx-stroke); }
.pv .vol .fil { height: 49px; flex: none; background: var(--tm-empty); }

/* ==========================================================================
   ARTBOARDS, SECOND LAYOUT (396:33286): a selection strip left of the list
   and a scrollbar right of it, filters above, search below.
   GEOMETRY from the node (browser 613 x 678: 1 + 10 + 591 + 10 + 1, list
   viewport 676 tall; strip cells 9 wide, 1 in from the left, on the rows'
   own tops; thumb 7 wide, 1 in and 2 down). The COLOURS of the strip and the
   bar are borrowed from the timeline scrollbar (.tl-scroll-r) - the CSS of
   this node was not available, so check them against the file.
   ========================================================================== */
.p-art .browser.v2 { display: flex; height: 678px; box-sizing: border-box; background: var(--bx-enabled); }
/* the viewport sits 1 in from the top and the bottom, so the browser's own
   --bx/enabled shows there as the list's edge and STAYS when the list is
   scrolled (it was the well's border, and scrolled away with the rows) */
.p-art .browser.v2 > .vp { flex: 1 0 0; display: flex; align-items: flex-start; overflow-y: auto;
                           scrollbar-width: none; height: 674px; margin: 1px 0; }
.p-art .browser.v2 > .vp::-webkit-scrollbar { display: none; }
/* SCROLL 506:70395 (the selection strip), from the file: 10 wide, a
   --bx/enabled edge on three sides (none on the right, where the list's own
   edge is), --bx/enabled behind, so the 1px between cells reads as a rule.
   Stretched to the list, so it scrolls with it at any length. The cells sit
   on the rows' own tops (set by the script), 9 wide inside the edge. */
.p-art .browser.v2 .selcol { position: relative; flex: none; align-self: stretch; width: 10px;
                             box-sizing: border-box; background: var(--bx-enabled);
                             border-left: 1px solid var(--bx-enabled); }
/* a cell (FILL), from the file: --bx/disabled. No hover state; a picked row
   turns its cell --hl/blue, and that is the only change. */
.p-art .browser.v2 .selcol > i { position: absolute; left: 0; width: 9px; background: var(--bx-disabled);
                                 cursor: var(--adi-pointer), default; }
.p-art .browser.v2 .selcol > i.on { background: var(--hl-blue); }
/* the NAV row's cell takes the NAV's own colour; it cannot be picked */
.p-art .browser.v2 .selcol > i:first-child { background: var(--ui-main); cursor: default; }
.p-art .browser.v2 > .vp > .well { flex: none; }
.p-art .browser.v2 .lst.art { position: relative; }
/* SCROLL 506:70390, from the file: 10 wide, 1 of padding, a --bx/enabled
   edge on three sides (none on the left, where the list's own edge is) and
   --ui/main-dark inside. The thumb is what is left: 7 wide, 1 in, 2 down. */
.p-art .browser.v2 > .scr { position: relative; flex: none; align-self: stretch; width: 10px; padding: 1px;
                            box-sizing: border-box; background: var(--ui-main-dark);
                            border-top: 1px solid var(--bx-enabled); border-right: 1px solid var(--bx-enabled);
                            border-bottom: 1px solid var(--bx-enabled); }
/* the thumb (506:70392), from the file: 150 tall, the strip's full inner
   width, --bx/stroke-light with a --bx/stroke-hover edge */
.p-art .browser.v2 > .scr > i { position: absolute; left: 1px; top: 1px; width: 7px; height: 150px;
                                box-sizing: border-box; border: 1px solid var(--bx-stroke-hover);
                                background: var(--bx-stroke-light); cursor: var(--adi-pointer), default; }
.p-art .browser.v2 > .scr > i[hidden] { display: none; }
/* held: --hl/blue, its inner stroke --hl/blue-light. LIVE is the same colour
   while the list is wheeled. It comes up as the panel's rollover does (.15s
   ease) and goes out slower, so the bar seems to breathe out after a scroll. */
/* out over .9s from 40ms after the last move (app.js SB_HOLD / SB_FADE), as
   every native bar now does - Adi: .2s after 150ms began too late, ended too soon */
.p-art .browser.v2 > .scr > i { transition: background-color .9s cubic-bezier(.3, 0, .2, 1), border-color .9s cubic-bezier(.3, 0, .2, 1); }
.p-art .browser.v2 > .scr > i.drag,
.p-art .browser.v2 > .scr > i.live { background: var(--hl-blue); border-color: var(--hl-blue-light);
                                     transition-duration: .1s; }
/* the two right-hand groups of a bar sit 12 apart, like the file's */
.p-list .bar > .bar { gap: 12px; }
/* the list's well, now inside the scrolling viewport: the same --bx/disabled
   ground and --bx/enabled edge as before, and the full 676 even when short */
.p-art .browser.v2 .well { box-sizing: border-box; min-height: 674px;
                           background: var(--bx-disabled); border: 1px solid var(--bx-enabled); border-width: 0 1px; }

/* ARTBOARDS, the LIST view (grid-list): Name and Format only. Subject is the
   second cell of every row and of the header; Language and Action are the
   w115 and w57 cells. The name cell takes the room they leave. */
.lst.art.compact .r.row > :nth-child(2), .lst.art.compact .r.hd > :nth-child(2),
.lst.art.compact .r > .w115, .lst.art.compact .r > .w57 { display: none; }
/* the view pair's buttons sit in spans so a click can tell them apart */
.p-list .bgrp.views [data-view] { display: flex; }
/* a button with its own hover drawing (nav zoom-in / zoom-out): the drawing
   is swapped, as the files are drawn - not recoloured */
.ui-ico.zm .zr, .ui-ico.zm .zh { display: flex; }
.ui-ico.zm .zh, .ui-ico.zm:hover .zr { display: none; }
.ui-ico.zm:hover .zh { display: flex; }

/* ---- COLUMN WIDTHS (LISTS.resizable): the app's LIBRARY handle ----
   2px of paint on the column's left edge, 5px of slack either side, blue
   under the pointer and while held. */
.lst .hd .c.cwc { position: relative; }
.lst .hd .cw { position: absolute; top: 0; bottom: 0; left: -1px; width: 2px; cursor: var(--cur-panel-horizontal), ew-resize; z-index: 4; }
.lst .hd .cw::after { content: ''; position: absolute; top: 0; bottom: 0; left: -5px; right: -5px; }
.lst .hd .cw:hover, .lst .hd .cw.on { background: var(--hl-blue); }
body.cw-resizing { cursor: var(--cur-panel-horizontal), ew-resize; user-select: none; }

/* ==========================================================================
   ARTBOARD SETTINGS (POPUP 509:50834)
   Three frames: --hl/icon 1px with the 4/4/10 shadow, --hl/arrow 2px, and a
   --bx/enabled 1px edge round NAV and LIST. NAV is --bx/disabled; each
   section opens with an OPTION head in --ui/main-light; rows (CAT) sit on
   --ui/main between 2px rules (--bx/stroke-light over --bx/disabled).
   ========================================================================== */
.p-aset { align-self: flex-start; }
.as-pop { border: 1px solid var(--hl-icon); box-shadow: 4px 4px 10px 0 rgba(0, 0, 0, .5); width: max-content; }
.as-in { border: 2px solid var(--hl-arrow); }
.as-act { border: 1px solid var(--bx-enabled); }
/* NAV (509:49465): the title 12 in; at the right a seam and the X in a
   40x40 cell on --ui/bg. X - HOVER (532:78767): the cell --ui/black, the
   glyph --hl/blue (its -hover twin). */
.as-nav { display: flex; align-items: center; justify-content: space-between; height: 40px; box-sizing: border-box;
          padding-left: 12px; background: var(--bx-disabled); }
.as-nav > b, .as-opt > b { font: 700 14px/normal 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light); }
.as-xg { display: flex; align-self: stretch; background: var(--ui-bg); }
.as-x { display: flex; align-items: center; justify-content: center; width: 40px; cursor: var(--adi-pointer), default; }
.as-x:hover { background: var(--ui-black); }
/* a glyph and its -hover twin: the twin shows under the pointer */
.as-g { display: flex; }
.as-g svg { display: block; }
.as-g > svg + svg,
.as-x:hover .as-g > svg:first-child, .as-opt:hover .as-chev .as-g > svg:first-child { display: none; }
.as-x:hover .as-g > svg + svg, .as-opt:hover .as-chev .as-g > svg + svg { display: block; }
/* the 2px seam: --bx/stroke then --bx/enabled; in an OPTION head
   --bx/stroke-light then --ui/main-dark */
.as-sep { display: block; flex: none; align-self: stretch; width: 2px;
          background: linear-gradient(90deg, var(--bx-stroke) 0 1px, var(--bx-enabled) 1px 2px); }
.as-opt .as-sep { background: linear-gradient(90deg, var(--bx-stroke-light) 0 1px, var(--ui-main-dark) 1px 2px); }
.as-r { display: flex; align-items: center; }
.as-list { width: 1141px; background: var(--ui-main); }
/* OPTION (509:49468): the title 12 in; at the right [seam, GROUP FILES 14
   each side], seam, the arrow in a 40 cell. HOVER (532:78888): the arrow
   --hl/blue. */
.as-opt { display: flex; align-items: center; justify-content: space-between; height: 40px; box-sizing: border-box;
          padding-left: 12px; background: var(--ui-main-light); cursor: var(--adi-pointer), default; }
.as-opt .as-r { align-self: stretch; }
.as-chev { display: flex; align-items: center; justify-content: center; width: 40px; }
/* the foot (532:65035): three how-to cells, 20 in, the cursor 10 from its
   words, a seam after each; then RESET DEFAULTS and SAVE share what is left.
   HOVER (532:79037): RESET --tx/light; SAVE --ui/black with --hl/blue words. */
.as-foot { display: flex; height: 50px; background: var(--bx-disabled); }
.as-tip { display: flex; align-items: center; gap: 10px; padding: 0 20px; flex: none; white-space: nowrap;
          font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light); }
.as-tip svg { display: block; }
.as-btns { display: flex; flex: 1 0 0; min-width: 0; }
.as-btn { display: flex; align-items: center; justify-content: center; flex: 1 0 0; min-width: 0; padding: 4px 6px;
          font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-dark);
          white-space: nowrap; cursor: var(--adi-pointer), default; user-select: none; }
.as-btn:hover { color: var(--tx-light); }
.as-btn.as-save { background: var(--ui-bg); color: var(--ui-white); }
.as-btn.as-save:hover { background: var(--ui-black); color: var(--hl-blue); }
.as-l { display: block; height: 2px; background: linear-gradient(var(--bx-stroke-light) 0 1px, var(--bx-disabled) 1px 2px); }
/* CAT: the items on the left, the row's own grip at the right end */
.as-cat { display: flex; align-items: flex-start; justify-content: space-between; padding: 10px; }
.as-cat.p12 { padding: 12px; }
.as-main { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.as-main .ui-grip:first-child { cursor: var(--cur-move), move; }
.as-cat > .ui-grip { cursor: default; }
/* a chip: --ui/main-light, a --bx/stroke-light edge, the SHADOW drop (1/1, 0 blur, 25%) */
.as-chip { display: flex; align-items: center; gap: 10px; box-sizing: border-box; padding: 4px 10px 4px 6px;
           background: var(--ui-main-light); border: 1px solid var(--bx-stroke-light);
           filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, .25));
           font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light);
           white-space: nowrap; cursor: var(--adi-pointer), default; user-select: none; }
.as-chip.main { width: 110px; padding: 4px 6px; }
.as-chip.add { position: relative; border-color: var(--hl-blue); }
/* open, it sits over the rows below (each chip is its own layer - the drop
   shadow filter - so without this the next row's chips cover the box) */
.as-chip.add.open { z-index: 30; }
/* NEW - HOVER, and while its box is open (533:80927): the chip --hl/blue,
   the checkbox rings --hl/blue-light over --ui/black */
.as-chip.add:hover, .as-chip.add.open { background: var(--hl-blue); border-color: var(--hl-blue); }
.as-chip.add:hover:not(.no-hov) .ui-cb.is-new > span, .as-chip.add.open .ui-cb.is-new > span { border-color: var(--hl-blue-light); }
.as-chip.add:hover:not(.no-hov) .ui-cb.is-new > span > span, .as-chip.add.open .ui-cb.is-new > span > span { border-color: var(--ui-black); }
/* the box under it, 130 wide on the chip's bottom edge: a --ui/main-light
   head, a --bx/stroke-light rule, then the field (--ui/main-dark on a
   --bx/disabled edge, the hint 8px --tx/dark), a seam and OK on --ui/bg */
.as-newpop { position: absolute; left: -1px; top: 28px; z-index: 20; width: 130px; box-sizing: border-box;
             display: flex; flex-direction: column; background: var(--ui-main); border: 1px solid var(--hl-blue);
             filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, .25)) drop-shadow(4px 4px 2px rgba(0, 0, 0, .25)); cursor: default; }
.as-newpop .hl { display: flex; align-items: center; height: 30px; padding: 0 10px; background: var(--ui-main-light);
                 font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light); }
.as-newpop .ln { display: block; height: 1px; background: var(--bx-stroke-light); }
.as-newpop .rw { display: flex; height: 30px; }
.as-newpop .in { flex: 1 0 0; min-width: 0; box-sizing: border-box; margin: 0; padding: 4px 6px; outline: 0;
                 background: var(--ui-main-dark); border: 1px solid var(--bx-disabled); text-align: center;
                 font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light);
                 text-transform: uppercase; cursor: text; }
.as-newpop .in::placeholder { font: 600 8px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-dark);
                              text-transform: none; }
.as-newpop .ok { display: flex; align-items: center; justify-content: center; width: 30px; flex: none; background: var(--ui-bg);
                 font: 600 10px/1 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--ui-white);
                 cursor: var(--adi-pointer), default; }
/* GROUP FILES: the switch and its label, 10 apart */
.as-tg { display: flex; align-items: center; gap: 10px; padding: 0 14px; cursor: var(--adi-pointer), default;
         font: 600 10px/10px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-light); }
/* moving: the chip being dragged, and where it would land */
.as-chip.dragging, .as-cat.dragging { opacity: .4; }
.as-chip.drop-a { box-shadow: -3px 0 0 var(--hl-blue); }
.as-chip.drop-b { box-shadow: 3px 0 0 var(--hl-blue); }
.as-cat.drop-a { box-shadow: inset 0 2px 0 var(--hl-blue); }
.as-cat.drop-b { box-shadow: inset 0 -2px 0 var(--hl-blue); }
/* hover lights the checkbox - not straight after a click that switched it
   off (.no-hov, until the pointer leaves and comes back) */
.as-chip:hover:not(.no-hov) .ui-cb.is-off > span { border-color: var(--hl-blue-dark); }
.as-chip:hover:not(.no-hov) .ui-cb.is-off b { color: var(--hl-blue); }
.as-chip:hover:not(.no-hov) .ui-cb:not(.is-off) > span { border-color: var(--hl-blue-dark); }
.as-chip:hover:not(.no-hov) .ui-cb:not(.is-off) b { background: var(--bx-enabled); }

/* ==========================================================================
   CHECKBOX (509:46150) - 20px: a --bx/stroke-light ring, a --bx/enabled ring,
   the 16px BOX with the tick drawn pixel by pixel in --hl/blue-light.
     ENABLED - HOVER   rings --hl/blue-dark, box --bx/enabled
     DISABLED          inner ring --ui/bg, box --ui/main-dark, tick --bx/stroke
     DISABLED - HOVER  outer ring --hl/blue-dark, tick --hl/blue
     NEW (Variant6)    the plus on --bx/enabled; NEW - HOVER rings --hl/blue-dark
   markup: <span class="ui-cb [is-off] [is-new] [is-hover]"><span><span><b>svg</b></span></span></span>
   ========================================================================== */
.ui-cb { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex: none;
         --cb-t: .3s; }
/* THE CHANGES ARE TWEENED: an empty box lights up slowly under the pointer
   (.3s), a ticked one quickly (.12s), and a click is quick too (.snap, set for
   the moment of the click). */
.ui-cb:not(.is-off), .ui-cb.snap { --cb-t: .12s; }
.ui-cb > span { display: flex; border: 1px solid var(--bx-stroke-light); transition: border-color var(--cb-t) ease; }
.ui-cb > span > span { display: flex; border: 1px solid var(--bx-enabled); transition: border-color var(--cb-t) ease; }
.ui-cb b { display: flex; align-items: center; justify-content: center; width: 16px; height: 16px;
           background: var(--bx-disabled); color: var(--hl-blue-light);
           transition: background-color var(--cb-t) ease, color var(--cb-t) ease; }
.ui-cb svg rect { transition: fill var(--cb-t) ease; }
.ui-cb svg { display: block; fill: currentColor; }
.ui-cb.is-hover > span { border-color: var(--hl-blue-dark); }
.ui-cb.is-hover b { background: var(--bx-enabled); }
.ui-cb.is-off > span > span { border-color: var(--ui-bg); }
.ui-cb.is-off b { background: var(--ui-main-dark); color: var(--bx-stroke); }
.ui-cb.is-off.is-hover b { background: var(--ui-main-dark); color: var(--hl-blue); }
.ui-cb.is-new b { background: var(--bx-enabled); }
/* TICK DRAW (UIC.tick): each 1px piece grows in from nothing, 28ms after the
   column to its left, and the box gives a small press - about a quarter of
   a second for the whole tick */
@keyframes cbDraw { from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: none; } }
@keyframes cbPress { 0% { transform: scale(1); } 40% { transform: scale(.88); } 100% { transform: scale(1); } }
.ui-cb.cb-draw svg rect { transform-box: fill-box; transform-origin: 50% 50%;
                          animation: cbDraw 180ms cubic-bezier(.2, .7, .2, 1) both;
                          animation-delay: calc(var(--d, 0) * 28ms); }
.ui-cb.cb-draw b { animation: cbPress 220ms ease both; }

/* ==========================================================================
   TOOGLE (530:61780) - 26x14, round, a --bx/stroke-light edge.
     DISABLED  --ui/bg with 1px each side, the track --ui/black, the knob at
               the left: --hl/blue-dark with a --hl/blue edge
     ENABLED   --hl/blue, the track --hl/blue with a --ui/black edge, the knob
               at the right: white with a --hl/blue-dark edge
     HOVER     (2026-10-17) DISABLED with the knob filled --hl/blue
   The track fills the whole box (Adi's fix, 2026-10-17: it used to sit 1px
   in from each side, showing --ui/bg around it); off, the knob sits 1px in
   from the left of it. The knob slides and the colours fade in the 220ms
   of every other control.
   ========================================================================== */
.ui-tgl { display: flex; align-items: center; width: 26px; height: 14px; box-sizing: border-box; flex: none;
          padding: 0; border: 1px solid var(--bx-stroke-light); border-radius: 50px; background: var(--ui-bg);
          cursor: var(--adi-pointer), default; transition: background-color 220ms ease; }
.ui-tgl > b { position: relative; flex: 1 0 0; height: 100%; box-sizing: border-box; border-radius: 10px;
              border: 0 solid var(--ui-black); background: var(--ui-black);
              transition: background-color 220ms ease, border-width 220ms ease, border-radius 220ms ease; }
.ui-tgl > b > i { position: absolute; top: 50%; left: 1px; width: 10px; height: 10px; box-sizing: border-box;
                  margin-top: -5px; border-radius: 50%; border: 1px solid var(--hl-blue); background: var(--hl-blue-dark);
                  transition: left 220ms ease, background-color 220ms ease, border-color 220ms ease; }
.ui-tgl:not(.is-on):hover > b > i,
.ui-tgl.is-hover:not(.is-on) > b > i { background: var(--hl-blue); border-color: var(--hl-blue); }
.ui-tgl.is-on { background: var(--hl-blue); }
.ui-tgl.is-on > b { border-width: 1px; border-radius: 50px; background: var(--hl-blue); }
.ui-tgl.is-on > b > i { left: calc(100% - 10px); background: var(--ui-white); border-color: var(--hl-blue-dark); }

/* ==========================================================================
   DROPDOWN (559:177195, 2026-10-17) - the list an OPTION with a <select>
   opens (ui-controls.js draws it in a fixed .sg-panel.dd-host under the field).
     the field   ENABLED: --bx/enabled under a --hl/blue edge, the text and
                 the arrow --hl/blue
     the list    the field's width: a --bx/stroke box with a --ui/black edge,
                 inside it --ui/bg in a --hl/blue edge, rows 1px apart
     a row       28 tall, 8 in, UI - NUMBERS (Bold 12/12) in --tx/light, on
                 --ui/black; CHOSEN --hl/blue; HOVER a 4px --hl/blue edge on
                 the left, which pushes the word 4px in
   It drops in and its rows follow one by one, as the menu bar's lists do.
   ========================================================================== */
.opt.is-open .num, .opt.is-open .val-text { color: var(--hl-blue); }
.dd { box-sizing: border-box; width: 100%; background: var(--bx-stroke); border: 1px solid var(--ui-black);
      animation: ddDrop 220ms cubic-bezier(.2, .7, .2, 1) both; }
/* the states sit on .dd, not on the host: in the app this file is wrapped in
   @scope (.sg-panel) and the host IS that root, so a selector that starts at
   the host never matches */
.dd.up { animation-name: ddRise; }
/* the font list: Ctrl + wheel sets the preview size (--ff, 10-48px); the row
   grows with it (Adi, 2026-10-17) */
.dd.dd-font .dd-r { height: auto; min-height: 28px; padding-top: 4px; padding-bottom: 4px; }
.dd.dd-font .dd-r > b { font-size: var(--ff, 12px); line-height: 1.25; }
/* refiltered while you type (the font list): it is already open, so no drop-in */
.dd.is-live, .dd.is-live .dd-r { animation: none; }
.dd-v { display: flex; flex-direction: column; gap: 1px; background: var(--ui-bg);
        border: 1px solid var(--hl-blue); max-height: 320px; overflow-y: auto; }
.dd-r { position: relative; flex: none; height: 28px; box-sizing: border-box; padding: 0 8px;
        display: flex; align-items: center; background: var(--ui-black);
        cursor: var(--adi-pointer), default;
        animation: ddIn 200ms cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(var(--n, 0) * 18ms);
        transition: background-color 220ms ease, padding-left 220ms cubic-bezier(.2, .7, .2, 1); }
/* a row at rest reads --tx/standard; chosen or under the pointer, --tx/light
   (Adi, 2026-10-17) */
.dd-r > b { font: 700 12px/12px 'Chakra Petch', 'Segoe UI', system-ui, sans-serif; color: var(--tx-standard);
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
            transition: color 220ms ease; }
.dd-r.is-sel > b, .dd-r:not(.is-off):hover > b, .dd-r.is-cur > b { color: var(--tx-light); }
/* the hover edge: 4px of --hl/blue, grown from the middle of the row
   (tried from the top-left corner, 2026-10-17 - the middle reads better) */
.dd-r::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--hl-blue);
                transform: scaleY(0); transform-origin: 50% 50%; transition: transform 220ms cubic-bezier(.2, .7, .2, 1); }
.dd-r:not(.is-sel):not(.is-off):hover { padding-left: 12px; }
.dd-r:not(.is-sel):not(.is-off):hover::before { transform: scaleY(1); }
/* the row the arrow keys are on (font list) looks like the hovered one */
.dd-r.is-cur:not(.is-sel) { padding-left: 12px; }
.dd-r.is-cur:not(.is-sel)::before { transform: scaleY(1); }
.dd-r.is-sel { background: var(--hl-blue); }
.dd-r.is-off { cursor: default; }
/* a GROUP HEADING (a select's <optgroup>: Source, a client's name) - not in
   559:177195; my placeholder until it is drawn: 22 tall, UI - TAB in
   --tx/dark on --ui/bg, not pickable (2026-10-17) */
.dd-g { flex: none; height: 22px; box-sizing: border-box; padding: 0 8px; display: flex; align-items: center;
        background: var(--ui-bg); cursor: default;
        animation: ddIn 200ms cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(var(--n, 0) * 18ms); }
.dd-g > b { font: var(--ui-tab); color: var(--tx-dark); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
            text-transform: uppercase; }
.dd.is-live .dd-g { animation: none; }
.dd-r.is-off > b { color: var(--tx-dark); }
@keyframes ddDrop { from { opacity: 0; transform: translateY(-8px); clip-path: inset(0 0 100% 0); }
                    to   { opacity: 1; transform: none; clip-path: inset(-20px); } }
@keyframes ddRise { from { opacity: 0; transform: translateY(8px); clip-path: inset(100% 0 0 0); }
                    to   { opacity: 1; transform: none; clip-path: inset(-20px); } }
@keyframes ddIn   { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* SPACER (526:41330) - the grip: five pairs of 2px dots, each over a --ui/bg
   shadow, 7x30; HORIZONTAL (530:61819) the same turned, 30x7. */
.ui-grip { display: block; flex: none; }
.ui-grip > svg { display: block; }
.ui-grip .s { fill: var(--ui-bg); }
.ui-grip .d { fill: var(--bx-stroke-light); }

/* ITEM (541:82785) - a menu row, 242x30: the label 20 in, at the right either
   the shortcut keys or the arrow of an item that opens further.
     ITEM / EXPAND           --ui/bg, label --tx/light, arrow --hl/arrow
     ITEM - HOVER / EXPAND - Hover
                             --ui/black, a 2px --hl/blue edge on the left,
                             label and arrow --hl/blue, the keys on --ui/bg
     EXPAND - Enabled        --hl/blue with a 1px edge of the same, label and
                             arrow white
   The arrow is arrows/arrow-down turned -90, as the file turns it. The sprite
   has a grey and a blue one but no white, so ENABLED whitens the grey one. */
.mi { display: flex; flex-direction: column; width: 242px; flex: none; }
.mi > .r { position: relative; isolation: isolate; height: 30px; box-sizing: border-box; padding: 0 10px 0 20px;
           display: flex; align-items: center; justify-content: space-between; gap: 24px;
           /* the hover gradient starts 12px left of the row and slides in:
              clipped here, or it shows as a black block beside the list */
           overflow: hidden;
           background: var(--ui-bg); filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, .25));
           cursor: var(--adi-pointer), default;
           transition: background-color 180ms ease; }
/* The label: SemiBold 12, the type of File and Edit on the bar (Adi,
   2026-10-15 - the file has Bold). It never moves: the blue edge is drawn
   OVER the row (::before), not as a border that would push the word 1-2px. */
.mi > .r > b { font: 600 12px/normal 'Chakra Petch', sans-serif; color: var(--tx-light); white-space: nowrap;
               transition: color 180ms ease; }
/* the edge, 2px of --hl/blue, grows from the middle of the row */
.mi > .r::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
                   background: var(--hl-blue); transform: scaleY(0); transform-origin: 50% 50%;
                   transition: transform 220ms cubic-bezier(.2, .7, .2, 1); }
/* a darker gradient slides in from the left over the row's colour */
.mi > .r::after { content: ''; position: absolute; inset: 0; z-index: -1;
                  background: linear-gradient(to right, var(--ui-black) 0%, var(--ui-black) 45%, rgba(17, 17, 17, .6) 100%);
                  opacity: 0; transform: translateX(-12px);
                  transition: opacity 180ms ease, transform 240ms cubic-bezier(.2, .7, .2, 1); }
.mi .arr { position: relative; display: block; flex: none; width: 12px; height: 12px; transform: rotate(-90deg); }
.mi .arr > svg { position: absolute; left: 0; top: 0; display: block; transition: opacity 180ms ease; }
.mi .arr > svg.lit { opacity: 0; }
/* the shortcut: keys in a 1px --bx/stroke box, a "+" between them */
.mi .kb { display: flex; align-items: center; flex: none; }
.mi .kb > i { font: 600 10px/10px 'Chakra Petch', sans-serif; font-style: normal; color: var(--tx-dark);
              padding: 4px; text-shadow: 1px 1px 0 rgba(0, 0, 0, .25); }
.mi .kb > kbd { font: 600 10px/10px 'Chakra Petch', sans-serif; color: var(--tx-standard);
                text-align: center; min-width: 16px; padding: 2px; box-sizing: border-box;
                background: var(--ui-main-dark); border: 1px solid var(--bx-stroke);
                text-shadow: 1px 1px 0 rgba(0, 0, 0, .25);
                filter: drop-shadow(1px 1px 0 rgba(0, 0, 0, .25)); transition: background-color 180ms ease; }
.mi .kb > kbd.w16 { width: 16px; padding: 2px 0; }

/* HOVER - drawn as a state, and live under the pointer */
.mi.is-hover > .r::before, .mi:not(.is-enabled) > .r:hover::before { transform: scaleY(1); }
.mi.is-hover > .r::after, .mi:not(.is-enabled) > .r:hover::after { opacity: 1; transform: translateX(0); }
.mi.is-hover > .r > b, .mi:not(.is-enabled) > .r:hover > b { color: var(--hl-blue); }
.mi.is-hover .arr > svg.dim, .mi:not(.is-enabled) > .r:hover .arr > svg.dim { opacity: 0; }
.mi.is-hover .arr > svg.lit, .mi:not(.is-enabled) > .r:hover .arr > svg.lit { opacity: 1; }
.mi.is-hover .kb > kbd, .mi:not(.is-enabled) > .r:hover .kb > kbd { background: var(--ui-bg); }

/* ENABLED - the open one: --hl/blue, the label and the arrow white */
.mi.is-enabled > .r { background: var(--hl-blue); }
.mi.is-enabled > .r::before { transform: scaleY(1); }
.mi.is-enabled > .r > b { color: var(--ui-white); }
.mi.is-enabled .arr > svg.dim { filter: brightness(0) invert(1); }

/* MENU (541:83363) - the box the ITEM rows sit in. 248 wide: a 2px edge,
   then ACTION - a 1px --ui/black frame whose --bx/stroke shows as the 1px
   line between the rows. The top menu's edge is --hl/arrow, a submenu's
   --hl/blue. LONG SHADOW: 6,6, radius 10, 25% black.
   SPACER: 3px of --bx/enabled under an item that closes a group; it belongs
   to that item, so it takes the place of the 1px line rather than adding one. */
/* 248 is the narrowest; a row with long keys (Edit) widens the list
   rather than spilling past its edge */
.mn { width: max-content; min-width: 248px; box-sizing: border-box; background: var(--ui-bg);
      border: 2px solid var(--hl-arrow); filter: drop-shadow(6px 6px 5px rgba(0, 0, 0, .25)); }
.mn.is-sub { border-color: var(--hl-blue); }
.mn > .act { display: flex; flex-direction: column; gap: 1px;
             background: var(--bx-stroke); border: 1px solid var(--ui-black); }
.mn .mi { width: 100%; }
.mn .sp { height: 3px; margin-top: -1px; background: var(--bx-enabled); flex: none; }

/* TEXT SELECTION (Adi, 2026-10-16): the system's blue-and-white replaced -
   --bx/enabled under the text, the text in --hl/blue, like a field's ENABLED. */
::selection { background: var(--bx-enabled); color: var(--hl-blue); }

/* ===========================================================================
   EVERY HOVER EASES (Adi, 2026-10-17) - the 220ms of the 28 bars, on every
   control that has a hover state: background, edge, text colour and the
   dim/lit glyph pair. In :where(), so it weighs nothing: any control that
   already sets its own transition (the menu rows, the carets that turn, the
   28 bars) keeps it. Re-drawn controls do not replay it - app.js marks a
   freshly drawn subtree .sg-fresh for a moment, which turns this off.
   =========================================================================== */
:where(button, select, input, textarea, [data-act],
       .opt, .opt .value, .opt .txt, .opt .num, .opt .name, .opt .icon,
       .ui-ico, .ui-ico > .plate, .tab, .mi > .r, .lst .r, .lst .c, .row, .ico,
       .as-chip, .as-x, .tl-field, .pf, .pf-btn, .switch, .lb-find, .lb-crumb, .lb-zoom,
       .lb-link, .lb-chip, .opt-sel, .sc-row, .pk-row, .tw-b, .pr-tile, .al-btn,
       .ph-btn, .ph-ico, .zm, .wl-row, .wl-act, .tr-item, .set-tab, .dlg-tag,
       .fc-sw, .cv-box, .ui-cb, .ui-tgl, .bb-seg, .bb-btn-box, .mb) {
  transition: background-color 220ms ease, border-color 220ms ease, color 220ms ease,
              box-shadow 220ms ease, fill 220ms ease;
}
:where(svg.dim, svg.lit, .g-rest, .g-hov, .g-hide, .g-hide-h) { transition: opacity 220ms ease; }
