/* =========================================================================
   CENTRAL COMMAND — THE WIDGET CANVAS

   Every module on this page is a rectangle on a 30-column grid. Columns are
   proportional — the canvas rests as 21 columns of working column plus 9 of
   instrument rail, which is the same split, to within a couple of pixels, that
   the page was hand-built with. Rows are a fixed 4px unit with NO row gap, so
   the 14px bottom gutter each widget carries inside its own box is the only
   thing separating one card from the next, and card heights stay put when the
   window is resized.

   The 4px row is storage only. The GUIDE draws squares — 30 across the
   landscape canvas — and the lattice under each square is twice as fine in
   both directions: a drag moves HALF a square across and half a square down,
   so a corner can land on any of the 9 points a square owns. That is why the
   column count is 60 and not 30: a half has to be a real grid column for the
   CSS grid to be able to address it. See COMMAND_SUBDIV in js/eo-command.js.

   TWO STATES, ONE RENDERER.
   .is-auto  — a layout nobody has edited. Bodies keep their natural height and
               js/eo-command.js measures them, converts to rows and float-packs
               the canvas after every render. The result is the original page:
               two independent card stacks, 14px apart.
   (default) — a saved layout. The rectangles are taken literally, bodies are
               height-locked to their cell, and content that outgrows one is
               redrawn SMALLER until it fits. Nothing here scrolls, ever.

   Nothing outside .eo-command-* is restyled: every card keeps the look it has
   in eo-operator.css, which is what makes the resting page identical. The only
   crossover rules are the "fill your cell" block below, which turns a handful
   of fixed pixel heights into floors.
   ========================================================================= */

#eoCommandPanel{ position:relative; }

.eo-command-deck{
  /* Overwritten inline on every render with the live profile's column count —
     60 on the landscape canvas, 24 on the portrait one, two per visible
     square. This is the fallback. */
  --command-cols:60;
  /* Columns per visible guide square — the denominator of the half. */
  --command-sub:2;
  --command-row:4px;
  /* One snap box. Overwritten from JS on every editor render with the live
     column width, so the guide's cells stay square at any window size; this
     value is only the pre-measurement fallback. */
  --command-box:28px;
  --command-gutter:14px;
  --command-gap:14px;
  display:flex;
  flex-direction:column;
  gap:12px;
}

/* ---- Canvas zoom ------------------------------------------------------- */

/* Type and cards, bigger or smaller — the PAGE still fits the window.

   `zoom` (not transform) is what makes that honest: the deck re-lays-out at the
   new size rather than being a stretched picture of the old one, so text stays
   crisp and the shrink pass still measures real boxes. Because a percentage
   width under zoom resolves so the deck keeps RENDERING at the panel's width,
   the canvas never grows a sideways scrollbar — the columns stay where they
   are and everything drawn in them, text and card heights alike, scales. Rows
   are a local length too, so a widget gets taller as its content gets bigger
   instead of being squeezed by the fit pass.

   The column COUNT never changes: zoom is a viewing size, not a different
   layout, so a canvas arranged at 140% is the same canvas at 80%. The zoom bar
   itself sits OUTSIDE the deck, so it stays put whatever the canvas is doing. */
.eo-command-deck{ zoom:var(--command-zoom, 1); }

/* The way in: one small button, right-aligned above the canvas. It only ever
   grows a label when the zoom is off 100%, so a canvas at its designed size
   carries no chrome at all. */
.eo-command-settings{ position:relative; display:flex; justify-content:flex-end; }

.eo-command-settings-btn{
  display:inline-flex; align-items:center; gap:5px;
  height:24px; padding:0 6px;
  border:1px solid var(--line-bright);
  background:transparent; color:var(--muted);
  cursor:pointer;
  transition:color var(--t-snap) var(--ease), border-color var(--t-snap) var(--ease), background var(--t-snap) var(--ease);
}
.eo-command-settings-btn svg{
  width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:1.6;
}
.eo-command-settings-btn b{ font:600 10px/1 var(--font-body); }
.eo-command-settings-btn:hover,
.eo-command-settings.is-open .eo-command-settings-btn{
  color:var(--text); border-color:var(--line-strong); background:rgba(var(--text-rgb),.05);
}

.eo-command-settings-pop{
  position:absolute; top:calc(100% + 6px); right:0; z-index:20;
  width:206px; padding:11px 12px 10px;
  border:1px solid var(--line-strong);
  background:var(--panel, var(--bg));
  box-shadow:0 12px 30px rgba(0,0,0,.28);
}
.eo-command-settings-note{
  margin:8px 0 0; font:400 10px/1.45 var(--font-body); color:var(--muted); opacity:.8;
}

.eo-command-zoom{ display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
.eo-command-zoom-label{
  font:600 9px/1 var(--font-body); letter-spacing:.14em; color:var(--muted);
}
.eo-command-zoom-row{ display:flex; align-items:center; gap:6px; margin-top:7px; }

.eo-command-zoom-step,
.eo-command-zoom-val{
  border:1px solid var(--line-bright);
  background:transparent; color:var(--muted);
  cursor:pointer;
  transition:color var(--t-snap) var(--ease), border-color var(--t-snap) var(--ease), background var(--t-snap) var(--ease);
}
.eo-command-zoom-step{ flex:none; width:22px; height:22px; font:600 13px/1 var(--font-body); }
.eo-command-zoom-val{ height:19px; padding:0 6px; font:600 10px/1 var(--font-body); }
.eo-command-zoom-step:hover,
.eo-command-zoom-val:hover{ color:var(--text); border-color:var(--line-strong); background:rgba(var(--text-rgb),.05); }

.eo-command-zoom-range{
  -webkit-appearance:none; appearance:none;
  flex:1 1 auto; min-width:0; height:22px; background:transparent; cursor:pointer;
}
.eo-command-zoom-range::-webkit-slider-runnable-track{ height:2px; background:var(--line-bright); }
.eo-command-zoom-range::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:10px; height:10px; margin-top:-4px;
  border-radius:50%; background:var(--accent);
}
.eo-command-zoom-range:hover::-webkit-slider-runnable-track{ background:var(--line-strong); }
.eo-command-zoom-range:focus-visible{ outline:1px solid rgba(var(--accent-rgb),.5); outline-offset:2px; }

/* Universal refresh — same instrument grammar as the zoom panel: a labelled
   section with an action button, spaced so it reads as a sibling rather than
   a squeeze-fit after the zoom row. */
.eo-command-refresh{ margin:10px 0 4px; display:flex; align-items:center; justify-content:space-between; gap:8px; }
.eo-command-refresh-btn{
  border:1px solid var(--line-bright);
  background:transparent; color:var(--muted);
  cursor:pointer;
  transition:color var(--t-snap) var(--ease), border-color var(--t-snap) var(--ease), background var(--t-snap) var(--ease);
}
.eo-command-refresh-btn{ height:22px; padding:0 8px; font:600 11px/1 var(--font-body); letter-spacing:.04em; }
.eo-command-refresh-btn:hover{ color:var(--accent); border-color:var(--accent); background:rgba(var(--accent-rgb),.08); }
.eo-command-refresh-btn:active{ transform:scale(.97); }
.eo-command-refresh-btn.is-busy{ opacity:.45; pointer-events:none; }

/* Stacked canvas: cards already run full width in one column and size
   themselves to their content, so there is nothing here for zoom to do. */
@media (max-width:640px){
  .eo-command-settings{ display:none; }
  .eo-command-deck{ zoom:1; }
}

/* ---- The canvas ------------------------------------------------------- */

.eo-command-canvas{ position:relative; min-width:0; }

.eo-command-grid{
  position:relative;
  z-index:1;
  display:grid;
  grid-template-columns:repeat(var(--command-cols), minmax(0, 1fr));
  grid-auto-rows:var(--command-row);
  column-gap:var(--command-gap);
  row-gap:0;
  align-items:stretch;
  min-height:calc(var(--command-rows, 40) * var(--command-row));
  margin-top:16px;
}

.eo-command-widget{
  position:relative;
  grid-column:var(--cx) / span var(--cw);
  grid-row:var(--cy) / span var(--ch);
  padding-bottom:var(--command-gutter);
  min-width:0;
  min-height:0;
}

/* TWO BOXES PER WIDGET, AND THE DIFFERENCE BETWEEN THEM IS THE WHOLE TRICK.

   The BODY is the frame. It is exactly the cell the widget was dragged to and
   it NEVER scrolls: a scrollbar inside a dashboard tile is a tile that has
   given up — a number you have to scroll to is a number you are not reading.

   The FIT is the content, and it is drawn at whatever scale makes it fit. Down
   to a widget's comfortable size that scale is 1 and none of this does
   anything. Past it js/eo-command.js lays the content out in a box 1/scale as
   large in BOTH directions and scales it back down, so the card first reflows
   into that wider, shorter shape and only then loses type size. A widget
   squeezed to a third of its natural height reads as a small version of
   itself, not as a card with its bottom cut off.

   The card fills via flex-grow rather than height:100%, which is what lets each
   card keep its own intrinsic height as the flex basis: released to its natural
   height there is no free space to distribute, so every pixel figure in
   eo-operator.css still decides the resting size. */
.eo-command-body{ height:100%; min-height:0; overflow:hidden; }
.eo-command-fit{
  height:100%; min-height:0;
  overflow:hidden;
  display:flex; flex-direction:column;
  transform-origin:0 0;
}
.eo-command-fit > *{ flex:1 0 auto; }
/* Only ever present on a widget whose content genuinely does not fit — a
   resting canvas carries no transform at all. */
.eo-command-fit.is-shrunk{
  width:calc(100% / var(--fit));
  height:calc(100% / var(--fit));
  transform:scale(var(--fit));
}

/* Measured: natural height wins, the row span merely reserves the space, and
   nothing is ever scaled — a pristine cell is the size of its content by
   construction. Released for measurement, likewise. */
.eo-command-grid.is-auto .eo-command-widget{ align-self:start; }
.eo-command-grid.is-auto .eo-command-body,
.eo-command-widget.is-free .eo-command-body{ height:auto; overflow:visible; }
.eo-command-grid.is-auto .eo-command-fit,
.eo-command-widget.is-free .eo-command-fit{
  width:100%; height:auto; overflow:visible; transform:none;
}

/* ---- Cards that were sized in pixels: widen them, keep their height -------
   Each of these was a fixed-height item in a flex ROW, sized by flex:1 or by an
   explicit width. In the canvas each one is alone in its widget, so it takes the
   full width and grows downward with the cell — but its original height stays
   its flex basis, which is why a measured layout still lands on 112px and 150px
   exactly where it always did. */
.eo-command-widget .eo-cslot-tile,
.eo-command-widget .eo-cslot-banner,
.eo-command-widget .eo-cslot-wide,
.eo-command-widget .eo-cslot-free,
.eo-command-widget .eo-count-tile{ width:100%; flex:1 0 auto; }


/* ---- IMAGES GO ALL THE WAY DOWN ----------------------------------------
   The rule above hands every pixel-sized card flex:1 0 auto, which makes its
   authored height (112px, 150px, 120px) a floor it cannot be pushed below. For
   a picture that floor is wrong. An image has nothing to reflow and nothing to
   read: at any size it is still the whole image, because object-fit is doing
   the work. So an image slot on an ARRANGED canvas takes the cell it was
   dragged to, all the way down to a single guide square — the smallest
   rectangle the grid can express. See commandWidgetFloor in eo-command.js for
   the other half: the drag has to be allowed down there in the first place.

   Shrink, not height:auto. Keeping the authored height as the flex BASIS is
   what makes a slot that has been given room still rest at 112px; all that
   changes is that it may now be compressed below it. min-height:0 is the part
   that does the work — a flex item's automatic minimum size would otherwise
   hold it at its content height whatever the shrink factor says.

   Untouched on a canvas being MEASURED (is-auto / is-free), because there the
   authored height is not a floor, it is the reading the packing pass takes. */
.eo-command-grid:not(.is-auto) .eo-command-widget:not(.is-free)
  :is(.eo-cslot-tile, .eo-cslot-banner, .eo-cslot-wide, .eo-cslot-free){
  flex-shrink:1; min-height:0;
}
.eo-command-grid:not(.is-auto) .eo-command-widget:not(.is-free) .eo-cslot-free{ min-height:0; }

/* THE CHROME GETS OUT OF THE WAY BEFORE THE PICTURE DOES.

   A slot carries three buttons and a placeholder line, and those DO have words
   to read — so they are what has to go as the tile gets small, in that order.
   Each slot is its own container, so this is a question of how big THAT SLOT
   is, not how wide the window is: two identical tiles side by side, one large
   and one tiny, each get the treatment they have earned.

   Only on an arranged canvas, for the same reason as above — container-type
   makes an element size independently of its contents, and a canvas being
   measured is one where the contents are precisely the point. */
.eo-command-grid:not(.is-auto) .eo-command-widget:not(.is-free)
  :is(.eo-cslot-tile, .eo-cslot-banner, .eo-cslot-wide, .eo-cslot-free){
  container-type:size;
}

/* Getting tight: the same controls, drawn small, so they still fit one row. */
@container (max-width: 200px) or (max-height: 100px){
  .eo-cslot-tools{ right:4px; bottom:4px; left:4px; gap:3px; }
  .eo-cslot-btn{ height:16px; padding:0 5px; font-size:8px; letter-spacing:.03em; }
  .eo-cslot-ph{ padding:4px; font-size:8px; letter-spacing:.06em; }
}

/* Past this there is no room for a control that would not be bigger than the
   thing it sits on, so the tile becomes what it is: the picture, and nothing
   else. It stays fully usable — an EMPTY slot is click-to-browse across its
   whole face and takes a drop at any size (see wireSlots in eo-command.js), so
   the only thing that needs the tile grown again is changing a picture that is
   already there. */
@container (max-width: 116px) or (max-height: 52px){
  .eo-cslot-tools, .eo-cslot-ph{ display:none; }
}

/* A counter tile is a fixed glyph — a number, a word and a button, with nothing
   below the fold to reveal. It keeps its natural 112px as the measured height
   and it does NOT squeeze: a squeezed tile clips its own number, where a tile
   that overflows its cell is caught by the fit pass and the whole glyph —
   number, word and button — is drawn smaller together. */
.eo-command-widget .eo-count-tile{ overflow:hidden; padding-block:8px; }
.eo-command-widget .eo-cslot-free{ min-height:120px; }
.eo-command-widget .pg-banner-wrap{ margin-bottom:0; flex:1 0 auto; }
.eo-command-widget .eo-ltf{ margin-top:0; }

/* The plot is the whole point of a trend widget, so it takes whatever height
   the widget has spare instead of staying a fixed 104px glyph. */
.eo-command-widget .eo-mini-trend-plot{ flex:1 1 auto; min-height:104px; display:flex; }
.eo-command-widget .eo-mini-trend-svg{ height:100%; min-height:104px; }
.eo-mtc-fill{ opacity:.14; stroke:none; }
.eo-mtc-bar{ opacity:.85; }
.eo-mini-trend-blank{ align-items:center; justify-content:center; text-align:center; }

/* The calendar draws exactly one period, so its natural height IS the card and
   an unarranged layout measures it correctly with no help. Given a rectangle it
   fills it: the card stretches and the day cells take the spare height, which
   is why this one is flex:1 1 rather than the 1 0 every other card gets. */
.eo-command-widget .eo-cal{ flex:1 1 auto; min-height:0; }
/* Same deal as the calendar: the list of captures IS the card, so it takes
   whatever rectangle the widget was given rather than keeping an intrinsic
   height — that is what the packing pass measures against. */
.eo-command-widget .eo-inbox-card{ flex:1 1 auto; min-height:0; }
.eo-command-body:has(> .eo-inbox-card){ overflow:hidden; }
/* Being MEASURED: no rectangle yet, so the scroller has no height to scroll
   against and would report its whole queue. Cap it, or two hundred captures
   would measure as a card two hundred rows tall and a pristine canvas would
   open with the inbox eating the page. This is the card's natural size. */
.eo-command-grid.is-auto .eo-inbox-scroll,
.eo-command-widget.is-free .eo-inbox-scroll{ max-height:186px; }
/* The clipboard list is the same shape of thing as the inbox — a list that IS
   the card — so it takes the rectangle it is given rather than an intrinsic
   height, and it gets the same cap while it is being measured: twenty clips
   must not measure as a card twenty rows tall. */
.eo-command-widget .eo-clips-card{ flex:1 1 auto; min-height:0; }
.eo-command-body:has(> .eo-clips-card){ overflow:hidden; }
.eo-command-grid.is-auto .eo-clips-scroll,
.eo-command-widget.is-free .eo-clips-scroll{ max-height:186px; }
/* The to-do card is the same shape of thing as the inbox — a list that IS the
   card — so it takes the rectangle rather than an intrinsic height, and it gets
   the same cap while it is being measured: a hundred open actions must not
   measure as a card a hundred rows tall and open the page with today's list
   eating it. */
.eo-command-widget .eo-todo-card{ flex:1 1 auto; min-height:0; }
.eo-command-body:has(> .eo-todo-card){ overflow:hidden; }
.eo-command-grid.is-auto .eo-todo-scroll,
.eo-command-widget.is-free .eo-todo-scroll{ max-height:186px; }
.eo-command-body:has(> .eo-cal){ overflow:hidden; }

.eo-command-note{ gap:7px; }
.eo-command-note p{
  margin:0; color:var(--muted);
  font:400 12px/1.55 var(--font-body);
  white-space:pre-wrap;
}

/* ---- Chrome profile launchers ------------------------------------------
   Identity ports rather than generic shortcut tiles: the circle is tinted
   to the exact color Chrome shows for that profile, so telling the three
   apart is a color match, not a re-read of an email address, and it carries
   the real four-color Google G rather than a letter — no text needed on top
   of a color that's already legible. Everything that isn't "which widget /
   that it's Google / that color" was cut to earn the room back — the entire
   instrument is one native button. */
.eo-chrome-profile{
  position:relative; width:100%; min-height:64px; padding:10px 12px;
  display:grid; grid-template-columns:40px minmax(0,1fr); align-items:center; gap:10px;
  overflow:hidden; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--card); color:var(--text); text-align:left; cursor:pointer;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.025);
  transition:border-color 140ms cubic-bezier(.23,1,.32,1), background-color 140ms cubic-bezier(.23,1,.32,1), transform 120ms cubic-bezier(.23,1,.32,1);
}
.eo-chrome-profile:hover{ border-color:var(--chrome-profile-color,var(--line-bright)); background:var(--card-hover); }
.eo-chrome-profile:active{ transform:scale(.98); }
.eo-chrome-profile:focus-visible{ outline:1px solid var(--accent); outline-offset:2px; }
.eo-chrome-profile:disabled{ cursor:wait; opacity:1; }
.eo-chrome-profile-mark{
  position:relative; z-index:1; width:40px; height:40px; display:grid; place-items:center;
  border-radius:50%; background:var(--chrome-profile-color, var(--accent));
  box-shadow:0 0 0 1px rgba(255,255,255,.1), 0 2px 10px -2px var(--chrome-profile-color, transparent);
}
.eo-chrome-profile-g-badge{
  position:relative; z-index:1; width:22px; height:22px; border-radius:50%;
  display:grid; place-items:center; background:#fff; box-shadow:0 0 0 2px rgba(255,255,255,.55);
}
.eo-chrome-profile-g{ width:13px; height:13px; }
.eo-chrome-profile-copy{ position:relative; z-index:1; min-width:0; display:flex; flex-direction:column; }
.eo-chrome-profile-copy b{
  overflow:hidden; color:var(--text); font:650 13px/1.2 var(--font-display);
  letter-spacing:-.01em; text-overflow:ellipsis; white-space:nowrap;
}
.eo-chrome-profile-status{
  min-height:11px; margin-top:3px; color:var(--accent-soft);
  font:650 8px/1 var(--font-mono); letter-spacing:.1em; white-space:nowrap;
}
.eo-chrome-profile.is-launching .eo-chrome-profile-status{ color:var(--accent-soft); }
.eo-chrome-profile.is-active{ border-color:rgba(var(--good-rgb),.62); }
.eo-chrome-profile.is-active .eo-chrome-profile-status{ color:var(--good); }
.eo-chrome-profile.is-error{ border-color:rgba(var(--danger-rgb),.62); }
.eo-chrome-profile.is-error .eo-chrome-profile-status{ color:var(--danger-soft); }
.eo-command-widget.is-narrow .eo-chrome-profile{ grid-template-columns:34px minmax(0,1fr); gap:8px; padding:8px; }
.eo-command-widget.is-narrow .eo-chrome-profile-mark{ width:32px; height:32px; }
.eo-command-widget.is-narrow .eo-chrome-profile-g-badge{ width:18px; height:18px; }
.eo-command-widget.is-narrow .eo-chrome-profile-g{ width:11px; height:11px; }

@media (prefers-reduced-motion:reduce){
  .eo-chrome-profile{ transition:none; }
}
html[data-motion="static"] .eo-chrome-profile{ transition:none; }

/* ---- Music library ----------------------------------------------------- */
/* The card is a tiny jukebox at rest. OPEN uses Command Peek to raise the
   genuine track bank above the dashboard, just like the money instruments. */
.eo-music-picker{ position:relative; padding:9px !important; overflow:hidden; isolation:isolate; }
.eo-music-picker::before{ content:''; position:absolute; inset:3px; z-index:-1; opacity:.22; pointer-events:none; background:repeating-linear-gradient(90deg,transparent 0 12px,rgba(var(--accent-rgb),.13) 12px 13px),linear-gradient(110deg,rgba(var(--accent-rgb),.08),transparent 45%); }
.eo-music-jukebox{ display:flex; align-items:stretch; min-height:82px; border:1px solid rgba(var(--accent-rgb),.25); background:rgba(var(--bg-rgb),.24); }
.eo-music-disc{ position:relative; flex:0 0 78px; display:grid; place-items:center; overflow:hidden; border-right:1px solid rgba(var(--accent-rgb),.22); background:radial-gradient(circle at 50% 50%,rgba(var(--accent-rgb),.16) 0 6px,transparent 7px 15px,rgba(var(--accent-rgb),.24) 16px 17px,transparent 18px 26px,rgba(var(--accent-rgb),.13) 27px 28px,transparent 29px); }
.eo-music-disc::before,.eo-music-disc::after{ content:''; position:absolute; width:58px; height:58px; border:1px dashed rgba(var(--accent-rgb),.25); border-radius:50%; }.eo-music-disc::after{ width:42px; height:42px; border-style:solid; opacity:.45; }
.eo-music-disc > i{ position:absolute; width:4px; height:4px; border-radius:50%; background:var(--accent); box-shadow:0 0 8px rgba(var(--accent-rgb),.85); }.eo-music-disc > i:nth-of-type(1){ transform:translate(28px); }.eo-music-disc > i:nth-of-type(2){ transform:rotate(120deg) translate(28px); }.eo-music-disc > i:nth-of-type(3){ transform:rotate(240deg) translate(28px); }
.eo-music-disc b{ z-index:1; display:grid; place-items:center; width:20px; height:20px; border:1px solid rgba(var(--accent-rgb),.6); border-radius:50%; background:var(--bg); color:var(--accent-soft); font:600 11px/1 var(--font-mono); }
.eo-music-disc span{ position:absolute; bottom:7px; left:0; right:0; color:var(--faint); font:600 6.5px/.95 var(--font-mono); letter-spacing:.1em; text-align:center; }
.eo-music-picker.is-live .eo-music-disc::before{ animation:eoMusicSpin 5s linear infinite; }.eo-music-picker.is-live .eo-music-disc b{ color:var(--good); border-color:rgba(var(--good-rgb),.75); }.eo-music-picker.is-live .eo-music-disc > i{ background:var(--good); box-shadow:0 0 8px rgba(var(--good-rgb),.85); }
@keyframes eoMusicSpin{ to{ transform:rotate(360deg); } }
.eo-music-console{ flex:1 1 auto; min-width:0; padding:11px 10px 8px; }
.eo-music-now{ min-width:0; }.eo-music-now > span{ display:block; color:var(--accent); font:600 8px/1 var(--font-mono); letter-spacing:.16em; }.eo-music-now b{ display:block; overflow:hidden; margin-top:5px; color:var(--text); font:600 14px/1.15 var(--font-display); letter-spacing:-.02em; text-overflow:ellipsis; white-space:nowrap; }.eo-music-now i{ display:block; overflow:hidden; margin-top:4px; color:var(--faint); font:500 8px/1 var(--font-mono); letter-spacing:.09em; text-overflow:ellipsis; text-transform:uppercase; white-space:nowrap; font-style:normal; }
.eo-music-picker-row{ display:flex; align-items:center; gap:6px; margin-top:9px; min-width:0; }
.eo-music-picker-play,.eo-music-step{ flex:none; height:26px; padding:0; cursor:pointer; color:var(--muted); }
.eo-music-picker-play{ width:26px; border:1px solid rgba(var(--accent-rgb),.42); border-radius:50%; background:rgba(var(--accent-rgb),.06); color:var(--accent-soft); font-size:10px; line-height:1; }
.eo-music-step{ width:19px; border:0; background:transparent; font:500 13px/1 var(--font-mono); }.eo-music-picker-play:hover:not(:disabled){ background:var(--accent); border-color:var(--accent); color:var(--on-accent); }.eo-music-step:hover:not(:disabled){ color:var(--accent); }.eo-music-picker-play:active:not(:disabled),.eo-music-step:active:not(:disabled){ transform:scale(.94); }.eo-music-picker-play:disabled,.eo-music-step:disabled{ cursor:not-allowed; opacity:.3; }.eo-music-picker.is-live .eo-music-picker-play{ background:var(--accent); color:var(--on-accent); box-shadow:0 0 0 3px rgba(var(--accent-rgb),.1); }
.eo-music-picker .eo-pill-toggle{ margin-left:auto; height:22px; padding:0 8px; border-radius:3px; color:var(--accent-soft); }
.eo-music-library-panel{ margin-top:12px; padding-top:12px; border-top:1px solid rgba(var(--accent-rgb),.28); }.eo-music-library-head{ display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; color:var(--accent); font:600 9px/1 var(--font-mono); letter-spacing:.14em; }.eo-music-library-head b{ color:var(--faint); font:500 8px/1 var(--font-mono); }
.eo-music-matrix{ padding:7px; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:4px; border:1px solid rgba(var(--accent-rgb),.3); border-radius:4px; background:rgba(var(--bg-rgb),.3); }.eo-music-signal{ position:relative; min-width:0; min-height:40px; padding:6px 7px; border:1px solid transparent; border-radius:3px; background:rgba(var(--text-rgb),.025); color:var(--muted); cursor:pointer; text-align:left; }.eo-music-signal:hover,.eo-music-signal:focus-visible{ border-color:rgba(var(--accent-rgb),.6); background:rgba(var(--accent-rgb),.1); color:var(--text); outline:none; }.eo-music-signal.is-selected{ border-color:rgba(var(--accent-rgb),.7); background:rgba(var(--accent-rgb),.13); color:var(--accent-soft); }.eo-music-signal i{ display:block; margin-bottom:3px; color:var(--faint); font:500 7.5px/1 var(--font-mono); letter-spacing:.12em; font-style:normal; }.eo-music-signal span{ display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font:600 9px/1.2 var(--font-body); }.eo-music-signal em{ display:block; overflow:hidden; margin-top:3px; color:var(--faint); font:500 7px/1 var(--font-mono); letter-spacing:.04em; text-overflow:ellipsis; white-space:nowrap; font-style:normal; }.eo-music-matrix p{ grid-column:1 / -1; margin:7px; color:var(--faint); font:500 10px/1.4 var(--font-mono); }
.eo-music-picker .eo-pill-toggle:focus-visible,.eo-music-picker-play:focus-visible,.eo-music-step:focus-visible{ outline:1px solid var(--accent); outline-offset:2px; }
.eo-command-widget.is-narrow .eo-music-disc{ flex-basis:56px; }.eo-command-widget.is-narrow .eo-music-disc::before{ width:44px; height:44px; }.eo-command-widget.is-narrow .eo-music-disc::after{ width:31px; height:31px; }.eo-command-widget.is-narrow .eo-music-disc > i:nth-of-type(1){ transform:translate(21px); }.eo-command-widget.is-narrow .eo-music-disc > i:nth-of-type(2){ transform:rotate(120deg) translate(21px); }.eo-command-widget.is-narrow .eo-music-disc > i:nth-of-type(3){ transform:rotate(240deg) translate(21px); }
@media (prefers-reduced-motion:reduce){ .eo-music-picker.is-live .eo-music-disc::before{ animation:none; } }


/* ---- World clocks ------------------------------------------------------ */
/* The six times off the top bar, now a widget. Two readings of the same data:
   DIGITAL packs as many columns as the widget's width honestly allows, FACES
   is pinned to 2 columns x 3 rows so the six read in the bar's old order. */
.eo-clock-card{ gap:10px; }
.eo-clock-grid{
  display:grid; gap:10px 14px;
  flex:1 1 auto; min-height:0; align-content:center;
}
.eo-clock-grid.is-six.is-digital{ grid-template-columns:repeat(auto-fit, minmax(104px, 1fr)); }
.eo-clock-grid.is-six.is-faces{ grid-template-columns:repeat(2, minmax(0, 1fr)); }
.eo-clock-grid.is-one{ grid-template-columns:minmax(0, 1fr); }

.eo-clock-cell{
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:3px; min-width:0;
}
.eo-clock-cell.is-digital{ align-items:flex-start; }
.eo-clock-label{
  display:flex; align-items:baseline; gap:6px;
  font-family:var(--font-mono); font-size:9px; letter-spacing:.14em;
  color:var(--faint); text-transform:uppercase;
}
/* The dials carry no readout of their own, so the code line answers "what time
   is it there" outright. A step smaller than the code, and brighter, so it
   reads as an annotation on the code rather than competing with it. */
.eo-clock-label-time{
  font-weight:400; font-size:8px; letter-spacing:.06em;
  color:var(--muted); font-variant-numeric:tabular-nums;
}
.eo-clock-cell.is-home .eo-clock-label-time{ color:#4fff8a; }
.eo-clock-digits{
  font-family:var(--font-mono); font-weight:400; font-size:24px; line-height:1.05;
  color:var(--text); font-variant-numeric:tabular-nums; letter-spacing:.02em;
}
.eo-clock-meta{
  font-family:var(--font-mono); font-size:8.5px; letter-spacing:.12em;
  color:var(--faint); text-transform:uppercase;
}
.eo-clock-under{
  font-family:var(--font-mono); font-weight:400; font-size:11px;
  color:var(--muted); font-variant-numeric:tabular-nums; letter-spacing:.06em;
}
/* LON is the device's own time — the one on the card that is "here". */
.eo-clock-cell.is-home .eo-clock-digits,
.eo-clock-cell.is-home .eo-clock-under{
  color:#4fff8a; text-shadow:0 0 6px rgba(79,255,138,.6);
}
.eo-clock-cell.is-home .eo-clock-hand.is-hour,
.eo-clock-cell.is-home .eo-clock-hand.is-min{ stroke:#4fff8a; }

/* The dial. Sized off the cell so one widget resize moves everything. */
.eo-clock-face{
  width:100%; max-width:96px; aspect-ratio:1 / 1; height:auto; display:block;
  overflow:visible;
}
.eo-clock-dial{ fill:rgba(255,255,255,.02); stroke:var(--line-bright); stroke-width:1.4; }
.eo-clock-tick{ stroke:var(--faint); stroke-width:1.2; stroke-linecap:round; }
.eo-clock-tick.is-major{ stroke:var(--muted); stroke-width:2.2; }
.eo-clock-hand{ stroke:var(--text); stroke-linecap:round; }
.eo-clock-hand.is-hour{ stroke-width:4; }
.eo-clock-hand.is-min{ stroke-width:2.6; }
.eo-clock-hand.is-sec{ stroke:var(--accent); stroke-width:1.2; }
.eo-clock-pin{ fill:var(--accent); }

/* A single clock has the whole card, so it is allowed to be big. */
.eo-clock-cell.is-solo{ gap:7px; }
.eo-clock-cell.is-solo.is-digital{ align-items:center; }
.eo-clock-cell.is-solo .eo-clock-digits{ font-size:42px; }
.eo-clock-cell.is-solo .eo-clock-face{ max-width:180px; }
.eo-clock-cell.is-solo .eo-clock-under{ font-size:14px; }

/* Narrow column: the six-up digital stacks rather than squeezing the readout. */
.eo-command-widget.is-narrow .eo-clock-grid.is-six.is-digital{
  grid-template-columns:repeat(2, minmax(0, 1fr));
}
.eo-command-widget.is-narrow .eo-clock-digits{ font-size:18px; }
.eo-command-widget.is-narrow .eo-clock-face{ max-width:64px; }

/* ---- The way in ------------------------------------------------------- */

/* The cover already carries hover-only tools, so Edit joins that toolbar and
   a resting Central Command gains no new visible chrome at all. */
.eo-command-edit-entry{ order:-1; }

/* Only when the cover itself has been taken off the canvas: a quiet dock. */
.eo-command-dock{
  position:sticky; top:8px; z-index:18;
  height:0; display:flex; justify-content:flex-end;
  padding-right:8px; pointer-events:none;
}
.eo-command-dock-btn{
  pointer-events:auto;
  display:flex; align-items:center; gap:8px;
  min-height:36px; padding:0 13px;
  border:1px solid var(--line-bright);
  background:rgba(10,15,26,.78);
  -webkit-backdrop-filter:var(--glass-blur);
          backdrop-filter:var(--glass-blur);
  color:var(--muted);
  font:600 10px/1 var(--font-mono); letter-spacing:.08em; text-transform:uppercase;
  cursor:pointer;
}
.eo-command-dock-btn:hover{ color:var(--accent); border-color:rgba(var(--accent-rgb),.55); }
.eo-command-dock-btn svg{ width:15px; height:15px; fill:none; stroke:currentColor; stroke-width:1.7; }

/* ---- Editor bar ------------------------------------------------------- */

.eo-command-editor{
  position:sticky; top:0; z-index:30;
  display:flex; align-items:center; gap:16px;
  min-height:58px; padding:9px 10px 9px 12px;
  border:1px solid rgba(var(--accent-rgb),.3);
  border-left:3px solid var(--accent);
  background:rgba(9,13,28,.95);
  -webkit-backdrop-filter:blur(18px) saturate(130%);
          backdrop-filter:blur(18px) saturate(130%);
  box-shadow:0 14px 40px rgba(0,0,0,.34);
}
.eo-command-editor-mark{
  flex:none;
  display:grid; place-items:center;
  width:34px; height:34px;
  background:rgba(var(--accent-rgb),.12);
  color:var(--accent);
}
.eo-command-editor-mark svg{ width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.5; }
.eo-command-editor-title{ flex:none; display:flex; flex-direction:column; gap:3px; }
.eo-command-editor-title span{
  color:var(--accent);
  font:600 8.5px/1 var(--font-mono); letter-spacing:.18em;
}
.eo-command-editor-title b{
  color:var(--text);
  font:650 14px/1.1 var(--font-display); letter-spacing:-.01em;
}
.eo-command-editor-status{
  flex:1 1 auto; min-width:0;
  display:flex; align-items:center; gap:8px;
  padding-left:16px;
  border-left:1px solid var(--line);
  color:var(--faint);
  font:500 11px/1.4 var(--font-body);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.eo-command-editor-status i{
  flex:none; width:6px; height:6px;
  border-radius:50% !important;
  background:var(--line-bright);
}
.eo-command-editor-status i.is-dirty{
  background:var(--warn);
  box-shadow:0 0 0 3px rgba(var(--warn-rgb),.18);
}
.eo-command-editor-actions{ flex:none; display:flex; gap:7px; }

.eo-command-btn{
  height:32px; padding:0 13px;
  border:1px solid var(--line-bright);
  background:transparent; color:var(--muted);
  font:600 11px/1 var(--font-body);
  cursor:pointer;
  transition:color var(--t-snap) var(--ease), border-color var(--t-snap) var(--ease), background var(--t-snap) var(--ease);
}
.eo-command-btn:hover{ color:var(--text); border-color:var(--line-strong); background:rgba(var(--text-rgb),.05); }
.eo-command-btn.is-add{ color:var(--accent); border-color:rgba(var(--accent-rgb),.45); }
.eo-command-btn.is-add:hover{ background:rgba(var(--accent-rgb),.12); }
.eo-command-btn.is-add span{ margin-right:3px; font-weight:700; }
.eo-command-btn.is-save{ background:var(--accent); border-color:transparent; color:var(--on-accent); }
.eo-command-btn.is-save:hover{ background:var(--accent-soft); color:var(--on-accent); }
.eo-command-btn.is-save.is-dirty{ box-shadow:0 0 0 3px rgba(var(--accent-rgb),.2); }

/* ---- Grid guide + drop preview ---------------------------------------- */

.eo-command-guide{
  position:absolute; inset:16px 0 0 0; z-index:0;
  display:grid;
  grid-template-columns:repeat(var(--command-cols), minmax(0, 1fr));
  grid-template-rows:1fr;
  column-gap:var(--command-gap);
  pointer-events:none;
  opacity:0;
  animation:eoCommandGuideIn .3s var(--ease) forwards;
}
@keyframes eoCommandGuideIn{ to{ opacity:1; } }
/* Square cells, each spanning --command-sub columns, ruled every --command-box
   down: this is the square you AIM at, and it is strong enough to read THROUGH
   the half-transparent widgets above it — the grid has to be visible while you
   are aiming at it, not only in the empty strip at the foot of the canvas.

   The two faint lines inside it — one down the middle, one across it — are the
   HALF, which is what a drag actually moves by. Drawn at roughly a third the
   strength of the square's own edge, so the square still reads as the unit and
   the halves read as the finer places a corner may stop. */
.eo-command-guide i{
  grid-column:span var(--command-sub);
  background:
    linear-gradient(90deg, transparent calc(50% - .5px),
      rgba(var(--accent-rgb),.05) calc(50% - .5px) calc(50% + .5px), transparent calc(50% + .5px)),
    repeating-linear-gradient(to bottom,
      rgba(var(--accent-rgb),.05) 0 1px,
      transparent 1px calc(var(--command-box) / 2)),
    repeating-linear-gradient(to bottom,
      rgba(var(--accent-rgb),.13) 0 1px,
      transparent 1px var(--command-box)),
    rgba(var(--accent-rgb),.055);
  box-shadow:inset 0 0 0 1px rgba(var(--accent-rgb),.13);
}

/* Lives inside the grid so it snaps to real cells, not to a guess. */
.eo-command-preview{
  display:none;
  grid-column:var(--cx) / span var(--cw);
  grid-row:var(--cy) / span var(--ch);
  margin-bottom:var(--command-gutter);
  border:1.5px dashed rgba(var(--accent-rgb),.75);
  background:rgba(var(--accent-rgb),.09);
  pointer-events:none;
}
.eo-command-preview.is-on{ display:block; }
.eo-command-preview.is-invalid{
  border-color:rgba(var(--danger-rgb),.8);
  background:rgba(var(--danger-rgb),.11);
}

/* ---- A widget in edit mode -------------------------------------------- */

/* The page goes inert and slightly flat on purpose: edit mode is a PLAN of the
   dashboard, not a live one, and nothing on it should be clickable by
   accident while you are arranging it. */
.eo-command-widget.is-editing{
  box-shadow:inset 0 0 0 1px rgba(var(--accent-rgb),.22);
  transition:box-shadow var(--t-snap) var(--ease);
}
.eo-command-widget.is-editing .eo-command-body{
  opacity:.46;
  filter:saturate(.7);
  pointer-events:none;
  -webkit-user-select:none; user-select:none;
}
.eo-command-widget.is-editing:hover{ box-shadow:inset 0 0 0 1px rgba(var(--accent-rgb),.5); }
.eo-command-widget.is-carrying,
.eo-command-widget.is-resizing{
  z-index:20;
  box-shadow:inset 0 0 0 1.5px var(--accent), 0 18px 44px rgba(0,0,0,.4);
}
/* Held, not dragged: it lifts off the canvas and lets the drop preview
   underneath it read through. */
.eo-command-widget.is-carrying{
  pointer-events:none;
  opacity:.9;
  box-shadow:inset 0 0 0 1.5px var(--accent), 0 26px 60px rgba(0,0,0,.55);
}
.eo-command-widget.is-invalid{ box-shadow:inset 0 0 0 1.5px var(--danger), 0 18px 44px rgba(0,0,0,.4); }
body.eo-command-gesturing{ cursor:grabbing; -webkit-user-select:none; user-select:none; }
body.eo-command-gesturing *{ transition:none !important; }
/* A widget in hand: the whole page is a drop target, so every cursor says so
   and nothing under it invites a click. */
body.eo-command-carrying{ cursor:grabbing; -webkit-user-select:none; user-select:none; }
body.eo-command-carrying *{ cursor:grabbing !important; transition:none !important; }

.eo-command-chrome{
  position:absolute; inset:0 0 auto 0; z-index:5;
  display:flex; align-items:center; gap:6px;
  padding:5px 6px 5px 5px;
  background:linear-gradient(180deg, rgba(9,13,28,.96), rgba(9,13,28,.74) 68%, transparent);
}
.eo-command-chrome-drag{
  flex:1 1 auto; min-width:0;
  display:flex; align-items:center; gap:6px;
  height:26px; padding:0 8px 0 3px;
  border:1px solid transparent;
  background:transparent; color:var(--text);
  font:600 10.5px/1 var(--font-body);
  cursor:pointer; text-align:left;
}
.eo-command-chrome-drag:hover{ border-color:rgba(var(--accent-rgb),.4); background:rgba(var(--accent-rgb),.1); }
.eo-command-chrome-drag{ cursor:pointer; }
.eo-command-widget.is-carrying .eo-command-chrome-drag{ border-color:var(--accent); background:rgba(var(--accent-rgb),.18); }
.eo-command-chrome-drag svg{ flex:none; width:15px; height:15px; fill:currentColor; color:var(--faint); }
.eo-command-chrome-drag span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.eo-command-chrome-drag kbd{
  flex:none; margin-left:auto; padding-left:6px;
  color:var(--accent);
  font:600 9px/1 var(--font-mono); letter-spacing:.06em;
}
.eo-command-chrome-tools{ flex:none; display:flex; gap:3px; }

/* A three-column tile cannot carry a name, a size and three tools. Below the
   threshold the chrome keeps only what you cannot do without — the grip and the
   tools — and the name stays on the drag handle's tooltip. */
.eo-command-widget.is-narrow .eo-command-chrome{ padding:4px 3px 4px 2px; gap:2px; }
.eo-command-widget.is-narrow .eo-command-chrome-drag span,
.eo-command-widget.is-narrow .eo-command-chrome-drag kbd{ display:none; }
.eo-command-widget.is-narrow .eo-command-chrome-drag{ flex:0 0 auto; padding:0 2px; }
.eo-command-widget.is-narrow .eo-command-chrome-tools{ margin-left:auto; }
.eo-command-widget.is-narrow .eo-command-chrome-btn{ width:21px; height:21px; }
.eo-command-widget.is-narrow .eo-command-chrome-btn svg{ width:12px; height:12px; }
.eo-command-chrome-btn{
  display:grid; place-items:center;
  width:24px; height:24px; padding:0;
  border:1px solid var(--line-bright);
  background:rgba(10,15,26,.72); color:var(--muted);
  cursor:pointer;
}
.eo-command-chrome-btn svg{ width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:1.7; stroke-linecap:round; }
.eo-command-chrome-btn:hover{ color:var(--accent); border-color:rgba(var(--accent-rgb),.6); }
.eo-command-chrome-btn.is-remove:hover{ color:var(--danger); border-color:rgba(var(--danger-rgb),.6); }

/* Grips: right edge for width, bottom edge for height, corner for both. */
.eo-command-grip{
  position:absolute; z-index:4;
  border:0; padding:0; background:transparent;
}
.eo-command-grip.is-e{
  top:38px; bottom:calc(var(--command-gutter) + 20px);
  right:calc(var(--command-gap) / -2); width:12px;
  cursor:ew-resize;
}
.eo-command-grip.is-s{
  left:14px; right:26px;
  bottom:calc(var(--command-gutter) / 2 - 6px); height:12px;
  cursor:ns-resize;
}
.eo-command-grip.is-se{
  right:0; bottom:var(--command-gutter);
  width:22px; height:22px;
  cursor:nwse-resize;
}
.eo-command-grip.is-e::after,
.eo-command-grip.is-s::after{
  content:''; position:absolute; inset:0; margin:auto;
  background:rgba(var(--accent-rgb),.45);
  opacity:0; transition:opacity var(--t-snap) var(--ease);
}
.eo-command-grip.is-e::after{ width:3px; height:24px; }
.eo-command-grip.is-s::after{ width:24px; height:3px; }
.eo-command-grip.is-se::after{
  content:''; position:absolute; right:5px; bottom:5px;
  width:9px; height:9px;
  border-right:2px solid var(--accent); border-bottom:2px solid var(--accent);
  border-radius:0 !important;
  opacity:.55; transition:opacity var(--t-snap) var(--ease);
}
.eo-command-widget.is-editing:hover .eo-command-grip::after,
.eo-command-grip:focus-visible::after{ opacity:1; }
.eo-command-grip:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

/* A module with no content yet. Nothing at all is drawn for it in the resting
   page — an empty placeholder costs more space than it earns — but the editor
   shows it so it can be placed before its data ever arrives. */
.eo-command-ghost{
  height:100%; min-height:64px;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:5px;
  padding:12px;
  border:1px dashed var(--line-bright);
  background:rgba(var(--panel-rgb),.4);
  text-align:center;
}
.eo-command-ghost span{ color:var(--muted); font:600 11px/1.3 var(--font-body); }
.eo-command-ghost em{
  color:var(--faint); font-style:normal;
  font:400 9.5px/1 var(--font-mono); letter-spacing:.1em; text-transform:uppercase;
}
.eo-command-widget.is-ghost .eo-command-body{ opacity:1; filter:none; }

/* ---- Widget library --------------------------------------------------- */

.eo-command-library{
  width:min(560px, calc(100vw - 48px));
  max-height:min(720px, calc(100vh - 72px));
  padding:0;
  border:1px solid var(--line-strong);
  background:var(--panel);
  color:var(--text);
  overflow:hidden;
}
.eo-command-library::backdrop{ background:rgba(4,6,12,.62); -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px); }
.eo-command-library-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:16px;
  padding:18px 18px 14px;
  border-bottom:1px solid var(--line);
}
.eo-command-library-head span{
  display:block; color:var(--accent);
  font:600 8.5px/1 var(--font-mono); letter-spacing:.2em;
}
.eo-command-library-head b{
  display:block; margin-top:6px; color:var(--text);
  font:650 17px/1.1 var(--font-display); letter-spacing:-.015em;
}
.eo-command-library-head button{
  flex:none; display:grid; place-items:center;
  width:28px; height:28px;
  border:1px solid var(--line-bright);
  background:transparent; color:var(--muted); cursor:pointer;
}
.eo-command-library-head button svg{ width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; }
.eo-command-library-head button:hover{ color:var(--text); border-color:var(--line-strong); }

.eo-command-tabs{
  display:flex; gap:2px;
  padding:10px 14px 0;
  border-bottom:1px solid var(--line);
}
.eo-command-tabs button{
  height:34px; padding:0 12px;
  border:0; border-bottom:2px solid transparent;
  background:transparent; color:var(--faint);
  font:600 11px/1 var(--font-body);
  cursor:pointer;
}
.eo-command-tabs button:hover{ color:var(--muted); }
.eo-command-tabs button.is-on{ color:var(--accent); border-bottom-color:var(--accent); }

.eo-command-library-body{ padding:18px; overflow-y:auto; }

.eo-command-form{ display:flex; flex-direction:column; gap:13px; }
.eo-command-form-lede{
  margin:0; color:var(--faint);
  font:400 11.5px/1.55 var(--font-body);
}
.eo-command-form label{ display:flex; flex-direction:column; gap:5px; min-width:0; }
.eo-command-form label > span{
  color:var(--muted);
  font:600 9.5px/1 var(--font-mono); letter-spacing:.13em; text-transform:uppercase;
}
.eo-command-form input,
.eo-command-form select,
.eo-command-form textarea{
  width:100%;
  min-height:34px; padding:8px 10px;
  border:1px solid var(--line-bright);
  background:var(--card); color:var(--text);
  font:400 12.5px/1.4 var(--font-body);
}
.eo-command-form textarea{ resize:vertical; }
.eo-command-form input:focus,
.eo-command-form select:focus,
.eo-command-form textarea:focus{ outline:none; border-color:var(--accent); }
.eo-command-form-pair{ display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:11px; }
.eo-command-form-hint{
  margin:-4px 0 0; color:var(--faint);
  font:400 10.5px/1.5 var(--font-body);
}
.eo-command-form-check{ flex-direction:row !important; align-items:center; gap:8px !important; }
.eo-command-form-check input{ width:15px; height:15px; min-height:0; accent-color:var(--accent); }
.eo-command-form label.eo-command-form-check > span{
  color:var(--muted);
  font:400 11.5px/1.3 var(--font-body);
  letter-spacing:0; text-transform:none;
}
.eo-command-form-go{
  align-self:flex-start;
  height:36px; margin-top:3px; padding:0 16px;
  border:1px solid transparent;
  background:var(--accent); color:var(--on-accent);
  font:600 12px/1 var(--font-body);
  cursor:pointer;
}
.eo-command-form-go:hover{ background:var(--accent-soft); }

.eo-command-restore{ display:grid; grid-template-columns:repeat(auto-fill, minmax(178px,1fr)); gap:9px; }
.eo-command-restore button{
  display:flex; flex-direction:column; gap:4px;
  padding:11px 12px;
  border:1px solid var(--line);
  background:var(--card); color:var(--text);
  cursor:pointer; text-align:left;
}
.eo-command-restore button:hover{ border-color:var(--accent); background:var(--card-hover); }
.eo-command-restore button span{
  color:var(--faint);
  font:600 8.5px/1 var(--font-mono); letter-spacing:.16em; text-transform:uppercase;
}
.eo-command-restore button b{ font:600 12px/1.3 var(--font-body); }
.eo-command-restore button i{
  color:var(--accent); font-style:normal;
  font:600 10px/1 var(--font-body);
}

/* ---- The portrait canvas ----------------------------------------------- */
/* A 12-column stats board for a screen taller than it is wide. It needs almost
   nothing of its own — the engine is identical and every card keeps its styling
   — beyond letting the editor bar wrap, because the canvas under it is roughly
   a third the width of the landscape one. */
[data-command-profile="tall"] .eo-command-editor{ flex-wrap:wrap; row-gap:10px; }
[data-command-profile="tall"] .eo-command-editor-status{
  order:3; width:100%; padding-left:0; border-left:0;
}
[data-command-profile="tall"] .eo-command-editor-actions{ margin-left:auto; }

/* ---- Emergency narrow -------------------------------------------------- */
/* Genuinely too narrow for any grid — even the 12-column canvas would be 20px
   cells here. Everything takes the full width in its stored order; no rectangle
   is rewritten, so widening the window brings the arrangement back exactly as
   it was left. */
@media (max-width:640px){
  .eo-command-grid{ display:flex; flex-direction:column; min-height:0; }
  .eo-command-grid .eo-command-widget{ width:100%; align-self:stretch; }
  .eo-command-grid .eo-command-body{ height:auto; overflow:visible; }
  .eo-command-grid .eo-command-fit{ width:100%; height:auto; overflow:visible; transform:none; }
  .eo-command-guide,
  .eo-command-preview{ display:none !important; }
  .eo-command-editor{ flex-wrap:wrap; }
  .eo-command-editor-status{ order:3; width:100%; padding-left:0; border-left:0; }
}

/* ---- The shelf -------------------------------------------------------------
   The rack you take a widget off. It sticks to the foot of the editor, so it
   is reachable wherever you have scrolled to, and the canvas keeps scrolling
   underneath it - you aim at the page with the shelf still open.

   Each card is a REAL render of the widget shrunk down: drawn at its natural
   380x210 and scaled, rather than restyled small, so what is on the shelf is
   what lands on the page. transform:scale keeps the type, the spacing and the
   proportions exactly as they will be, only smaller. */
.eo-command-shelf{
  position:sticky; bottom:0; z-index:30;
  margin-top:18px;
  padding:11px 14px 13px;
  border-top:1px solid rgba(var(--accent-rgb),.3);
  background:linear-gradient(180deg, rgba(9,13,28,.9), rgba(9,13,28,.985) 32%);
  backdrop-filter:blur(9px);
}
.eo-shelf-head{ display:flex; align-items:center; gap:11px; margin-bottom:10px; }
.eo-shelf-hint{
  flex:1 1 auto; min-width:0;
  color:var(--faint); font:500 10.5px/1.3 var(--font-body);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.eo-shelf-nav{ flex:none; display:flex; gap:4px; }
.eo-shelf-nav button,
.eo-shelf-close{
  width:24px; height:24px; padding:0;
  border:1px solid var(--line-bright); border-radius:3px;
  background:transparent; color:var(--muted);
  font:600 15px/1 var(--font-body);
  display:flex; align-items:center; justify-content:center;
  cursor:pointer;
  transition:color var(--t-snap) var(--ease), border-color var(--t-snap) var(--ease);
}
.eo-shelf-nav button:hover,
.eo-shelf-close:hover{ color:var(--accent); border-color:rgba(var(--accent-rgb),.5); }
.eo-shelf-close{ flex:none; }
.eo-shelf-close svg{ width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:2; }

.eo-shelf-rail{
  display:flex; gap:12px;
  overflow-x:auto; overflow-y:hidden;
  padding-bottom:5px;
  scroll-snap-type:x proximity;
  scrollbar-width:thin; scrollbar-color:var(--line-bright) transparent;
}
.eo-shelf-rail::-webkit-scrollbar{ height:7px; }
.eo-shelf-rail::-webkit-scrollbar-thumb{ background:var(--line-bright); border-radius:4px; }
.eo-shelf-rail::-webkit-scrollbar-thumb:hover{ background:var(--line-strong); }
.eo-shelf-rail::-webkit-scrollbar-track{ background:transparent; }

.eo-shelf-card{
  flex:0 0 auto; width:264px;
  display:flex; flex-direction:column; gap:0;
  padding:0; border:1px solid var(--line-bright);
  background:rgba(var(--text-rgb),.03);
  text-align:left; cursor:pointer;
  scroll-snap-align:start;
  transition:border-color var(--t-snap) var(--ease), background var(--t-snap) var(--ease), transform var(--t-snap) var(--ease);
}
/* The card is a div playing a button, so it does not inherit a control's reset
   and the type inside it has to be stated. */
.eo-shelf-card{ font:inherit; color:inherit; }
.eo-shelf-card:hover{
  border-color:var(--accent);
  background:rgba(var(--accent-rgb),.09);
  transform:translateY(-2px);
}
.eo-shelf-card:focus-visible{ outline:2px solid rgba(var(--accent-rgb),.8); outline-offset:2px; }

/* The window onto the drawing. The drawing itself is full size inside it. */
/* The window onto the drawing. Fixed size, so every card on the shelf is the
   same card whatever it holds; the drawing inside is what varies. */
.eo-shelf-frame{
  display:block; position:relative;
  width:100%; height:158px; overflow:hidden;
  border-bottom:1px solid var(--line);
  background:rgba(0,0,0,.22);
  /* Nothing inside a preview is clickable, hoverable or tabbable - it is a
     picture of a widget, and the card underneath owns the whole gesture. */
  pointer-events:none;
}
/* Size and scale are both set by scaleCommandShelfPreviews() in
   js/eo-command.js: the drawing is laid out at the real pixel rectangle the
   widget would take on the canvas, then scaled down into the frame above. */
.eo-shelf-draw{
  display:block; position:absolute; top:0; left:0;
  transform-origin:0 0;
  padding:8px 9px;
}
/* Inside a preview the widget shell is the whole drawing, not a grid cell. */
.eo-shelf-draw .eo-command-widget{
  width:100%; height:100%;
  grid-column:auto; grid-row:auto;
}
.eo-shelf-blank{
  display:flex; align-items:center; justify-content:center; height:100%;
  color:var(--faint); font:500 16px/1 var(--font-body);
}
.eo-shelf-meta{ display:flex; flex-direction:column; gap:3px; padding:8px 10px 9px; }
.eo-shelf-group{
  color:var(--accent);
  font:600 8.5px/1 var(--font-mono); letter-spacing:.16em; text-transform:uppercase;
}
.eo-shelf-label{
  color:var(--text); font:600 11.5px/1.3 var(--font-body);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.eo-shelf-empty{
  margin:0; padding:14px 2px;
  color:var(--faint); font:400 11.5px/1.5 var(--font-body);
}

/* Something is in the hand, so the shelf steps back rather than competing with
   the canvas you are aiming at. */
body.eo-command-carrying .eo-command-shelf{ opacity:.4; }

.eo-command-btn.is-add.is-on{
  background:rgba(var(--accent-rgb),.18);
  border-color:var(--accent); color:var(--accent);
}

/* Landing on top of something. Not an error - the pile underneath will move -
   so it is marked as a consequence rather than a refusal: amber, where a real
   refusal (off the edge of the canvas) is red. */
.eo-command-widget.is-displacing{
  box-shadow:inset 0 0 0 1.5px var(--warn), 0 26px 60px rgba(0,0,0,.55);
}
